Permitindo que o usuário edite apenas determinadas páginas


16

Eu gostaria de permitir que determinado usuário edite apenas uma página e suas subpáginas. Como isso seria possível? Eu tentei o antigo Role Scoper, mas parece ter muitos problemas e bugs.


2
Eu removi sua solicitação de recomendação de plug-in, pois isso tornava a questão fora de tópico. Sim, isso deve ser possível com um plug-in, mas quando vejo tentativas de fazer coisas que exijam esse tipo de invasão da funcionalidade básica, não posso deixar de pensar que você está adotando a abordagem errada. Você pode explicar o projeto com mais detalhes?
s_ha_dum

Respostas:


14

A primeira coisa a fazer para implementar essa tarefa é ser capaz de reconhecer qual página um usuário pode editar.

Existem diferentes maneiras de fazer isso. Poderia ser uma meta do usuário, algum valor de configuração ... Por uma questão de resposta, assumirei que existe uma função nesse estilo:

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...

}

Agora que temos uma maneira de determinar se um usuário pode editar uma página, precisamos dizer ao WordPress para usar essa função para verificar a capacidade do usuário de editar uma página.

Isso pode ser feito via 'map_meta_cap'filtro.

Algo como:

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 );

Neste ponto, precisamos apenas de uma maneira de conectar um usuário a uma ou mais páginas.

Pode haver soluções diferentes, dependendo do caso de uso.

Uma solução flexível poderia ser adicionar uma lista suspensa de páginas "raiz" (consulte wp_dropdown_pages) à tela de edição do administrador do usuário e salvar as páginas selecionadas como meta do usuário.

Poderíamos aproveitar 'edit_user_profile'para adicionar o campo suspenso de páginas e 'edit_user_profile_update'armazenar o valor selecionado como meta do usuário.

Estou certo de que neste site há orientações suficientes sobre como fazer isso em detalhes.

Quando as páginas são armazenadas como meta do usuário, a wpse_user_can_edit()função acima pode ser concluída verificando se o ID da página faz parte do valor da meta do usuário.

Removendo a capacidade de editar a página, o WordPress fará o resto: removerá qualquer link de edição do back-end e do front-end, impedirá o acesso direto ... e assim por diante.


3
Isso é muito melhor que a minha resposta. Por que limitar os links de edição quando você pode apenas modificar a capacidade do usuário e deixar o WordPress cuidar do resto?
Ricotheque 19/03

você deve usar "a" antes da palavra "usuário" e não "an" porque um "u" longo soa como "yu", que começa com uma consoante.
Philip

7

É preciso uma pequena quantidade de código para implementar esse recurso, mesmo se você usar uma classe PHP para evitar variáveis ​​globais. Também não queria ocultar as páginas proibidas para o usuário no painel. E se eles adicionassem conteúdo que já estava no site?

$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;
    }
}

O que o código acima faz é impedir que o seguinte funcione ou apareça conforme necessário:

  1. get_edit_post_link
  2. Edit Page link na barra de administração do WP que aparece nas páginas
  3. Edit, Quick EditE Trashlinks rápidos que aparecem debaixo das Páginas na/wp-admin/edit.php?post_type=page

Isso funcionou na minha instalação local do WordPress 4.7. Supondo que as páginas do site não sejam alteradas com frequência, talvez seja melhor codificar os IDs da página e de suas subpáginas e remover o WP_Queryinterior do __constructmétodo. Isso economizará muito em chamadas ao banco de dados.


+1 para a resposta mais completa do que @ Ben, mas a maneira correta de lidar com as ligações é através da manipulação das capacidades,
Mark Kaplun

Sim, quando vi a resposta do gmazzap, acabei pensando "Agora, por que não pensei nisso?"
Ricotheque 19/03/19

5

Se você quiser se manter afastado dos plug-ins, poderá fazer uma variação do código abaixo em um arquivo functions.php ou em um plug-in personalizado.

Existem duas partes separadas nesse código. Você só precisa usar 1 delas, mas qual delas depende da complexidade dos requisitos.

A Parte 1 está especificando um único usuário e restringindo-o a uma postagem específica.

A parte 2 permite criar um mapa de usuários e IDs de postagem e permite várias postagens

O código abaixo é apenas para uma página, mas se você quiser alterar isso para uma postagem ou um tipo de postagem personalizado, será necessário alterar a sequência $screen->id == 'page'para outra coisa.

Você pode encontrar uma referência aos IDs da tela em torno de wp-admin aqui

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 como ele pode trabalhar para fazer a funcionalidade básica, mas isso ainda deixa os links para editar as páginas estão a ser enviados até mesmo para usuários que não pode editar os que faz uma má UI
Mark Kaplun

-4

Eu usei User Role Editoralgumas vezes e é muito bom. Talvez isso possa ajudá-lo também. Aqui está o link Editor de Função de Usuário


Parece ser um plugin sólido, mas não consigo encontrar uma maneira de restringir um usuário para editar páginas específicas.
NaF

Torne os usuários que você deseja limitar dessa maneira usuários no nível do autor Adicione o recurso "edit_pages" ao nível do usuário do autor (usando o Editor de Função do Usuário) Defina o autor de uma página para o usuário que você deseja conceder o privilégio de editá-la. Um usuário no nível do autor, com o recurso de edit_pages, pode ver a lista de páginas no painel, mas não tem a opção de editar, exceto as páginas das quais é o autor.
user2319361

4
Obrigado, isso funciona até certo ponto. Em algum momento, talvez seja necessário restringir vários usuários para modificar uma página específica; portanto, haveria uma maneira de definir vários autores para uma página.
NaF

Para restringir os usuários a páginas específicas, você precisará adquirir o Pro versoin. Estou procurando a mesma coisa e descobri isso. wordpress.stackexchange.com/questions/191658/…
Ricardo Andres

1
embora esse plug-in específico seja uma coisa sólida no momento, provavelmente é mais fácil escrever código para fazê-lo do que percorrer todas as opções que o plug-in oferece. (se ele ainda permite que você fazer o que o OP pede)
Mark Kaplun
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.