admin管理员组文章数量:1404923
I would want to allow certain user to edit only one page and it's subpages. How would this be possible? I tried the old Role Scoper, but it seems to have a lot of problems and bugs.
I would want to allow certain user to edit only one page and it's subpages. How would this be possible? I tried the old Role Scoper, but it seems to have a lot of problems and bugs.
Share Improve this question edited Jun 16, 2015 at 14:41 s_ha_dum 65.6k13 gold badges84 silver badges174 bronze badges asked Jun 16, 2015 at 14:15 nafnaf 2731 gold badge2 silver badges4 bronze badges 1- 2 I removed your request for a plugin recommendation as that made the question off-topic. Yes, this should be possible with a plugin but when I see attempts to do things that require this kind of hacking of basic functionality I can't help but think that you are taking the wrong approach. Can you explain the project in more detail? – s_ha_dum Commented Jun 16, 2015 at 14:44
4 Answers
Reset to default 17 +100The first thing to do to implements such task is to be able to recognise which page an user can edit.
There are different ways to do it. It could be a user meta, some configuration value... For the sake of this answer, I will assume that a function lile this exists:
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...
}
Now that we have a way to determine if an user can edit a page we just need to tell WordPress to use this function to check useer capability to edit a page.
That can be done via 'map_meta_cap'
filter.
Something like:
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 );
At this point, we need only a way to connect an user to one or more pages.
There might be different solutions depending on use case.
A flexible solution could be to add a dropdown of "root" pages (see wp_dropdown_pages
) to the edit user admin screen, and save selected page(s) as user meta.
We could leverage 'edit_user_profile'
to add the pages dropdown field and 'edit_user_profile_update'
to store the selected value as user meta.
I am sure that in this website there's enough guidance on how to that in detail.
When page(s) are stored as user meta, the wpse_user_can_edit()
function from above can be finished by checking if the page id is part of the user meta value.
Removing capability to edit the page, WordPress will do the rest: will remove any edit link from backend and frontend, will prevent direct access... and so on.
It does take a small amount of code to implement this feature, even if you use a PHP class to avoid global variables. I also didn't want to hide the prohibited pages for the user in the Dashboard. What if they added content that was already on the 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;
}
}
What the code above does is prevent the following from working or appearing as needed:
get_edit_post_link
Edit Page
link on the WP Admin Bar that appears for the PagesEdit
,Quick Edit
, andTrash
quick links that appear underneath the Pages in/wp-admin/edit.php?post_type=page
This worked on my local WordPress 4.7 install. Assuming that the pages on the site won't change often, it might be better to hardcode the IDs of the page and its sub-pages, and remove the WP_Query
inside the __construct
method. This will save a lot on database calls.
If you wanted to keep away from plugins, you could a variation of the code below in a functions.php file or a custom plugin.
There are 2 seperate parts to this code, You would only need to use 1 of them, but which one depends on the complexity of the requirements.
Part 1 is specifying a single user and restricting them to a specific post.
Part 2 allows you to create a map of users and post ID's and allows multiple posts
The code below is for a page only, but if you wanted to change that to a post, or a custom post type, you would need to change the string in $screen->id == 'page'
to something else.
You can find a reference to the screen ID's around wp-admin here
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' );
I used User Role Editor
a couple of times and is pretty good.
Maybe it could help you too.
Here is the link User Role Editor
本文标签: Allowing user to edit only certain pages
版权声明:本文标题:Allowing user to edit only certain pages 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744876736a2629958.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论