From 963df7bbe7ae1b61f9212b427c46caeb2b6c436b Mon Sep 17 00:00:00 2001
From: tedbow <tedbow@240860.no-reply.drupal.org>
Date: Tue, 6 Sep 2022 19:18:49 +0000
Subject: [PATCH] Issue #3304367 by tedbow, bnjmnm, phenaproxima, TravisCarden:
 Add StatusCheckEvent to report errors and warnings in the staging error to
 the user

---
 .../src/Event/StatusCheckEvent.php            | 29 +++++++++++++++++++
 .../Validator/ComposerExecutableValidator.php |  2 ++
 .../Validator/ComposerPatchesValidator.php    |  2 ++
 .../Validator/ComposerSettingsValidator.php   |  2 ++
 .../src/Validator/DiskSpaceValidator.php      |  2 ++
 .../src/Validator/MultisiteValidator.php      |  2 ++
 .../src/Validator/PendingUpdatesValidator.php |  2 ++
 .../src/Validator/SettingsValidator.php       |  2 ++
 .../src/Validator/SymlinkValidator.php        |  2 ++
 .../Validator/WritableFileSystemValidator.php |  2 ++
 .../ComposerExecutableValidatorTest.php       |  3 ++
 .../Kernel/ComposerPatchesValidatorTest.php   |  3 +-
 .../Kernel/ComposerSettingsValidatorTest.php  |  1 +
 .../src/Kernel/DiskSpaceValidatorTest.php     |  1 +
 .../src/Kernel/MultisiteValidatorTest.php     |  1 +
 .../Kernel/PackageManagerKernelTestBase.php   | 13 +++++++++
 .../Kernel/PendingUpdatesValidatorTest.php    |  3 ++
 .../src/Kernel/SettingsValidatorTest.php      |  1 +
 .../tests/src/Kernel/SymlinkValidatorTest.php |  1 +
 .../WritableFileSystemValidatorTest.php       |  2 ++
 20 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 package_manager/src/Event/StatusCheckEvent.php

diff --git a/package_manager/src/Event/StatusCheckEvent.php b/package_manager/src/Event/StatusCheckEvent.php
new file mode 100644
index 0000000000..7c4250443a
--- /dev/null
+++ b/package_manager/src/Event/StatusCheckEvent.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Drupal\package_manager\Event;
+
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\package_manager\ValidationResult;
+
+/**
+ * Event fired to check the status of the system to use Package Manager.
+ *
+ * The event's stage will be set with the type of stage that will perform the
+ * operations. The stage may or may not be currently in use.
+ */
+class StatusCheckEvent extends PreOperationStageEvent {
+
+  /**
+   * Adds warning information to the event.
+   *
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup[] $messages
+   *   One or more warning messages.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $summary
+   *   A summary of warning messages. Required if there is more than one
+   *   message, optional otherwise.
+   */
+  public function addWarning(array $messages, ?TranslatableMarkup $summary = NULL): void {
+    $this->results[] = ValidationResult::createWarning($messages, $summary);
+  }
+
+}
diff --git a/package_manager/src/Validator/ComposerExecutableValidator.php b/package_manager/src/Validator/ComposerExecutableValidator.php
index 3600876e41..f0abe41a9e 100644
--- a/package_manager/src/Validator/ComposerExecutableValidator.php
+++ b/package_manager/src/Validator/ComposerExecutableValidator.php
@@ -9,6 +9,7 @@ use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\package_manager\Event\StatusCheckEvent;
 use PhpTuf\ComposerStager\Domain\Exception\ExceptionInterface;
 use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface;
 use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface;
@@ -126,6 +127,7 @@ final class ComposerExecutableValidator implements PreOperationStageValidatorInt
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'validateStagePreOperation',
+      StatusCheckEvent::class => 'validateStagePreOperation',
     ];
   }
 
