Make WordPress Core

Opened 5 weeks ago

Last modified 4 hours ago

#63427 reviewing defect (bug)

User roles property should always be an array, but they sometimes become an object in localized data

Reported by: haruncpi's profile haruncpi Owned by: sergeybiryukov's profile SergeyBiryukov
Milestone: 6.9 Priority: normal
Severity: normal Version: 2.0
Component: Users Keywords: has-patch has-test-info has-unit-tests changes-requested reporter-feedback
Focuses: Cc:

Description

When filtering roles via array_filter() in wp-includes/class-wp-user.php, the resulting array ($this->roles) can retain non-sequential numeric keys, if any roles are filtered out. This causes WP_User->roles to be treated as an object when JSON-encoded (e.g., in wp_localize_script()), instead of a proper array, which breaks client-side expectations.

$current_user = wp_get_current_user();

$local_data = array(
    'current_user' => array(
        'id' => $current_user->ID,
        'roles' => $current_user->roles,
    ),
);

wp_localize_script( 'myplugin-frontend', '_myplugin_object', $local_data );

If roles contains keys like [0 => 'editor', 2 => 'seo'] , the resulting JSON becomes:

{ roles: { "0": "editor", "2": "custom" } }

Instead of

{ roles: ["editor", "custom"] }

Attachments (1)

63427.diff (506 bytes) - added by haruncpi 5 weeks ago.
Adds array reindexing to ensure roles remains a proper indexed array

Download all attachments as: .zip

Change History (10)

@haruncpi
5 weeks ago

Adds array reindexing to ensure roles remains a proper indexed array

This ticket was mentioned in PR #8790 on WordPress/wordpress-develop by @haruncpi.


5 weeks ago
#1

When filtering roles via array_filter() in wp-includes/class-wp-user.php, the resulting array ($this->roles) can retain non-sequential numeric keys, if any roles are filtered out. This causes WP_User->roles to be treated as an object when JSON-encoded (e.g., in wp_localize_script()), instead of a proper array, which breaks client-side expectations.

$current_user = wp_get_current_user();

$local_data = array(
    'current_user' => array(
        'id' => $current_user->ID,
        'roles' => $current_user->roles,
    ),
);

wp_localize_script( 'myplugin-frontend', '_myplugin_object', $local_data );

If roles contains keys like [0 => 'editor', 2 => 'seo'], the resulting JSON becomes:

{ roles: { "0": "editor", "2": "custom" } }

Instead of

{ roles: ["editor", "custom"] }

Ticket’s URL
https://core.trac.wordpress.org/ticket/63427

@getsyash commented on PR #8790:


5 weeks ago
#2

### Test Report

I’ve tested this PR and can confirm that it works as expected. After applying the changes, the $current_user->roles array is properly reindexed using array_values(), ensuring sequential keys. The localized JSON output now correctly produces an array instead of a JavaScript object, which resolves the client-side issue.

Tested with multiple role combinations, including cases where some roles were removed — everything behaves correctly. ✅

### Testing environment:

WordPress Version: 6.8.1
PHP Version: 8.2.27
Theme: TwentyTwentyFive
Plugins: None installed
OS: Windows

Thanks for the Fix

#3 @haruncpi
4 weeks ago

  • Resolution set to worksforme
  • Status changed from assigned to closed

Could you kindly take a look and review this fix? @SergeyBiryukov @desrosj

#4 @SirLouen
4 weeks ago

  • Component changed from General to Users
  • Focuses sustainability removed
  • Keywords has-test-info dev-feedback has-unit-tests added
  • Resolution worksforme deleted
  • Status changed from closed to reopened

@haruncpi If you have a patch and a test report, you dont have to close the ticket. Leave it open for review with the patch. Closing with worksforme is used when someone reports a bug, you test it and you see there is no bug.

PS: I have not tested the patch, I'm just informing the user.

#5 @haruncpi
4 weeks ago

Thank you @SirLouen
Reopened for review.

#6 @SergeyBiryukov
4 weeks ago

  • Milestone changed from Awaiting Review to 6.9
  • Owner changed from haruncpi to SergeyBiryukov
  • Status changed from reopened to reviewing

#7 @SirLouen
24 hours ago

  • Keywords needs-testing added; dev-feedback removed

#8 @SirLouen
7 hours ago

  • Keywords changes-requested added; needs-testing removed

@haruncpi I've added some code review in your PR. Give it a check when you can.

#9 @SirLouen
4 hours ago

  • Keywords reporter-feedback added
  • Version changed from 6.8 to 2.0

<has-code-review>

I've been able to track the introduction of array_keys back to 1.6 [2793], which is not the problem itself, but is the main reason of why this is happening. Because this thing has probably existed historically, from the inception of this function.

The question here is: @haruncpi why you don't simply preprocess the resulting json into an array, before delivering it to wp_localize_script?

Last edited 4 hours ago by SirLouen (previous) (diff)
Note: See TracTickets for help on using tickets.