[wp-trac] [WordPress Trac] #64467: Grid view displays attachments in the wrong order when an order query var is present but not normalized (was: Media Library Grid view displays attachments in the wrong order when an order query var is present but not normalized (e.g. `order=desc` or `order=pizza`). Not a `WP_Query` / database issue: the server returns correctly ordered results; the UI reverses them client‑side in JavaScript.)

WordPress Trac noreply at wordpress.org
Thu Jan 1 16:30:34 UTC 2026


#64467: Grid view displays attachments in the wrong order when an order query var
is present but not normalized
-----------------------------+-----------------------------------------
 Reporter:  trivedikavit     |       Owner:  (none)
     Type:  defect (bug)     |      Status:  new
 Priority:  normal           |   Milestone:  Awaiting Review
Component:  Media            |     Version:
 Severity:  minor            |  Resolution:
 Keywords:  has-screenshots  |     Focuses:  javascript, administration
-----------------------------+-----------------------------------------
Changes (by sabernhardt):

 * keywords:  has-patch needs-testing has-test-info has-screenshots
     javascript => has-screenshots
 * focuses:  javascript => javascript, administration


Old description:

> = Are you using either the latest version of WordPress, or the latest
> development version? =
>
> Yes. Reproduced on:
>
> * A clean ''local'' WordPress install running WordPress '''6.9'''
> * Multiple production sites, showing the same behavior. The local
> reproduction confirms this is core behavior and not environment-specific.
>
> === Direct URL reproduction (most deterministic) ===
>
> Visit: `/wp-admin/upload.php?mode=grid&orderby=date&order=desc`
>
> Observe the ordering displayed in the grid.
> Control cases:
>
> * Works as expected:
>  * `/wp-admin/upload.php?mode=grid&orderby=date&order=DESC`
>  * `/wp-admin/upload.php?mode=grid&orderby=date`
> * Also triggers incorrect ordering:
>  * `/wp-admin/upload.php?mode=grid&orderby=date&order=pizza`
>
> === Screenshots ===
>
> ** Incorrect Order: `order=desc` **
> [[Image(https://iili.io/fhBAuFs.png)]]
>
> ** Correct Order: `order=DESC` **
> [[Image(https://iili.io/fhBAAcG.png)]]
>
> === Common User Path (List Mode with Filters => Grid Mode) ===
>
> * Visit List mode with sorting: `/wp-
> admin/upload.php?mode=list&orderby=date&order=desc`
> * Click the ''Grid view'' toggle (the generated link preserves
> orderby/order).
> * Grid view renders the first batch of attachments in the wrong order.
>

> = Does the problem occur even when you deactivate all plugins and use the
> default theme? =
>
> Yes. Reproduced on a clean local install with:
>
> * Default theme (twentytwentyfive)
> * No plugins
>
> = What steps should be taken to consistently reproduce the problem? =
> ''Precondition:'' Media Library contains a few images where this sorting
> issue would be apparent.
>

> = What is the expected output or result? What did you see instead? =
>
> === Expected ===
>
> For: `mode=grid&orderby=date&order=desc` The grid should display
> attachments newest-first (DESC), consistent with server-side behavior and
> the AJAX response.
>
> === Actual ===
>
> With `order=desc` (lowercase) or invalid values such as `order=pizza`:
>
> The server-side query and the AJAX response contain attachments in the
> correct order (DESC by date).
>
> The Grid UI renders them reversed (appears ASC / oldest-first).
>
> This demonstrates the defect is ''not'' in `WP_Query` and not in SQL
> ordering; it is a ''client-side UI sorting issue'' in the Media Library
> grid JavaScript.
>

> = Please provide any additional information that you think we'd find
> useful. =
>
> * Tested primarily in Chrome on macOS (but this is browser-independent)
> * Grid view uses AJAX via `wp_ajax_query_attachments()` (admin-ajax).
> When reproducing, the network response data array arrives in the correct
> (DESC) order even when the URL contains lowercase/invalid order values.
> * Root cause appears to be a normalization mismatch: ** PHP / `WP_Query`
> normalizes order to uppercase (ASC/DESC) and defaults invalid values to
> DESC. ** Media grid JS uses a case-sensitive 'DESC' `===` order check;
> lowercase/invalid values fall through to the ascending branch and reverse
> the display order.
> * Relevant core code (6.9):
>  * `wp.media.model.Query.prototype.filters.order`:
>   * https://github.com/WordPress/WordPress/blob/6.9/wp-includes/js/media-
> models.js#L34-L76
>  * `wp.media.model.Attachments.comparator`:
>   * https://github.com/WordPress/WordPress/blob/6.9/wp-includes/js/media-
> models.js#L1092-L1112
>

> = Patch =
>
> Here's the patch:
> {{{
> --- a/wp-includes/js/media-models.js
> +++ b/wp-includes/js/media-models.js
> @@ -43,7 +43,7 @@ Query = Attachments.extend(/** @lends
> wp.media.model.Query.prototype */{
>
>                this.filters.order = function( attachment ) {
>                        var orderby = this.props.get('orderby'),
> -                              order = this.props.get('order');
> +                              order = ( this.props.get('order') ||
> 'DESC' ).toUpperCase();
>
>                        if ( ! this.comparator ) {
>                                return true;
> @@ -1091,7 +1091,7 @@ var Attachments = Backbone.Collection.extend(/**
> @lends wp.media.model.Attachmen
>         */
>        comparator: function( a, b, options ) {
>                var key   = this.props.get('orderby'),
> -                      order = this.props.get('order') || 'DESC',
> +                      order = ( this.props.get('order') || 'DESC'
> ).toUpperCase(),
>                        ac    = a.cid,
>                        bc    = b.cid;
>
> @@ -1108,7 +1108,7 @@ var Attachments = Backbone.Collection.extend(/**
> @lends wp.media.model.Attachmen
>                        ac = bc = null;
>                }
>
> -              return ( 'DESC' === order ) ? wp.media.compare( a, b, ac,
> bc ) : wp.media.compare( b, a, bc, ac );
> +              return ( 'ASC' === order ) ? wp.media.compare( b, a, bc,
> ac ) : wp.media.compare( a, b, ac, bc );
>        },
>        /** @namespace wp.media.model.Attachments.filters */
>        filters: {
> }}}
>
> == What the patch changes ==
> The patch makes two small but important changes in wp-includes/js/media-
> models.js:
>
> === 1) Normalize order to uppercase in the media models ===
> It changes:
> {{{
> order = this.props.get('order');
> }}}
> and
> {{{
> order = this.props.get('order') || 'DESC';
> }}}
> to:
> {{{
> order = ( this.props.get('order') || 'DESC' ).toUpperCase();
> }}}
>
> So:
>
> 'desc' becomes 'DESC'
> 'asc' becomes 'ASC'
> undefined becomes 'DESC'
> 'pizza' becomes 'PIZZA' (still invalid, but now handled consistently)
> This ensures the subsequent comparisons behave deterministically.
>
> === 2) Change the comparator to treat only explicit ASC as ascending
> (default everything else to DESC) ===
> It changes the comparator decision from:
> {{{
> return ( 'DESC' === order ) ? DESC_logic : ASC_logic;
> }}}
> to:
> {{{
> return ( 'ASC' === order ) ? ASC_logic : DESC_logic;
> }}}
>
> Effect:
>
> If order is exactly 'ASC', the Grid sorts ascending.
> For 'DESC' (and for any unexpected/invalid value), the Grid sorts
> descending.
> That default-to-DESC behavior matches how WP_Query behaves when order is
> missing or invalid, which prevents the UI from "flipping" the already-
> correct server ordering.
>
> == Testing Instructions ==
>
> Since this patch modifies the unminified JavaScript file `wp-includes/js
> /media-models.js`, to test it properly:
>
> 1. Set `define( 'SCRIPT_DEBUG', true );` in your `wp-config.php` to
> ensure WordPress loads unminified JavaScript files instead of the
> minified versions (otherwise you need to rebuild or patch the minified
> file too.)
> 2. Apply the patch to `wp-includes/js/media-models.js`.
> 3. Clear your browser cache or use an incognito/private browsing window
> to avoid cached scripts.
> 4. Follow the reproduction steps above to verify the fix:
>    * Visit `/wp-admin/upload.php?mode=grid&orderby=date&order=desc` and
> confirm attachments display newest-first.
>    * Test control cases: `order=DESC`, `order=asc`, and invalid values
> like `order=pizza` should all behave correctly (defaulting to DESC where
> appropriate).
>
> == Net Result ==
>
> * Grid view displays attachments in the same order as the AJAX response.
> * `order=desc` and `order=DESC` behave identically.
> * Invalid order values no longer cause the Grid UI to reverse the display
> order; they fall back to descending behavior instead.

New description:

 Media Library Grid view displays attachments in the wrong order when an
 order query var is present but not normalized (e.g. `order=desc` or
 `order=pizza`). Not a `WP_Query` / database issue: the server returns
 correctly ordered results; the UI reverses them client‑side in JavaScript.

 ==== Are you using either the latest version of WordPress, or the latest
 development version? ====

 Yes. Reproduced on:

 * A clean ''local'' WordPress install running WordPress '''6.9'''
 * Multiple production sites, showing the same behavior. The local
 reproduction confirms this is core behavior and not environment-specific.

 ===== Direct URL reproduction (most deterministic) =====

 Visit: `/wp-admin/upload.php?mode=grid&orderby=date&order=desc`

 Observe the ordering displayed in the grid.
 Control cases:

 * Works as expected:
  * `/wp-admin/upload.php?mode=grid&orderby=date&order=DESC`
  * `/wp-admin/upload.php?mode=grid&orderby=date`
 * Also triggers incorrect ordering:
  * `/wp-admin/upload.php?mode=grid&orderby=date&order=pizza`

 ==== Screenshots ====

 ** Incorrect Order: `order=desc` **
 [[Image(https://core.trac.wordpress.org/raw-attachment/ticket/64467
 /incorrect-order.png, alt="Incorrect Order in Grid View with order=desc
 (lowercase)", title="")]]

 ** Correct Order: `order=DESC` **
 [[Image(https://core.trac.wordpress.org/raw-attachment/ticket/64467
 /correct-order.png, alt="Correct Order in Grid View with order=DESC
 (uppercase)", title="")]]

 ==== Common User Path (List Mode with Filters => Grid Mode) ====

 * Visit List mode with sorting: `/wp-
 admin/upload.php?mode=list&orderby=date&order=desc`
 * Click the ''Grid view'' toggle (the generated link preserves
 orderby/order).
 * Grid view renders the first batch of attachments in the wrong order.


 ==== Does the problem occur even when you deactivate all plugins and use
 the default theme? ====

 Yes. Reproduced on a clean local install with:

 * Default theme (twentytwentyfive)
 * No plugins

 ==== What steps should be taken to consistently reproduce the problem?
 ====
 ''Precondition:'' Media Library contains a few images where this sorting
 issue would be apparent.


 ==== What is the expected output or result? What did you see instead? ====

 ===== Expected =====

 For: `mode=grid&orderby=date&order=desc` The grid should display
 attachments newest-first (DESC), consistent with server-side behavior and
 the AJAX response.

 ===== Actual =====

 With `order=desc` (lowercase) or invalid values such as `order=pizza`:

 The server-side query and the AJAX response contain attachments in the
 correct order (DESC by date).

 The Grid UI renders them reversed (appears ASC / oldest-first).

 This demonstrates the defect is ''not'' in `WP_Query` and not in SQL
 ordering; it is a ''client-side UI sorting issue'' in the Media Library
 grid JavaScript.


 ==== Please provide any additional information that you think we'd find
 useful. ====

 * Tested primarily in Chrome on macOS (but this is browser-independent)
 * Grid view uses AJAX via `wp_ajax_query_attachments()` (admin-ajax). When
 reproducing, the network response data array arrives in the correct (DESC)
 order even when the URL contains lowercase/invalid order values.
 * Root cause appears to be a normalization mismatch: ** PHP / `WP_Query`
 normalizes order to uppercase (ASC/DESC) and defaults invalid values to
 DESC. ** Media grid JS uses a case-sensitive 'DESC' `===` order check;
 lowercase/invalid values fall through to the ascending branch and reverse
 the display order.
 * Relevant core code (6.9):
  * `wp.media.model.Query.prototype.filters.order`: \\
 https://github.com/WordPress/WordPress/blob/6.9/wp-includes/js/media-
 models.js#L34-L76
  * `wp.media.model.Attachments.comparator`: \\
 https://github.com/WordPress/WordPress/blob/6.9/wp-includes/js/media-
 models.js#L1092-L1112


 === Patch ===

 Here's the patch:
 {{{
 --- a/wp-includes/js/media-models.js
 +++ b/wp-includes/js/media-models.js
 @@ -43,7 +43,7 @@ Query = Attachments.extend(/** @lends
 wp.media.model.Query.prototype */{

                this.filters.order = function( attachment ) {
                        var orderby = this.props.get('orderby'),
 -                              order = this.props.get('order');
 +                              order = ( this.props.get('order') || 'DESC'
 ).toUpperCase();

                        if ( ! this.comparator ) {
                                return true;
 @@ -1091,7 +1091,7 @@ var Attachments = Backbone.Collection.extend(/**
 @lends wp.media.model.Attachmen
         */
        comparator: function( a, b, options ) {
                var key   = this.props.get('orderby'),
 -                      order = this.props.get('order') || 'DESC',
 +                      order = ( this.props.get('order') || 'DESC'
 ).toUpperCase(),
                        ac    = a.cid,
                        bc    = b.cid;

 @@ -1108,7 +1108,7 @@ var Attachments = Backbone.Collection.extend(/**
 @lends wp.media.model.Attachmen
                        ac = bc = null;
                }

 -              return ( 'DESC' === order ) ? wp.media.compare( a, b, ac,
 bc ) : wp.media.compare( b, a, bc, ac );
 +              return ( 'ASC' === order ) ? wp.media.compare( b, a, bc, ac
 ) : wp.media.compare( a, b, ac, bc );
        },
        /** @namespace wp.media.model.Attachments.filters */
        filters: {
 }}}

 ==== What the patch changes ====
 The patch makes two small but important changes in `wp-includes/js/media-
 models.js`:

 ===== 1) Normalize order to uppercase in the media models =====
 It changes:
 {{{
 order = this.props.get('order');
 }}}
 and
 {{{
 order = this.props.get('order') || 'DESC';
 }}}
 to:
 {{{
 order = ( this.props.get('order') || 'DESC' ).toUpperCase();
 }}}

 So:

 - 'desc' becomes 'DESC'
 - 'asc' becomes 'ASC'
 - undefined becomes 'DESC'
 - 'pizza' becomes 'PIZZA' (still invalid, but now handled consistently)
 - This ensures the subsequent comparisons behave deterministically.

 ===== 2) Change the comparator to treat only explicit ASC as ascending
 (default everything else to DESC) =====
 It changes the comparator decision from:
 {{{
 return ( 'DESC' === order ) ? DESC_logic : ASC_logic;
 }}}
 to:
 {{{
 return ( 'ASC' === order ) ? ASC_logic : DESC_logic;
 }}}

 Effect:

 - If order is exactly 'ASC', the Grid sorts ascending.
 - For 'DESC' (and for any unexpected/invalid value), the Grid sorts
 descending.
 - That default-to-DESC behavior matches how `WP_Query` behaves when order
 is missing or invalid, which prevents the UI from "flipping" the already-
 correct server ordering.

 ==== Testing Instructions ====

 Since this patch modifies the unminified JavaScript file `wp-includes/js
 /media-models.js`, to test it properly:

 1. Set `define( 'SCRIPT_DEBUG', true );` in your `wp-config.php` to ensure
 WordPress loads unminified JavaScript files instead of the minified
 versions (otherwise you need to rebuild or patch the minified file too.)
 2. Apply the patch to `wp-includes/js/media-models.js`.
 3. Clear your browser cache or use an incognito/private browsing window to
 avoid cached scripts.
 4. Follow the reproduction steps above to verify the fix:
    * Visit `/wp-admin/upload.php?mode=grid&orderby=date&order=desc` and
 confirm attachments display newest-first.
    * Test control cases: `order=DESC`, `order=asc`, and invalid values
 like `order=pizza` should all behave correctly (defaulting to DESC where
 appropriate).

 ==== Net Result ====

 * Grid view displays attachments in the same order as the AJAX response.
 * `order=desc` and `order=DESC` behave identically.
 * Invalid order values no longer cause the Grid UI to reverse the display
 order; they fall back to descending behavior instead.

--

Comment:

 Hi and welcome to WordPress Core Trac!

 In trunk, the script involves both
 [https://core.trac.wordpress.org/browser/trunk/src/js/media/models/query.js?rev=51632&marks=40#L40
 query.js] and
 [https://core.trac.wordpress.org/browser/trunk/src/js/media/models/attachments.js?rev=51191&marks=497,514#L497
 attachments.js].

 There is also a
 [https://core.trac.wordpress.org/browser/trunk/src/js/media/models/query.js?rev=51632&marks=40#L40
 'menuOrder' option] that relies on `ASC` uppercase.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/64467#comment:1>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list