diff --git a/package_manager/src/Validator/ComposerPatchesValidator.php b/package_manager/src/Validator/ComposerPatchesValidator.php
index b6412dc9d5..f25296edb0 100644
--- a/package_manager/src/Validator/ComposerPatchesValidator.php
+++ b/package_manager/src/Validator/ComposerPatchesValidator.php
@@ -5,6 +5,7 @@ namespace Drupal\package_manager\Validator;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
+use Drupal\package_manager\Event\StatusCheckEvent;
 
 /**
  * Validates the configuration of the cweagans/composer-patches plugin.
@@ -42,6 +43,7 @@ class ComposerPatchesValidator implements PreOperationStageValidatorInterface {
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'validateStagePreOperation',
+      StatusCheckEvent::class => 'validateStagePreOperation',
     ];
   }
 
diff --git a/package_manager/src/Validator/ComposerSettingsValidator.php b/package_manager/src/Validator/ComposerSettingsValidator.php
index d906b572bf..0e35167e73 100644
--- a/package_manager/src/Validator/ComposerSettingsValidator.php
+++ b/package_manager/src/Validator/ComposerSettingsValidator.php
@@ -6,6 +6,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
+use Drupal\package_manager\Event\StatusCheckEvent;
 
 /**
  * Validates certain Composer settings.
@@ -53,6 +54,7 @@ final class ComposerSettingsValidator implements PreOperationStageValidatorInter
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'validateStagePreOperation',
+      StatusCheckEvent::class => 'validateStagePreOperation',
     ];
   }
 
diff --git a/package_manager/src/Validator/DiskSpaceValidator.php b/package_manager/src/Validator/DiskSpaceValidator.php
index 2c763e3f95..59dc1ade35 100644
--- a/package_manager/src/Validator/DiskSpaceValidator.php
+++ b/package_manager/src/Validator/DiskSpaceValidator.php
@@ -8,6 +8,7 @@ use Drupal\Component\FileSystem\FileSystem;
 use Drupal\Component\Utility\Bytes;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\package_manager\Event\StatusCheckEvent;
 use Drupal\package_manager\PathLocator;
 
 /**
@@ -165,6 +166,7 @@ class DiskSpaceValidator implements PreOperationStageValidatorInterface {
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'validateStagePreOperation',
+      StatusCheckEvent::class => 'validateStagePreOperation',
     ];
   }
 
diff --git a/package_manager/src/Validator/MultisiteValidator.php b/package_manager/src/Validator/MultisiteValidator.php
index 720f4d3f1b..bd9c5a4b1a 100644
--- a/package_manager/src/Validator/MultisiteValidator.php
+++ b/package_manager/src/Validator/MultisiteValidator.php
@@ -6,6 +6,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
+use Drupal\package_manager\Event\StatusCheckEvent;
 use Drupal\package_manager\PathLocator;
 
 /**
@@ -73,6 +74,7 @@ final class MultisiteValidator implements PreOperationStageValidatorInterface {
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'validateStagePreOperation',
+      StatusCheckEvent::class => 'validateStagePreOperation',
     ];
   }
 
diff --git a/package_manager/src/Validator/PendingUpdatesValidator.php b/package_manager/src/Validator/PendingUpdatesValidator.php
index afd7622761..588e073b11 100644
--- a/package_manager/src/Validator/PendingUpdatesValidator.php
+++ b/package_manager/src/Validator/PendingUpdatesValidator.php
@@ -8,6 +8,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\Core\Update\UpdateRegistry;
 use Drupal\Core\Url;
+use Drupal\package_manager\Event\StatusCheckEvent;
 
 /**
  * Validates that there are no pending database updates.
@@ -87,6 +88,7 @@ final class PendingUpdatesValidator implements PreOperationStageValidatorInterfa
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'validateStagePreOperation',
+      StatusCheckEvent::class => 'validateStagePreOperation',
     ];
   }
 
diff --git a/package_manager/src/Validator/SettingsValidator.php b/package_manager/src/Validator/SettingsValidator.php
index 607e200892..971f477dcf 100644
--- a/package_manager/src/Validator/SettingsValidator.php
+++ b/package_manager/src/Validator/SettingsValidator.php
@@ -7,6 +7,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
+use Drupal\package_manager\Event\StatusCheckEvent;
 
 /**
  * Checks that Drupal's settings are valid for Package Manager.
@@ -47,6 +48,7 @@ final class SettingsValidator implements PreOperationStageValidatorInterface {
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'validateStagePreOperation',
+      StatusCheckEvent::class => 'validateStagePreOperation',
     ];
   }
 
diff --git a/package_manager/src/Validator/SymlinkValidator.php b/package_manager/src/Validator/SymlinkValidator.php
index 1e9fd18627..b72dc30702 100644
--- a/package_manager/src/Validator/SymlinkValidator.php
+++ b/package_manager/src/Validator/SymlinkValidator.php
@@ -6,6 +6,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\package_manager\Event\PreApplyEvent;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
+use Drupal\package_manager\Event\StatusCheckEvent;
 use Drupal\package_manager\PathLocator;
 use Symfony\Component\Finder\Finder;
 
@@ -112,6 +113,7 @@ class SymlinkValidator implements PreOperationStageValidatorInterface {
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'validateStagePreOperation',
+      StatusCheckEvent::class => 'validateStagePreOperation',
       PreApplyEvent::class => [
         ['validateStagePreOperation'],
         ['preApply'],
diff --git a/package_manager/src/Validator/WritableFileSystemValidator.php b/package_manager/src/Validator/WritableFileSystemValidator.php
index b8c656d7c6..db2ff02768 100644
--- a/package_manager/src/Validator/WritableFileSystemValidator.php
+++ b/package_manager/src/Validator/WritableFileSystemValidator.php
@@ -6,6 +6,7 @@ use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\package_manager\Event\StatusCheckEvent;
 use Drupal\package_manager\PathLocator;
 
 /**
@@ -95,6 +96,7 @@ class WritableFileSystemValidator implements PreOperationStageValidatorInterface
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'validateStagePreOperation',
+      StatusCheckEvent::class => 'validateStagePreOperation',
     ];
   }
 
diff --git a/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php b/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php
index 26e873a80a..cbe721f079 100644
--- a/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php
+++ b/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php
@@ -59,6 +59,7 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase {
     $error = ValidationResult::createError([
       $exception->getMessage(),
     ]);
+    $this->assertStatusCheckResults([$error]);
     $this->assertResults([$error], PreCreateEvent::class);
 
     $this->enableModules(['help']);
@@ -160,6 +161,7 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase {
 
     // If the validator can't find a recognized, supported version of Composer,
     // it should produce errors.
+    $this->assertStatusCheckResults($expected_results);
     $this->assertResults($expected_results, PreCreateEvent::class);
 
     $this->enableModules(['help']);
@@ -189,6 +191,7 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase {
       $messages = array_map($map, $result->getMessages());
       $expected_results[$index] = ValidationResult::createError($messages);
     }
+    $this->assertStatusCheckResults($expected_results);
     $this->assertResults($expected_results, $event_class);
   }
 
diff --git a/package_manager/tests/src/Kernel/ComposerPatchesValidatorTest.php b/package_manager/tests/src/Kernel/ComposerPatchesValidatorTest.php
index 5e5e9746f1..482f0a167d 100644
--- a/package_manager/tests/src/Kernel/ComposerPatchesValidatorTest.php
+++ b/package_manager/tests/src/Kernel/ComposerPatchesValidatorTest.php
@@ -16,7 +16,7 @@ class ComposerPatchesValidatorTest extends PackageManagerKernelTestBase {
   /**
    * Tests that the patcher configuration is validated during pre-create.
    */
