Opened 16 years ago
Closed 15 years ago
#9128 closed defect (bug) (fixed)
array_merge() Error when Adding Roles via Plugins
Reported by: | johnkolbert | Owned by: | |
---|---|---|---|
Milestone: | 3.0 | Priority: | normal |
Severity: | major | Version: | 2.7 |
Component: | Role/Capability | Keywords: | has-patch commit |
Focuses: | Cc: |
Description
Scenario:
Adding a new user role that has the same capabilities as the "Administrator" role.
Code Used:
global $wp_roles; $admin_role = $wp_roles->get_role("administrator"); $wp_roles->add_role("superadmin", Super Admin, $admin_role->capabilities);
Error Encountered:
Warning: array_merge() [function.array-merge]: Argument #2 is not an array in /Applications/MAMP/htdocs/wp2pt7/wp-includes/capabilities.php on line 537 Warning: array_merge() [function.array-merge]: Argument #1 is not an array in /Applications/MAMP/htdocs/wp2pt7/wp-includes/capabilities.php on line 537 Warning: array_merge() [function.array-merge]: Argument #1 is not an array in /Applications/MAMP/htdocs/wp2pt7/wp-includes/capabilities.php on line 539
Suggested Fix:
PHP 5.0 is sensitive for array_merge only using arrays. By using typecasting you can merge other types.
Here's what capabilities.php should be for lines 534-539:
$this->allcaps = array(); foreach ( (array) $this->roles as $role ) { $role =& $wp_roles->get_role( $role ); $this->allcaps = array_merge( (array)$this->allcaps, (array)$role->capabilities ); } $this->allcaps = array_merge( (array)$this->allcaps, (array)$this->caps );
Notice the addition of the (array) typecast in the array_merge functions.
Attachments (2)
Change History (10)
#5
@
15 years ago
- Resolution fixed deleted
- Status changed from closed to reopened
This bug is not fixed, and the above explanations miss the real problem.
In capabilities.php, in function get_role_caps, there is a foreach loop that is iterating on "$this->roles as $role". Then within the body of the loop, there is a line like:
$role =& $wp_roles->get_role( $role );
This line is making $role a pointer to an element in the $this->role_objects object (because that is what get_role has returned). Then on the next iteration through the loop, the foreach sets $role to a role string (like "contributor"). But $role is still a reference to an element of role_objects! So that element gets clobbered in place, corrupting the role_objects object and causing junk to be returned on subsequent accesses.
You can prove this by adding a couple var_dump() statements to monitor the state of role_objects as we iterate through the loop.
The fix for this is to use a different, unique variable name within the loop body, rather than reusing $role, which should only be the loop iterator.
Oops, forgot the quotes around "Super Admin" on the third line of code at the top.