You are currently viewing Patch TYPO3 and Extensions using Composer

Patch TYPO3 and Extensions using Composer

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.

Get a patch on review.TYPO3.org

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 patch directly from github website

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”.

Get a patch from bitbucket

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:

Successfull run of “composer update”

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 installor 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.

This Post Has 6 Comments

  1. Alex kellner

    I played a bit with this feature – thx Marcus for your blog post.
    As I invested a lot of time now, some `composer install` commands results in a message `Could not apply patch! Skipping. The error was: Cannot apply patch Build/Patches/DifferentLanguageFallbackThenDefaultLanguageForPages.patch` without defining what’s exactly wrong.
    In addition I added (as you mentioned above) the line `”composer-exit-on-patch-failure”: true` to the extra section in the composer.json and this stops the building process immediately as the patch could not be executed with a exception with exactly the same message.
    It turned out that two things helped me with my problem:
    1) I created the patchfile with the command `git diff > file.patch` now (instead of using PhpStorm)
    2) Because I want to patch typo3/cms this package has to be set on preferred-install to `”source”` (I think git is needed to execute a patch and this is not possible with “dist”).

    BTW: I would always use “composer-exit-on-patch-failure” because I don’t want to deploy an unpatched TYPO3 (in my case) to production.

  2. Anonymous

    5

Leave a Reply