How to make a plugin require another plugin?

Thanks for the answers guys. Though both answers set me on the right path, none worked out of the box. So I’m sharing my solutions below.

Method 1 – Using register_activation_hook:

Create the Parent Plugin in plugins/parent-plugin/parent-plugin.php:

<?php
/*
Plugin Name: Parent Plugin
Description: Demo plugin with a dependent child plugin.
Version: 1.0.0
*/

Create the Child Plugin in plugins/child-plugin/child-plugin.php:

<?php
/*
Plugin Name: Child Plugin
Description: Parent Plugin should be installed and active to use this plugin.
Version: 1.0.0
*/
register_activation_hook( __FILE__, 'child_plugin_activate' );
function child_plugin_activate(){

    // Require parent plugin
    if ( ! is_plugin_active( 'parent-plugin/parent-plugin.php' ) and current_user_can( 'activate_plugins' ) ) {
        // Stop activation redirect and show error
        wp_die('Sorry, but this plugin requires the Parent Plugin to be installed and active. <br><a href="' . admin_url( 'plugins.php' ) . '">&laquo; Return to Plugins</a>');
    }
}

Notice that I’m not using deactivate_plugins( $plugin ); as for some reason it does not work. So I used wp_die to cancel the activation redirection and inform the user.

Advantage:

  • Simple solution and does not incur additional db hits compared to method 2

Disadvantages:

  • wp_die screen is ugly
  • wp_die screen will STILL show up if you activated the Parent Plugin and Child Plugin at the same time using the checkboxes in the plugins admin screen.

Method 2 – Using admin_init and admin_notices

Create the Parent Plugin in plugins/parent-plugin/parent-plugin.php:

<?php
/*
Plugin Name: Parent Plugin
Description: Demo plugin with a dependent child plugin.
Version: 1.0.0
*/

Create the Child Plugin in plugins/child-plugin/child-plugin.php:

<?php
/*
Plugin Name: Child Plugin
Description: Parent Plugin should be installed and active to use this plugin.
Version: 1.0.0
*/
add_action( 'admin_init', 'child_plugin_has_parent_plugin' );
function child_plugin_has_parent_plugin() {
    if ( is_admin() && current_user_can( 'activate_plugins' ) &&  !is_plugin_active( 'parent-plugin/parent-plugin.php' ) ) {
        add_action( 'admin_notices', 'child_plugin_notice' );

        deactivate_plugins( plugin_basename( __FILE__ ) ); 

        if ( isset( $_GET['activate'] ) ) {
            unset( $_GET['activate'] );
        }
    }
}

function child_plugin_notice(){
    ?><div class="error"><p>Sorry, but Child Plugin requires the Parent plugin to be installed and active.</p></div><?php
}

Advantage:

  • Works when you activate the Parent and Child plugin at the same time using checkboxes

Disadvantage:

  • Incur additional db hits as the plugin is actually activated at first and deactivated once admin_init runs.

As for my question regarding disabling the activate link, I could use:

add_filter( 'plugin_action_links', 'disable_child_link', 10, 2 );
function disable_child_link( $links, $file ) {

    if ( 'child-plugin/child-plugin.php' == $file and isset($links['activate']) )
        $links['activate'] = '<span>Activate</span>';

    return $links;
}

However, it turned out to be highly impractical as there is NO place to put this code. I could not put it on the parent plugin as the parent plugin should be active for this code to run. Certainly does not belong to child plugin or functions.php. So I’m scrapping this idea.

Leave a Comment