Plugin Development, Web Development, Wordpress Plugins,

WordPress plugin dependencies checker – Plugin Development

Sometimes a WordPress plugin you are writing extends the functionality of another plugin or simply relies on it to work. In these cases, you need to make sure your plugin’s dependencies are installed and active to be sure you can use their functions.

There are some existing libraries that you can use to make sure that a plugin is running – one such library is Contact form 7. Checking if another plugin is running, however, is fairly simple and you can implement it yourself if you don’t want to pull an external library for the purpose.

How to check if another plugin is running

WordPress provides a function that allows us to check if a plugin is running. It requires you to load extra code that is only available in the admin dashboard by default:

include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
if ( is_plugin_active( 'path to plugin file' ) ) {
	// Plugin is active
}

What you can do instead is what this WooCommerce guide advises:

$active_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ) );
if ( in_array( 'woocommerce/woocommerce.php', $active_plugins ) ) {
    // Plugin is active
}

Checking if all required plugins are active

We can now create a class that will allow us to check if all required plugins are running and throw an exception (that we will catch later) if they are not:

<?php
// my-plugin-name/classes/Dependency_Checker.php
class My_Plugin_Name_Dependency_Checker {

	/**
	 * Define the plugins that our plugin requires to function.
	 * Array format: 'Plugin Name' => 'Path to main plugin file'
	 */
	const REQUIRED_PLUGINS = array(
		'Akismet'     => 'akismet/akismet.php',
		'WooCommerce' => 'woocommerce/woocommerce.php',
	);

	/**
	 * Check if all required plugins are active, otherwise throw an exception.
	 *
	 * @throws My_Plugin_Name_Missing_Dependencies_Exception
	 */
	public function check() {
		$missing_plugins = $this->get_missing_plugins_list();
		if ( ! empty( $missing_plugins ) ) {
			throw new My_Plugin_Name_Missing_Dependencies_Exception( $missing_plugins );
		}
	}

	/**
	 * @return string[] Names of plugins that we require, but that are inactive.
	 */
	private function get_missing_plugins_list() {
		$missing_plugins = array();
		foreach ( self::REQUIRED_PLUGINS as $plugin_name => $main_file_path ) {
			if ( ! $this->is_plugin_active( $main_file_path ) ) {
				$missing_plugins[] = $plugin_name;
			}
		}
		return $missing_plugins;
	}

	/**
	 * @param string $main_file_path Path to main plugin file, as defined in self::REQUIRED_PLUGINS.
	 *
	 * @return bool
	 */
	private function is_plugin_active( $main_file_path ) {
		return in_array( $main_file_path, $this->get_active_plugins() );
	}

	/**
	 * @return string[] Returns an array of active plugins' main files.
	 */
	private function get_active_plugins() {
		return apply_filters( 'active_plugins', get_option( 'active_plugins' ) );
	}

}

… and the abstract class it extends:

<?php
// my-plugin-name/classes/exceptions/Exception.php
abstract class My_Plugin_Name_Exception extends Exception {

}

Suppressing plugin activation if dependencies are not met

If our dependencies are not met, we can prevent our plugin from executing any actual functionality. In a class that sets up our plugin, we can do the following:

<?php
// my-plugin-name/classes/Setup.php
class My_Plugin_Name_Setup {

	/** @var My_Plugin_Dependency_Checker */
	private $dependency_checker;

	public function init() {
		$this->load_classes();
		$this->create_instances();
		
		try {
			$this->dependency_checker->check();
		} catch ( My_Plugin_Name_Missing_Dependencies_Exception $e ) {
			return;
		}
		
		// Do actual plugin functionality registration here - add_action(), add_filter() etc.
	}

	private function load_classes() {
		// Exceptions
		require_once dirname( __FILE__ ) . '/exceptions/Exception.php';
		require_once dirname( __FILE__ ) . '/exceptions/Missing_Dependencies_Exception.php';

		// Dependency checker
		require_once dirname( __FILE__ ) . '/Dependency_Checker.php';
	}

	private function create_instances() {
		$this->dependency_checker = new My_Plugin_Name_Dependency_Checker();
	}

}

Reporting missing dependencies to admins

The code we wrote so far will check if all required plugins are running and only bind any actual functionality if they are. It would also be nice if we got a notice in the admin dashboard if the required plugins are not running.

To achieve this, we will create another class that will take care of reporting missing plugins to users with the activate_plugins capability (so that only user roles who can actually do something about it – and probably the only ones that should know about it – know about the issue). Only administrators have the activate_plugins capability by default.

<?php
// my-plugin-name/classes/Missing_Dependency_Reporter.php
class My_Plugin_Name_Missing_Dependency_Reporter {

	const REQUIRED_CAPABILITY = 'activate_plugins';