-  public function testPreCreate(): void {
+  public function testError(): void {
     // Simulate an active directory where the patcher is installed, but there's
     // no composer-exit-on-patch-failure flag.
     $dir = $this->container->get('package_manager.path_locator')
@@ -35,6 +35,7 @@ class ComposerPatchesValidatorTest extends PackageManagerKernelTestBase {
     $error = ValidationResult::createError([
       'The <code>cweagans/composer-patches</code> plugin is installed, but the <code>composer-exit-on-patch-failure</code> key is not set to <code>true</code> in the <code>extra</code> section of composer.json.',
     ]);
+    $this->assertStatusCheckResults([$error]);
     $this->assertResults([$error], PreCreateEvent::class);
   }
 
diff --git a/package_manager/tests/src/Kernel/ComposerSettingsValidatorTest.php b/package_manager/tests/src/Kernel/ComposerSettingsValidatorTest.php
index 14e2361de7..a2b60d2d32 100644
--- a/package_manager/tests/src/Kernel/ComposerSettingsValidatorTest.php
+++ b/package_manager/tests/src/Kernel/ComposerSettingsValidatorTest.php
@@ -62,6 +62,7 @@ class ComposerSettingsValidatorTest extends PackageManagerKernelTestBase {
     $active_dir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
     file_put_contents("$active_dir/composer.json", $contents);
+    $this->assertStatusCheckResults($expected_results);
     $this->assertResults($expected_results, PreCreateEvent::class);
   }
 
diff --git a/package_manager/tests/src/Kernel/DiskSpaceValidatorTest.php b/package_manager/tests/src/Kernel/DiskSpaceValidatorTest.php
index 283247ab63..6392fa5857 100644
--- a/package_manager/tests/src/Kernel/DiskSpaceValidatorTest.php
+++ b/package_manager/tests/src/Kernel/DiskSpaceValidatorTest.php
@@ -148,6 +148,7 @@ class DiskSpaceValidatorTest extends PackageManagerKernelTestBase {
     $validator->sharedDisk = $shared_disk;
     $validator->freeSpace = array_map([Bytes::class, 'toNumber'], $free_space);
 
+    $this->assertStatusCheckResults($expected_results);
     $this->assertResults($expected_results, PreCreateEvent::class);
   }
 
diff --git a/package_manager/tests/src/Kernel/MultisiteValidatorTest.php b/package_manager/tests/src/Kernel/MultisiteValidatorTest.php
index 2843998cc8..f8f8763d78 100644
--- a/package_manager/tests/src/Kernel/MultisiteValidatorTest.php
+++ b/package_manager/tests/src/Kernel/MultisiteValidatorTest.php
@@ -54,6 +54,7 @@ class MultisiteValidatorTest extends PackageManagerKernelTestBase {
         ->getProjectRoot();
       touch($project_root . '/sites/sites.php');
     }
+    $this->assertStatusCheckResults($expected_results);
     $this->assertResults($expected_results, PreCreateEvent::class);
   }
 
diff --git a/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php b/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
index 2937f204d7..280bb13327 100644
--- a/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
+++ b/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
@@ -6,6 +6,7 @@ use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\package_manager\Event\PreApplyEvent;
 use Drupal\package_manager\Event\StageEvent;
+use Drupal\package_manager\Event\StatusCheckEvent;
 use Drupal\package_manager\Validator\DiskSpaceValidator;
 use Drupal\package_manager\Exception\StageException;
 use Drupal\package_manager\Exception\StageValidationException;
@@ -171,6 +172,18 @@ abstract class PackageManagerKernelTestBase extends KernelTestBase {
     }
   }
 
