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 :
- post-install-cmd
- post-update-cmd
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.