diff --git a/src/Form/UpdateReady.php b/src/Form/UpdateReady.php index 84e7757903ee334998aa128078ec032445d08dbf..1867539cc745186a507cb9acd2a6d6faccaaec69 100644 --- a/src/Form/UpdateReady.php +++ b/src/Form/UpdateReady.php @@ -107,14 +107,14 @@ class UpdateReady extends FormBase { $messages = []; - // If there are any installed modules with database updates in the staging - // area, warn the user that they might be sent to update.php once the - // staged changes have been applied. - $pending_updates = $this->getModulesWithStagedDatabaseUpdates(); + // If there are any installed extensions with database updates in the + // staging area, warn the user that they might be sent to update.php once + // the staged changes have been applied. + $pending_updates = $this->stagedDatabaseUpdateValidator->getExtensionsWithDatabaseUpdates($this->updater); if ($pending_updates) { - $messages[MessengerInterface::TYPE_WARNING][] = $this->t('Possible database updates were detected in the following modules; you may be redirected to the database update page in order to complete the update process.'); - foreach ($pending_updates as $info) { - $messages[MessengerInterface::TYPE_WARNING][] = $info['name']; + $messages[MessengerInterface::TYPE_WARNING][] = $this->t('Possible database updates were detected in the following extensions; you may be redirected to the database update page in order to complete the update process.'); + foreach ($pending_updates as $pending_update) { + $messages[MessengerInterface::TYPE_WARNING][] = $pending_update; } } @@ -181,20 +181,6 @@ class UpdateReady extends FormBase { return $form; } - /** - * Returns info for all installed modules that have staged database updates. - * - * @return array[] - * The info arrays for the modules which have staged database updates, keyed - * by module machine name. - */ - protected function getModulesWithStagedDatabaseUpdates(): array { - $filter = function (string $name): bool { - return $this->stagedDatabaseUpdateValidator->hasStagedUpdates($this->updater, $this->moduleList->get($name)); - }; - return array_filter($this->moduleList->getAllInstalledInfo(), $filter, ARRAY_FILTER_USE_KEY); - } - /** * {@inheritdoc} */ diff --git a/src/Validator/StagedDatabaseUpdateValidator.php b/src/Validator/StagedDatabaseUpdateValidator.php index a585490d3d4468fab0fff843272bd6e9ba5bc1cc..647d9c0cf4585b363469e3cb0bab7ce3b9b7c3b0 100644 --- a/src/Validator/StagedDatabaseUpdateValidator.php +++ b/src/Validator/StagedDatabaseUpdateValidator.php @@ -3,7 +3,6 @@ namespace Drupal\automatic_updates\Validator; use Drupal\automatic_updates\CronUpdater; -use Drupal\automatic_updates\Updater; use Drupal\Core\Extension\Extension; use Drupal\Core\Extension\ModuleExtensionList; use Drupal\Core\Extension\ThemeExtensionList; @@ -11,6 +10,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\package_manager\Event\PreApplyEvent; use Drupal\package_manager\PathLocator; +use Drupal\package_manager\Stage; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -76,21 +76,7 @@ class StagedDatabaseUpdateValidator implements EventSubscriberInterface { return; } - $invalid_extensions = []; - // Although \Drupal\automatic_updates\Validator\StagedProjectsValidator - // should prevent non-core modules from being added, updated, or removed in - // the staging area, we check all installed modules so as not to rely on the - // presence of StagedProjectsValidator. - foreach ($this->moduleList->getAllInstalledInfo() as $module_name => $module_info) { - if ($this->hasStagedUpdates($stage, $this->moduleList->get($module_name))) { - $invalid_extensions[] = $module_info['name']; - } - } - foreach ($this->themeList->getAllInstalledInfo() as $theme_name => $theme_info) { - if ($this->hasStagedUpdates($stage, $this->themeList->get($theme_name))) { - $invalid_extensions[] = $theme_info['name']; - } - } + $invalid_extensions = $this->getExtensionsWithDatabaseUpdates($stage); if ($invalid_extensions) { $event->addError($invalid_extensions, $this->t('The update cannot proceed because possible database updates have been detected in the following extensions.')); } @@ -99,7 +85,7 @@ class StagedDatabaseUpdateValidator implements EventSubscriberInterface { /** * Determines if a staged extension has changed update functions. * - * @param \Drupal\automatic_updates\Updater $updater + * @param \Drupal\package_manager\Stage $stage * The updater which is controlling the update process. * @param \Drupal\Core\Extension\Extension $extension * The extension to check. @@ -120,9 +106,9 @@ class StagedDatabaseUpdateValidator implements EventSubscriberInterface { * * @see https://www.drupal.org/project/automatic_updates/issues/3253828 */ - public function hasStagedUpdates(Updater $updater, Extension $extension): bool { + public function hasStagedUpdates(Stage $stage, Extension $extension): bool { $active_dir = $this->pathLocator->getProjectRoot(); - $stage_dir = $updater->getStageDirectory(); + $stage_dir = $stage->getStageDirectory(); $web_root = $this->pathLocator->getWebRoot(); if ($web_root) { @@ -175,4 +161,31 @@ class StagedDatabaseUpdateValidator implements EventSubscriberInterface { ]; } + /** + * Get extensions that have database updates. + * + * @param \Drupal\package_manager\Stage $stage + * The stage. + * + * @return string[] + * The names of the extensions that have possible database updates. + */ + public function getExtensionsWithDatabaseUpdates(Stage $stage): array { + $invalid_extensions = []; + // Although \Drupal\automatic_updates\Validator\StagedProjectsValidator + // should prevent non-core modules from being added, updated, or removed in + // the staging area, we check all installed extensions so as not to rely on + // the presence of StagedProjectsValidator. + $lists = [$this->moduleList, $this->themeList]; + foreach ($lists as $list) { + foreach ($list->getAllInstalledInfo() as $name => $info) { + if ($this->hasStagedUpdates($stage, $list->get($name))) { + $invalid_extensions[] = $info['name']; + } + } + } + + return $invalid_extensions; + } + } diff --git a/tests/src/Functional/UpdaterFormTest.php b/tests/src/Functional/UpdaterFormTest.php index dc485c4fd93a6e5b99bde273637adfb553837e9b..d6caa165ba67458ac5f14885a7703060adbc7b5b 100644 --- a/tests/src/Functional/UpdaterFormTest.php +++ b/tests/src/Functional/UpdaterFormTest.php @@ -456,6 +456,7 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase { public function testStagedDatabaseUpdates(bool $maintenance_mode_on): void { $this->setCoreVersion('9.8.0'); $this->checkForUpdates(); + $this->container->get('theme_installer')->install(['automatic_updates_theme_with_updates']); $cached_message = $this->setAndAssertCachedMessage(); $state = $this->container->get('state'); @@ -488,9 +489,10 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase { // changes have been applied, we should be redirected to update.php, where // neither warning should be visible. $assert_session->pageTextNotContains(reset($messages)); - $possible_update_message = 'Possible database updates were detected in the following modules; you may be redirected to the database update page in order to complete the update process.'; + $possible_update_message = 'Possible database updates were detected in the following extensions; you may be redirected to the database update page in order to complete the update process.'; $assert_session->pageTextContains($possible_update_message); $assert_session->pageTextContains('System'); + $assert_session->pageTextContainsOnce('Automatic Updates Theme With Updates'); if ($maintenance_mode_on === TRUE) { $assert_session->fieldNotExists('maintenance_mode'); }