我正在运行一个WordPress 5.2.3网站,在管理面板中的东西有麻烦。
我有一个自定义角色,我们称之为librarian
,还有一个自定义帖子类型,我们称之为book
。
我想使librarian
可以编辑book
,但不能创建新的book
。
按照另一个问题(WordPress: Disable “Add New” on Custom Post Type)和WordPressdocumentation中的建议,我最终得到了以下代码:
// Custom post type.
register_post_type('book',
array(
'labels' => array(
'name' => __( 'book' ),
'singular_name' => __( 'Book' )
),
'capability_type' => array('book', 'books'),
'capabilities' => array(
'create_posts' => 'do_not_allow' // <-- The important bit.
),
'map_meta_cap' => true,
'description' => 'Book full of pages',
'exclude_from_search' => true,
'publicly_queryable' => false,
'show_in_nav_menus' => false,
'show_ui' => true,
'show_in_menu' => true,
'show_in_rest' => true,
'menu_icon' => 'dashicons-location',
'menu_position' => 5,
'supports' => array('title', 'revisions')
));
// Custom role.
add_role('librarian', 'Librarian', array(
'read' => true,
'edit_books' => true,
'edit_published_books' => true
));
当我以librariran
的身份访问edit.php?post_type=book
时,我希望看到books
的列表以供编辑,但我看不到Add New按钮。然而,我实际上得到的是403
的响应:
对不起,您没有权限访问此页面。
我认为这可能是WordPress中的一个错误,因为以下情况:
- 如果我以
administrator
的身份访问edit.php?post_type=book
,那么我看到的列表页没有所需的Add New按钮。 - 如果我为
librarian
角色提供edit_posts
功能,那么我看到的列表页面将没有所需的Add New按钮(但我不想为他们提供edit_posts
功能!)。
这些让我认为这不是一个问题,自定义后类型设置一般。
- 如果我从
book
类型注册中删除'create_posts' => 'do_not_allow'
,librarian
* 可以 * 看到列表页面,但它包括Add New按钮。
这使我认为,这不是一个问题,与自定义角色设置一般。
以前有没有人遇到过这个问题?我的配置中有没有遗漏什么?或者有没有简单的补丁或变通方法?
任何帮助都将不胜感激!谢谢。
4条答案
按热度按时间njthzxwz1#
看来这是WordPress中的一个bug。我已经找到了问题的根源和解决方法。
变通方案
如果您对原因不感兴趣,解决方法是注解掉
wp-admin/includes/menu.php
中的这段修饰代码:https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/menu.php#L168
这意味着以前不显示子菜单的一些菜单项现在会显示子菜单(单个菜单项与主菜单项相同),但这只是外观UI的变化。
原因
如果你们想知道细节...
访问
edit.php?post_type=book
导致wp-admin/includes/menu.php
中的此检查失败:https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/menu.php#L341
对
user_can_access_admin_page()
的调用会调用到get_admin_page_parent()
。如果子菜单已被删除,则
get_admin_page_parent()
返回一个空父级,这最终导致user_can_access_admin_page()
在librarian
角色的情况下错误地返回false
(administrator
角色由于不同原因而通过)。如果子菜单保留在原处,
get_admin_page_parent()
将返回一个非空的父级,访问检查将从那里正确地进行。所以根本问题是全局的
$submenu
被用来决定用户界面和权限层次结构。我没有看到一个即时的快速解决这个问题,不会有副作用在整个WordPress代码的其他地方,除了上面的变通办法。noj0wjuj2#
我想我已经找到了一个解决办法,不必编辑核心文件。
正如您所说,此bug的原因是没有子菜单项的空菜单将导致访问检查错误地返回false。
因此,解决方法是不要将列表页设置为顶级菜单。而是将其设置为现有菜单下的子菜单。这样就不会有空的顶级菜单,并且您可以在没有“添加新项”按钮的情况下正确查看列表页。
这只是一种变通方法,并不理想,但也许比编辑核心文件要好。
创建一个自定义帖子类型的方法很简单,同时将其列表页面作为子菜单项。
register_post_type
的args有一个名为show_in_menu
的args。正如the docs所说:如果是现有顶级菜单的字符串(例如'tools.php'或'edit.php?post_type= page'),则帖子类型将被放置为该菜单的子菜单。
因此代码将为:
yshpjwxd3#
我找到了此问题的2种解决方法:
首先,我发现为custom_post_type create_posts分配一个特定的功能比使用
do_not_allow
更好所以我用:
这样,我可以为管理员或其他经理分配add_new_books功能,但不允许其他角色使用该功能。
(过滤user_has_cap以假装用户具有"edit_posts",然后删除"帖子"菜单项)
虽然这样做的工作,它确实增加了一些PHP通知未定义的索引。
(过滤$pagenow变量)
这可以在不添加任何PHP通知的情况下工作,但可能会有不可预见的问题,因为它更改了$pagenow变量,但仅在该页面上。
到目前为止,我使用选项2没有任何问题。
3z6pesqy4#
这个代码对我有用
感谢@ggedde