- Checking in on OpenMage and Magento in 2020
- Composer Plugins and Installers
- Installing OpenMage: Bridging a Generational Gap
Magento 1 was one of the last big PHP platforms that didn’t embrace composer as a distribution model — probably because Magento’s initial release predates the release of composer by a few years. Magento 1 comes from an era where source code was distributed as an archive and moved to a server via SFTP or direct export from a source control repository.
This creates a challenge for the OpenMage project. In the twelve plus years since Magento 1’s release, Composer’s become a de-facto standard in the PHP community. If a platform doesn’t use composer, that platform will be invisible to a lot of people.
OpenMage’s getting started page currently has two competing set of code snippets for using OpenMage with Composer. Today we’re going to take a look at them and how they might surprise someone used to a more developer oriented composer workflow.
OpenMage Installers
If we head over to the the OpenMage install page, we see a few different things.
First, we have a suggestion on how to install OpenMage
The suggested way to install this Magento 1 Fork is via composer. For this we know of two working installers with support for the magento core as dependency.
and then two JSON snippets.
{
"require": {
"aydin-hassan/magento-core-composer-installer": "*",
"openmage/magento-lts": "19.4.6"
},
"extra": {
"magento-core-package-type": "magento-source",
"magento-root-dir": "htdocs"
}
}
// --------------------------------------------------
{
"require": {
"aoepeople/composer-installers": "*",
"openmage/magento-lts": "19.4.6"
}
}
It may not be obvious to someone who’s not already conversant in composer, but these are meant to be starting composer.json
files. Create a composer.json
with these contents, run composer install
, and you’ll have the OpenMage source.
The first snippet is a starter for the aydin-hassan/magento-core-composer-installer
package, which is a personal project from Aydin Hassan.
The second snippet is from the aoepeople/composer-installers
package, which is a small (README-less?) project from Fabrizio Branca under the AOE GitHub organization.
Before we begin, if you’re not familiar with composer plugins and composer installers, you may want to brush up on these concepts via our recent intro post. This article assumes you have a passing familiarity with both.
AEO People
Looking at the aoepeople/composer-installers
package first, we see this configuration.
// File: composer.json
{
"require": {
"aoepeople/composer-installers": "*",
"openmage/magento-lts": "19.4.6"
}
}
This installs the aoepeople/composer-installers
package and the OpenMage composer package (openmage/magento-lts
) to your vendor folder.
If you create a composer.json
file with the above contents (minus the file name comment), and run
$ composer.phar install
you’ll end up with the following directory contents.
$ ls
composer.json composer.lock htdocs vendor
The aoepeople/composer-installers
package appears to be designed to look for an installed Magento source package (openmage/magento-lts
), and then copy that package out of vendor and into htdocs
.
We say appears because how the aoepeople/composer-installers
works is a little unclear. If we look at its composer.json
file, we see it’s not a composer plugin. Instead, its package type is composer-installer
, and it registers a plugin via the extra
configuration.
{
"name": "aoepeople/composer-installers",
"type": "composer-installer",
/* ... */
"extra": {
"class": "Aoepeople\\ComposerInstallers\\Installer"
},
}
If we look at the class registered as a plugin we see it extends a Composer\Installer\LibraryInstaller
that we haven’t seen before. It turns out this aoepeople/composer-installers
package is based on a very early version of the composer installer feature/API.
In addition to (or perhaps because of) being a bit of mystery code, this installer has another curious property. When responding to a composer update
command the aoepeople/composer-installers
package will reinstall Magento to the htdocs
folder, overwriting any updates you’ve made there. If this is the intended behavior, it would appear that this installer works best when it’s part of a larger workflow that copies or symlinks configuration, theme, and modules into the main Magento source repository.
Because of its destructive behavior with regards to updates and its reliance on a very old, possibly never officially supported, version of the installer API, I’d recommend staying away from this installer.
Aydin Hassan Installer
If we look at the aydin-hassan/magento-core-composer-installer
configuration, we see a few additional configuration fields. Similar to the aoepeople/composer-installers
installer, we have the the main installer composer package (aydin-hassan/magento-core-composer-installer
) configured, as well as a Magento source package (openmage/magento-lts
). However, we also have these two items.
{
/* ... */,
"extra": {
"magento-core-package-type": "magento-source",
"magento-root-dir": "htdocs"
}
}
The magento-core-package-type
configuration tells the installer which composer type
identifiers another package as a Magento source package. This is magento-source
because the magento/magento-lts
package’s type is magento-source
. The aydin-hassan/magento-core-composer-installer
package is designed to install any composer packaged Magento source, not just OpenMage.
The magento-root-dir
configuration tells the installer which folder to install the Magento source into.
What it Does
If we create this composer.json
file.
// File: composer.json
{
"require": {
"aydin-hassan/magento-core-composer-installer": "*",
"openmage/magento-lts": "19.4.6"
},
"extra": {
"magento-core-package-type": "magento-source",
"magento-root-dir": "htdocs"
}
}
and then run composer install
, we’ll see the following in our project folder
$ composer.phar install
// ...
$ ls
composer.json composer.lock htdocs vendor
The htdocs
folder now contains our copy of OpenMage.
Unlike aoepeople/composer-installers
, if we update the version of OpenMage,
// File: composer.json
{
"require": {
"aydin-hassan/magento-core-composer-installer": "*",
"openmage/magento-lts": "^20.0"
},
"extra": {
"magento-core-package-type": "magento-source",
"magento-root-dir": "htdocs"
}
}
and then run composer update
$ composer.phar update
The aydin-hassan/magento-core-composer-installer
installer will only update files from the source package. It will not replace new files you may have put into htdocs
. However, if you’ve changed a core file, those changes will be overwritten. Also, in the unlikely (but possible) case where one of your files has the same path and name as a file in the new source package, it appears the installer will copy the source file over your file. If this is a problem, it appears there’s support for an excludes
configuration that will let a system owner skip copying certain files.
Implementation
When it comes to its implementation, the aydin-hassan/magento-core-composer-installer
installer is a composer plugin. You can see the package configures a plugin class via composer.json
.
It is not, however, a composer custom installer. Instead, the AydinHassan\MagentoCoreComposerInstaller\CoreManager
class listens for (i.e. subscribes to) a number of different composer events, and takes appropriate action to install, uninstall, or update the Magento source.
So while this plugin is an installer in the general sense (it installs Magento), it is not an example of a composer custom installer, and is not something that works on top of the composer/installers
plugin/custom-installer.
One More Installer
There’s one more installer you’ll want to be aware of if you’re using OpenMage. To start, let’s try adding a package from the packages.firegento.com composer repository to our project.
First, we’ll want to configure composer globally so this repository is available.
$ composer.phar config -g repositories.firegento composer https://packages.firegento.com
Then, let’s require my old Pulse Storm Launcher package.
$ composer.phar require astorm/pulsestorm-launcher:dev-master
After running the above command, we’ll find this extension code in the vendor
folder
$ ls vendor/astorm/pulsestorm-launcher/
LICENSE.txt
README.md
app
build_launcher.bash
composer.json
magento-tar-to-connect.launcher.php
modman
skin
However, we’ll also find it inside our htdocs
folder.
$ ls htdocs/app/code/community/Pulsestorm/Launcher/
Block Model controllers
Helper README.md etc
$ ls htdocs/app/design/adminhtml/default/default/template/pulsestorm_launcher/
hook.phtml js-nav.phtml
// etc ...
You’re probably wondering what installed this module into this folder. I know I was the first time I saw this happen.
The OpenMage project has a dependency on the magento-hackathon/magento-composer-installer
package. This package contains another composer plugin that recognizes packages of type magento-module
and is able to install them into a Magento source repository. The magento-hackathon/magento-composer-installer
package is also not a composer installer — it’s just a plain composer plugin.
Interestingly, if you attempt to install openmage/magento-lts
without one of the installer packages we’ve mentioned.
$ composer.phar require openmage/magento-lts
// ...
please define your magento root dir [root]
magento root dir "root" missing! create now? [Y,n] Y
magento root dir "root" created
you will be prompted to create a root directory. This is the magento-hackathon/magento-composer-installer
package at work, and will update the magento-root-dir
configuration variable for you.
As long as we’re talking about weird unexpected-but-useful things, the magento-hackathon/magento-composer-installer
package will also add a small code snippet to htdocs/app/Mage.php
#File: htdocs/app/Mage.php
/** AUTOLOADER PATCH **/
if (file_exists($autoloaderPath = BP . DS . 'vendor/autoload.php') ||
file_exists($autoloaderPath = BP . DS . '../vendor/autoload.php')
) {
require $autoloaderPath;
}
/** AUTOLOADER PATCH **/
This snippet will try to load composer’s autoloader from the following two files.
htdocs/vendor/autoload.php
vendor/autoload.php
This will give code in your Magento system the ability to use class files loaded via composer’s standard PSR-0 and PSR-4 autoloaders.
Wrap Up
So — that’s three different composer plugins, two that install Magento’s source, a third that installs Magento modules, and none of them are actually formal composer installers. This all seems like it works OK in practice — assuming you’re already familiar with Magento.
I’m not sure what you would think if you were new to Magento. While I’m sure the aydin-hassan/magento-core-composer-installer
and magento-hackathon/magento-composer-installer
plugins do their jobs well, to someone just learning Magento’s conventions I imagine this setup adds a tremendous amount of cognitive overhead.
Put another way — these plugins will serve an experienced Magento developer well, but will only add a layer to Magento’s already legendary impenetrableness.
Next time, as we start to wrap this series up, we’ll do a bit of speculating on what a composer create-project
workflow might look like for OpenMage, and how something like this might help reduce the cognitive overhead for someone just learning Magento’s complex module and theme structures.