当一个CPT作为受角色保护的另一个CPT的子菜单放置时,我如何通过代码访问该CPT的内置用户界面?

时间:2020-05-25 作者:Bernie

我在玩弄WordPress的功能,很难理解哪里出了问题。现在,我有一个管理菜单,作为学校的子菜单显示给所有有学生的管理员:每个链接到http://example.com/wp-admin/edit.php?post_type=student. (当用户担任校长角色时,将显示指向教师内置UI的链接,学校将模拟其链接)。到目前为止,一切都很好。

道路上的颠簸是当非校长管理员单击学校或学生时,会出现错误“抱歉,您不允许访问此页面”。(正如预期的那样,当同一个管理员访问http://example.com/wp-admin/edit.php?post_type=teacher, 出现错误“您需要更高级别的权限”和“抱歉,不允许您在此帖子类型中编辑帖子”。)问题是,并非所有管理员都可以访问学生内置UI。(正如所料,校长们没有问题。)如何解决这一问题,使所有站点管理员都可以访问学生,只有校长可以访问教师,同时保留管理菜单和内置UI的布局和功能?

What I\'ve Tried:\'show_in_menu\' => \'edit.php?post_type=teacher\' 该行已从学生CPT中删除,一切正常,但学生成为顶级菜单项,而不是学校。我尝试将教师作为学生的子菜单项,但当用户担任校长角色时,学校不会更改其链接(教师和学生的顺序也是向后的)。我也试过了add_menu_page() 对于学校和添加slug返回show_in_menu 师生争论register_post_type 但这不起作用,因为它创建了一个页面,而不是转发到相应的内置UI。

class School {
    public static function init() {
        add_action(\'init\', array(__CLASS__, \'register_cpt\'));
        add_action(\'init\', array(__CLASS__, \'add_role\'));
        add_action(\'admin_menu\', array(__CLASS__, \'modify_menu\'));
    }

    public static function register_cpt() {
        register_post_type(\'teacher\', array(
            \'labels\' => array(
                \'name\'          => __(\'TEACHER\'),
                \'all_items\'     => __(\'TEACHERS\'),
                \'menu_name\'     => __(\'SCHOOL\'),
            ),
            \'show_ui\'           => TRUE,
            \'capability_type\'   => \'educator\',
            \'map_meta_cap\'      => TRUE,
        ));
        register_post_type(\'student\', array(
            \'labels\' => array(
                \'name\'          => __(\'STUDENT\'),
                \'menu_name\'     => __(\'STUDENTS\'),
            ),
            \'show_ui\'           => TRUE,
            \'show_in_menu\'      => \'edit.php?post_type=teacher\',
        ));
    }

    public static function add_role() {
        if(get_role(\'headmaster\') === NULL) {
            $caps = array();
            foreach(get_role(\'administrator\')->capabilities as $cap => $tmp) {
                $pos = strpos($cap, \'post\');
                if($pos !== FALSE) {
                    $cap = str_replace(\'post\', \'educator\', $cap);
                    $caps[$cap] = TRUE;
                }
            }
            add_role(\'headmaster\', \'HEADMASTER\', $caps);
        }
    }

    public static function modify_menu() {
        global $submenu;
        unset($submenu[\'edit.php?post_type=teacher\'][10]);
    }
} School::init();

1 个回复
SO网友:Mort 1305

codex

连接以处理页面输出的函数必须检查用户是否也具有所需的“能力”。

它没有提到的是,子页面的检查向上迭代到其父页面。如果用户无法访问教师,则无法访问“管理”菜单中显示在其下方的子页面。(我不知道这个功能有什么好处,我认为这可能是一个bug。)

add_menu_page() 是你的答案。在codex 它将实现您希望的功能,如果您将其slug传递给自定义post类型show_in_menu 的参数register_post_type() (与页面的钩子后缀相反add_menu_page()). 为了获得此功能,必须在父菜单项之前添加子菜单项,例如通过注册帖子类型。(这样,家长菜单项将呈现添加的第一个子菜单项的特征。请注意,教师是在学生之前添加的,因此它将在菜单顺序中显示在其上方,学校项目是在添加CPT子菜单项之后添加的。)因此,以下是要对代码所做的更改,以使其按您希望的方式工作:

public static function register_cpt() {
    register_post_type(\'teacher\', array(
        \'labels\' => array(
            ...
        //  \'all_items\' => __(\'TEACHERS\'),      // Remove
            \'menu_name\' => __(\'TEACHERS\'),      // Change
        ),
        \'show_in_menu\'      => \'school\',        // Add
        ...
    ));
    register_post_type(\'student\', array(
        ...
        \'show_in_menu\'      => \'school\',        // Change
    ));
}

public static function modify_menu() {          // Change
    $pg = add_menu_page(
        NULL,                                   // Page name will not be displayed.
        \'SCHOOL\',                               // Formerly register_post_type(\'teacher\')->menu_name.
        \'administrator\',                        // Lowest level of permission required to be displayed.
        \'school\'                                // Slug (used in register_post_type).
    //  ,NULL                                   // Page callback omitted as will not be called.
    );
    // I think you were passing $pg to show_in_menu, but this will not work
    // The page slug (school) must be used instead.
}

UPDATE: 我提交了bug ticket 有关此问题,请联系WordPress core。此外,请注意,无论子页面嵌套在哪个页面下,即使它们显示为能够显示,也必须具有其父页面的权限。因此,所需的最低级别权限是add_menu_page 方法例如,如果新的学校管理菜单页面的功能是educator, 就像你最初的例子中老师的情况一样。

相关推荐

正在尝试获取wp-includes/capabilities.php中非对象的属性

在调试中,我每分钟都会收到以下通知序列。日志:[23-Oct-2012 13:27:33 UTC] PHP Notice: Trying to get property of non-object in mysite/wp-includes/capabilities.php on line 1022 [23-Oct-2012 13:27:33 UTC] PHP Notice: Trying to get property of non-object in mysite/wp-includes/