canedit_others_posts
というエディタをいくつか追加したいのですが、publishothersの投稿を許可したくない、saveだけにします。 レビュー用に送信 ボタンをクリックして投稿します。
これどうやってするの?
編集:これを詳細に説明する。現在のところ、ユーザーにonlyによる投稿の編集による他の投稿の編集を許可することはできません。ユーザに対してedit_others_post
が有効になっている場合は、publish投稿できます。
私が目指しているワークフロー
私がよく理解しているならば、あなたのサイトで特別な役割を持っているユーザーは以下をするべきです:
もしそうなら、それは私には '作者'より '編集者'に似た役割のようです。
作者との違いはそれだけです
最初に提案できるのは、ロール 'author'を出発点として使用し、3つの不要なキャップを削除し、カスタムのロールを追加するという単純なクラスで、カスタムロールを作成することです。
class CustomEditorRole {
private static $role = 'authorplus';
private $role_label;
function __construct() {
// here we need a real, loaded, text domain
$this->role_label = __( 'Author +', 'yout-txt-dmn' );
}
function addRole() {
global $wp_roles;
if ( ! $wp_roles instanceof WP_Roles ) {
$wp_roles = new WP_Roles;
}
$author = get_role( 'author' );
$caps = $author->capabilities; // start with author capabilities
$caps['publish_posts'] = FALSE;
$caps['edit_published_posts'] = FALSE;
$caps['delete_published_posts'] = FALSE;
$caps['edit_others_pending_posts'] = TRUE; // custom cap
// create new role with custom caps
add_role( self::$role, $this->role_label, $caps );
}
function removeRole() {
global $wp_roles;
if ( ! $wp_roles instanceof WP_Roles ) {
$wp_roles = new WP_Roles;
}
remove_role(self::$role);
}
}
プラグインの有効化/無効化に対するアクションを追加しましょう。
register_activation_hook( __FILE__, array( new CustomEditorRole, 'addRole' ) );
register_deactivation_hook( __FILE__, array( new CustomEditorRole, 'removeRole' ) );
ここで私は以前のコードがメインプラグインファイルにあると仮定します。
上記で設定した機能は、投稿の投稿者や投稿のステータスに関係なく、すべての投稿に対して有効です。これで、カスタムロールを持つユーザーに保留中の他の投稿の編集を許可する必要があります。
私たちが遭遇する最初の問題は、投稿リスト画面(edit.php
)で、機能edit_others_posts
がそのユーザーに対して有効になっていない(そして私たちのカスタムロールでは無効になっている)場合、他のユーザーによる投稿はリストに表示されないことです。クエリから除外され、クエリが発生したときには投稿データにアクセスできないため、少なくともクエリが実行されるまで、投稿ステータスに関係なく機能を割り当てる必要があります。
2つ目の問題は、保存時に、カスタムロールを持つユーザーにedit_others_posts
キャップを付与する前に、現在のステータスが「保留」であることだけでなく、ユーザーがそれを変更しようとしていないことも確認する必要があることです。それは$_POST
データ内の情報を見ることで行うことができます。 2つの "ルーチン"が必要です。1つは管理画面(edit.php
とpost.php
)で実行され、もう1つはポストセーブ中に実行されます。
保留中の投稿に対してのみedit_others_post
機能をカスタムロールユーザーに付与する方法は、'user_has_cap'
にフィルタを追加することです。
フィルタコールバックの内側に、このワークフローを実装できます。
'edit-post'
または'edit-others-posts'
、管理者であるかどうか、ユーザーがカスタム機能を持っているかどうかを確認します)。それ以外の場合は何もしない、つまり元の機能を返す保存時のルーチン:
'edit-others-posts'
機能をユーザーに割り当てます('edit-post'
は自動的にマッピングされます)。保存しないときのルーチン:
'edit-others-posts'
の場合、投稿データはありませんので、主クエリが実行される前で、edit.php
画面上でのみ割り当てます。'edit-post'
の場合は投稿データを取得し、投稿が保留中の場合は'edit-others-posts'
キャップを割り当てます('edit-post'
は自動的にマッピングされます)最後にやることがあります。説明されているワークフローのカスタムロールを使用すると、編集可能であっても、保留中の他の投稿をプレビューすることはできません。
ケーパビリティを再度フィルタリングすることもできますが、もっと簡単な方法があります。メインクエリの間に(WP_Query
によって起動される多数のフックのうちの1つを使用)、 $wp_post_statuses['pending']
object を取り、public
プロパティを現在のユーザーがカスタムロールを持っている場合はtrueです。唯一の効果は、保留中の投稿がプレビュー可能であり、機能を変更しなくても安全を維持できることです。
それでは、コード内の単語を翻訳するだけです。
class CustomEditorCaps {
function manageCaps( $allcaps, $caps, $args, $user ) {
if ( ! $this->shouldManage( $args[0], $user ) ) {
return $allcaps;
}
// Are we saving?
$action = filter_input( INPUT_POST, 'action', FILTER_SANITIZE_STRING );
$method = strtoupper(filter_var($_SERVER['REQUEST_METHOD'], FILTER_SANITIZE_STRING ));
if ( $method !== 'POST' ) { // not saving
global $pagenow;
// we are interested only on post list and post edit screens
if (
is_admin()
&& in_array( $pagenow, array( 'post.php', 'post-new.php', 'edit.php' ), TRUE
) ) {
$screen_id = $pagenow === 'edit.php' ? 'edit-post' : 'post';
$allcaps = $this->maybeAllow( $args, $allcaps, $user, $screen_id );
}
} elseif ( $action === 'editpost' ) { // saving and right action
$allcaps = $this->maybeAllowOnSave( $args, $allcaps, $user );
}
return $allcaps; // always return: it's a filter
}
function lockPendingStatus( $data, $postarr ) {
if (
isset( $postarr['ID'] )
&& ! empty($postarr['ID'])
&& $data['post_type'] === 'post' // 'post' post type
&& $data['post_status'] !== 'pending' // a non pending status
&& ! current_user_can( 'delete_others_posts' ) // current user is not an admin
) {
$orig = get_post_status( $postarr['ID'] );
if ( $orig === 'pending' ) { // hey post was pending!
$data['post_status'] = 'pending'; // let's restore pending status
}
}
return $data; // always return: it's a filter
}
function allowPreview( $posts, $query ) {
if ( is_admin()
|| ! $query->is_main_query()
|| empty( $posts )
|| ! $query->is_single
|| $posts[0]->post_type !== 'post'
) {
return $posts; // return first argument: it's a filter
}
$status = get_post_status( $posts[0] );
$post_status_obj = get_post_status_object( $status );
if (
! $post_status_obj->public
&& $status === 'pending'
&& current_user_can('edit_others_pending_posts')
) {
// post is pending and our user has our special role
// allow preview
global $wp_post_statuses;
$wp_post_statuses[$status]->public = TRUE;
}
return $posts; // return first argument: it's a filter
}
private function maybeAllow( $args, $allcaps, $user, $screen ) {
if ( $args[0] === 'edit_others_posts' ) {
// if filtering 'edit_others_posts' we have no access to single post data
// allow cap only on post list screen and before querying posts
$allcaps['edit_others_posts'] = ! did_action('pre_get_posts')
&& $screen === 'edit-post';
return $allcaps;
}
$post = get_post( $args[2] );
if ( $post->post_status === 'pending' ) {
$allcaps['edit_others_posts'] = TRUE;
}
return $allcaps; // always return: it's a filter
}
private function maybeAllowOnSave( $args, $allcaps, $user ) {
$data = $this->getPostedData();
if ( $data['post_type'] !== 'post' || (int) $data['post_ID'] <= 0 ) {
return $allcaps;
}
$post = get_post( $data['post_ID'] );
if (
$post->post_status === 'pending'
&& $data['original_post_status'] === 'pending'
&& ( empty( $data['post_status'] ) || $data['post_status'] === 'pending' )
) {
// if post is pending and will stay pending allow editing
$allcaps['edit_others_posts'] = true;
}
return $allcaps;
}
private function shouldManage( $cap, $user ) {
return is_admin() // not affect frontend
&& in_array( $cap, array( 'edit_others_posts', 'edit_post' ), TRUE )
&& ! $user->has_cap( 'delete_others_posts' ) // real editor or more
&& $user->has_cap( 'edit_others_pending_posts' ) // our role
&& ! defined( 'DOING_AJAX' ); // does not affect ajax
}
private function getPostedData() {
return filter_input_array( INPUT_POST, array(
'post_type' => FILTER_SANITIZE_STRING,
'post_ID' => FILTER_SANITIZE_NUMBER_INT,
'original_post_status' => FILTER_SANITIZE_STRING,
'post_status' => FILTER_SANITIZE_STRING,
) );
}
}
2つの関連するフックを追加します。1つは'user_has_cap'
をフィルタリングするためのもの、もう1つは管理者または実際の編集者のみ保留中のステータスを変更できるようにするためのもの、最後のフィルタリングはプレビューを許可する'posts_results'
です。
$cap_manager = new CustomEditorCaps;
add_filter( 'user_has_cap', array( $cap_manager, 'manageCaps' ), PHP_INT_MAX, 4 );
add_filter( 'posts_results', array( $cap_manager, 'allowPreview' ), 10, 2 );
add_filter( 'wp_insert_post_data', array( $cap_manager, 'lockPendingStatus' ), 10, 2 );
このコードをすべてプラグインに入れてアクティブにしたら、プラグインが作成したカスタムロールをユーザーに割り当てるだけで済みます。
要旨 ここ の中で、プラグインとして利用可能なすべてのコード。