Plugins requirements with Composer

Using Composer to pull in plugin dependencies into plugins.

The problem

While developing the Restricted Content framework plugin and its behind the scenes worker I will need to use the functions defined in the tad-reschedule plugin.
The latter is a small WordPress utility plugin defining one function and one class I’d like to use to empower the tasks of the former one.
In a controlled scenario, like a managed client site, I’d simply add both to the plugins (or mu-plugins) folder and call it done: being the installation and plugin configuration under my control I will be reasonably sure both will be installed and activated.
But what about someone, even me, willing to install the Restricted Content framework plugin plugin alone? I could check, inside it, for the existence and active state of the tad-reschedule plugin and either cut some tasks or replace them; that would but make the idea of re-using code so dear to Object-Oriented Programming worthless.

Composer to the rescue

I’ve configured the tad-reschedule Composer configuration file to be able to use it not only as a stand-alone plugin but as a library dependency too.
Here it is:

{
  "name": "lucatume/tad-reschedule",
  "description": "Easy cron event rescheduling in WordPress",
  "type": "wordpress-plugin",
  "require": {
    "composer/installers": "~1.0",
    "xrstf/composer-php52": "1.*"
  },
  "require-dev": {
    "lucatume/wp-browser": "dev-master",
    "lucatume/function-mocker": "dev-master"
  },
  "license": "GPL 2.0",
  "authors": [
    {
      "name": "Luca Tumedei",
      "email": "[email protected]"
    }
  ],
  "scripts": {
    "post-install-cmd": [
      "xrstf\\Composer52\\Generator::onPostInstallCmd"
    ],
    "post-update-cmd": [
      "xrstf\\Composer52\\Generator::onPostInstallCmd"
    ],
    "post-autoload-dump": [
      "xrstf\\Composer52\\Generator::onPostInstallCmd"
    ]
  },
  "autoload": {
    "files": [
      "tad-reschedule.php"
    ]
  }
}

Worth of note is that

  • the type of the package is wordpress-plugin to benefit from Composer Installers smart installations
  • the autoload instruction will take care of autoloading the main (and only) plugin file and have it ready to use

While the type of the tad-reschedule plugin might be defined as wordpress-plugin to the Restricted Content framework plugin, itself a WordPress plugin, it will be a dependency.

Require a plugin in plugin

The Restricted Content framework plugin own composer file file will specify the tad-reschedule plugin as requirement and will tell composer to install it in the plugin own vendor folder:

{
  "name": "lucatume/tad-conntent-restriction",
  "type": "wordpress-plugin",
  "description": "A WordPress content restriction framework",
  "license": "GPL 2.0",
  "authors": [
    {
      "name": "Luca Tumedei",
      "email": "[email protected]"
    }
  ],
  "minimum-stability": "dev",
  "repositories": [
    {
      "type": "git",
      "url": "https://github.com/lucatume/wp-browser.git"
    },
    {
      "type": "git",
      "url": "https://github.com/lucatume/tad-reschedule.git"
    }
  ],
  "require": {
    "composer/installers": "~1.0",
    "xrstf/composer-php52": "1.*",
    "lucatume/tad-reschedule": "~1.0"
  },
  "extra": {
    "installer-paths": {
      "vendor/{$vendor}/{$name}": [
        "lucatume/tad-reschedule"
      ]
    }
  },
  "require-dev": {
    "lucatume/wp-browser": "dev-master",
    "lucatume/function-mocker": "dev-master"
  },
  "autoload": {
    "psr-0": {
      "trc_": "src/"
    }
  },
  "scripts": {
    "post-install-cmd": [
      "xrstf\\Composer52\\Generator::onPostInstallCmd"
    ],
    "post-update-cmd": [
      "xrstf\\Composer52\\Generator::onPostInstallCmd"
    ],
    "post-autoload-dump": [
      "xrstf\\Composer52\\Generator::onPostInstallCmd"
    ]
  }
}

and that will suffice to have the required plugin installed as a dependency in the consumer plugin.
tad-reschedule in the folder tree

Caveat

To have all of the above happening all of the plugins must have Composer files set and and extra care has to be taken to avoid naming collisions.
If the tad-reschedule plugin is installed on the site as a stand-alone plugin or is required more than one time from other plugins then a function/class redefinition issue might arise.
The code below is customary in WordPress and checking for the existence of functions or classes

/**
 * Plugin Name: Reschedule Utility
 * Plugin URI: http://theAverageDev.com
 * Description: Easy cron event rescheduling.
 * Version: 1.0
 * Author: theAverageDev
 * Author URI: http://theAverageDev.com
 * License: GPL 2.0
 */

if ( ! function_exists( 'tad_reschedule' ) ) {
    /**
     * @param string $hook The name of the action hook to reschedule.
     *
     * @return tad_Reschedule An instance of the underlying class to keep the chain going.
     *
     */
    function tad_reschedule( $hook ) {
        return tad_Reschedule::instance( $hook );
    }
}

if ( ! class_exists( 'tad_Reschedule' ) ) {
    class tad_Reschedule {
    // ...
    }
}

but it will be, in this case, mandatory to avoid collisions.

I appreciate your input