	/** @var string[] */
	private $missing_plugin_names;

	/**
	 * @param string[] $missing_plugin_names
	 */
	public function __construct( $missing_plugin_names ) {
		$this->missing_plugin_names = $missing_plugin_names;
	}

	public function bind_to_admin_hooks() {
		add_action( 'admin_notices', array( $this, 'display_admin_notice' ) );
	}

	public function display_admin_notice() {
		if ( ! current_user_can( self::REQUIRED_CAPABILITY ) ) {
			// If the user does not have the "activate_plugins" capability, do nothing.
			return;
		}

		$missing_plugin_names = $this->missing_plugin_names;
		include dirname( __FILE__ ) . '/../views/missing-dependencies-admin-notice.php';
	}

}

And the view to display the actual message:

<?php
// my-plugin-name/views/missing-dependencies-admin-notice.php
if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

/** @var string[] $missing_plugin_names */
?>

<div class="error notice">
    <p>
        <strong>Error:</strong>
        The <em>My Plugin Name</em> plugin won't execute
        because the following required plugins are not active:
		<?php echo esc_html( implode( ', ', $missing_plugin_names ) ) ?>.
        Please activate these plugins.
    </p>
</div>

Now we have to make our plugin setup class run the Missing_Dependency_Reporter class whenever the dependencies are missing. Let’s rewrite our Setup class:

<?php
// my-plugin-name/classes/Setup.php (updated)
class My_Plugin_Name_Setup {

	/** @var My_Plugin_Dependency_Checker */
	private $dependency_checker;

	public function init() {
		$this->load_classes();
		$this->create_instances();
		
		try {
			$this->dependency_checker->check();
		} catch ( My_Plugin_Name_Missing_Dependencies_Exception $e ) {
			// The exception contains the names of missing plugins.
			$this->report_missing_dependencies( $e->get_missing_plugin_names() );
			return;
		}
		
		// Do actual plugin functionality registration here - add_action(), add_filter() etc.
	}

	private function load_classes() {
		// Exceptions
		require_once dirname( __FILE__ ) . '/exceptions/Exception.php';
		require_once dirname( __FILE__ ) . '/exceptions/Missing_Dependencies_Exception.php';

		// Dependency checker
		require_once dirname( __FILE__ ) . '/Dependency_Checker.php';
		require_once dirname( __FILE__ ) . '/Missing_Dependency_Reporter.php';
	}

	private function create_instances() {
		$this->dependency_checker = new My_Plugin_Name_Dependency_Checker();
	}
	
	/**
	 * @param string[] $missing_plugin_names
	 */
	private function report_missing_dependencies( $missing_plugin_names ) {
		$missing_dependency_reporter = new My_Plugin_Name_Missing_Dependency_Reporter( $missing_plugin_names );
		$missing_dependency_reporter->bind_to_admin_hooks();
	}

}

And finally, to execute our plugin’s Setup class:

<?php
// my-plugin-name/my-plugin-name.php
if ( ! class_exists( 'My_Plugin_Name_Setup' ) ) {
	require_once dirname( __FILE__ ) . '/classes/Setup.php';
	$my_plugin_name_setup = new My_Plugin_Name_Setup();
	$my_plugin_name_setup->init();
}

And that’s it! We have a fully-functional plugin dependency checker.

Please let me know if you liked this post and if it was useful for you. Maybe you know of a better approach? I would love to hear about it!

Credits:
Post you may like
Web Development / Wordpress /

Top 9 WordPress Ecommerce Plugins

Web Design / Web Development / Wordpress /

Custom vs Pre-made WordPress Themes – Pros & Cons

Web Design / Web Development /

8 Design Techniques to Sharpen Your Skills

When it comes to creating professional and effective websites,
there is no company that can surpass Innozilla. Thanks to their talent, our site has taken off in the search engines like a rocket. In this day and age, it is impossible to get ahead as a business without the support of gurus like Innozilla standing behind you.

Savier Ferrer / All Miami Party Rental

Innozilla have taken our business to the next level.
Their professional solutions continue to impress us and their knowledge has catapulted our sales.
They have created 4 different websites for our companies; all with excellent results.
I will sure use them for all my upcoming projects and recommend them!!

Ronny Esquenazi / WMCP

What a wonderful experience it was to hire someone that I’ve never met on the other side of the planet! I have had the pleasure of working with Innozilla for the creation of howwelist.com, and several other sites I have built since then. He made the process painless, and I would recommend him to anyone that is needing help in multiple scopes of website creation. Consistently going above and beyond to always answer my questions within a timely manner, Innozilla Web Solutions is a true professional. All in all, the distance wasn’t a hurdle, the language barrier wasn’t an issue.

Ballard Sweat / Team Leader - The Sweat Team