Merge pull request #18931 from kamil-tekiela/Refactor-VersionInformation

Refactor VersionInformation
This commit is contained in:
Maurício Meneghini Fauth 2024-01-29 14:52:09 -03:00 committed by GitHub
commit ac181e3a54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 93 additions and 311 deletions

View File

@ -6235,16 +6235,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
@ -14575,31 +14565,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
@ -16100,21 +16065,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
@ -16130,41 +16080,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
@ -16175,21 +16095,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

View File

@ -4248,13 +4248,6 @@
</PossiblyUnusedMethod>
</file>
<file src="src/Controllers/VersionCheckController.php">
<MixedArgument>
<code><![CDATA[$versionDetails->releases]]></code>
</MixedArgument>
<MixedAssignment>
<code>$date</code>
<code>$version</code>
</MixedAssignment>
<PossiblyUnusedParam>
<code>$request</code>
</PossiblyUnusedParam>
@ -11021,12 +11014,6 @@
</PossiblyNullOperand>
</file>
<file src="src/Setup/Index.php">
<MixedArgument>
<code>$date</code>
<code>$date</code>
<code>$version</code>
<code><![CDATA[$versionData->releases]]></code>
</MixedArgument>
<MixedArrayAccess>
<code>$messages[$id]</code>
<code><![CDATA[$msg['active']]]></code>
@ -11044,7 +11031,6 @@
<code>$messages[$id]</code>
</MixedArrayOffset>
<MixedAssignment>
<code>$date</code>
<code>$id</code>
<code>$id</code>
<code>$id</code>
@ -11056,7 +11042,6 @@
<code>$msg</code>
<code>$removeIds[]</code>
<code>$type</code>
<code>$version</code>
</MixedAssignment>
</file>
<file src="src/Sql.php">
@ -12223,14 +12208,7 @@
<code>Config::getInstance()</code>
<code>DatabaseInterface::getInstance()</code>
</DeprecatedMethod>
<LessSpecificReturnStatement>
<code>$data</code>
</LessSpecificReturnStatement>
<MixedArgument>
<code><![CDATA[$latestRelease['version']]]></code>
<code>$mysqlVersions</code>
<code>$phpVersions</code>
<code><![CDATA[$release->version]]></code>
<code>$response</code>
</MixedArgument>
<MixedArrayAccess>
@ -12241,25 +12219,12 @@
<code><![CDATA[$_SESSION['cache']['version_check']]]></code>
</MixedArrayAssignment>
<MixedAssignment>
<code>$mysqlVersions</code>
<code>$phpVersions</code>
<code>$release</code>
<code>$response</code>
<code>$response</code>
</MixedAssignment>
<MixedOperand>
<code><![CDATA[$_SESSION['cache']['version_check']['timestamp']]]></code>
</MixedOperand>
<MixedPropertyFetch>
<code><![CDATA[$release->date]]></code>
<code><![CDATA[$release->mysql_versions]]></code>
<code><![CDATA[$release->php_versions]]></code>
<code><![CDATA[$release->version]]></code>
<code><![CDATA[$release->version]]></code>
</MixedPropertyFetch>
<MoreSpecificReturnType>
<code>stdClass|null</code>
</MoreSpecificReturnType>
<PossiblyInvalidArgument>
<code>$response</code>
</PossiblyInvalidArgument>

View File

@ -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]);
}
}

16
src/Release.php Normal file
View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin;
final class Release
{
public function __construct(
public readonly string $version,
public readonly string $date,
public readonly string $phpVersions,
public readonly string $mysqlVersions,
) {
}
}

View File

@ -116,7 +116,7 @@ class Index
// Fetch data
$versionInformation = new VersionInformation();
$versionData = $versionInformation->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);

View File

@ -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

View File

@ -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(

View File

@ -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<object> $versions The versions to use
* @param list<Release> $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{list<object>, array{int, string}, string|null}>
* @return list<array{list<Release>, 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',