at path:ROOT / wp-includes / js / wp-api.js
run:R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
10.3 KB
2026-03-11 16:18:51
R W Run
3.41 KB
2026-03-11 16:18:51
R W Run
3.25 KB
2026-03-11 16:18:51
R W Run
1023 By
2026-03-11 16:18:51
R W Run
21.95 KB
2026-03-11 16:18:51
R W Run
5.67 KB
2026-03-11 16:18:51
R W Run
78.51 KB
2026-03-11 16:18:51
R W Run
23.73 KB
2026-03-11 16:18:51
R W Run
26.18 KB
2026-03-11 16:18:51
R W Run
8.8 KB
2026-03-11 16:18:51
R W Run
28.4 KB
2026-03-11 16:18:51
R W Run
16.11 KB
2026-03-11 16:18:51
R W Run
12.22 KB
2026-03-11 16:18:51
R W Run
2.96 KB
2026-03-11 16:18:51
R W Run
25.22 KB
2026-03-11 16:18:51
R W Run
7.67 KB
2026-03-11 16:18:51
R W Run
7.72 KB
2026-03-11 16:18:51
R W Run
3.47 KB
2026-03-11 16:18:51
R W Run
6.66 KB
2026-03-11 16:18:51
R W Run
3.59 KB
2026-03-11 16:18:51
R W Run
14.67 KB
2026-03-11 16:18:51
R W Run
4.92 KB
2026-03-11 16:18:51
R W Run
22.71 KB
2026-03-11 16:18:51
R W Run
7.64 KB
2026-03-11 16:18:51
R W Run
27.93 KB
2026-03-11 16:18:51
R W Run
10.75 KB
2026-03-11 16:18:51
R W Run
32.55 KB
2026-03-11 16:18:51
R W Run
10.44 KB
2026-03-11 16:18:51
R W Run
5.1 KB
2026-03-11 16:18:51
R W Run
2.51 KB
2026-03-11 16:18:51
R W Run
23.49 KB
2026-03-11 16:18:51
R W Run
5.81 KB
2026-03-11 16:18:51
R W Run
7.06 KB
2026-03-11 16:18:51
R W Run
1.46 KB
2026-03-11 16:18:51
R W Run
1.68 KB
2026-03-11 16:18:51
R W Run
5.39 KB
2026-03-11 16:18:51
R W Run
31 By
2026-03-11 16:18:51
R W Run
35 By
2026-03-11 16:18:51
R W Run
23.57 KB
2026-03-11 16:18:51
R W Run
25.24 KB
2026-03-11 16:18:51
R W Run
9.54 KB
2026-03-11 16:18:51
R W Run
24.24 KB
2026-03-11 16:18:51
R W Run
11.77 KB
2026-03-11 16:18:51
R W Run
28.44 KB
2026-03-11 16:18:51
R W Run
10.63 KB
2026-03-11 16:18:51
R W Run
26.15 KB
2026-03-11 16:18:51
R W Run
12.98 KB
2026-03-11 16:18:51
R W Run
42.58 KB
2026-03-11 16:18:51
R W Run
12.97 KB
2026-03-11 16:18:51
R W Run
266.99 KB
2026-03-11 16:18:51
R W Run
108.18 KB
2026-03-11 16:18:51
R W Run
22.07 KB
2026-03-11 16:18:51
R W Run
10.87 KB
2026-03-11 16:18:51
R W Run
10.51 KB
2026-03-11 16:18:51
R W Run
2.58 KB
2026-03-11 16:18:51
R W Run
0 By
2026-03-11 16:18:51
R W Run
35 By
2026-03-11 16:18:51
R W Run
4.85 KB
2026-03-11 16:18:51
R W Run
3.21 KB
2026-03-11 16:18:51
R W Run
36.32 KB
2026-03-11 16:18:51
R W Run
19.39 KB
2026-03-11 16:18:51
R W Run
67.12 KB
2026-03-11 16:18:51
R W Run
18.46 KB
2026-03-11 16:18:51
R W Run
4.56 KB
2026-03-11 16:18:51
R W Run
1.82 KB
2026-03-11 16:18:51
R W Run
3.81 KB
2026-03-11 16:18:51
R W Run
2.51 KB
2026-03-11 16:18:51
R W Run
45.88 KB
2026-03-11 16:18:51
R W Run
14.34 KB
2026-03-11 16:18:51
R W Run
4.11 KB
2026-03-11 16:18:51
R W Run
1.62 KB
2026-03-11 16:18:51
R W Run
14.88 KB
2026-03-11 16:18:51
R W Run
2.97 KB
2026-03-11 16:18:51
R W Run
10.22 KB
2026-03-11 16:18:51
R W Run
4.34 KB
2026-03-11 16:18:51
R W Run
6.62 KB
2026-03-11 16:18:51
R W Run
3.1 KB
2026-03-11 16:18:51
R W Run
3.14 KB
2026-03-11 16:18:51
R W Run
1.22 KB
2026-03-11 16:18:51
R W Run
12.89 KB
2026-03-11 16:18:51
R W Run
2.82 KB
2026-03-11 16:18:51
R W Run
22.23 KB
2026-03-11 16:18:51
R W Run
8.59 KB
2026-03-11 16:18:51
R W Run
2.79 KB
2026-03-11 16:18:51
R W Run
970 By
2026-03-11 16:18:51
R W Run
597 By
2026-03-11 16:18:51
R W Run
24.72 KB
2026-03-11 16:18:51
R W Run
7.34 KB
2026-03-11 16:18:51
R W Run
9.99 KB
2026-03-11 16:18:51
R W Run
3.54 KB
2026-03-11 16:18:51
R W Run
1.3 KB
2026-03-11 16:18:51
R W Run
444 By
2026-03-11 16:18:51
R W Run
4.58 KB
2026-03-11 16:18:51
R W Run
1.4 KB
2026-03-11 16:18:51
R W Run
569 By
2026-03-11 16:18:51
R W Run
281 By
2026-03-11 16:18:51
R W Run
20.74 KB
2026-03-11 16:18:51
R W Run
11.05 KB
2026-03-11 16:18:51
R W Run
821 By
2026-03-11 16:18:51
R W Run
351 By
2026-03-11 16:18:51
R W Run
802.97 KB
2026-03-11 16:18:51
R W Run
error_log
📄wp-api.js
1/**
2 * @output wp-includes/js/wp-api.js
3 */
4
5(function( window, undefined ) {
6
7 'use strict';
8
9 /**
10 * Initialize the WP_API.
11 */
12 function WP_API() {
13 /** @namespace wp.api.models */
14 this.models = {};
15 /** @namespace wp.api.collections */
16 this.collections = {};
17 /** @namespace wp.api.views */
18 this.views = {};
19 }
20
21 /** @namespace wp */
22 window.wp = window.wp || {};
23 /** @namespace wp.api */
24 wp.api = wp.api || new WP_API();
25 wp.api.versionString = wp.api.versionString || 'wp/v2/';
26
27 // Alias _includes to _.contains, ensuring it is available if lodash is used.
28 if ( ! _.isFunction( _.includes ) && _.isFunction( _.contains ) ) {
29 _.includes = _.contains;
30 }
31
32})( window );
33
34(function( window, undefined ) {
35
36 'use strict';
37
38 var pad, r;
39
40 /** @namespace wp */
41 window.wp = window.wp || {};
42 /** @namespace wp.api */
43 wp.api = wp.api || {};
44 /** @namespace wp.api.utils */
45 wp.api.utils = wp.api.utils || {};
46
47 /**
48 * Determine model based on API route.
49 *
50 * @param {string} route The API route.
51 *
52 * @return {Backbone Model} The model found at given route. Undefined if not found.
53 */
54 wp.api.getModelByRoute = function( route ) {
55 return _.find( wp.api.models, function( model ) {
56 return model.prototype.route && route === model.prototype.route.index;
57 } );
58 };
59
60 /**
61 * Determine collection based on API route.
62 *
63 * @param {string} route The API route.
64 *
65 * @return {Backbone Model} The collection found at given route. Undefined if not found.
66 */
67 wp.api.getCollectionByRoute = function( route ) {
68 return _.find( wp.api.collections, function( collection ) {
69 return collection.prototype.route && route === collection.prototype.route.index;
70 } );
71 };
72
73
74 /**
75 * ECMAScript 5 shim, adapted from MDN.
76 * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
77 */
78 if ( ! Date.prototype.toISOString ) {
79 pad = function( number ) {
80 r = String( number );
81 if ( 1 === r.length ) {
82 r = '0' + r;
83 }
84
85 return r;
86 };
87
88 Date.prototype.toISOString = function() {
89 return this.getUTCFullYear() +
90 '-' + pad( this.getUTCMonth() + 1 ) +
91 '-' + pad( this.getUTCDate() ) +
92 'T' + pad( this.getUTCHours() ) +
93 ':' + pad( this.getUTCMinutes() ) +
94 ':' + pad( this.getUTCSeconds() ) +
95 '.' + String( ( this.getUTCMilliseconds() / 1000 ).toFixed( 3 ) ).slice( 2, 5 ) +
96 'Z';
97 };
98 }
99
100 /**
101 * Parse date into ISO8601 format.
102 *
103 * @param {Date} date.
104 */
105 wp.api.utils.parseISO8601 = function( date ) {
106 var timestamp, struct, i, k,
107 minutesOffset = 0,
108 numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ];
109
110 /*
111 * ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string
112 * before falling back to any implementation-specific date parsing, so that’s what we do, even if native
113 * implementations could be faster.
114 */
115 // 1 YYYY 2 MM 3 DD 4 HH 5 mm 6 ss 7 msec 8 Z 9 ± 10 tzHH 11 tzmm
116 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 ) ) ) {
117
118 // Avoid NaN timestamps caused by “undefined” values being passed to Date.UTC.
119 for ( i = 0; ( k = numericKeys[i] ); ++i ) {
120 struct[k] = +struct[k] || 0;
121 }
122
123 // Allow undefined days and months.
124 struct[2] = ( +struct[2] || 1 ) - 1;
125 struct[3] = +struct[3] || 1;
126
127 if ( 'Z' !== struct[8] && undefined !== struct[9] ) {
128 minutesOffset = struct[10] * 60 + struct[11];
129
130 if ( '+' === struct[9] ) {
131 minutesOffset = 0 - minutesOffset;
132 }
133 }
134
135 timestamp = Date.UTC( struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7] );
136 } else {
137 timestamp = Date.parse ? Date.parse( date ) : NaN;
138 }
139
140 return timestamp;
141 };
142
143 /**
144 * Helper function for getting the root URL.
145 * @return {[type]} [description]
146 */
147 wp.api.utils.getRootUrl = function() {
148 return window.location.origin ?
149 window.location.origin + '/' :
150 window.location.protocol + '//' + window.location.host + '/';
151 };
152
153 /**
154 * Helper for capitalizing strings.
155 */
156 wp.api.utils.capitalize = function( str ) {
157 if ( _.isUndefined( str ) ) {
158 return str;
159 }
160 return str.charAt( 0 ).toUpperCase() + str.slice( 1 );
161 };
162
163 /**
164 * Helper function that capitalizes the first word and camel cases any words starting
165 * after dashes, removing the dashes.
166 */
167 wp.api.utils.capitalizeAndCamelCaseDashes = function( str ) {
168 if ( _.isUndefined( str ) ) {
169 return str;
170 }
171 str = wp.api.utils.capitalize( str );
172
173 return wp.api.utils.camelCaseDashes( str );
174 };
175
176 /**
177 * Helper function to camel case the letter after dashes, removing the dashes.
178 */
179 wp.api.utils.camelCaseDashes = function( str ) {
180 return str.replace( /-([a-z])/g, function( g ) {
181 return g[ 1 ].toUpperCase();
182 } );
183 };
184
185 /**
186 * Extract a route part based on negative index.
187 *
188 * @param {string} route The endpoint route.
189 * @param {number} part The number of parts from the end of the route to retrieve. Default 1.
190 * Example route `/a/b/c`: part 1 is `c`, part 2 is `b`, part 3 is `a`.
191 * @param {string} [versionString] Version string, defaults to `wp.api.versionString`.
192 * @param {boolean} [reverse] Whether to reverse the order when extracting the route part. Optional, default false.
193 */
194 wp.api.utils.extractRoutePart = function( route, part, versionString, reverse ) {
195 var routeParts;
196
197 part = part || 1;
198 versionString = versionString || wp.api.versionString;
199
200 // Remove versions string from route to avoid returning it.
201 if ( 0 === route.indexOf( '/' + versionString ) ) {
202 route = route.substr( versionString.length + 1 );
203 }
204
205 routeParts = route.split( '/' );
206 if ( reverse ) {
207 routeParts = routeParts.reverse();
208 }
209 if ( _.isUndefined( routeParts[ --part ] ) ) {
210 return '';
211 }
212 return routeParts[ part ];
213 };
214
215 /**
216 * Extract a parent name from a passed route.
217 *
218 * @param {string} route The route to extract a name from.
219 */
220 wp.api.utils.extractParentName = function( route ) {
221 var name,
222 lastSlash = route.lastIndexOf( '_id>[\\d]+)/' );
223
224 if ( lastSlash < 0 ) {
225 return '';
226 }
227 name = route.substr( 0, lastSlash - 1 );
228 name = name.split( '/' );
229 name.pop();
230 name = name.pop();
231 return name;
232 };
233
234 /**
235 * Add args and options to a model prototype from a route's endpoints.
236 *
237 * @param {Array} routeEndpoints Array of route endpoints.
238 * @param {Object} modelInstance An instance of the model (or collection)
239 * to add the args to.
240 */
241 wp.api.utils.decorateFromRoute = function( routeEndpoints, modelInstance ) {
242
243 /**
244 * Build the args based on route endpoint data.
245 */
246 _.each( routeEndpoints, function( routeEndpoint ) {
247
248 // Add post and edit endpoints as model args.
249 if ( _.includes( routeEndpoint.methods, 'POST' ) || _.includes( routeEndpoint.methods, 'PUT' ) ) {
250
251 // Add any non-empty args, merging them into the args object.
252 if ( ! _.isEmpty( routeEndpoint.args ) ) {
253
254 // Set as default if no args yet.
255 if ( _.isEmpty( modelInstance.prototype.args ) ) {
256 modelInstance.prototype.args = routeEndpoint.args;
257 } else {
258
259 // We already have args, merge these new args in.
260 modelInstance.prototype.args = _.extend( modelInstance.prototype.args, routeEndpoint.args );
261 }
262 }
263 } else {
264
265 // Add GET method as model options.
266 if ( _.includes( routeEndpoint.methods, 'GET' ) ) {
267
268 // Add any non-empty args, merging them into the defaults object.
269 if ( ! _.isEmpty( routeEndpoint.args ) ) {
270
271 // Set as default if no defaults yet.
272 if ( _.isEmpty( modelInstance.prototype.options ) ) {
273 modelInstance.prototype.options = routeEndpoint.args;
274 } else {
275
276 // We already have options, merge these new args in.
277 modelInstance.prototype.options = _.extend( modelInstance.prototype.options, routeEndpoint.args );
278 }
279 }
280
281 }
282 }
283
284 } );
285
286 };
287
288 /**
289 * Add mixins and helpers to models depending on their defaults.
290 *
291 * @param {Backbone Model} model The model to attach helpers and mixins to.
292 * @param {string} modelClassName The classname of the constructed model.
293 * @param {Object} loadingObjects An object containing the models and collections we are building.
294 */
295 wp.api.utils.addMixinsAndHelpers = function( model, modelClassName, loadingObjects ) {
296
297 var hasDate = false,
298
299 /**
300 * Array of parseable dates.
301 *
302 * @type {string[]}.
303 */
304 parseableDates = [ 'date', 'modified', 'date_gmt', 'modified_gmt' ],
305
306 /**
307 * Mixin for all content that is time stamped.
308 *
309 * This mixin converts between mysql timestamps and JavaScript Dates when syncing a model
310 * to or from the server. For example, a date stored as `2015-12-27T21:22:24` on the server
311 * gets expanded to `Sun Dec 27 2015 14:22:24 GMT-0700 (MST)` when the model is fetched.
312 *
313 * @type {{toJSON: toJSON, parse: parse}}.
314 */
315 TimeStampedMixin = {
316
317 /**
318 * Prepare a JavaScript Date for transmitting to the server.
319 *
320 * This helper function accepts a field and Date object. It converts the passed Date
321 * to an ISO string and sets that on the model field.
322 *
323 * @param {Date} date A JavaScript date object. WordPress expects dates in UTC.
324 * @param {string} field The date field to set. One of 'date', 'date_gmt', 'date_modified'
325 * or 'date_modified_gmt'. Optional, defaults to 'date'.
326 */
327 setDate: function( date, field ) {
328 var theField = field || 'date';
329
330 // Don't alter non-parsable date fields.
331 if ( _.indexOf( parseableDates, theField ) < 0 ) {
332 return false;
333 }
334
335 this.set( theField, date.toISOString() );
336 },
337
338 /**
339 * Get a JavaScript Date from the passed field.
340 *
341 * WordPress returns 'date' and 'date_modified' in the timezone of the server as well as
342 * UTC dates as 'date_gmt' and 'date_modified_gmt'. Draft posts do not include UTC dates.
343 *
344 * @param {string} field The date field to set. One of 'date', 'date_gmt', 'date_modified'
345 * or 'date_modified_gmt'. Optional, defaults to 'date'.
346 */
347 getDate: function( field ) {
348 var theField = field || 'date',
349 theISODate = this.get( theField );
350
351 // Only get date fields and non-null values.
352 if ( _.indexOf( parseableDates, theField ) < 0 || _.isNull( theISODate ) ) {
353 return false;
354 }
355
356 return new Date( wp.api.utils.parseISO8601( theISODate ) );
357 }
358 },
359
360 /**
361 * Build a helper function to retrieve related model.
362 *
363 * @param {string} parentModel The parent model.
364 * @param {number} modelId The model ID if the object to request
365 * @param {string} modelName The model name to use when constructing the model.
366 * @param {string} embedSourcePoint Where to check the embedded object for _embed data.
367 * @param {string} embedCheckField Which model field to check to see if the model has data.
368 *
369 * @return {Deferred.promise} A promise which resolves to the constructed model.
370 */
371 buildModelGetter = function( parentModel, modelId, modelName, embedSourcePoint, embedCheckField ) {
372 var getModel, embeddedObjects, attributes, deferred;
373
374 deferred = jQuery.Deferred();
375 embeddedObjects = parentModel.get( '_embedded' ) || {};
376
377 // Verify that we have a valid object id.
378 if ( ! _.isNumber( modelId ) || 0 === modelId ) {
379 deferred.reject();
380 return deferred;
381 }
382
383 // If we have embedded object data, use that when constructing the getModel.
384 if ( embeddedObjects[ embedSourcePoint ] ) {
385 attributes = _.findWhere( embeddedObjects[ embedSourcePoint ], { id: modelId } );
386 }
387
388 // Otherwise use the modelId.
389 if ( ! attributes ) {
390 attributes = { id: modelId };
391 }
392
393 // Create the new getModel model.
394 getModel = new wp.api.models[ modelName ]( attributes );
395
396 if ( ! getModel.get( embedCheckField ) ) {
397 getModel.fetch( {
398 success: function( getModel ) {
399 deferred.resolve( getModel );
400 },
401 error: function( getModel, response ) {
402 deferred.reject( response );
403 }
404 } );
405 } else {
406 // Resolve with the embedded model.
407 deferred.resolve( getModel );
408 }
409
410 // Return a promise.
411 return deferred.promise();
412 },
413
414 /**
415 * Build a helper to retrieve a collection.
416 *
417 * @param {string} parentModel The parent model.
418 * @param {string} collectionName The name to use when constructing the collection.
419 * @param {string} embedSourcePoint Where to check the embedded object for _embed data.
420 * @param {string} embedIndex An additional optional index for the _embed data.
421 *
422 * @return {Deferred.promise} A promise which resolves to the constructed collection.
423 */
424 buildCollectionGetter = function( parentModel, collectionName, embedSourcePoint, embedIndex ) {
425 /**
426 * Returns a promise that resolves to the requested collection
427 *
428 * Uses the embedded data if available, otherwise fetches the
429 * data from the server.
430 *
431 * @return {Deferred.promise} promise Resolves to a wp.api.collections[ collectionName ]
432 * collection.
433 */
434 var postId, embeddedObjects, getObjects,
435 classProperties = '',
436 properties = '',
437 deferred = jQuery.Deferred();
438
439 postId = parentModel.get( 'id' );
440 embeddedObjects = parentModel.get( '_embedded' ) || {};
441
442 // Verify that we have a valid post ID.
443 if ( ! _.isNumber( postId ) || 0 === postId ) {
444 deferred.reject();
445 return deferred;
446 }
447
448 // If we have embedded getObjects data, use that when constructing the getObjects.
449 if ( ! _.isUndefined( embedSourcePoint ) && ! _.isUndefined( embeddedObjects[ embedSourcePoint ] ) ) {
450
451 // Some embeds also include an index offset, check for that.
452 if ( _.isUndefined( embedIndex ) ) {
453
454 // Use the embed source point directly.
455 properties = embeddedObjects[ embedSourcePoint ];
456 } else {
457
458 // Add the index to the embed source point.
459 properties = embeddedObjects[ embedSourcePoint ][ embedIndex ];
460 }
461 } else {
462
463 // Otherwise use the postId.
464 classProperties = { parent: postId };
465 }
466
467 // Create the new getObjects collection.
468 getObjects = new wp.api.collections[ collectionName ]( properties, classProperties );
469
470 // If we didn’t have embedded getObjects, fetch the getObjects data.
471 if ( _.isUndefined( getObjects.models[0] ) ) {
472 getObjects.fetch( {
473 success: function( getObjects ) {
474
475 // Add a helper 'parent_post' attribute onto the model.
476 setHelperParentPost( getObjects, postId );
477 deferred.resolve( getObjects );
478 },
479 error: function( getModel, response ) {
480 deferred.reject( response );
481 }
482 } );
483 } else {
484
485 // Add a helper 'parent_post' attribute onto the model.
486 setHelperParentPost( getObjects, postId );
487 deferred.resolve( getObjects );
488 }
489
490 // Return a promise.
491 return deferred.promise();
492
493 },
494
495 /**
496 * Set the model post parent.
497 */
498 setHelperParentPost = function( collection, postId ) {
499
500 // Attach post_parent id to the collection.
501 _.each( collection.models, function( model ) {
502 model.set( 'parent_post', postId );
503 } );
504 },
505
506 /**
507 * Add a helper function to handle post Meta.
508 */
509 MetaMixin = {
510
511 /**
512 * Get meta by key for a post.
513 *
514 * @param {string} key The meta key.
515 *
516 * @return {Object} The post meta value.
517 */
518 getMeta: function( key ) {
519 var metas = this.get( 'meta' );
520 return metas[ key ];
521 },
522
523 /**
524 * Get all meta key/values for a post.
525 *
526 * @return {Object} The post metas, as a key value pair object.
527 */
528 getMetas: function() {
529 return this.get( 'meta' );
530 },
531
532 /**
533 * Set a group of meta key/values for a post.
534 *
535 * @param {Object} meta The post meta to set, as key/value pairs.
536 */
537 setMetas: function( meta ) {
538 var metas = this.get( 'meta' );
539 _.extend( metas, meta );
540 this.set( 'meta', metas );
541 },
542
543 /**
544 * Set a single meta value for a post, by key.
545 *
546 * @param {string} key The meta key.
547 * @param {Object} value The meta value.
548 */
549 setMeta: function( key, value ) {
550 var metas = this.get( 'meta' );
551 metas[ key ] = value;
552 this.set( 'meta', metas );
553 }
554 },
555
556 /**
557 * Add a helper function to handle post Revisions.
558 */
559 RevisionsMixin = {
560 getRevisions: function() {
561 return buildCollectionGetter( this, 'PostRevisions' );
562 }
563 },
564
565 /**
566 * Add a helper function to handle post Tags.
567 */
568 TagsMixin = {
569
570 /**
571 * Get the tags for a post.
572 *
573 * @return {Deferred.promise} promise Resolves to an array of tags.
574 */
575 getTags: function() {
576 var tagIds = this.get( 'tags' ),
577 tags = new wp.api.collections.Tags();
578
579 // Resolve with an empty array if no tags.
580 if ( _.isEmpty( tagIds ) ) {
581 return jQuery.Deferred().resolve( [] );
582 }
583
584 return tags.fetch( { data: { include: tagIds } } );
585 },
586
587 /**
588 * Set the tags for a post.
589 *
590 * Accepts an array of tag slugs, or a Tags collection.
591 *
592 * @param {Array|Backbone.Collection} tags The tags to set on the post.
593 *
594 */
595 setTags: function( tags ) {
596 var allTags, newTag,
597 self = this,
598 newTags = [];
599
600 if ( _.isString( tags ) ) {
601 return false;
602 }
603
604 // If this is an array of slugs, build a collection.
605 if ( _.isArray( tags ) ) {
606
607 // Get all the tags.
608 allTags = new wp.api.collections.Tags();
609 allTags.fetch( {
610 data: { per_page: 100 },
611 success: function( alltags ) {
612
613 // Find the passed tags and set them up.
614 _.each( tags, function( tag ) {
615 newTag = new wp.api.models.Tag( alltags.findWhere( { slug: tag } ) );
616
617 // Tie the new tag to the post.
618 newTag.set( 'parent_post', self.get( 'id' ) );
619
620 // Add the new tag to the collection.
621 newTags.push( newTag );
622 } );
623 tags = new wp.api.collections.Tags( newTags );
624 self.setTagsWithCollection( tags );
625 }
626 } );
627
628 } else {
629 this.setTagsWithCollection( tags );
630 }
631 },
632
633 /**
634 * Set the tags for a post.
635 *
636 * Accepts a Tags collection.
637 *
638 * @param {Array|Backbone.Collection} tags The tags to set on the post.
639 *
640 */
641 setTagsWithCollection: function( tags ) {
642
643 // Pluck out the category IDs.
644 this.set( 'tags', tags.pluck( 'id' ) );
645 return this.save();
646 }
647 },
648
649 /**
650 * Add a helper function to handle post Categories.
651 */
652 CategoriesMixin = {
653
654 /**
655 * Get a the categories for a post.
656 *
657 * @return {Deferred.promise} promise Resolves to an array of categories.
658 */
659 getCategories: function() {
660 var categoryIds = this.get( 'categories' ),
661 categories = new wp.api.collections.Categories();
662
663 // Resolve with an empty array if no categories.
664 if ( _.isEmpty( categoryIds ) ) {
665 return jQuery.Deferred().resolve( [] );
666 }
667
668 return categories.fetch( { data: { include: categoryIds } } );
669 },
670
671 /**
672 * Set the categories for a post.
673 *
674 * Accepts an array of category slugs, or a Categories collection.
675 *
676 * @param {Array|Backbone.Collection} categories The categories to set on the post.
677 *
678 */
679 setCategories: function( categories ) {
680 var allCategories, newCategory,
681 self = this,
682 newCategories = [];
683
684 if ( _.isString( categories ) ) {
685 return false;
686 }
687
688 // If this is an array of slugs, build a collection.
689 if ( _.isArray( categories ) ) {
690
691 // Get all the categories.
692 allCategories = new wp.api.collections.Categories();
693 allCategories.fetch( {
694 data: { per_page: 100 },
695 success: function( allcats ) {
696
697 // Find the passed categories and set them up.
698 _.each( categories, function( category ) {
699 newCategory = new wp.api.models.Category( allcats.findWhere( { slug: category } ) );
700
701 // Tie the new category to the post.
702 newCategory.set( 'parent_post', self.get( 'id' ) );
703
704 // Add the new category to the collection.
705 newCategories.push( newCategory );
706 } );
707 categories = new wp.api.collections.Categories( newCategories );
708 self.setCategoriesWithCollection( categories );
709 }
710 } );
711
712 } else {
713 this.setCategoriesWithCollection( categories );
714 }
715
716 },
717
718 /**
719 * Set the categories for a post.
720 *
721 * Accepts Categories collection.
722 *
723 * @param {Array|Backbone.Collection} categories The categories to set on the post.
724 *
725 */
726 setCategoriesWithCollection: function( categories ) {
727
728 // Pluck out the category IDs.
729 this.set( 'categories', categories.pluck( 'id' ) );
730 return this.save();
731 }
732 },
733
734 /**
735 * Add a helper function to retrieve the author user model.
736 */
737 AuthorMixin = {
738 getAuthorUser: function() {
739 return buildModelGetter( this, this.get( 'author' ), 'User', 'author', 'name' );
740 }
741 },
742
743 /**
744 * Add a helper function to retrieve the featured media.
745 */
746 FeaturedMediaMixin = {
747 getFeaturedMedia: function() {
748 return buildModelGetter( this, this.get( 'featured_media' ), 'Media', 'wp:featuredmedia', 'source_url' );
749 }
750 };
751
752 // Exit if we don't have valid model defaults.
753 if ( _.isUndefined( model.prototype.args ) ) {
754 return model;
755 }
756
757 // Go thru the parsable date fields, if our model contains any of them it gets the TimeStampedMixin.
758 _.each( parseableDates, function( theDateKey ) {
759 if ( ! _.isUndefined( model.prototype.args[ theDateKey ] ) ) {
760 hasDate = true;
761 }
762 } );
763
764 // Add the TimeStampedMixin for models that contain a date field.
765 if ( hasDate ) {
766 model = model.extend( TimeStampedMixin );
767 }
768
769 // Add the AuthorMixin for models that contain an author.
770 if ( ! _.isUndefined( model.prototype.args.author ) ) {
771 model = model.extend( AuthorMixin );
772 }
773
774 // Add the FeaturedMediaMixin for models that contain a featured_media.
775 if ( ! _.isUndefined( model.prototype.args.featured_media ) ) {
776 model = model.extend( FeaturedMediaMixin );
777 }
778
779 // Add the CategoriesMixin for models that support categories collections.
780 if ( ! _.isUndefined( model.prototype.args.categories ) ) {
781 model = model.extend( CategoriesMixin );
782 }
783
784 // Add the MetaMixin for models that support meta.
785 if ( ! _.isUndefined( model.prototype.args.meta ) ) {
786 model = model.extend( MetaMixin );
787 }
788
789 // Add the TagsMixin for models that support tags collections.
790 if ( ! _.isUndefined( model.prototype.args.tags ) ) {
791 model = model.extend( TagsMixin );
792 }
793
794 // Add the RevisionsMixin for models that support revisions collections.
795 if ( ! _.isUndefined( loadingObjects.collections[ modelClassName + 'Revisions' ] ) ) {
796 model = model.extend( RevisionsMixin );
797 }
798
799 return model;
800 };
801
802})( window );
803
804/* global wpApiSettings:false */
805
806// Suppress warning about parse function's unused "options" argument:
807/* jshint unused:false */
808(function() {
809
810 'use strict';
811
812 var wpApiSettings = window.wpApiSettings || {},
813 trashableTypes = [ 'Comment', 'Media', 'Comment', 'Post', 'Page', 'Status', 'Taxonomy', 'Type' ];
814
815 /**
816 * Backbone base model for all models.
817 */
818 wp.api.WPApiBaseModel = Backbone.Model.extend(
819 /** @lends WPApiBaseModel.prototype */
820 {
821
822 // Initialize the model.
823 initialize: function() {
824
825 /**
826 * Types that don't support trashing require passing ?force=true to delete.
827 *
828 */
829 if ( -1 === _.indexOf( trashableTypes, this.name ) ) {
830 this.requireForceForDelete = true;
831 }
832 },
833
834 /**
835 * Set nonce header before every Backbone sync.
836 *
837 * @param {string} method.
838 * @param {Backbone.Model} model.
839 * @param {{beforeSend}, *} options.
840 * @return {*}.
841 */
842 sync: function( method, model, options ) {
843 var beforeSend;
844
845 options = options || {};
846
847 // Remove date_gmt if null.
848 if ( _.isNull( model.get( 'date_gmt' ) ) ) {
849 model.unset( 'date_gmt' );
850 }
851
852 // Remove slug if empty.
853 if ( _.isEmpty( model.get( 'slug' ) ) ) {
854 model.unset( 'slug' );
855 }
856
857 if ( _.isFunction( model.nonce ) && ! _.isEmpty( model.nonce() ) ) {
858 beforeSend = options.beforeSend;
859
860 // @todo Enable option for jsonp endpoints.
861 // options.dataType = 'jsonp';
862
863 // Include the nonce with requests.
864 options.beforeSend = function( xhr ) {
865 xhr.setRequestHeader( 'X-WP-Nonce', model.nonce() );
866
867 if ( beforeSend ) {
868 return beforeSend.apply( this, arguments );
869 }
870 };
871
872 // Update the nonce when a new nonce is returned with the response.
873 options.complete = function( xhr ) {
874 var returnedNonce = xhr.getResponseHeader( 'X-WP-Nonce' );
875
876 if ( returnedNonce && _.isFunction( model.nonce ) && model.nonce() !== returnedNonce ) {
877 model.endpointModel.set( 'nonce', returnedNonce );
878 }
879 };
880 }
881
882 // Add '?force=true' to use delete method when required.
883 if ( this.requireForceForDelete && 'delete' === method ) {
884 model.url = model.url() + '?force=true';
885 }
886 return Backbone.sync( method, model, options );
887 },
888
889 /**
890 * Save is only allowed when the PUT OR POST methods are available for the endpoint.
891 */
892 save: function( attrs, options ) {
893
894 // Do we have the put method, then execute the save.
895 if ( _.includes( this.methods, 'PUT' ) || _.includes( this.methods, 'POST' ) ) {
896
897 // Proxy the call to the original save function.
898 return Backbone.Model.prototype.save.call( this, attrs, options );
899 } else {
900
901 // Otherwise bail, disallowing action.
902 return false;
903 }
904 },
905
906 /**
907 * Delete is only allowed when the DELETE method is available for the endpoint.
908 */
909 destroy: function( options ) {
910
911 // Do we have the DELETE method, then execute the destroy.
912 if ( _.includes( this.methods, 'DELETE' ) ) {
913
914 // Proxy the call to the original save function.
915 return Backbone.Model.prototype.destroy.call( this, options );
916 } else {
917
918 // Otherwise bail, disallowing action.
919 return false;
920 }
921 }
922
923 }
924 );
925
926 /**
927 * API Schema model. Contains meta information about the API.
928 */
929 wp.api.models.Schema = wp.api.WPApiBaseModel.extend(
930 /** @lends Schema.prototype */
931 {
932 defaults: {
933 _links: {},
934 namespace: null,
935 routes: {}
936 },
937
938 initialize: function( attributes, options ) {
939 var model = this;
940 options = options || {};
941
942 wp.api.WPApiBaseModel.prototype.initialize.call( model, attributes, options );
943
944 model.apiRoot = options.apiRoot || wpApiSettings.root;
945 model.versionString = options.versionString || wpApiSettings.versionString;
946 },
947
948 url: function() {
949 return this.apiRoot + this.versionString;
950 }
951 }
952 );
953})();
954
955( function() {
956
957 'use strict';
958
959 var wpApiSettings = window.wpApiSettings || {};
960
961 /**
962 * Contains basic collection functionality such as pagination.
963 */
964 wp.api.WPApiBaseCollection = Backbone.Collection.extend(
965 /** @lends BaseCollection.prototype */
966 {
967
968 /**
969 * Setup default state.
970 */
971 initialize: function( models, options ) {
972 this.state = {
973 data: {},
974 currentPage: null,
975 totalPages: null,
976 totalObjects: null
977 };
978 if ( _.isUndefined( options ) ) {
979 this.parent = '';
980 } else {
981 this.parent = options.parent;
982 }
983 },
984
985 /**
986 * Extend Backbone.Collection.sync to add nince and pagination support.
987 *
988 * Set nonce header before every Backbone sync.
989 *
990 * @param {string} method.
991 * @param {Backbone.Model} model.
992 * @param {{success}, *} options.
993 * @return {*}.
994 */
995 sync: function( method, model, options ) {
996 var beforeSend, success,
997 self = this;
998
999 options = options || {};
1000
1001 if ( _.isFunction( model.nonce ) && ! _.isEmpty( model.nonce() ) ) {
1002 beforeSend = options.beforeSend;
1003
1004 // Include the nonce with requests.
1005 options.beforeSend = function( xhr ) {
1006 xhr.setRequestHeader( 'X-WP-Nonce', model.nonce() );
1007
1008 if ( beforeSend ) {
1009 return beforeSend.apply( self, arguments );
1010 }
1011 };
1012
1013 // Update the nonce when a new nonce is returned with the response.
1014 options.complete = function( xhr ) {
1015 var returnedNonce = xhr.getResponseHeader( 'X-WP-Nonce' );
1016
1017 if ( returnedNonce && _.isFunction( model.nonce ) && model.nonce() !== returnedNonce ) {
1018 model.endpointModel.set( 'nonce', returnedNonce );
1019 }
1020 };
1021 }
1022
1023 // When reading, add pagination data.
1024 if ( 'read' === method ) {
1025 if ( options.data ) {
1026 self.state.data = _.clone( options.data );
1027
1028 delete self.state.data.page;
1029 } else {
1030 self.state.data = options.data = {};
1031 }
1032
1033 if ( 'undefined' === typeof options.data.page ) {
1034 self.state.currentPage = null;
1035 self.state.totalPages = null;
1036 self.state.totalObjects = null;
1037 } else {
1038 self.state.currentPage = options.data.page - 1;
1039 }
1040
1041 success = options.success;
1042 options.success = function( data, textStatus, request ) {
1043 if ( ! _.isUndefined( request ) ) {
1044 self.state.totalPages = parseInt( request.getResponseHeader( 'x-wp-totalpages' ), 10 );
1045 self.state.totalObjects = parseInt( request.getResponseHeader( 'x-wp-total' ), 10 );
1046 }
1047
1048 if ( null === self.state.currentPage ) {
1049 self.state.currentPage = 1;
1050 } else {
1051 self.state.currentPage++;
1052 }
1053
1054 if ( success ) {
1055 return success.apply( this, arguments );
1056 }
1057 };
1058 }
1059
1060 // Continue by calling Backbone's sync.
1061 return Backbone.sync( method, model, options );
1062 },
1063
1064 /**
1065 * Fetches the next page of objects if a new page exists.
1066 *
1067 * @param {data: {page}} options.
1068 * @return {*}.
1069 */
1070 more: function( options ) {
1071 options = options || {};
1072 options.data = options.data || {};
1073
1074 _.extend( options.data, this.state.data );
1075
1076 if ( 'undefined' === typeof options.data.page ) {
1077 if ( ! this.hasMore() ) {
1078 return false;
1079 }
1080
1081 if ( null === this.state.currentPage || this.state.currentPage <= 1 ) {
1082 options.data.page = 2;
1083 } else {
1084 options.data.page = this.state.currentPage + 1;
1085 }
1086 }
1087
1088 return this.fetch( options );
1089 },
1090
1091 /**
1092 * Returns true if there are more pages of objects available.
1093 *
1094 * @return {null|boolean}
1095 */
1096 hasMore: function() {
1097 if ( null === this.state.totalPages ||
1098 null === this.state.totalObjects ||
1099 null === this.state.currentPage ) {
1100 return null;
1101 } else {
1102 return ( this.state.currentPage < this.state.totalPages );
1103 }
1104 }
1105 }
1106 );
1107
1108} )();
1109
1110( function() {
1111
1112 'use strict';
1113
1114 var Endpoint, initializedDeferreds = {},
1115 wpApiSettings = window.wpApiSettings || {};
1116
1117 /** @namespace wp */
1118 window.wp = window.wp || {};
1119
1120 /** @namespace wp.api */
1121 wp.api = wp.api || {};
1122
1123 // If wpApiSettings is unavailable, try the default.
1124 if ( _.isEmpty( wpApiSettings ) ) {
1125 wpApiSettings.root = window.location.origin + '/wp-json/';
1126 }
1127
1128 Endpoint = Backbone.Model.extend(/** @lends Endpoint.prototype */{
1129 defaults: {
1130 apiRoot: wpApiSettings.root,
1131 versionString: wp.api.versionString,
1132 nonce: null,
1133 schema: null,
1134 models: {},
1135 collections: {}
1136 },
1137
1138 /**
1139 * Initialize the Endpoint model.
1140 */
1141 initialize: function() {
1142 var model = this, deferred;
1143
1144 Backbone.Model.prototype.initialize.apply( model, arguments );
1145
1146 deferred = jQuery.Deferred();
1147 model.schemaConstructed = deferred.promise();
1148
1149 model.schemaModel = new wp.api.models.Schema( null, {
1150 apiRoot: model.get( 'apiRoot' ),
1151 versionString: model.get( 'versionString' ),
1152 nonce: model.get( 'nonce' )
1153 } );
1154
1155 // When the model loads, resolve the promise.
1156 model.schemaModel.once( 'change', function() {
1157 model.constructFromSchema();
1158 deferred.resolve( model );
1159 } );
1160
1161 if ( model.get( 'schema' ) ) {
1162
1163 // Use schema supplied as model attribute.
1164 model.schemaModel.set( model.schemaModel.parse( model.get( 'schema' ) ) );
1165 } else if (
1166 ! _.isUndefined( sessionStorage ) &&
1167 ( _.isUndefined( wpApiSettings.cacheSchema ) || wpApiSettings.cacheSchema ) &&
1168 sessionStorage.getItem( 'wp-api-schema-model' + model.get( 'apiRoot' ) + model.get( 'versionString' ) )
1169 ) {
1170
1171 // Used a cached copy of the schema model if available.
1172 model.schemaModel.set( model.schemaModel.parse( JSON.parse( sessionStorage.getItem( 'wp-api-schema-model' + model.get( 'apiRoot' ) + model.get( 'versionString' ) ) ) ) );
1173 } else {
1174 model.schemaModel.fetch( {
1175 /**
1176 * When the server returns the schema model data, store the data in a sessionCache so we don't
1177 * have to retrieve it again for this session. Then, construct the models and collections based
1178 * on the schema model data.
1179 *
1180 * @ignore
1181 */
1182 success: function( newSchemaModel ) {
1183
1184 // Store a copy of the schema model in the session cache if available.
1185 if ( ! _.isUndefined( sessionStorage ) && ( _.isUndefined( wpApiSettings.cacheSchema ) || wpApiSettings.cacheSchema ) ) {
1186 try {
1187 sessionStorage.setItem( 'wp-api-schema-model' + model.get( 'apiRoot' ) + model.get( 'versionString' ), JSON.stringify( newSchemaModel ) );
1188 } catch ( error ) {
1189
1190 // Fail silently, fixes errors in safari private mode.
1191 }
1192 }
1193 },
1194
1195 // Log the error condition.
1196 error: function( err ) {
1197 window.console.log( err );
1198 }
1199 } );
1200 }
1201 },
1202
1203 constructFromSchema: function() {
1204 var routeModel = this, modelRoutes, collectionRoutes, schemaRoot, loadingObjects,
1205
1206 /**
1207 * Set up the model and collection name mapping options. As the schema is built, the
1208 * model and collection names will be adjusted if they are found in the mapping object.
1209 *
1210 * Localizing a variable wpApiSettings.mapping will over-ride the default mapping options.
1211 *
1212 */
1213 mapping = wpApiSettings.mapping || {
1214 models: {
1215 'Categories': 'Category',
1216 'Comments': 'Comment',
1217 'Pages': 'Page',
1218 'PagesMeta': 'PageMeta',
1219 'PagesRevisions': 'PageRevision',
1220 'Posts': 'Post',
1221 'PostsCategories': 'PostCategory',
1222 'PostsRevisions': 'PostRevision',
1223 'PostsTags': 'PostTag',
1224 'Schema': 'Schema',
1225 'Statuses': 'Status',
1226 'Tags': 'Tag',
1227 'Taxonomies': 'Taxonomy',
1228 'Types': 'Type',
1229 'Users': 'User'
1230 },
1231 collections: {
1232 'PagesMeta': 'PageMeta',
1233 'PagesRevisions': 'PageRevisions',
1234 'PostsCategories': 'PostCategories',
1235 'PostsMeta': 'PostMeta',
1236 'PostsRevisions': 'PostRevisions',
1237 'PostsTags': 'PostTags'
1238 }
1239 },
1240
1241 modelEndpoints = routeModel.get( 'modelEndpoints' ),
1242 modelRegex = new RegExp( '(?:.*[+)]|\/(' + modelEndpoints.join( '|' ) + '))$' );
1243
1244 /**
1245 * Iterate thru the routes, picking up models and collections to build. Builds two arrays,
1246 * one for models and one for collections.
1247 */
1248 modelRoutes = [];
1249 collectionRoutes = [];
1250 schemaRoot = routeModel.get( 'apiRoot' ).replace( wp.api.utils.getRootUrl(), '' );
1251 loadingObjects = {};
1252
1253 /**
1254 * Tracking objects for models and collections.
1255 */
1256 loadingObjects.models = {};
1257 loadingObjects.collections = {};
1258
1259 _.each( routeModel.schemaModel.get( 'routes' ), function( route, index ) {
1260
1261 // Skip the schema root if included in the schema.
1262 if ( index !== routeModel.get( ' versionString' ) &&
1263 index !== schemaRoot &&
1264 index !== ( '/' + routeModel.get( 'versionString' ).slice( 0, -1 ) )
1265 ) {
1266
1267 // Single items end with a regex, or a special case word.
1268 if ( modelRegex.test( index ) ) {
1269 modelRoutes.push( { index: index, route: route } );
1270 } else {
1271
1272 // Collections end in a name.
1273 collectionRoutes.push( { index: index, route: route } );
1274 }
1275 }
1276 } );
1277
1278 /**
1279 * Construct the models.
1280 *
1281 * Base the class name on the route endpoint.
1282 */
1283 _.each( modelRoutes, function( modelRoute ) {
1284
1285 // Extract the name and any parent from the route.
1286 var modelClassName,
1287 routeName = wp.api.utils.extractRoutePart( modelRoute.index, 2, routeModel.get( 'versionString' ), true ),
1288 parentName = wp.api.utils.extractRoutePart( modelRoute.index, 1, routeModel.get( 'versionString' ), false ),
1289 routeEnd = wp.api.utils.extractRoutePart( modelRoute.index, 1, routeModel.get( 'versionString' ), true );
1290
1291 // Clear the parent part of the rouite if its actually the version string.
1292 if ( parentName === routeModel.get( 'versionString' ) ) {
1293 parentName = '';
1294 }
1295
1296 // Handle the special case of the 'me' route.
1297 if ( 'me' === routeEnd ) {
1298 routeName = 'me';
1299 }
1300
1301 // If the model has a parent in its route, add that to its class name.
1302 if ( '' !== parentName && parentName !== routeName ) {
1303 modelClassName = wp.api.utils.capitalizeAndCamelCaseDashes( parentName ) + wp.api.utils.capitalizeAndCamelCaseDashes( routeName );
1304 modelClassName = mapping.models[ modelClassName ] || modelClassName;
1305 loadingObjects.models[ modelClassName ] = wp.api.WPApiBaseModel.extend( {
1306
1307 // Return a constructed url based on the parent and id.
1308 url: function() {
1309 var url =
1310 routeModel.get( 'apiRoot' ) +
1311 routeModel.get( 'versionString' ) +
1312 parentName + '/' +
1313 ( ( _.isUndefined( this.get( 'parent' ) ) || 0 === this.get( 'parent' ) ) ?
1314 ( _.isUndefined( this.get( 'parent_post' ) ) ? '' : this.get( 'parent_post' ) + '/' ) :
1315 this.get( 'parent' ) + '/' ) +
1316 routeName;
1317
1318 if ( ! _.isUndefined( this.get( 'id' ) ) ) {
1319 url += '/' + this.get( 'id' );
1320 }
1321 return url;
1322 },
1323
1324 // Track nonces on the Endpoint 'routeModel'.
1325 nonce: function() {
1326 return routeModel.get( 'nonce' );
1327 },
1328
1329 endpointModel: routeModel,
1330
1331 // Include a reference to the original route object.
1332 route: modelRoute,
1333
1334 // Include a reference to the original class name.
1335 name: modelClassName,
1336
1337 // Include the array of route methods for easy reference.
1338 methods: modelRoute.route.methods,
1339
1340 // Include the array of route endpoints for easy reference.
1341 endpoints: modelRoute.route.endpoints
1342 } );
1343 } else {
1344
1345 // This is a model without a parent in its route.
1346 modelClassName = wp.api.utils.capitalizeAndCamelCaseDashes( routeName );
1347 modelClassName = mapping.models[ modelClassName ] || modelClassName;
1348 loadingObjects.models[ modelClassName ] = wp.api.WPApiBaseModel.extend( {
1349
1350 // Function that returns a constructed url based on the ID.
1351 url: function() {
1352 var url = routeModel.get( 'apiRoot' ) +
1353 routeModel.get( 'versionString' ) +
1354 ( ( 'me' === routeName ) ? 'users/me' : routeName );
1355
1356 if ( ! _.isUndefined( this.get( 'id' ) ) ) {
1357 url += '/' + this.get( 'id' );
1358 }
1359 return url;
1360 },
1361
1362 // Track nonces at the Endpoint level.
1363 nonce: function() {
1364 return routeModel.get( 'nonce' );
1365 },
1366
1367 endpointModel: routeModel,
1368
1369 // Include a reference to the original route object.
1370 route: modelRoute,
1371
1372 // Include a reference to the original class name.
1373 name: modelClassName,
1374
1375 // Include the array of route methods for easy reference.
1376 methods: modelRoute.route.methods,
1377
1378 // Include the array of route endpoints for easy reference.
1379 endpoints: modelRoute.route.endpoints
1380 } );
1381 }
1382
1383 // Add defaults to the new model, pulled form the endpoint.
1384 wp.api.utils.decorateFromRoute(
1385 modelRoute.route.endpoints,
1386 loadingObjects.models[ modelClassName ],
1387 routeModel.get( 'versionString' )
1388 );
1389
1390 } );
1391
1392 /**
1393 * Construct the collections.
1394 *
1395 * Base the class name on the route endpoint.
1396 */
1397 _.each( collectionRoutes, function( collectionRoute ) {
1398
1399 // Extract the name and any parent from the route.
1400 var collectionClassName, modelClassName,
1401 routeName = collectionRoute.index.slice( collectionRoute.index.lastIndexOf( '/' ) + 1 ),
1402 parentName = wp.api.utils.extractRoutePart( collectionRoute.index, 1, routeModel.get( 'versionString' ), false );
1403
1404 // If the collection has a parent in its route, add that to its class name.
1405 if ( '' !== parentName && parentName !== routeName && routeModel.get( 'versionString' ) !== parentName ) {
1406
1407 collectionClassName = wp.api.utils.capitalizeAndCamelCaseDashes( parentName ) + wp.api.utils.capitalizeAndCamelCaseDashes( routeName );
1408 modelClassName = mapping.models[ collectionClassName ] || collectionClassName;
1409 collectionClassName = mapping.collections[ collectionClassName ] || collectionClassName;
1410 loadingObjects.collections[ collectionClassName ] = wp.api.WPApiBaseCollection.extend( {
1411
1412 // Function that returns a constructed url passed on the parent.
1413 url: function() {
1414 return routeModel.get( 'apiRoot' ) + routeModel.get( 'versionString' ) +
1415 parentName + '/' +
1416 ( ( _.isUndefined( this.parent ) || '' === this.parent ) ?
1417 ( _.isUndefined( this.get( 'parent_post' ) ) ? '' : this.get( 'parent_post' ) + '/' ) :
1418 this.parent + '/' ) +
1419 routeName;
1420 },
1421
1422 // Specify the model that this collection contains.
1423 model: function( attrs, options ) {
1424 return new loadingObjects.models[ modelClassName ]( attrs, options );
1425 },
1426
1427 // Track nonces at the Endpoint level.
1428 nonce: function() {
1429 return routeModel.get( 'nonce' );
1430 },
1431
1432 endpointModel: routeModel,
1433
1434 // Include a reference to the original class name.
1435 name: collectionClassName,
1436
1437 // Include a reference to the original route object.
1438 route: collectionRoute,
1439
1440 // Include the array of route methods for easy reference.
1441 methods: collectionRoute.route.methods
1442 } );
1443 } else {
1444
1445 // This is a collection without a parent in its route.
1446 collectionClassName = wp.api.utils.capitalizeAndCamelCaseDashes( routeName );
1447 modelClassName = mapping.models[ collectionClassName ] || collectionClassName;
1448 collectionClassName = mapping.collections[ collectionClassName ] || collectionClassName;
1449 loadingObjects.collections[ collectionClassName ] = wp.api.WPApiBaseCollection.extend( {
1450
1451 // For the url of a root level collection, use a string.
1452 url: function() {
1453 return routeModel.get( 'apiRoot' ) + routeModel.get( 'versionString' ) + routeName;
1454 },
1455
1456 // Specify the model that this collection contains.
1457 model: function( attrs, options ) {
1458 return new loadingObjects.models[ modelClassName ]( attrs, options );
1459 },
1460
1461 // Track nonces at the Endpoint level.
1462 nonce: function() {
1463 return routeModel.get( 'nonce' );
1464 },
1465
1466 endpointModel: routeModel,
1467
1468 // Include a reference to the original class name.
1469 name: collectionClassName,
1470
1471 // Include a reference to the original route object.
1472 route: collectionRoute,
1473
1474 // Include the array of route methods for easy reference.
1475 methods: collectionRoute.route.methods
1476 } );
1477 }
1478
1479 // Add defaults to the new model, pulled form the endpoint.
1480 wp.api.utils.decorateFromRoute( collectionRoute.route.endpoints, loadingObjects.collections[ collectionClassName ] );
1481 } );
1482
1483 // Add mixins and helpers for each of the models.
1484 _.each( loadingObjects.models, function( model, index ) {
1485 loadingObjects.models[ index ] = wp.api.utils.addMixinsAndHelpers( model, index, loadingObjects );
1486 } );
1487
1488 // Set the routeModel models and collections.
1489 routeModel.set( 'models', loadingObjects.models );
1490 routeModel.set( 'collections', loadingObjects.collections );
1491
1492 }
1493
1494 } );
1495
1496 wp.api.endpoints = new Backbone.Collection();
1497
1498 /**
1499 * Initialize the wp-api, optionally passing the API root.
1500 *
1501 * @param {Object} [args]
1502 * @param {string} [args.nonce] The nonce. Optional, defaults to wpApiSettings.nonce.
1503 * @param {string} [args.apiRoot] The api root. Optional, defaults to wpApiSettings.root.
1504 * @param {string} [args.versionString] The version string. Optional, defaults to wpApiSettings.root.
1505 * @param {Object} [args.schema] The schema. Optional, will be fetched from API if not provided.
1506 */
1507 wp.api.init = function( args ) {
1508 var endpoint, attributes = {}, deferred, promise;
1509
1510 args = args || {};
1511 attributes.nonce = _.isString( args.nonce ) ? args.nonce : ( wpApiSettings.nonce || '' );
1512 attributes.apiRoot = args.apiRoot || wpApiSettings.root || '/wp-json';
1513 attributes.versionString = args.versionString || wpApiSettings.versionString || 'wp/v2/';
1514 attributes.schema = args.schema || null;
1515 attributes.modelEndpoints = args.modelEndpoints || [ 'me', 'settings' ];
1516 if ( ! attributes.schema && attributes.apiRoot === wpApiSettings.root && attributes.versionString === wpApiSettings.versionString ) {
1517 attributes.schema = wpApiSettings.schema;
1518 }
1519
1520 if ( ! initializedDeferreds[ attributes.apiRoot + attributes.versionString ] ) {
1521
1522 // Look for an existing copy of this endpoint.
1523 endpoint = wp.api.endpoints.findWhere( { 'apiRoot': attributes.apiRoot, 'versionString': attributes.versionString } );
1524 if ( ! endpoint ) {
1525 endpoint = new Endpoint( attributes );
1526 }
1527 deferred = jQuery.Deferred();
1528 promise = deferred.promise();
1529
1530 endpoint.schemaConstructed.done( function( resolvedEndpoint ) {
1531 wp.api.endpoints.add( resolvedEndpoint );
1532
1533 // Map the default endpoints, extending any already present items (including Schema model).
1534 wp.api.models = _.extend( wp.api.models, resolvedEndpoint.get( 'models' ) );
1535 wp.api.collections = _.extend( wp.api.collections, resolvedEndpoint.get( 'collections' ) );
1536 deferred.resolve( resolvedEndpoint );
1537 } );
1538 initializedDeferreds[ attributes.apiRoot + attributes.versionString ] = promise;
1539 }
1540 return initializedDeferreds[ attributes.apiRoot + attributes.versionString ];
1541 };
1542
1543 /**
1544 * Construct the default endpoints and add to an endpoints collection.
1545 */
1546
1547 // The wp.api.init function returns a promise that will resolve with the endpoint once it is ready.
1548 wp.api.loadPromise = wp.api.init();
1549
1550} )();
1551
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1