WordPress Plug-in Self Deactivation
WordPress 3.5 is almost upon us, and I was excited to learn that my Sort Query by Post In plug-in had been folded into core, thanks to a ticket I opened and submitted a patch for some time ago. Sort Query by Post In allowed developers to return posts from a post query (WP_Query) in the order designated using the post__in parameter.
Now that identical functionality is in core, I wanted to update my plug-in to automatically disable itself – with a notice – for users running 3.5 or newer. This code would also prevent the plug-in from being activated if installed on 3.5 or newer. Surprisingly, there seemed to be a dearth of good tutorials, so I came up with my own solution.
Trick #1 – which isn’t really that tricky – was getting the plug-in to deactivate itself, and notify the user of the change. Trick #2 – a bit more tricky – was preventing new activations without showing an ugly and scary warning message on the plug-in activation screen.
Here’s how it works:
if ( version_compare( floatval( get_bloginfo( 'version' ) ), '3.5', '>=' ) ) { if ( current_user_can( 'activate_plugins' ) ) { add_action( 'admin_init', 'my_plugin_deactivate' ); add_action( 'admin_notices', 'my_plugin_admin_notice' ); function my_plugin_deactivate() { deactivate_plugins( plugin_basename( __FILE__ ) ); } function my_plugin_admin_notice() { echo '<div class="updated"><p><strong>Plug-in name</strong> was folded into WordPress core in 3.5; the plug-in has been <strong>deactivated</strong>.</p></div>'; if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] ); } } } else { ... normal plug-in code ... }
So let’s break this down a bit.
You can retrieve the current WordPress version using get_bloginfo(‘version’) (or the global $wp_version). If you’re not running a final / stable release (i.e. a beta or trunk), that doesn’t return just a number, but something like “3.5-beta2-…”. PHP’s floatval will take care of stripping that down to a comparable numeric version, and we can use PHP’s version_compare to reliably compare against the version number we’re looking for.
If we pass the “deactivate / don’t run this” test, I than recommend another test to check the current user’s right to activate_plugins (only administrators, out of the box). This will ensure that Joe subscriber doesn’t see a plug-in deactivation message, and that the next administrator to log-in does.
I add two hooks. The admin_init hooks runs when the admin dashboard is loaded; this will ensure it doesn’t deactivate until a message can be shown, and also ensures that plug-ins have been loaded up before we run our deactivation code. The callback simple executes WordPress’s deactivate_plugins function.
The second hook, admin_notices, will allow us to show a notice / message in the admin, and also conveniently runs right before the code that generates the “Plug-in activated” or error message generated by activating a plug-in. In the callback, I echo out the desired, formatted notice, and, should it be set (translation: should the administrator have just activated the plug-in), unsets the $_GET parameter (activate) that core code checks to determine whether and what message to show after attempting to activate a plug-in.
The result is a clean deactivation (even if the plug-in was just activated), with a clear message!
Comments
George Stephanis on
You don’t need to floatval() it first — version_compare is designed to take a string like 3.5-alpha or 3.5-RC2 and successfully compare it against 3.4, 3.5-beta4, or 3.7.1
http://php.net/manual/en/function.version-compare.php
This Week In WordPress: Dec 17, 2012 – Max Foundry on
[…] WordPress Plugin Self Deactivation […]
Paul on
I found this tutorial that seems to work well.
http://www.squarepenguin.com/wordpress/?p=6
This solution is better for me as I’m using OOP and so I can integrate the function in my class and call it on the activation hook
Jake Goldman on
Not a bad approach either, but… (1) it doesn’t account for users who already have the plug-in active (that hook doesn’t fire on plug-in updates anymore), and (2) I don’t like that it should a “fatal error” warning.
Paul on
I agree. I ended up doing a mashup of this and the way that woocommerce extensions check for the presence of woocommerce with get_option( ‘active_plugins’ )
Andrew on
Hi Jake,
I came across your code and it’s pretty much what I need, but I can’t get it to work.
I’ve coded an extension to Contact Form 7, so I just want to check that the Contact Form 7 plugin is active for mine to activate.
This is what I’ve done so far: http://pastebin.com/hbMTvyHt
The first debug line of ‘CF7 not active’ gets emailed to me. But the other functions I’ve created for those action hooks never get called.
Any tips?
Jake Goldman on
It’s almost certainly a timing issue (when this hook runs vs when those hooks run). Also – not really ideal to put your functions instead another function like that.
Zohaib on
Thank you so much! it helped me.