Hooking into add_submenu_page

时间:2012-11-02 作者:Zach

是否遇到过使用manage_options 页面的功能。。。真的不需要吗?嗯,我遇到过这样的情况。

这可能是一个更普遍的问题add_submenu_page, 所以不仅仅是针对我的用例。

我看着add_dashboard_page 它只是add_submenu_page:

function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = \'\' ) {
    global $submenu;
    global $menu;
    global $_wp_real_parent_file;
    global $_wp_submenu_nopriv;
    global $_registered_pages;
    global $_parent_pages;

    $menu_slug = plugin_basename( $menu_slug );
    $parent_slug = plugin_basename( $parent_slug);

    if ( isset( $_wp_real_parent_file[$parent_slug] ) )
        $parent_slug = $_wp_real_parent_file[$parent_slug];

    if ( !current_user_can( $capability ) ) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }

    // If the parent doesn\'t already have a submenu, add a link to the parent
    // as the first item in the submenu. If the submenu file is the same as the
    // parent file someone is trying to link back to the parent manually. In
    // this case, don\'t automatically add a link back to avoid duplication.
    if (!isset( $submenu[$parent_slug] ) && $menu_slug != $parent_slug ) {
        foreach ( (array)$menu as $parent_menu ) {
            if ( $parent_menu[2] == $parent_slug && current_user_can( $parent_menu[1] ) )
                $submenu[$parent_slug][] = $parent_menu;
        }
    }

    $submenu[$parent_slug][] = array ( $menu_title, $capability, $menu_slug, $page_title );

    $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug);
    if (!empty ( $function ) && !empty ( $hookname ))
        add_action( $hookname, $function );

    $_registered_pages[$hookname] = true;
    // backwards-compatibility for plugins using add_management page. See wp-admin/admin.php for redirect from edit.php to tools.php
    if ( \'tools.php\' == $parent_slug )
        $_registered_pages[get_plugin_page_hookname( $menu_slug, \'edit.php\')] = true;

    // No parent as top level
    $_parent_pages[$menu_slug] = $parent_slug;

    return $hookname;
}
老实说,我似乎没有任何东西可以通过插入现有的仪表板页面来更改功能。所以我在试着决定使用remove_submenu_page 然后尝试重新声明相同的子菜单。我知道我需要注意一些事情(如果页面使用的显示功能有任何额外的功能检查或显示对站点至关重要的内容)。第二双眼睛盯着这些东西总是很有帮助的,这样我就不会把事情弄得太复杂了。谢谢大家!

多亏了@toscho和@userabuser,我得到了以下信息:

function wpse_71303_change_menu_cap()
{
    global $submenu;
    foreach ($submenu[\'index.php\'] as $dashboard => $key) {
        if ($key[0] == \'Analytics360°\') {
            $submenu[\'index.php\'][$dashboard][1] = \'analytics\';
        }
    }
}
add_action( \'admin_head\', \'wpse_71303_change_menu_cap\' );
如果我运行print_r($submenu) I do see the new capability - but I still can\'t access the menu item under the client role I created (with theanalytics\\u 360 `功能)(使用成员插件创建)。可能开火太晚了?肯定有点奇怪。一如既往地感谢!

The code from Update works for anyone that comes across this. It was an unneeded check around add_dashboard_page() giving me the issue.

2 个回复
最合适的回答,由SO网友:fuxia 整理而成

钩入admin_head, 渲染菜单之前的最后一个操作,并更改全局$menu:

add_action( \'admin_head\', \'wpse_71303_change_menu_cap\' );

/**
 * Change the capability to access an admin menu item.
 *
 * @wp-hook admin_head
 * @return void
 */
function wpse_71303_change_menu_cap()
{
    global $menu;

    foreach ( $menu as $key => $item )
    {
        // Find menu by name
        if ( \'Tools\' === $item[0] ) // default cap: \'edit_posts\'
        {
            $menu[ $key ][1] = \'new_capability\';
        }
    }
}

SO网友:Martin_W

把之前的答案和原始海报的更新放在一起,以下是对我有用的:

请注意,下面的代码恰好是针对CiviCRM插件的。它更改访问权限access_civicrmadminister_civicrm 对于;“设置”;菜单项,因为我不希望普通用户访问它。在我的例子中,我不是检查英文子菜单名,而是检查页面的slugcivi_options (即。civi_options.php) 已调用。此外,我发现有必要设置$submenu[\'CiviCRM\'][$key] = $item; 要更新$submenu 结构

另请注意,下面的方法是not true security! 它会抑制子菜单项,但如果用户知道正确的URL,则不会阻止访问子菜单。


/////////////////////////////////////////////////
// ...this goes in my class `init()` function...
    add_action( \'admin_head\', array( $this, \'cv_adjust_submenu_permissions\') );

/////////////////////////////////////////////////
// ...and then later in the body of the class...

    function cv_adjust_submenu_permissions() {
        global $submenu;
        //error_log(print_r($submenu, true));
        foreach ( $submenu[\'CiviCRM\'] as $key => $item ) {
            // change CiviCRM... Settings submenu item capability
            if ( \'civi_options\' === $item[2] ) { // default capability: \'access_civicrm\'
                $item[1] = \'administer_civicrm\'; // new capability
                $submenu[\'CiviCRM\'][$key] = $item;
            }
        }
    }

结束