Commit 2e5593b5 authored by heddn's avatar heddn Committed by heddn
Browse files

Issue #3063127 by heddn, tatarbj: Backport SupportedPhpVersion,...

Issue #3063127 by heddn, tatarbj: Backport SupportedPhpVersion, BlacklistPhp72Versions and MinimumPhpVersion
parent eadede3d
<?php
/**
* A value object representing a Drupal version constraint.
*/
class Constraint {
/**
* The constraint represented as a string. For example '>=7.x-5.x'.
*
* @var string
*/
protected $constraint;
/**
* A list of associative arrays representing the constraint.
*
* Each containing the keys:
* - 'op': can be one of: '=', '==', '!=', '<>', '<', '<=', '>', or '>='.
* - 'version': A complete version, e.g. '4.5-beta3'.
*
* @var array[]
*/
protected $constraintArray = [];
/**
* Constraint constructor.
*
* @param string $constraint
* The constraint string to create the object from. For example, '>7.x-1.1'.
* @param string $core_compatibility
* Core compatibility declared for the current version of Drupal core.
* Normally this is set to DRUPAL_CORE_COMPATIBILITY by the caller.
*/
public function __construct($constraint, $core_compatibility) {
$this->constraint = $constraint;
$this->parseConstraint($constraint, $core_compatibility);
}
/**
* Gets the constraint as a string.
*
* Can be used in the UI for reporting incompatibilities.
*
* @return string
* The constraint as a string.
*/
public function __toString() {
return $this->constraint;
}
/**
* Determines if the provided version is satisfied by this constraint.
*
* @param string $version
* The version to check, for example '4.2'.
*
* @return bool
* TRUE if the provided version is satisfied by this constraint, FALSE if
* not.
*/
public function isCompatible($version) {
foreach ($this->constraintArray as $constraint) {
if (!version_compare($version, $constraint['version'], $constraint['op'])) {
return FALSE;
}
}
return TRUE;
}
/**
* Parses a constraint string.
*
* @param string $constraint_string
* The constraint string to parse.
* @param string $core_compatibility
* Core compatibility declared for the current version of Drupal core.
* Normally this is set to DRUPAL_CORE_COMPATIBILITY by the caller.
*/
private function parseConstraint($constraint_string, $core_compatibility) {
// We use named subpatterns and support every op that version_compare
// supports. Also, op is optional and defaults to equals.
$p_op = '(?<operation>!=|==|=|<|<=|>|>=|<>)?';
// Core version is always optional: 7.x-2.x and 2.x is treated the same.
$p_core = '(?:' . preg_quote($core_compatibility) . '-)?';
$p_major = '(?<major>\d+)';
// By setting the minor version to x, branches can be matched.
$p_minor = '(?<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
foreach (explode(',', $constraint_string) as $constraint) {
if (preg_match("/^\s*$p_op\s*$p_core$p_major\.$p_minor/", $constraint, $matches)) {
$op = !empty($matches['operation']) ? $matches['operation'] : '=';
if ($matches['minor'] == 'x') {
// Drupal considers "2.x" to mean any version that begins with
// "2" (e.g. 2.0, 2.9 are all "2.x"). PHP's version_compare(),
// on the other hand, treats "x" as a string; so to
// version_compare(), "2.x" is considered less than 2.0. This
// means that >=2.x and <2.x are handled by version_compare()
// as we need, but > and <= are not.
if ($op == '>' || $op == '<=') {
$matches['major']++;
}
// Equivalence can be checked by adding two restrictions.
if ($op == '=' || $op == '==') {
$this->constraintArray[] = ['op' => '<', 'version' => ($matches['major'] + 1) . '.x'];
$op = '>=';
}
}
$this->constraintArray[] = ['op' => $op, 'version' => $matches['major'] . '.' . $matches['minor']];
}
}
}
}
<?php
use Composer\Semver\VersionParser;
/**
* Blacklisted PHP 7.2 version checker.
*/
class BlacklistPhp72Versions implements ReadinessCheckerInterface {
/**
* {@inheritdoc}
*/
public static function run() {
$module_directory = drupal_get_path('module', 'automatic_updates');
include_once $module_directory . '/semver/src/Constraint/ConstraintInterface.php';
include_once $module_directory . '/semver/src/Constraint/Constraint.php';
include_once $module_directory . '/semver/src/Constraint/EmptyConstraint.php';
include_once $module_directory . '/semver/src/Constraint/MultiConstraint.php';
include_once $module_directory . '/semver/src/VersionParser.php';
$messages = [];
$parser = new VersionParser();
$unsupported_constraint = static::getUnsupportedVersionConstraint();
if ($unsupported_constraint->matches($parser->parseConstraints(static::getPhpVersion()))) {
$messages[] = static::getMessage();
}
return $messages;
}
/**
* Get the PHP version.
*
* @return string
* The current php version.
*/
protected static function getPhpVersion() {
return PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
}
/**
* {@inheritdoc}
*/
protected static function getUnsupportedVersionConstraint() {
$parser = new VersionParser();
// Rather than make things complicated with cli vs non-cli PHP and
// differences in their support of opcache, libsodium and Sodium_Compat,
// simply blacklist the entire version range to ensure the best possible
// and coherent update support.
return $parser->parseConstraints('>=7.2.0 <=7.2.2');
}
/**
* {@inheritdoc}
*/
protected static function getMessage() {
return t('PHP 7.2.0, 7.2.1 and 7.2.2 have issues with opcache that breaks signature validation. Please upgrade to a newer version of PHP to ensure assurance and security for package signing.');
}
}
......@@ -22,6 +22,7 @@ class ReadinessCheckerManager {
* The registered checkers.
*/
protected static function getCheckers() {
static::$checkers['warning'][0][] = 'BlacklistPhp72Versions';
static::$checkers['warning'][0][] = 'FileOwnership';
static::$checkers['warning'][0][] = 'MissingProjectInfo';
static::$checkers['warning'][0][] = 'ModifiedFiles';
......
......@@ -2,6 +2,7 @@ name= Automatic Updates
type = module
description = Drupal Automatic Updates
core = 7.x
php = 5.6
package = Security
files[] = tests/automatic_updates.test
......@@ -9,6 +10,7 @@ files[] = AutomaticUpdatesPsa.php
files[] = ModifiedFilesService.php
files[] = ReadinessCheckers/ReadinessCheckerManager.php
files[] = ReadinessCheckers/ReadinessCheckerInterface.php
files[] = ReadinessCheckers/BlacklistPhp72Versions.php
files[] = ReadinessCheckers/FileOwnership.php
files[] = ReadinessCheckers/MissingProjectInfo.php
files[] = ReadinessCheckers/ModifiedFiles.php
......
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