# Drupal 9: Fix Composer modules prohibiting upgrade


Drupal 9: Fix Composer modules prohibiting upgrade

How *packages.drupal.org* sets *drupal/core* version constraints that prevent updating to Drupal 9.

I went about to update a Drupal 8 project to Drupal 9. As preparation, I updated all Composer dependencies to their latest major versions and Drupal to the latest version of Drupal 8.

I quickly noticed that a few modules didn’t have a version out that supports Drupal 9 yet. Luckily all of them already had patches ready to fix this. Easy, just apply the patches inside the *composer.json*’s **extra: { patches: { } }** block (assuming you’re using the[ cweagans/composer-patches](https://github.com/cweagans/composer-patches) library). And done. Sadly this does not work. As documented in the [composer-patches readme](https://github.com/cweagans/composer-patches#patches-containing-modifications-to-composerjson-files).

Have a look at the **require** part.
*composer.json* file of the module:

```
{
  "name": "drupal/facets_pretty_paths",
  "type": "drupal-module",
  "description": "Facets Pretty Paths module.",
  "keywords": ["drupal"],
  "license": "GPL-2.0+",
  "minimum-stability": "dev",
  "prefer-stable": true,
  "authors": [
    {
      "name": "All contributors",
      "homepage": "https://www.drupal.org/node/2625160/committers"
    }
  ],
  **"require": {
    "drupal/facets": "~1",
    "drupal/pathauto": "~1"
  },**
  "require-dev": {
    "composer/installers": "^1.2",
    "cweagans/composer-patches": "~1.4",
    "dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
    "drupal-composer/drupal-scaffold": "^2.2",
    "drupal/admin_toolbar": "^1.24",
    "drupal/coder": "^8.3",
    "drupal/config_installer": "~1",
    "drupal/console": "~1",
    "drupal/search_api": "~1.5",
    "drush/drush": "~9",
    "openeuropa/drupal-core-require-dev": "~8.6@rc",
    "openeuropa/task-runner": "~1.0-beta2"
  },
  "repositories": [
    {
      "type": "composer",
      "url": "https://packages.drupal.org/8"
    }
  ],
  "autoload": {
    "psr-4": {
      "Drupal\\facets_pretty_paths\\": "./src"
    }
  },
  "autoload-dev": {
    "psr-4": {
      "Drupal\\Tests\\facets_pretty_paths\\": "./tests/src"
    }
  },
  "scripts": {
    "drupal-scaffold": "DrupalComposer\\DrupalScaffold\\Plugin::scaffold",
    "post-install-cmd": "./vendor/bin/run drupal:site-setup",
    "post-update-cmd": "./vendor/bin/run drupal:site-setup"
  },
  "extra": {
    "composer-exit-on-patch-failure": true,
    "enable-patching": true,
    "installer-paths": {
      "build/core": ["type:drupal-core"],
      "build/modules/contrib/{$name}": ["type:drupal-module"],
      "build/profiles/contrib/{$name}": ["type:drupal-profile"],
      "build/themes/contrib/{$name}": ["type:drupal-theme"]
    }
  },
  "config": {
    "sort-packages": true
  }
}
```


[Code Source](https://git.drupalcode.org/project/facets_pretty_paths/-/blob/6db024747637c7db3a3517f1adae13ba11a2d25b/composer.json)

This generates the following entry inside the *composer.lock* file:

```
{
    "name": "drupal/facets_pretty_paths",
    "version": "1.0.0",
    "source": {
        "type": "git",
        "url": "https://git.drupalcode.org/project/facets_pretty_paths.git",
        "reference": "8.x-1.0"
    },
    "dist": {
        "type": "zip",
        "url": "https://ftp.drupal.org/files/projects/facets_pretty_paths-8.x-1.0.zip",
        "reference": "8.x-1.0",
        "shasum": "c6660cd296dd68e2f22d42337035eca65ce94ffb"
    },
    "require": {
       ** "drupal/core": "~8.0",**
        "drupal/facets": "~1",
        "drupal/pathauto": "~1"
    },
    "require-dev": {
        "composer/installers": "^1.2",
        "cweagans/composer-patches": "~1.4",
        "dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
        "drupal-composer/drupal-scaffold": "^2.2",
        "drupal/admin_toolbar": "^1.24",
        "drupal/coder": "^8.3",
        "drupal/config_installer": "~1",
        "drupal/console": "~1",
        "drupal/search_api": "~1.5",
        "drush/drush": "~9",
        "openeuropa/drupal-core-require-dev": "~8.6@rc",
        "openeuropa/task-runner": "~1.0-beta2"
    },
    "type": "drupal-module",
    "extra": {
        "branch-alias": {
            "dev-1.x": "1.x-dev"
        },
        "drupal": {
            "version": "8.x-1.0",
            "datestamp": "1568102885",
            "security-coverage": {
                "status": "not-covered",
                "message": "Project has not opted into security advisory coverage!"
            }
        },
        "composer-exit-on-patch-failure": true,
        "enable-patching": true,
        "installer-paths": {
            "build/core": [
                "type:drupal-core"
            ],
            "build/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "build/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "build/themes/contrib/{$name}": [
                "type:drupal-theme"
            ]
        }
    },
    "autoload": {
        "psr-4": {
            "Drupal\\facets_pretty_paths\\": "./src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Drupal\\Tests\\facets_pretty_paths\\": "./tests/src"
        }
    },
    "notification-url": "https://packages.drupal.org/8/downloads",
    "scripts": {
        "drupal-scaffold": [
            "DrupalComposer\\DrupalScaffold\\Plugin::scaffold"
        ],
        "post-install-cmd": [
            "./vendor/bin/run drupal:site-setup"
        ],
        "post-update-cmd": [
            "./vendor/bin/run drupal:site-setup"
        ]
    },
    "license": [
        "GPL-2.0+"
    ],
    "authors": [
        {
            "name": "All contributors",
            "homepage": "https://www.drupal.org/node/2625160/committers"
        },
        {
            "name": "Upchuk",
            "homepage": "https://www.drupal.org/user/1885838"
        },
        {
            "name": "dasjo",
            "homepage": "https://www.drupal.org/user/228295"
        }
    ],
    "description": "Facets Pretty Paths module.",
    "homepage": "https://www.drupal.org/project/facets_pretty_paths",
    "keywords": [
        "drupal"
    ],
    "support": {
        "source": "https://git.drupalcode.org/project/facets_pretty_paths"
    }
}
```


Check out the require part. **“drupal/core”: “~8.0”** is also required. Hmm.. looks like the drupal.org Packagist adds this automatically 🤔

I found this in the [documentation about using composer.json files](https://www.drupal.org/docs/creating-custom-modules/add-a-composerjson-file#s-drupal-9-compatibility) for Drupal modules:
> Having a `composer.json` file is not required for Drupal 9 compatibility. A [Drupal 9 compatible info.yml file](https://www.drupal.org/docs/8/creating-custom-modules/let-drupal-8-know-about-your-module-with-an-infoyml-file#s-specifying-core-version-requirement) is required and is enough. If your project does have a `composer.json` file, having a `drupal/core` version requirement is also not required for Drupal 9 compatibility. **It is better not to provide **a `drupal/core` version requirement in `composer.json` because [Drupal's composer facade](https://www.drupal.org/project/project_composer) will generate the appropriate metadata based on the info.yml file. If for some reason you do need to have a `drupal/core` version requirement in your `composer.json` file's `require` section, then it needs to be Drupal 9 compatible.

Alright, so the Packagist takes the version requirement from the module’s *.info.yml* file then. Which looks like this for this particular module:

```
name: 'Facets Pretty Paths'
type: module
description: 'Pretty paths for Facets.'
**core: 8.x**
package: Search
dependencies:
  - facets:facets
  - pathauto:pathauto
```


[Code Source](https://git.drupalcode.org/project/facets_pretty_paths/-/blob/6db024747637c7db3a3517f1adae13ba11a2d25b/facets_pretty_paths.info.yml)

Since the updated version requirement (**core_version_requirement: ^8 || ^9**) is not committed to the module’s *.info.yml* file yet, and only available as a patch, the Packagist adds the requirement for Drupal 8 to the **composer.json** file, and does not allow Drupal 9.

Not great..

**Option 1:
**You can copy the Git repo to your own Git instance (or GitHub, GitLab, whatever..) of the module and add a repository of type** “git”** to the **repositories** section inside the *composer.json* (Note: Needs te be above the packages.drupal.org entry).

**Option 2:
**I prefer this variant.
Create a *composer.json* repositories entry of type **“package”.
**For example:

```
"**my-author**/facets_pretty_paths": {
    "type": "package",
    "package": {
        "name": "**my-author**/facets_pretty_paths",
        "version": "dev-6db0247",
        "source": {
            "type": "git",
            "url": "https://git.drupalcode.org/project/facets_pretty_paths.git",
            "reference": "6db0247"
        },
        "require": {
            "drupal/core": "^8.8 || ^9.0"
        },
        "type": "drupal-module"
    }
}
```


This way you “create your own” module using the Git repository of the module.

Note the **my-author** part. Otherwise Composer would always get the module from the packages.drupal.org repository, even when setting the **— prefer-source **flag. I couldn’t find any **.zip** URLs for specific commits that could be added as “dist” to the package definition.

You can specify any version using the “version” and “reference” properties. [Documented here.](https://getcomposer.org/doc/05-repositories.md#package-2) If you want to know how Git references work, you can look it up in the [Git docs](https://git-scm.com/book/en/v2/Git-Internals-Git-References).

In this case I used a specific commit, because the patch that makes the module compatible with Drupal 9 didn’t apply to a tagged version.

You can remove this and replace your “custom module” with the real one once the maintainer made it compatible with Drupal 9.

*Option ?:* Feel free to post a comment if you found a better solution :)

## Resolving issues with Drupal Console & Drush

### If you use Drush

I needed to add **consolidation/site-process** to the [Composer update statement](#05f9).

### Drupal Console ist not ready for Drupal 9

At the time of writing, the [drupal/console](https://github.com/hechoendrupal/drupal-console) library does not support Drupal 9 yet. Thus I needed to remove it.

```
composer remove drupal/console
```


There is an open issue for Drupal 9 compatibility: [https://github.com/hechoendrupal/drupal-console/issues/4250](https://github.com/hechoendrupal/drupal-console/issues/4250)

## Finally: Updating Drupal Core

Change the version constraint of **drupal/core** to **^9.0** inside the *composer.json* file.

Update Drupal Core and it’s dependencies:

```
composer update symfony/* symfony-cmf/* twig/twig laminas/* drupal/core
```


🎉
