summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/update
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/update')
-rw-r--r--core/modules/update/src/Hook/UpdateHooks.php11
-rw-r--r--core/modules/update/src/Hook/UpdateRequirements.php161
-rw-r--r--core/modules/update/src/UpdateRoot.php10
-rw-r--r--core/modules/update/tests/src/Functional/UpdateManagerTest.php37
-rw-r--r--core/modules/update/tests/src/Functional/UpdateMiscTest.php17
-rw-r--r--core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php1
-rw-r--r--core/modules/update/update.authorize.inc12
-rw-r--r--core/modules/update/update.fetch.inc9
-rw-r--r--core/modules/update/update.install139
-rw-r--r--core/modules/update/update.manager.inc15
-rw-r--r--core/modules/update/update.module35
-rw-r--r--core/modules/update/update.post_update.php23
-rw-r--r--core/modules/update/update.services.yml1
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' ]