Make WordPress Core

Changeset 61037


Ignore:
Timestamp:
10/21/2025 03:23:43 PM (10 months ago)
Author:
jorbin
Message:

Users: Revert Lazy load user capabilities in WP_User object.

The change from public to protected broke tests for extenders and this also broke WP_User::to_array().

Reverts [60915].

Props davidbaumwald, ellatrix, timothyblynjacobs, welcher, spacedmonkey, bradshawtm, peterwilsoncc, jorbin.
See #58001.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-user.php

    r60915 r61037  
    3838 * @property string $syntax_highlighting
    3939 * @property string $use_ssl
    40  * @property array<string, bool> $caps
    41  * @property string[] $roles
    42  * @property array<string, bool> $allcaps
    4340 */
    4441#[AllowDynamicProperties]
     
    6461         *
    6562         * @since 2.0.0
    66          * @var array<string, bool>|null Array of key/value pairs where keys represent a capability name
    67          *                               and boolean values represent whether the user has that capability.
    68          */
    69         protected $caps = null;
     63         * @var bool[] Array of key/value pairs where keys represent a capability name
     64         *             and boolean values represent whether the user has that capability.
     65         */
     66        public $caps = array();
    7067
    7168        /**
     
    8380         * @var string[]
    8481         */
    85         protected $roles = array();
     82        public $roles = array();
    8683
    8784        /**
     
    8986         *
    9087         * @since 2.0.0
    91          * @var array<string, bool> Array of key/value pairs where keys represent a capability name
    92          *                          and boolean values represent whether the user has that capability.
    93          */
    94         protected $allcaps = array();
     88         * @var bool[] Array of key/value pairs where keys represent a capability name
     89         *             and boolean values represent whether the user has that capability.
     90         */
     91        public $allcaps = array();
    9592
    9693        /**
     
    292289                }
    293290
    294                 if ( in_array( $key, array( 'caps', 'allcaps', 'roles' ), true ) ) {
    295                         return true;
    296                 }
    297 
    298291                if ( isset( $this->data->$key ) ) {
    299292                        return true;
     
    327320                        );
    328321                        return $this->ID;
    329                 }
    330 
    331                 if ( in_array( $key, array( 'caps', 'allcaps', 'roles' ), true ) ) {
    332                         $this->load_capability_data();
    333                         return $this->$key;
    334322                }
    335323
     
    376364                }
    377365
    378                 // Ensure capability data is loaded before setting related properties.
    379                 if ( in_array( $key, array( 'caps', 'allcaps', 'roles' ), true ) ) {
    380                         $this->load_capability_data();
    381                         $this->$key = $value;
    382                         return;
    383                 }
    384 
    385366                $this->data->$key = $value;
    386367        }
     
    406387                }
    407388
    408                 if ( in_array( $key, array( 'caps', 'allcaps', 'roles' ), true ) ) {
    409                         $this->$key = null;
    410                 }
    411 
    412389                if ( isset( $this->data->$key ) ) {
    413390                        unset( $this->data->$key );
     
    538515
    539516                $wp_roles = wp_roles();
    540 
    541                 // Edge case: In case someone calls this method before lazy initialization, we need to initialize on demand.
    542                 if ( ! isset( $this->caps ) ) {
    543                         $this->caps = $this->get_caps_data();
    544                 }
    545517
    546518                // Filter out caps that are not role names and assign to $this->roles.
     
    577549                        return;
    578550                }
    579                 $this->load_capability_data();
    580551
    581552                if ( in_array( $role, $this->roles, true ) ) {
     
    607578         */
    608579        public function remove_role( $role ) {
    609                 $this->load_capability_data();
    610580                if ( ! in_array( $role, $this->roles, true ) ) {
    611581                        return;
     
    640610         */
    641611        public function set_role( $role ) {
    642                 $this->load_capability_data();
    643612                if ( 1 === count( $this->roles ) && current( $this->roles ) === $role ) {
    644613                        return;
     
    742711         */
    743712        public function add_cap( $cap, $grant = true ) {
    744                 $this->load_capability_data();
    745713                $this->caps[ $cap ] = $grant;
    746714                update_user_meta( $this->ID, $this->cap_key, $this->caps );
     
    757725         */
    758726        public function remove_cap( $cap ) {
    759                 $this->load_capability_data();
    760727                if ( ! isset( $this->caps[ $cap ] ) ) {
    761728                        return;
     
    776743        public function remove_all_caps() {
    777744                global $wpdb;
    778                 $this->caps = null;
     745                $this->caps = array();
    779746                delete_user_meta( $this->ID, $this->cap_key );
    780747                delete_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level' );
    781                 $this->load_capability_data();
     748                $this->get_role_caps();
    782749        }
    783750
     
    810777         */
    811778        public function has_cap( $cap, ...$args ) {
    812                 $this->load_capability_data();
    813 
    814779                if ( is_numeric( $cap ) ) {
    815780                        _deprecated_argument( __FUNCTION__, '2.0.0', __( 'Usage of user levels is deprecated. Use capabilities instead.' ) );
     
    913878
    914879                $this->cap_key = $wpdb->get_blog_prefix( $this->site_id ) . 'capabilities';
    915                 $this->caps    = null;
     880
     881                $this->caps = $this->get_caps_data();
     882
     883                $this->get_role_caps();
    916884        }
    917885
     
    944912                return $caps;
    945913        }
    946 
    947         /**
    948          * Loads capability data if it has not been loaded yet.
    949          *
    950          * @since 6.9.0
    951          */
    952         private function load_capability_data() {
    953                 if ( isset( $this->caps ) ) {
    954                         return;
    955                 }
    956                 $this->caps = $this->get_caps_data();
    957                 $this->get_role_caps();
    958         }
    959914}
  • trunk/tests/phpunit/tests/user/capabilities.php

    r60915 r61037  
    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         /**
    1032996         * Test add_role with implied capabilities grant successfully grants capabilities.
    1033997         *
     
    11351099                $this->flush_roles();
    11361100                $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                 }
    11721101        }
    11731102
  • trunk/tests/phpunit/tests/user/multisite.php

    r60977 r61037  
    370370                switch_to_blog( $site_id );
    371371                $user = get_user_by( 'id', $user_id );
    372                 $this->assertContains( 'subscriber', $user->roles, 'User should have subscriber role' );
    373372                restore_current_blog();
    374373
     
    376375                wpmu_delete_user( $user_id );
    377376
    378                 $this->assertContains( 'subscriber', $user->roles, 'User should still have subscriber role' );
     377                $this->assertContains( 'subscriber', $user->roles );
    379378        }
    380379
  • trunk/tests/phpunit/tests/user/query.php

    r60915 r61037  
    163163                add_filter( 'update_user_metadata_cache', array( $filter, 'filter' ), 10, 2 );
    164164
    165                 $query = new WP_User_Query(
     165                new WP_User_Query(
    166166                        array(
    167167                                'include' => self::$author_ids,
     
    169169                        )
    170170                );
    171 
    172                 $users = $query->get_results();
    173                 foreach ( $users as $user ) {
    174                         $this->assertIsArray( $user->roles );
    175                         foreach ( $user->roles as $role ) {
    176                                 $this->assertIsString( $role );
    177                         }
    178                 }
    179171
    180172                $args      = $filter->get_args();
Note: See TracChangeset for help on using the changeset viewer.