(编辑:去拿“学生”徽章,想知道是否有人可以投票支持这个问题?)
我回答说a question 关于能力,但现在我需要这方面的帮助。在审查之后the manual, 我更困惑了。
我有两种自定义帖子类型,管理员都可以完全访问。我有订阅者,有些人可以访问其中一个CPT,它是第一个CPT的“子”并将其父ID存储在_adm_id
元数据。这些“特殊”订阅者可以访问父CPT admin表,因此他们可以单击链接来创建具有特殊状态的父CPT帖子。接下来,允许订阅者编辑子帖子(包括其自己的帖子和其他人创建的帖子),但前提是它具有特定的自定义帖子状态。最后,特别订阅者不允许删除帖子(或编辑已删除的帖子),甚至不允许删除自己的帖子。
以下是我得到的(工作代码)。。。
// Setup custom post types and statuses
add_action(\'init\', function() {
// Custom Post Types
register_post_type(\'adm-cpt\', array(
\'label\' => __(\'Admin Only CPT\'),
\'show_ui\' => TRUE,
\'show_in_menu\' => \'my-menu-item\',
\'show_in_admin_bar\' => FALSE,
\'capability_type\' => \'adm\',
\'map_meta_cap\' => TRUE,
\'capabilities\' => array(
\'create_posts\' => \'administrator\', // Only admin can create, not special Subscribers
),
));
register_post_type(\'sub-cpt\', array(
\'label\' => __(\'Subscriber/Admin CPT\'),
\'show_ui\' => TRUE,
\'show_in_menu\' => \'my-menu-item\',
\'show_in_admin_bar\' => FALSE,
\'capability_type\' => \'sub\',
\'map_meta_cap\' => TRUE,
));
// Custom Post Statuses
foreach(array(
\'adm-childable\' => __(\'Can Create Children\'),
\'sub-editable\' => __(\'Any Subscriber Can Edit\'),
) as $slug => $label) {
register_post_status($slug, array(
\'label\' => _x($label, \'post\'),
\'label_count\' => _n_noop($label .\' <span class="count">(%s)</span>\', $label .\' <span class="count">(%s)</span>\' ),
\'public\' => TRUE,
));
}
});
// Setup parent page in admin menu
add_action(\'admin_menu\', function() {
// Add menu item
if(current_user_can(\'administrator\')
|| current_user_can(\'special-subscriber\')
) {
// Admin menu header
add_menu_page(
NULL,
\'CPTs\',
\'exist\',
\'my-menu-item\',
\'\'
);
}
});
// Set up role
add_action(\'wp_roles_init\', function($wp_roles){
// Prepare
$role = \'special-subscriber\';
$caps = array(
\'delete_subs\' => FALSE, // No trashing ...
\'delete_others_subs\' => FALSE,
\'delete_published_subs\' => FALSE,
\'delete_private_subs\' => FALSE,
\'edit_published_subs\' => FALSE, // And no editing published/private posts ...
\'edit_private_subs\' => FALSE,
\'edit_adms\' => TRUE, // Allow viewing of adm-cpt table
\'edit_posts\' => TRUE, // WARNING: Here\'s the permission that is causing the problems!
);
$name = __(\'"Special" Subscriber\');
// Update role in database, if needed
if($wp_roles->get_role($role) === NULL
|| $wp_roles->get_role($role)->capabilities != $caps
|| $wp_roles->roles[$role][\'name\'] !== $name
) {
$wp_roles->remove_role($role);
$wp_roles->add_role($role, $name, $caps);
}
});
// Dynamicly set capabilities
add_action(\'user_has_cap\', function($allcaps, $caps, $args, $user) {
foreach($caps as $cap) {
$perm = substr($cap, 0, strrpos($cap, \'_\'));
$type = substr($cap, strlen($perm)+1);
if(in_array($type, array(\'adm\', \'adms\')) && in_array(\'administrator\', $user->roles)
|| in_array($type, array(\'sub\', \'subs\')) && !empty(array_intersect(array(\'administrator\', \'special-subscriber\'), $user->roles))
) {
// Check Subscriber if post is editable
if(in_array($cap, array(\'edit_subs\', \'edit_others_subs\'))
&& in_array(\'special-subscriber\', $user->roles)
&& !in_array(\'administrator\', $user->roles)
&& !empty($args[2])
&& ( !in_array(get_post_status($args[2]), array(\'sub-editable\'))
&& !in_array($_REQUEST[\'original_post_status\'], array(\'sub-editable\', \'auto-draft\')) // Creating
|| get_post_status(get_post_meta($args[2], \'_adm_id\', TRUE)) === \'trash\'
)
) {
$allcaps[$cap] = FALSE;
}
// Add the cap
if(!isset($allcaps[$cap])
) {
$allcaps[$cap] = TRUE; // All the _adm and _sub capabilities are made available.
}
}
}
return $allcaps;
}, 10, 4);
// Add stuff to force proper navigation
add_action(\'post_row_actions\', function($actions, $post) {
// Add link to adm-cpt table entries to create child
if(get_post_type($post) === \'adm-cpt\'
&& get_post_status($post) === \'adm-childable\'
&& current_user_can(\'edit_subs\')
) {
$lbl = __(\'New \'). get_post_type_object(\'sub-cpt\')->labels->name;
$actions[\'adm-cpt-create-sub-cpt\'] = sprintf(
\'<a href="%s" aria-label="%s">%s</a>\',
admin_url(\'post-new.php?post_type=sub-cpt&adm_id=\'. $post->ID),
esc_attr(\'“\'. $lbl .\'”\'),
$lbl
);
}
// Return
return $actions;
}, 10, 2);
// Modify publish metabox
add_action(\'post_submitbox_misc_actions\', function($post) {
$arr = array();
switch(get_post_type($post)) {
case \'adm-cpt\':
$arr = array(\'adm-childable\');
break;
case \'sub-cpt\':
$arr = array(\'sub-editable\');
break;
default:
return;
}
// Check that parent exists -- Should be in an init hook, but it\'s prettier here.
if($_REQUEST[\'post_type\'] === \'sub-cpt\'
&& (empty($_REQUEST[\'adm_id\']) || get_post_type($_REQUEST[\'adm_id\']) !== \'adm-cpt\')
&& (empty($post->_adm_id) || get_post_type($post->_adm_id) !== \'adm-cpt\')
){
?><script>window.document.location.replace("<?= admin_url(\'edit.php?post_type=adm-cpt\') ?>")</script><?php
return;
}
// Add custom post statuses
?><input type=\'hidden\' name=\'adm_id\' value=\'<?= $_REQUEST[\'adm_id\'] ?>\'><?php
if(count($arr)) {
?><script>
<?php foreach($arr as $k) { $obj = get_post_status_object($k); ?>
jQuery("select#post_status").append("<option value=\\"<?= $k ?>\\"><?= $obj->label ?></option>");
<?php if(get_post_status($post) == $k) { ?>
jQuery("#post-status-display").text("<?= $obj->label ?>");
jQuery("select#post_status").val("<?= $k ?>");
<?php } ?>
<?php } ?>
</script><?php
}
// Display parent -- Informational
if(!empty($_REQUEST[\'adm_id\'])
|| !empty($post->_adm_id)
) {
$parent_id = $post->_adm_id;
if(!$parent_id) $parent_id = $_REQUEST[\'adm_id\'];
?><div class="misc-pub-section misc-pub-adm-cpt">Parent: <span id="post-status-display"><?= get_the_title($parent_id) ?></span></div><?php
}
});
// Save parent ID
add_action(\'save_post_sub-cpt\', function($post_id, $post, $update) {
// Ensure we continue only id a new child is created
if(defined(\'DOING_AUTOSAVE\') && DOING_AUTOSAVE
|| get_post_type($post_id) !== \'sub-cpt\'
|| empty($_REQUEST[\'adm_id\'])
|| get_post_type($_REQUEST[\'adm_id\']) !== \'adm-cpt\'
) return;
// Set parent ID
update_post_meta($post_id, \'_adm_id\', $_REQUEST[\'adm_id\']);
}, 10, 3);
// Navigation when changed to uneditable
add_action(\'load-post.php\', function(){
if(!empty($_REQUEST[\'post\'])
&& get_post_type($_REQUEST[\'post\']) === \'sub-cpt\'
&& !current_user_can(\'edit_subs\', $_REQUEST[\'post\'])
) {
delete_post_meta($_REQUEST[\'post\'], \'_edit_lock\');
wp_redirect(\'edit.php?post_type=sub-cpt\');
die();
}
});
这里的问题是,特别订阅者可以编辑常规帖子和评论。我知道这是
edit_posts
功能,该功能允许编辑/创建
all 职位类型。但是,删除它会阻止特殊订阅者创建
sub-cpt
职位和授予
edit_subs
无法解决问题。设置
capabilities->create_post=special-subscriber
注册子CPT时。我可以限制订阅者创建
adm-cpt
通过定义
capabilities
注册帖子类型时的参数。但我不希望特殊订阅者能够编辑/创建除
sub-cpt
键入,但我似乎不知道如何键入。
我找到了a Q&A 与主题相关,但这似乎不起作用。CPT映射到自定义功能,它们存在,并且user_has_cap
filter动态授予每个功能。我甚至尝试在special-subscriber
角色定义。不管怎样,我相信变化很简单--“它是什么?”?
(如果您感兴趣,我还有另一个功能问题。当特殊订阅者设置子CPT时post_status
若要发布,将锁定帖子并将其转发到edit.php
但我想解锁帖子,让观众转发到edit.php?post_type=sub-cpt
就像在load-post.php
我的代码的钩子,我似乎不知道怎么做。)罢工>
UPDATE: 我已经将其隔离到菜单中CPT的位置。当CPT注册为使用register_post_type
选项show_in_menu=TRUE
, 一切正常。但是,当CPT被添加为一个老式管理菜单项的子菜单时,情况就不一样了。添加UI并隐藏它会导致相同的问题,同时添加子页面并将其重定向到CPT的UI。示例:
// 1.) Works as expected if user has every custom capability
add_action(\'init\', function() {
register_post_type(\'sub-cpt\', array(
\'label\' => __(\'Subscriber/Admin CPT\'),
\'show_ui\' => TRUE,
\'show_in_menu\' => TRUE, // Take note of this
\'show_in_admin_bar\' => FALSE,
\'capability_type\' => \'sub\',
\'map_meta_cap\' => TRUE,
));
}
// 2.) Same as #1 with the exception that access to \'post-new.php\' when "Add New" button is clicked is prohibited
add_action(\'init\', function() {
register_post_type(\'sub-cpt\', array(
\'label\' => __(\'Subscriber/Admin CPT\'),
\'show_ui\' => TRUE,
\'show_in_menu\' => \'my-menu-item\', // Take note of this
\'show_in_admin_bar\' => FALSE,
\'capability_type\' => \'sub\',
\'map_meta_cap\' => TRUE,
));
}
add_action(\'admin_menu\', function() {
add_menu_page(
\'CPT in title bar\',
\'CPT in menu\',
\'edit_subs\',
\'my-menu-item\',
\'\'
);
}
// 3.) Breaks the same as #2
add_action(\'init\', function() {
register_post_type(\'sub-cpt\', array(
\'label\' => __(\'Subscriber/Admin CPT\'),
\'show_ui\' => TRUE,
\'show_in_menu\' => FALSE, // Take note of this
\'show_in_admin_bar\' => FALSE,
\'capability_type\' => \'sub\',
\'map_meta_cap\' => TRUE,
));
}
add_action(\'admin_menu\', function() {
global $submenu;
add_menu_page(
\'CPT in title bar\',
\'CPT in menu\',
\'edit_subs\',
\'my-menu-item\'
);
add_submenu_page(
\'my-menu-item\',
get_post_type_object(\'sub-cpt\')->label,
get_post_type_object(\'sub-cpt\')->label,
\'edit_subs\',
\'my-menu-item-sub\'
);
// Change link
$url = \'edit.php?post_type=sub-cpt\';
$submenu[\'my-menu-item\'][1][2] = admin_url($url); // Set URL to view CPT
unset($submenu[\'my-menu-item\'][0]); // Remove WP generated menu item
});
如果我可以将“添加新”功能作为子页面与CPT一起使用,我想我的问题会得到解决,因为
edit_posts
给我带来麻烦的能力可以具体映射到
edit_subs
. 有人知道怎么做吗?