From 0ae874a34c44c9a4a31a8e5f9cd9abcd473f8973 Mon Sep 17 00:00:00 2001
From: "kunal.sachdev" <kunal.sachdev@3685163.no-reply.drupal.org>
Date: Fri, 14 Oct 2022 20:41:03 +0000
Subject: [PATCH] Issue #3314805 by phenaproxima, kunal.sachdev: Create a base
 class for UpdaterForm and UpdateReady to help run status checks and display
 the results

---
 .../src/Form/UpdateReady.php                  | 29 +------
 .../src/Form/UpdaterForm.php                  |  9 +-
 .../tests/src/Functional/UpdaterFormTest.php  |  5 +-
 dictionary.txt                                |  1 +
 src/Form/UpdateFormBase.php                   | 85 +++++++++++++++++++
 src/Form/UpdateReady.php                      | 28 +-----
 src/Form/UpdaterForm.php                      | 26 +-----
 7 files changed, 98 insertions(+), 85 deletions(-)
 create mode 100644 src/Form/UpdateFormBase.php

diff --git a/automatic_updates_extensions/src/Form/UpdateReady.php b/automatic_updates_extensions/src/Form/UpdateReady.php
index 12daefbc69..e3dd027592 100644
--- a/automatic_updates_extensions/src/Form/UpdateReady.php
+++ b/automatic_updates_extensions/src/Form/UpdateReady.php
@@ -2,7 +2,7 @@
 
 namespace Drupal\automatic_updates_extensions\Form;
 
-use Drupal\automatic_updates\Validation\ReadinessTrait;
+use Drupal\automatic_updates\Form\UpdateFormBase;
 use Drupal\package_manager\Event\StatusCheckEvent;
 use Drupal\package_manager\Exception\ApplyFailedException;
 use Drupal\package_manager\ProjectInfo;
@@ -12,7 +12,6 @@ use Drupal\automatic_updates\BatchProcessor as AutoUpdatesBatchProcessor;
 use Drupal\automatic_updates_extensions\ExtensionUpdater;
 use Drupal\Core\Batch\BatchBuilder;
 use Drupal\Core\Extension\ModuleExtensionList;
-use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\RendererInterface;
 use Drupal\Core\Messenger\MessengerInterface;
@@ -30,11 +29,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  * @internal
  *   Form classes are internal.
  */
