Skip to content

Commit 49b38e9

Browse files
SergeyBiryukovSergeyBiryukov
authored andcommitted
Users: Initialize the WP_User::$roles property as a sequential array.
Previously, if any roles were filtered out via `array_filter()` when assigning the `WP_User::$roles` property in `WP_User::get_role_caps()`, the resulting array could contain non-sequential numeric keys, which would then cause it to be treated as an object when JSON-encoded, e.g. in `wp_localize_script()`, instead of a proper array, breaking client-side expectations. This commit ensures that the `WP_User::$roles` property is always treated as an array. Follow-up to [2703], [2793], [22118]. Props haruncpi, peterwilsoncc, SirLouen, getsyash, wildworks, johnjamesjacoby, SergeyBiryukov. Fixes #63427. git-svn-id: https://develop.svn.wordpress.org/trunk@61210 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 6d36bb7 commit 49b38e9

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/wp-includes/class-wp-user.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,9 +515,15 @@ public function get_role_caps() {
515515

516516
$wp_roles = wp_roles();
517517

518-
// Filter out caps that are not role names and assign to $this->roles.
518+
// Select caps that are role names and assign to $this->roles.
519519
if ( is_array( $this->caps ) ) {
520-
$this->roles = array_filter( array_keys( $this->caps ), array( $wp_roles, 'is_role' ) );
520+
$this->roles = array();
521+
522+
foreach ( $this->caps as $key => $value ) {
523+
if ( $wp_roles->is_role( $key ) ) {
524+
$this->roles[] = $key;
525+
}
526+
}
521527
}
522528

523529
// Build $allcaps from role caps, overlay user's $caps.

tests/phpunit/tests/user.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,6 +2157,37 @@ public function test_send_confirmation_on_profile_email_html_entities_decoded()
21572157
$this->assertStringNotContainsString( ''Test' blog's "name" has <html entities> &', $email->subject, 'Email subject does contains HTML entities' );
21582158
}
21592159

2160+
/**
2161+
* Tests that the `WP_User::$roles` property is a sequential array.
2162+
*
2163+
* @ticket 63427
2164+
*
2165+
* @covers WP_User::get_role_caps
2166+
*/
2167+
public function test_wp_user_roles_property_is_sequential_array() {
2168+
$user = new WP_User( self::$author_id );
2169+
$this->assertTrue( $this->is_sequential( $user->roles ), 'Initial roles array should be sequential.' );
2170+
2171+
$user->remove_role( 'author' );
2172+
$this->assertIsArray( $user->roles, 'After removing all roles, $user->roles should still be an array.' );
2173+
$this->assertSame( array(), $user->roles, 'After removing all roles, $user->roles should be an empty array.' );
2174+
2175+
$user->add_role( 'author' );
2176+
$user->add_role( 'subscriber' );
2177+
$this->assertSame( array( 'author', 'subscriber' ), $user->roles, 'After adding multiple roles, $user->roles should contain added roles.' );
2178+
$this->assertTrue( $this->is_sequential( $user->roles ), 'After adding multiple roles, $user->roles should still be sequential.' );
2179+
}
2180+
2181+
/**
2182+
* Determines whether an array has sequential numeric keys.
2183+
*
2184+
* @param array $arr The array to check.
2185+
* @return bool True if the array has sequential numeric keys, false otherwise.
2186+
*/
2187+
private function is_sequential( array $arr ) {
2188+
return array_keys( $arr ) === range( 0, count( $arr ) - 1 );
2189+
}
2190+
21602191
/**
21612192
* @ticket 42564
21622193
*/

0 commit comments

Comments
 (0)