From 2b1471bf56a4beb92b21e73f354e5dcb1af04e03 Mon Sep 17 00:00:00 2001 From: Thomas Fini Hansen Date: Thu, 19 Dec 2024 11:52:05 +0100 Subject: [PATCH] Skip the /admin/update/ready page The page suggests backing up the site and offers to put the site into maintenance mode, but even webmaster administrators is allowed neither. So we copy the important part from UpdateReady::submitForm. Ref DDFHER-183 --- phpstan.neon.dist | 2 + .../src/Form/InstallOrUpdateModule.php | 54 ++++++++++++++++--- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index ecfb99042..06c5ded33 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -79,3 +79,5 @@ parameters: - web/core/modules/locale/locale.batch.inc - web/core/modules/locale/locale.bulk.inc - web/modules/contrib/config_translation_po/config_translation_po.bulk.inc + # Drupal\dpl_webmaster\Form\InstallOrUpdateModule uses this. + - web/core/modules/update/update.authorize.inc diff --git a/web/modules/custom/dpl_webmaster/src/Form/InstallOrUpdateModule.php b/web/modules/custom/dpl_webmaster/src/Form/InstallOrUpdateModule.php index c211948d9..85d7df566 100644 --- a/web/modules/custom/dpl_webmaster/src/Form/InstallOrUpdateModule.php +++ b/web/modules/custom/dpl_webmaster/src/Form/InstallOrUpdateModule.php @@ -198,6 +198,11 @@ public function submitForm(array &$form, FormStateInterface $form_state): void { // MODULE/) and others list an actual file (i.e., MODULE/README.TXT). $project = strtok($files[0], '/\\'); + if (!$project) { + $this->messenger()->addError($this->t('Could not determine module name from archive')); + return; + } + $archive_errors = $this->moduleHandler->invokeAll('verify_update_archive', [$project, $local_cache, $directory]); if (!empty($archive_errors)) { $this->messenger()->addError(array_shift($archive_errors)); @@ -240,15 +245,11 @@ public function submitForm(array &$form, FormStateInterface $form_state): void { return; } - // This is where we diverge from UpdateManagerInstall. It simply errors out, - // we set a session variable to tell /admin/update/ready which module to - // update and redirect to it instead. It'll pick up the files for the module - // as we've already extracted it in the directory where it expects to find - // it. + // This is where we diverge from UpdateManagerInstall and pass over control + // to update.php. It'll pick up the files for the module as we've already + // extracted it in the directory where it expects to find it. if ($updater->isInstalled()) { - // Tell UpdateReady form which projects to update. - $this->session->set('update_manager_update_projects', [$project => $project]); - $form_state->setRedirect('update.confirmation_page'); + $this->updateProject([$project], $form_state); return; } @@ -291,4 +292,41 @@ public function submitForm(array &$form, FormStateInterface $form_state): void { } } + /** + * Copy uploaded module into place run updates. + * + * @param string[] $projects + * List of projects to update. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * Form state to set redirect on. + */ + protected function updateProject(array $projects, FormStateInterface $form_state): void { + // Most of this has been lifted from UpdateReady::submitForm(). + drupal_get_updaters(); + + $updates = []; + $directory = _update_manager_extract_directory(); + + $project_real_location = NULL; + foreach ($projects as $project) { + $project_location = $directory . '/' . $project; + $updater = Updater::factory($project_location, $this->root); + $project_real_location = $this->fileSystem->realpath($project_location); + $updates[] = [ + 'project' => $project, + 'updater_name' => get_class($updater), + 'local_url' => $project_real_location, + ]; + } + + // Contrary to UpdateReady::submitForm(), we don't check file owners or + // support FTP method. + $this->moduleHandler->loadInclude('update', 'inc', 'update.authorize'); + $filetransfer = new Local($this->root, $this->fileSystem); + $response = update_authorize_run_update($filetransfer, $updates); + if ($response instanceof Response) { + $form_state->setResponse($response); + } + } + }