From 73a5d20ea90f9af3524293ddb0b09ee86667b4e8 Mon Sep 17 00:00:00 2001 From: xjm <xjm@65776.no-reply.drupal.org> Date: Fri, 27 May 2022 11:13:39 -0500 Subject: [PATCH] Revert "Issue #3261447 by xjm, lauriii, ravi.shankar, Wim Leers, alexpott, tedbow, daffie: Add an API for dynamically setting recommended and supported PHP versions based on known and predicted PHP release schedules" This reverts commit 3412b7bdb83edfe8120f4d25a4ba3c939c81e2d8. --- core/lib/Drupal.php | 11 ++ .../Drupal/Core/Utility/PhpRequirements.php | 109 ----------- core/modules/system/system.install | 9 +- .../Functional/System/PhpRequirementTest.php | 8 +- .../Installer/InstallerTestBase.php | 3 +- core/tests/Drupal/Tests/Core/DrupalTest.php | 8 +- .../Core/Utility/PhpRequirementsTest.php | 184 ------------------ .../Drupal/Tests/RequirementsPageTrait.php | 6 +- 8 files changed, 23 insertions(+), 315 deletions(-) delete mode 100644 core/lib/Drupal/Core/Utility/PhpRequirements.php delete mode 100644 core/tests/Drupal/Tests/Core/Utility/PhpRequirementsTest.php diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php index 230fd76a3c38..c0270ada4a7f 100644 --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -87,6 +87,17 @@ class Drupal { */ const CORE_MINIMUM_SCHEMA_VERSION = 8000; + /** + * Minimum supported version of PHP. + * + * Below this version: + * - New sites cannot be installed, except from within tests. + * - Updates from previous Drupal versions can be run, but users are warned + * that Drupal no longer supports that PHP version. + * - An error is shown in the status report that the PHP version is too old. + */ + const MINIMUM_SUPPORTED_PHP = '8.1.0'; + /** * Minimum allowed version of PHP for Drupal to be bootstrapped. * diff --git a/core/lib/Drupal/Core/Utility/PhpRequirements.php b/core/lib/Drupal/Core/Utility/PhpRequirements.php deleted file mode 100644 index 2414c582d800..000000000000 --- a/core/lib/Drupal/Core/Utility/PhpRequirements.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -namespace Drupal\Core\Utility; - -/** - * Provides an object for dynamically identifying the minimum supported PHP. - */ -final class PhpRequirements { - - /** - * The minimum PHP version requirement for the installed Drupal version. - * - * This property is maintained to make the class testable. - * - * @var string - * - * @see version_compare() - */ - private static $drupalMinimumPhp = \Drupal::MINIMUM_PHP; - - /** - * The expected PHP version end-of-life dates, keyed by PHP minor version. - * - * The array keys are in 'major.minor' format, and the date values are in ISO - * 8601 format. - * - * @var string[] - * An array of end-of-life dates in ISO 8601 format, keyed by the PHP minor - * version in 'major.minor' format. The list must be sorted in an ascending - * order by the date. Multiple versions EOL on the same day must be sorted - * by the PHP version. - */ - private static $phpEolDates = [ - '7.3' => '2021-12-06', - '7.4' => '2022-11-28', - '8.0' => '2023-11-26', - '8.1' => '2024-11-25', - ]; - - /** - * This class should not be instantiated. - */ - private function __construct() { - } - - /** - * Dynamically identifies the minimum supported PHP version based on the date. - * - * Drupal automatically increases the minimum supported PHP version from - * \Drupal::MINIMUM_PHP to a newer version after PHP's documented end-of-life - * date for the previous version. - * - * Below this version: - * - New sites can be installed (to allow update deployment workflows that - * reinstall sites from configuration), but a warning is displayed in the - * installer that the PHP version is too old (except within tests). - * - Updates from previous Drupal versions can be run, but users are warned - * that Drupal no longer supports that PHP version. - * - An error is shown in the status report that the PHP version is too old. - * - * @param \DateTime|null $date - * The DateTime to check. Defaults to the current datetime (now) if NULL. - * - * @return string - * The minimum supported PHP version on the date in a PHP-standardized - * number format supported by version_compare(). For example, '8.0.2' or - * '8.1'. This will be the lowest PHP version above the minimum PHP version - * supported by Drupal that is still supported, or the highest known PHP - * version if no known versions are still supported. - * - * @see version_compare() - */ - public static function getMinimumSupportedPhp(?\DateTime $date = NULL): string { - // By default, use the current date (right now). - $date = $date ?? new \DateTime('now'); - - // In case no data are available or all known PHP versions in this class - // are already end-of-life, default to the version that had the most recent - // end-of-life (the key of the last element in the sorted array). - // The string cast ensures the value is a string, even if the PHP EOL date - // array is empty. As of PHP 8.1, version_compare() no longer accepts NULL - // as a parameter; empty string must be used instead. - $lowest_supported_version = $lowest_supported_version ?? (string) array_key_last(static::$phpEolDates); - - // Next, look at versions that are end-of-life after the current date. - // Find the lowest PHP version that is still supported. - foreach (static::$phpEolDates as $version => $eol_date) { - $eol_datetime = new \DateTime($eol_date); - - if ($eol_datetime > $date) { - // If $version is less than the previously discovered lowest supported - // version, use $version as the lowest supported version instead. - if (version_compare($version, $lowest_supported_version) < 0) { - $lowest_supported_version = $version; - } - } - } - - // If PHP versions older than the Drupal minimum PHP version are still - // supported, return Drupal minimum PHP version instead. - if (version_compare($lowest_supported_version, static::$drupalMinimumPhp) < 0) { - return static::$drupalMinimumPhp; - } - - // Otherwise, return the lowest supported PHP version. - return $lowest_supported_version; - } - -} diff --git a/core/modules/system/system.install b/core/modules/system/system.install index d8cf4c9d44e4..d896ffd2ac78 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -16,7 +16,6 @@ use Drupal\Core\Extension\ExtensionLifecycle; use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Link; -use Drupal\Core\Utility\PhpRequirements; use Drupal\Core\Render\Markup; use Drupal\Core\Site\Settings; use Drupal\Core\StreamWrapper\PrivateStream; @@ -32,10 +31,6 @@ */ function system_requirements($phase) { global $install_state; - - // Get the current default PHP requirements for this version of Drupal. - $minimum_supported_php = PhpRequirements::getMinimumSupportedPhp(); - // Reset the extension lists. /** @var \Drupal\Core\Extension\ModuleExtensionList $module_extension_list */ $module_extension_list = \Drupal::service('extension.list.module'); @@ -289,10 +284,10 @@ function system_requirements($phase) { } // Check if the PHP version is below what Drupal supports. - if (version_compare($phpversion, $minimum_supported_php) < 0) { + if (version_compare($phpversion, \Drupal::MINIMUM_SUPPORTED_PHP) < 0) { $requirements['php']['description'] = t('Your PHP installation is too old. Drupal requires at least PHP %version. It is recommended to upgrade to PHP version %recommended or higher for the best ongoing support. See <a href="http://php.net/supported-versions.php">PHP\'s version support documentation</a> and the <a href=":php_requirements">Drupal PHP requirements</a> page for more information.', [ - '%version' => $minimum_supported_php, + '%version' => \Drupal::MINIMUM_SUPPORTED_PHP, '%recommended' => \Drupal::RECOMMENDED_PHP, ':php_requirements' => 'https://www.drupal.org/docs/system-requirements/php-requirements', ] diff --git a/core/modules/system/tests/src/Functional/System/PhpRequirementTest.php b/core/modules/system/tests/src/Functional/System/PhpRequirementTest.php index dfb63bee495b..af5791940815 100644 --- a/core/modules/system/tests/src/Functional/System/PhpRequirementTest.php +++ b/core/modules/system/tests/src/Functional/System/PhpRequirementTest.php @@ -2,7 +2,6 @@ namespace Drupal\Tests\system\Functional\System; -use Drupal\Core\Utility\PhpRequirements; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\RequirementsPageTrait; @@ -48,7 +47,6 @@ protected function setUp(): void { * Tests status report messages regarding the PHP version. */ public function testStatusPage() { - $minimum_php_version = PhpRequirements::getMinimumSupportedPhp(); // Go to Administration. $this->drupalGet('admin/reports/status'); $this->assertSession()->statusCodeEquals(200); @@ -59,13 +57,13 @@ public function testStatusPage() { // Verify that an error is displayed about the PHP version if it is below // the minimum supported PHP. - if (version_compare($phpversion, $minimum_php_version) < 0) { + if (version_compare($phpversion, \Drupal::MINIMUM_SUPPORTED_PHP) < 0) { $this->assertErrorSummaries(['PHP']); - $this->assertSession()->pageTextContains('Your PHP installation is too old. Drupal requires at least PHP ' . $minimum_php_version); + $this->assertSession()->pageTextContains('Your PHP installation is too old. Drupal requires at least PHP ' . \Drupal::MINIMUM_SUPPORTED_PHP); } // Otherwise, there should be no error. else { - $this->assertSession()->pageTextNotContains('Your PHP installation is too old. Drupal requires at least PHP ' . $minimum_php_version); + $this->assertSession()->pageTextNotContains('Your PHP installation is too old. Drupal requires at least PHP ' . \Drupal::MINIMUM_SUPPORTED_PHP); $this->assertSession()->pageTextNotContains('Errors found'); } diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php index 4b6c28d40f15..3c8e5f66e8de 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php @@ -7,7 +7,6 @@ use Drupal\Core\Session\UserSession; use Drupal\Core\Site\Settings; use Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware; -use Drupal\Core\Utility\PhpRequirements; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\RequirementsPageTrait; use GuzzleHttp\HandlerStack; @@ -253,7 +252,7 @@ protected function setUpSettings() { * @see system_requirements() */ protected function setUpRequirementsProblem() { - if (version_compare(phpversion(), PhpRequirements::getMinimumSupportedPhp()) < 0) { + if (version_compare(phpversion(), \Drupal::MINIMUM_SUPPORTED_PHP) < 0) { $this->continueOnExpectedWarnings(['PHP']); } } diff --git a/core/tests/Drupal/Tests/Core/DrupalTest.php b/core/tests/Drupal/Tests/Core/DrupalTest.php index 052af81346ed..ae549b3b4cd2 100644 --- a/core/tests/Drupal/Tests/Core/DrupalTest.php +++ b/core/tests/Drupal/Tests/Core/DrupalTest.php @@ -437,8 +437,8 @@ public function testAccessManager() { * Tests the PHP constants have consistent values. */ public function testPhpConstants() { - // RECOMMENDED_PHP can be just MAJOR.MINOR so normalize it to allow using - // version_compare(). + // RECOMMENDED_PHP and MINIMUM_SUPPORTED_PHP can be just MAJOR.MINOR so + // normalize them so that version_compare() can be used. $normalizer = function (string $version): string { // The regex below is from \Composer\Semver\VersionParser::normalize(). preg_match('{^(\d{1,5})(\.\d++)?(\.\d++)?$}i', $version, $matches); @@ -447,8 +447,10 @@ public function testPhpConstants() { . (!empty($matches[3]) ? $matches[3] : '.9999999'); }; + $minimum_supported_php = $normalizer(\Drupal::MINIMUM_SUPPORTED_PHP); $recommended_php = $normalizer(\Drupal::RECOMMENDED_PHP); - $this->assertTrue(version_compare($recommended_php, \Drupal::MINIMUM_PHP, '>='), "\Drupal::RECOMMENDED_PHP should be greater or equal to \Drupal::MINIMUM_PHP"); + $this->assertTrue(version_compare($minimum_supported_php, \Drupal::MINIMUM_PHP, '>='), "\Drupal::MINIMUM_SUPPORTED_PHP should be greater or equal to \Drupal::MINIMUM_PHP"); + $this->assertTrue(version_compare($recommended_php, \Drupal::MINIMUM_SUPPORTED_PHP, '>='), "\Drupal::RECOMMENDED_PHP should be greater or equal to \Drupal::MINIMUM_SUPPORTED_PHP"); // As this test depends on the $normalizer function it is tested. $this->assertSame('10.9999999.9999999', $normalizer('10')); diff --git a/core/tests/Drupal/Tests/Core/Utility/PhpRequirementsTest.php b/core/tests/Drupal/Tests/Core/Utility/PhpRequirementsTest.php deleted file mode 100644 index dd13b4f15766..000000000000 --- a/core/tests/Drupal/Tests/Core/Utility/PhpRequirementsTest.php +++ /dev/null @@ -1,184 +0,0 @@ -<?php - -namespace Drupal\Tests\Core\Utility; - -use Drupal\Core\Utility\PhpRequirements; -use Drupal\Tests\UnitTestCase; - -/** - * Tests the \Drupal\Core\Utility\PhpRequirements class. - * - * @coversDefaultClass \Drupal\Core\Utility\PhpRequirements - * @group Utility - */ -class PhpRequirementsTest extends UnitTestCase { - - /** - * Ensures that PHP EOL dates are valid. - * - * This ensures that that all of the PHP EOL Date items are valid ISO 8601 - * dates and are keyed by a valid version number. - */ - public function testPhpEolDates(): void { - $reflected = new \ReflectionClass(PhpRequirements::class); - $php_eol_dates = $reflected->getStaticPropertyValue('phpEolDates'); - - foreach ($php_eol_dates as $version => $eol_date) { - // Ensure that all of the version numbers are defined in a superset of - // semver: 'major.minor.patch-modifier', where (unlike in semver) all - // parts but the major are optional. - // @see version_compare() - $this->assertMatchesRegularExpression('/^([0-9]+)(\.([0-9]+)(\.([0-9]+)(-[A-Za-z0-9]+)?)?)?$/', $version); - - // Ensure that all of the EOL dates are defined using ISO 8601 format. - $this->assertMatchesRegularExpression('/^([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])$/', $eol_date); - } - - // Ensure that the EOL list is sorted in an ascending order by the date. If - // there are multiple versions EOL on the same day, sort by the PHP - // version. - uksort($php_eol_dates, function ($a, $b) use ($php_eol_dates) { - $a_date = strtotime($php_eol_dates[$a]); - $b_date = strtotime($php_eol_dates[$b]); - if ($a_date === $b_date) { - return $a <=> $b; - } - return $a_date <=> $b_date; - }); - $this->assertSame($php_eol_dates, $reflected->getStaticPropertyValue('phpEolDates')); - } - - /** - * Tests the minimum supported PHP for valid scenarios. - * - * @param string $date_string - * A valid PHP date string for the date to check. - * @param string $drupal_minimum_php - * The PHP minimum version hard requirement for the Drupal version, below - * which Drupal cannot be installed or updated, typically - * \Drupal::MINIMUM_PHP. - * @param string[] $php_eol_dates - * Associative array of PHP version EOL date strings, keyed by the PHP minor - * version. - * @param string $expected_php_version - * The PHP version the test should recommend. - * - * @covers ::getMinimumSupportedPhp - * - * @dataProvider providerMinimumSupportedPhp - */ - public function testMinimumSupportedPhp(string $date_string, string $drupal_minimum_php, array $php_eol_dates, string $expected_php_version): void { - $reflected = new \ReflectionClass(PhpRequirements::class); - $reflected->setStaticPropertyValue('drupalMinimumPhp', $drupal_minimum_php); - $reflected->setStaticPropertyValue('phpEolDates', $php_eol_dates); - $date = new \DateTime($date_string); - $this->assertSame($expected_php_version, PhpRequirements::getMinimumSupportedPhp($date)); - } - - /** - * Data provider for ::testMinimumSupportedPhp(). - * - * See the parameter documentation of testMinimumSupportedPhp() for the test - * array structure. The last element is the expected minimum supported PHP. - * - * @return \Generator - * Test scenarios. - */ - public function providerMinimumSupportedPhp(): \Generator { - $eol_lists = []; - - // Test against the known valid data from 9.0.0 to 9.3.0. - $eol_lists['d9_release'] = [ - '7.2' => '2020-11-30', - '7.3' => '2021-12-06', - '7.4' => '2022-11-28', - '8.0' => '2023-11-26', - '8.1' => '2024-11-25', - ]; - - // The actual situation the day of 9.0.0's release. - yield ['2020-06-03', '7.3.0', $eol_lists['d9_release'], '7.3.0']; - - // If Drupal's MINIMUM_PHP had been 7.3.12 then. - yield ['2020-06-03', '7.3.12', $eol_lists['d9_release'], '7.3.12']; - - // If Drupal's MINIMUM_PHP had been 7.2.17 then. - yield ['2020-06-03', '7.2.17', $eol_lists['d9_release'], '7.2.17']; - - // If Drupal's MINIMUM_PHP had been 7.1.5 then. - yield ['2020-06-03', '7.1.5', $eol_lists['d9_release'], '7.2']; - - // If the PHP EOL date list were empty. - yield ['2020-06-03', '7.3.0', [], '7.3.0']; - - // Cases around PHP 7.2's EOL. - yield ['2020-11-29', '7.3.0', $eol_lists['d9_release'], '7.3.0']; - yield ['2020-11-30', '7.3.0', $eol_lists['d9_release'], '7.3.0']; - yield ['2020-12-01', '7.3.0', $eol_lists['d9_release'], '7.3.0']; - - // Cases around PHP 7.3's EOL. - yield ['2021-12-05', '7.3.0', $eol_lists['d9_release'], '7.3.0']; - yield ['2021-12-06', '7.3.0', $eol_lists['d9_release'], '7.4']; - yield ['2021-12-07', '7.3.0', $eol_lists['d9_release'], '7.4']; - - // Cases around PHP 7.4's EOL. - yield ['2022-11-27', '7.3.0', $eol_lists['d9_release'], '7.4']; - yield ['2022-11-28', '7.3.0', $eol_lists['d9_release'], '8.0']; - yield ['2022-11-29', '7.3.0', $eol_lists['d9_release'], '8.0']; - - // Cases around PHP 8.0's EOL. - yield ['2023-11-25', '7.3.0', $eol_lists['d9_release'], '8.0']; - yield ['2023-11-26', '7.3.0', $eol_lists['d9_release'], '8.1']; - yield ['2023-11-27', '7.3.0', $eol_lists['d9_release'], '8.1']; - - // Cases around PHP 8.1's EOL, without any data for 8.2. - yield ['2024-11-24', '7.3.0', $eol_lists['d9_release'], '8.1']; - yield ['2024-11-25', '7.3.0', $eol_lists['d9_release'], '8.1']; - yield ['2024-11-26', '7.3.0', $eol_lists['d9_release'], '8.1']; - - // Cases for Drupal 10, with its current 8.0.2 MINIMUM_PHP, prior to PHP - // 8.0's EOL. - yield ['2021-12-05', '8.0.2', $eol_lists['d9_release'], '8.0.2']; - yield ['2021-12-06', '8.0.2', $eol_lists['d9_release'], '8.0.2']; - yield ['2021-12-07', '8.0.2', $eol_lists['d9_release'], '8.0.2']; - yield ['2022-11-27', '8.0.2', $eol_lists['d9_release'], '8.0.2']; - yield ['2022-11-28', '8.0.2', $eol_lists['d9_release'], '8.0.2']; - yield ['2022-11-29', '8.0.2', $eol_lists['d9_release'], '8.0.2']; - - // Cases for Drupal 10 around PHP 8.0's EOL. - yield ['2023-11-25', '8.0.2', $eol_lists['d9_release'], '8.0.2']; - yield ['2023-11-26', '8.0.2', $eol_lists['d9_release'], '8.1']; - yield ['2023-11-27', '8.0.2', $eol_lists['d9_release'], '8.1']; - - // Cases for Drupal 10 around and after PHP 8.1's EOL, without any data - // for 8.2. - yield ['2024-11-24', '8.0.2', $eol_lists['d9_release'], '8.1']; - yield ['2024-11-25', '8.0.2', $eol_lists['d9_release'], '8.1']; - yield ['2024-11-26', '8.0.2', $eol_lists['d9_release'], '8.1']; - yield ['2027-01-01', '8.0.2', $eol_lists['d9_release'], '8.1']; - - // Test against a hypothetical set of PHP versions that have an LTS - // (supported longer than subsequent versions). - $eol_lists['php_with_lts'] = $eol_lists['d9_release']; - - // Ensure that the PHP version with longest support is listed last. - unset($eol_lists['php_with_lts']['7.4']); - $eol_lists['php_with_lts']['7.4'] = '2025-11-28'; - - yield ['2021-12-05', '7.3', $eol_lists['php_with_lts'], '7.3']; - yield ['2021-12-06', '7.3', $eol_lists['php_with_lts'], '7.4']; - yield ['2022-11-28', '7.3', $eol_lists['php_with_lts'], '7.4']; - yield ['2023-11-26', '7.3', $eol_lists['php_with_lts'], '7.4']; - yield ['2024-11-25', '7.3', $eol_lists['php_with_lts'], '7.4']; - yield ['2025-12-01', '7.3', $eol_lists['php_with_lts'], '7.4']; - - // Case with multiple versions EOL on the same day. - $eol_lists['same_eol_date'] = $eol_lists['d9_release']; - $eol_lists['same_eol_date']['8.2'] = $eol_lists['same_eol_date']['8.1']; - - yield ['2021-12-05', '7.3', $eol_lists['same_eol_date'], '7.3']; - yield ['2023-11-27', '8.0.2', $eol_lists['same_eol_date'], '8.1']; - yield ['2027-07-31', '8.0.2', $eol_lists['same_eol_date'], '8.2']; - } - -} diff --git a/core/tests/Drupal/Tests/RequirementsPageTrait.php b/core/tests/Drupal/Tests/RequirementsPageTrait.php index 9c2db04d46e4..eef29535db27 100644 --- a/core/tests/Drupal/Tests/RequirementsPageTrait.php +++ b/core/tests/Drupal/Tests/RequirementsPageTrait.php @@ -2,8 +2,6 @@ namespace Drupal\Tests; -use Drupal\Core\Utility\PhpRequirements; - /** * Provides helper methods for the requirements page. */ @@ -15,9 +13,7 @@ trait RequirementsPageTrait { protected function updateRequirementsProblem() { // Assert a warning is shown on older test environments. $links = $this->getSession()->getPage()->findAll('named', ['link', 'try again']); - - // Get the default Drupal core PHP requirements. - if ($links && version_compare(phpversion(), PhpRequirements::getMinimumSupportedPhp()) < 0) { + if ($links && version_compare(phpversion(), \Drupal::MINIMUM_SUPPORTED_PHP) < 0) { $this->assertSession()->pageTextNotContains('Errors found'); $this->assertWarningSummaries(['PHP']); $this->clickLink('try again'); -- GitLab