-final class UpdateReady extends FormBase {
-
-  use ReadinessTrait {
-    formatResult as traitFormatResult;
-  }
+final class UpdateReady extends UpdateFormBase {
 
   /**
    * The updater service.
@@ -176,7 +171,7 @@ final class UpdateReady extends FormBase {
       /** @var \Drupal\package_manager\ValidationResult[] $results */
       $results = $event->getResults();
       // This will have no effect if $results is empty.
-      $this->displayResults($results, $this->messenger(), $this->renderer);
+      $this->displayResults($results, $this->renderer);
       // If any errors occurred, return the form early so the user cannot
       // continue.
       if (ValidationResult::getOverallSeverity($results) === SystemManager::REQUIREMENT_ERROR) {
@@ -338,22 +333,4 @@ final class UpdateReady extends FormBase {
     ];
   }
 
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Remove this in https://www.drupal.org/project/automatic_updates/issues/3313414.
-   */
-  protected function formatResult(ValidationResult $result) {
-    $messages = $result->getMessages();
-
-    if (count($messages) > 1) {
-      return [
-        '#theme' => 'item_list__automatic_updates_validation_results',
-        '#prefix' => $result->getSummary(),
-        '#items' => $messages,
-      ];
-    }
-    return $this->traitFormatResult($result);
-  }
-
 }
diff --git a/automatic_updates_extensions/src/Form/UpdaterForm.php b/automatic_updates_extensions/src/Form/UpdaterForm.php
index 48d384629c..663b946641 100644
--- a/automatic_updates_extensions/src/Form/UpdaterForm.php
+++ b/automatic_updates_extensions/src/Form/UpdaterForm.php
@@ -3,11 +3,10 @@
 namespace Drupal\automatic_updates_extensions\Form;
 
 use Drupal\automatic_updates\Event\ReadinessCheckEvent;
-use Drupal\automatic_updates\Validation\ReadinessTrait;
+use Drupal\automatic_updates\Form\UpdateFormBase;
 use Drupal\automatic_updates_extensions\BatchProcessor;
 use Drupal\automatic_updates_extensions\ExtensionUpdater;
 use Drupal\Core\Batch\BatchBuilder;
-use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\State\StateInterface;
 use Drupal\Core\Messenger\MessengerInterface;
@@ -28,9 +27,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  * @internal
  *   Form classes are internal.
  */
-final class UpdaterForm extends FormBase {
-
-  use ReadinessTrait;
+final class UpdaterForm extends UpdateFormBase {
 
   /**
    * The extension updater service.
@@ -170,7 +167,7 @@ final class UpdaterForm extends FormBase {
       $this->eventDispatcher->dispatch($event);
       $results = $event->getResults();
     }
-    $this->displayResults($results, $this->messenger(), $this->renderer);
+    $this->displayResults($results, $this->renderer);
     $security_level = ValidationResult::getOverallSeverity($results);
 
     if ($update_projects && $security_level !== SystemManager::REQUIREMENT_ERROR) {
diff --git a/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php b/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php
index 870ec56ccb..29d71e52b6 100644
--- a/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php
+++ b/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php
@@ -193,9 +193,8 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
     $assert_session->pageTextNotContains('The following dependencies will also be updated:');
     // Ensure that a list of pending database updates is visible, along with a
     // short explanation, in the warning messages.
-    $possible_update_message = 'Possible database updates have been detected in the following extensions.<ul><li>System</li><li>Automatic Updates Theme With Updates</li></ul>';
-    $warning_messages = $assert_session->elementExists('css', 'div[data-drupal-messages] div[aria-label="Warning message"]');
-    $this->assertStringContainsString($possible_update_message, $warning_messages->getHtml());
+    $warning_messages = $assert_session->elementExists('xpath', '//div[@data-drupal-messages]//div[@aria-label="Warning message"]');
+    $this->assertStringContainsString('Possible database updates have been detected in the following extensions.<ul><li>System</li><li>Automatic Updates Theme With Updates</li></ul>', $warning_messages->getHtml());
 
     $page->pressButton('Continue');
     $this->checkForMetaRefresh();
diff --git a/dictionary.txt b/dictionary.txt
index d69a828c01..5b339b5f5c 100644
--- a/dictionary.txt
+++ b/dictionary.txt
@@ -3,3 +3,4 @@ updater's
 stager's
 syncer
 syncers
+unrequested
diff --git a/src/Form/UpdateFormBase.php b/src/Form/UpdateFormBase.php
new file mode 100644
index 0000000000..1c44060b53
--- /dev/null
+++ b/src/Form/UpdateFormBase.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Drupal\automatic_updates\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\package_manager\ValidationResult;
+use Drupal\system\SystemManager;
+
+/**
+ * Base class for update forms provided by Automatic Updates.
+ *
+ * @internal
+ *   This is an internal part of Automatic Updates and may be changed or removed
+ *   at any time without warning. External code should not extend this class.
+ */
+abstract class UpdateFormBase extends FormBase {
+
+  /**
+   * Gets a message, based on severity, when readiness checkers fail.
+   *
+   * @param int $severity
+   *   The severity. Should be one of the SystemManager::REQUIREMENT_*
+   *   constants.
+   *
+   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
+   *   The message.
+   *
+   * @see \Drupal\system\SystemManager::REQUIREMENT_ERROR
+   * @see \Drupal\system\SystemManager::REQUIREMENT_WARNING
+   */
+  protected function getFailureMessageForSeverity(int $severity): TranslatableMarkup {
+    return $severity === SystemManager::REQUIREMENT_WARNING ?
+      // @todo Link "automatic updates" to documentation in
+      //   https://www.drupal.org/node/3168405.
+      $this->t('Your site does not pass some readiness checks for automatic updates. Depending on the nature of the failures, it might affect the eligibility for automatic updates.') :
+      $this->t('Your site does not pass some readiness checks for automatic updates. It cannot be automatically updated until further action is performed.');
+  }
+
+  /**
+   * Adds a set of validation results to the messages.
+   *
+   * @param \Drupal\package_manager\ValidationResult[] $results
+   *   The validation results.
+   * @param \Drupal\Core\Render\RendererInterface $renderer
+   *   The renderer service.
+   */
+  protected function displayResults(array $results, RendererInterface $renderer): void {
+    $severity = ValidationResult::getOverallSeverity($results);
+
+    if ($severity === SystemManager::REQUIREMENT_OK) {
+      return;
+    }
+
+    // Format the results as a single item list prefixed by a preamble message.
+    $build = [
+      '#theme' => 'item_list__automatic_updates_validation_results',
+      '#prefix' => $this->getFailureMessageForSeverity($severity),
+    ];
+    foreach ($results as $result) {
+      $messages = $result->getMessages();
+
+      if (count($messages) > 1) {
+        $build['#items'][] = [
+          '#theme' => $build['#theme'],
+          '#prefix' => $result->getSummary(),
+          '#items' => $messages,
+        ];
+      }
+      else {
+        $build['#items'][] = reset($messages);
+      }
+    }
+    $message = $renderer->renderRoot($build);
+
+    if ($severity === SystemManager::REQUIREMENT_ERROR) {
+      $this->messenger()->addError($message);
+    }
+    else {
+      $this->messenger()->addWarning($message);
+    }
+  }
+
+}
diff --git a/src/Form/UpdateReady.php b/src/Form/UpdateReady.php
index 024fb590e1..a87b5197b7 100644
--- a/src/Form/UpdateReady.php
+++ b/src/Form/UpdateReady.php
@@ -4,11 +4,9 @@ namespace Drupal\automatic_updates\Form;
 
 use Drupal\automatic_updates\BatchProcessor;
 use Drupal\automatic_updates\Updater;
-use Drupal\automatic_updates\Validation\ReadinessTrait;
 use Drupal\package_manager\ValidationResult;
 use Drupal\Core\Batch\BatchBuilder;
 use Drupal\Core\Extension\ModuleExtensionList;
-use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Messenger\MessengerInterface;
 use Drupal\Core\Render\RendererInterface;
@@ -27,11 +25,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  * @internal
  *   Form classes are internal and the form structure may change at any time.
  */
-final class UpdateReady extends FormBase {
-
-  use ReadinessTrait {
-    formatResult as traitFormatResult;
-  }
+final class UpdateReady extends UpdateFormBase {
 
   /**
    * The updater service.
@@ -194,7 +188,7 @@ final class UpdateReady extends FormBase {
       /** @var \Drupal\package_manager\ValidationResult[] $results */
       $results = $event->getResults();
       // This will have no effect if $results is empty.
-      $this->displayResults($results, $this->messenger(), $this->renderer);
+      $this->displayResults($results, $this->renderer);
       // If any errors occurred, return the form early so the user cannot
       // continue.
       if (ValidationResult::getOverallSeverity($results) === SystemManager::REQUIREMENT_ERROR) {
@@ -248,22 +242,4 @@ final class UpdateReady extends FormBase {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Remove this in https://www.drupal.org/project/automatic_updates/issues/3313414.
-   */
-  protected function formatResult(ValidationResult $result) {
-    $messages = $result->getMessages();
-
-    if (count($messages) > 1) {
-      return [
-        '#theme' => 'item_list__automatic_updates_validation_results',
-        '#prefix' => $result->getSummary(),
-        '#items' => $messages,
-      ];
-    }
-    return $this->traitFormatResult($result);
-  }
-
 }
diff --git a/src/Form/UpdaterForm.php b/src/Form/UpdaterForm.php
index 2884a1b467..c63b3c751c 100644
--- a/src/Form/UpdaterForm.php
+++ b/src/Form/UpdaterForm.php
@@ -9,12 +9,10 @@ use Drupal\package_manager\FailureMarker;
 use Drupal\package_manager\ProjectInfo;
 use Drupal\automatic_updates\ReleaseChooser;
 use Drupal\automatic_updates\Updater;
-use Drupal\automatic_updates\Validation\ReadinessTrait;
 use Drupal\package_manager\Exception\ApplyFailedException;
 use Drupal\update\ProjectRelease;
 use Drupal\Core\Batch\BatchBuilder;
 use Drupal\Core\Extension\ExtensionVersion;
-use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Messenger\MessengerInterface;
 use Drupal\Core\Render\RendererInterface;
@@ -35,11 +33,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  * @internal
  *   Form classes are internal and the form structure may change at any time.
  */
-final class UpdaterForm extends FormBase {
-
-  use ReadinessTrait {
-    formatResult as traitFormatResult;
-  }
+final class UpdaterForm extends UpdateFormBase {
 
   /**
    * The updater service.
@@ -204,7 +198,7 @@ final class UpdaterForm extends FormBase {
       $this->eventDispatcher->dispatch($event);
       $results = $event->getResults();
     }
-    $this->displayResults($results, $this->messenger(), $this->renderer);
+    $this->displayResults($results, $this->renderer);
     $project = $project_info->getProjectInfo();
     if ($installed_minor_release === NULL && $next_minor_release === NULL) {
       if ($project['status'] === UpdateManagerInterface::CURRENT) {
@@ -380,22 +374,6 @@ final class UpdaterForm extends FormBase {
     batch_set($batch);
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function formatResult(ValidationResult $result) {
-    $messages = $result->getMessages();
-
-    if (count($messages) > 1) {
-      return [
-        '#theme' => 'item_list__automatic_updates_validation_results',
-        '#prefix' => $result->getSummary(),
-        '#items' => $messages,
-      ];
-    }
-    return $this->traitFormatResult($result);
-  }
-
   /**
    * Gets the update table for a specific release.
    *
-- 
GitLab