jofitz: How to Patch Drupal Core and Contrib Modules

As a developer working with Drupal, it's essential to understand the importance of patching core and contrib modules. One of the first things I was taught when starting my journey with Drupal was "Never hack Core!" - an adage that still holds true in Drupal 11 as much as it did back in Drupal 7.

One of the key takeaways from this tutorial is that patching core and contrib modules should be done using Composer Patches, a package that enables you to apply patches to your dependencies. In essence, Composer Patches allows you to "patch" your dependencies, making it easier to apply bug fixes and features to Drupal core or contrib modules.

The best description of this package comes from the documentation: "A simple plugin for Composer that allows you to apply patches to your dependencies." The Composer Patches package is installed in the same way as a Drupal module. To install it, use the command:

composer require cweagans/composer-patches:^2.0

The details of all required patches are described in the "extra" section of composer.json. For example:

For instance, if you want to apply two patches to Drupal core and one patch to the Metatag module, the notation would look like this:

{
    "require": {
        "drupal/core": "^2.0"
        // Add other dependencies here
    },
    "extra": {
        "composer-patches": [
            {
                "package": "drupal/core",
                "path": "https://example.com/patch1.diff",
                "version": "1.3"
            },
            {
                "package": "drupal/core",
                "path": "https://example.com/patch2.diff",
                "version": "2.0"
            },
            {
                "package": "metatag",
                "path": "./patches/metatag.patch",
                "version": "1.2"
            }
        ]
    }
}

Both of the patches for core are stored remotely and accessed with a web address, but the patch for Metatag module is stored locally. Locally stored patches are specified by a path relative to the root of the project.

It's most likely that the patches you wish to apply come from an entry in the issue queue on drupal.org. I have not included it in the example above, but I recommend a naming convention that makes reference to the issue number. This makes it easier for anyone maintaining the code to locate the relevant issue and check for the latest patch.

I prefer using a naming convention like this: "Patch-12345" - where 12345 is the issue number. It makes it clear which patch corresponds to which issue, and it's also easy to identify the latest version.

However, not all patches come from drupal.org. There are cases where dev contributors upload their own patches or modified versions of existing ones. In such scenarios, it's crucial to be cautious when integrating these patches into your codebase.

In November 2020, contributing to a Drupal project shifted from a patch-based workflow to using merge requests. This change aimed to streamline the development process and improve collaboration between developers. However, it introduced new challenges - for instance, issues on drupal.org provide a link to a text file of the changes made in a merge request.

Beware! The content of this patch can change if further commits are pushed. This poses functionality risks or even security risks; a malicious user could add a commit that introduces vulnerabilities. To mitigate this risk, you can download the patch file and add it to your codebase, specifying the local path to it.

Version 2 of Composer provides an additional layer of security - the ability to lock the patch file version. This functionality will be discussed in full in my follow-up article. For now, it's essential to understand that this feature is available to help you manage patch versions more effectively.

This article covers the basic usage of Composer Packages, but only scratches the surface. Stay tuned for my next article discussing more advanced features - coming soon!