Commit 9f26cfb2 authored by effulgentsia's avatar effulgentsia

Issue #2670966 by xjm, Crell, claudiu.cristea, alexpott, timmillwood,...

Issue #2670966 by xjm, Crell, claudiu.cristea, alexpott, timmillwood, rakesh.gectcr, catch, dawehner, David_Rothstein, hchonov, martin107, tstoeckler, andypost, cilefen, RobLoach, Fabianx, salvis, hussainweb, JeroenT, larowlan, pfrenssen, daffie, webchick, wturrell: Warn users of old PHP versions
parent c9678f59
...@@ -19,9 +19,20 @@ ...@@ -19,9 +19,20 @@
/** /**
* Minimum supported version of PHP. * Minimum supported version of PHP.
*
* Drupal cannot be installed on versions of PHP older than this version.
*/ */
const DRUPAL_MINIMUM_PHP = '5.5.9'; const DRUPAL_MINIMUM_PHP = '5.5.9';
/**
* Minimum recommended version of PHP.
*
* Sites installing Drupal on PHP versions lower than this will see a warning
* message, but Drupal can still be installed. Used for (e.g.) PHP versions
* that have reached their EOL or will in the near future.
*/
const DRUPAL_RECOMMENDED_PHP = '7.1';
/** /**
* Minimum recommended value of PHP memory_limit. * Minimum recommended value of PHP memory_limit.
* *
......
...@@ -122,6 +122,9 @@ protected function setUp() { ...@@ -122,6 +122,9 @@ protected function setUp() {
// Select profile. // Select profile.
$this->setUpProfile(); $this->setUpProfile();
// Address the requirements problem screen, if any.
$this->setUpRequirementsProblem();
// Configure settings. // Configure settings.
$this->setUpSettings(); $this->setUpSettings();
...@@ -195,6 +198,23 @@ protected function setUpSettings() { ...@@ -195,6 +198,23 @@ protected function setUpSettings() {
$this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']); $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
} }
/**
* Installer step: Requirements problem.
*
* Override this method to test specific requirements warnings or errors
* during the installer.
*
* @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(), DRUPAL_RECOMMENDED_PHP) < 0) {
$this->continueOnExpectedWarnings(['PHP']);
}
}
/** /**
* Final installer step: Configure site. * Final installer step: Configure site.
*/ */
...@@ -218,4 +238,44 @@ protected function refreshVariables() { ...@@ -218,4 +238,44 @@ 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');
}
} }
...@@ -64,6 +64,27 @@ protected function visitInstaller() { ...@@ -64,6 +64,27 @@ protected function visitInstaller() {
// The unrouted URL assembler does not exist at this point, so we build the // The unrouted URL assembler does not exist at this point, so we build the
// URL ourselves. // URL ourselves.
$this->drupalGet($GLOBALS['base_url'] . '/core/install.php' . '?langcode=fr'); $this->drupalGet($GLOBALS['base_url'] . '/core/install.php' . '?langcode=fr');
}
/**
* {@inheritdoc}
*/
protected function setUpLanguage() {
// This step is skipped, because the distribution profile uses a fixed
// language.
}
/**
* {@inheritdoc}
*/
protected function setUpProfile() {
// This step is skipped, because there is a distribution profile.
}
/**
* {@inheritdoc}
*/
protected function setUpSettings() {
// The language should have been automatically detected, all following // The language should have been automatically detected, all following
// screens should be translated already. // screens should be translated already.
$elements = $this->xpath('//input[@type="submit"]/@value'); $elements = $this->xpath('//input[@type="submit"]/@value');
...@@ -80,21 +101,8 @@ protected function visitInstaller() { ...@@ -80,21 +101,8 @@ protected function visitInstaller() {
$this->assertRaw($this->info['distribution']['install']['theme']); $this->assertRaw($this->info['distribution']['install']['theme']);
// Verify that the "Choose profile" step does not appear. // Verify that the "Choose profile" step does not appear.
$this->assertNoText('profile'); $this->assertNoText('profile');
}
/** parent::setUpSettings();
* {@inheritdoc}
*/
protected function setUpLanguage() {
// This step is skipped, because the distribution profile uses a fixed
// language.
}
/**
* {@inheritdoc}
*/
protected function setUpProfile() {
// This step is skipped, because there is a distribution profile.
} }
/** /**
......
...@@ -59,7 +59,27 @@ protected function visitInstaller() { ...@@ -59,7 +59,27 @@ protected function visitInstaller() {
file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de'));
parent::visitInstaller(); parent::visitInstaller();
}
/**
* {@inheritdoc}
*/
protected function setUpLanguage() {
// This step is skipped, because the distribution profile uses a fixed
// language.
}
/**
* {@inheritdoc}
*/
protected function setUpProfile() {
// This step is skipped, because there is a distribution profile.
}
/**
* {@inheritdoc}
*/
protected function setUpSettings() {
// The language should have been automatically detected, all following // The language should have been automatically detected, all following
// screens should be translated already. // screens should be translated already.
$elements = $this->xpath('//input[@type="submit"]/@value'); $elements = $this->xpath('//input[@type="submit"]/@value');
...@@ -76,22 +96,10 @@ protected function visitInstaller() { ...@@ -76,22 +96,10 @@ protected function visitInstaller() {
$this->assertRaw($this->info['distribution']['install']['theme']); $this->assertRaw($this->info['distribution']['install']['theme']);
// Verify that the "Choose profile" step does not appear. // Verify that the "Choose profile" step does not appear.
$this->assertNoText('profile'); $this->assertNoText('profile');
}
/** parent::setUpSettings();
* {@inheritdoc}
*/
protected function setUpLanguage() {
// This step is skipped, because the distribution profile uses a fixed
// language.
} }
/**
* {@inheritdoc}
*/
protected function setUpProfile() {
// This step is skipped, because there is a distribution profile.
}
/** /**
* Confirms that the installation succeeded. * Confirms that the installation succeeded.
......
...@@ -32,6 +32,7 @@ public function testInstaller() { ...@@ -32,6 +32,7 @@ public function testInstaller() {
$this->visitInstaller(); $this->visitInstaller();
$this->setUpLanguage(); $this->setUpLanguage();
$this->setUpProfile(); $this->setUpProfile();
$this->setUpRequirementsProblem();
$this->setUpSettings(); $this->setUpSettings();
$this->assertRaw('Drupal already installed'); $this->assertRaw('Drupal already installed');
} }
......
...@@ -157,7 +157,11 @@ function system_requirements($phase) { ...@@ -157,7 +157,11 @@ function system_requirements($phase) {
} }
} }
// Test PHP version and show link to phpinfo() if it's available // Verify the user is running a supported PHP version.
// If the site is running a recommended version of PHP, just display it
// as an informational message on the status report. This will be overridden
// with an error or warning if the site is running older PHP versions for
// which Drupal has already or will soon drop support.
$phpversion = $phpversion_label = phpversion(); $phpversion = $phpversion_label = phpversion();
if (function_exists('phpinfo')) { if (function_exists('phpinfo')) {
if ($phase === 'runtime') { if ($phase === 'runtime') {
...@@ -169,6 +173,8 @@ function system_requirements($phase) { ...@@ -169,6 +173,8 @@ function system_requirements($phase) {
]; ];
} }
else { else {
// @todo Revisit whether this description makes sense in
// https://www.drupal.org/project/drupal/issues/2927318.
$requirements['php'] = [ $requirements['php'] = [
'title' => t('PHP'), 'title' => t('PHP'),
'value' => $phpversion_label, 'value' => $phpversion_label,
...@@ -183,11 +189,18 @@ function system_requirements($phase) { ...@@ -183,11 +189,18 @@ function system_requirements($phase) {
// If PHP is old, it's not safe to continue with the requirements check. // If PHP is old, it's not safe to continue with the requirements check.
return $requirements; return $requirements;
} }
// @todo Warn about specific end dates for our PHP 5.5, 5.6, and 7.0 support
// once each is set.
// @see https://www.drupal.org/project/drupal/issues/2927344
if ((version_compare($phpversion, DRUPAL_RECOMMENDED_PHP) < 0) && ($phase === 'install' || $phase === 'runtime')) {
$requirements['php']['description'] = t('Your PHP installation is running version %version. Support for this version will be dropped in a future Drupal release. Upgrade to PHP version %recommended or higher to ensure your site continues to receive Drupal updates and remains secure. See <a href="http://php.net/supported-versions.php">PHP\'s version support documentation</a> and the <a href=":php_requirements">Drupal 8 PHP requirements handbook page</a> for more information.', ['%version' => $phpversion, '%recommended' => DRUPAL_RECOMMENDED_PHP, ':php_requirements' => 'https://www.drupal.org/docs/8/system-requirements/php']);
$requirements['php']['severity'] = REQUIREMENT_WARNING;
}
// Suggest to update to at least 5.5.21 or 5.6.5 for disabling multiple // Suggest to update to at least 5.5.21 or 5.6.5 for disabling multiple
// statements. // statements.
if (($phase === 'install' || \Drupal::database()->driver() === 'mysql') && !SystemRequirements::phpVersionWithPdoDisallowMultipleStatements($phpversion)) { if (($phase === 'install' || \Drupal::database()->driver() === 'mysql') && !SystemRequirements::phpVersionWithPdoDisallowMultipleStatements($phpversion)) {
$requirements['php'] = [ $requirements['php_multiple_statement'] = [
'title' => t('PHP (multiple statement disabling)'), 'title' => t('PHP (multiple statement disabling)'),
'value' => $phpversion_label, 'value' => $phpversion_label,
'description' => t('PHP versions higher than 5.6.5 or 5.5.21 provide built-in SQL injection protection for mysql databases. It is recommended to update.'), 'description' => t('PHP versions higher than 5.6.5 or 5.5.21 provide built-in SQL injection protection for mysql databases. It is recommended to update.'),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment