WordPress Plugin Dependency Programming

There are many discussions about wordpress plugin dependencies handling, there is also a plugin to allow you set up dependency relations between plugins. In my view, plugin dependencies are not something you will face very often, and in some cases you do need to require other plugins for your one to work, I would rather deal with it in a more personal way that is to handle it privately in that dependent plugin

While there are many ways to establish the dependency relationship, the purpose of my exploration of this is to find the most elegant way to handle this.

1. Establish dependency in plugin activation
As a rule of thumb, do not run any code in your main plugin page, wrap the code into functions and register them using propriate hooks or filters, as code in main plugin page will be run for every request, it not only slows down the speed, but also any error in those parts will cause wordpress fail miserably, as a plugin author, this is the last thing you want to happen.

To me the best time to establish the dependency is when user activates your plugin, as how to fail with grace in plugin activation, it turns out to be a bit of a lesson which I would like to share with you, following is the code I finally used:

register_activation_hook( __FILE__, 'dependentplugin_activate' );

function dependentplugin_activate()
{
  require_once( ABSPATH . '/wp-admin/includes/plugin.php' );

  if ( is_plugin_active( 'requiredplugin/requiredplugin.php' ) )
  {
    require_once ( WP_PLUGIN_DIR . '/requiredplugin/requiredplugin.php' );
  }
  else
  {
     // deactivate dependent plugin
    deactivate_plugins( __FILE__);
    //   throw new Exception('Requires another plugin!');
   //  exit();
    exit ('Requires another plugin!');
   }
}

2. Just simply check the required plugin is activated or not
3. It is important to deactivate your dependent plugin if the required one does not exist, otherwise you will get error :

Cannot redeclare yourfailedfuncitonname() previously declared in…

To understand this we need to have a look what system does to activate a plugin, here is an excerpt of function activate_plugin in /wp-admin/includes/plugin.php

	include(WP_PLUGIN_DIR . '/' . $plugin);
	do_action( 'activate_plugin', trim( $plugin) );
	if ( $network_wide ) {
			$current[$plugin] = time();
			update_site_option( 'active_sitewide_plugins', $current );
	} else {
			$current[] = $plugin;
			sort($current);
			update_option('active_plugins', $current);
	}
	do_action( 'activate_' . trim( $plugin ) );
	do_action( 'activated_plugin', trim( $plugin) );

So you can see that plugin will be marked as activated and saved to database before your registered activate handler is reached, so even the activation of plugin is failed, it has already been treated as activated, this causes ‘redeclare’ error when there is any error happened after this in activation which is our scenario when the required plugin does not exist.

To fix this you just need to deactivate if required plugin is not activated.

4. How to send the error message out.
WP_Error will not do anything in terms of flow of UI, wp_die() is too harsh because it just stops the running of whole application abruptly. Echo message is not acceptable here, as activation of plugin is not allowing any character output, likely you will get a message like:

The plugin generated n characters of unexpected output during activation. If you notice “headers already sent” messages, problems with syndication feeds or other issues, try deactivating or removing this plugin.

The script must be terminated using exit or by throwing exception; This will let user return to the plugin page with just the error message at the top which is what I wanted, you can throw an exception if you do not mind the error message area being replaced with raw php error output.

Tags:

This entry was posted on Monday, November 1st, 2010 at 3:56 am and is filed under PHP. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply

*