Commit 43cb1b5c authored by catch's avatar catch

Issue #3053363 by alexpott, Wim Leers, Berdir, mondrake, xjm: Remove support...

Issue #3053363 by alexpott, Wim Leers, Berdir, mondrake, xjm: Remove support for PHP 5 in Drupal 8.8
parent e46168f2
......@@ -2,11 +2,8 @@
SQLITE REQUIREMENTS
-------------------
To use SQLite with your Drupal installation, the following requirements must be
met: Server has PHP 5.3.10 or later with PDO, and the PDO SQLite driver must be
enabled.
If you have not pdo_sqlite available depending on your system there are different ways to install it.
PHP's PDO SQLite driver must be enabled. If you do not have pdo_sqlite
available, depending on your system there are different ways to install it.
Windows
-------
......
......@@ -15,7 +15,7 @@ QUICKSTART
----------------------
Prerequisites:
- PHP 5.5.9 (or greater) (https://php.net).
- PHP 7.0.8 (or greater) (https://php.net).
In the instructions below, replace the version x.y.z with the specific version
you wish to download. Example: 8.6.0.zip. You can find the latest stable version
......@@ -48,8 +48,8 @@ Drupal requires:
- A web server with PHP support, for example:
- Apache 2.0 (or greater) (http://httpd.apache.org/).
- Nginx 1.1 (or greater) (http://nginx.com/).
- PHP 5.5.9 (or greater) (http://php.net/). For better security support it is
recommended to update to at least 5.5.21 or 5.6.5.
- PHP 7.0.8 (or greater) (http://php.net/). For better security support it is
recommended to update to at least 7.2.17.
- One of the following databases:
- MySQL 5.5.3 (or greater) (http://www.mysql.com/).
- MariaDB 5.5.20 (or greater) (https://mariadb.org/). MariaDB is a fully
......@@ -93,10 +93,6 @@ OPTIONAL SERVER REQUIREMENTS
configuration allows the web server to initiate outbound connections. Most web
hosting setups allow this.
- PHP 5.5.21 provides features for improved security when used with MySQL. While
this is not required, it is highly encouraged to use PHP 5.5.21 or 5.6.5 and
above.
INSTALLATION
------------
......
......@@ -17,7 +17,7 @@
"ext-SPL": "*",
"ext-tokenizer": "*",
"ext-xml": "*",
"php": "^5.5.9|>=7.0.8",
"php": ">=7.0.8",
"symfony/class-loader": "~3.4.0",
"symfony/console": "~3.4.0",
"symfony/dependency-injection": "~3.4.26",
......
......@@ -32,7 +32,7 @@
* @todo Move this to an appropriate autoloadable class. See
* https://www.drupal.org/project/drupal/issues/2908079
*/
const DRUPAL_MINIMUM_PHP = '5.5.9';
const DRUPAL_MINIMUM_PHP = '7.0.8';
/**
* Minimum supported version of PHP.
......@@ -604,15 +604,10 @@ function _drupal_exception_handler($exception) {
// Log the message to the watchdog and return an error page to the user.
_drupal_log_error(Error::decodeException($exception), TRUE);
}
// PHP 7 introduces Throwable, which covers both Error and
// Exception throwables.
// Catch \Throwable, which covers both Error and Exception throwables.
catch (\Throwable $error) {
_drupal_exception_handler_additional($exception, $error);
}
// In order to be compatible with PHP 5 we also catch regular Exceptions.
catch (\Exception $exception2) {
_drupal_exception_handler_additional($exception, $exception2);
}
}
/**
......@@ -1057,15 +1052,10 @@ function _drupal_shutdown_function() {
next($callbacks);
}
}
// PHP 7 introduces Throwable, which covers both Error and
// Exception throwables.
// Catch \Throwable, which covers both Error and Exception throwables.
catch (\Throwable $error) {
_drupal_shutdown_function_handle_exception($error);
}
// In order to be compatible with PHP 5 we also catch regular Exceptions.
catch (\Exception $exception) {
_drupal_shutdown_function_handle_exception($exception);
}
}
/**
......
......@@ -25,8 +25,8 @@
// The minimum version is specified explicitly, as DRUPAL_MINIMUM_PHP is not
// yet available. It is defined in bootstrap.inc, but it is not possible to
// load that file yet as it would cause a fatal error on older versions of PHP.
if (version_compare(PHP_VERSION, '5.5.9') < 0) {
print 'Your PHP installation is too old. Drupal requires at least PHP 5.5.9. See the <a href="https://www.drupal.org/requirements">system requirements</a> page for more information.';
if (version_compare(PHP_VERSION, '7.0.8') < 0) {
print 'Your PHP installation is too old. Drupal requires at least PHP 7.0.8. See the <a href="https://www.drupal.org/requirements">system requirements</a> page for more information.';
exit;
}
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"doctrine/common": "^2.5",
"doctrine/annotations": "1.2.*",
"drupal/core-file-cache": "^8.2",
......
......@@ -5,37 +5,21 @@
/**
* Handler for runtime assertion failures.
*
* This class allows PHP 5.x to throw exceptions on runtime assertion fails
* in the same manner as PHP 7, and sets the ASSERT_EXCEPTION flag to TRUE
* for the PHP 7 runtime.
*
* @ingroup php_assert
*
* @todo Deprecate this class. https://www.drupal.org/node/3054072
*/
class Handle {
/**
* Registers uniform assertion handling.
* Ensures exceptions are thrown when an assertion fails.
*/
public static function register() {
// Since we're using exceptions, turn error warnings off.
assert_options(ASSERT_WARNING, FALSE);
if (version_compare(PHP_VERSION, '7.0.0-dev') < 0) {
if (!class_exists('AssertionError', FALSE)) {
require __DIR__ . '/global_namespace_php5.php';
}
// PHP 5 - create a handler to throw the exception directly.
assert_options(ASSERT_CALLBACK, function ($file = '', $line = 0, $code = '', $message = '') {
if (empty($message)) {
$message = $code;
}
throw new \AssertionError($message, 0, NULL, $file, $line);
});
}
else {
// PHP 7 - just turn exception throwing on.
assert_options(ASSERT_EXCEPTION, TRUE);
}
// Turn exception throwing on.
assert_options(ASSERT_EXCEPTION, TRUE);
}
}
{
"name": "drupal/core-assertion",
"description": "Provides runtime assertions similar to those in PHP 7, under PHP 5.",
"description": "Provides helper functionality for runtime assertions.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
"php": ">=7.0.8"
},
"autoload": {
"psr-4": {
......
<?php
/**
* @file
* Contains PHP5 version of the \AssertionError class.
*/
/**
* Emulates PHP 7 AssertionError as closely as possible.
*
* This class is declared in the global namespace. It will only be included by
* \Drupal\Component\Assertion\Handle for PHP5 since this class exists natively
* in PHP 7. Note that in PHP 7 it extends from Error, not Exception, but that
* isn't possible for PHP 5 - all exceptions must extend from exception.
*/
class AssertionError extends Exception {
/**
* {@inheritdoc}
*/
public function __construct($message = '', $code = 0, Exception $previous = NULL, $file = '', $line = 0) {
parent::__construct($message, $code, $previous);
// Preserve the filename and line number of the assertion failure.
$this->file = $file;
$this->line = $line;
}
}
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"zendframework/zend-feed": "^2.4"
},
"autoload": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"doctrine/common": "^2.5"
},
"autoload": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"drupal/core-utility": "^8.2"
},
"autoload": {
......
......@@ -11,7 +11,7 @@
"source": "https://www.drupal.org/project/drupal/git-instructions"
},
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"symfony/dependency-injection": ">=2.8 <4.0.0"
},
"suggest": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"symfony/polyfill-mbstring": "~1.0"
},
"autoload": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"drupal/core-file-cache": "^8.2",
"drupal/core-serialization": "^8.2"
},
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"symfony/dependency-injection": ">=2.8 <4.0.0",
"symfony/event-dispatcher": ">=2.7 <4.0.0"
},
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
"php": ">=7.0.8"
},
"autoload": {
"psr-4": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
"php": ">=7.0.8"
},
"autoload": {
"psr-4": {
......
......@@ -9,7 +9,7 @@
"source": "https://www.drupal.org/project/drupal/git-instructions"
},
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"drupal/core-utility": "^8.2"
},
"autoload": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
"php": ">=7.0.8"
},
"autoload": {
"psr-4": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"symfony/http-foundation": ">=2.7 <4.0.0"
},
"autoload": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
"php": ">=7.0.8"
},
"autoload": {
"psr-4": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"symfony/validator": ">=2.7 <4.0.0"
},
"autoload": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
"php": ">=7.0.8"
},
"autoload": {
"psr-4": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"drupal/core-utility": "^8.2"
},
"autoload": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"symfony/yaml": ">=2.7 <4.0.0"
},
"autoload": {
......
......@@ -27,45 +27,12 @@ class Crypt {
*
* @return string
* A randomly generated string.
*
* @todo Deprecate in favor of random_bytes().
* https://www.drupal.org/node/3054311
*/
public static function randomBytes($count) {
try {
return random_bytes($count);
}
catch (\Exception $e) {
// $random_state does not use drupal_static as it stores random bytes.
static $random_state, $bytes;
// If the compatibility library fails, this simple hash-based PRNG will
// generate a good set of pseudo-random bytes on any system.
// Note that it may be important that our $random_state is passed
// through hash() prior to being rolled into $output, that the two hash()
// invocations are different, and that the extra input into the first one
// - the microtime() - is prepended rather than appended. This is to avoid
// directly leaking $random_state via the $output stream, which could
// allow for trivial prediction of further "random" numbers.
if (strlen($bytes) < $count) {
// Initialize on the first call. The $_SERVER variable includes user and
// system-specific information that varies a little with each page.
if (!isset($random_state)) {
$random_state = print_r($_SERVER, TRUE);
if (function_exists('getmypid')) {
// Further initialize with the somewhat random PHP process ID.
$random_state .= getmypid();
}
$bytes = '';
// Ensure mt_rand() is reseeded before calling it the first time.
mt_srand();
}
do {
$random_state = hash('sha256', microtime() . mt_rand() . $random_state);
$bytes .= hash('sha256', mt_rand() . $random_state, TRUE);
} while (strlen($bytes) < $count);
}
$output = substr($bytes, 0, $count);
$bytes = substr($bytes, $count);
return $output;
}
return random_bytes($count);
}
/**
......@@ -120,37 +87,12 @@ public static function hashBase64($data) {
*
* @return bool
* Returns TRUE when the two strings are equal, FALSE otherwise.
*
* @todo Deprecate in favor of hash_equals().
* https://www.drupal.org/node/3053956
*/
public static function hashEquals($known_string, $user_string) {
if (function_exists('hash_equals')) {
return hash_equals($known_string, $user_string);
}
else {
// Backport of hash_equals() function from PHP 5.6
// @see https://github.com/php/php-src/blob/PHP-5.6/ext/hash/hash.c#L739
if (!is_string($known_string)) {
trigger_error(sprintf("Expected known_string to be a string, %s given", gettype($known_string)), E_USER_WARNING);
return FALSE;
}
if (!is_string($user_string)) {
trigger_error(sprintf("Expected user_string to be a string, %s given", gettype($user_string)), E_USER_WARNING);
return FALSE;
}
$known_len = strlen($known_string);
if ($known_len !== strlen($user_string)) {
return FALSE;
}
// This is security sensitive code. Do not optimize this for speed.
$result = 0;
for ($i = 0; $i < $known_len; $i++) {
$result |= (ord($known_string[$i]) ^ ord($user_string[$i]));
}
return $result === 0;
}
return hash_equals($known_string, $user_string);
}
/**
......
......@@ -162,16 +162,6 @@ public static function check() {
if (ini_get('mbstring.encoding_translation') != 0) {
return 'mbstring.encoding_translation';
}
// mbstring.http_input and mbstring.http_output are deprecated and empty by
// default in PHP 5.6.
if (version_compare(PHP_VERSION, '5.6.0') == -1) {
if (ini_get('mbstring.http_input') != 'pass') {
return 'mbstring.http_input';
}
if (ini_get('mbstring.http_output') != 'pass') {
return 'mbstring.http_output';
}
}
return '';
}
......
......@@ -27,7 +27,7 @@ class UrlHelper {
* not valid as a "URL" in HTML5.
*
* @todo Remove this function once PHP 5.4 is required as we can use just
* http_build_query() directly.
* http_build_query() directly. https://www.drupal.org/node/2322059
*
* @param array $query
* The query parameter array to be processed; for instance,
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"paragonie/random_compat": "^1.0|^2.0",
"drupal/core-render": "^8.2",
"symfony/polyfill-iconv": "~1.0",
......
......@@ -9,7 +9,7 @@
"source": "https://www.drupal.org/project/drupal/git-instructions"
},
"require": {
"php": ">=5.5.9",
"php": ">=7.0.8",
"drupal/core-utility": "^8.2"
},
"autoload": {
......
......@@ -5,7 +5,7 @@
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
"php": ">=7.0.8"
},
"autoload": {
"psr-4": {
......
......@@ -12,7 +12,7 @@
/**
* Common base class for form interstitial controllers.
*
* @todo Make this a trait in PHP 5.4.
* @todo Make this a trait in PHP 5.4. https://www.drupal.org/node/3054053
*/
abstract class FormController {
use DependencySerializationTrait;
......
......@@ -409,12 +409,9 @@ public static function open(array &$connection_options = []) {
\PDO::MYSQL_ATTR_FOUND_ROWS => TRUE,
// Because MySQL's prepared statements skip the query cache, because it's dumb.
\PDO::ATTR_EMULATE_PREPARES => TRUE,
// Limit SQL to a single statement like mysqli.
\PDO::MYSQL_ATTR_MULTI_STATEMENTS => FALSE,
];
if (defined('\PDO::MYSQL_ATTR_MULTI_STATEMENTS')) {
// An added connection option in PHP 5.5.21 to optionally limit SQL to a
// single statement like mysqli.
$connection_options['pdo'] += [\PDO::MYSQL_ATTR_MULTI_STATEMENTS => FALSE];
}
try {
$pdo = new \PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
......
......@@ -907,16 +907,6 @@ protected function initializeContainer() {
// If there is no container and no cached container definition, build a new
// one from scratch.
if (!isset($container) && !isset($container_definition)) {
// Building the container creates 1000s of objects. Garbage collection of
// these objects is expensive. This appears to be causing random
// segmentation faults in PHP 5.6 due to
// https://bugs.php.net/bug.php?id=72286. Once the container is rebuilt,
// garbage collection is re-enabled.
$disable_gc = version_compare(PHP_VERSION, '7', '<') && gc_enabled();
if ($disable_gc) {
gc_collect_cycles();
gc_disable();
}
$container = $this->compileContainer();
// Only dump the container if dumping is allowed. This is useful for
......@@ -926,11 +916,6 @@ protected function initializeContainer() {
$dumper = new $this->phpArrayDumperClass($container);
$container_definition = $dumper->getArray();
}
// If garbage collection was disabled prior to rebuilding container,
// re-enable it.
if ($disable_gc) {
gc_enable();
}
}
// The container was rebuilt successfully.
......@@ -1043,8 +1028,6 @@ public static function bootEnvironment($app_root = NULL) {
// Web tests are to be conducted with runtime assertions active.
assert_options(ASSERT_ACTIVE, TRUE);
// Now synchronize PHP 5 and 7's handling of assertions as much as
// possible.
Handle::register();
// Log fatal errors to the test site directory.
......
......@@ -27,6 +27,7 @@
*
* @todo Use RecursiveCallbackFilterIterator instead of the $acceptTests
* parameter forwarding once PHP 5.4 is available.
* https://www.drupal.org/node/2532228
*/
class RecursiveExtensionFilterIterator extends \RecursiveFilterIterator {
......
......@@ -310,7 +310,7 @@ public function invokeAllDeprecated($description, $hook, array $args = []);
* $this->alter('mymodule_data', $alterable1, $alterable2, $context);
* @endcode
*
* Note that objects are always passed by reference in PHP5. If it is absolutely
* Note that objects are always passed by reference. If it is absolutely
* required that no implementation alters a passed object in $context, then an
* object needs to be cloned:
* @code
......
......@@ -440,7 +440,7 @@ public function setDefaultValueCallback($callback) {
*
* Using the Serialize interface and serialize() / unserialize() methods
* breaks entity forms in PHP 5.4.
* @todo Investigate in https://www.drupal.org/node/2074253.
* @todo Investigate in https://www.drupal.org/node/1977206.
*/
public function __sleep() {
// Only serialize necessary properties, excluding those that can be
......
......@@ -64,12 +64,7 @@ public function setValue($values, $notify = TRUE) {
$values = $values->getValue();
}
else {
if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
$values = unserialize($values, ['allowed_classes' => FALSE]);
}
else {
$values = unserialize($values);
}
$values = unserialize($values, ['allowed_classes' => FALSE]);
}
}
......
......@@ -182,7 +182,6 @@ protected function crypt($algo, $password, $setting) {
// Convert the base 2 logarithm into an integer.
$count = 1 << $count_log2;
// We rely on the hash() function being available in PHP 5.2+.
$hash = hash($algo, $salt . $password, TRUE);
do {
$hash = hash($algo, $hash . $password, TRUE);
......
......@@ -87,9 +87,9 @@ public function setActiveTheme(ActiveTheme $active_theme);
* $this->alter('mymodule_data', $alterable1, $alterable2, $context);
* @endcode
*
* Note that objects are always passed by reference in PHP5. If it is
* absolutely required that no implementation alters a passed object in
* $context, then an object needs to be cloned:
* Note that objects are always passed by reference. If it is absolutely
* required that no implementation alters a passed object in $context, then an
* object needs to be cloned:
* @code
* $context = array(
* 'unalterable_object' => clone $object,
......
......@@ -3,6 +3,7 @@
namespace Drupal\Core\TypedData;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
......@@ -14,7 +15,7 @@
* @ingroup typed_data
*/
abstract class TypedData implements TypedDataInterface, PluginInspectionInterface {
use DependencySerializationTrait;
use StringTranslationTrait;
use TypedDataTrait;
......@@ -191,22 +192,4 @@ public function getParent() {
return $this->parent;
}
/**
* {@inheritdoc}
*/
public function __sleep() {
$vars = get_object_vars($this);
// Prevent services from being serialized. static::getStringTranslation()
// and static::getTypedDataManager() lazy-load them after $this has been
// unserialized.
// @todo Replace this with
// \Drupal\Core\DependencyInjection\DependencySerializationTrait before
// Drupal 9.0.0. We cannot use that now, because child classes already use
// it and PHP 5 would consider that conflicts.
unset($vars['stringTranslation']);
unset($vars['typedDataManager']);
return array_keys($vars);
}
}
......@@ -715,7 +715,7 @@ public function hasData() {
*
* Using the Serialize interface and serialize() / unserialize() methods
* breaks entity forms in PHP 5.4.
* @todo Investigate in https://www.drupal.org/node/2074253.
* @todo Investigate in https://www.drupal.org/node/1977206.
*/
public function __sleep() {
// Only serialize necessary properties, excluding those that can be
......
......@@ -18,6 +18,7 @@ class FieldLayoutEntityFormDisplay extends EntityFormDisplay implements EntityDi
public function getDefaultRegion() {
// This cannot be provided by the trait due to