From time to time there might the requirement that a feature or a bugfix should be available prior to an official release or should be backported to a legacy version of TYPO3. If you are still not using composer, after reading this post, you might really consider doing so. But now, let’s see how it works.
There are a few steps required to patch a composer package of your project.
Require the module
The first step is to require the module “composer-patches” written and maintained by Cameron Eagans (@cweagans).
composer require cweagans/composer-patches
This command updates your composer.json and .lock and downloads the necessary packages to patch later on.
Provide the patches
In the second step you need to provide the patches. The patches can come with your projects code in a separate directory or you an link an external resource accessible via https (or if necessary, with http).
Assuming that you are using the common folder layout of TYPO3 for composer installations, you should place the “patches” folder underneath a “build” folder. To achieve this, you need to create the folder with the following command:
mkdir -p build/patches
Maybe this is the first time, you are using a “build” folder. But you can use this also for saving assets of your frontend build toolchain, like javascript or scss. If you do not intend to use something like that, you can also place the patches folder next to your composer.json
.
Get a TYPO3 core patch
The easiest way to get an existing patch for TYPO3 is to use https://review.typo3.org. Direct your browser to the wanted review and click on “Download” on the upper right corner. Then you have several possibilities, but right now only the “Patch File” Option is interesting.
Now download the zip file and unpack it. The resulting file must be placed on the folder “build/patches” from step 1.
Get a patch for a TYPO3 extension from Github
With Github the procedure is slightly different. Here you need to navigate via the web interface to the desired commit or pull request.
For example: https://github.com/georgringer/news/commit/a5d4d30e8fe293c9aa3e50e4e4cf34e3a979ca37.
Adding a “.diff” to the URL shows you the plain diff of the changes: https://github.com/georgringer/news/commit/a5d4d30e8fe293c9aa3e50e4e4cf34e3a979ca37.diff
Now you can save the resulting browser window also to the patches folder. (BTW: The same mechanism also works for pending pull requests.)
Instead of using the plain commit hash as filename, I recommend to add a prefix for each extension. If you have many patches or just visit the folder from time to time, this makes it much easier to remember to which extension or core a patch belongs to.
Get a patch for a TYPO3 extension from Bitbucket
At this stage Bitbucket is a little bit more user friendly for existing commits … There is a link named “View raw commit”.
For complete pull requests I did not find any similar function. If you know one, I’d be happy to read it in the comments. :-)
Specify the patch(es) in composer.json
The third step is to adjust the composer configuration, so that your patches will be installed, while running a composer install
or composer update
.
Usually you will provide the patches within your composer.json
. The patch files are listed in the extra
section.
"extra": { "patches": { "typo3/cms": { "Bring RTE linkbrowser options back": "build/patches/core_19ff22c8.diff" } } }
Here you add a json array “patches” to the extra section, which contains the list of packages to patch and a series of patches to apply. The string before the patch url should contain a description, that helps to understand the purpose of the patch.
If you have too many patches and you do not want to pollute your root composer.json, there is also the possibility to outsource these definitions to an extra file.
"patches-file": "composer.patches.json"
In this file there is only the patches section from above
{ "patches": { "vendor/project": { "Patch title": "http://example.com/url/to/patch.patch" } } }
Sources of patches
Until now you learned only about providing patches from local sources. But it is also possible to pull patches via https. Therefore you must only replace the string containing the local folder with the public url of the patch.
I would be really careful about this option, especially, if you are not in control of the diff. A PR on Github, which is “work in progress” might defer over time from that want you originally wanted or expected.
Full example for patching TYPO3
Here is the full composer.json
` with the patches from above
{ "repositories": [ { "type": "path", "url": "packages/*/" }, { "type": "composer", "url": "https://composer.typo3.org/" } ], "name": "helhum/minimal-typo3-distribution", "description" : "Minimum viable TYPO3 Composer distribution", "license": "GPL-2.0+", "require": { "roave/security-advisories": "dev-master", "typo3/cms": "^8.7", "georgringer/news": "^6.0", "helhum/typo3-console": "^4.6", "helhum/site-example": "@dev", "cweagans/composer-patches": "^1.6" }, "scripts": { "package-states": [ "@php vendor/helhum/typo3-console/Scripts/typo3cms install:generatepackagestates" ], "folder-structure": [ "@php vendor/helhum/typo3-console/Scripts/typo3cms install:fixfolderstructure" ], "ext-setup": [ "@php vendor/helhum/typo3-console/Scripts/typo3cms install:extensionsetupifpossible" ], "post-autoload-dump": [ "@package-states", "@folder-structure", "@ext-setup" ] }, "extra": { "helhum/typo3-console": { "install-extension-dummy": false }, "typo3/cms": { "cms-package-dir": "{$vendor-dir}/typo3/cms", "web-dir": "web" }, "patches": { "typo3/cms": { "Bring back linkhandler options": "build/patches/core_19ff22c8.diff" }, "georgringer/news": { "Update news": "https://patch-diff.githubusercontent.com/raw/georgringer/news/pull/381.diff" } } } }
If everything wents fine, the output of your (ssh) console should look like this screenshot:
Error handling
At least source wise, this is where the error handling comes in. You need to make sure that the patches were applied successfully. If applying of a patch fails, the complete composer install
or composer update
should fail. This is activated with the option "composer-exit-on-patch-failure": true
in the extra section of your composer.json.
Other solutions: netresearch
As you might expect, there is more than one solution which can achieve this. The other one is from netresearch (@netresearch) on https://github.com/netresearch/composer-patches-plugin. The setup and configuration seems a little bit more complicated, not only at the first glance. But the advantage of this solution is, that it can support different patches for different version of packages. So this solution would perfectly fit, if you have a meta-package with patches, you would like to apply across various TYPO3 or extension versions.
Thank You!
I hope, that you could learn a little bit from this blog post. If so or if you know somebody, who could profit from it, please share this post via your favorite social network. For your convenience I added some share buttons at the end of this page.
I want to thank my supporters via patreon.com, who made this blog post possible:
If you appreciate my blog and want to support me, you can say “Thank You!”. Find out the possiblities here:
I found the blog post image on pixabay . It was published by real-napster under the Pixabay license. It was modified by myself using pablo on buffer.