+  /**
+   * Asserts validation results are returned from the status check event.
+   *
+   * @param \Drupal\package_manager\ValidationResult[] $expected_results
+   *   The expected validation results.
+   */
+  protected function assertStatusCheckResults(array $expected_results): void {
+    $event = new StatusCheckEvent($this->createStage());
+    $this->container->get('event_dispatcher')->dispatch($event);
+    $this->assertValidationResultsEqual($expected_results, $event->getResults());
+  }
+
   /**
    * Marks all pending post-update functions as completed.
    *
diff --git a/package_manager/tests/src/Kernel/PendingUpdatesValidatorTest.php b/package_manager/tests/src/Kernel/PendingUpdatesValidatorTest.php
index 50e4c0e669..e41ccd8c9e 100644
--- a/package_manager/tests/src/Kernel/PendingUpdatesValidatorTest.php
+++ b/package_manager/tests/src/Kernel/PendingUpdatesValidatorTest.php
@@ -21,6 +21,7 @@ class PendingUpdatesValidatorTest extends PackageManagerKernelTestBase {
    * Tests that no error is raised if there are no pending updates.
    */
   public function testNoPendingUpdates(): void {
+    $this->assertStatusCheckResults([]);
     $this->assertResults([], PreCreateEvent::class);
   }
 
