Dev Series: Patching core Magento 2 files

Magento 2 is still a relatively new piece of software, but it’s great that Magento have chosen to put their development process in front of the development community on GitHub;.  This transparency allows bugs to be reported, and more importantly, gives a platform for the community to provide revisions to core code, and fixes to bugs that they find.

Given the nature of software, it can be some time before an official patch is rolled into a release – and this might hold up development of key functionality for a client site.

The Magento core code (for both Open Source and Commerce offerings) are provided within Composer repositories for easy installation and upgrade.  This means that the core of Magento doesn’t need to be kept in source control, as it is all available from Composer and can be installed / upgraded alongside any extensions that you might be utilising in the same way.

As this code isn’t in source control, there is an issue however.  If you are affected by a core bug, and you want to fix it, how do you do so whilst maintaining this configuration?

There are a number of approaches you could take.

Have a local verison of the module

Composer includes repositories in order of preference, meaning you can add a repository to pull from ahead of Magento’s – for specific modules.

This means that you could copy the module into your own git repository, include it ahead of the Magento version of the module and apply your patches into it.

You need to:

  • Remove the package from your vendor/magento folder if you’ve already installed it.
  • Add the url of your Git repository in the repositories list in composer.json (before repo.magento.com).
  • Add a require reference for the modules you’ve patched, i.e. magento/module-catalog, or magento/module-cms with the version nuber required.

This situation isn’t ideal.  If you want to upgrade Magento at some point, there is a likelihood that Magento will update the core module that you’ve patched.  This means that you would need to download a new version of an entire module, inspect it, patch it, and update your repository.  You’d then need to match verison numbers in your composer.json file and ensure that there were no conflicts.

Put everything in source control

You could simply ignore composer entirely, and include everything within source control. This would allow you to patch any required files, and simply roll them out across enviornments. This becomes a problem moving forward however when you upgrade your store, or you try to bolt something on, and something within core doesn’t play along quite as expected. It does mean however, with good branching, documentation and commit messages, you could keep track of what you’d patched and repatch if/when required.

Apply Patch files

As Composer is being used within the solution, it would be great if we could run a patch file every time that Composer install or Composer update is run.  This would mean that we wouldn’t have to setup a new repository for a module, (potentially per a project) – we could include the patch within the source control for the site.

If we upgrade Magento, then we don’t have a whole module to go through and check, we just have the small (compared to the whole module) amount of code to review.  We can see at this point whether the patch is still required – rewriting it if neccessary.

So, how can we do this?

Luckily, there’s already a Composer plugin that can do it for us.

https://github.com/cweagans/composer-patches

This plugin allows us to apply patches both from local and external sources when a composer install or composer update is made.

Firstly, tell composer to include the compose-patches module:

composer require cweagans/composer-patches

You should see this as a new entry in your composer.json file now.

Next, you need to get a patch file for what you’re wanting to patch.  In this example, I’ll reference https://raw.githubusercontent.com/allanpaiste/magento2-patches/master/Patch-Magento_Catalog-M2.1.0-image-attribute-backend-model-hardcoded-attribute-code-removal.patch

Fun fact – if you find any PR on Github, simply add “.patch” onto the URL for a full diff patch file.

Add your patch into a “patches” folder in your Magento document root.  You could sub folder this depending on how many patches you have so that things are organised, but a naming convention on your patch files should be enough.

Once this is done, you need to tell composer.json about the patch that it needs to include.

"require": {
   ....
}
"extra": {
     "magento-force": "override",
     "patches": {
         "magento/module-catalog": {
             "Fix: https://github.com/magento/magento2/issues/5438":
             "patches/Patch-Magento_Catalog-M2.1.0-image-attribute.patch"
         }
     }
 }

Here, we’re telling the patch system to patch "magento/module-catalog" with the patch file found in "patches/Patch-Magento_Catalog-M2.1.0-image-attribute-backend-model-hardcoded-attribute-code-removal.patch"

The key is just a description of what it’s fixing. It can be anything you want.

Next, just run a “composer update”.

Composer uninstalls the original package, and reinstalls it – subsequently applying the patch. You’ll see from the output whether or not this was successful. If it wasn’t, there’s a chance that your patch file isn’t quite right.

This last approach is the one we use here at Pinpoint.