From a1cf378f644beafed54e689c7946a76b67e47875 Mon Sep 17 00:00:00 2001 From: "omkar.podey" <omkar.podey@3685158.no-reply.drupal.org> Date: Fri, 30 Sep 2022 16:45:07 +0000 Subject: [PATCH] Issue #3302524 by omkar.podey, phenaproxima, kunal.sachdev: Support Composer 2.2 --- automatic_updates.module | 2 +- package_manager/package_manager.module | 2 +- .../Validator/ComposerExecutableValidator.php | 10 +++--- .../ComposerExecutableValidatorTest.php | 32 ++++++++++++++++--- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/automatic_updates.module b/automatic_updates.module index 2c5d74c39b..79baecbeca 100644 --- a/automatic_updates.module +++ b/automatic_updates.module @@ -28,7 +28,7 @@ function automatic_updates_help($route_name, RouteMatchInterface $route_match) { $output .= '</p>'; $output .= '<p>' . t('Additionally, Automatic Updates periodically runs checks to ensure that updates can be installed, and will warn site administrators if problems are detected.') . '</p>'; $output .= '<h3>' . t('Requirements') . '</h3>'; - $output .= '<p>' . t('Automatic Updates requires Composer @version or later available as an executable, and PHP must have permission to run it. The path to the executable may be set in the <code>package_manager.settings:executables.composer</code> config setting, or it will be automatically detected.', ['@version' => ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION]) . '</p>'; + $output .= '<p>' . t('Automatic Updates requires a Composer executable whose version satisfies <code>@version</code>, and PHP must have permission to run it. The path to the executable may be set in the <code>package_manager.settings:executables.composer</code> config setting, or it will be automatically detected.', ['@version' => ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION_CONSTRAINT]) . '</p>'; $output .= '<p>' . t('For more information, see the <a href=":automatic-updates-documentation">online documentation for the Automatic Updates module</a>.', [':automatic-updates-documentation' => 'https://www.drupal.org/docs/8/update/automatic-updates']) . '</p>'; return $output; } diff --git a/package_manager/package_manager.module b/package_manager/package_manager.module index e5d99a3125..f369d8419a 100644 --- a/package_manager/package_manager.module +++ b/package_manager/package_manager.module @@ -21,7 +21,7 @@ function package_manager_help($route_name, RouteMatchInterface $route_match) { $output .= '<h3 id="package-manager-requirements">' . t('Requirements') . '</h3>'; $output .= '<ul>'; $output .= ' <li>' . t("The Drupal application's codebase must be writable in order to use Automatic Updates. This includes Drupal core, modules, themes and the Composer dependencies in the <code>vendor</code> directory. This makes Automatic Updates incompatible with some hosting platforms.") . '</li>'; - $output .= ' <li>' . t('Package Manager requires Composer @version or later available as an executable, and PHP must have permission to run it. It should be detected automatically. If not, see <a href="#package-manager-faq-composer-not-found">What if it says the "composer" executable cannot be found?</a>.', ['@version' => ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION]) . '</li>'; + $output .= ' <li>' . t('Package Manager requires a Composer executable whose version satisfies <code>@version</code>, and PHP must have permission to run it. The path to the executable may be stored in config, or it will be automatically detected. To set the path to Composer, you can add the following line to settings.php:', ['@version' => ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION_CONSTRAINT]) . '</li>'; $output .= '</ul>'; $output .= '<h3 id="package-manager-limitations">' . t('Limitations') . '</h3>'; diff --git a/package_manager/src/Validator/ComposerExecutableValidator.php b/package_manager/src/Validator/ComposerExecutableValidator.php index e1c40f7806..9fa5315ae8 100644 --- a/package_manager/src/Validator/ComposerExecutableValidator.php +++ b/package_manager/src/Validator/ComposerExecutableValidator.php @@ -2,7 +2,7 @@ namespace Drupal\package_manager\Validator; -use Composer\Semver\Comparator; +use Composer\Semver\Semver; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Url; use Drupal\package_manager\Event\PreCreateEvent; @@ -31,7 +31,7 @@ final class ComposerExecutableValidator implements PreOperationStageValidatorInt * * @var string */ - public const MINIMUM_COMPOSER_VERSION = '2.3.5'; + public const MINIMUM_COMPOSER_VERSION_CONSTRAINT = '~2.2.12 || ^2.3.5'; /** * The Composer runner. @@ -83,9 +83,9 @@ final class ComposerExecutableValidator implements PreOperationStageValidatorInt } if ($this->version) { - if (Comparator::lessThan($this->version, static::MINIMUM_COMPOSER_VERSION)) { - $message = $this->t('Composer @minimum_version or later is required, but version @detected_version was detected.', [ - '@minimum_version' => static::MINIMUM_COMPOSER_VERSION, + if (!Semver::satisfies($this->version, static::MINIMUM_COMPOSER_VERSION_CONSTRAINT)) { + $message = $this->t('A Composer version which satisfies <code>@minimum_version</code> is required, but version @detected_version was detected.', [ + '@minimum_version' => static::MINIMUM_COMPOSER_VERSION_CONSTRAINT, '@detected_version' => $this->version, ]); $this->setError($message, $event); diff --git a/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php b/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php index 5bbf643593..07dd32553b 100644 --- a/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php +++ b/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php @@ -81,18 +81,38 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase { // in the validation result, so we need a function to churn out those fake // results for the test method. $unsupported_version = function (string $version): ValidationResult { - $minimum_version = ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION; + $minimum_version = ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION_CONSTRAINT; return ValidationResult::createError([ - "Composer $minimum_version or later is required, but version $version was detected.", + "A Composer version which satisfies <code>$minimum_version</code> is required, but version $version was detected.", ]); }; return [ 'Minimum version' => [ - ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION, + '2.2.12', [], ], + '2.2.13' => [ + '2.2.13', + [], + ], + '2.3.6' => [ + '2.3.6', + [], + ], + '2.4.1' => [ + '2.4.1', + [], + ], + '2.2.11' => [ + '2.2.11', + [$unsupported_version('2.2.11')], + ], + '2.3.4' => [ + '2.3.4', + [$unsupported_version('2.3.4')], + ], '2.1.6' => [ '2.1.6', [$unsupported_version('2.1.6')], @@ -188,7 +208,11 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase { return $message . ' See <a href="' . $url . '">the help page</a> for information on how to configure the path to Composer.'; }; foreach ($expected_results as $index => $result) { - $messages = array_map($map, $result->getMessages()); + // The original messages contain HTML, so they need to be properly escaped + // before they are modified, to ensure that they are accurately compared + // with the messages returned by the validator. + $messages = array_map('\Drupal\Component\Utility\Html::escape', $result->getMessages()); + $messages = array_map($map, $messages); $expected_results[$index] = ValidationResult::createError($messages); } $this->assertStatusCheckResults($expected_results); -- GitLab