diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 499f552..68d8cb8 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -20,7 +20,11 @@ /** * Minimum supported version of PHP. * - * Drupal cannot be installed on versions of PHP older than this version. + * Updates cannot be run on versions of PHP older than this version. + * + * The installer exits early on versions of PHP older than this version. + * + * @see install.php * * @todo Move this to an appropriate autoloadable class. See * https://www.drupal.org/project/drupal/issues/2908079 @@ -28,6 +32,14 @@ const DRUPAL_MINIMUM_PHP = '5.5.9'; /** + * Drupal cannot be installed on versions of PHP older than this version. + * + * @todo Move this to an appropriate autoloadable class. See + * https://www.drupal.org/project/drupal/issues/2908079 + */ +const DRUPAL_MINIMUM_INSTALL_PHP = '7.0.8'; + +/** * Minimum recommended version of PHP. * * Sites installing Drupal on PHP versions lower than this will see a warning diff --git a/core/modules/locale/tests/src/Functional/LocaleTranslatedSchemaDefinitionTest.php b/core/modules/locale/tests/src/Functional/LocaleTranslatedSchemaDefinitionTest.php index 3e39f74..ba5afb9 100644 --- a/core/modules/locale/tests/src/Functional/LocaleTranslatedSchemaDefinitionTest.php +++ b/core/modules/locale/tests/src/Functional/LocaleTranslatedSchemaDefinitionTest.php @@ -4,6 +4,7 @@ use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\RequirementsPageTrait; /** * Adds and configures languages to check field schema definition. @@ -12,6 +13,8 @@ */ class LocaleTranslatedSchemaDefinitionTest extends BrowserTestBase { + use RequirementsPageTrait; + /** * Modules to enable. * @@ -83,6 +86,8 @@ public function testTranslatedUpdate() { // markup and a link instead of specific text because text may be // translated. $this->drupalGet($update_url . '/selection', ['external' => TRUE]); + $this->updateRequirementsProblem(); + $this->drupalGet($update_url . '/selection', ['external' => TRUE]); $this->assertRaw('messages--status', 'No pending updates.'); $this->assertNoLinkByHref('fr/update.php/run', 'No link to run updates.'); } diff --git a/core/modules/simpletest/src/InstallerTestBase.php b/core/modules/simpletest/src/InstallerTestBase.php index 369c3ab..0f4af3a 100644 --- a/core/modules/simpletest/src/InstallerTestBase.php +++ b/core/modules/simpletest/src/InstallerTestBase.php @@ -8,6 +8,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\Session\UserSession; use Drupal\Core\Site\Settings; +use Drupal\Tests\RequirementsPageTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; @@ -22,6 +23,8 @@ */ abstract class InstallerTestBase extends WebTestBase { + use RequirementsPageTrait; + /** * Custom settings.php values to write for a test run. * @@ -213,12 +216,7 @@ protected function setUpSettings() { * @see system_requirements() */ protected function setUpRequirementsProblem() { - // By default, skip the "recommended PHP version" warning on older test - // environments. This allows the installer to be tested consistently on - // both recommended PHP versions and older (but still supported) versions. - if (version_compare(phpversion(), '7.0') < 0) { - $this->continueOnExpectedWarnings(['PHP']); - } + // Do nothing. } /** @@ -244,44 +242,4 @@ protected function refreshVariables() { } } - /** - * Continues installation when an expected warning is found. - * - * @param string[] $expected_warnings - * A list of warning summaries to expect on the requirements screen (e.g. - * 'PHP', 'PHP OPcode caching', etc.). If only the expected warnings - * are found, the test will click the "continue anyway" link to go to the - * next screen of the installer. If an expected warning is not found, or if - * a warning not in the list is present, a fail is raised. - */ - protected function continueOnExpectedWarnings($expected_warnings = []) { - // Don't try to continue if there are errors. - if (strpos($this->getTextContent(), 'Errors found') !== FALSE) { - return; - } - // Allow only details elements that are directly after the warning header - // or each other. There is no guaranteed wrapper we can rely on across - // distributions. When there are multiple warnings, the selectors will be: - // - h3#warning+details summary - // - h3#warning+details+details summary - // - etc. - // We add one more selector than expected warnings to confirm that there - // isn't any other warning before clicking the link. - // @todo Make this more reliable in - // https://www.drupal.org/project/drupal/issues/2927345. - $selectors = []; - for ($i = 0; $i <= count($expected_warnings); $i++) { - $selectors[] = 'h3#warning' . implode('', array_fill(0, $i + 1, '+details')) . ' summary'; - } - $warning_elements = $this->cssSelect(implode(', ', $selectors)); - - // Confirm that there are only the expected warnings. - $warnings = []; - foreach ($warning_elements as $warning) { - $warnings[] = trim((string) $warning); - } - $this->assertEqual($expected_warnings, $warnings); - $this->clickLink('continue anyway'); - } - } diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 960bb7d..d4f3e87 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -186,26 +186,34 @@ function system_requirements($phase) { ]; } - if (version_compare($phpversion, DRUPAL_MINIMUM_PHP) < 0) { - $requirements['php']['description'] = t('Your PHP installation is too old. Drupal requires at least PHP %version.', ['%version' => DRUPAL_MINIMUM_PHP]); + if (version_compare($phpversion, DRUPAL_MINIMUM_INSTALL_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 PHP\'s version support documentation and the Drupal 8 PHP requirements handbook page for more information.', + [ + '%version' => DRUPAL_MINIMUM_INSTALL_PHP, + '%recommended' => DRUPAL_RECOMMENDED_PHP, + ':php_requirements' => 'https://www.drupal.org/docs/8/system-requirements/php', + ] + ); $requirements['php']['severity'] = REQUIREMENT_ERROR; + // If PHP is old, it's not safe to continue with the requirements check. - return $requirements; - } - if ((version_compare($phpversion, DRUPAL_RECOMMENDED_PHP) < 0) && ($phase === 'install' || $phase === 'runtime')) { - // Warn if still on PHP 5. If at least PHP 7.0, relax from "warning" to - // "info", and show it at runtime only, to not scare users while installing. - if (version_compare($phpversion, '7.0') < 0) { - $requirements['php']['description'] = t('Drupal will drop support for this version on March 6, 2019. Upgrade to PHP version %recommended or higher to ensure your site can receive updates and remain secure. See PHP\'s version support documentation and the Drupal 8 PHP requirements handbook page for more information.', ['%recommended' => DRUPAL_RECOMMENDED_PHP, ':php_requirements' => 'https://www.drupal.org/docs/8/system-requirements/php']); + if (version_compare($phpversion, DRUPAL_MINIMUM_PHP) < 0) { + return $requirements; + } + // Only show a warning during updates, so sites running on an older version + // of PHP are still able to run them. + elseif ($phase === 'update') { $requirements['php']['severity'] = REQUIREMENT_WARNING; } - else { - if ($phase === 'runtime') { - $requirements['php']['description'] = t('It is recommended to upgrade to PHP version %recommended or higher for the best ongoing support. See PHP\'s version support documentation and the Drupal 8 PHP requirements handbook page for more information.', ['%recommended' => DRUPAL_RECOMMENDED_PHP, ':php_requirements' => 'https://www.drupal.org/docs/8/system-requirements/php']); - $requirements['php']['severity'] = REQUIREMENT_INFO; - } + // Allow test installations of Drupal on older PHP versions. + elseif ($phase === 'install' && drupal_valid_test_ua()) { + $requirements['php']['severity'] = REQUIREMENT_INFO; } } + elseif ($phase === 'runtime' && version_compare($phpversion, DRUPAL_RECOMMENDED_PHP) < 0) { + $requirements['php']['description'] = t('It is recommended to upgrade to PHP version %recommended or higher for the best ongoing support. See PHP\'s version support documentation and the Drupal 8 PHP requirements handbook page for more information.', ['%recommended' => DRUPAL_RECOMMENDED_PHP, ':php_requirements' => 'https://www.drupal.org/docs/8/system-requirements/php']); + $requirements['php']['severity'] = REQUIREMENT_INFO; + } // Suggest to update to at least 5.5.21 or 5.6.5 for disabling multiple // statements. diff --git a/core/modules/system/tests/src/Functional/Update/DbUpdatesTrait.php b/core/modules/system/tests/src/Functional/Update/DbUpdatesTrait.php index 55f3a04..5fbc1ee 100644 --- a/core/modules/system/tests/src/Functional/Update/DbUpdatesTrait.php +++ b/core/modules/system/tests/src/Functional/Update/DbUpdatesTrait.php @@ -4,6 +4,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; +use Drupal\Tests\RequirementsPageTrait; /** * Provides methods to conditionally enable db update functions and apply @@ -14,6 +15,7 @@ trait DbUpdatesTrait { use StringTranslationTrait; + use RequirementsPageTrait; /** * Enables db updates until the specified index. @@ -34,6 +36,7 @@ protected function enableUpdates($module, $group, $index) { */ protected function applyUpdates() { $this->drupalGet(Url::fromRoute('system.db_update')); + $this->updateRequirementsProblem(); $this->clickLink($this->t('Continue')); $this->clickLink($this->t('Apply pending updates')); $this->checkForMetaRefresh(); diff --git a/core/modules/system/tests/src/Functional/Update/InvalidUpdateHookTest.php b/core/modules/system/tests/src/Functional/Update/InvalidUpdateHookTest.php index 85d041e..44fdf81 100644 --- a/core/modules/system/tests/src/Functional/Update/InvalidUpdateHookTest.php +++ b/core/modules/system/tests/src/Functional/Update/InvalidUpdateHookTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\system\Functional\Update; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\RequirementsPageTrait; /** * Tests that a module implementing hook_update_8000() causes an error to be @@ -12,6 +13,8 @@ */ class InvalidUpdateHookTest extends BrowserTestBase { + use RequirementsPageTrait; + /** * Modules to enable. * @@ -45,6 +48,7 @@ public function testInvalidUpdateHook() { // Confirm that a module with hook_update_8000() cannot be updated. $this->drupalLogin($this->updateUser); $this->drupalGet($this->updateUrl); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->assertText(t('Some of the pending updates cannot be applied because their dependencies were not met.')); } diff --git a/core/modules/system/tests/src/Functional/Update/UpdatePostUpdateTest.php b/core/modules/system/tests/src/Functional/Update/UpdatePostUpdateTest.php index fd9e011..3e2c46a 100644 --- a/core/modules/system/tests/src/Functional/Update/UpdatePostUpdateTest.php +++ b/core/modules/system/tests/src/Functional/Update/UpdatePostUpdateTest.php @@ -78,6 +78,8 @@ public function testPostUpdate() { } $this->drupalGet('update.php/selection'); + $this->updateRequirementsProblem(); + $this->drupalGet('update.php/selection'); $this->assertText('No pending updates.'); } diff --git a/core/modules/system/tests/src/Functional/Update/UpdateSchemaTest.php b/core/modules/system/tests/src/Functional/Update/UpdateSchemaTest.php index e35d52b..aa28be0 100644 --- a/core/modules/system/tests/src/Functional/Update/UpdateSchemaTest.php +++ b/core/modules/system/tests/src/Functional/Update/UpdateSchemaTest.php @@ -5,6 +5,7 @@ use Drupal\Core\Database\Database; use Drupal\Core\Url; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\RequirementsPageTrait; /** * Tests that update hooks are properly run. @@ -13,6 +14,8 @@ */ class UpdateSchemaTest extends BrowserTestBase { + use RequirementsPageTrait; + /** * {@inheritdoc} */ @@ -56,6 +59,7 @@ public function testUpdateHooks() { $this->drupalLogin($this->user); $this->drupalGet($this->updateUrl, ['external' => TRUE]); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->assertRaw('Schema version 8001.'); // Run the update hooks. diff --git a/core/modules/system/tests/src/Functional/Update/UpdateScriptTest.php b/core/modules/system/tests/src/Functional/Update/UpdateScriptTest.php index da215d4..162cbf4 100644 --- a/core/modules/system/tests/src/Functional/Update/UpdateScriptTest.php +++ b/core/modules/system/tests/src/Functional/Update/UpdateScriptTest.php @@ -5,6 +5,7 @@ use Drupal\Core\Url; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\RequirementsPageTrait; /** * Tests the update script access and functionality. @@ -13,6 +14,8 @@ */ class UpdateScriptTest extends BrowserTestBase { + use RequirementsPageTrait; + /** * Modules to enable. * @@ -99,6 +102,7 @@ public function testRequirements() { // If there are no requirements warnings or errors, we expect to be able to // go through the update process uninterrupted. $this->drupalGet($this->updateUrl, ['external' => TRUE]); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->assertText(t('No pending updates.'), 'End of update process was reached.'); // Confirm that all caches were cleared. @@ -110,6 +114,7 @@ public function testRequirements() { // First, run this test with pending updates to make sure they can be run // successfully. + $this->drupalLogin($this->updateUser); $update_script_test_config->set('requirement_type', REQUIREMENT_WARNING)->save(); drupal_set_installed_schema_version('update_script_test', drupal_get_installed_schema_version('update_script_test') - 1); $this->drupalGet($this->updateUrl, ['external' => TRUE]); @@ -177,6 +182,7 @@ public function testNoUpdateFunctionality() { // Click through update.php with 'administer software updates' permission. $this->drupalLogin($this->updateUser); $this->drupalGet($this->updateUrl, ['external' => TRUE]); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->assertText(t('No pending updates.')); $this->assertNoLink('Administration pages'); @@ -188,6 +194,7 @@ public function testNoUpdateFunctionality() { $admin_user = $this->drupalCreateUser(['administer software updates', 'access administration pages']); $this->drupalLogin($admin_user); $this->drupalGet($this->updateUrl, ['external' => TRUE]); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->assertText(t('No pending updates.')); $this->assertLink('Administration pages'); @@ -220,6 +227,7 @@ public function testSuccessfulUpdateFunctionality() { $admin_user = $this->drupalCreateUser(['administer software updates', 'access administration pages', 'access site reports', 'access site in maintenance mode']); $this->drupalLogin($admin_user); $this->drupalGet($this->updateUrl, ['external' => TRUE]); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->clickLink(t('Apply pending updates')); $this->checkForMetaRefresh(); @@ -287,6 +295,7 @@ public function testSuccessfulMultilingualUpdateFunctionality() { // Click through update.php with 'access administration pages' and // 'access site reports' permissions. $this->drupalGet($this->updateUrl, ['external' => TRUE]); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->clickLink(t('Apply pending updates')); $this->checkForMetaRefresh(); @@ -319,6 +328,7 @@ protected function runUpdates($maintenance_mode) { $this->assertNoText('Operating in maintenance mode.'); } $this->drupalGet($this->updateUrl, ['external' => TRUE]); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->clickLink(t('Apply pending updates')); $this->checkForMetaRefresh(); diff --git a/core/modules/system/tests/src/Functional/Update/UpdatesWith7xTest.php b/core/modules/system/tests/src/Functional/Update/UpdatesWith7xTest.php index 4f536ea..7d3a5ef 100644 --- a/core/modules/system/tests/src/Functional/Update/UpdatesWith7xTest.php +++ b/core/modules/system/tests/src/Functional/Update/UpdatesWith7xTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\system\Functional\Update; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\RequirementsPageTrait; /** * Tests that the minimum schema version is correct even if only 7.x update @@ -12,6 +13,8 @@ */ class UpdatesWith7xTest extends BrowserTestBase { + use RequirementsPageTrait; + /** * Modules to enable. * @@ -48,6 +51,7 @@ public function testWith7x() { // Click through update.php with 'administer software updates' permission. $this->drupalLogin($this->updateUser); $this->drupalGet($this->updateUrl, ['external' => TRUE]); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->assertText(t('Some of the pending updates cannot be applied because their dependencies were not met.')); } diff --git a/core/profiles/minimal/tests/src/Functional/MinimalTest.php b/core/profiles/minimal/tests/src/Functional/MinimalTest.php index 568918a..d743fee 100644 --- a/core/profiles/minimal/tests/src/Functional/MinimalTest.php +++ b/core/profiles/minimal/tests/src/Functional/MinimalTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\minimal\Functional; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\RequirementsPageTrait; use Drupal\user\UserInterface; /** @@ -12,6 +13,8 @@ */ class MinimalTest extends BrowserTestBase { + use RequirementsPageTrait; + protected $profile = 'minimal'; /** @@ -34,6 +37,8 @@ public function testMinimal() { // Ensure that there are no pending updates after installation. $this->drupalLogin($this->rootUser); $this->drupalGet('update.php/selection'); + $this->updateRequirementsProblem(); + $this->drupalGet('update.php/selection'); $this->assertText('No pending updates.'); // Ensure that there are no pending entity updates after installation. diff --git a/core/profiles/standard/tests/src/Functional/StandardTest.php b/core/profiles/standard/tests/src/Functional/StandardTest.php index 79584b4..f62e183 100644 --- a/core/profiles/standard/tests/src/Functional/StandardTest.php +++ b/core/profiles/standard/tests/src/Functional/StandardTest.php @@ -10,6 +10,7 @@ use Drupal\dynamic_page_cache\EventSubscriber\DynamicPageCacheSubscriber; use Drupal\filter\Entity\FilterFormat; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\RequirementsPageTrait; use Drupal\user\Entity\Role; /** @@ -20,6 +21,7 @@ class StandardTest extends BrowserTestBase { use SchemaCheckTestTrait; + use RequirementsPageTrait; protected $profile = 'standard'; @@ -155,6 +157,8 @@ public function testStandard() { // Ensure that there are no pending updates after installation. $this->drupalLogin($this->rootUser); $this->drupalGet('update.php/selection'); + $this->updateRequirementsProblem(); + $this->drupalGet('update.php/selection'); $this->assertText('No pending updates.'); // Ensure that there are no pending entity updates after installation. diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php index 9810f34..a66bd57 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php @@ -8,6 +8,7 @@ use Drupal\Core\Site\Settings; use Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\RequirementsPageTrait; use GuzzleHttp\HandlerStack; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -19,6 +20,8 @@ */ abstract class InstallerTestBase extends BrowserTestBase { + use RequirementsPageTrait; + /** * Custom settings.php values to write for a test run. * @@ -244,12 +247,7 @@ protected function setUpSettings() { * @see system_requirements() */ protected function setUpRequirementsProblem() { - // By default, skip the "recommended PHP version" warning on older test - // environments. This allows the installer to be tested consistently on - // both recommended PHP versions and older (but still supported) versions. - if (version_compare(phpversion(), '7.0') < 0) { - $this->continueOnExpectedWarnings(['PHP']); - } + // Do nothing. } /** @@ -275,45 +273,4 @@ protected function refreshVariables() { } } - /** - * Continues installation when an expected warning is found. - * - * @param string[] $expected_warnings - * A list of warning summaries to expect on the requirements screen (e.g. - * 'PHP', 'PHP OPcode caching', etc.). If only the expected warnings - * are found, the test will click the "continue anyway" link to go to the - * next screen of the installer. If an expected warning is not found, or if - * a warning not in the list is present, a fail is raised. - */ - protected function continueOnExpectedWarnings($expected_warnings = []) { - // Don't try to continue if there are errors. - if (strpos($this->getTextContent(), 'Errors found') !== FALSE) { - return; - } - // Allow only details elements that are directly after the warning header - // or each other. There is no guaranteed wrapper we can rely on across - // distributions. When there are multiple warnings, the selectors will be: - // - h3#warning+details summary - // - h3#warning+details+details summary - // - etc. - // We add one more selector than expected warnings to confirm that there - // isn't any other warning before clicking the link. - // @todo Make this more reliable in - // https://www.drupal.org/project/drupal/issues/2927345. - $selectors = []; - for ($i = 0; $i <= count($expected_warnings); $i++) { - $selectors[] = 'h3#warning' . implode('', array_fill(0, $i + 1, '+details')) . ' summary'; - } - $warning_elements = $this->cssSelect(implode(', ', $selectors)); - - // Confirm that there are only the expected warnings. - $warnings = []; - foreach ($warning_elements as $warning) { - $warnings[] = trim($warning->getText()); - } - $this->assertEquals($expected_warnings, $warnings); - $this->clickLink('continue anyway'); - $this->checkForMetaRefresh(); - } - } diff --git a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php index a127ab4..af27c7d 100644 --- a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php @@ -10,6 +10,7 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Language\Language; use Drupal\Core\Url; +use Drupal\Tests\RequirementsPageTrait; use Drupal\user\Entity\User; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; @@ -42,6 +43,7 @@ abstract class UpdatePathTestBase extends BrowserTestBase { use SchemaCheckTestTrait; + use RequirementsPageTrait; /** * Modules to enable after the database is loaded. @@ -295,6 +297,7 @@ protected function runUpdates() { ]); $this->drupalGet($this->updateUrl); + $this->updateRequirementsProblem(); $this->clickLink(t('Continue')); $this->doSelectionTest(); diff --git a/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php b/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php index 5622aa2..fe2788b 100644 --- a/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php +++ b/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php @@ -58,6 +58,7 @@ public function setUp() { } // Get a lock and a valid site path. $this->testDb = new TestDatabase(); + include $this->root . '/core/includes/bootstrap.inc'; } /** @@ -83,6 +84,10 @@ public function tearDown() { * Tests the quick-start command. */ public function testQuickStartCommand() { + if (version_compare(phpversion(), DRUPAL_MINIMUM_INSTALL_PHP) < 0) { + $this->markTestSkipped(); + } + // Install a site using the standard profile to ensure the one time login // link generation works. @@ -117,7 +122,6 @@ public function testQuickStartCommand() { $this->assertContains("127.0.0.1:$port/user/reset/1/", $process->getOutput()); // Generate a cookie so we can make a request against the installed site. - include $this->root . '/core/includes/bootstrap.inc'; define('DRUPAL_TEST_IN_CHILD_SITE', FALSE); chmod($this->testDb->getTestSitePath(), 0755); $cookieJar = CookieJar::fromArray([ @@ -133,9 +137,47 @@ public function testQuickStartCommand() { } /** + * Tests that the installer throws a requirement error on older PHP versions. + */ + public function testPhpRequirement() { + if (version_compare(phpversion(), DRUPAL_MINIMUM_INSTALL_PHP) >= 0) { + $this->markTestSkipped(); + } + + $install_command = [ + $this->php, + 'core/scripts/drupal', + 'quick-start', + 'standard', + "--site-name='Test site {$this->testDb->getDatabasePrefix()}'", + '--suppress-login', + ]; + $process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]); + $process->inheritEnvironmentVariables(); + $process->setTimeout(500); + $process->start(); + while ($process->isRunning()) { + // Wait for more output. + sleep(1); + } + + $error_output = $process->getErrorOutput(); + $this->assertContains('Your PHP installation is too old.', $error_output); + $this->assertContains('Drupal requires at least PHP', $error_output); + $this->assertContains(DRUPAL_MINIMUM_INSTALL_PHP, $error_output); + + // Stop the web server. + $process->stop(); + } + + /** * Tests the quick-start commands. */ public function testQuickStartInstallAndServerCommands() { + if (version_compare(phpversion(), DRUPAL_MINIMUM_INSTALL_PHP) < 0) { + $this->markTestSkipped(); + } + // Install a site. $install_command = [ $this->php, @@ -180,7 +222,6 @@ public function testQuickStartInstallAndServerCommands() { sleep(2); // Generate a cookie so we can make a request against the installed site. - include $this->root . '/core/includes/bootstrap.inc'; define('DRUPAL_TEST_IN_CHILD_SITE', FALSE); chmod($this->testDb->getTestSitePath(), 0755); $cookieJar = CookieJar::fromArray([ diff --git a/core/tests/Drupal/Tests/RequirementsPageTrait.php b/core/tests/Drupal/Tests/RequirementsPageTrait.php new file mode 100644 index 0000000..82e87ca --- /dev/null +++ b/core/tests/Drupal/Tests/RequirementsPageTrait.php @@ -0,0 +1,75 @@ +assertNoText('Errors found'); + $this->assertWarningSummaries(['PHP']); + $this->clickLink('try again'); + $this->checkForMetaRefresh(); + } + } + + /** + * Continues installation when the expected warnings are found. + * + * @param string[] $expected_warnings + * A list of warning summaries to expect on the requirements screen (e.g. + * 'PHP', 'PHP OPcode caching', etc.). If only the expected warnings + * are found, the test will click the "continue anyway" link to go to the + * next screen of the installer. If an expected warning is not found, or if + * a warning not in the list is present, a fail is raised. + */ + protected function continueOnExpectedWarnings($expected_warnings = []) { + $this->assertNoText('Errors found'); + $this->assertWarningSummaries($expected_warnings); + $this->clickLink('continue anyway'); + $this->checkForMetaRefresh(); + } + + /** + * Assert the given warning summaries are present on the page. + * + * If an expected warning is not found, or if a warning not in the list is + * present, a fail is raised. + * + * @param string[] $warning_summaries + * A list of warning summaries to expect on the requirements screen (e.g. + * 'PHP', 'PHP OPcode caching', etc.). + */ + protected function assertWarningSummaries(array $warning_summaries) { + // Allow only details elements that are directly after the warning header + // or each other. There is no guaranteed wrapper we can rely on across + // distributions. When there are multiple warnings, the selectors will be: + // - h3#warning+details summary + // - h3#warning+details+details summary + // - etc. + // We add one more selector than expected warnings to confirm that there + // isn't any other warning before clicking the link. + // @todo Make this more reliable in + // https://www.drupal.org/project/drupal/issues/2927345. + $selectors = []; + for ($i = 0; $i <= count($warning_summaries); $i++) { + $selectors[] = 'h3#warning' . implode('', array_fill(0, $i + 1, '+details')) . ' summary'; + } + $warning_elements = $this->cssSelect(implode(', ', $selectors)); + + // Confirm that there are only the expected warnings. + $warnings = []; + foreach ($warning_elements as $warning) { + $warnings[] = trim($warning->getText()); + } + $this->assertEquals($warning_summaries, $warnings); + } + +}