How could I make particular role access widgets administration menu (wp-admin/widgets.php), but not access other theme administration menu elements.
I have got that far as to display Appearance menu linking to widgets.php by binding to _admin_menu event and modifying global variable $submenu. Although that clearly does not work, as I see this code in wp-admin/widgets.php itself:
if ( ! current_user_can('edit_theme_options') )
wp_die( __( 'Cheatin’ uh?' ));
It is clear – you SHALL NOT be allowed to access this page, unless you clearly have edit_theme_options capability. But what to do, if I do not want other elements of this capability, apart of widgets, modifiable by current user (role)?
It is easy to “hide” other options from menu. But that leaves user, who knows how WP works (understands addressing, at least), free to access them and that I would clearly like to avoid.
Thanks for any help in advance.
Confirming…
Yes, there’s currently (WP 3.4.1) no way to modify the access arguments for admin menu pages. The only one, that you can modify through the public wp API is the »Comments« menu item. All others are registered by hand.
But there’s help coming from @scribu (read more at the trac ticket) who has so far taken a lot of effort to bring something more useful to core.
Explanation
When look deeper into core, then you’ll see the function
wp_widgets_add_menu()
inside~/wp-includes/functions.php
. This one basically does add the submenu item since WP 2.2…This function gets added to the
_admin_menu
action by thewp_maybe_load_widgets()
function.Intermediate work around for the menu item & widgets page
Currently the function, that loads the default widgets and registers the sub menu item (namely
wp_maybe_load_widgets
) is called during theplugins_loaded
hook with a priority of0
.That makes it tough to deregister it with a normal plugin. Therefore you need to use a plugin in your
mu-plugins
folder.Simply drop this into your MU-Plugins folder, adjust the
SET_CUSTOM_CAP_HERE
string inside the plugin (class variable on top â) and you’re ready to go. Make sure that you’re using some role manager (like Members, that allows you to give this role only to those who are meant to access the widgets page. Or add it manually with some own/custom plugin.Also make sure, that users don’t have some left over capability stuff. If it’s not working, deactivate all plugins, switch back to TwentyTen/Eleven and do reset of your local database with a plugin like »WordPress Reset«.
Proven Result
Note: The plugin is tested and works in a plain vanilla installation.
Disable default widgets and the submenu items
Note: This is only for later readers, who want to get rid of it all.
If you want to completely get rid of all default widgets, then there’s a simple filter, that you can call, that stops including the
~/wp-includes/default-widgets.php
file and disables the registration of the page:OVERVIEW
While the question was about limiting editor roles to access only Widgets, the following example shows how to limit access only to Menus. However as you will see, it can easily be changed to allow only Widgets or more!
I added Step #3 because I forgot about the Admin Bar. Oops! So now whether logged into the Dashboard or logged in and on the WP website, you have full control of what is available to an editor for the ‘edit_theme_capablity’ sub-menus.
If you don’t have a Roles & Capabilities Plugin installed, you can do this:
(If you do, skip #1 and go to #2, then #3)
(1) Add this to your theme’s
functions.php
:(2) Add this to
admin-footer.php
: (located in wp-admin directory)What this does is to allow you to choose which option you want Editors to have on their Dashboard.
READ THIS for more info from the author of the jQuery snippet.
(3) Add this to the Theme’s
footer.php
:What this does is to allow you to choose which option you want Editors to have on their Admin Bar.
I have found a partial way around this.
Binding actions
I add late (priority=10) method to
user_has_cap
action.In the bound method I check for page accessed (ensure it is wp-admin/widgets.php) and if it is the case, and permission being checked is edit_theme_options – I grant that permission
return $all_caps + array('edit_theme_options' => true);
.Additionally I bound very late (priority=999) method to admin_menu action.
That method, given that current user has my own defined capability to access only widgets menu (does not make sense – could be user_can_customize_themes_widgets_only) I iterate over global $submenu array section related to appearance ($submenu[‘themes.php’]) and remove any elements, that do not have ‘widgets.php’ as path element (index for path is 2). And finally I re-add widgets.php to it, in case it got missing.
Things to consider
Why I say it is partial?
Because it is a work-around. I grant user edit_theme_options right, even if for a short time period and after making sure user is accessing widgets.php and not any other page.
And also – I can not rely on this to work with future versions of WP, as I am modifying global variable $submenu, that could change in any way at any time.
Given that – it is easy to implement solution, but it is not nice in any way.