Make WordPress Core


Ignore:
Timestamp:
10/08/2025 07:59:28 PM (3 months ago)
Author:
spacedmonkey
Message:

Users: Lazy load user capabilities in WP_User object.

Convert the WP_User object properties caps, roles, and allcaps to protected, and introduce lazy loading for capabilities. These properties are now populated only when first accessed.

The existing magic methods (get, set, and unset) have been updated to maintain backward compatibility, ensuring that reading or modifying these formerly public properties continues to work as expected.

Ensure that these properties are initialised when calling remove_all_caps(), remove_cap(), has_cap(), add_role(), and set_role() methods.

Props spacedmonkey, flixos90, peterwilsoncc, mukesh27, westonruter, swissspidy, prettyboymp.
Fixes #58001.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/user/capabilities.php

    r60614 r60915  
    994994
    995995    /**
     996     * Test adding capabilities, roles, and allcaps manually to a user.
     997     *
     998     * @ticket 58001
     999     *
     1000     * @dataProvider data_add_user_properties_manually
     1001     *
     1002     * @param string $property_name  The property name to set.
     1003     * @param array  $property_value The property value to set.
     1004     * @param bool   $check_null     Whether to check that the property is null after unsetting it.
     1005     */
     1006    public function test_add_user_properties_manually( $property_name, $property_value, $check_null ) {
     1007        $id                     = self::factory()->user->create();
     1008        $user                   = new WP_User( $id );
     1009        $user->{$property_name} = $property_value;
     1010
     1011        $this->assertSameSets( $property_value, $user->{$property_name}, "User property {$property_name} was not set correctly." );
     1012        unset( $user->{$property_name} );
     1013        if ( $check_null ) {
     1014            $this->assertNull( $user->{$property_name}, "User property {$property_name} should be null after unsetting it." );
     1015        }
     1016    }
     1017
     1018    /**
     1019     * Data provider for test_add_user_properties_manually.
     1020     *
     1021     * @return array<string, array{0:string,1:array}>
     1022     */
     1023    public function data_add_user_properties_manually() {
     1024        return array(
     1025            'caps'    => array( 'caps', array( 'foo' => true ), false ),
     1026            'roles'   => array( 'roles', array( 'foo' => true ), true ),
     1027            'allcaps' => array( 'allcaps', array( 'foo' => true ), true ),
     1028        );
     1029    }
     1030
     1031    /**
    9961032     * Test add_role with implied capabilities grant successfully grants capabilities.
    9971033     *
     
    10991135        $this->flush_roles();
    11001136        $this->assertFalse( $wp_roles->is_role( $role_name ) );
     1137    }
     1138
     1139    /**
     1140     * @ticket 58001
     1141     */
     1142    public function test_get_role_caps() {
     1143        $id_1   = self::$users['contributor']->ID;
     1144        $user_1 = new WP_User( $id_1 );
     1145
     1146        $role_caps = $user_1->get_role_caps();
     1147        $this->assertIsArray( $role_caps, 'User role capabilities should be an array' );
     1148        $this->assertArrayHasKey( 'edit_posts', $role_caps, 'User role capabilities should contain the edit_posts capability' );
     1149    }
     1150
     1151    /**
     1152     * @ticket 58001
     1153     */
     1154    public function test_user_lazy_capabilities() {
     1155        $id_1   = self::$users['contributor']->ID;
     1156        $user_1 = new WP_User( $id_1 );
     1157
     1158        $this->assertTrue( isset( $user_1->roles ), 'User roles should be set' );
     1159        $this->assertTrue( isset( $user_1->allcaps ), 'User all capabilities should be set' );
     1160        $this->assertTrue( isset( $user_1->caps ), 'User capabilities should be set' );
     1161        $this->assertIsArray( $user_1->roles, 'User roles should be an array' );
     1162        $this->assertSame( array( 'contributor' ), $user_1->roles, 'User roles should match' );
     1163        $this->assertIsArray( $user_1->allcaps, 'User allcaps should be an array' );
     1164        $this->assertIsArray( $user_1->caps, 'User caps should be an array' );
     1165
     1166        $caps = $this->getAllCapsAndRoles();
     1167        foreach ( $caps as $cap => $roles ) {
     1168            if ( in_array( 'contributor', $roles, true ) ) {
     1169                $this->assertTrue( $user_1->has_cap( $cap ), "User should have the {$cap} capability" );
     1170            }
     1171        }
    11011172    }
    11021173
Note: See TracChangeset for help on using the changeset viewer.