I'm trying to write a simple permission admin page plugin.
So far I made a page with every role where I can check a certain menu page to be disabled from menu. I simply get global $menu
and save to option encoded to JSON array.
Example:
array(2) {
["sub_administrator"]=>
array(11) {
[0]=>
string(10) "menu-posts"
[1]=>
string(19) "toplevel_page_wpcf7"
[2]=>
string(15) "menu-appearance"
[3]=>
string(12) "menu-plugins"
[4]=>
string(10) "menu-tools"
[5]=>
string(13) "menu-settings"
[6]=>
string(32) "toplevel_page_edit?post_type=acf"
[7]=>
string(30) "toplevel_page_bwp_capt_general"
[8]=>
string(40) "toplevel_page_mr_permissions_admin_pages"
[9]=>
string(23) "toplevel_page_Wordfence"
[10]=>
string(28) "toplevel_page_wp-user-avatar"
}
}
Later using admin_menu
hook I remove from display a certain menu item
function mr_permissions_roles_admin_menu_restriction() {
echo'<pre>';
global $menu;
$restricted=array();
$current_user=wp_get_current_user();
$role_restriction=get_option('mr_permissions_roles');
$role_restriction=(array)json_decode($role_restriction);
$role=$current_user->roles[0];
if(!empty($role_restriction[$role]))
{
$restricted=$role_restriction[$role];
}
foreach ( $menu as $item => $data ) {
if ( ! isset( $data[5] ) ) {
continue; // Move along if the current $item doesn't have a slug.
} elseif ( in_array( $data[5], $restricted ) ) {
unset( $menu[$item] ); // Remove the current $item from the $menu.
}
}
echo'</pre>';
}
add_action( 'admin_menu', 'mr_permissions_roles_admin_menu_restriction',20);
That's the easy part here.
Now I want before every admin page to load check if user has plugin permission to go to page (people still can go to page by url).
I made something that works but not everywhere. I explain under code.
function mr_permissions_roles_admin_page_restriction($screen)
{
global $menu;
$current_user=wp_get_current_user();
$role_restriction=get_option('mr_permissions_roles');
$role_restriction=(array)json_decode($role_restriction);
$role=$current_user->roles[0];
if(in_array($screen->base,$role_restriction[$role]))
exit('<!DOCTYPE html> <!-- Ticket #11289, IE bug fix: always pad the error page with enough characters such that it is greater than 512 bytes, even after gzip compression abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono --> <html xmlns="http://www.w3.org/1999/xhtml" lang="pl-PL"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width"> <title>WordPress › Błąd</title> <style type="text/css"> html { background: #f1f1f1; } body { background: #fff; color: #444; font-family: "Open Sans", sans-serif; margin: 2em auto; padding: 1em 2em; max-width: 700px; -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13); box-shadow: 0 1px 3px rgba(0,0,0,0.13); } h1 { border-bottom: 1px solid #dadada; clear: both; color: #666; font: 24px "Open Sans", sans-serif; margin: 30px 0 0 0; padding: 0; padding-bottom: 7px; } #error-page { margin-top: 50px; } #error-page p { font-size: 14px; line-height: 1.5; margin: 25px 0 20px; } #error-page code { font-family: Consolas, Monaco, monospace; } ul li { margin-bottom: 10px; font-size: 14px; } a { color: #0073aa; } a:hover, a:active { color: #00a0d2; } a:focus { color: #124964; -webkit-box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); outline: none; } .button { background: #f7f7f7; border: 1px solid #ccc; color: #555; display: inline-block; text-decoration: none; font-size: 13px; line-height: 26px; height: 28px; margin: 0; padding: 0 10px 1px; cursor: pointer; -webkit-border-radius: 3px; -webkit-appearance: none; border-radius: 3px; white-space: nowrap; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-box-shadow: 0 1px 0 #ccc; box-shadow: 0 1px 0 #ccc; vertical-align: top; } .button.button-large { height: 30px; line-height: 28px; padding: 0 12px 2px; } .button:hover, .button:focus { background: #fafafa; border-color: #999; color: #23282d; } .button:focus { border-color: #5b9dd9; -webkit-box-shadow: 0 0 3px rgba( 0, 115, 170, .8 ); box-shadow: 0 0 3px rgba( 0, 115, 170, .8 ); outline: none; } .button:active { background: #eee; border-color: #999; -webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 ); box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 ); -webkit-transform: translateY(1px); -ms-transform: translateY(1px); transform: translateY(1px); } </style> </head> <body id="error-page"> <p>Nie posiadasz wystarczających uprawnień, by wejść na tę stronę.</p></body> </html> ');
if($current_user->ID!=38)
{
echo '<pre>';
//var_dump($screen);
echo '</pre>';
}
}
add_action('current_screen','mr_permissions_roles_admin_page_restriction');
I found that current_screen
hook. Well hook which I wanted but not exactly. For example to post menu item slug is menu-posts
. In $screen
variable and $menu variable there no single thing I can compare. For custom admin menu pages it works well. $menu slug is in $screen->base so I can compare it. But when it comes to built-in pages it doesn't work. So here are a few questions which may solve my problem.
How to get admin menu item. Then I can save it in a different way and compare differently.
Is there any way I can get more data from
current_screen
.Any other ideas?
(bonus) How can I get submenu pages for example for posts.
global $menu
doesn't have it. I would like to add to my plugin possibility to disable access to submenu pages (a few of them not all for example)
I even tried to look into database for any information but couldn't find anything.
I also made a custom page to edit every user to let them add posts to one or few of my custom_posts. So for default Editor have no right to custom_posts. When I want to make someone who will for example add companies (custom_post) I go to users and I check checkbox and save. From now on this user with role editor can edit companies but others editors can't.