From dee92696a855240d11b1c1fcfc5eafaf45000b17 Mon Sep 17 00:00:00 2001 From: Schnitzel <schnitzel@643820.no-reply.drupal.org> Date: Tue, 4 Oct 2022 19:06:18 +0000 Subject: [PATCH] Issue #3109082 by phenaproxima, Schnitzel, yash.rode, tedbow, wiifm, heddn, Leksat: Allow hosting platforms to declare that they don't support Package Manager --- automatic_updates.services.yml | 6 ++ package_manager/package_manager.services.yml | 4 + .../Validator/EnvironmentSupportValidator.php | 70 +++++++++++++++++ .../EnvironmentSupportValidatorTest.php | 75 +++++++++++++++++++ .../PackageManagerReadinessChecksTest.php | 1 + 5 files changed, 156 insertions(+) create mode 100644 package_manager/src/Validator/EnvironmentSupportValidator.php create mode 100644 package_manager/tests/src/Kernel/EnvironmentSupportValidatorTest.php diff --git a/automatic_updates.services.yml b/automatic_updates.services.yml index 9b26b15583..e78d85265d 100644 --- a/automatic_updates.services.yml +++ b/automatic_updates.services.yml @@ -73,6 +73,12 @@ services: - '@package_manager.validator.settings' tags: - { name: event_subscriber } + automatic_updates.validator.environment_support: + class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck + arguments: + - '@package_manager.validator.environment_support' + tags: + - { name: event_subscriber } automatic_updates.validator.composer_settings: class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck arguments: diff --git a/package_manager/package_manager.services.yml b/package_manager/package_manager.services.yml index cd785118a5..e5d60db0a7 100644 --- a/package_manager/package_manager.services.yml +++ b/package_manager/package_manager.services.yml @@ -51,6 +51,10 @@ services: - '@package_manager.path_locator' # Validators. + package_manager.validator.environment_support: + class: Drupal\package_manager\Validator\EnvironmentSupportValidator + tags: + - { name: event_subscriber } package_manager.validator.composer_executable: class: Drupal\package_manager\Validator\ComposerExecutableValidator arguments: diff --git a/package_manager/src/Validator/EnvironmentSupportValidator.php b/package_manager/src/Validator/EnvironmentSupportValidator.php new file mode 100644 index 0000000000..76679ba87f --- /dev/null +++ b/package_manager/src/Validator/EnvironmentSupportValidator.php @@ -0,0 +1,70 @@ +<?php + +namespace Drupal\package_manager\Validator; + +use Drupal\Core\Link; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\package_manager\Event\PreCreateEvent; +use Drupal\package_manager\Event\PreOperationStageEvent; +use Drupal\package_manager\Event\StatusCheckEvent; +use Drupal\Core\Url; + +/** + * Checks that the environment has support for Package Manager. + * + * @internal + * This is an internal part of Package Manager and may be changed or removed + * at any time without warning. External code should not interact with this + * class. + */ +final class EnvironmentSupportValidator implements PreOperationStageValidatorInterface { + + use StringTranslationTrait; + + /** + * The name of the environment variable to check. + * + * This environment variable, if defined, should be parseable by + * \Drupal\Core\Url::fromUri() and link to an explanation of why Package + * Manager is not supported in the current environment. + * + * @var string + */ + public const VARIABLE_NAME = 'DRUPAL_PACKAGE_MANAGER_NOT_SUPPORTED_HELP_URL'; + + /** + * {@inheritdoc} + */ + public function validateStagePreOperation(PreOperationStageEvent $event): void { + $message = $this->t('Package Manager is not supported by your environment.'); + + $help_url = getenv(static::VARIABLE_NAME); + if (empty($help_url)) { + return; + } + // If the URL is not parseable, catch the exception that Url::fromUri() + // would generate. + try { + $message = Link::fromTextAndUrl($message, Url::fromUri($help_url)) + ->toString(); + } + catch (\InvalidArgumentException $e) { + // No need to do anything here. The message just won't be a link. + } + $event->addError([$message]); + // If Package Manager is unsupported, there's no point in doing any more + // validation. + $event->stopPropagation(); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + return [ + PreCreateEvent::class => ['validateStagePreOperation', 200], + StatusCheckEvent::class => ['validateStagePreOperation', 200], + ]; + } + +} diff --git a/package_manager/tests/src/Kernel/EnvironmentSupportValidatorTest.php b/package_manager/tests/src/Kernel/EnvironmentSupportValidatorTest.php new file mode 100644 index 0000000000..bef49a244a --- /dev/null +++ b/package_manager/tests/src/Kernel/EnvironmentSupportValidatorTest.php @@ -0,0 +1,75 @@ +<?php + +namespace Drupal\Tests\package_manager\Kernel; + +use Drupal\package_manager\Event\PreCreateEvent; +use Drupal\package_manager\Event\PreOperationStageEvent; +use Drupal\package_manager\ValidationResult; +use Drupal\package_manager\Validator\EnvironmentSupportValidator; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * @covers \Drupal\package_manager\Validator\EnvironmentSupportValidator + * + * @group package_manager + */ +class EnvironmentSupportValidatorTest extends PackageManagerKernelTestBase implements EventSubscriberInterface { + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + $this->container->get('event_dispatcher')->addSubscriber($this); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $map = function (): string { + return 'assertValidationStopped'; + }; + return array_map($map, EnvironmentSupportValidator::getSubscribedEvents()); + } + + /** + * Ensures that the validator stops any further validation. + * + * @param \Drupal\package_manager\Event\PreOperationStageEvent $event + * The event object. + */ + public function assertValidationStopped(PreOperationStageEvent $event): void { + if ($event->getResults()) { + $this->assertTrue($event->isPropagationStopped()); + } + } + + /** + * Tests handling of an invalid URL in the environment support variable. + */ + public function testInvalidUrl(): void { + putenv(EnvironmentSupportValidator::VARIABLE_NAME . '=broken/url.org'); + + $result = ValidationResult::createError([ + 'Package Manager is not supported by your environment.', + ]); + $this->assertStatusCheckResults([$result]); + $this->assertResults([$result], PreCreateEvent::class); + } + + /** + * Tests that the validation message links to the provided URL. + */ + public function testValidUrl(): void { + $url = 'http://www.example.com'; + putenv(EnvironmentSupportValidator::VARIABLE_NAME . '=' . $url); + + $result = ValidationResult::createError([ + '<a href="' . $url . '">Package Manager is not supported by your environment.</a>', + ]); + $this->assertStatusCheckResults([$result]); + $this->assertResults([$result], PreCreateEvent::class); + } + +} diff --git a/tests/src/Kernel/ReadinessValidation/PackageManagerReadinessChecksTest.php b/tests/src/Kernel/ReadinessValidation/PackageManagerReadinessChecksTest.php index 2ac412e8c2..96296a11b5 100644 --- a/tests/src/Kernel/ReadinessValidation/PackageManagerReadinessChecksTest.php +++ b/tests/src/Kernel/ReadinessValidation/PackageManagerReadinessChecksTest.php @@ -54,6 +54,7 @@ class PackageManagerReadinessChecksTest extends AutomaticUpdatesKernelTestBase { 'Symlink validator' => ['package_manager.validator.symlink'], 'Settings validator' => ['package_manager.validator.settings'], 'Patches validator' => ['package_manager.validator.patches'], + 'Environment support validator' => ['package_manager.validator.environment_support'], ]; } -- GitLab