Permitir al usuario editar solo ciertas páginas


16

Me gustaría permitir que cierto usuario edite solo una página y sus subpáginas. ¿Cómo sería esto posible? Probé el viejo Role Scoper, pero parece tener muchos problemas y errores.


2
Eliminé su solicitud de una recomendación de complemento ya que eso hizo que la pregunta fuera de tema. Sí, esto debería ser posible con un complemento, pero cuando veo intentos de hacer cosas que requieren este tipo de pirateo de la funcionalidad básica, no puedo evitar pensar que estás tomando el enfoque equivocado. ¿Puedes explicar el proyecto con más detalle?
s_ha_dum

Respuestas:


14

Lo primero que debe hacer para implementar dicha tarea es poder reconocer qué página puede editar un usuario.

Hay diferentes formas de hacerlo. Podría ser un meta del usuario, algún valor de configuración ... En aras de esta respuesta, supondré que existe una función lile:

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

}

Ahora que tenemos una manera de determinar si un usuario puede editar una página, solo necesitamos decirle a WordPress que use esta función para verificar la capacidad del usuario para editar una página.

Eso se puede hacer a través del '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 );

En este punto, solo necesitamos una forma de conectar a un usuario a una o más páginas.

Puede haber diferentes soluciones según el caso de uso.

Una solución flexible podría ser agregar un menú desplegable de páginas "raíz" (ver wp_dropdown_pages) a la pantalla de edición del administrador del usuario y guardar las páginas seleccionadas como meta del usuario.

Podríamos aprovechar 'edit_user_profile'para agregar el campo desplegable de páginas y 'edit_user_profile_update'almacenar el valor seleccionado como meta del usuario.

Estoy seguro de que en este sitio web hay suficiente orientación sobre cómo hacerlo en detalle.

Cuando las páginas se almacenan como meta del usuario, la wpse_user_can_edit()función de arriba se puede finalizar verificando si la identificación de la página es parte del meta valor del usuario.

Al eliminar la capacidad de editar la página, WordPress hará el resto: eliminará cualquier enlace de edición del backend y la interfaz, evitará el acceso directo ... y así sucesivamente.


3
Esto es mucho mejor que mi respuesta. ¿Por qué limitar los enlaces de edición cuando solo puede modificar la capacidad del usuario y dejar que WordPress se encargue del resto?
ricotheque

debe usar "a" antes de la palabra "usuario" no "an" porque una "u" larga suena como "yu" que comienza con una consonante.
Philip

7

Se necesita una pequeña cantidad de código para implementar esta característica, incluso si usa una clase PHP para evitar variables globales. Tampoco quería ocultar las páginas prohibidas para el usuario en el Panel. ¿Qué pasa si agregaron contenido que ya estaba en el sitio?

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

Lo que hace el código anterior es evitar que lo siguiente funcione o aparezca según sea necesario:

  1. get_edit_post_link
  2. Edit Page enlace en la barra de administración de WP que aparece para las páginas
  3. Edit, Quick Edity Trashenlaces rápidos que aparecen debajo de las páginas en/wp-admin/edit.php?post_type=page

Esto funcionó en mi instalación local de WordPress 4.7. Suponiendo que las páginas en el sitio no cambien a menudo, podría ser mejor codificar los ID de la página y sus subpáginas, y eliminar el WP_Queryinterior del __constructmétodo. Esto ahorrará mucho en llamadas a la base de datos.


+1 para la respuesta más completa que @ Ben's, pero la forma correcta de manejar los enlaces es manipulando las capacidades,
Mark Kaplun

Sí, cuando vi la respuesta de gmazzap terminé pensando "Ahora, ¿por qué no pensé en eso?"
ricotheque

5

Si desea mantenerse alejado de los complementos, puede realizar una variación del código a continuación en un archivo functions.php o un complemento personalizado.

Hay 2 partes separadas para este código, solo necesitaría usar 1 de ellas, pero cuál depende de la complejidad de los requisitos.

La Parte 1 es especificar un solo usuario y restringirlo a una publicación específica.

La Parte 2 le permite crear un mapa de usuarios e ID de publicaciones y permite múltiples publicaciones

El código a continuación es solo para una página, pero si desea cambiar eso a una publicación, o un tipo de publicación personalizada, necesitaría cambiar la cadena $screen->id == 'page'a otra.

Puede encontrar una referencia a los ID de pantalla en wp-admin aquí

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 ya que puede funcionar para hacer la funcionalidad principal, pero esto todavía deja los enlaces para editar las páginas que se envían incluso a los usuarios que no pueden editarlas, lo que hace una mala interfaz de usuario
Mark Kaplun

-4

Utilicé User Role Editorun par de veces y es bastante bueno. Quizás también te pueda ayudar. Aquí está el enlace Editor de roles de usuario


Parece ser un complemento sólido, pero no puedo encontrar una manera de restringir a un usuario para editar páginas específicas.
naf

Haga que los usuarios que desea limitar de esta manera usuarios a nivel de autor Agregue la capacidad "editar_páginas" al nivel de usuario autor (usando el Editor de roles de usuario) Establezca el autor de una página para el usuario al que desea otorgar el privilegio de editarla. Un usuario de nivel de autor con la capacidad de editar páginas puede ver la lista de páginas en el panel, pero no tiene la opción de editar, excepto las páginas de las que es autor.
user2319361

44
Gracias, eso funciona hasta cierto punto. En algún momento, podría tener que restringir a varios usuarios para modificar una página específica, por lo que tendría que haber una manera de establecer múltiples autores en una página.
naf

Para restringir a los usuarios a páginas específicas, deberá comprar la versión Pro. Estoy buscando lo mismo y lo descubrí. wordpress.stackexchange.com/questions/191658/…
Ricardo Andres

1
Si bien ese complemento específico es una cosa sólida en este momento, probablemente sea más fácil escribir código para hacerlo que leer todas las opciones que ofrece el complemento. (si incluso te permite hacer lo que el OP te pide)
Mark Kaplun
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.