Creating a plugin for PHP Composer

    When deploying Magento applications using Magento Composer, there was a problem that different instances of the same application (development, test, etc.) must use different local settings (for example, database connection settings). Before that, in another project, an approach was used when the application (under version control) contains configuration file templates with placeholders and a script that replaces placeholders with local values ​​and copies the result to the right place. Local values ​​were stored separately for each instance at the place of deployment. I wanted to keep the familiar approach for the new deployment method. Search for a suitable plugin at packagist.orgended with a failure to find, by virtue of which the idea was born to make such a plug-in yourself. When creating the plug-in, I had to pull information from various sources - the information from the Composer site on the plug-ins was not enough. Which led to the writing of this article.

    composer.json


    The main file of the plug-in package looks something like this:
    {
      "name": "praxigento/composer_plugin_templates",
      "type": "composer-plugin",
      "require": {
        "composer-plugin-api": "1.0.0"
      },
      "autoload": {
        "psr-4": {
          "\\Praxigento\\Composer\\Plugin\\Templates\\": "src/"
        }
      },
      "extra": {
        "class": "\\Praxigento\\Composer\\Plugin\\Templates\\"
      },
      "scripts": {
        "test": "phpunit"
      }
    }
    


    The name parameter is filled to your liking, I got praxigento / composer_plugin_templates .

    With the type and require parameters, everything is fairly straightforward - they should be and be just that.

    The autoload.psr-4 parameter determines the autoload configuration of the plugin classes in accordance with PSR-4 (it is recommended to use this standard because PSR-0 was deprecated on October 21, 2014). According to this setting, our sources are located in the ./src/ subdirectory .

    The extra.class parameter definesthe main class of the plugin, which is loaded by Composer (or a set of classes, if the parameter value is an array).

    The scripts.test parameter allows you to run plug-in testing from the command line: " $ composer test ".

    Point of entry


    The class specified in extra.class is the entry point of Composer into our plugin. According to Composer’s requirements, this class should implement the Composer \ Plugin \ PluginInterface interface .

    namespace Praxigento\Composer\Plugin\Templates;
    use Composer\Composer;
    use Composer\IO\IOInterface;
    use Composer\Plugin\PluginInterface;
    class Main implements PluginInterface {
    	protected $composer;
    	protected $io;
    	public function activate(Composer $composer, IOInterface $io) {
    		$this->composer = $composer;
    		$this->io       = $io;
    	}
    }
    


    Parameter Access


    The plug-in operation parameters are configured through the extra section in composer.json of the main package in which our plug-in is used.
    {
      "name": "vendor/package",
      "type": "project",
      "repositories": [
        {
          "type": "vcs",
          "url": "https://github.com/praxigento/composer_plugin_templates"
        }
      ],
      "require": {
        "praxigento/composer_plugin_templates": "*"
      },
      "extra": {
        "praxigento_templates_config": "./instance_cfg.json"
      }
    }
    


    The plugin should take the settings for its work from the file, which is set via the extra.praxigento_templates_config parameter of the project configuration file ( composer.json ). We do this when the plugin is initialized:
    class Main implements PluginInterface, EventSubscriberInterface {
    	public function activate(Composer $composer, IOInterface $io) {
    		$this->composer = $composer;
    		$this->io       = $io;
    		$extra          = $composer->getPackage()->getExtra();
    		$configFile = $extra['praxigento_templates_config'];
    	}
    }
    


    Event handling


    In our implementation of the plugin, we wanted it to respond to events :
    • post-install-cmd
    • post-update-cmd


    For this, our entry point should also implement the EventSubscriberInterface interface , subscribe to the corresponding events and register handlers:
    class Main implements PluginInterface, EventSubscriberInterface {
    	public static function getSubscribedEvents() {
    		$result = array(
    			ScriptEvents::POST_INSTALL_CMD => array(
    				array( 'onPostInstallCmd', 0 )
    			),
    			ScriptEvents::POST_UPDATE_CMD  => array(
    				array( 'onPostUpdateCmd', 0 )
    			),
    		);
    		return $result;
    	}
    	public function onPostInstallCmd(CommandEvent $event) {
    	}
    	public function onPostUpdateCmd(CommandEvent $event) {
    	}
    }
    


    Running tests


    PhpUnit is connected in composer.json :
    {
      "require-dev": {
        "phpunit/phpunit": "4.4.*"
      }
    }
    


    Unit testing settings - in the phpunit.xml.dist file :
    ./src/


    Download autoloader compatible with PSR-4 (without it tests are not launched through the PhpStorm IDE) in the phpunit.bootstrap.php script :
    require __DIR__.'/vendor/autoload.php';
    


    Running tests through composer:
    $ composer test
    


    Conclusion


    This information should be enough to create your own plugin for Composer. Thanks to everyone who read to the end.

    Also popular now: