From 41dce09cc0aaad556251831eedcdfcf4c8355d68 Mon Sep 17 00:00:00 2001
From: catch <catch56@gmail.com>
Date: Fri, 21 Oct 2022 11:29:07 +0100
Subject: [PATCH] Issue #309040 by claudiu.cristea, David_Rothstein, Chi,
 BryanGullan, larowlan, dww, joachim: Add hook_requirements_alter()

(cherry picked from commit 5e67517d01085ae5e1d66b7b62f162f20d59ee90)
---
 core/lib/Drupal/Core/Extension/module.api.php | 23 +++++++++++++
 core/modules/system/src/SystemManager.php     |  1 +
 .../requirements1_test.install                | 12 +++++++
 .../requirements1_test.module                 | 18 ++++++++++
 .../src/Kernel/Module/RequirementsTest.php    | 33 +++++++++++++++++++
 5 files changed, 87 insertions(+)
 create mode 100644 core/modules/system/tests/modules/requirements1_test/requirements1_test.module
 create mode 100644 core/modules/system/tests/src/Kernel/Module/RequirementsTest.php

diff --git a/core/lib/Drupal/Core/Extension/module.api.php b/core/lib/Drupal/Core/Extension/module.api.php
index 60e35eecf2a2..582ba318d7d4 100644
--- a/core/lib/Drupal/Core/Extension/module.api.php
+++ b/core/lib/Drupal/Core/Extension/module.api.php
@@ -1022,6 +1022,29 @@ function hook_requirements($phase) {
   return $requirements;
 }
 
+/**
+ * Alters requirements data.
+ *
+ * Implementations are able to alter the title, value, description or the
+ * severity of certain requirements defined by hook_requirements()
+ * implementations or even remove such entries.
+ *
+ * @param array $requirements
+ *   The requirements data to be altered.
+ *
+ * @see hook_requirements()
+ */
+function hook_requirements_alter(array &$requirements): void {
+  // Change the title from 'PHP' to 'PHP version'.
+  $requirements['php']['title'] = t('PHP version');
+
+  // Decrease the 'update status' requirement severity from warning to warning.
+  $requirements['update status']['severity'] = REQUIREMENT_INFO;
+
+  // Remove a requirements entry.
+  unset($requirements['foo']);
+}
+
 /**
  * @} End of "addtogroup hooks".
  */
diff --git a/core/modules/system/src/SystemManager.php b/core/modules/system/src/SystemManager.php
index d8fc9d36ee4c..7c88d95c3e77 100644
--- a/core/modules/system/src/SystemManager.php
+++ b/core/modules/system/src/SystemManager.php
@@ -107,6 +107,7 @@ public function listRequirements() {
 
     // Check run-time requirements and status information.
     $requirements = $this->moduleHandler->invokeAll('requirements', ['runtime']);
+    $this->moduleHandler->alter('requirements', $requirements);
     uasort($requirements, function ($a, $b) {
       if (!isset($a['weight'])) {
         if (!isset($b['weight'])) {
diff --git a/core/modules/system/tests/modules/requirements1_test/requirements1_test.install b/core/modules/system/tests/modules/requirements1_test/requirements1_test.install
index e8121617adc3..611d2d49b87e 100644
--- a/core/modules/system/tests/modules/requirements1_test/requirements1_test.install
+++ b/core/modules/system/tests/modules/requirements1_test/requirements1_test.install
@@ -20,5 +20,17 @@ function requirements1_test_requirements($phase) {
     ];
   }
 
+  $requirements['requirements1_test_alterable'] = [
+    'title' => t('Requirements 1 Test Alterable'),
+    'severity' => REQUIREMENT_ERROR,
+    'description' => t('A requirement that will be altered.'),
+  ];
+
+  $requirements['requirements1_test_deletable'] = [
+    'title' => t('Requirements 1 Test Deletable'),
+    'severity' => REQUIREMENT_INFO,
+    'description' => t('A requirement that will be deleted.'),
+  ];
+
   return $requirements;
 }
diff --git a/core/modules/system/tests/modules/requirements1_test/requirements1_test.module b/core/modules/system/tests/modules/requirements1_test/requirements1_test.module
new file mode 100644
index 000000000000..615c578df329
--- /dev/null
+++ b/core/modules/system/tests/modules/requirements1_test/requirements1_test.module
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @file
+ * Hook implementations for requirements1_test module.
+ */
+
+/**
+ * Implements hook_requirements_alter().
+ */
+function requirements1_test_requirements_alter(array &$requirements): void {
+  // Change the title.
+  $requirements['requirements1_test_alterable']['title'] = t('Requirements 1 Test - Changed');
+  // Decrease the severity.
+  $requirements['requirements1_test_alterable']['severity'] = REQUIREMENT_WARNING;
+  // Delete 'requirements1_test_deletable',
+  unset($requirements['requirements1_test_deletable']);
+}
diff --git a/core/modules/system/tests/src/Kernel/Module/RequirementsTest.php b/core/modules/system/tests/src/Kernel/Module/RequirementsTest.php
new file mode 100644
index 000000000000..f44442417fd2
--- /dev/null
+++ b/core/modules/system/tests/src/Kernel/Module/RequirementsTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Drupal\Tests\system\Kernel\Module;
+
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * @covers \hook_requirements
+ * @covers \hook_requirements_alter
+ * @group Module
+ */
+class RequirementsTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'requirements1_test',
+    'system',
+  ];
+
+  /**
+   * Tests requirements data altering.
+   */
+  public function testRequirementsAlter(): void {
+    $requirements = $this->container->get('system.manager')->listRequirements();
+    // @see requirements1_test_requirements_alter()
+    $this->assertEquals('Requirements 1 Test - Changed', $requirements['requirements1_test_alterable']['title']);
+    $this->assertEquals(REQUIREMENT_WARNING, $requirements['requirements1_test_alterable']['severity']);
+    $this->assertArrayNotHasKey('requirements1_test_deletable', $requirements);
+  }
+
+}
-- 
GitLab