Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 10 additions & 36 deletions lib/comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
* @beta
*/
var CollectionRequest = require( './shared/collection-request' );
var pick = require( 'lodash' ).pick;
var extend = require( 'node.extend' );
var inherit = require( 'util' ).inherits;

var parameters = require( './mixins/parameters' );

/**
* CommentsRequest extends CollectionRequest to handle the /comments API endpoint
*
Expand Down Expand Up @@ -73,6 +77,12 @@ function CommentsRequest( options ) {
// CommentsRequest extends CollectionRequest
inherit( CommentsRequest, CollectionRequest );

// Mixins
extend( CommentsRequest.prototype, pick( parameters, [
'parent',
'forPost'
] ) );

/**
* A hash table of path keys and regex validators for those path elements
*
Expand Down Expand Up @@ -143,40 +153,4 @@ CommentsRequest.prototype.term = function( term ) {
return this;
};

/**
* Search for hierarchical taxonomy terms that are children of the parent term
* indicated by the provided term ID
*
* @example
*
* wp.categories().parent( 42 ).then(function( categories ) {
* console.log( 'all of these categories are sub-items of cat ID#42:' );
* console.log( categories );
* });
*
* @method parent
* @chainable
* @param {Number} parentId The ID of a (hierarchical) taxonomy term
* @return {CommentsRequest} The CommentsRequest instance (for chaining)
*/
CommentsRequest.prototype.parent = function( parentId ) {
this.param( 'parent', parentId, true );

return this;
};

/**
* Specify the post for which to retrieve terms
*
* @method forPost
* @chainable
* @param {String|Number} post The ID of the post for which to retrieve terms
* @return {CommentsRequest} The CommentsRequest instance (for chaining)
*/
CommentsRequest.prototype.forPost = function( postId ) {
this.param( 'post', postId );

return this;
};

