Composer: Scripts

“Hook me up
I’m reaching out for you, come on
Hook me up
I know you can do it, come on, take me on” – Bon Jovi

We all use composer to manage libraries for our apps. Usually we build composer.json file, install dependencies and eventually update them later. These are common and repetitive tasks but composer of course has much more to offer.

I wish to share a real life example.

My task was to check some external module, it’s code quality, compatibility with the rest of module’s stack and such a stuff and then to put it on packagist. Procedure of module’s installation was very ancient – copy and paste all files into app/code and pub/media however we wanted to convert it into a real composer’s module.

But the small nasty problem was hiding in the grass all the time – pub/media assets.

Those assets were used in module to display cluster markers on google map so they had to be available through http request.

My first thought was to put those assets into module’s directory, write DataInstall script and copy all of them into media during installation process. That was not a bad idea however I was not sure if deployment of assets should be a part of data setup procedure, in the end assets are not the kind of data we wish to update or set in setup script.

Then my friend told me to check the composer’s scripts. And that was exactly what I was looking for.

Scripts

Composer give us the possibility to add scripts to some predefined hooks. In the documentation we can find the following hooks types:

Installer Events
  • pre-dependencies-solving: occurs before the dependencies are resolved.
  • post-dependencies-solving: occurs after the dependencies have been resolved.
Package Events
  • pre-package-install: occurs before a package is installed.
  • post-package-install: occurs after a package has been installed.
  • pre-package-update: occurs before a package is updated.
  • post-package-update: occurs after a package has been updated.
  • pre-package-uninstall: occurs before a package is uninstalled.
  • post-package-uninstall: occurs after a package has been uninstalled.
Plugin Events
  • init: occurs after a Composer instance is done being initialized.
  • command: occurs before any Composer Command is executed on the CLI. It provides you with access to the input and output objects of the program.
  • pre-file-download: occurs before files are downloaded and allows you to manipulate the RemoteFilesystem object prior to downloading files based on the URL to be downloaded.

For my purpose post-package-install event was the best solution.

Attached script can be any shell command or static method in class which is available for composer’s autoloader.

The easiest way to achieve desired effect was to simply copy assets from module into pub/media by using shell “cp -R” command.

So I added the following lines in composer.json

Bingo!

Copying of files is now a part of the module’s deployment but not the data update procedure – that’s great!

Mistake!

All fine but this is not working… how is that?

As it showed up scripts are not run for main package’s dependencies. It means that after installation of all packages my script wont run either. That’s not nice… I had to move it into the main composer.json in Mangento’s root. Also I had to change all paths.

I tried again and it worked as expected.

This is a little flaw of my solution but I still perceive it as better than copying files during DataInstall/Upgrade process.

That’s all for now. Check composer’s docs for more details not covered in my article.

See you soon! 🙂

Along with a mate we found a better overall concept for this issue. You can read about that in my I was wrong! entry.