Я хотів би дозволити певному користувачеві редагувати лише одну сторінку та це підсторінки. Як це було б можливо? Я спробував старого ролевого Scoper, але, схоже, є багато проблем і помилок.
Я хотів би дозволити певному користувачеві редагувати лише одну сторінку та це підсторінки. Як це було б можливо? Я спробував старого ролевого Scoper, але, схоже, є багато проблем і помилок.
Відповіді:
Перше, що потрібно зробити для реалізації такого завдання - це вміти розпізнавати, яку сторінку може редагувати користувач.
Існують різні способи зробити це. Це може бути мета користувача, якесь значення конфігурації ... Заради цієї відповіді я вважаю, що функція 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...
}
Тепер, коли у нас є спосіб визначити, чи може користувач редагувати сторінку, нам просто потрібно сказати 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
. Це дозволить значно заощадити на дзвінках до бази даних.
Якщо ви хочете триматися подалі від плагінів, ви можете змінити код нижче у файлі function.php або користувацькому плагіні.
У цьому коді є дві окремі частини, вам потрібно буде використовувати лише 1 з них, але яка залежить від складності вимог.
Частина 1 вказує одного користувача та обмежує їх конкретною публікацією.
Частина 2 дозволяє створити карту користувачів та ідентифікаторів публікацій та дозволяє декілька публікацій
Код, наведений нижче, призначений лише для сторінки, але якщо ви хочете змінити його на публікацію або на спеціальний тип публікації, вам потрібно буде змінити рядок $screen->id == 'page'
на щось інше.
Ви можете знайти посилання на екран Ідентифікатор навколо Wp-адміністратора тут
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
пару разів і досить непогано. Можливо, це теж могло б вам допомогти. Ось посилання редактора ролей користувача