PageRenderTime 7ms CodeModel.GetById 16ms app.highlight 36ms RepoModel.GetById 2ms app.codeStats 0ms

/wp-content/plugins/json-rest-api/wp-api.js

https://gitlab.com/dhanukanuwan/hangover-office
JavaScript | 987 lines | 581 code | 141 blank | 265 comment | 60 complexity | 7a14b7671a3853db5baa248b1cf63a6c MD5 | raw file
  1(function( window, undefined ) {
  2
  3	'use strict';
  4
  5	function WP_API() {
  6		this.models = {};
  7		this.collections = {};
  8		this.views = {};
  9	}
 10
 11	window.wp = window.wp || {};
 12	wp.api = wp.api || new WP_API();
 13
 14})( window );
 15
 16(function( Backbone, _, window, undefined ) {
 17
 18	//'use strict';
 19
 20	// ECMAScript 5 shim, from MDN
 21	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
 22	if ( ! Date.prototype.toISOString ) {
 23		var pad = function( number ) {
 24			var r = String( number );
 25			if ( r.length === 1 ) {
 26				r = '0' + r;
 27			}
 28			return r;
 29		};
 30
 31		Date.prototype.toISOString = function() {
 32			return this.getUTCFullYear() +
 33				'-' + pad( this.getUTCMonth() + 1 ) +
 34				'-' + pad( this.getUTCDate() ) +
 35				'T' + pad( this.getUTCHours() ) +
 36				':' + pad( this.getUTCMinutes() ) +
 37				':' + pad( this.getUTCSeconds() ) +
 38				'.' + String( ( this.getUTCMilliseconds()/1000 ).toFixed( 3 ) ).slice( 2, 5 ) +
 39				'Z';
 40		};
 41	}
 42
 43	function WP_API_Utils() {
 44		var origParse = Date.parse,
 45			numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ];
 46
 47
 48		this.parseISO8601 = function( date ) {
 49			var timestamp, struct, i, k,
 50				minutesOffset = 0;
 51
 52			// ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string
 53			// before falling back to any implementation-specific date parsing, so that’s what we do, even if native
 54			// implementations could be faster
 55			//              1 YYYY                2 MM       3 DD           4 HH    5 mm       6 ss        7 msec        8 Z 9 ±    10 tzHH    11 tzmm
 56			if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) {
 57				// avoid NaN timestamps caused by “undefined” values being passed to Date.UTC
 58				for ( i = 0; ( k = numericKeys[i] ); ++i) {
 59					struct[k] = +struct[k] || 0;
 60				}
 61
 62				// allow undefined days and months
 63				struct[2] = ( +struct[2] || 1 ) - 1;
 64				struct[3] = +struct[3] || 1;
 65
 66				if ( struct[8] !== 'Z' && struct[9] !== undefined ) {
 67					minutesOffset = struct[10] * 60 + struct[11];
 68
 69					if ( struct[9] === '+' ) {
 70						minutesOffset = 0 - minutesOffset;
 71					}
 72				}
 73
 74				timestamp = Date.UTC( struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7] );
 75			}
 76			else {
 77				timestamp = origParse ? origParse( date ) : NaN;
 78			}
 79
 80			return timestamp;
 81		};
 82	}
 83
 84	window.wp = window.wp || {};
 85	wp.api = wp.api || {};
 86	wp.api.utils = wp.api.utils || new WP_API_Utils();
 87
 88})( Backbone, _, window );
 89
 90/* global WP_API_Settings:false */
 91// Suppress warning about parse function's unused "options" argument:
 92/* jshint unused:false */
 93(function( wp, WP_API_Settings, Backbone, _, window, undefined ) {
 94
 95	'use strict';
 96
 97	/**
 98	 * Array of parseable dates
 99	 *
100	 * @type {string[]}
101	 */
102	var parseable_dates = [ 'date', 'modified', 'date_gmt', 'modified_gmt' ];
103
104	/**
105	 * Mixin for all content that is time stamped
106	 *
107	 * @type {{toJSON: toJSON, parse: parse}}
108	 */
109	var TimeStampedMixin = {
110		/**
111		 * Serialize the entity pre-sync
112		 *
113		 * @returns {*}
114		 */
115		toJSON: function() {
116			var attributes = _.clone( this.attributes );
117
118			// Serialize Date objects back into 8601 strings
119			_.each( parseable_dates, function ( key ) {
120				if ( key in attributes ) {
121					attributes[key] = attributes[key].toISOString();
122				}
123			});
124
125			return attributes;
126		},
127
128		/**
129		 * Unserialize the fetched response
130		 *
131		 * @param {*} response
132		 * @returns {*}
133		 */
134		parse: function( response ) {
135			// Parse dates into native Date objects
136			_.each( parseable_dates, function ( key ) {
137				if ( ! ( key in response ) ) {
138					return;
139				}
140
141				var timestamp = wp.api.utils.parseISO8601( response[key] );
142				response[key] = new Date( timestamp );
143			});
144
145			// Parse the author into a User object
146			if ( response.author !== 'undefined' ) {
147				response.author = new wp.api.models.User( response.author );
148			}
149
150			return response;
151		}
152	};
153
154	/**
155	 * Mixin for all hierarchical content types such as posts
156	 *
157	 * @type {{parent: parent}}
158	 */
159	var HierarchicalMixin = {
160		/**
161		 * Get parent object
162		 *
163		 * @returns {Backbone.Model}
164		 */
165		parent: function() {
166
167			var object, parent = this.get( 'parent' );
168
169			// Return null if we don't have a parent
170			if ( parent === 0 ) {
171				return null;
172			}
173
174			var parentModel = this;
175
176			if ( typeof this.parentModel !== 'undefined' ) {
177				/**
178				 * Probably a better way to do this. Perhaps grab a cached version of the
179				 * instantiated model?
180				 */
181				parentModel = new this.parentModel();
182			}
183
184			// Can we get this from its collection?
185			if ( parentModel.collection ) {
186				return parentModel.collection.get( parent );
187			} else {
188				// Otherwise, get the object directly
189				object = new parentModel.constructor( {
190					ID: parent
191				});
192
193				// Note that this acts asynchronously
194				object.fetch();
195				return object;
196			}
197		}
198	};
199
200	/**
201	 * Private Backbone base model for all models
202	 */
203	var BaseModel = Backbone.Model.extend(
204		/** @lends BaseModel.prototype  */
205		{
206			/**
207			 * Set nonce header before every Backbone sync
208			 *
209			 * @param {string} method
210			 * @param {Backbone.Model} model
211			 * @param {{beforeSend}, *} options
212			 * @returns {*}
213			 */
214			sync: function( method, model, options ) {
215				options = options || {};
216
217				if ( typeof WP_API_Settings.nonce !== 'undefined' ) {
218					var beforeSend = options.beforeSend;
219
220					options.beforeSend = function( xhr ) {
221						xhr.setRequestHeader( 'X-WP-Nonce', WP_API_Settings.nonce );
222
223						if ( beforeSend ) {
224							return beforeSend.apply( this, arguments );
225						}
226					};
227				}
228
229				return Backbone.sync( method, model, options );
230			}
231		}
232	);
233
234	/**
235	 * Backbone model for single users
236	 */
237	wp.api.models.User = BaseModel.extend(
238		/** @lends User.prototype  */
239		{
240			idAttribute: 'ID',
241
242			urlRoot: WP_API_Settings.root + '/users',
243
244			defaults: {
245				ID: null,
246				username: '',
247				email: '',
248				password: '',
249				name: '',
250				first_name: '',
251				last_name: '',
252				nickname: '',
253				slug: '',
254				URL: '',
255				avatar: '',
256				meta: {
257					links: {}
258				}
259			},
260
261			/**
262			 * Return avatar URL
263			 *
264			 * @param {number} size
265			 * @returns {string}
266			 */
267			avatar: function( size ) {
268				return this.get( 'avatar' ) + '&s=' + size;
269			}
270		}
271	);
272
273	/**
274	 * Model for Taxonomy
275	 */
276	wp.api.models.Taxonomy = BaseModel.extend(
277		/** @lends Taxonomy.prototype  */
278		{
279			idAttribute: 'slug',
280
281			urlRoot: WP_API_Settings.root + '/taxonomies',
282
283			defaults: {
284				name: '',
285				slug: null,
286				labels: {},
287				types: {},
288				show_cloud: false,
289				hierarchical: false,
290				meta: {
291					links: {}
292				}
293			}
294		}
295	);
296
297	/**
298	 * Backbone model for term
299	 */
300	wp.api.models.Term = BaseModel.extend( _.extend(
301		/** @lends Term.prototype */
302		{
303			idAttribute: 'ID',
304
305			taxonomy: 'category',
306
307			/**
308			 * @class Represent a term
309			 * @augments Backbone.Model
310			 * @constructs
311			 */
312			initialize: function( attributes, options ) {
313				if ( typeof options !== 'undefined' ) {
314					if ( options.taxonomy ) {
315						this.taxonomy = options.taxonomy;
316					}
317				}
318			},
319
320			/**
321			 * Return URL for the model
322			 *
323			 * @returns {string}
324			 */
325			url: function() {
326				var id = this.get( 'ID' );
327				id = id || '';
328
329				return WP_API_Settings.root + '/taxonomies/' + this.taxonomy + '/terms/' + id;
330			},
331
332			defaults: {
333				ID: null,
334				name: '',
335				slug: '',
336				description: '',
337				parent: null,
338				count: 0,
339				link: '',
340				meta: {
341					links: {}
342				}
343			}
344
345		}, TimeStampedMixin, HierarchicalMixin )
346	);
347
348	/**
349	 * Backbone model for single posts
350	 */
351	wp.api.models.Post = BaseModel.extend( _.extend(
352		/** @lends Post.prototype  */
353		{
354			idAttribute: 'ID',
355
356			urlRoot: WP_API_Settings.root + '/posts',
357
358			defaults: {
359				ID: null,
360				title: '',
361				status: 'draft',
362				type: 'post',
363				author: new wp.api.models.User(),
364				content: '',
365				link: '',
366				'parent': 0,
367				date: new Date(),
368				date_gmt: new Date(),
369				modified: new Date(),
370				modified_gmt: new Date(),
371				format: 'standard',
372				slug: '',
373				guid: '',
374				excerpt: '',
375				menu_order: 0,
376				comment_status: 'open',
377				ping_status: 'open',
378				sticky: false,
379				date_tz: 'Etc/UTC',
380				modified_tz: 'Etc/UTC',
381				featured_image: null,
382				terms: {},
383				post_meta: {},
384				meta: {
385					links: {}
386				}
387			}
388		}, TimeStampedMixin, HierarchicalMixin )
389	);
390
391	/**
392	 * Backbone model for pages
393	 */
394	wp.api.models.Page = BaseModel.extend( _.extend(
395		/** @lends Page.prototype  */
396		{
397			idAttribute: 'ID',
398
399			urlRoot: WP_API_Settings.root + '/pages',
400
401			defaults: {
402				ID: null,
403				title: '',
404				status: 'draft',
405				type: 'page',
406				author: new wp.api.models.User(),
407				content: '',
408				parent: 0,
409				link: '',
410				date: new Date(),
411				modified: new Date(),
412				date_gmt: new Date(),
413				modified_gmt: new Date(),
414				date_tz: 'Etc/UTC',
415				modified_tz: 'Etc/UTC',
416				format: 'standard',
417				slug: '',
418				guid: '',
419				excerpt: '',
420				menu_order: 0,
421				comment_status: 'closed',
422				ping_status: 'open',
423				sticky: false,
424				password: '',
425				meta: {
426					links: {}
427				},
428				featured_image: null,
429				terms: []
430			}
431		}, TimeStampedMixin, HierarchicalMixin )
432	);
433
434	/**
435	 * Backbone model for revisions
436	 */
437	wp.api.models.Revision = wp.api.models.Post.extend(
438		/** @lends Revision.prototype */
439		{
440			/**
441			 * Return URL for model
442			 *
443			 * @returns {string}
444			 */
445			url: function() {
446				var parent_id = this.get( 'parent' );
447				parent_id = parent_id || '';
448
449				var id = this.get( 'ID' );
450				id = id || '';
451
452				return WP_API_Settings.root + '/posts/' + parent_id + '/revisions/' + id;
453			},
454
455			/**
456			 * @class Represent a revision
457			 * @augments Backbone.Model
458			 * @constructs
459			 */
460			initialize: function() {
461				// Todo: what of the parent model is a page?
462				this.parentModel = wp.api.models.Post;
463			}
464		}
465	);
466
467	/**
468	 * Backbone model for media items
469	 */
470	wp.api.models.Media = BaseModel.extend( _.extend(
471		/** @lends Media.prototype */
472		{
473			idAttribute: 'ID',
474
475			urlRoot: WP_API_Settings.root + '/media',
476
477			defaults: {
478				ID: null,
479				title: '',
480				status: 'inherit',
481				type: 'attachment',
482				author: new wp.api.models.User(),
483				content: '',
484				parent: 0,
485				link: '',
486				date: new Date(),
487				modified: new Date(),
488				format: 'standard',
489				slug: '',
490				guid: '',
491				excerpt: '',
492				menu_order: 0,
493				comment_status: 'open',
494				ping_status: 'open',
495				sticky: false,
496				date_tz: 'Etc/UTC',
497				modified_tz: 'Etc/UTC',
498				date_gmt: new Date(),
499				modified_gmt: new Date(),
500				meta: {
501					links: {}
502				},
503				terms: [],
504				source: '',
505				is_image: true,
506				attachment_meta: {},
507				image_meta: {}
508			},
509
510			/**
511			 * @class Represent a media item
512			 * @augments Backbone.Model
513			 * @constructs
514			 */
515			initialize: function() {
516				// Todo: what of the parent model is a page?
517				this.parentModel = wp.api.models.Post;
518			}
519		}, TimeStampedMixin, HierarchicalMixin )
520	);
521
522	/**
523	 * Backbone model for comments
524	 */
525	wp.api.models.Comment = BaseModel.extend( _.extend(
526		/** @lends Comment.prototype */
527		{
528			idAttribute: 'ID',
529
530			defaults: {
531				ID: null,
532				post: null,
533				content: '',
534				status: 'hold',
535				type: '',
536				parent: 0,
537				author: new wp.api.models.User(),
538				date: new Date(),
539				date_gmt: new Date(),
540				date_tz: 'Etc/UTC',
541				meta: {
542					links: {}
543				}
544			},
545
546			/**
547			 * Return URL for model
548			 *
549			 * @returns {string}
550			 */
551			url: function() {
552				var post_id = this.get( 'post' );
553				post_id = post_id || '';
554
555				var id = this.get( 'ID' );
556				id = id || '';
557
558				return WP_API_Settings.root + '/posts/' + post_id + '/comments/' + id;
559			}
560		}, TimeStampedMixin, HierarchicalMixin )
561	);
562
563	/**
564	 * Backbone model for single post types
565	 */
566	wp.api.models.PostType = BaseModel.extend(
567		/** @lends PostType.prototype */
568		{
569			idAttribute: 'slug',
570
571			urlRoot: WP_API_Settings.root + '/posts/types',
572
573			defaults: {
574				slug: null,
575				name: '',
576				description: '',
577				labels: {},
578				queryable: false,
579				searchable: false,
580				hierarchical: false,
581				meta: {
582					links: {}
583				},
584				taxonomies: []
585			},
586
587			/**
588			 * Prevent model from being saved
589			 *
590			 * @returns {boolean}
591			 */
592			save: function () {
593				return false;
594			},
595
596			/**
597			 * Prevent model from being deleted
598			 *
599			 * @returns {boolean}
600			 */
601			'delete': function () {
602				return false;
603			}
604		}
605	);
606
607	/**
608	 * Backbone model for a post status
609	 */
610	wp.api.models.PostStatus = BaseModel.extend(
611		/** @lends PostStatus.prototype */
612		{
613			idAttribute: 'slug',
614
615			urlRoot: WP_API_Settings.root + '/posts/statuses',
616
617			defaults: {
618				slug: null,
619				name: '',
620				'public': true,
621				'protected': false,
622				'private': false,
623				queryable: true,
624				show_in_list: true,
625				meta: {
626					links: {}
627				}
628			},
629
630			/**
631			 * Prevent model from being saved
632			 *
633			 * @returns {boolean}
634			 */
635			save: function() {
636				return false;
637			},
638
639			/**
640			 * Prevent model from being deleted
641			 *
642			 * @returns {boolean}
643			 */
644			'delete': function() {
645				return false;
646			}
647		}
648	);
649
650})( wp, WP_API_Settings, Backbone, _, window );
651
652/* global WP_API_Settings:false */
653(function( wp, WP_API_Settings, Backbone, _, window, undefined ) {
654
655	'use strict';
656
657	var BaseCollection = Backbone.Collection.extend(
658		/** @lends BaseCollection.prototype  */
659		{
660
661			/**
662			 * Setup default state
663			 */
664			initialize: function() {
665				this.state = {
666					data: {},
667					currentPage: null,
668					totalPages: null,
669					totalObjects: null
670				};
671			},
672
673			/**
674			 * Overwrite Backbone.Collection.sync to pagination state based on response headers.
675			 *
676			 * Set nonce header before every Backbone sync.
677			 *
678			 * @param {string} method
679			 * @param {Backbone.Model} model
680			 * @param {{success}, *} options
681			 * @returns {*}
682			 */
683			sync: function( method, model, options ) {
684				options = options || {};
685				var beforeSend = options.beforeSend;
686
687				if ( typeof WP_API_Settings.nonce !== 'undefined' ) {
688					options.beforeSend = function( xhr ) {
689						xhr.setRequestHeader( 'X-WP-Nonce', WP_API_Settings.nonce );
690
691						if ( beforeSend ) {
692							return beforeSend.apply( this, arguments );
693						}
694					};
695				}
696
697				if ( 'read' === method ) {
698					var SELF = this;
699
700					if ( options.data ) {
701						SELF.state.data = _.clone( options.data );
702
703						delete SELF.state.data.page;
704					} else {
705						SELF.state.data = options.data = {};
706					}
707
708					if ( typeof options.data.page === 'undefined' ) {
709						SELF.state.currentPage = null;
710						SELF.state.totalPages = null;
711						SELF.state.totalObjects = null;
712					} else {
713						SELF.state.currentPage = options.data.page - 1;
714					}
715
716					var success = options.success;
717					options.success = function( data, textStatus, request ) {
718						SELF.state.totalPages = parseInt( request.getResponseHeader( 'X-WP-TotalPages' ), 10 );
719						SELF.state.totalObjects = parseInt( request.getResponseHeader( 'X-WP-Total' ), 10 );
720
721						if ( SELF.state.currentPage === null ) {
722							SELF.state.currentPage = 1;
723						} else {
724							SELF.state.currentPage++;
725						}
726
727						if ( success ) {
728							return success.apply( this, arguments );
729						}
730					};
731				}
732
733				return Backbone.sync( method, model, options );
734			},
735
736			/**
737			 * Fetches the next page of objects if a new page exists
738			 *
739			 * @param {data: {page}} options
740			 * @returns {*}
741			 */
742			more: function( options ) {
743				options = options || {};
744				options.data = options.data || {};
745
746				_.extend( options.data, this.state.data );
747
748				if ( typeof options.data.page === 'undefined' ) {
749					if ( ! this.hasMore() ) {
750						return false;
751					}
752
753					if ( this.state.currentPage === null || this.state.currentPage <= 1 ) {
754						options.data.page = 2;
755					} else {
756						options.data.page = this.state.currentPage + 1;
757					}
758				}
759
760				return this.fetch( options );
761			},
762
763			/**
764			 * Returns true if there are more pages of objects available
765			 *
766			 * @returns null|boolean
767			 */
768			hasMore: function() {
769				if ( this.state.totalPages === null ||
770					 this.state.totalObjects === null ||
771					 this.state.currentPage === null ) {
772					return null;
773				} else {
774					return ( this.state.currentPage < this.state.totalPages );
775				}
776			}
777		}
778	);
779
780	/**
781	 * Backbone collection for posts
782	 */
783	wp.api.collections.Posts = BaseCollection.extend(
784		/** @lends Posts.prototype */
785		{
786			url: WP_API_Settings.root + '/posts',
787
788			model: wp.api.models.Post
789		}
790	);
791
792	/**
793	 * Backbone collection for pages
794	 */
795	wp.api.collections.Pages = BaseCollection.extend(
796		/** @lends Pages.prototype */
797		{
798			url: WP_API_Settings.root + '/pages',
799
800			model: wp.api.models.Page
801		}
802	);
803
804	/**
805	 * Backbone users collection
806	 */
807	wp.api.collections.Users = BaseCollection.extend(
808		/** @lends Users.prototype */
809		{
810			url: WP_API_Settings.root + '/users',
811
812			model: wp.api.models.User
813		}
814	);
815
816	/**
817	 * Backbone post statuses collection
818	 */
819	wp.api.collections.PostStatuses = BaseCollection.extend(
820		/** @lends PostStatuses.prototype */
821		{
822			url: WP_API_Settings.root + '/posts/statuses',
823
824			model: wp.api.models.PostStatus
825
826		}
827	);
828
829	/**
830	 * Backbone media library collection
831	 */
832	wp.api.collections.MediaLibrary = BaseCollection.extend(
833		/** @lends MediaLibrary.prototype */
834		{
835			url: WP_API_Settings.root + '/media',
836
837			model: wp.api.models.Media
838		}
839	);
840
841	/**
842	 * Backbone taxonomy collection
843	 */
844	wp.api.collections.Taxonomies = BaseCollection.extend(
845		/** @lends Taxonomies.prototype */
846		{
847			model: wp.api.models.Taxonomy,
848
849			url: WP_API_Settings.root + '/taxonomies'
850		}
851	);
852
853	/**
854	 * Backbone comment collection
855	 */
856	wp.api.collections.Comments = BaseCollection.extend(
857		/** @lends Comments.prototype */
858		{
859			model: wp.api.models.Comment,
860
861			post: null,
862
863			/**
864			 * @class Represent an array of comments
865			 * @augments Backbone.Collection
866			 * @constructs
867			 */
868			initialize: function( models, options ) {
869				this.constructor.__super__.initialize.apply( this, arguments );
870
871				if ( options && options.post ) {
872					this.post = options.post;
873				}
874			},
875
876			/**
877			 * Return URL for collection
878			 *
879			 * @returns {string}
880			 */
881			url: function() {
882				return WP_API_Settings.root + '/posts/' + this.post + '/comments';
883			}
884		}
885	);
886
887	/**
888	 * Backbone post type collection
889	 */
890	wp.api.collections.PostTypes = BaseCollection.extend(
891		/** @lends PostTypes.prototype */
892		{
893			model: wp.api.models.PostType,
894
895			url: WP_API_Settings.root + '/posts/types'
896		}
897	);
898
899	/**
900	 * Backbone terms collection
901	 */
902	wp.api.collections.Terms = BaseCollection.extend(
903		/** @lends Terms.prototype */
904		{
905			model: wp.api.models.Term,
906
907			type: 'post',
908
909			taxonomy: 'category',
910
911			/**
912			 * @class Represent an array of terms
913			 * @augments Backbone.Collection
914			 * @constructs
915			 */
916			initialize: function( models, options ) {
917				this.constructor.__super__.initialize.apply( this, arguments );
918
919				if ( typeof options !== 'undefined' ) {
920					if ( options.type ) {
921						this.type = options.type;
922					}
923
924					if ( options.taxonomy ) {
925						this.taxonomy = options.taxonomy;
926					}
927				}
928
929				this.on( 'add', _.bind( this.addModel, this ) );
930			},
931
932			/**
933			 * We need to set the type and taxonomy for each model
934			 *
935			 * @param {Backbone.model} model
936			 */
937			addModel: function( model ) {
938				model.type = this.type;
939				model.taxonomy = this.taxonomy;
940			},
941
942			/**
943			 * Return URL for collection
944			 *
945			 * @returns {string}
946			 */
947			url: function() {
948				return WP_API_Settings.root + '/posts/types/' + this.type + '/taxonomies/' + this.taxonomy + '/terms/';
949			}
950		}
951	);
952
953	/**
954	 * Backbone revisions collection
955	 */
956	wp.api.collections.Revisions = BaseCollection.extend(
957		/** @lends Revisions.prototype */
958		{
959			model: wp.api.models.Revision,
960
961			parent: null,
962
963			/**
964			 * @class Represent an array of revisions
965			 * @augments Backbone.Collection
966			 * @constructs
967			 */
968			initialize: function( models, options ) {
969				this.constructor.__super__.initialize.apply( this, arguments );
970
971				if ( options && options.parent ) {
972					this.parent = options.parent;
973				}
974			},
975
976			/**
977			 * return URL for collection
978			 *
979			 * @returns {string}
980			 */
981			url: function() {
982				return WP_API_Settings.root + '/posts/' + this.parent + '/revisions';
983			}
984		}
985	);
986
987})( wp, WP_API_Settings, Backbone, _, window );