Steve Taylor photo

Disabling WordPress plugin deactivation and theme changing

Someone asked in a comment here recently whether a WordPress plugin I’d posted could be adapted to work as theme code. The reasoning was that a client might deactivate a plugin, breaking some of the site’s functionality.

Careless clients clicking around in the admin interface can be a concern for a responsible developer. Of course, the primary way of limiting this kind of risk is to assign clients to appropriate roles. If the pre-defined roles don’t quite fit, Justin Tadlock’s excellent Members plugin can help you get it right.

But say you have a client to whom you want to give plugin activation / deactivation capabilities (so they can add new plugins themselves), but the site you’ve built includes certain plugins that really shouldn’t be deactivated. What then?

I’ve come up with a bit of code (to be added to your custom theme’s functions.php) that removes the “Deactivate” links on the plugins list. In the code below, the $plugin_file values being tested for are those from my own core set of plugins. The values are just the paths (relative to /wp-content/plugins/) of the main plugin PHP files. Adjust this array as appropriate.

As a bonus, the “Edit” links are removed for all plugins. Adjust this as you see fit. Personally, I don’t think there’s much use for the plugin editor, and there’s a lot of risk.

add_filter( 'plugin_action_links', 'slt_lock_plugins', 10, 4 );
function slt_lock_plugins( $actions, $plugin_file, $plugin_data, $context ) {
	// Remove edit link for all
	if ( array_key_exists( 'edit', $actions ) )
		unset( $actions['edit'] );
	// Remove deactivate link for crucial plugins
	if ( array_key_exists( 'deactivate', $actions ) && in_array( $plugin_file, array(
		unset( $actions['deactivate'] );
	return $actions;

Of course, this isn’t preventing the actual deactivation. A crafty client could cobble together the deactivation URL and just run it. But if you’ve got a crafty client… well, they almost certainly have FTP details to their own site, so even if you’ve disabled actual deactivation, they could just go in there and delete plugins if they really want to. The above seems like a quick-and-easy method of preventing gross risks.


What about themes? On most WordPress sites I build, the theme is the site, in a way. I’m branching more and more of my custom code out into plugins, but still, my clients’ sites just aren’t the kind that can be easily switched from one theme to another, as is the idea with the more blog-centric end of WordPress.

Well, again I’m only going to bother disabling the interface elements, given that any client who really wants to balls things up will probably find a way. I’ve expanded on a snippet on, which removes the “Themes” submenu item, by adding a check for the current user ID. My user account on all sites I build is the first one, with ID 1, so this submenu is only available to me. It’s good to have access sometimes, for instance when isolating issues by switching to the default theme briefly.

Again, this goes in your theme’s functions.php:

add_action( 'admin_init', 'slt_lock_theme' );
function slt_lock_theme() {
	global $submenu, $userdata;
	if ( $userdata->ID != 1 ) {
		unset( $submenu['themes.php'][5] );
		unset( $submenu['themes.php'][15] );


  1. Hi Lee, good point. I had a quick look into MU plugins, but didn’t like the fact that you couldn’t use folder structures – the main plugin file has to be in the root of /mu-plugins/. You can just put the main file in there and have a sub-folder with files that are referenced by the main file, I guess. I’m not sure about the ins and outs.

    I may have persisted and tried to go with MU plugins if it weren’t for the fact that it looks like you can’t auto-update them. A lot of the reason I’m doing these bits of code, that I use as standard in my sites, as plugins is so I can auto-update them on all sites easily. So, at the time I looked into it, I decided MU plugins weren’t quite right for me.

    Besides, the above isn’t much work. Took me 5 minutes to code it, now it’s in my standard parent theme and I don’t have to think about it again :)

    This post might be relevant – I’ll have to look into it. Do let me know if you come up with any other tips on this issue!

  2. Adal avatar Adal

    Hey Steve,

    Great code as usual. Makes me wonder… do you have a clue as to how you would disable Theme UPDATING?

    A lot of my clients come to me with existing WordPress sites that were created by, well churners I guess. They basically end up with a modified Twenty-Ten and having the option of “updating your theme” is a HUGE liability for these clients.

    Without starting from scratch, I feel like disabling theme update links and notifications would be a quick fix for low budget people.

  3. Not sure about the best way to remove the links, but an easy thing to do would be to rename the modified theme (in style.css) to “Twenty Ten custom” or something :)

  4. SEO Info avatar SEO Info

    I develop Site for my clients and many time they change the themes i configure for them and later they revert back with some issues or the other. Your Post has save many hours of mine by disabling the theme changing option.

Comments are closed.