[wp-trac] [WordPress Trac] #29213: Introduce capability for access to nav-menus.php

WordPress Trac noreply at wordpress.org
Mon Aug 18 19:52:12 UTC 2014


#29213: Introduce capability for access to nav-menus.php
-------------------------+------------------------------
 Reporter:  westonruter  |       Owner:
     Type:  enhancement  |      Status:  new
 Priority:  normal       |   Milestone:  Awaiting Review
Component:  Menus        |     Version:  3.0
 Severity:  normal       |  Resolution:
 Keywords:  needs-patch  |     Focuses:  administration
-------------------------+------------------------------

Comment (by jesin):

 I created patch **29213.diff** as a starting point based on changesheet
 [29170] and added `edit_nav_menus` capability through the `map_meta_cap`
 filter. However accessing **wp-admin/nav-menus.php** displayed the
 following error:

 > **You do not have sufficient permissions to access this page.**

 This was because `user_can_access_admin_page()` was returning `false`.
 Digging deeper I found that `$_wp_menu_nopriv` contained the following
 value:

 {{{
 $_wp_menu_nopriv["nav-menus.php"] = true;
 }}}

 To test how `customize` worked I used the same filter and printed
 `$_wp_menu_nopriv`. This is what I saw:

 {{{
 $_wp_menu_nopriv["customize.php?return=%2Fwp-admin%2Fcustomize.php"] =
 true;
 }}}

 But **wp-admin/customize.php** was accessible, so I narrowed down to the
 `user_can_access_admin_page()` function's following lines:

 {{{
 if ( isset( $_wp_menu_nopriv[$pagenow] ) )
     return false;
 }}}

 The `$pagenow` variable only contains the filename without query strings
 so when `customize` was used this line checked for `isset(
 $_wp_menu_nopriv["customize.php"] )` which obviously caused this `if` loop
 to be skipped with `user_can_access_admin_page()` returning `true`.

 Now the question is why did **customize.php** and **nav-menus.php** end up
 in the `$_wp_menu_nopriv` list when appropriate capabilities were being
 used.

 The answer is in **lines 93 - 117** of file **wp-
 admin/includes/menu.php**. Specifically the following lines:

 {{{
 if ( $new_parent != $old_parent ) {
     $_wp_real_parent_file[$old_parent] = $new_parent;
     $menu[$id][2] = $new_parent;
 }}}

 This piece of code replaces the parent menu's filename with the filename
 of its child menu. This results in the following values:

 {{{
 Array
 (
         [0] => Appearance
         [1] => edit_theme_options
         [2] => nav-menus.php
         [3] =>
         [4] => menu-top menu-icon-appearance
         [5] => menu-appearance
         [6] => dashicons-admin-appearance
 )
 }}}

 Notice how this menu got its parent's capability requirement. This causes
 **nav-menus.php** (or **customize.php?return=%2Fwp-
 admin%2Fcustomize.php**) to be added to the `$_wp_menu_nopriv` list.

 So when filenames are being replaced we should also replace their
 capability requirement.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/29213#comment:2>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list