module.exports = CommentsRequest;
File renamed without changes.
18 changes: 0 additions & 18 deletions lib/media.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,6 @@ function MediaRequest( options ) {
*/
this._options = options || {};

/**
* A hash of filter values to parse into the final request URI
* @property _filters
* @type Object
* @private
* @default {}
*/
this._filters = {};

/**
* A hash of taxonomy terms to parse into the final request URI
* @property _taxonomyFilters
* @type Object
* @private
* @default {}
*/
this._taxonomyFilters = {};

/**
* A hash of non-filter query parameters
*
Expand Down
218 changes: 218 additions & 0 deletions lib/mixins/filters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
'use strict';
/**
* Filter methods that can be mixed in to a request constructor's prototype to
* allow that request to take advantage of the `?filter[]=` aliases for WP_Query
* parameters for collection endpoints. These are most relevant to posts, pages
* and CPTs.
*
* @module filters
*/
var _ = require( 'lodash' );
var extend = require( 'node.extend' );
var alphaNumericSort = require( '../lib/alphanumeric-sort' );

var filterMixins = {};

// Filter Methods
// ==============

/**
* Specify key-value pairs by which to filter the API results (commonly used
* to retrieve only posts meeting certain criteria, such as posts within a
* particular category or by a particular author).
*
* @example
* // Set a single property:
* wp.filter( 'post_type', 'cpt_event' )...
*
* // Set multiple properties at once:
* wp.filter({
* post_status: 'publish',
* category_name: 'news'
* })...
*
* // Chain calls to .filter():
* wp.filter( 'post_status', 'publish' ).filter( 'category_name', 'news' )...
*
* @method filter
* @chainable
* @param {String|Object} props A filter property name string, or object of name/value pairs
* @param {String|Number|Array} [value] The value(s) corresponding to the provided filter property
* @return The request instance (for chaining)
*/
filterMixins.filter = function( props, value ) {
/* jshint validthis:true */

if ( ! props || _.isString( props ) && typeof value === 'undefined' ) {
// We have no filter to set, or no value to set for that filter
return this;
}

// convert the property name string `props` and value `value` into an object
if ( _.isString( props ) ) {
props = _.zipObject([[ props, value ]]);
}

this._filters = extend( this._filters, props );

return this;
};

/**
* Restrict the query results to posts matching one or more taxonomy terms.
*
* @method taxonomy
* @chainable
* @param {String} taxonomy The name of the taxonomy to filter by
* @param {String|Number|Array} term A string or integer, or array thereof, representing terms
* @return The request instance (for chaining)
*/
filterMixins.taxonomy = function( taxonomy, term ) {
/* jshint validthis:true */
var termIsArray = _.isArray( term );
var termIsNumber = termIsArray ?
term.reduce(function( allAreNumbers, term ) {
return allAreNumbers && _.isNumber( term );
}, true ) :
_.isNumber( term );
var termIsString = termIsArray ?
term.reduce(function( allAreStrings, term ) {
return allAreStrings && _.isString( term );
}, true ) :
_.isString( term );
var taxonomyTerms;

if ( ! termIsString && ! termIsNumber ) {
throw new Error( 'term must be a number, string, or array of numbers or strings' );
}

if ( taxonomy === 'category' ) {
if ( termIsString ) {
// Query param for filtering by category slug is "category_name"
taxonomy = 'category_name';
} else {
// The boolean check above ensures that if taxonomy === 'category' and
// term is not a string, then term must be a number and therefore an ID:
// Query param for filtering by category ID is "cat"
taxonomy = 'cat';
}
} else if ( taxonomy === 'post_tag' ) {
// tag is used in place of post_tag in the public query variables
taxonomy = 'tag';
}

// Ensure the taxonomy filters object is available
this._taxonomyFilters = this._taxonomyFilters || {};

// Ensure there's an array of terms available for this taxonomy
taxonomyTerms = ( this._taxonomyFilters[ taxonomy ] || [] )
// Insert the provided terms into the specified taxonomy's terms array
.concat( term )
// Sort array
.sort( alphaNumericSort );

// De-dupe
this._taxonomyFilters[ taxonomy ] = _.unique( taxonomyTerms, true );

return this;
};

/**
* Convenience wrapper for `.taxonomy( 'category', ... )`.
*
* @method category
* @chainable
* @param {String|Number|Array} category A string or integer, or array thereof, representing terms
* @return The request instance (for chaining)
*/
filterMixins.category = function( category ) {
/* jshint validthis:true */
return filterMixins.taxonomy.call( this, 'category', category );
};

/**
* Convenience wrapper for `.taxonomy( 'tag', ... )`.
*
* @method tag
* @chainable
* @param {String|Number|Array} tag A tag term string or array of tag term strings
* @return The request instance (for chaining)
*/
filterMixins.tag = function( tag ) {
/* jshint validthis:true */
return filterMixins.taxonomy.call( this, 'tag', tag );
};

/**
* Query for posts published in a given year.
*
* @method year
* @chainable
* @param {Number} year integer representation of year requested
* @returns The request instance (for chaining)
*/
filterMixins.year = function( year ) {
/* jshint validthis:true */
return filterMixins.filter.call( this, 'year', year );
};

/**
* Query for posts published in a given month, either by providing the number
* of the requested month (e.g. 3), or the month's name as a string (e.g. "March")
*
* @method month
* @chainable
* @param {Number|String} month Integer for month (1) or month string ("January")
* @returns The request instance (for chaining)
*/
filterMixins.month = function( month ) {
/* jshint validthis:true */
var monthDate;
if ( _.isString( month ) ) {
// Append a arbitrary day and year to the month to parse the string into a Date
monthDate = new Date( Date.parse( month + ' 1, 2012' ) );

// If the generated Date is NaN, then the passed string is not a valid month
if ( isNaN( monthDate ) ) {
return this;
}

// JS Dates are 0 indexed, but the WP API requires a 1-indexed integer
month = monthDate.getMonth() + 1;
}

// If month is a Number, add the monthnum filter to the request
if ( _.isNumber( month ) ) {
return filterMixins.filter.call( this, 'monthnum', month );
}

return this;
};

/**
* Add the day filter into the request to retrieve posts for a given day
*
* @method day
* @chainable
* @param {Number} day Integer representation of the day requested
* @returns The request instance (for chaining)
*/
filterMixins.day = function( day ) {
/* jshint validthis:true */
return filterMixins.filter.call( this, 'day', day );
};

/**
* Specify that we are requesting a page by its path (specific to Page resources)
*
* @method path
* @chainable
* @param {String} path The root-relative URL path for a page
* @returns The request instance (for chaining)
*/
filterMixins.path = function( path ) {
/* jshint validthis:true */
return filterMixins.filter.call( this, 'pagename', path );
};

module.exports = filterMixins;
Loading