Make WordPress Core

Changeset 60614


Ignore:
Timestamp:
08/07/2025 01:32:17 AM (3 months ago)
Author:
peterwilsoncc
Message:

Upgrade/Install: Reduce number of DB queries populating roles.

Reduces the number of database queries made when populating roles during install/multisite site creation by 344 (347 queries down to 3).

populate_roles() has been modified to prevent an individual database query each time a role or capability is added to the WP_Roles object. Instead the roles option, {$wpdb->prefix}user_roles is updated once at the end of the function call.

Introduces a test to ensure that updating the roles option via WP_Roles and updating the option in the manner now used by populate_roles() results in the same capabilities been applied to a role.

Props fliespl, johnjamesjacoby, ocean90, realloc, rishabhwp, sainathpoojary, sirlouen, spacedmonkey, swissspidy.
Fixes #37687.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/schema.php

    r60497 r60614  
    714714 */
    715715function populate_roles() {
     716    $wp_roles = wp_roles();
     717
     718    // Disable role updates to the database while populating roles.
     719    $original_use_db  = $wp_roles->use_db;
     720    $wp_roles->use_db = false;
     721
     722    // Populate roles
    716723    populate_roles_160();
    717724    populate_roles_210();
     
    722729    populate_roles_280();
    723730    populate_roles_300();
     731
     732    // Save the updated roles to the database.
     733    if ( $original_use_db ) {
     734        update_option( $wp_roles->role_key, $wp_roles->roles, true );
     735    }
     736
     737    // Restore original value for writing to database.
     738    $wp_roles->use_db = $original_use_db;
    724739}
    725740
  • trunk/tests/phpunit/tests/user/capabilities.php

    r60491 r60614  
    25432543        }
    25442544    }
     2545
     2546    /**
     2547     * Ensure that caps are updated correctly when using `update_option()` to save roles.
     2548     *
     2549     * Compares the efficiency and accuracy of updating role capabilities when `WP_Roles`
     2550     * uses the database vs when the updates are done via `update_option()`.
     2551     *
     2552     * This method of updating roles is used in `populate_roles()` to reduce the number of
     2553     * queries by approximately 300.
     2554     *
     2555     * @ticket 37687
     2556     */
     2557    public function test_role_capabilities_updated_correctly_via_update_option() {
     2558        global $wp_roles;
     2559        $emcee_role = 'emcee';
     2560        $wp_roles->add_role( $emcee_role, 'Emcee', array( 'level_1' => true ) );
     2561        $this->flush_roles();
     2562
     2563        $expected_caps = array(
     2564            'level_1'             => true,
     2565            'attend_kit_kat_klub' => true,
     2566            'win_tony_award'      => true,
     2567        );
     2568
     2569        $start_queries = get_num_queries();
     2570        $wp_roles->add_cap( $emcee_role, 'attend_kit_kat_klub' );
     2571        $wp_roles->add_cap( $emcee_role, 'win_tony_award' );
     2572        $emcee_queries = get_num_queries() - $start_queries;
     2573        $this->flush_roles();
     2574        $emcee_caps = $wp_roles->get_role( $emcee_role )->capabilities;
     2575
     2576        $wp_roles->use_db = false;
     2577        $sally_role       = 'sally';
     2578        $wp_roles->add_role( $sally_role, 'Sally Bowles', array( 'level_1' => true ) );
     2579        $start_queries = get_num_queries();
     2580        $wp_roles->add_cap( $sally_role, 'attend_kit_kat_klub' );
     2581        $wp_roles->add_cap( $sally_role, 'win_tony_award' );
     2582
     2583        update_option( $wp_roles->role_key, $wp_roles->roles, true );
     2584        $sally_queries    = get_num_queries() - $start_queries;
     2585        $wp_roles->use_db = true;
     2586
     2587        // Restore the default value.
     2588        $this->flush_roles();
     2589        $sally_caps = $wp_roles->get_role( $sally_role )->capabilities;
     2590
     2591        $this->assertSameSetsWithIndex( $expected_caps, $emcee_caps, 'Emcee role should include the three expected capabilities.' );
     2592        $this->assertSameSetsWithIndex( $expected_caps, $sally_caps, 'Sally role should include the three expected capabilities.' );
     2593        $this->assertSameSetsWithIndex( $emcee_caps, $sally_caps, 'Emcee and Sally roles should have the same capabilities after update.' );
     2594        $this->assertLessThan( $emcee_queries, $sally_queries, 'Updating roles via update_option should be more efficient than WP_Roles using the database.' );
     2595    }
    25452596}
Note: See TracChangeset for help on using the changeset viewer.