diff options
Diffstat (limited to 'core/modules/update')
-rw-r--r-- | core/modules/update/src/Hook/UpdateHooks.php | 11 | ||||
-rw-r--r-- | core/modules/update/src/Hook/UpdateRequirements.php | 161 | ||||
-rw-r--r-- | core/modules/update/src/UpdateRoot.php | 10 | ||||
-rw-r--r-- | core/modules/update/tests/src/Functional/UpdateManagerTest.php | 37 | ||||
-rw-r--r-- | core/modules/update/tests/src/Functional/UpdateMiscTest.php | 17 | ||||
-rw-r--r-- | core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php | 1 | ||||
-rw-r--r-- | core/modules/update/update.authorize.inc | 12 | ||||
-rw-r--r-- | core/modules/update/update.fetch.inc | 9 | ||||
-rw-r--r-- | core/modules/update/update.install | 139 | ||||
-rw-r--r-- | core/modules/update/update.manager.inc | 15 | ||||
-rw-r--r-- | core/modules/update/update.module | 35 | ||||
-rw-r--r-- | core/modules/update/update.post_update.php | 23 | ||||
-rw-r--r-- | core/modules/update/update.services.yml | 1 |
13 files changed, 298 insertions, 173 deletions
diff --git a/core/modules/update/src/Hook/UpdateHooks.php b/core/modules/update/src/Hook/UpdateHooks.php index 293882f01246..2502d4bb1715 100644 --- a/core/modules/update/src/Hook/UpdateHooks.php +++ b/core/modules/update/src/Hook/UpdateHooks.php @@ -77,8 +77,15 @@ class UpdateHooks { $verbose = TRUE; break; } + // This loadInclude() is to ensure that the install API is available. + // Since we're loading an include of type 'install', this will also + // include core/includes/install.inc for us, which is where the + // REQUIREMENTS* constants are currently defined. + // @todo Remove this once those constants live in a better place. + // @see https://www.drupal.org/project/drupal/issues/2909480 + // @see https://www.drupal.org/project/drupal/issues/3410938 \Drupal::moduleHandler()->loadInclude('update', 'install'); - $status = update_requirements('runtime'); + $status = \Drupal::moduleHandler()->invoke('update', 'runtime_requirements'); foreach (['core', 'contrib'] as $report_type) { $type = 'update_' . $report_type; // hook_requirements() supports render arrays therefore we need to @@ -178,8 +185,6 @@ class UpdateHooks { \Drupal::moduleHandler()->loadInclude('update', 'inc', 'update.fetch'); _update_cron_notify(); } - // Clear garbage from disk. - update_clear_update_disk_cache(); } /** diff --git a/core/modules/update/src/Hook/UpdateRequirements.php b/core/modules/update/src/Hook/UpdateRequirements.php new file mode 100644 index 000000000000..4aa5ccc1826f --- /dev/null +++ b/core/modules/update/src/Hook/UpdateRequirements.php @@ -0,0 +1,161 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\update\Hook; + +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Hook\Attribute\Hook; +use Drupal\Core\Link; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\Url; +use Drupal\update\ProjectSecurityData; +use Drupal\update\ProjectSecurityRequirement; +use Drupal\update\UpdateFetcherInterface; +use Drupal\update\UpdateManagerInterface; + +/** + * Requirements for the update module. + */ +class UpdateRequirements { + + use StringTranslationTrait; + + public function __construct( + protected readonly ModuleHandlerInterface $moduleHandler, + ) {} + + /** + * Implements hook_runtime_requirements(). + * + * Describes the status of the site regarding available updates. If + * there is no update data, only one record will be returned, indicating that + * the status of core can't be determined. If data is available, there will + * be two records: one for core, and another for all of contrib (assuming + * there are any contributed modules or themes installed on the site). In + * addition to the fields expected by hook_requirements ('value', 'severity', + * and optionally 'description'), this array will contain a 'reason' + * attribute, which is an integer constant to indicate why the given status + * is being returned (UPDATE_NOT_SECURE, UPDATE_NOT_CURRENT, or + * UPDATE_UNKNOWN). This is used for generating the appropriate email + * notification messages during update_cron(), and might be useful for other + * modules that invoke update_runtime_requirements() to find out if the site + * is up to date or not. + * + * @see _update_message_text() + * @see _update_cron_notify() + * @see \Drupal\update\UpdateManagerInterface + */ + #[Hook('runtime_requirements')] + public function runtime(): array { + $requirements = []; + if ($available = update_get_available(FALSE)) { + $this->moduleHandler->loadInclude('update', 'inc', 'update.compare'); + $data = update_calculate_project_data($available); + // First, populate the requirements for core: + $requirements['update_core'] = $this->requirementCheck($data['drupal'], 'core'); + if (!empty($available['drupal']['releases'])) { + $security_data = ProjectSecurityData::createFromProjectDataAndReleases($data['drupal'], $available['drupal']['releases'])->getCoverageInfo(); + if ($core_coverage_requirement = ProjectSecurityRequirement::createFromProjectDataAndSecurityCoverageInfo($data['drupal'], $security_data)->getRequirement()) { + $requirements['coverage_core'] = $core_coverage_requirement; + } + } + + // We don't want to check drupal a second time. + unset($data['drupal']); + if (!empty($data)) { + // Now, sort our $data array based on each project's status. The + // status constants are numbered in the right order of precedence, so + // we just need to make sure the projects are sorted in ascending + // order of status, and we can look at the first project we find. + uasort($data, '_update_project_status_sort'); + $first_project = reset($data); + $requirements['update_contrib'] = $this->requirementCheck($first_project, 'contrib'); + } + } + else { + $requirements['update_core']['title'] = $this->t('Drupal core update status'); + $requirements['update_core']['value'] = $this->t('No update data available'); + $requirements['update_core']['severity'] = REQUIREMENT_WARNING; + $requirements['update_core']['reason'] = UpdateFetcherInterface::UNKNOWN; + $requirements['update_core']['description'] = _update_no_data(); + } + return $requirements; + } + + /** + * Fills in the requirements array. + * + * This is shared for both core and contrib to generate the right elements in + * the array for hook_runtime_requirements(). + * + * @param array $project + * Array of information about the project we're testing as returned by + * update_calculate_project_data(). + * @param string $type + * What kind of project this is ('core' or 'contrib'). + * + * @return array + * An array to be included in the nested $requirements array. + * + * @see hook_requirements() + * @see update_requirements() + * @see update_calculate_project_data() + */ + protected function requirementCheck($project, $type): array { + $requirement = []; + if ($type == 'core') { + $requirement['title'] = $this->t('Drupal core update status'); + } + else { + $requirement['title'] = $this->t('Module and theme update status'); + } + $status = $project['status']; + if ($status != UpdateManagerInterface::CURRENT) { + $requirement['reason'] = $status; + $requirement['severity'] = REQUIREMENT_ERROR; + // When updates are available, append the available updates link to the + // message from _update_message_text(), and format the two translated + // strings together in a single paragraph. + $requirement['description'][] = ['#markup' => _update_message_text($type, $status)]; + if (!in_array($status, [UpdateFetcherInterface::UNKNOWN, UpdateFetcherInterface::NOT_CHECKED, UpdateFetcherInterface::NOT_FETCHED, UpdateFetcherInterface::FETCH_PENDING])) { + $requirement['description'][] = ['#prefix' => ' ', '#markup' => $this->t('See the <a href=":available_updates">available updates</a> page for more information.', [':available_updates' => Url::fromRoute('update.status')->toString()])]; + } + } + switch ($status) { + case UpdateManagerInterface::NOT_SECURE: + $requirement_label = $this->t('Not secure!'); + break; + + case UpdateManagerInterface::REVOKED: + $requirement_label = $this->t('Revoked!'); + break; + + case UpdateManagerInterface::NOT_SUPPORTED: + $requirement_label = $this->t('Unsupported release'); + break; + + case UpdateManagerInterface::NOT_CURRENT: + $requirement_label = $this->t('Out of date'); + $requirement['severity'] = REQUIREMENT_WARNING; + break; + + case UpdateFetcherInterface::UNKNOWN: + case UpdateFetcherInterface::NOT_CHECKED: + case UpdateFetcherInterface::NOT_FETCHED: + case UpdateFetcherInterface::FETCH_PENDING: + $requirement_label = $project['reason'] ?? $this->t('Can not determine status'); + $requirement['severity'] = REQUIREMENT_WARNING; + break; + + default: + $requirement_label = $this->t('Up to date'); + } + if ($status != UpdateManagerInterface::CURRENT && $type == 'core' && isset($project['recommended'])) { + $requirement_label .= ' ' . $this->t('(version @version available)', ['@version' => $project['recommended']]); + } + $requirement['value'] = Link::fromTextAndUrl($requirement_label, Url::fromRoute('update.status'))->toString(); + return $requirement; + } + +} diff --git a/core/modules/update/src/UpdateRoot.php b/core/modules/update/src/UpdateRoot.php index a2f1619d6ea6..604e9ff0f529 100644 --- a/core/modules/update/src/UpdateRoot.php +++ b/core/modules/update/src/UpdateRoot.php @@ -6,7 +6,12 @@ use Drupal\Core\DrupalKernelInterface; use Symfony\Component\HttpFoundation\RequestStack; /** - * Gets the root path used by the Update Manager to install or update projects. + * Gets the root path used by the legacy Update Manager. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ class UpdateRoot { @@ -32,7 +37,7 @@ class UpdateRoot { protected $updateRoot; /** - * Constructs an UpdateRootFactory instance. + * Constructs an UpdateRoot instance. * * @param \Drupal\Core\DrupalKernelInterface $drupal_kernel * The Drupal kernel. @@ -40,6 +45,7 @@ class UpdateRoot { * The request stack. */ public function __construct(DrupalKernelInterface $drupal_kernel, RequestStack $request_stack) { + @trigger_error(__CLASS__ . ' is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); $this->drupalKernel = $drupal_kernel; $this->requestStack = $request_stack; } diff --git a/core/modules/update/tests/src/Functional/UpdateManagerTest.php b/core/modules/update/tests/src/Functional/UpdateManagerTest.php new file mode 100644 index 000000000000..a69e06a72fdd --- /dev/null +++ b/core/modules/update/tests/src/Functional/UpdateManagerTest.php @@ -0,0 +1,37 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\update\Functional; + +/** + * Tests legacy Update Manager functionality of the Update Status module. + * + * @group legacy + * @group update + */ +class UpdateManagerTest extends UpdateTestBase { + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * Checks that clearing the disk cache works. + */ + public function testClearDiskCache(): void { + $directories = [ + _update_manager_cache_directory(FALSE), + _update_manager_extract_directory(FALSE), + ]; + // Check that update directories does not exists. + foreach ($directories as $directory) { + $this->assertDirectoryDoesNotExist($directory); + } + + // Method must not fail if update directories do not exists. + update_clear_update_disk_cache(); + } + +} diff --git a/core/modules/update/tests/src/Functional/UpdateMiscTest.php b/core/modules/update/tests/src/Functional/UpdateMiscTest.php index 5b544ea36b0e..3a06d965ee5e 100644 --- a/core/modules/update/tests/src/Functional/UpdateMiscTest.php +++ b/core/modules/update/tests/src/Functional/UpdateMiscTest.php @@ -41,23 +41,6 @@ class UpdateMiscTest extends UpdateTestBase { } /** - * Checks that clearing the disk cache works. - */ - public function testClearDiskCache(): void { - $directories = [ - _update_manager_cache_directory(FALSE), - _update_manager_extract_directory(FALSE), - ]; - // Check that update directories does not exists. - foreach ($directories as $directory) { - $this->assertDirectoryDoesNotExist($directory); - } - - // Method must not fail if update directories do not exists. - update_clear_update_disk_cache(); - } - - /** * Tests the Update Status module when the update server returns 503 errors. */ public function testServiceUnavailable(): void { diff --git a/core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php b/core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php index ff5a8b02d457..1e33d81d6141 100644 --- a/core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php +++ b/core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php @@ -10,6 +10,7 @@ use Drupal\KernelTests\KernelTestBase; * Tests the update_delete_file_if_stale() function. * * @group update + * @group legacy */ class UpdateDeleteFileIfStaleTest extends KernelTestBase { diff --git a/core/modules/update/update.authorize.inc b/core/modules/update/update.authorize.inc index 64f8fe7b014a..cab253303bbb 100644 --- a/core/modules/update/update.authorize.inc +++ b/core/modules/update/update.authorize.inc @@ -33,7 +33,7 @@ use Drupal\Core\Url; */ #[ProceduralHookScanStop] function update_authorize_run_update($filetransfer, $projects) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); $batch_builder = (new BatchBuilder()) ->setFile(\Drupal::service('extension.list.module')->getPath('update') . '/update.authorize.inc') @@ -79,7 +79,7 @@ function update_authorize_run_update($filetransfer, $projects) { * Reference to an array used for Batch API storage. */ function update_authorize_batch_copy_project($project, $updater_name, $local_url, $filetransfer, &$context): void { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); // Initialize some variables in the Batch API $context array. if (!isset($context['results']['log'])) { @@ -100,6 +100,7 @@ function update_authorize_batch_copy_project($project, $updater_name, $local_url // though the connection itself is now gone. So, although it's ugly, we have // to unset the connection variable at this point so that the FileTransfer // object will re-initiate the actual connection. + // @phpstan-ignore property.deprecatedClass unset($filetransfer->connection); if (!empty($context['results']['log'][$project]['#abort'])) { @@ -107,6 +108,7 @@ function update_authorize_batch_copy_project($project, $updater_name, $local_url return; } + // @phpstan-ignore getDeprecatedService.deprecated $updater = new $updater_name($local_url, \Drupal::getContainer()->get('update.root')); try { @@ -149,7 +151,7 @@ function update_authorize_batch_copy_project($project, $updater_name, $local_url * An associative array of results from the batch operation. */ function update_authorize_update_batch_finished($success, $results): void { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); foreach ($results['log'] as $messages) { if (!empty($messages['#abort'])) { @@ -233,7 +235,7 @@ function update_authorize_update_batch_finished($success, $results): void { * if there were errors. Defaults to TRUE. */ function _update_batch_create_message(&$project_results, $message, $success = TRUE): void { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); $project_results[] = ['message' => $message, 'success' => $success]; } @@ -252,7 +254,7 @@ function _update_batch_create_message(&$project_results, $message, $success = TR * @see update_storage_clear() */ function _update_authorize_clear_update_status(): void { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); \Drupal::keyValueExpirable('update')->deleteAll(); \Drupal::keyValueExpirable('update_available_release')->deleteAll(); diff --git a/core/modules/update/update.fetch.inc b/core/modules/update/update.fetch.inc index 296dfbd3d06d..a0d2a22e5624 100644 --- a/core/modules/update/update.fetch.inc +++ b/core/modules/update/update.fetch.inc @@ -19,8 +19,15 @@ use Drupal\update\UpdateManagerInterface; #[ProceduralHookScanStop] function _update_cron_notify(): void { $update_config = \Drupal::config('update.settings'); + // This loadInclude() is to ensure that the install API is available. + // Since we're loading an include of type 'install', this will also + // include core/includes/install.inc for us, which is where the + // REQUIREMENTS* constants are currently defined. + // @todo Remove this once those constants live in a better place. + // @see https://www.drupal.org/project/drupal/issues/2909480 + // @see https://www.drupal.org/project/drupal/issues/3410938 \Drupal::moduleHandler()->loadInclude('update', 'install'); - $status = update_requirements('runtime'); + $status = \Drupal::moduleHandler()->invoke('update', 'runtime_requirements'); $params = []; $notify_all = ($update_config->get('notification.threshold') == 'all'); foreach (['core', 'contrib'] as $report_type) { diff --git a/core/modules/update/update.install b/core/modules/update/update.install index 3ad55265aab1..ccd73e993bc6 100644 --- a/core/modules/update/update.install +++ b/core/modules/update/update.install @@ -6,70 +6,6 @@ */ use Drupal\Core\Hook\Attribute\ProceduralHookScanStop; -use Drupal\Core\Link; -use Drupal\Core\Url; -use Drupal\update\ProjectSecurityData; -use Drupal\update\ProjectSecurityRequirement; -use Drupal\update\UpdateFetcherInterface; -use Drupal\update\UpdateManagerInterface; - -/** - * Implements hook_requirements(). - * - * Describes the status of the site regarding available updates. If - * there is no update data, only one record will be returned, indicating that - * the status of core can't be determined. If data is available, there will be - * two records: one for core, and another for all of contrib (assuming there - * are any contributed modules or themes installed on the site). In addition to - * the fields expected by hook_requirements ('value', 'severity', and - * optionally 'description'), this array will contain a 'reason' attribute, - * which is an integer constant to indicate why the given status is being - * returned (UPDATE_NOT_SECURE, UPDATE_NOT_CURRENT, or UPDATE_UNKNOWN). This - * is used for generating the appropriate email notification messages during - * update_cron(), and might be useful for other modules that invoke - * update_requirements() to find out if the site is up to date or not. - * - * @see _update_message_text() - * @see _update_cron_notify() - * @see \Drupal\update\UpdateManagerInterface - */ -function update_requirements($phase): array { - $requirements = []; - if ($phase == 'runtime') { - if ($available = update_get_available(FALSE)) { - \Drupal::moduleHandler()->loadInclude('update', 'inc', 'update.compare'); - $data = update_calculate_project_data($available); - // First, populate the requirements for core: - $requirements['update_core'] = _update_requirement_check($data['drupal'], 'core'); - if (!empty($available['drupal']['releases'])) { - $security_data = ProjectSecurityData::createFromProjectDataAndReleases($data['drupal'], $available['drupal']['releases'])->getCoverageInfo(); - if ($core_coverage_requirement = ProjectSecurityRequirement::createFromProjectDataAndSecurityCoverageInfo($data['drupal'], $security_data)->getRequirement()) { - $requirements['coverage_core'] = $core_coverage_requirement; - } - } - - // We don't want to check drupal a second time. - unset($data['drupal']); - if (!empty($data)) { - // Now, sort our $data array based on each project's status. The - // status constants are numbered in the right order of precedence, so - // we just need to make sure the projects are sorted in ascending - // order of status, and we can look at the first project we find. - uasort($data, '_update_project_status_sort'); - $first_project = reset($data); - $requirements['update_contrib'] = _update_requirement_check($first_project, 'contrib'); - } - } - else { - $requirements['update_core']['title'] = t('Drupal core update status'); - $requirements['update_core']['value'] = t('No update data available'); - $requirements['update_core']['severity'] = REQUIREMENT_WARNING; - $requirements['update_core']['reason'] = UpdateFetcherInterface::UNKNOWN; - $requirements['update_core']['description'] = _update_no_data(); - } - } - return $requirements; -} /** * Implements hook_install(). @@ -92,81 +28,6 @@ function update_uninstall(): void { } /** - * Fills in the requirements array. - * - * This is shared for both core and contrib to generate the right elements in - * the array for hook_requirements(). - * - * @param array $project - * Array of information about the project we're testing as returned by - * update_calculate_project_data(). - * @param string $type - * What kind of project this is ('core' or 'contrib'). - * - * @return array - * An array to be included in the nested $requirements array. - * - * @see hook_requirements() - * @see update_requirements() - * @see update_calculate_project_data() - */ -function _update_requirement_check($project, $type): array { - $requirement = []; - if ($type == 'core') { - $requirement['title'] = t('Drupal core update status'); - } - else { - $requirement['title'] = t('Module and theme update status'); - } - $status = $project['status']; - if ($status != UpdateManagerInterface::CURRENT) { - $requirement['reason'] = $status; - $requirement['severity'] = REQUIREMENT_ERROR; - // When updates are available, append the available updates link to the - // message from _update_message_text(), and format the two translated - // strings together in a single paragraph. - $requirement['description'][] = ['#markup' => _update_message_text($type, $status)]; - if (!in_array($status, [UpdateFetcherInterface::UNKNOWN, UpdateFetcherInterface::NOT_CHECKED, UpdateFetcherInterface::NOT_FETCHED, UpdateFetcherInterface::FETCH_PENDING])) { - $requirement['description'][] = ['#prefix' => ' ', '#markup' => t('See the <a href=":available_updates">available updates</a> page for more information.', [':available_updates' => Url::fromRoute('update.status')->toString()])]; - } - } - switch ($status) { - case UpdateManagerInterface::NOT_SECURE: - $requirement_label = t('Not secure!'); - break; - - case UpdateManagerInterface::REVOKED: - $requirement_label = t('Revoked!'); - break; - - case UpdateManagerInterface::NOT_SUPPORTED: - $requirement_label = t('Unsupported release'); - break; - - case UpdateManagerInterface::NOT_CURRENT: - $requirement_label = t('Out of date'); - $requirement['severity'] = REQUIREMENT_WARNING; - break; - - case UpdateFetcherInterface::UNKNOWN: - case UpdateFetcherInterface::NOT_CHECKED: - case UpdateFetcherInterface::NOT_FETCHED: - case UpdateFetcherInterface::FETCH_PENDING: - $requirement_label = $project['reason'] ?? t('Can not determine status'); - $requirement['severity'] = REQUIREMENT_WARNING; - break; - - default: - $requirement_label = t('Up to date'); - } - if ($status != UpdateManagerInterface::CURRENT && $type == 'core' && isset($project['recommended'])) { - $requirement_label .= ' ' . t('(version @version available)', ['@version' => $project['recommended']]); - } - $requirement['value'] = Link::fromTextAndUrl($requirement_label, Url::fromRoute('update.status'))->toString(); - return $requirement; -} - -/** * Implements hook_update_last_removed(). */ function update_update_last_removed(): int { diff --git a/core/modules/update/update.manager.inc b/core/modules/update/update.manager.inc index f4b18321002b..de29e229dd46 100644 --- a/core/modules/update/update.manager.inc +++ b/core/modules/update/update.manager.inc @@ -26,7 +26,7 @@ use Psr\Http\Client\ClientExceptionInterface; */ #[ProceduralHookScanStop] function _update_manager_check_backends(&$form, $operation) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); // If file transfers will be performed locally, we do not need to display any // warnings or notices to the user and should automatically continue the @@ -94,7 +94,7 @@ function _update_manager_check_backends(&$form, $operation) { * @throws Exception */ function update_manager_archive_extract($file, $directory) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); /** @var \Drupal\Core\Archiver\ArchiverInterface $archiver */ $archiver = \Drupal::service('plugin.manager.archiver')->getInstance([ @@ -145,7 +145,7 @@ function update_manager_archive_extract($file, $directory) { * are no errors, it will be an empty array. */ function update_manager_archive_verify($project, $archive_file, $directory) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); return \Drupal::moduleHandler()->invokeAllDeprecated('There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', 'verify_update_archive', [$project, $archive_file, $directory]); } @@ -162,7 +162,7 @@ function update_manager_archive_verify($project, $archive_file, $directory) { * Path to local file, or FALSE if it could not be retrieved. */ function update_manager_file_get($url) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); $parsed_url = parse_url($url); $remote_schemes = ['http', 'https', 'ftp', 'ftps', 'smb', 'nfs']; @@ -172,9 +172,11 @@ function update_manager_file_get($url) { } // Check the cache and download the file if needed. + // @phpstan-ignore function.deprecated $cache_directory = _update_manager_cache_directory(); $local = $cache_directory . '/' . \Drupal::service('file_system')->basename($parsed_url['path']); + // @phpstan-ignore function.deprecated if (!file_exists($local) || update_delete_file_if_stale($local)) { try { $data = (string) \Drupal::httpClient()->get($url)->getBody(); @@ -212,7 +214,7 @@ function update_manager_file_get($url) { * @see update_manager_download_page() */ function update_manager_batch_project_get($project, $url, &$context): void { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); // This is here to show the user that we are in the process of downloading. if (!isset($context['sandbox']['started'])) { @@ -229,6 +231,7 @@ function update_manager_batch_project_get($project, $url, &$context): void { } // Extract it. + // @phpstan-ignore function.deprecated $extract_directory = _update_manager_extract_directory(); try { update_manager_archive_extract($local_cache, $extract_directory); @@ -274,7 +277,7 @@ function update_manager_batch_project_get($project, $url, &$context): void { * @see install_check_requirements() */ function update_manager_local_transfers_allowed() { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3512364', E_USER_DEPRECATED); $file_system = \Drupal::service('file_system'); // Compare the owner of a webserver-created temporary file to the owner of diff --git a/core/modules/update/update.module b/core/modules/update/update.module index e06ac21ea317..89e94fe7b1d7 100644 --- a/core/modules/update/update.module +++ b/core/modules/update/update.module @@ -276,8 +276,15 @@ function update_storage_clear(): void { * * @return string * An eight character string uniquely identifying this Drupal installation. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function _update_manager_unique_identifier() { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + static $id; if (!isset($id)) { $id = substr(hash('sha256', Settings::getHashSalt()), 0, 8); @@ -295,8 +302,15 @@ function _update_manager_unique_identifier() { * @return string * The full path to the temporary directory where update file archives should * be extracted. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function _update_manager_extract_directory($create = TRUE) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + static $directory; if (!isset($directory)) { $directory = 'temporary://update-extraction-' . _update_manager_unique_identifier(); @@ -317,8 +331,15 @@ function _update_manager_extract_directory($create = TRUE) { * @return string * The full path to the temporary directory where update file archives should * be cached. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function _update_manager_cache_directory($create = TRUE) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + static $directory; if (!isset($directory)) { $directory = 'temporary://update-cache-' . _update_manager_unique_identifier(); @@ -331,8 +352,15 @@ function _update_manager_cache_directory($create = TRUE) { /** * Clears the temporary files and directories based on file age from disk. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function update_clear_update_disk_cache(): void { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + // List of update module cache directories. Do not create the directories if // they do not exist. $directories = [ @@ -368,8 +396,15 @@ function update_clear_update_disk_cache(): void { * * @return bool * TRUE if the file is stale and deleted successfully, FALSE otherwise. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function update_delete_file_if_stale($path) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + if (file_exists($path)) { $filectime = filectime($path); $max_age = \Drupal::config('system.file')->get('temporary_maximum_age'); diff --git a/core/modules/update/update.post_update.php b/core/modules/update/update.post_update.php index 3462899d989b..34ddba396858 100644 --- a/core/modules/update/update.post_update.php +++ b/core/modules/update/update.post_update.php @@ -5,6 +5,8 @@ * Post update functions for Update Status. */ +use Drupal\Core\Site\Settings; + /** * Implements hook_removed_post_updates(). */ @@ -14,3 +16,24 @@ function update_remove_post_updates() { 'update_post_update_set_blank_fetch_url_to_null' => '11.0.0', ]; } + +/** + * Removes the legacy 'Update Manager' disk cache. + */ +function update_post_update_clear_disk_cache(): void { + // @see _update_manager_unique_id() + $id = substr(hash('sha256', Settings::getHashSalt()), 0, 8); + // List of legacy 'Update Manager' cache directories. + $directories = [ + // @see _update_manager_cache_directory() + "temporary://update-cache-$id", + // @see _update_manager_extract_directory() + "temporary://update-extraction-$id", + ]; + foreach ($directories as $directory) { + if (is_dir($directory)) { + \Drupal::service('file_system')->deleteRecursive($directory); + } + } + +} diff --git a/core/modules/update/update.services.yml b/core/modules/update/update.services.yml index 465df135529a..bebf0398151c 100644 --- a/core/modules/update/update.services.yml +++ b/core/modules/update/update.services.yml @@ -21,6 +21,7 @@ services: update.root: class: Drupal\update\UpdateRoot arguments: ['@kernel', '@request_stack'] + deprecated: The "%service_id%" service is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119 logger.channel.update: parent: logger.channel_base arguments: [ 'update' ] |