Drupal tries to add new features, make improvements, and change the way it is built with each big release. Drupal 10 was released in December 2022 as the latest big update. It had a lot of great new features and dependencies. Contributed modules are a big part of what makes every Drupal application work. These modules add to Drupal’s core features, which makes it easier for developers to change and adapt Drupal websites to meet unique needs.

It’s important to keep in mind that while some contributed modules will work perfectly with Drupal 10 because they have compatible versions, others might need more attention and changes. In this post, we’ll talk about how you can use Drupal 9 modules in a Drupal 10 project and still meet its standards and requirements.

Getting the modules to work on Drupal 10

How do we plan to move to Drupal 10 and add these features at the same time? Using the available patches is a possibility, but whether or not it will work relies on how our project handles version control and what hosting platform is being used.

Patches can be applied directly if our remote repository includes all repositories, like modules/contrib/* and themes/contrib/*, and the hosting site doesn’t ignore them. But if these sources aren’t used, and since Drupal projects now use a composer-based structure, we might have to add the patches directly to the composer.json file. If the module doesn’t depend on any other libraries or modules, we just ignore the core_version_requirement key with drupal/lenient and add it. But if the module depends on another module that is not D10-compatible, you will have to do the steps below. 

Using Drupal 9 features that don’t work with Drupal 10    

Adding Drupal 9 modules that aren’t compatible with Drupal 10 requires a few important steps in the composer.json configuration:

  1. Inclusion of Module folder: First, add the module’s folder to the composer.json file.
  2. Module Key Update: Change the key of the module as needed to make sure it works well.
  3. Integration of Patches: Add the correct patch under “Patches” to solve compatibility problems.
  4. Root Composer requirement: Add the module’s requirement to the root composer.json. 

Note: Please keep in mind that the “drupal/header_and_footer_scripts” module will be used as an example throughout this piece. As of the time this piece was written, there was no Drupal 10 release of this module.

Module Repository is added to composer.json

As the composer is a dependency manager, it will check if it works with the composer.json file of other modules, the version of Drupal, the version of PHP, etc.

So, you will need to tell the composer not to check the requirement and directly clone the directory from repositories.

Add the module’s repositories in the following way to the composer.json file at the top:

“repositories”: [  

   “header_and_footer_scripts”: {  

          “type”: “package”,  

          “package”: {  

              “name”: “drupal-gitlab/header_and_footer_scripts”,  

              “type”: “drupal-module”,  

              “version”: “dev-3.0.x@dev”,  

              “source”: {  

                  “type”: “git”,  

                  “url”: “https://git.drupalcode.org/project/header_and_footer_scripts.git”,  

                  “reference”: “3.0.x”  

              }  

          }  

      }  

  ]  

Here, on the page about the project, you can find information about the source. Copy the address.  

Here, the name of the package is drupal-gitlab/module-name, and the reference should be the version of the module that was used to make the patch.

Change Module Key

Now, since we used drupal-gitlab/header_and_footer_scripts as the package name (as stated above), let’s replace/add the same thing under the required key of composer.json so that composer sees it as a dependency and tries to download the repositories into our codebase.

“require”: {  

  “drupal-gitlab/header_and_footer_scripts: “dev-3.0.x@dev”  

}

Here, you should look at the version listed in the source as the package version.

Integration of Patch

To use the patches, you will need the “cweagans/composer-patches” so that you can apply the patch.

“extra”: {  

      “patches”: {  

          “drupal-gitlab/header_and_footer_scripts”: {  

              “Drupal 10 compatibility”: “patches/header_and_footer_scripts_d10.patch”  

      }  

  },

There are two ways to put on the patch:

1 A patch file says: 

  1. Get the patch file and put it in the place where your project files are kept.
  2. Refer to the file named in the code above.

 

2 From a link:

  1. The Drupal.org bugs page has the URL for the patch.
  2. Put the URL in place of the file name.

 

If there isn’t a patch already, you can make one by using the “Upgrade Status” or “Rector” module to check for outdated methods and other problems.

Dependency on Root Composer

Some modules’ repositories may have a composer.json file in them. It is important to check these requirements and, if needed, add them to our root composer.json file. This safety measure is important, especially since we said in our directions that dependency checks should be skipped.

When looking at the composer.json file of “header_and_footer_scripts” here, it’s important to follow these rules:

  • If a module’s composer.json has a “require” key with a list of dependencies, these should be added to the composer.json at the top of our project.
  • During the process, you can ignore the things on the list that have to do with verification, such as PHP and Drupal version requirements.

It is very important to remember that if the needed dependencies aren’t there, the site could break down completely.

Putting it through its paces

Let’s do the Drupal 10 upgrade for the same module both the standard way and the way we showed above in a Drupal 10 installation that hasn’t been changed.

Using the tried-and-true method:

{

“name”: “drupal/drupal”,

  “description”: “Drupal is an open source content management platform powering millions of websites and applications.”,

  “type”: “project”,

  “license”: “GPL-2.0-or-later”,

  “homepage”: “https://www.drupal.org/project/drupal”,

  “support”: {

      “docs”: “https://www.drupal.org/docs/user_guide/en/index.html”,

      “chat”: “https://www.drupal.org/node/314178”

  },

  “require”: {

      “composer/installers”: “^2.0”,

      “drupal/core”: “self.version”,

      “drupal/core-project-message”: “self.version”,

      “drupal/core-vendor-hardening”: “self.version”,

      “drupal/header_and_footer_scripts”: “^3.0”

  },

  “require-dev”: {

      “behat/mink”: “^1.10”,

      “behat/mink-browserkit-driver”: “^2.1”,

      “behat/mink-selenium2-driver”: “^1.4”,

      “colinodell/psr-testlogger”: “^1.2”,

      “composer/composer”: “^2.4”,

      “drupal/coder”: “^8.3.10”,

      “instaclick/php-webdriver”: “^1.4.1”,

      “justinrainbow/json-schema”: “^5.2”,

      “mglaman/phpstan-drupal”: “^1.1.34”,

      “mikey179/vfsstream”: “^1.6.11”,

      “phpspec/prophecy-phpunit”: “^2”,

      “phpstan/extension-installer”: “^1.1”,

      “phpstan/phpstan”: “^1.10.1”,

      “phpstan/phpstan-phpunit”: “^1.3.11”,

      “phpunit/phpunit”: “^9.5”,

      “symfony/browser-kit”: “^6.3”,

      “symfony/css-selector”: “^6.3”,

      “symfony/dom-crawler”: “^6.3”,

      “symfony/error-handler”: “^6.3”,

      “symfony/filesystem”: “^6.3”,

      “symfony/finder”: “^6.3”,

      “symfony/lock”: “^6.3”,

      “symfony/phpunit-bridge”: “^6.3”,

      “symfony/var-dumper”: “^6.3”

  },

  “replace”: {

      “symfony/polyfill-php72”: “*”,

      “symfony/polyfill-php73”: “*”,

      “symfony/polyfill-php74”: “*”,

      “symfony/polyfill-php80”: “*”,

      “symfony/polyfill-php81”: “*”

  },

  “minimum-stability”: “dev”,

  “prefer-stable”: true,

  “config”: {

      “preferred-install”: “dist”,

      “sort-packages”: true,

      “platform”: {

          “php”: “8.1.0”

      },

      “allow-plugins”: {

          “composer/installers”: true,

          “drupal/core-project-message”: true,

          “drupal/core-vendor-hardening”: true,

          “phpstan/extension-installer”: true,

          “dealerdirect/phpcodesniffer-composer-installer”: true

      }

  },

  “extra”: {

      “_readme”: [

          “By default Drupal loads the autoloader from ./vendor/autoload.php.”,

          “To change the autoloader you can edit ./autoload.php.”,

          “This file specifies the packages.drupal.org repository.”,

          “You can read more about this composer repository at:”,

          “https://www.drupal.org/node/2718229”

      ],

      “installer-paths”: {

          “core”: [“type:drupal-core”],

          “libraries/{$name}”: [“type:drupal-library”],

          “modules/contrib/{$name}”: [“type:drupal-module”],

          “profiles/contrib/{$name}”: [“type:drupal-profile”],

          “themes/contrib/{$name}”: [“type:drupal-theme”],

          “drush/Commands/contrib/{$name}”: [“type:drupal-drush”],

          “modules/custom/{$name}”: [“type:drupal-custom-module”],

          “themes/custom/{$name}”: [“type:drupal-custom-theme”]

      },

      “drupal-core-project-message”: {

          “post-install-cmd-message”: [

              “<bg=blue;fg=white>drupal/drupal</>: This package is meant for core development,”,

              ”               and not intended to be used for production sites.”,

              ”               See: https://www.drupal.org/node/3082474″

          ],

          “post-create-project-cmd-message”: [

              “<bg=red;fg=white>drupal/drupal</>: This package is meant for core development,”,

              ”               and not intended to be used for production sites.”,

              ”               See: https://www.drupal.org/node/3082474″

          ]

      }

  },

  “autoload”: {

      “psr-4”: {

          “Drupal\\Core\\Composer\\”: “core/lib/Drupal/Core/Composer”,

          “Drupal\\Composer\\”: “composer”

      }

  },

  “scripts”: {

      “pre-install-cmd”: “Drupal\\Composer\\Composer::ensureComposerVersion”,

      “pre-update-cmd”: “Drupal\\Composer\\Composer::ensureComposerVersion”,

      “pre-autoload-dump”: “Drupal\\Core\\Composer\\Composer::preAutoloadDump”,

      “drupal-phpunit-upgrade-check”: “Drupal\\Core\\Composer\\Composer::upgradePHPUnit”,

      “drupal-phpunit-upgrade”: [

          “@composer update phpunit/phpunit –with-dependencies –no-progress”

      ],

      “post-update-cmd”: [

          “Drupal\\Composer\\Composer::generateMetapackages”,

          “Drupal\\Composer\\Composer::generateComponentPackages”

      ],

      “phpcs”: “phpcs –standard=core/phpcs.xml.dist –parallel=$(nproc) –“,

      “phpcbf”: “phpcbf –standard=core/phpcs.xml.dist –parallel=$(nproc) –“

  },

  “repositories”: [

      {

          “type”: “path”,

          “url”: “core”

      },

      {

          “type”: “path”,

          “url”: “composer/Plugin/ProjectMessage”

      },

      {

          “type”: “path”,

          “url”: “composer/Plugin/VendorHardening”

      },

      {

          “type”: “composer”,

          “url”: “https://packages.drupal.org/8”

      }

  ]

}

Source: Specbee

When you try to update the dependencies, you will get an error message that says, “Your requirements could not be resolved to an installable set of packages.”

Using the method we’ve already talked about:

{

  “name”: “drupal/drupal”,

  “description”: “Drupal is an open source content management platform powering millions of websites and applications.”,

  “type”: “project”,

  “license”: “GPL-2.0-or-later”,

  “homepage”: “https://www.drupal.org/project/drupal”,

  “support”: {

      “docs”: “https://www.drupal.org/docs/user_guide/en/index.html”,

      “chat”: “https://www.drupal.org/node/314178”

  },

  “require”: {

      “composer/installers”: “^2.0”,

      “cweagans/composer-patches”: “^1.7”,

      “drupal/core”: “self.version”,

      “drupal/core-project-message”: “self.version”,

      “drupal/core-vendor-hardening”: “self.version”,

      “drupal-gitlab/header_and_footer_scripts”: “dev-3.0.x@dev”

  },

  “require-dev”: {

      “behat/mink”: “^1.10”,

      “behat/mink-browserkit-driver”: “^2.1”,

      “behat/mink-selenium2-driver”: “^1.4”,

      “colinodell/psr-testlogger”: “^1.2”,

      “composer/composer”: “^2.4”,

      “drupal/coder”: “^8.3.10”,

      “instaclick/php-webdriver”: “^1.4.1”,

      “justinrainbow/json-schema”: “^5.2”,

      “mglaman/phpstan-drupal”: “^1.1.34”,

      “mikey179/vfsstream”: “^1.6.11”,

      “phpspec/prophecy-phpunit”: “^2”,

      “phpstan/extension-installer”: “^1.1”,

      “phpstan/phpstan”: “^1.10.1”,

      “phpstan/phpstan-phpunit”: “^1.3.11”,

      “phpunit/phpunit”: “^9.5”,

      “symfony/browser-kit”: “^6.3”,

      “symfony/css-selector”: “^6.3”,

      “symfony/dom-crawler”: “^6.3”,

      “symfony/error-handler”: “^6.3”,

      “symfony/filesystem”: “^6.3”,

      “symfony/finder”: “^6.3”,

      “symfony/lock”: “^6.3”,

      “symfony/phpunit-bridge”: “^6.3”,

      “symfony/var-dumper”: “^6.3”

  },

  “replace”: {

      “symfony/polyfill-php72”: “*”,

      “symfony/polyfill-php73”: “*”,

      “symfony/polyfill-php74”: “*”,

      “symfony/polyfill-php80”: “*”,

      “symfony/polyfill-php81”: “*”

  },

  “minimum-stability”: “dev”,

  “prefer-stable”: true,

  “config”: {

      “preferred-install”: “dist”,

      “sort-packages”: true,

      “platform”: {

          “php”: “8.1.0”

      },

      “allow-plugins”: {

          “composer/installers”: true,

          “drupal/core-project-message”: true,

          “drupal/core-vendor-hardening”: true,

          “phpstan/extension-installer”: true,

          “dealerdirect/phpcodesniffer-composer-installer”: true,

          “cweagans/composer-patches”: true

      }

  },

  “extra”: {

      “patches”: {

          “drupal-gitlab/header_and_footer_scripts”: {

              “Drupal 10 compatibility”: “patches/header_and_footer_scripts_d10.patch”

          }   

      },

      “_readme”: [

          “By default Drupal loads the autoloader from ./vendor/autoload.php.”,

          “To change the autoloader you can edit ./autoload.php.”,

          “This file specifies the packages.drupal.org repository.”,

          “You can read more about this composer repository at:”,

          “https://www.drupal.org/node/2718229”

      ],

      “installer-paths”: {

          “core”: [“type:drupal-core”],

          “libraries/{$name}”: [“type:drupal-library”],

          “modules/contrib/{$name}”: [“type:drupal-module”],

          “profiles/contrib/{$name}”: [“type:drupal-profile”],

          “themes/contrib/{$name}”: [“type:drupal-theme”],

          “drush/Commands/contrib/{$name}”: [“type:drupal-drush”],

          “modules/custom/{$name}”: [“type:drupal-custom-module”],

          “themes/custom/{$name}”: [“type:drupal-custom-theme”]

      },

      “drupal-core-project-message”: {

          “post-install-cmd-message”: [

              “<bg=blue;fg=white>drupal/drupal</>: This package is meant for core development,”,

              ”               and not intended to be used for production sites.”,

              ”               See: https://www.drupal.org/node/3082474″

          ],

          “post-create-project-cmd-message”: [

              “<bg=red;fg=white>drupal/drupal</>: This package is meant for core development,”,

              ”               and not intended to be used for production sites.”,

              ”               See: https://www.drupal.org/node/3082474″

          ]

      }

  },

  “autoload”: {

      “psr-4”: {

          “Drupal\\Core\\Composer\\”: “core/lib/Drupal/Core/Composer”,

          “Drupal\\Composer\\”: “composer”

      }

  },

  “scripts”: {

      “pre-install-cmd”: “Drupal\\Composer\\Composer::ensureComposerVersion”,

      “pre-update-cmd”: “Drupal\\Composer\\Composer::ensureComposerVersion”,

      “pre-autoload-dump”: “Drupal\\Core\\Composer\\Composer::preAutoloadDump”,

      “drupal-phpunit-upgrade-check”: “Drupal\\Core\\Composer\\Composer::upgradePHPUnit”,

      “drupal-phpunit-upgrade”: [

          “@composer update phpunit/phpunit –with-dependencies –no-progress”

      ],

      “post-update-cmd”: [

          “Drupal\\Composer\\Composer::generateMetapackages”,

          “Drupal\\Composer\\Composer::generateComponentPackages”

      ],

      “phpcs”: “phpcs –standard=core/phpcs.xml.dist –parallel=$(nproc) –“,

      “phpcbf”: “phpcbf –standard=core/phpcs.xml.dist –parallel=$(nproc) –“

  },

  “repositories”: [

      {

          “type”: “path”,

          “url”: “core”

      },

      {

          “type”: “path”,

          “url”: “composer/Plugin/ProjectMessage”

      },

      {

          “type”: “path”,

          “url”: “composer/Plugin/VendorHardening”

      },

      {

          “type”: “composer”,

          “url”: “https://packages.drupal.org/8”

      },

      {

          “type”: “package”,

          “package”: {

              “name”: “drupal-gitlab/header_and_footer_scripts”,

              “type”: “drupal-module”,

              “version”: “dev-3.0.x@dev”,

              “source”: {

                  “type”: “git”,

                  “url”: “https://git.drupalcode.org/project/header_and_footer_scripts.git”,

                  “reference”: “3.0.x”

              }

          }

      }

  ]

}

Source: Specbee

Once Drupal 10 has a version of the module, remove the code above and add “drupal/module-name”: “version” as usual. 

Conclusion

Looking to the future, the fact that Drupal 10 uses modern technologies and follows industry standards puts it in a good position to lead the way in providing cutting-edge digital experiences. Adding modules that work with Drupal 9 to your Drupal 10 project isn’t just about integrating code; it’s also about making sure your site can thrive in the changing digital environment of the future.

At Appic Softwares, our goal is to help your digital projects use Drupal to its fullest extent. Our experienced experts know all about Drupal 10’s new features and have the skills to combine modules smoothly, making sure that your website stays on the cutting edge of technology. We can help you move your Drupal 10 project forward with confidence and new ideas if you work with us. 

Contact us now!

This blog is inspired by <https://www.specbee.com/blogs/how-incorporate-drupal-9-compatible-modules-your-drupal-10-project>