Я хотел бы разрешить определенному пользователю редактировать только одну страницу и ее подстраницы. Как это было бы возможно? Я попробовал старый Role Scoper, но, похоже, у него много проблем и ошибок.
Я хотел бы разрешить определенному пользователю редактировать только одну страницу и ее подстраницы. Как это было бы возможно? Я попробовал старый Role Scoper, но, похоже, у него много проблем и ошибок.
Ответы:
Первое, что нужно сделать для реализации такой задачи, - это определить, какую страницу пользователь может редактировать.
Есть разные способы сделать это. Это может быть пользовательская мета, какое-то значение конфигурации ... Ради этого ответа я буду предполагать, что эта функция существует:
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 );
На данный момент нам нужен только способ подключения пользователя к одной или нескольким страницам.
В зависимости от варианта использования могут быть разные решения.
Гибким решением может быть добавление выпадающего списка «корневых» страниц (см. wp_dropdown_pages
) На экран редактирования пользовательского администратора и сохранение выбранных страниц в качестве пользовательских мета.
Мы могли бы использовать, 'edit_user_profile'
чтобы добавить раскрывающееся поле страниц и'edit_user_profile_update'
сохранить выбранное значение в качестве пользовательской мета.
Я уверен, что на этом сайте достаточно указаний, как это сделать в деталях.
Когда страницы сохранены как пользовательские мета, wpse_user_can_edit()
вышеуказанную функцию можно завершить, проверив, является ли идентификатор страницы частью пользовательского мета-значения.
Удаляя возможность редактировать страницу, WordPress сделает все остальное: удалит любую ссылку для редактирования из бэкэнда и внешнего интерфейса, запретит прямой доступ ... и так далее.
Для реализации этой функции требуется небольшой объем кода, даже если вы используете класс 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;
}
}
Код, приведенный выше, предотвращает работу или появление следующего:
get_edit_post_link
Edit Page
ссылка на панели администратора WP, которая появляется для страницEdit
, Quick Edit
И Trash
быстрые ссылки , которые появляются под страницу в/wp-admin/edit.php?post_type=page
Это работало на моей локальной установке WordPress 4.7. Предполагая, что страницы на сайте не будут часто меняться, возможно, было бы лучше жестко закодировать идентификаторы страницы и ее подстраниц и удалить WP_Query
изнутри __construct
метод. Это значительно сэкономит на вызовах базы данных.
Если вы хотите держаться подальше от плагинов, вы можете изменить приведенный ниже код в файле functions.php или в пользовательском плагине.
Этот код состоит из 2 отдельных частей, вам нужно будет использовать только одну из них, но какая из них зависит от сложности требований.
Часть 1 указывает отдельного пользователя и ограничивает его определенным постом.
Часть 2 позволяет создавать карту пользователей и идентификаторы сообщений, а также позволяет создавать несколько сообщений.
Приведенный ниже код предназначен только для страницы, но если вы хотите изменить это на сообщение или пользовательский тип сообщения, вам нужно изменить строку $screen->id == 'page'
на что-то другое.
Вы можете найти ссылку на идентификатор экрана вокруг wp-admin здесь
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' );
Я использовал User Role Editor
пару раз, и это довольно хорошо. Может быть, это может помочь вам тоже. Вот ссылка Редактор ролей пользователей