There have been times through out several projects where I’ve wanted to display a plugin activation message (or deactivation message).

WordPress makes it relatively easy to do this using two functions:

But here’s the the thing: These two functions may not work as you expect if you’re writing your plugins using object-oriented practices.

So I thought I’d share how I go about displaying a plugin activation message in hopes that it not only helps you in your future projects, but in hopes that you guys could offer up your own code review as well.

A Plugin Activation Message

In short, a WordPress plugin activation message is a notice that appears at the top of the dashboard whenever, y’know, the plugin is activated.

Ideally, it should look as if it’s part of the native WordPress dashboard theme, and should provide the user with any information they need to know (which shouldn’t be much) about the plugin.

For example:

And the behavior of something like this should happen as follows:

The plugin is activated

The message displays

The plugin is deactivated

If the plugin is activated again, the process repeats

Simple, right?

The Class Skeleton

To set this up, here’s a basic skeleton that I use when creating class-based plugins (note that I’ll actually be including this in the next version of the Plugin Boilerplate).

// Set the version of this plugin if( ! defined( 'ADVANCED_GOOGLE_ANALYTICS' ) ) { define( 'ADVANCED_GOOGLE_ANALYTICS', '1.0' ); } // end if /** * @version 1.0 */ class Advanced_Google_Analytics { /*--------------------------------------------------------* * Attributes *--------------------------------------------------------*/ /** Static property to hold our singleton instance */ private static $instance = null; /*--------------------------------------------------------* * Constructor *--------------------------------------------------------*/ /** * Initializes the widget's classname, description, and JavaScripts. */ public function get_instance() { // Get an instance of the if( null == self::$instance ) { self::$instance = new self; } // end if return self::$instance; } // end get_instance /** * Initializes the plugin' textdomain, adminitration message, and more. */ private function __construct() { // Load plugin textdomain add_action( 'init', array( $this, 'plugin_textdomain' ) ); // Display the admin notification add_action( 'admin_notices', array( $this, 'plugin_activation' ) ) ; } // end constructor /*--------------------------------------------------------* * Functions *--------------------------------------------------------*/ /** * Defines the plugin textdomain. */ public function plugin_textdomain() { $domain = 'advanced-google-analytics'; $locale = apply_filters( 'advanced-google-analytics', get_locale(), $domain ); load_textdomain( $domain, WP_LANG_DIR . '/' . $domain . '/' . $domain . '-' . $locale . '.mo' ); load_plugin_textdomain( $domain, FALSE, dirname( plugin_basename( __FILE__ ) ) . '/lang/' ); } // end plugin_textdomain /** * Saves the version of the plugin to the database and displays an activation notice on where users * can access the new options. */ public function plugin_activation() { if( ADVANCED_GOOGLE_ANALYTICS != get_option( 'advanced_google_analytics' ) ) { add_option( 'advanced_google_analytics', ADVANCED_GOOGLE_ANALYTICS ); $html = '<div class="updated">'; $html .= '<p>'; $html .= __( 'The Advanced Google Analytics are available <a href="admin.php?page=theme_options&tab=lobal_options">on this page</a>.', 'advanced-google-analytics' ); $html .= '</p>'; $html .= '</div><!-- /.updated -->'; echo $html; } // end if } // end plugin_activation /** * Deletes the option from the database. Optionally displays an error message if there is a * problem deleting the option. */ public static function plugin_deactivation() { // Display an error message if the option isn't properly deleted. if( false == delete_option( 'dvanced_google_analytics' ) ) { $html = '<div class="error">'; $html .= '<p>'; $html .= __( 'There was a problem deactivating the Google Analytics Plugin. Please try again.', 'advanced-google-analytics' ); $html .= '</p>'; $html .= '</div><!-- /.updated -->'; echo $html; } // end if/else } // end plugin_deactivation } // end class

In this class, I’m using an implementation of the singleton pattern and then I’m constructing an instance by using the plugins_loaded hook and by making a call to the get_instance static function.

The Plugin Action Message

Notice that in the constructor, I have a hook to admin_notices that calls to plugin_activation . It’s important to understand what’s happening in this particular function:

First, I compare the value of the current version of the plugin as defined at the top of the file matches the advanced_google_analytics option.

option. If it does not, I’ll save this option

Next, I’ll build a div element containing the message

element containing the message Then I echo it to the screen

Nothing too complicated, but it’s important to note that version tracking using an option is how this is made possible especially when it comes to deactivation

Deactivating The Plugin

When deactivating the plugin:

The plugin’s version should be wiped from the database

If the deletion fails, then we need to notify the user

The thing is, using register_deactivation_hook in the context of the class doesn’t work. As such, we have to define a static method:

/** * Deletes the option from the database. Optionally displays an error message if there is a * problem deleting the option. */ public static function plugin_deactivation() { // Display an error message if the option isn't properly deleted. if( false == delete_option( 'dvanced_google_analytics' ) ) { $html = '<div class="error">'; $html .= '<p>'; $html .= __( 'There was a problem deactivating the Google Analytics Plugin. Please try again.', 'advanced-google-analytics' ); $html .= '</p>'; $html .= '</div><!-- /.updated -->'; echo $html; } // end if/else } // end plugin_deactivation

Finally, we add the following line to the end of the file:

register_deactivation_hook( __FILE__, array( 'Advanced_Google_Analytics', 'plugin_deactivation' ) );

Notice that this is outside of the context of the class, but it’s calling the static method defined within it.

A Few Words About Deactivation

Since we’re actually only displaying the plugin activation notice when the plugin is activated, and since we’re doing so by comparing the values of the plugin’s version to what’s saved in the database, we don’t actually have to delete anything.

The reason that I’m doing this is so that I can guarantee the user will see this message each time they activate the plugin. Ultimately, it’s about trying to make sure there’s a solid user experience.

If people forget where the new options have been added, then they’ll always be guided to them whenever the plugin is activated.

Is This How You’d Do It?

Obviously, I’ve simplified the code quite a bit for purposes of this post, but this is my implementation for a project that I’ve been working on.

It’s something that I felt worth sharing with the rest of you guys as I think it’s a relatively common need, but I’m also interested in feedback on the process.

So let’s hear it.