是否可以让贡献者更改自己帖子的作者?我意识到这将有效地将他们锁定在职位之外,这就是我想要的。我希望他们一旦完成编辑就可以更改作者。
是否可以让贡献者更改自己帖子的作者?我意识到这将有效地将他们锁定在职位之外,这就是我想要的。我希望他们一旦完成编辑就可以更改作者。
Answers:
我要添加第二个答案,因为我的第一种方法被否决了,并且该方法没有得到适当的关注。
想法是创建自定义元框,该框列出所有用户并更改save_post
钩子中的作者。这样,您就不会打扰用户的功能,并且作者的更改会在帖子已保存时发生。另外,您还可以控制作者下拉列表中可用的用户列表。遵循的步骤:
注册元框:
function wpse313020_add_custom_box() {
// Bail out for users other than contributors
if ( ! user_can( get_current_user_id(), 'contributor' ) ) {
return;
}
// Register custom meta box
add_meta_box(
'wpse313020_author_override',
'Change Author', // metabox title
'wpse313020_author_ovveride_box_html', // callbac function
'post' // a post type you want to show the metabox on
);
}
add_action('add_meta_boxes', 'wpse313020_add_custom_box');
为您的元框构建标记:
/**
* HTML for custom meta box
*/
function wpse313020_author_ovveride_box_html() {
// you can modify the list of users by passing additional args to get_users()
$users = get_users();
?>
<label for="wpse313020_author_override_id">Select post author</label><br />
<select name="wpse313020_author_override_id" id="wpse313020_author_override_id" class="postbox">
<option value="">Select user...</option>
<?php
// get post ID on admin edit screen and retrieve saved post meta
$post_id = is_admin() && isset( $_GET['post'] ) ? absint( wp_unslash( $_GET['post'] ) ) : '';
$saved_value = ! empty( $post_id ) ? get_post_meta( $post_id, 'wpse313020_author_override', true ) : '';
foreach ( $users as $user ) {
echo sprintf( '<option value="%1$d" %2$s>%3$s</option>', absint( $user->ID ), selected( $saved_value, absint($user->ID, false ) ), esc_html( $user->display_name ) );
}
?>
</select>
<?php
}
挂钩save_post
以保存数据并覆盖作者:
/**
* Save custom post meta and override the post author
*/
function wpse313020_save_postdata( $post_id ) {
if ( array_key_exists('wpse313020_author_override_id', $_POST ) ) {
// save post meta with author ID
update_post_meta( $post_id, 'wpse313020_author_override', absint( $_POST['wpse313020_author_override_id'] ) );
// now modify the post author, we need to unhook the current function to prevent infinite loop
// you could add additional check here to see if the current author is not the same as chosen author
remove_action( 'save_post', 'wpse313020_save_postdata' );
$updated_data = [
'ID' => $post_id,
'post_author' => absint( $_POST['wpse313020_author_override_id'] ),
];
wp_update_post( $updated_data );
add_action( 'save_post', 'wpse313020_save_postdata' );
}
}
add_action('save_post', 'wpse313020_save_postdata');
注意
请记住添加随机数字段,并在保存后检查。您也可以考虑使用其他挂钩代替save_post
,即pre_post_update
或wp_insert_post_data
,以在初始后保存时处理数据。
希望有帮助!
即使可以允许作者(或贡献者)使用user_has_cap
过滤器挂钩和一些相关的CODE 将另一位作者分配给他/她自己的帖子,但是,这种方法本身在根本上是有缺陷的。因此,即使您采取了所有必要的安全措施,它仍然是一个漏洞,因为它将功能架构分解在一起。
让我给您提供一个示例场景:假设具有作者角色的用户意图不佳,并且向拥有大量帖子(可能使用脚本)的另一位作者发送垃圾邮件。下一次目标作者登录时,他/她将以他/她的名字看到所有这些帖子!这将继续,因为其他作者无法阻止它!因此,我们必须找到一种没有此缺陷的替代方法。
如果作者更改是必要的功能,则更好的方法是让其他作者(或其他编辑或管理员这样的高级用户)参与作者更改过程,以使发起作者可能无法向该作者发送垃圾邮件。目的作者。
为此,我们让发起作者从编辑器中选择目标作者,但我们不会直接更改帖子作者。相反,在更改作者时,我们将保存一个自定义帖子元,该元将保存目标作者ID。然后在管理面板中,我们将有一个帖子子菜单,其中将显示所有带有作者更改请求的帖子。只有目标作者和有edit_others_post
能力的用户(例如编辑者,管理员等)才能访问此作者更改请求UI。具有正确访问权限的用户将从用户界面中批准更改,然后才进行最终的作者更改。
CODE的实现可能会根据要求而有所不同,但是,没有任何其他CODE的实现,发起作者将能够在批准过程的窗口内修改帖子,甚至还原作者的更改请求。作者变更请求获得批准后,他们将被锁定在职位之外。
作者下拉列表框仅在用户具有此edit_others_posts
功能时显示。但是,出于明显的原因,您不想默认将此功能提供给作者。解决方案是仅在特定情况下(即当他正在编辑自己的帖子时)才提供此功能。由于该功能已写入数据库,因此您还必须确保在其他页面上将其删除。
这是一个精确的时间问题。您要在 WP确定贡献者有权编辑帖子之后但在post.php
生成编辑页面()的形式之前更改功能。一个合适的钩子是admin_init
。
像这样:
add_action ('admin_init', 'wpse313020_change_author');
function wpse313020_change_author () {
global $pagenow;
$current_user = wp_get_current_user();
// only do this if current user is contributor
if ('contributor' == $current_user->roles[0]) {
// add capability when we're editing a post, remove it when we're not
if ('post.php' == $pagenow)
$current_user->add_cap('edit_others_posts')
else
$current_user->remove_cap('edit_others_posts');
}
}
我没有测试过代码,因此可能有问题,但是您明白了。
我试图通过过滤贡献者的元功能来实现您所需的功能,并且它似乎可以正常工作。我要做的只是edit_others_posts
在WordPress请求时为贡献者添加功能。
但是,我会说这对我来说有点棘手,而且我不确定它是否完全安全。根据我将过滤器放入functions.php
WordPress 后的检查内容,贡献者无法在其他情况下编辑您所要求的其他用户的帖子。看起来不错,但是我们不能真正明确地检查当前用户是否是当前编辑的帖子的作者(如果将有条件检查添加到函数中,您将无法将帖子另存为其他用户)-让我担心
/**
* author_cap_filter()
*
* Filter on the current_user_can() function.
* This function is used to explicitly allow contributors to change post authors
*
* @param array $allcaps All the capabilities of the user
* @param array $cap [0] Required capability
* @param array $args [0] Requested capability
* [1] User ID
*/
function author_cap_filter( $allcaps, $cap, $args ) {
// Bail out if we're not dealing with right capability:
if ( ! in_array( $args[0], [ 'edit_others_posts' ] ) ) {
return $allcaps;
}
// Bail out for users who are not contributors
if ( ! user_can( $args[1], 'contributor' ) ) {
return $allcaps;
}
// Bail out for users who can already edit others posts:
if ( isset( $allcaps['edit_others_posts'] ) && $allcaps['edit_others_posts'] ) {
return $allcaps;
}
// overwrite 'edit_others_posts' capability
$allcaps[ $args[0] ] = true;
return $allcaps;
}
add_filter( 'user_has_cap', 'author_cap_filter', 100, 3 );
edit_others_posts
权限实际上将使他们能够编辑其他人的帖子。我们同样可以使作者成为编辑,这可能比赋予他们更高的功能更好。第二种解决方案是可能的,但是需要做更多的工作,恕我直言。
edit_others_posts
始终允许编辑其他用户的帖子,您并不完全正确。请从我的答案中测试代码-即使安装了过滤器if ( ! current_user_can( 'edit_post', $post_id ) )
,github.com / WordPress / WordPress / blob /…中的功能检查仍会返回false。再次,我确实同意这不是我的答案中提到的安全解决方案,但我认为值得一提,因为它确实有效。(对不起,连续两次发表评论,我不符合该字符数限制)
首先,安装插件用户角色编辑器(https://wordpress.org/plugins/user-role-editor/)。
其次,使用该插件创建一个名为Post Manager的新角色,例如:
创建新角色后,您将能够编辑其功能。现在,是解决问题的时刻,但是您必须在两个选项之间做出选择:
(现在不用担心贡献者的角色)
第一:
edit_others_posts
并publish_posts
。第二:
edit_others_posts
。决定后,单击“更新”。现在,您的新角色应具有该read
能力以及您选择的一个或多个角色。
现在,转到您的贡献者用户配置文件页面,并在页面结尾为他们提供其他角色(用户角色编辑器功能):
现在,作为贡献者和帖子管理员的每个用户都可以更改未发布帖子的帖子作者。而且,根据您先前的选择,用户可能还会发布帖子,如果这样做,他们将无法再编辑帖子。
重要!!!
我向您展示了一种创建新角色以保留贡献者默认功能的解决方案。如果需要(不明智的话),可以跳过Post Manager的创建,而使用User Role Editor,您只需直接编辑Contributor功能。
仅作记录,默认情况下WordPress仅允许edit_others_posts
更改帖子作者。参见https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/class-wp-posts-list-table.php第1483行。