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 library). And done. Sadly this does not work. As documented in the composer-patches readme.
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
}
}
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 for Drupal modules:
Having a
composer.json
file is not required for Drupal 9 compatibility. A Drupal 9 compatible info.yml file is required and is enough. If your project does have acomposer.json
file, having adrupal/core
version requirement is also not required for Drupal 9 compatibility. It is better not to provide adrupal/core
version requirement incomposer.json
because Drupal's composer facade will generate the appropriate metadata based on the info.yml file. If for some reason you do need to have adrupal/core
version requirement in yourcomposer.json
file'srequire
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
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. If you want to know how Git references work, you can look it up in the Git docs.
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.
Drupal Console ist not ready for Drupal 9
At the time of writing, the 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
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
🎉