Make WordPress Core

Changeset 57580


Ignore:
Timestamp:
02/09/2024 07:48:41 PM (3 years ago)
Author:
joedolson
Message:

Quick/Bulk Edit: Pre-fill category fields with their status.

Pre-fill category fields in the Quick/Bulk Edit form with their current status.

When bulk editing, if only some of the selected items are in a given category, the category's checkbox will display a line to indicate an indeterminate status.

Originally committed in [56172], but reverted due to a bug that removed all categories. Updated commit fixes the bug, adds unit tests, and improves the accessibility of the indeterminate state checkboxes.

Props pavelevap, scribu, chasedsiedu, helen, joshcanhelp, ubernaut, Cyberchicken, laumindproductscomau, SergeyBiryukov, Marcoevich, tomybyte, thinkluke, virtality-marketing-solutions, Michalooki, dmsnell, itecrs, pannelars, WHSajid, samba45, Mte90, johnbillion, tomluckies, soulseekah, francina, oglekler, ajmcfadyen, mukesh27, costdev, hellofromTonya, peterwilsoncc, joedolson, pbiron, oglekler, webcommsat, jorbin, ajmcfadyen, huzaifaalmesbah.
Fixes #11302.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/js/_enqueues/admin/inline-edit-post.js

    r57093 r57580  
    179179        setBulk : function(){
    180180                var te = '', type = this.type, c = true;
     181                var checkedPosts = $( 'tbody th.check-column input[type="checkbox"]:checked' );
     182                var categories = {};
    181183                this.revert();
    182184
     
    217219                // Populate the list of items to bulk edit.
    218220                $( '#bulk-titles' ).html( '<ul id="bulk-titles-list" role="list">' + te + '</ul>' );
     221
     222                // Gather up some statistics on which of these checked posts are in which categories.
     223                checkedPosts.each( function() {
     224                        var id      = $( this ).val();
     225                        var checked = $( '#category_' + id ).text().split( ',' );
     226
     227                        checked.map( function( cid ) {
     228                                categories[ cid ] || ( categories[ cid ] = 0 );
     229                                // Just record that this category is checked.
     230                                categories[ cid ]++;
     231                        } );
     232                } );
     233
     234                // Compute initial states.
     235                $( '.inline-edit-categories input[name="post_category[]"]' ).each( function() {
     236                        if ( categories[ $( this ).val() ] == checkedPosts.length ) {
     237                                // If the number of checked categories matches the number of selected posts, then all posts are in this category.
     238                                $( this ).prop( 'checked', true );
     239                        } else if ( categories[ $( this ).val() ] > 0 ) {
     240                                // If the number is less than the number of selected posts, then it's indeterminate.
     241                                $( this ).prop( 'indeterminate', true );
     242                                if ( ! $( this ).parent().find( 'input[name="indeterminate_post_category[]"]' ).length ) {
     243                                        // Get the term label text.
     244                                        var label = $( this ).parent().text();
     245                                        // Set indeterminate states for the backend. Add accessible text for indeterminate inputs.
     246                                        $( this ).after( '<input type="hidden" name="indeterminate_post_category[]" value="' + $( this ).val() + '">' ).attr( 'aria-label', label.trim() + ': ' + wp.i18n.__( 'Some selected posts have this category' ) );
     247                                }
     248                        }
     249                } );
     250
     251                $( '.inline-edit-categories input[name="post_category[]"]:indeterminate' ).on( 'change', function() {
     252                        // Remove accessible label text. Remove the indeterminate flags as there was a specific state change.
     253                        $( this ).removeAttr( 'aria-label' ).parent().find( 'input[name="indeterminate_post_category[]"]' ).remove();
     254                } );
     255
     256                $( '.inline-edit-save button' ).on( 'click', function() {
     257                        $( '.inline-edit-categories input[name="post_category[]"]' ).prop( 'indeterminate', false );
     258                } );
    219259
    220260                /**
  • trunk/src/wp-admin/css/list-tables.css

    r57553 r57580  
    11501150}
    11511151
     1152ul.cat-checklist input[name="post_category[]"]:indeterminate::before {
     1153        content: '';
     1154        border-top: 2px solid grey;
     1155        width: 65%;
     1156        height: 2px;
     1157        position: absolute;
     1158        top: calc( 50% + 1px );
     1159        left: 50%;
     1160        transform: translate( -50%, -50% );
     1161}
     1162
    11521163#bulk-titles .ntdelbutton,
    11531164#bulk-titles .ntdeltitle,
  • trunk/src/wp-admin/includes/post.php

    r57521 r57580  
    650650
    651651                if ( isset( $new_cats ) && in_array( 'category', $tax_names, true ) ) {
    652                         $cats                       = (array) wp_get_post_categories( $post_id );
    653                         $post_data['post_category'] = array_unique( array_merge( $cats, $new_cats ) );
     652                        $cats = (array) wp_get_post_categories( $post_id );
     653
     654                        if (
     655                                isset( $post_data['indeterminate_post_category'] )
     656                                && is_array( $post_data['indeterminate_post_category'] )
     657                        ) {
     658                                $indeterminate_post_category = $post_data['indeterminate_post_category'];
     659                        } else {
     660                                $indeterminate_post_category = array();
     661                        }
     662
     663                        $indeterminate_cats         = array_intersect( $cats, $indeterminate_post_category );
     664                        $determinate_cats           = array_diff( $new_cats, $indeterminate_post_category );
     665                        $post_data['post_category'] = array_unique( array_merge( $indeterminate_cats, $determinate_cats ) );
     666
    654667                        unset( $post_data['tax_input']['category'] );
    655668                }
  • trunk/tests/phpunit/tests/admin/includesPost.php

    r57068 r57580  
    383383                        $this->assertSame( 'aside', get_post_format( $post_id ) );
    384384                }
     385        }
     386
     387        /**
     388         * @ticket 11302
     389         */
     390        public function test_bulk_edit_if_categories_unchanged() {
     391                wp_set_current_user( self::$admin_id );
     392
     393                $post_ids = self::factory()->post->create_many( 3 );
     394
     395                wp_set_post_categories( $post_ids[0], array( 'test1', 'test2' ) );
     396                wp_set_post_categories( $post_ids[1], array( 'test2', 'test3' ) );
     397                wp_set_post_categories( $post_ids[2], array( 'test1', 'test3' ) );
     398
     399                $terms1 = wp_get_post_categories( $post_ids[0] );
     400                $terms2 = wp_get_post_categories( $post_ids[1] );
     401                $terms3 = wp_get_post_categories( $post_ids[2] );
     402
     403                $indeterminate_categories = array_merge( $terms1, $terms2, $terms3 );
     404
     405                $request = array(
     406                        '_status'                     => -1,
     407                        'post'                        => $post_ids,
     408                        'indeterminate_post_category' => $indeterminate_categories,
     409                );
     410
     411                bulk_edit_posts( $request );
     412
     413                $updated_terms1 = wp_get_post_categories( $post_ids[0] );
     414                $updated_terms2 = wp_get_post_categories( $post_ids[1] );
     415                $updated_terms3 = wp_get_post_categories( $post_ids[2] );
     416
     417                $this->assertSame( $terms1, $updated_terms1, 'Post 1 should have terms 1 and 2.' );
     418                $this->assertSame( $terms2, $updated_terms2, 'Post 2 should have terms 2 and 3.' );
     419                $this->assertSame( $terms3, $updated_terms3, 'Post 3 should have terms 1 and 3.' );
     420        }
     421
     422        /**
     423         * @ticket 11302
     424         */
     425        public function test_bulk_edit_if_some_categories_added() {
     426                wp_set_current_user( self::$admin_id );
     427
     428                $post_ids = self::factory()->post->create_many( 3 );
     429                $term1    = wp_create_category( 'test1' );
     430                $term2    = wp_create_category( 'test2' );
     431                $term3    = wp_create_category( 'test3' );
     432                $term4    = wp_create_category( 'test4' );
     433
     434                wp_set_post_categories( $post_ids[0], array( $term1, $term2 ) );
     435                wp_set_post_categories( $post_ids[1], array( $term2, $term3 ) );
     436                wp_set_post_categories( $post_ids[2], array( $term1, $term3 ) );
     437
     438                $terms1 = wp_get_post_categories( $post_ids[0], array( 'fields' => 'ids' ) );
     439                $terms2 = wp_get_post_categories( $post_ids[1], array( 'fields' => 'ids' ) );
     440                $terms3 = wp_get_post_categories( $post_ids[2], array( 'fields' => 'ids' ) );
     441                // All existing categories are indeterminate.
     442                $indeterminate = array_unique( array_merge( $terms1, $terms2, $terms3 ) );
     443                // Add new category.
     444                $categories[] = $term4;
     445
     446                $request = array(
     447                        '_status'                     => -1,
     448                        'post'                        => $post_ids,
     449                        'post_category'               => $categories,
     450                        'indeterminate_post_category' => $indeterminate,
     451                );
     452
     453                bulk_edit_posts( $request );
     454
     455                $updated_terms1 = wp_get_post_categories( $post_ids[0], array( 'fields' => 'ids' ) );
     456                $updated_terms2 = wp_get_post_categories( $post_ids[1], array( 'fields' => 'ids' ) );
     457                $updated_terms3 = wp_get_post_categories( $post_ids[2], array( 'fields' => 'ids' ) );
     458
     459                // Each post should have the same categories as before and add term 4.
     460                $this->assertSame( array( $term1, $term2, $term4 ), $updated_terms1, 'Post should have terms 1, 2, and 4.' );
     461                $this->assertSame( array( $term2, $term3, $term4 ), $updated_terms2, 'Post should have terms 2, 3, and 4.' );
     462                $this->assertSame( array( $term1, $term3, $term4 ), $updated_terms3, 'Post should have terms 1, 3, and 4.' );
     463        }
     464
     465        /**
     466         * @ticket 11302
     467         */
     468        public function test_bulk_edit_if_some_categories_removed() {
     469                wp_set_current_user( self::$admin_id );
     470
     471                $post_ids = self::factory()->post->create_many( 3 );
     472                $term1    = wp_create_category( 'test1' );
     473                $term2    = wp_create_category( 'test2' );
     474                $term3    = wp_create_category( 'test3' );
     475
     476                wp_set_post_categories( $post_ids[0], array( $term1, $term2 ) );
     477                wp_set_post_categories( $post_ids[1], array( $term2, $term3 ) );
     478                wp_set_post_categories( $post_ids[2], array( $term1, $term3 ) );
     479
     480                $terms1 = wp_get_post_categories( $post_ids[0], array( 'fields' => 'ids' ) );
     481                $terms2 = wp_get_post_categories( $post_ids[1], array( 'fields' => 'ids' ) );
     482                $terms3 = wp_get_post_categories( $post_ids[2], array( 'fields' => 'ids' ) );
     483
     484                // Terms 2 and 3 are in indeterminate state.
     485                $indeterminate = array( $term2, $term3 );
     486                // Remove term 1 from selected categories.
     487                $categories = array_unique( array_merge( $terms1, $terms2, $terms3 ) );
     488                $remove_key = array_search( $term1, $categories, true );
     489                unset( $categories[ $remove_key ] );
     490
     491                $request = array(
     492                        '_status'                     => -1,
     493                        'post'                        => $post_ids,
     494                        'post_category'               => $categories,
     495                        'indeterminate_post_category' => $indeterminate,
     496                );
     497
     498                bulk_edit_posts( $request );
     499
     500                $updated_terms1 = wp_get_post_categories( $post_ids[0], array( 'fields' => 'ids' ) );
     501                $updated_terms2 = wp_get_post_categories( $post_ids[1], array( 'fields' => 'ids' ) );
     502                $updated_terms3 = wp_get_post_categories( $post_ids[2], array( 'fields' => 'ids' ) );
     503
     504                // Post 1 should only have term 2.
     505                $this->assertSame( $updated_terms1, array( $term2 ), 'Post 1 should only have term 2.' );
     506                // Post 2 should be unchanged.
     507                $this->assertSame( $terms2, $updated_terms2, 'Post 2 should be unchanged.' );
     508                // Post 3 should only have term 3.
     509                $this->assertSame( $updated_terms3, array( $term3 ), 'Post 3 should only have term 3.' );
    385510        }
    386511
Note: See TracChangeset for help on using the changeset viewer.