@@ -42,6 +43,7 @@ class PendingUpdatesValidatorTest extends PackageManagerKernelTestBase {
     $result = ValidationResult::createError([
       'Some modules have database schema updates to install. You should run the <a href="/update.php">database update script</a> immediately.',
     ]);
+    $this->assertStatusCheckResults([$result]);
     $this->assertResults([$result], PreCreateEvent::class);
   }
 
@@ -55,6 +57,7 @@ class PendingUpdatesValidatorTest extends PackageManagerKernelTestBase {
     $result = ValidationResult::createError([
       'Some modules have database schema updates to install. You should run the <a href="/update.php">database update script</a> immediately.',
     ]);
+    $this->assertStatusCheckResults([$result]);
     $this->assertResults([$result], PreCreateEvent::class);
   }
 
diff --git a/package_manager/tests/src/Kernel/SettingsValidatorTest.php b/package_manager/tests/src/Kernel/SettingsValidatorTest.php
index 6ee4fed0c8..3a4df2b119 100644
--- a/package_manager/tests/src/Kernel/SettingsValidatorTest.php
+++ b/package_manager/tests/src/Kernel/SettingsValidatorTest.php
@@ -39,6 +39,7 @@ class SettingsValidatorTest extends PackageManagerKernelTestBase {
    */
   public function testSettingsValidation(bool $setting, array $expected_results): void {
     $this->setSetting('update_fetch_with_http_fallback', $setting);
+    $this->assertStatusCheckResults($expected_results);
     $this->assertResults($expected_results, PreCreateEvent::class);
   }
 
diff --git a/package_manager/tests/src/Kernel/SymlinkValidatorTest.php b/package_manager/tests/src/Kernel/SymlinkValidatorTest.php
index afe8343e64..965b650650 100644
--- a/package_manager/tests/src/Kernel/SymlinkValidatorTest.php
+++ b/package_manager/tests/src/Kernel/SymlinkValidatorTest.php
@@ -37,6 +37,7 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
       ->getProjectRoot();
     // @see \Drupal\Tests\package_manager\Kernel\TestSymlinkValidator::isLink()
     touch($active_dir . '/modules/a_link');
+    $this->assertStatusCheckResults([$result]);
     $this->assertResults([$result], PreCreateEvent::class);
   }
 
diff --git a/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php b/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php
index d9f25fcb76..4005a8a0f3 100644
--- a/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php
+++ b/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php
@@ -84,6 +84,7 @@ class WritableFileSystemValidatorTest extends PackageManagerKernelTestBase {
     $this->assertTrue(chmod($path_locator->getVendorDirectory(), $vendor_permissions));
     $this->assertTrue(chmod($path_locator->getProjectRoot(), $root_permissions));
 
+    $this->assertStatusCheckResults($expected_results);
     $this->assertResults($expected_results, PreCreateEvent::class);
   }
 
@@ -143,6 +144,7 @@ class WritableFileSystemValidatorTest extends PackageManagerKernelTestBase {
       $dir = dirname($dir);
     }
     $this->assertTrue(chmod($dir, $permissions));
+    $this->assertStatusCheckResults($expected_results);
     $this->assertResults($expected_results, PreCreateEvent::class);
   }
 
-- 
GitLab