📜 ⬆️ ⬇️

Creating a plugin for PHP Composer

When deploying Magento applications using Magento Composer, we encountered the problem that different instances of the same application (developer, test, etc.) must use different local settings (for example, database connection settings). Prior to this, in another project, the approach was used when the application (under version control) contains templates of configuration files with place holders and a script that replaces place holders with local values ​​and copies the result to the right place. Local values ​​were stored separately for each specimen at the place of deployment. I wanted to keep the usual approach for the new deployment method. The search for a suitable plug-in on packagist.org ended with non-occurrence, which is why the idea was born to make such a plug-in yourself. When creating a plug-in, I had to pull information from various sources - information from the Composer site about plug-ins was not enough. Which led to the writing of this article.

composer.json


The main file of the plugin package looks 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 have got praxigento / composer_plugin_templates .

With the parameters type and require, everything is quite unambiguous - they should be and be just like that.
')
The autoload.psr-4 parameter defines the autoload setting for the plug-in classes in accordance with PSR-4 (it is recommended to use this standard, since PSR-0 is outdated on October 21, 2014). According to this setting, our sources are located in the ./src/ subdirectory.

The extra.class parameter specifies the main class of the plug-in that is loaded by Composer (or a set of classes if the parameter value is an array).

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

Point of entry


The class specified in extra.class is the Composer entry point to our plugin. According to the requirements of Composer, this class must 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; } } 


Access to parameters


The configuration of the parameters of the plugin is carried out through the extra section in the main package composer.json , which uses our plugin.
 { "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 using the extra.praxigento_templates_config parameter of the project configuration file ( composer.json ). We do this when initializing the plugin:
 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 react to events :


To do this, our entry point must also implement the EventSubscriberInterface interface, subscribe to the appropriate events and register handles:
 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 are in the phpunit.xml.dist file:
 <?xml version="1.0" encoding="UTF-8"?> <phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" syntaxCheck="false" bootstrap="phpunit.bootstrap.php" > <testsuites> <testsuite name="Plugin Test Suite"> <directory suffix="_Test.php">./src/</directory> </testsuite> </testsuites> </phpunit> 


Downloading autoloader compatible with PSR-4 (without it, tests are not run via IDE PhpStorm) 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.

Source: https://habr.com/ru/post/247519/


All Articles