From e6b72cc22628675e168e440aef0ad1119cbad70b Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Wed, 24 Jan 2024 00:26:38 +0100 Subject: [PATCH] Refactor VersionInformation Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 95 ----------- psalm-baseline.xml | 35 ----- src/Controllers/VersionCheckController.php | 10 +- src/Release.php | 16 ++ src/Setup/Index.php | 8 +- src/VersionInformation.php | 40 +++-- .../VersionCheckControllerTest.php | 53 ++----- tests/classes/VersionInformationTest.php | 147 ++++-------------- 8 files changed, 93 insertions(+), 311 deletions(-) create mode 100644 src/Release.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 73ae547596..44f95b29a3 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -6245,16 +6245,6 @@ parameters: count: 1 path: src/Controllers/UserPasswordController.php - - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 2 - path: src/Controllers/VersionCheckController.php - - - - message: "#^Parameter \\#1 \\$releases of method PhpMyAdmin\\\\VersionInformation\\:\\:getLatestCompatibleVersion\\(\\) expects array, mixed given\\.$#" - count: 1 - path: src/Controllers/VersionCheckController.php - - message: "#^Cannot access offset 'back' on mixed\\.$#" count: 1 @@ -14645,31 +14635,6 @@ parameters: count: 4 path: src/Setup/Index.php - - - message: "#^Parameter \\#1 \\$releases of method PhpMyAdmin\\\\VersionInformation\\:\\:getLatestCompatibleVersion\\(\\) expects array, mixed given\\.$#" - count: 1 - path: src/Setup/Index.php - - - - message: "#^Parameter \\#1 \\$string of function htmlspecialchars expects string, mixed given\\.$#" - count: 2 - path: src/Setup/Index.php - - - - message: "#^Parameter \\#1 \\$version of method PhpMyAdmin\\\\VersionInformation\\:\\:versionToInt\\(\\) expects string, mixed given\\.$#" - count: 1 - path: src/Setup/Index.php - - - - message: "#^Parameter \\#2 \\.\\.\\.\\$values of function sprintf expects bool\\|float\\|int\\|string\\|null, mixed given\\.$#" - count: 1 - path: src/Setup/Index.php - - - - message: "#^Parameter \\#3 \\.\\.\\.\\$values of function sprintf expects bool\\|float\\|int\\|string\\|null, mixed given\\.$#" - count: 1 - path: src/Setup/Index.php - - message: "#^Access to an undefined property PhpMyAdmin\\\\SqlParser\\\\Statement\\:\\:\\$expr\\.$#" count: 2 @@ -16170,21 +16135,6 @@ parameters: count: 8 path: src/Utils/SessionCache.php - - - message: "#^Access to an undefined property object\\:\\:\\$date\\.$#" - count: 1 - path: src/VersionInformation.php - - - - message: "#^Access to an undefined property object\\:\\:\\$releases\\.$#" - count: 1 - path: src/VersionInformation.php - - - - message: "#^Access to an undefined property object\\:\\:\\$version\\.$#" - count: 1 - path: src/VersionInformation.php - - message: "#^Cannot access offset 'response' on mixed\\.$#" count: 1 @@ -16200,41 +16150,11 @@ parameters: count: 2 path: src/VersionInformation.php - - - message: "#^Cannot access property \\$date on mixed\\.$#" - count: 1 - path: src/VersionInformation.php - - - - message: "#^Cannot access property \\$mysql_versions on mixed\\.$#" - count: 1 - path: src/VersionInformation.php - - - - message: "#^Cannot access property \\$php_versions on mixed\\.$#" - count: 1 - path: src/VersionInformation.php - - - - message: "#^Cannot access property \\$version on mixed\\.$#" - count: 2 - path: src/VersionInformation.php - - message: "#^Comparison operation \"\\>\\=\" between int\\<1, max\\> and 1 is always true\\.$#" count: 1 path: src/VersionInformation.php - - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 3 - path: src/VersionInformation.php - - - - message: "#^Method PhpMyAdmin\\\\VersionInformation\\:\\:getLatestVersion\\(\\) should return stdClass\\|null but returns object\\.$#" - count: 1 - path: src/VersionInformation.php - - message: "#^Only booleans are allowed in an if condition, int\\|false given\\.$#" count: 1 @@ -16245,21 +16165,6 @@ parameters: count: 1 path: src/VersionInformation.php - - - message: "#^Parameter \\#1 \\$version1 of function version_compare expects string, mixed given\\.$#" - count: 1 - path: src/VersionInformation.php - - - - message: "#^Parameter \\#2 \\$string of function explode expects string, mixed given\\.$#" - count: 2 - path: src/VersionInformation.php - - - - message: "#^Parameter \\#2 \\$version2 of function version_compare expects string, mixed given\\.$#" - count: 1 - path: src/VersionInformation.php - - message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#" count: 1 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index c420b39355..7d748aedeb 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -4273,13 +4273,6 @@ - - releases]]> - - - $date - $version - $request @@ -11084,12 +11077,6 @@ - - $date - $date - $version - releases]]> - $messages[$id] @@ -11107,7 +11094,6 @@ $messages[$id] - $date $id $id $id @@ -11119,7 +11105,6 @@ $msg $removeIds[] $type - $version @@ -12286,14 +12271,7 @@ Config::getInstance() DatabaseInterface::getInstance() - - $data - - - $mysqlVersions - $phpVersions - version]]> $response @@ -12304,25 +12282,12 @@ - $mysqlVersions - $phpVersions - $release $response $response - - date]]> - mysql_versions]]> - php_versions]]> - version]]> - version]]> - - - stdClass|null - $response diff --git a/src/Controllers/VersionCheckController.php b/src/Controllers/VersionCheckController.php index 46a125e1f1..41e3b5473c 100644 --- a/src/Controllers/VersionCheckController.php +++ b/src/Controllers/VersionCheckController.php @@ -39,7 +39,7 @@ class VersionCheckController extends AbstractController header(sprintf('%s: %s', $name, $value)); } - $versionDetails = $this->versionInformation->getLatestVersion(); + $versionDetails = $this->versionInformation->getLatestVersions(); if ($versionDetails === null) { echo json_encode([]); @@ -47,14 +47,14 @@ class VersionCheckController extends AbstractController return; } - $latestCompatible = $this->versionInformation->getLatestCompatibleVersion($versionDetails->releases); + $latestCompatible = $this->versionInformation->getLatestCompatibleVersion($versionDetails); $version = ''; $date = ''; if ($latestCompatible != null) { - $version = $latestCompatible['version']; - $date = $latestCompatible['date']; + $version = $latestCompatible->version; + $date = $latestCompatible->date; } - echo json_encode(['version' => ! empty($version) ? $version : '', 'date' => ! empty($date) ? $date : '']); + echo json_encode(['version' => $version, 'date' => $date]); } } diff --git a/src/Release.php b/src/Release.php new file mode 100644 index 0000000000..23def577d2 --- /dev/null +++ b/src/Release.php @@ -0,0 +1,16 @@ +getLatestVersion(); + $versionData = $versionInformation->getLatestVersions(); if ($versionData === null) { self::messagesSet( @@ -131,13 +131,13 @@ class Index return; } - $latestCompatible = $versionInformation->getLatestCompatibleVersion($versionData->releases); + $latestCompatible = $versionInformation->getLatestCompatibleVersion($versionData); if ($latestCompatible == null) { return; } - $version = $latestCompatible['version']; - $date = $latestCompatible['date']; + $version = $latestCompatible->version; + $date = $latestCompatible->date; $versionUpstream = $versionInformation->versionToInt($version); diff --git a/src/VersionInformation.php b/src/VersionInformation.php index b1bf3abaf3..b2082826ae 100644 --- a/src/VersionInformation.php +++ b/src/VersionInformation.php @@ -8,13 +8,12 @@ declare(strict_types=1); namespace PhpMyAdmin; use PhpMyAdmin\Utils\HttpRequest; -use stdClass; use function count; use function explode; use function intval; +use function is_array; use function is_numeric; -use function is_object; use function is_string; use function json_decode; use function preg_match; @@ -34,9 +33,9 @@ class VersionInformation /** * Returns information with latest version from phpmyadmin.net * - * @return stdClass|null JSON decoded object with the data + * @return Release[]|null JSON decoded object with the data */ - public function getLatestVersion(): stdClass|null + public function getLatestVersions(): array|null { if (! Config::getInstance()->settings['VersionCheck']) { return null; @@ -59,10 +58,10 @@ class VersionInformation $response = $response ?: '{}'; /* Parse response */ - $data = json_decode($response); + $data = json_decode($response, true); /* Basic sanity checking */ - if (! is_object($data) || empty($data->version) || empty($data->releases) || empty($data->date)) { + if (! is_array($data) || ! isset($data['releases']) || ! is_array($data['releases'])) { return null; } @@ -70,7 +69,18 @@ class VersionInformation $_SESSION['cache']['version_check'] = ['response' => $response, 'timestamp' => time()]; } - return $data; + $releases = []; + /** @var string[] $release */ + foreach ($data['releases'] as $release) { + $releases[] = new Release( + $release['version'], + $release['date'], + $release['php_versions'], + $release['mysql_versions'], + ); + } + + return $releases; } /** @@ -137,17 +147,16 @@ class VersionInformation * Returns the version and date of the latest phpMyAdmin version compatible * with the available PHP and MySQL versions * - * @param mixed[] $releases array of information related to each version + * @param Release[] $releases array of information related to each version * - * @return mixed[]|null containing the version and date of latest compatible version + * @return Release|null containing the version and date of latest compatible version */ - public function getLatestCompatibleVersion(array $releases): array|null + public function getLatestCompatibleVersion(array $releases): Release|null { // Maintains the latest compatible version $latestRelease = null; foreach ($releases as $release) { - // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps - $phpVersions = $release->php_versions; + $phpVersions = $release->phpVersions; $phpConditions = explode(',', $phpVersions); foreach ($phpConditions as $phpCondition) { if (! $this->evaluateVersionCondition('PHP', $phpCondition)) { @@ -159,8 +168,7 @@ class VersionInformation // We evaluate MySQL version constraint if there are only // one server configured. if (count(Config::getInstance()->settings['Servers']) === 1) { - // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps - $mysqlVersions = $release->mysql_versions; + $mysqlVersions = $release->mysqlVersions; $mysqlConditions = explode(',', $mysqlVersions); foreach ($mysqlConditions as $mysqlCondition) { if (! $this->evaluateVersionCondition('MySQL', $mysqlCondition)) { @@ -170,11 +178,11 @@ class VersionInformation } // To compare the current release with the previous latest release or no release is set - if ($latestRelease !== null && ! version_compare($latestRelease['version'], $release->version, '<')) { + if ($latestRelease !== null && ! version_compare($latestRelease->version, $release->version, '<')) { continue; } - $latestRelease = ['version' => $release->version, 'date' => $release->date]; + $latestRelease = $release; } // no compatible version diff --git a/tests/classes/Controllers/VersionCheckControllerTest.php b/tests/classes/Controllers/VersionCheckControllerTest.php index 5fb748f6c2..b230453760 100644 --- a/tests/classes/Controllers/VersionCheckControllerTest.php +++ b/tests/classes/Controllers/VersionCheckControllerTest.php @@ -7,6 +7,7 @@ namespace PhpMyAdmin\Tests\Controllers; use PhpMyAdmin\Controllers\VersionCheckController; use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\Http\ServerRequest; +use PhpMyAdmin\Release; use PhpMyAdmin\Template; use PhpMyAdmin\Tests\AbstractTestCase; use PhpMyAdmin\Tests\Stubs\ResponseRenderer; @@ -28,30 +29,16 @@ class VersionCheckControllerTest extends AbstractTestCase public function testWithLatestCompatibleVersion(): void { $_GET = []; - $versionInfo = (object) [ - 'date' => '2022-02-11', - 'version' => '5.1.3', - 'releases' => [ - (object) [ - 'date' => '2022-02-11', - 'php_versions' => '>=7.1,<8.1', - 'version' => '5.1.3', - 'mysql_versions' => '>=5.5', - ], - (object) [ - 'date' => '2022-02-11', - 'php_versions' => '>=5.5,<8.0', - 'version' => '4.9.10', - 'mysql_versions' => '>=5.5', - ], - ], + $versionInfo = [ + new Release('5.1.3', '2022-02-11', '>=7.1,<8.1', '>=5.5'), + new Release('4.9.10', '2022-02-11', '>=5.5,<8.0', '>=5.5'), ]; $versionInformation = $this->createMock(VersionInformation::class); - $versionInformation->expects($this->once())->method('getLatestVersion')->willReturn($versionInfo); + $versionInformation->expects($this->once())->method('getLatestVersions')->willReturn($versionInfo); $versionInformation->expects($this->once())->method('getLatestCompatibleVersion') - ->with($this->equalTo($versionInfo->releases)) - ->willReturn(['version' => '5.1.3', 'date' => '2022-02-11']); + ->with($this->equalTo($versionInfo)) + ->willReturn($versionInfo[0]); (new VersionCheckController( new ResponseRenderer(), @@ -67,29 +54,15 @@ class VersionCheckControllerTest extends AbstractTestCase public function testWithoutLatestCompatibleVersion(): void { $_GET = []; - $versionInfo = (object) [ - 'date' => '2022-02-11', - 'version' => '5.1.3', - 'releases' => [ - (object) [ - 'date' => '2022-02-11', - 'php_versions' => '>=7.1,<8.1', - 'version' => '5.1.3', - 'mysql_versions' => '>=5.5', - ], - (object) [ - 'date' => '2022-02-11', - 'php_versions' => '>=5.5,<8.0', - 'version' => '4.9.10', - 'mysql_versions' => '>=5.5', - ], - ], + $versionInfo = [ + new Release('5.1.3', '2022-02-11', '>=7.1,<8.1', '>=5.5'), + new Release('4.9.10', '2022-02-11', '>=5.5,<8.0', '>=5.5'), ]; $versionInformation = $this->createMock(VersionInformation::class); - $versionInformation->expects($this->once())->method('getLatestVersion')->willReturn($versionInfo); + $versionInformation->expects($this->once())->method('getLatestVersions')->willReturn($versionInfo); $versionInformation->expects($this->once())->method('getLatestCompatibleVersion') - ->with($this->equalTo($versionInfo->releases)) + ->with($this->equalTo($versionInfo)) ->willReturn(null); (new VersionCheckController( @@ -108,7 +81,7 @@ class VersionCheckControllerTest extends AbstractTestCase $_GET = []; $versionInformation = $this->createMock(VersionInformation::class); - $versionInformation->expects($this->once())->method('getLatestVersion')->willReturn(null); + $versionInformation->expects($this->once())->method('getLatestVersions')->willReturn(null); $versionInformation->expects($this->never())->method('getLatestCompatibleVersion'); (new VersionCheckController( diff --git a/tests/classes/VersionInformationTest.php b/tests/classes/VersionInformationTest.php index 4b70ae5aef..3a20359a08 100644 --- a/tests/classes/VersionInformationTest.php +++ b/tests/classes/VersionInformationTest.php @@ -5,16 +5,16 @@ declare(strict_types=1); namespace PhpMyAdmin\Tests; use PhpMyAdmin\Config; +use PhpMyAdmin\Release; use PhpMyAdmin\VersionInformation; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; -use stdClass; #[CoversClass(VersionInformation::class)] class VersionInformationTest extends AbstractTestCase { - /** @var stdClass[] */ + /** @var Release[] */ private array $releases; /** @@ -29,28 +29,14 @@ class VersionInformationTest extends AbstractTestCase $this->releases = []; - // phpcs:disable Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps - $release = new stdClass(); - $release->date = '2015-09-08'; - $release->php_versions = '>=5.3,<7.1'; - $release->version = '4.4.14.1'; - $release->mysql_versions = '>=5.5'; + $release = new Release('4.4.14.1', '2015-09-08', '>=5.3,<7.1', '>=5.5'); $this->releases[] = $release; - $release = new stdClass(); - $release->date = '2015-09-09'; - $release->php_versions = '>=5.3,<7.0'; - $release->version = '4.4.13.3'; - $release->mysql_versions = '>=5.5'; + $release = new Release('4.4.13.3', '2015-09-09', '>=5.3,<7.0', '>=5.5'); $this->releases[] = $release; - $release = new stdClass(); - $release->date = '2015-05-13'; - $release->php_versions = '>=5.2,<5.3'; - $release->version = '4.0.10.10'; - $release->mysql_versions = '>=5.0'; + $release = new Release('4.0.10.10', '2015-05-13', '>=5.2,<5.3', '>=5.0'); $this->releases[] = $release; - // phpcs:enable } /** @@ -64,10 +50,9 @@ class VersionInformationTest extends AbstractTestCase Config::getInstance()->settings['VersionCheck'] = true; unset($_SESSION['cache']['version_check']); $versionInformation = new VersionInformation(); - $version = $versionInformation->getLatestVersion(); - $this->assertIsObject($version); - $this->assertNotEmpty($version->version); - $this->assertNotEmpty($version->date); + $version = $versionInformation->getLatestVersions(); + $this->assertIsArray($version); + $this->assertNotEmpty($version); } /** @@ -128,8 +113,8 @@ class VersionInformationTest extends AbstractTestCase $mockVersionInfo->expects($this->exactly(2))->method('getMySQLVersion')->willReturn('5.5.0'); $compatible = $mockVersionInfo->getLatestCompatibleVersion($this->releases); - $this->assertIsArray($compatible); - $this->assertEquals('4.4.14.1', $compatible['version']); + $this->assertInstanceOf(Release::class, $compatible); + $this->assertEquals('4.4.14.1', $compatible->version); } /** @@ -144,8 +129,8 @@ class VersionInformationTest extends AbstractTestCase $mockVersionInfo->expects($this->never())->method('getMySQLVersion'); $compatible = $mockVersionInfo->getLatestCompatibleVersion($this->releases); - $this->assertIsArray($compatible); - $this->assertEquals('4.4.14.1', $compatible['version']); + $this->assertInstanceOf(Release::class, $compatible); + $this->assertEquals('4.4.14.1', $compatible->version); } /** @@ -160,14 +145,14 @@ class VersionInformationTest extends AbstractTestCase $mockVersionInfo->expects($this->never())->method('getMySQLVersion'); $compatible = $mockVersionInfo->getLatestCompatibleVersion($this->releases); - $this->assertIsArray($compatible); - $this->assertEquals('4.0.10.10', $compatible['version']); + $this->assertInstanceOf(Release::class, $compatible); + $this->assertEquals('4.0.10.10', $compatible->version); } /** * Tests getLatestCompatibleVersion() with an new PHP version * - * @param list $versions The versions to use + * @param list $versions The versions to use * @param array{int, string} $conditions The conditions that will be executed * @param string|null $matchedLastVersion The version that will be matched */ @@ -184,140 +169,70 @@ class VersionInformationTest extends AbstractTestCase $mockVersionInfo->expects($this->never())->method('getMySQLVersion'); $compatible = $mockVersionInfo->getLatestCompatibleVersion($versions); - $this->assertEquals($matchedLastVersion, $compatible['version'] ?? null); + $this->assertEquals($matchedLastVersion, $compatible->version ?? null); } /** * Provider for testGetLatestCompatibleVersionWithNewPHPVersion * Returns the conditions to be used for mocks * - * @return list, array{int, string}, string|null}> + * @return list, array{int, string}, string|null}> */ public static function dataProviderVersionConditions(): array { return [ [ [ - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=5.5,<8.0', - 'version' => '4.9.3', - 'mysql_versions' => '>=5.5', - ]), - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=7.1,<8.0', - 'version' => '5.0.0', - 'mysql_versions' => '>=5.5', - ]), + new Release('4.9.3', '2019-12-26', '>=5.5,<8.0', '>=5.5'), + new Release('5.0.0', '2019-12-26', '>=7.1,<8.0', '>=5.5'), ], [3, '7.0.0'], '4.9.3', ], [ [ - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=5.5,<7.0', - 'version' => '6.0.0', - 'mysql_versions' => '>=5.5', - ]), - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=7.1,<8.0', - 'version' => '5.0.0', - 'mysql_versions' => '>=5.5', - ]), + new Release('6.0.0', '2019-12-26', '>=5.5,<7.0', '>=5.5'), + new Release('5.0.0', '2019-12-26', '>=7.1,<8.0', '>=5.5'), ], [3, '5.6.0'], '6.0.0', ], [ [ - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=5.5,<7.0', - 'version' => '6.0.0-rc1', - 'mysql_versions' => '>=5.5', - ]), - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=7.1,<8.0', - 'version' => '6.0.0-rc2', - 'mysql_versions' => '>=5.5', - ]), + new Release('6.0.0-rc1', '2019-12-26', '>=5.5,<7.0', '>=5.5'), + new Release('6.0.0-rc2', '2019-12-26', '>=7.1,<8.0', '>=5.5'), ], [3, '5.6.0'], '6.0.0-rc1', ], [ [ - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=5.5,<7.0', - 'version' => '6.0.0', - 'mysql_versions' => '>=5.5', - ]), - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=7.1,<8.0', - 'version' => '5.0.0', - 'mysql_versions' => '>=5.5', - ]), + new Release('6.0.0', '2019-12-26', '>=5.5,<7.0', '>=5.5'), + new Release('5.0.0', '2019-12-26', '>=7.1,<8.0', '>=5.5'), ], [3, '7.0.0'], null, ], [ [ - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=5.5,<7.0', - 'version' => '6.0.0', - 'mysql_versions' => '>=5.5', - ]), - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=7.1,<8.0', - 'version' => '5.0.0', - 'mysql_versions' => '>=5.5', - ]), + new Release('6.0.0', '2019-12-26', '>=5.5,<7.0', '>=5.5'), + new Release('5.0.0', '2019-12-26', '>=7.1,<8.0', '>=5.5'), ], [4, '7.1.0'], '5.0.0', ], [ [ - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=5.5,<8.0', - 'version' => '4.9.3', - 'mysql_versions' => '>=5.5', - ]), - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=7.1,<8.0', - 'version' => '5.0.0', - 'mysql_versions' => '>=5.5', - ]), + new Release('4.9.3', '2019-12-26', '>=5.5,<8.0', '>=5.5'), + new Release('5.0.0', '2019-12-26', '>=7.1,<8.0', '>=5.5'), ], [4, '7.1.0'], '5.0.0', ], [ [ - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=7.1,<8.0', - 'version' => '5.0.0', - 'mysql_versions' => '>=5.5', - ]), - ((object) [ - 'date' => '2019-12-26', - 'php_versions' => '>=5.5,<8.0', - 'version' => '4.9.3', - 'mysql_versions' => '>=5.5', - ]), + new Release('5.0.0', '2019-12-26', '>=7.1,<8.0', '>=5.5'), + new Release('4.9.3', '2019-12-26', '>=5.5,<8.0', '>=5.5'), ], [4, '7.2.0'], '5.0.0',