Skip to content

Instantly share code, notes, and snippets.

@greg-randall
Created June 12, 2024 18:50
Show Gist options
  • Save greg-randall/ed0d79c695165637606734147c212f07 to your computer and use it in GitHub Desktop.
Save greg-randall/ed0d79c695165637606734147c212f07 to your computer and use it in GitHub Desktop.
WordPress plugin to limit editing of pages and their children to certain user roles.
<?php
/**
* Plugin Name: Role-Based Page Editor Limitations
* Description: This plugin restricts editing capabilities of specific pages to certain user roles. It dynamically creates roles if they don't exist and assigns them editor capabilities. It then checks if a user with a specific role is trying to edit a page that they're not assigned to, and if so, it removes their editing capabilities for that page. Edit the $role_page_map array to specify which roles can edit which pages.
* Version: 1
* Author: Greg R.
*/
/* For example you want to make it so that some peolple at your company can edit /subpage/ and all the children under that page, so you can create a user role that restricts them to jus that section of the site. */
global $role_page_map;
// user role as key and page path as value
// note that the page and any children (and childrens children etc) of the page will be editable by the user with the role
$role_page_map = array(
'subpage_editor' => 'subpage'
);
// Loop over the role-page map
foreach ($role_page_map as $role => $page_path) {
// If the role doesn't exist
if (!get_role($role)) {
// Get the capabilities of the editor role
$editor_capabilities = get_role('editor')->capabilities;
// Create a friendly name for the role
$friendly_name = ucwords(str_replace('_', ' ', $role));
// Add the new role with the capabilities of the editor role
add_role($role, $friendly_name, $editor_capabilities);
}
}
function role_based_edit_map_meta_cap($caps, $cap, $user_id, $args) {
global $role_page_map;
// If we're checking the 'edit_post' or 'edit_page' capability
if ('edit_post' === $cap || 'edit_page' === $cap) {
// Get the post
$post = get_post($args[0]);
// Get the user
$user = get_userdata($user_id);
// Check each role in the role-page map
foreach ($role_page_map as $role => $page_path) {
// If the user has the current role
if (in_array($role, $user->roles)) {
// Get the ID of the page for this role
$page_id = get_page_by_path($page_path)->ID;
// Check if the post is a descendant of the page
$is_descendant = false;
$parent_id = $post->post_parent;
while ($parent_id != 0) {
if ($parent_id == $page_id) {
$is_descendant = true;
break;
}
$parent_post = get_post($parent_id);
$parent_id = $parent_post->post_parent;
}
// If the post is not the page or a descendant of the page
if ($post->ID != $page_id && !$is_descendant) {
// Remove the 'edit_post' or 'edit_page' capability
$caps[] = 'do_not_allow';
}
}
}
}
return $caps;
}
add_filter('map_meta_cap', 'role_based_edit_map_meta_cap', 10, 4);
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment