diff -r 48c4eec2b7e6 -r 8c2e4d02f4ef wp/wp-includes/js/media-models.js --- a/wp/wp-includes/js/media-models.js Fri Sep 05 18:40:08 2025 +0200 +++ b/wp/wp-includes/js/media-models.js Fri Sep 05 18:52:52 2025 +0200 @@ -1,6 +1,317 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ +/***/ 1288: +/***/ ((module) => { + +var Attachments = wp.media.model.Attachments, + Query; + +/** + * wp.media.model.Query + * + * A collection of attachments that match the supplied query arguments. + * + * Note: Do NOT change this.args after the query has been initialized. + * Things will break. + * + * @memberOf wp.media.model + * + * @class + * @augments wp.media.model.Attachments + * @augments Backbone.Collection + * + * @param {array} [models] Models to initialize with the collection. + * @param {object} [options] Options hash. + * @param {object} [options.args] Attachments query arguments. + * @param {object} [options.args.posts_per_page] + */ +Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{ + /** + * @param {Array} [models=[]] Array of initial models to populate the collection. + * @param {Object} [options={}] + */ + initialize: function( models, options ) { + var allowed; + + options = options || {}; + Attachments.prototype.initialize.apply( this, arguments ); + + this.args = options.args; + this._hasMore = true; + this.created = new Date(); + + this.filters.order = function( attachment ) { + var orderby = this.props.get('orderby'), + order = this.props.get('order'); + + if ( ! this.comparator ) { + return true; + } + + /* + * We want any items that can be placed before the last + * item in the set. If we add any items after the last + * item, then we can't guarantee the set is complete. + */ + if ( this.length ) { + return 1 !== this.comparator( attachment, this.last(), { ties: true }); + + /* + * Handle the case where there are no items yet and + * we're sorting for recent items. In that case, we want + * changes that occurred after we created the query. + */ + } else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) { + return attachment.get( orderby ) >= this.created; + + // If we're sorting by menu order and we have no items, + // accept any items that have the default menu order (0). + } else if ( 'ASC' === order && 'menuOrder' === orderby ) { + return attachment.get( orderby ) === 0; + } + + // Otherwise, we don't want any items yet. + return false; + }; + + /* + * Observe the central `wp.Uploader.queue` collection to watch for + * new matches for the query. + * + * Only observe when a limited number of query args are set. There + * are no filters for other properties, so observing will result in + * false positives in those queries. + */ + allowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent', 'author' ]; + if ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) { + this.observe( wp.Uploader.queue ); + } + }, + /** + * Whether there are more attachments that haven't been sync'd from the server + * that match the collection's query. + * + * @return {boolean} + */ + hasMore: function() { + return this._hasMore; + }, + /** + * Fetch more attachments from the server for the collection. + * + * @param {Object} [options={}] + * @return {Promise} + */ + more: function( options ) { + var query = this; + + // If there is already a request pending, return early with the Deferred object. + if ( this._more && 'pending' === this._more.state() ) { + return this._more; + } + + if ( ! this.hasMore() ) { + return jQuery.Deferred().resolveWith( this ).promise(); + } + + options = options || {}; + options.remove = false; + + return this._more = this.fetch( options ).done( function( response ) { + if ( _.isEmpty( response ) || -1 === query.args.posts_per_page || response.length < query.args.posts_per_page ) { + query._hasMore = false; + } + }); + }, + /** + * Overrides Backbone.Collection.sync + * Overrides wp.media.model.Attachments.sync + * + * @param {string} method + * @param {Backbone.Model} model + * @param {Object} [options={}] + * @return {Promise} + */ + sync: function( method, model, options ) { + var args, fallback; + + // Overload the read method so Attachment.fetch() functions correctly. + if ( 'read' === method ) { + options = options || {}; + options.context = this; + options.data = _.extend( options.data || {}, { + action: 'query-attachments', + post_id: wp.media.model.settings.post.id + }); + + // Clone the args so manipulation is non-destructive. + args = _.clone( this.args ); + + // Determine which page to query. + if ( -1 !== args.posts_per_page ) { + args.paged = Math.round( this.length / args.posts_per_page ) + 1; + } + + options.data.query = args; + return wp.media.ajax( options ); + + // Otherwise, fall back to `Backbone.sync()`. + } else { + /** + * Call wp.media.model.Attachments.sync or Backbone.sync + */ + fallback = Attachments.prototype.sync ? Attachments.prototype : Backbone; + return fallback.sync.apply( this, arguments ); + } + } +}, /** @lends wp.media.model.Query */{ + /** + * @readonly + */ + defaultProps: { + orderby: 'date', + order: 'DESC' + }, + /** + * @readonly + */ + defaultArgs: { + posts_per_page: 80 + }, + /** + * @readonly + */ + orderby: { + allowed: [ 'name', 'author', 'date', 'title', 'modified', 'uploadedTo', 'id', 'post__in', 'menuOrder' ], + /** + * A map of JavaScript orderby values to their WP_Query equivalents. + * @type {Object} + */ + valuemap: { + 'id': 'ID', + 'uploadedTo': 'parent', + 'menuOrder': 'menu_order ID' + } + }, + /** + * A map of JavaScript query properties to their WP_Query equivalents. + * + * @readonly + */ + propmap: { + 'search': 's', + 'type': 'post_mime_type', + 'perPage': 'posts_per_page', + 'menuOrder': 'menu_order', + 'uploadedTo': 'post_parent', + 'status': 'post_status', + 'include': 'post__in', + 'exclude': 'post__not_in', + 'author': 'author' + }, + /** + * Creates and returns an Attachments Query collection given the properties. + * + * Caches query objects and reuses where possible. + * + * @static + * @method + * + * @param {object} [props] + * @param {Object} [props.order] + * @param {Object} [props.orderby] + * @param {Object} [props.include] + * @param {Object} [props.exclude] + * @param {Object} [props.s] + * @param {Object} [props.post_mime_type] + * @param {Object} [props.posts_per_page] + * @param {Object} [props.menu_order] + * @param {Object} [props.post_parent] + * @param {Object} [props.post_status] + * @param {Object} [props.author] + * @param {Object} [options] + * + * @return {wp.media.model.Query} A new Attachments Query collection. + */ + get: (function(){ + /** + * @static + * @type Array + */ + var queries = []; + + /** + * @return {Query} + */ + return function( props, options ) { + var args = {}, + orderby = Query.orderby, + defaults = Query.defaultProps, + query; + + // Remove the `query` property. This isn't linked to a query, + // this *is* the query. + delete props.query; + + // Fill default args. + _.defaults( props, defaults ); + + // Normalize the order. + props.order = props.order.toUpperCase(); + if ( 'DESC' !== props.order && 'ASC' !== props.order ) { + props.order = defaults.order.toUpperCase(); + } + + // Ensure we have a valid orderby value. + if ( ! _.contains( orderby.allowed, props.orderby ) ) { + props.orderby = defaults.orderby; + } + + _.each( [ 'include', 'exclude' ], function( prop ) { + if ( props[ prop ] && ! _.isArray( props[ prop ] ) ) { + props[ prop ] = [ props[ prop ] ]; + } + } ); + + // Generate the query `args` object. + // Correct any differing property names. + _.each( props, function( value, prop ) { + if ( _.isNull( value ) ) { + return; + } + + args[ Query.propmap[ prop ] || prop ] = value; + }); + + // Fill any other default query args. + _.defaults( args, Query.defaultArgs ); + + // `props.orderby` does not always map directly to `args.orderby`. + // Substitute exceptions specified in orderby.keymap. + args.orderby = orderby.valuemap[ props.orderby ] || props.orderby; + + queries = []; + + // Otherwise, create a new query and add it to the cache. + if ( ! query ) { + query = new Query( [], _.extend( options || {}, { + props: props, + args: args + } ) ); + queries.push( query ); + } + + return query; + }; + }()) +}); + +module.exports = Query; + + +/***/ }), + /***/ 3343: /***/ ((module) => { @@ -177,6 +488,110 @@ /***/ }), +/***/ 4134: +/***/ ((module) => { + +var Attachments = wp.media.model.Attachments, + Selection; + +/** + * wp.media.model.Selection + * + * A selection of attachments. + * + * @memberOf wp.media.model + * + * @class + * @augments wp.media.model.Attachments + * @augments Backbone.Collection + */ +Selection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{ + /** + * Refresh the `single` model whenever the selection changes. + * Binds `single` instead of using the context argument to ensure + * it receives no parameters. + * + * @param {Array} [models=[]] Array of models used to populate the collection. + * @param {Object} [options={}] + */ + initialize: function( models, options ) { + /** + * call 'initialize' directly on the parent class + */ + Attachments.prototype.initialize.apply( this, arguments ); + this.multiple = options && options.multiple; + + this.on( 'add remove reset', _.bind( this.single, this, false ) ); + }, + + /** + * If the workflow does not support multi-select, clear out the selection + * before adding a new attachment to it. + * + * @param {Array} models + * @param {Object} options + * @return {wp.media.model.Attachment[]} + */ + add: function( models, options ) { + if ( ! this.multiple ) { + this.remove( this.models ); + } + /** + * call 'add' directly on the parent class + */ + return Attachments.prototype.add.call( this, models, options ); + }, + + /** + * Fired when toggling (clicking on) an attachment in the modal. + * + * @param {undefined|boolean|wp.media.model.Attachment} model + * + * @fires wp.media.model.Selection#selection:single + * @fires wp.media.model.Selection#selection:unsingle + * + * @return {Backbone.Model} + */ + single: function( model ) { + var previous = this._single; + + // If a `model` is provided, use it as the single model. + if ( model ) { + this._single = model; + } + // If the single model isn't in the selection, remove it. + if ( this._single && ! this.get( this._single.cid ) ) { + delete this._single; + } + + this._single = this._single || this.last(); + + // If single has changed, fire an event. + if ( this._single !== previous ) { + if ( previous ) { + previous.trigger( 'selection:unsingle', previous, this ); + + // If the model was already removed, trigger the collection + // event manually. + if ( ! this.get( previous.cid ) ) { + this.trigger( 'selection:unsingle', previous, this ); + } + } + if ( this._single ) { + this._single.trigger( 'selection:single', this._single, this ); + } + } + + // Return the single model, or the last model as a fallback. + return this._single; + } +}); + +module.exports = Selection; + + +/***/ }), + /***/ 8266: /***/ ((module) => { @@ -944,421 +1359,6 @@ module.exports = PostImage; -/***/ }), - -/***/ 1288: -/***/ ((module) => { - -var Attachments = wp.media.model.Attachments, - Query; - -/** - * wp.media.model.Query - * - * A collection of attachments that match the supplied query arguments. - * - * Note: Do NOT change this.args after the query has been initialized. - * Things will break. - * - * @memberOf wp.media.model - * - * @class - * @augments wp.media.model.Attachments - * @augments Backbone.Collection - * - * @param {array} [models] Models to initialize with the collection. - * @param {object} [options] Options hash. - * @param {object} [options.args] Attachments query arguments. - * @param {object} [options.args.posts_per_page] - */ -Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{ - /** - * @param {Array} [models=[]] Array of initial models to populate the collection. - * @param {Object} [options={}] - */ - initialize: function( models, options ) { - var allowed; - - options = options || {}; - Attachments.prototype.initialize.apply( this, arguments ); - - this.args = options.args; - this._hasMore = true; - this.created = new Date(); - - this.filters.order = function( attachment ) { - var orderby = this.props.get('orderby'), - order = this.props.get('order'); - - if ( ! this.comparator ) { - return true; - } - - /* - * We want any items that can be placed before the last - * item in the set. If we add any items after the last - * item, then we can't guarantee the set is complete. - */ - if ( this.length ) { - return 1 !== this.comparator( attachment, this.last(), { ties: true }); - - /* - * Handle the case where there are no items yet and - * we're sorting for recent items. In that case, we want - * changes that occurred after we created the query. - */ - } else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) { - return attachment.get( orderby ) >= this.created; - - // If we're sorting by menu order and we have no items, - // accept any items that have the default menu order (0). - } else if ( 'ASC' === order && 'menuOrder' === orderby ) { - return attachment.get( orderby ) === 0; - } - - // Otherwise, we don't want any items yet. - return false; - }; - - /* - * Observe the central `wp.Uploader.queue` collection to watch for - * new matches for the query. - * - * Only observe when a limited number of query args are set. There - * are no filters for other properties, so observing will result in - * false positives in those queries. - */ - allowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent', 'author' ]; - if ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) { - this.observe( wp.Uploader.queue ); - } - }, - /** - * Whether there are more attachments that haven't been sync'd from the server - * that match the collection's query. - * - * @return {boolean} - */ - hasMore: function() { - return this._hasMore; - }, - /** - * Fetch more attachments from the server for the collection. - * - * @param {Object} [options={}] - * @return {Promise} - */ - more: function( options ) { - var query = this; - - // If there is already a request pending, return early with the Deferred object. - if ( this._more && 'pending' === this._more.state() ) { - return this._more; - } - - if ( ! this.hasMore() ) { - return jQuery.Deferred().resolveWith( this ).promise(); - } - - options = options || {}; - options.remove = false; - - return this._more = this.fetch( options ).done( function( response ) { - if ( _.isEmpty( response ) || -1 === query.args.posts_per_page || response.length < query.args.posts_per_page ) { - query._hasMore = false; - } - }); - }, - /** - * Overrides Backbone.Collection.sync - * Overrides wp.media.model.Attachments.sync - * - * @param {string} method - * @param {Backbone.Model} model - * @param {Object} [options={}] - * @return {Promise} - */ - sync: function( method, model, options ) { - var args, fallback; - - // Overload the read method so Attachment.fetch() functions correctly. - if ( 'read' === method ) { - options = options || {}; - options.context = this; - options.data = _.extend( options.data || {}, { - action: 'query-attachments', - post_id: wp.media.model.settings.post.id - }); - - // Clone the args so manipulation is non-destructive. - args = _.clone( this.args ); - - // Determine which page to query. - if ( -1 !== args.posts_per_page ) { - args.paged = Math.round( this.length / args.posts_per_page ) + 1; - } - - options.data.query = args; - return wp.media.ajax( options ); - - // Otherwise, fall back to `Backbone.sync()`. - } else { - /** - * Call wp.media.model.Attachments.sync or Backbone.sync - */ - fallback = Attachments.prototype.sync ? Attachments.prototype : Backbone; - return fallback.sync.apply( this, arguments ); - } - } -}, /** @lends wp.media.model.Query */{ - /** - * @readonly - */ - defaultProps: { - orderby: 'date', - order: 'DESC' - }, - /** - * @readonly - */ - defaultArgs: { - posts_per_page: 80 - }, - /** - * @readonly - */ - orderby: { - allowed: [ 'name', 'author', 'date', 'title', 'modified', 'uploadedTo', 'id', 'post__in', 'menuOrder' ], - /** - * A map of JavaScript orderby values to their WP_Query equivalents. - * @type {Object} - */ - valuemap: { - 'id': 'ID', - 'uploadedTo': 'parent', - 'menuOrder': 'menu_order ID' - } - }, - /** - * A map of JavaScript query properties to their WP_Query equivalents. - * - * @readonly - */ - propmap: { - 'search': 's', - 'type': 'post_mime_type', - 'perPage': 'posts_per_page', - 'menuOrder': 'menu_order', - 'uploadedTo': 'post_parent', - 'status': 'post_status', - 'include': 'post__in', - 'exclude': 'post__not_in', - 'author': 'author' - }, - /** - * Creates and returns an Attachments Query collection given the properties. - * - * Caches query objects and reuses where possible. - * - * @static - * @method - * - * @param {object} [props] - * @param {Object} [props.order] - * @param {Object} [props.orderby] - * @param {Object} [props.include] - * @param {Object} [props.exclude] - * @param {Object} [props.s] - * @param {Object} [props.post_mime_type] - * @param {Object} [props.posts_per_page] - * @param {Object} [props.menu_order] - * @param {Object} [props.post_parent] - * @param {Object} [props.post_status] - * @param {Object} [props.author] - * @param {Object} [options] - * - * @return {wp.media.model.Query} A new Attachments Query collection. - */ - get: (function(){ - /** - * @static - * @type Array - */ - var queries = []; - - /** - * @return {Query} - */ - return function( props, options ) { - var args = {}, - orderby = Query.orderby, - defaults = Query.defaultProps, - query; - - // Remove the `query` property. This isn't linked to a query, - // this *is* the query. - delete props.query; - - // Fill default args. - _.defaults( props, defaults ); - - // Normalize the order. - props.order = props.order.toUpperCase(); - if ( 'DESC' !== props.order && 'ASC' !== props.order ) { - props.order = defaults.order.toUpperCase(); - } - - // Ensure we have a valid orderby value. - if ( ! _.contains( orderby.allowed, props.orderby ) ) { - props.orderby = defaults.orderby; - } - - _.each( [ 'include', 'exclude' ], function( prop ) { - if ( props[ prop ] && ! _.isArray( props[ prop ] ) ) { - props[ prop ] = [ props[ prop ] ]; - } - } ); - - // Generate the query `args` object. - // Correct any differing property names. - _.each( props, function( value, prop ) { - if ( _.isNull( value ) ) { - return; - } - - args[ Query.propmap[ prop ] || prop ] = value; - }); - - // Fill any other default query args. - _.defaults( args, Query.defaultArgs ); - - // `props.orderby` does not always map directly to `args.orderby`. - // Substitute exceptions specified in orderby.keymap. - args.orderby = orderby.valuemap[ props.orderby ] || props.orderby; - - queries = []; - - // Otherwise, create a new query and add it to the cache. - if ( ! query ) { - query = new Query( [], _.extend( options || {}, { - props: props, - args: args - } ) ); - queries.push( query ); - } - - return query; - }; - }()) -}); - -module.exports = Query; - - -/***/ }), - -/***/ 4134: -/***/ ((module) => { - -var Attachments = wp.media.model.Attachments, - Selection; - -/** - * wp.media.model.Selection - * - * A selection of attachments. - * - * @memberOf wp.media.model - * - * @class - * @augments wp.media.model.Attachments - * @augments Backbone.Collection - */ -Selection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{ - /** - * Refresh the `single` model whenever the selection changes. - * Binds `single` instead of using the context argument to ensure - * it receives no parameters. - * - * @param {Array} [models=[]] Array of models used to populate the collection. - * @param {Object} [options={}] - */ - initialize: function( models, options ) { - /** - * call 'initialize' directly on the parent class - */ - Attachments.prototype.initialize.apply( this, arguments ); - this.multiple = options && options.multiple; - - this.on( 'add remove reset', _.bind( this.single, this, false ) ); - }, - - /** - * If the workflow does not support multi-select, clear out the selection - * before adding a new attachment to it. - * - * @param {Array} models - * @param {Object} options - * @return {wp.media.model.Attachment[]} - */ - add: function( models, options ) { - if ( ! this.multiple ) { - this.remove( this.models ); - } - /** - * call 'add' directly on the parent class - */ - return Attachments.prototype.add.call( this, models, options ); - }, - - /** - * Fired when toggling (clicking on) an attachment in the modal. - * - * @param {undefined|boolean|wp.media.model.Attachment} model - * - * @fires wp.media.model.Selection#selection:single - * @fires wp.media.model.Selection#selection:unsingle - * - * @return {Backbone.Model} - */ - single: function( model ) { - var previous = this._single; - - // If a `model` is provided, use it as the single model. - if ( model ) { - this._single = model; - } - // If the single model isn't in the selection, remove it. - if ( this._single && ! this.get( this._single.cid ) ) { - delete this._single; - } - - this._single = this._single || this.last(); - - // If single has changed, fire an event. - if ( this._single !== previous ) { - if ( previous ) { - previous.trigger( 'selection:unsingle', previous, this ); - - // If the model was already removed, trigger the collection - // event manually. - if ( ! this.get( previous.cid ) ) { - this.trigger( 'selection:unsingle', previous, this ); - } - } - if ( this._single ) { - this._single.trigger( 'selection:single', this._single, this ); - } - } - - // Return the single model, or the last model as a fallback. - return this._single; - } -}); - -module.exports = Selection; - - /***/ }) /******/ }); @@ -1388,9 +1388,6 @@ /******/ } /******/ /************************************************************************/ -var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { /** * @output wp-includes/js/media-models.js */ @@ -1630,7 +1627,5 @@ }); }; -})(); - /******/ })() ; \ No newline at end of file