diff --git a/automatic_updates.services.yml b/automatic_updates.services.yml index 76c420edffe25b1275e44ffdfcbfa061c905a4f6..5dc14c723a642a084b80158b802883ecbd628a97 100644 --- a/automatic_updates.services.yml +++ b/automatic_updates.services.yml @@ -61,6 +61,14 @@ services: - '@automatic_updates.drupal_finder' tags: - { name: readiness_checker, category: warning} + automatic_updates.minimum_php_version: + class: Drupal\automatic_updates\ReadinessChecker\MinimumPhpVersion + tags: + - { name: readiness_checker, category: error} + automatic_updates.blacklist_php_72: + class: Drupal\automatic_updates\ReadinessChecker\BlacklistPhp72Versions + tags: + - { name: readiness_checker, category: warning} automatic_updates.pending_db_updates: class: Drupal\automatic_updates\ReadinessChecker\PendingDbUpdates tags: diff --git a/src/ReadinessChecker/BlacklistPhp72Versions.php b/src/ReadinessChecker/BlacklistPhp72Versions.php new file mode 100644 index 0000000000000000000000000000000000000000..e847310a26bb61873e91f0287906aed5245b2e0a --- /dev/null +++ b/src/ReadinessChecker/BlacklistPhp72Versions.php @@ -0,0 +1,33 @@ +<?php + +namespace Drupal\automatic_updates\ReadinessChecker; + +use Composer\Semver\VersionParser; +use Drupal\Core\StringTranslation\StringTranslationTrait; + +/** + * Blacklisted PHP 7.2 version checker. + */ +class BlacklistPhp72Versions extends SupportedPhpVersion { + use StringTranslationTrait; + + /** + * {@inheritdoc} + */ + protected 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 function getMessage() { + return $this->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.'); + } + +} diff --git a/src/ReadinessChecker/MinimumPhpVersion.php b/src/ReadinessChecker/MinimumPhpVersion.php new file mode 100644 index 0000000000000000000000000000000000000000..e9edc6fdf8ac3f32ce00d849e21f37e2d2d5903f --- /dev/null +++ b/src/ReadinessChecker/MinimumPhpVersion.php @@ -0,0 +1,29 @@ +<?php + +namespace Drupal\automatic_updates\ReadinessChecker; + +use Composer\Semver\VersionParser; +use Drupal\Core\StringTranslation\StringTranslationTrait; + +/** + * Minimum PHP version checker. + */ +class MinimumPhpVersion extends SupportedPhpVersion { + use StringTranslationTrait; + + /** + * {@inheritdoc} + */ + protected function getUnsupportedVersionConstraint() { + $parser = new VersionParser(); + return $parser->parseConstraints('<' . DRUPAL_MINIMUM_SUPPORTED_PHP); + } + + /** + * {@inheritdoc} + */ + protected function getMessage() { + return $this->t('This site is running on an unsupported version of PHP. It cannot be updated. Please update to at least PHP @version.', ['@version' => DRUPAL_MINIMUM_SUPPORTED_PHP]); + } + +} diff --git a/src/ReadinessChecker/SupportedPhpVersion.php b/src/ReadinessChecker/SupportedPhpVersion.php new file mode 100644 index 0000000000000000000000000000000000000000..a3ff7d190bc9c7f5e4c1e3a1984de0b5dbdfe832 --- /dev/null +++ b/src/ReadinessChecker/SupportedPhpVersion.php @@ -0,0 +1,51 @@ +<?php + +namespace Drupal\automatic_updates\ReadinessChecker; + +use Composer\Semver\VersionParser; + +/** + * Supported PHP version checker. + */ +abstract class SupportedPhpVersion implements ReadinessCheckerInterface { + + /** + * {@inheritdoc} + */ + public function run() { + $messages = []; + $parser = new VersionParser(); + $unsupported_constraint = $this->getUnsupportedVersionConstraint(); + if ($unsupported_constraint->matches($parser->parseConstraints($this->getPhpVersion()))) { + $messages[] = $this->getMessage(); + } + return $messages; + } + + /** + * Get the PHP version. + * + * @return string + * The current php version. + */ + protected function getPhpVersion() { + return PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION; + } + + /** + * Get the unsupported PHP version constraint. + * + * @return \Composer\Semver\Constraint\ConstraintInterface + * The version constraint. + */ + abstract protected function getUnsupportedVersionConstraint(); + + /** + * Get the message to return if the current PHP version is unsupported. + * + * @return \Drupal\Component\Render\MarkupInterface + * The message to return if the current PHP version is unsupported. + */ + abstract protected function getMessage(); + +} diff --git a/tests/src/Kernel/ReadinessChecker/SupportedPhpVersionTest.php b/tests/src/Kernel/ReadinessChecker/SupportedPhpVersionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f8d394cd7a947dc6ee72c94dcbb65d34c2b5dbfc --- /dev/null +++ b/tests/src/Kernel/ReadinessChecker/SupportedPhpVersionTest.php @@ -0,0 +1,73 @@ +<?php + +namespace Drupal\Tests\automatic_updates\Kernel\ReadinessChecker; + +use Drupal\automatic_updates\ReadinessChecker\BlacklistPhp72Versions; +use Drupal\automatic_updates\ReadinessChecker\MinimumPhpVersion; +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests supported PHP version readiness checking. + * + * @group automatic_updates + */ +class SupportedPhpVersionTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'automatic_updates', + ]; + + /** + * Tests the functionality of supported PHP version readiness checks. + */ + public function testSupportedPhpVersion() { + // No unsupported PHP versions. + $services = [ + 'automatic_updates.minimum_php_version', + 'automatic_updates.blacklist_php_72', + ]; + foreach ($services as $service) { + $messages = $this->container->get($service)->run(); + $this->assertEmpty($messages); + } + $this->assertNotEmpty($services); + + // Unsupported versions. + $messages = (new TestBlacklistPhp72Versions())->run(); + $this->assertEquals('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.', $messages[0]); + $messages = (new TestMinimumPhpVersion())->run(); + $this->assertEquals('This site is running on an unsupported version of PHP. It cannot be updated. Please update to at least PHP 7.0.8.', $messages[0]); + } + +} + +/** + * Class TestBlacklistPhp72Versions. + */ +class TestBlacklistPhp72Versions extends BlacklistPhp72Versions { + + /** + * {@inheritdoc} + */ + protected function getPhpVersion() { + return '7.2.0'; + } + +} + +/** + * Class TestMinimumPhpVersion. + */ +class TestMinimumPhpVersion extends MinimumPhpVersion { + + /** + * {@inheritdoc} + */ + protected function getPhpVersion() { + return '7.0.7'; + } + +}