ユーザーが特定のページのみを編集できるようにする


16

特定のユーザーが1ページのみを編集できるようにしたいのですが、そのサブページです。これはどのように可能でしょうか?古いRole Scoperを試しましたが、多くの問題とバグがあるようです。


2
プラグインの推奨のリクエストを削除したため、質問はトピックから外れました。はい、これはプラグインで可能になりますが、この種の基本機能のハッキングを必要とすることをしようとすると、私は仕方がありませんが、間違ったアプローチを取っていると思います。プロジェクトについて詳しく説明していただけますか?
s_ha_dum

回答:


14

このようなタスクを実装するために最初に行うことは、ユーザーが編集できるページを認識できるようにすることです。

さまざまな方法があります。それは、ユーザーメタ、いくつかの設定値である可能性があります...この答えのために、この関数が存在すると仮定します。

function wpse_user_can_edit( $user_id, $page_id ) {

   $page = get_post( $page_id );

   // let's find the topmost page in the hierarchy
   while( $page && (int) $page->parent ) {
     $page = get_post( $page->parent );
   }

   if ( ! $page ) {
     return false;
   }

   // now $page is the top page in the hierarchy
   // how to know if an user can edit it, it's up to you...

}

ユーザーがページを編集できるかどうかを判断する方法ができたので、WordPressにこの機能を使用してページを編集するユーザー機能をチェックするよう指示するだけです。

それは'map_meta_cap'フィルターを介して行うことができます。

何かのようなもの:

add_filter( 'map_meta_cap', function ( $caps, $cap, $user_id, $args ) {

    $to_filter = [ 'edit_post', 'delete_post', 'edit_page', 'delete_page' ];

    // If the capability being filtered isn't of our interest, just return current value
    if ( ! in_array( $cap, $to_filter, true ) ) {
        return $caps;
    }

    // First item in $args array should be page ID
    if ( ! $args || empty( $args[0] ) || ! wpse_user_can_edit( $user_id, $args[0] ) ) {
        // User is not allowed, let's tell that to WP
        return [ 'do_not_allow' ];
    }
    // Otherwise just return current value
    return $caps;

}, 10, 4 );

この時点で、ユーザーを1つ以上のページに接続する方法のみが必要です。

ユースケースに応じて異なるソリューションが存在する場合があります。

柔軟な解決策は、「root」ページのドロップダウン(を参照wp_dropdown_pages)をユーザー管理画面の編集に追加し、選択したページをユーザーメタとして保存することです。

'edit_user_profile'ページドロップダウンフィールドを追加し'edit_user_profile_update'、選択した値をユーザーメタとして保存するために活用できます。

このWebサイトには、その詳細について十分なガイダンスがあると確信しています。

ページがユーザーメタとして保存されているwpse_user_can_edit()場合、ページIDがユーザーメタ値の一部であるかどうかを確認することで、上記の機能を終了できます。

ページを編集する機能を削除すると、WordPressは残りの処理を行います。バックエンドとフロントエンドから編集リンクを削除し、直接アクセスを防ぎます...など。


3
これは私の答えよりもはるかに良い。ユーザーの機能を変更するだけで、WordPressに残りを処理させることができるのに、なぜ編集リンクを制限するのですか?
リコテック

長い「u」は子音で始まる「yu」のように聞こえるので、「an」ではなく「user」という単語の前に「a」を使用する必要があります。
フィリップ

7

PHPクラスを使用してグローバル変数を回避する場合でも、この機能を実装するには少量のコードが必要です。また、ダッシュボードでユーザーの禁止ページを非表示にしたくありませんでした。すでにサイトにあったコンテンツを追加した場合はどうなりますか?

$user_edit_limit = new NS_User_Edit_Limit(
    15,       // User ID we want to limit
    [2, 17]   // Array of parent page IDs user is allowed to edit
                 (also accepts sub-page IDs)
);

class NS_User_Edit_Limit {

    /**
     * Store the ID of the user we want to control, and the
     * posts we will let the user edit.
     */
    private $user_id = 0;
    private $allowed = array();

    public function __construct( $user_id, $allowed ) {

        // Save the ID of the user we want to limit.
        $this->user_id = $user_id;

        // Expand the list of allowed pages to include sub pages
        $all_pages = new WP_Query( array(
            'post_type' => 'page',
            'posts_per_page' => -1,
        ) );            
        foreach ( $allowed as $page ) {
            $this->allowed[] = $page;
            $sub_pages = get_page_children( $page, $all_pages );
            foreach ( $sub_pages as $sub_page ) {
                $this->allowed[] = $sub_page->ID;
            }
        }

        // For the prohibited user...
        // Remove the edit link from the front-end as needed
        add_filter( 'get_edit_post_link', array( $this, 'remove_edit_link' ), 10, 3 );
        add_action( 'admin_bar_menu', array( $this, 'remove_wp_admin_edit_link' ), 10, 1 );
        // Remove the edit link from wp-admin as needed
        add_action( 'page_row_actions', array( $this, 'remove_page_list_edit_link' ), 10, 2 );
    }

    /**
     * Helper functions that check if the current user is the one
     * we want to limit, and check if a specific post is in our
     * list of posts that we allow the user to edit.
     */
    private function is_user_limited() {
        $current_user = wp_get_current_user();
        return ( $current_user->ID == $this->user_id );
    }
    private function is_page_allowed( $post_id ) {
        return in_array( $post_id, $this->allowed );
    }

    /**
     * Removes the edit link from the front-end as needed.
     */
    public function remove_edit_link( $link, $post_id, $test ) {
        /**
         * If...
         * - The limited user is logged in
         * - The page the edit link is being created for is not in the allowed list
         * ...return an empty $link. This also causes edit_post_link() to show nothing.
         *
         * Otherwise, return link as normal.
         */
        if ( $this->is_user_limited() && !$this->is_page_allowed( $post_id ) ) {
            return '';
        }
        return $link;
    }

