From 2334a1d18f9dec0c923c759a9cf7c2d4299bf629 Mon Sep 17 00:00:00 2001
From: phenaproxima <phenaproxima@205645.no-reply.drupal.org>
Date: Fri, 6 May 2022 17:02:12 +0000
Subject: [PATCH] Issue #3276031 by phenaproxima, kunal.sachdev: Create
 installed version validator

---
 automatic_updates.services.yml                |  4 ++
 src/Validator/InstalledVersionValidator.php   | 55 +++++++++++++++++++
 src/Validator/UpdateVersionValidator.php      |  6 +-
 .../InstalledVersionValidatorTest.php         | 32 +++++++++++
 .../UpdateVersionValidatorTest.php            | 16 +-----
 5 files changed, 93 insertions(+), 20 deletions(-)
 create mode 100644 src/Validator/InstalledVersionValidator.php
 create mode 100644 tests/src/Kernel/ReadinessValidation/InstalledVersionValidatorTest.php

diff --git a/automatic_updates.services.yml b/automatic_updates.services.yml
index f0efbee5f3..bf3916ff1c 100644
--- a/automatic_updates.services.yml
+++ b/automatic_updates.services.yml
@@ -133,6 +133,10 @@ services:
     class: Drupal\automatic_updates\Validator\XdebugValidator
     tags:
       - { name: event_subscriber }
+  automatic_updates.validator.installed_version:
+    class: Drupal\automatic_updates\Validator\InstalledVersionValidator
+    tags:
+      - { name: event_subscriber }
   automatic_updates.validator.target_release:
     class: Drupal\automatic_updates\Validator\UpdateReleaseValidator
     tags:
diff --git a/src/Validator/InstalledVersionValidator.php b/src/Validator/InstalledVersionValidator.php
new file mode 100644
index 0000000000..abb30dc612
--- /dev/null
+++ b/src/Validator/InstalledVersionValidator.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Drupal\automatic_updates\Validator;
+
+use Drupal\automatic_updates\Event\ReadinessCheckEvent;
+use Drupal\automatic_updates\ProjectInfo;
+use Drupal\automatic_updates\Updater;
+use Drupal\Core\Extension\ExtensionVersion;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\package_manager\Event\PreCreateEvent;
+use Drupal\package_manager\Event\PreOperationStageEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Validates that the site can update from the installed version of Drupal.
+ */
+class InstalledVersionValidator implements EventSubscriberInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * Checks that the site can update from the installed version of Drupal.
+   *
+   * @param \Drupal\package_manager\Event\PreOperationStageEvent $event
+   *   The event object.
+   */
+  public function checkInstalledVersion(PreOperationStageEvent $event): void {
+    // This check only works with Automatic Updates.
+    if (!$event->getStage() instanceof Updater) {
+      return;
+    }
+
+    $installed_version = (new ProjectInfo('drupal'))->getInstalledVersion();
+    $extra = ExtensionVersion::createFromVersionString($installed_version)
+      ->getVersionExtra();
+
+    if ($extra === 'dev') {
+      $message = $this->t('Drupal cannot be automatically updated from the installed version, @installed_version, because automatic updates from a dev version to any other version are not supported.', [
+        '@installed_version' => $installed_version,
+      ]);
+      $event->addError([$message]);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    return [
+      ReadinessCheckEvent::class => 'checkInstalledVersion',
+      PreCreateEvent::class => 'checkInstalledVersion',
+    ];
+  }
+
+}
diff --git a/src/Validator/UpdateVersionValidator.php b/src/Validator/UpdateVersionValidator.php
index b4e090f444..bd87af4ab8 100644
--- a/src/Validator/UpdateVersionValidator.php
+++ b/src/Validator/UpdateVersionValidator.php
@@ -172,13 +172,9 @@ class UpdateVersionValidator implements EventSubscriberInterface {
       '@from_version' => $from_version_string,
     ];
     $from_version = ExtensionVersion::createFromVersionString($from_version_string);
+
     // @todo Return multiple validation messages and summary in
     //   https://www.drupal.org/project/automatic_updates/issues/3272068.
-    if ($from_version->getVersionExtra() === 'dev') {
-      return ValidationResult::createError([
-        $this->t('Drupal cannot be automatically updated from the installed version, @from_version, because automatic updates from a dev version to any other version are not supported.', $variables),
-      ]);
-    }
     if (Comparator::lessThan($to_version_string, $from_version_string)) {
       return ValidationResult::createError([
         $this->t('Update version @to_version is lower than @from_version, downgrading is not supported.', $variables),
diff --git a/tests/src/Kernel/ReadinessValidation/InstalledVersionValidatorTest.php b/tests/src/Kernel/ReadinessValidation/InstalledVersionValidatorTest.php
new file mode 100644
index 0000000000..3fb138504e
--- /dev/null
+++ b/tests/src/Kernel/ReadinessValidation/InstalledVersionValidatorTest.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Drupal\Tests\automatic_updates\Kernel\ReadinessValidation;
+
+use Drupal\package_manager\ValidationResult;
+use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase;
+
+/**
+ * @covers \Drupal\automatic_updates\Validator\InstalledVersionValidator
+ *
+ * @group automatic_updates
+ */
+class InstalledVersionValidatorTest extends AutomaticUpdatesKernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['automatic_updates'];
+
+  /**
+   * Tests that the installed version of Drupal is checked for updateability.
+   */
+  public function testInstalledVersionValidation(): void {
+    $this->setCoreVersion('9.8.0-dev');
+
+    $result = ValidationResult::createError([
+      'Drupal cannot be automatically updated from the installed version, 9.8.0-dev, because automatic updates from a dev version to any other version are not supported.',
+    ]);
+    $this->assertCheckerResultsFromManager([$result], TRUE);
+  }
+
+}
diff --git a/tests/src/Kernel/ReadinessValidation/UpdateVersionValidatorTest.php b/tests/src/Kernel/ReadinessValidation/UpdateVersionValidatorTest.php
index 0d6aae08e7..3193ada45a 100644
--- a/tests/src/Kernel/ReadinessValidation/UpdateVersionValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/UpdateVersionValidatorTest.php
@@ -256,6 +256,7 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase {
     $unstable_current_version = ValidationResult::createError([
       'Drupal cannot be automatically updated during cron from its current version, 9.8.0-alpha1, because Automatic Updates only supports updating from stable versions during cron.',
     ]);
+
     return [
       'unstable current version, cron disabled' => [
         CronUpdater::DISABLED,
@@ -275,21 +276,6 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase {
         '9.8.0-alpha1',
         [$unstable_current_version],
       ],
-      'dev current version, cron disabled' => [
-        CronUpdater::DISABLED,
-        '9.8.x-dev',
-        [],
-      ],
-      'dev current version, security updates allowed' => [
-        CronUpdater::SECURITY,
-        '9.8.x-dev',
-        [],
-      ],
-      'dev current version, all updates allowed' => [
-        CronUpdater::ALL,
-        '9.8.x-dev',
-        [],
-      ],
       // @todo In the 3 following test cases the installed version is not
       //   in a supported branch. These test expectations should be changed or
       //   moved to a new test when we add a validator to check if the installed
-- 
GitLab