Commit dee92696 authored by Michael Schmid's avatar Michael Schmid Committed by Adam G-H
Browse files

Issue #3109082 by phenaproxima, Schnitzel, yash.rode, tedbow, wiifm, heddn,...

Issue #3109082 by phenaproxima, Schnitzel, yash.rode, tedbow, wiifm, heddn, Leksat: Allow hosting platforms to declare that they don't support Package Manager
parent 5e2745b5
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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:
+4 −0
Original line number Diff line number Diff line
@@ -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:
+70 −0
Original line number Diff line number Diff line
<?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],
    ];
  }

}
+75 −0
Original line number Diff line number Diff line
<?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);
  }

}
+1 −0
Original line number Diff line number Diff line
@@ -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'],
    ];
  }