    /**
     * Removes the edit link from WP Admin Bar
     */
    public function remove_wp_admin_edit_link( $wp_admin_bar ) {
        /**
         *  If:
         *  - We're on a single page
         *  - The limited user is logged in
         *  - The page is not in the allowed list
         *  ...Remove the edit link from the WP Admin Bar
         */
        if ( 
            is_page() &&
            $this->is_user_limited() &&
            !$this->is_page_allowed( get_post()->ID )
        ) {
            $wp_admin_bar->remove_node( 'edit' );
        }
    }

    /**
     * Removes the edit link from WP Admin's edit.php
     */
    public function remove_page_list_edit_link( $actions, $post ) {
        /**
         * If:
         * -The limited user is logged in
         * -The page is not in the allowed list
         * ...Remove the "Edit", "Quick Edit", and "Trash" quick links.
         */
        if ( 
            $this->is_user_limited() &&
            !$this->is_page_allowed( $post->ID )
        ) {
            unset( $actions['edit'] );
            unset( $actions['inline hide-if-no-js']);
            unset( $actions['trash'] );
        }
        return $actions;
    }
}

上記のコードが行うことは、必要に応じて以下が機能したり表示されたりすることを防ぎます。

  1. get_edit_post_link
  2. Edit Page ページに表示されるWP管理バーのリンク
  3. EditQuick Edit、およびTrashページ内の下に表示されるクイックリンク/wp-admin/edit.php?post_type=page

これは、ローカルのWordPress 4.7インストールで機能しました。サイトのページが頻繁に変更されないと仮定すると、ページとそのサブページのIDをハードコーディングしWP_Query__constructメソッド内を削除する方がよい場合があります。これにより、データベース呼び出しが大幅に節約されます。


@Benの場合よりも完全な答えを得るために+1を使用しますが、リンクを処理する正しい方法は、機能を操作することです。
Mark Kaplun

ええ、gmazzapの答えを見たとき、「なぜ今、私はそれを考えなかったのか?」
リコテク

5

プラグインを避けたい場合は、functions.phpファイルまたはカスタムプラグインで以下のコードのバリエーションを作成できます。

このコードには2つの独立した部分があり、そのうちの1つだけを使用する必要がありますが、どれが要件の複雑さに依存します。

パート1では、1人のユーザーを指定し、特定の投稿に制限しています。

パート2では、ユーザーと投稿IDのマップを作成し、複数の投稿を許可します

以下のコードはページ専用ですが、それを投稿またはカスタム投稿タイプに変更する場合は、文字列を$screen->id == 'page'別のものに変更する必要があります。

ここで、wp-adminの周りのスクリーンIDへの参照を見つけることができます。

function my_pre_get_posts( $query ){

    $screen = get_current_screen();
    $current_user = wp_get_current_user();

    /**
     * Specify a single user and restrict to a single page
     */
    $restricted_user_id = 10; //User ID of the restricted user
    $allowed_post_id = 1234; //Post ID of the allowed post

    $current_post_id = isset( $_GET['post'] ) ? (int)$_GET['post'] : false ;

    //Only affecting a specific user
    if( $current_user->ID !== $restricted_user_id ){
        return;
    }

    //Only Affecting EDIT page.
    if( ! $current_post_id ){
        return;
    }

    if( $screen->id == 'page' && $current_post_id !== $allowed_post_id ){
        wp_redirect( admin_url( ) );
        exit;
    }

    /**
     * Specify a map of user_id => $allowed_posts
     */
    $restrictions_map = [
        10 => [ 123 ], //Allow user ID to edit Page ID 123
        11 => [ 152, 186 ] //Allow user ID to edit Page ID 123 and 186
    ];

    if( array_key_exists( $current_user->ID, $restrictions_map ) ){

        $allowed_posts = $restrictions_map[$current_user->ID];

        if( $screen->id == 'page' && ! in_array( $current_user->ID, $allowed_posts ) ){
            wp_redirect( admin_url( ) );
            exit;
        }

    }

}
add_action( 'pre_get_posts', 'my_pre_get_posts' );

1
1それはコア機能を行うために働くことができますが、これはまだページも悪いUIを作ることができない編集、それらのユーザに出力されている編集へのリンクを残して
マーク・Kaplun

-4

User Role Editorは数回使用し、かなり良いです。たぶんあなたにも役立つかもしれません。リンクはユーザーロールエディターです


確かなプラグインのようですが、特定のページを編集するようにユーザーを制限する方法を見つけることができません。
naf

この方法で制限したいユーザーを作成者レベルのユーザーにする作成者ユーザーレベルに機能「edit_pages」を追加します(ユーザーロールエディターを使用)ページの作成者を編集権限を付与するユーザーに設定します。edit_pagesの機能が与えられた作成者レベルのユーザーは、ダッシュボードのページのリストを表示できますが、作成者であるページを除いて編集するオプションはありません。
user2319361

4
おかげで、ある程度は機能します。ある時点で、特定のページを変更するために複数のユーザーを制限する必要がある場合があるため、ページに複数の作成者を設定する方法が必要になります。
naf

ユーザーを特定のページに制限するには、Proバージョンを購入する必要があります。私は同じものを探していて、それを見つけました。wordpress.stackexchange.com/questions/191658/...
リカルド・アンドレス・

1
現在、その特定のプラグインは堅実なものですが、プラグインが提供するすべてのオプションを探すよりも、それを行うためのコードを記述する方がおそらく簡単です。(OPが求めることさえできるようになる場合)
マークカプルン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.