From 4d0c57651128cea139e5b644004e8d7d690de0e5 Mon Sep 17 00:00:00 2001 From: Dmytro Khrysiev Date: Fri, 22 Sep 2023 17:37:26 +0200 Subject: [PATCH] BAP-22252: Update doctrine-extensions to support latest dependencies --- .php-version | 1 + composer.json | 10 +++-- src/Oro/ORM/Query/AST/FunctionFactory.php | 18 ++++++++- .../AbstractPlatformAwareFunctionNode.php | 6 +-- src/Oro/ORM/Query/AST/Functions/Cast.php | 7 +++- .../AST/Functions/DateTime/ConvertTz.php | 3 ++ .../ORM/Query/AST/Functions/Numeric/Pow.php | 3 ++ .../ORM/Query/AST/Functions/Numeric/Round.php | 3 ++ .../ORM/Query/AST/Functions/Numeric/Sign.php | 3 ++ .../AST/Functions/Numeric/TimestampDiff.php | 5 ++- .../Query/AST/Functions/SimpleFunction.php | 3 ++ .../Query/AST/Functions/String/ConcatWs.php | 3 ++ .../Query/AST/Functions/String/DateFormat.php | 9 +++-- .../AST/Functions/String/GroupConcat.php | 1 + .../Query/AST/Functions/String/Replace.php | 3 ++ .../AST/Platform/Functions/Mysql/Cast.php | 4 -- .../Platform/Functions/Postgresql/Cast.php | 4 +- tests/Oro/Tests/DBAL/Types/ArrayTypeTest.php | 2 +- tests/Oro/Tests/DBAL/Types/ObjectTypeTest.php | 2 +- .../Oro/Tests/ORM/AST/FunctionFactoryTest.php | 38 ++++++++++++------ .../ORM/AST/Query/Functions/FunctionsTest.php | 13 ++---- .../Functions/fixtures/postgresql/cast.yml | 6 +-- tests/config/mysql.phpunit.xml | 40 +++++++------------ tests/config/pgsql.phpunit.xml | 40 +++++++------------ 24 files changed, 128 insertions(+), 99 deletions(-) create mode 100644 .php-version diff --git a/.php-version b/.php-version new file mode 100644 index 00000000000..b8eb0263502 --- /dev/null +++ b/.php-version @@ -0,0 +1 @@ +8.1 diff --git a/composer.json b/composer.json index 5cdb73283fe..5f445e022c4 100644 --- a/composer.json +++ b/composer.json @@ -12,15 +12,17 @@ } ], "require": { - "php": ">=7.3", - "doctrine/orm": ">=2.6" + "php": ">=8.1", + "doctrine/orm": ">=2.6", + "doctrine/dbal": ">=2.6" }, "require-dev": { - "phpunit/phpunit": "9.*", + "phpunit/phpunit": "~10", "doctrine/data-fixtures": "^1.3", "symfony/yaml": "5.*", "symfony/cache": "5.*", - "squizlabs/php_codesniffer": "3.5.*" + "squizlabs/php_codesniffer": "3.5.*", + "doctrine/annotations": ">1.0, <2.0" }, "autoload": { "psr-4": { diff --git a/src/Oro/ORM/Query/AST/FunctionFactory.php b/src/Oro/ORM/Query/AST/FunctionFactory.php index b6ba3f4d1f7..cbf62562f11 100644 --- a/src/Oro/ORM/Query/AST/FunctionFactory.php +++ b/src/Oro/ORM/Query/AST/FunctionFactory.php @@ -3,6 +3,9 @@ namespace Oro\ORM\Query\AST; +use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; +use Doctrine\DBAL\Platforms\PostgreSQLPlatform; use Doctrine\ORM\Query\QueryException; use Oro\ORM\Query\AST\Platform\Functions\PlatformFunctionNode; @@ -13,8 +16,21 @@ class FunctionFactory * * @throws QueryException */ - public static function create(string $platformName, string $functionName, array $parameters): PlatformFunctionNode + public static function create(AbstractPlatform $platform, string $functionName, array $parameters): PlatformFunctionNode { + if ($platform instanceof PostgreSQLPlatform) { + $platformName = 'postgresql'; + } elseif ($platform instanceof MySQLPlatform) { + $platformName = 'mysql'; + } else { + throw QueryException::syntaxError( + \sprintf( + 'Not supported platform "%s"', + $platform::class + ) + ); + } + $className = __NAMESPACE__ . '\\Platform\\Functions\\' . static::classify(\strtolower($platformName)) diff --git a/src/Oro/ORM/Query/AST/Functions/AbstractPlatformAwareFunctionNode.php b/src/Oro/ORM/Query/AST/Functions/AbstractPlatformAwareFunctionNode.php index 41b364ca291..1f347b68c7b 100644 --- a/src/Oro/ORM/Query/AST/Functions/AbstractPlatformAwareFunctionNode.php +++ b/src/Oro/ORM/Query/AST/Functions/AbstractPlatformAwareFunctionNode.php @@ -9,17 +9,17 @@ abstract class AbstractPlatformAwareFunctionNode extends FunctionNode { - /** @var array */ - public $parameters = []; + public array $parameters = []; /** * @noinspection PhpMissingReturnTypeInspection * @noinspection ReturnTypeCanBeDeclaredInspection + * {@inheritdoc} */ public function getSql(SqlWalker $sqlWalker) { $function = FunctionFactory::create( - $sqlWalker->getConnection()->getDatabasePlatform()->getName(), + $sqlWalker->getConnection()->getDatabasePlatform(), $this->name, $this->parameters ); diff --git a/src/Oro/ORM/Query/AST/Functions/Cast.php b/src/Oro/ORM/Query/AST/Functions/Cast.php index fdd26b6572a..9a745d25679 100644 --- a/src/Oro/ORM/Query/AST/Functions/Cast.php +++ b/src/Oro/ORM/Query/AST/Functions/Cast.php @@ -12,7 +12,7 @@ class Cast extends AbstractPlatformAwareFunctionNode public const TYPE_KEY = 'type'; /** @var array */ - protected $supportedTypes = [ + protected array $supportedTypes = [ 'char', 'string', 'text', @@ -30,6 +30,9 @@ class Cast extends AbstractPlatformAwareFunctionNode 'uuid' ]; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); @@ -79,7 +82,7 @@ protected function isSupportedType(string $type): bool { $type = \strtolower(\trim($type)); foreach ($this->supportedTypes as $supportedType) { - if (0 === \strpos($type, $supportedType)) { + if (str_starts_with($type, $supportedType)) { return true; } } diff --git a/src/Oro/ORM/Query/AST/Functions/DateTime/ConvertTz.php b/src/Oro/ORM/Query/AST/Functions/DateTime/ConvertTz.php index 11c1c9ea8ec..06a8f8b50b2 100644 --- a/src/Oro/ORM/Query/AST/Functions/DateTime/ConvertTz.php +++ b/src/Oro/ORM/Query/AST/Functions/DateTime/ConvertTz.php @@ -13,6 +13,9 @@ class ConvertTz extends AbstractPlatformAwareFunctionNode public const FROM_TZ_KEY = 'from_tz'; public const TO_TZ_KEY = 'to_tz'; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); diff --git a/src/Oro/ORM/Query/AST/Functions/Numeric/Pow.php b/src/Oro/ORM/Query/AST/Functions/Numeric/Pow.php index 8cd1f69bec1..eee793f126d 100644 --- a/src/Oro/ORM/Query/AST/Functions/Numeric/Pow.php +++ b/src/Oro/ORM/Query/AST/Functions/Numeric/Pow.php @@ -12,6 +12,9 @@ class Pow extends AbstractPlatformAwareFunctionNode public const VALUE_KEY = 'value'; public const POWER_KEY = 'power'; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); diff --git a/src/Oro/ORM/Query/AST/Functions/Numeric/Round.php b/src/Oro/ORM/Query/AST/Functions/Numeric/Round.php index 2bc4a6ea5fa..0af8bc1a2e2 100644 --- a/src/Oro/ORM/Query/AST/Functions/Numeric/Round.php +++ b/src/Oro/ORM/Query/AST/Functions/Numeric/Round.php @@ -12,6 +12,9 @@ class Round extends AbstractPlatformAwareFunctionNode public const VALUE = 'value'; public const PRECISION = 'precision'; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $lexer = $parser->getLexer(); diff --git a/src/Oro/ORM/Query/AST/Functions/Numeric/Sign.php b/src/Oro/ORM/Query/AST/Functions/Numeric/Sign.php index 4a9626f5492..22870b2e99a 100644 --- a/src/Oro/ORM/Query/AST/Functions/Numeric/Sign.php +++ b/src/Oro/ORM/Query/AST/Functions/Numeric/Sign.php @@ -11,6 +11,9 @@ class Sign extends AbstractPlatformAwareFunctionNode { public const PARAMETER_KEY = 'expression'; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); diff --git a/src/Oro/ORM/Query/AST/Functions/Numeric/TimestampDiff.php b/src/Oro/ORM/Query/AST/Functions/Numeric/TimestampDiff.php index 082eabbc9b9..2f5a71cbfb4 100644 --- a/src/Oro/ORM/Query/AST/Functions/Numeric/TimestampDiff.php +++ b/src/Oro/ORM/Query/AST/Functions/Numeric/TimestampDiff.php @@ -16,7 +16,7 @@ class TimestampDiff extends AbstractPlatformAwareFunctionNode /** * @var array */ - protected $supportedUnits = [ + protected array $supportedUnits = [ 'MICROSECOND', 'SECOND', 'MINUTE', @@ -28,6 +28,9 @@ class TimestampDiff extends AbstractPlatformAwareFunctionNode 'YEAR' ]; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); diff --git a/src/Oro/ORM/Query/AST/Functions/SimpleFunction.php b/src/Oro/ORM/Query/AST/Functions/SimpleFunction.php index 369f8a304d4..49f3106c6fd 100644 --- a/src/Oro/ORM/Query/AST/Functions/SimpleFunction.php +++ b/src/Oro/ORM/Query/AST/Functions/SimpleFunction.php @@ -10,6 +10,9 @@ class SimpleFunction extends AbstractPlatformAwareFunctionNode { public const PARAMETER_KEY = 'expression'; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); diff --git a/src/Oro/ORM/Query/AST/Functions/String/ConcatWs.php b/src/Oro/ORM/Query/AST/Functions/String/ConcatWs.php index 7c6bd7776ef..2752e2e89a5 100644 --- a/src/Oro/ORM/Query/AST/Functions/String/ConcatWs.php +++ b/src/Oro/ORM/Query/AST/Functions/String/ConcatWs.php @@ -13,6 +13,9 @@ class ConcatWs extends AbstractPlatformAwareFunctionNode public const STRINGS_KEY = 'strings'; public const SEPARATOR_KEY = 'separator'; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); diff --git a/src/Oro/ORM/Query/AST/Functions/String/DateFormat.php b/src/Oro/ORM/Query/AST/Functions/String/DateFormat.php index 596bf2492c6..ef55fdbe98c 100644 --- a/src/Oro/ORM/Query/AST/Functions/String/DateFormat.php +++ b/src/Oro/ORM/Query/AST/Functions/String/DateFormat.php @@ -13,7 +13,7 @@ class DateFormat extends AbstractPlatformAwareFunctionNode public const FORMAT_KEY = 'format'; /** @var array */ - private static $knownFormats = [ + private static array $knownFormats = [ '%a', '%b', '%c', @@ -49,7 +49,7 @@ class DateFormat extends AbstractPlatformAwareFunctionNode ]; /** @var array */ - private static $supportedFormats = [ + private static array $supportedFormats = [ '%a', '%b', '%c', @@ -76,6 +76,9 @@ class DateFormat extends AbstractPlatformAwareFunctionNode '%%', ]; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); @@ -96,7 +99,7 @@ private function validateFormat(Parser $parser): void $format = \str_replace('%%', '', (string)$this->parameters[self::FORMAT_KEY]); $unsupportedFormats = \array_diff(self::$knownFormats, self::$supportedFormats); foreach ($unsupportedFormats as $unsupportedFormat) { - if (false !== \strpos($format, $unsupportedFormat)) { + if (str_contains($format, $unsupportedFormat)) { $parser->syntaxError( \sprintf( 'Format string contains unsupported specifier %s. The supported specifiers are: "%s"', diff --git a/src/Oro/ORM/Query/AST/Functions/String/GroupConcat.php b/src/Oro/ORM/Query/AST/Functions/String/GroupConcat.php index 20387a1c8de..af04c74575f 100644 --- a/src/Oro/ORM/Query/AST/Functions/String/GroupConcat.php +++ b/src/Oro/ORM/Query/AST/Functions/String/GroupConcat.php @@ -16,6 +16,7 @@ class GroupConcat extends AbstractPlatformAwareFunctionNode /** * @url http://sysmagazine.com/posts/181666/ + * {@inheritdoc} */ public function parse(Parser $parser) { diff --git a/src/Oro/ORM/Query/AST/Functions/String/Replace.php b/src/Oro/ORM/Query/AST/Functions/String/Replace.php index eab49c46aa5..a6481972dd8 100644 --- a/src/Oro/ORM/Query/AST/Functions/String/Replace.php +++ b/src/Oro/ORM/Query/AST/Functions/String/Replace.php @@ -14,6 +14,9 @@ class Replace extends AbstractPlatformAwareFunctionNode public const FROM_KEY = 'from'; public const TO_KEY = 'to'; + /** + * {@inheritdoc} + */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); diff --git a/src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Cast.php b/src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Cast.php index db7e2eeb822..6a705b63467 100644 --- a/src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Cast.php +++ b/src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Cast.php @@ -16,10 +16,6 @@ public function getSql(SqlWalker $sqlWalker): string $value = $this->parameters[DqlFunction::PARAMETER_KEY]; $type = $this->parameters[DqlFunction::TYPE_KEY]; - if ($type === 'json' && !$sqlWalker->getConnection()->getDatabasePlatform()->hasNativeJsonType()) { - $type = 'text'; - } - $type = \strtolower($type); $isBoolean = $type === 'bool' || $type === 'boolean'; if ($type === 'char') { diff --git a/src/Oro/ORM/Query/AST/Platform/Functions/Postgresql/Cast.php b/src/Oro/ORM/Query/AST/Platform/Functions/Postgresql/Cast.php index b3312954a04..26c54b55014 100644 --- a/src/Oro/ORM/Query/AST/Platform/Functions/Postgresql/Cast.php +++ b/src/Oro/ORM/Query/AST/Platform/Functions/Postgresql/Cast.php @@ -26,8 +26,8 @@ public function getSql(SqlWalker $sqlWalker): string return $timestampFunction->getSql($sqlWalker); } - if ($type === 'json' && !$sqlWalker->getConnection()->getDatabasePlatform()->hasNativeJsonType()) { - $type = 'text'; + if ($type === 'json') { + $type = 'jsonb'; } if ($type === 'bool') { diff --git a/tests/Oro/Tests/DBAL/Types/ArrayTypeTest.php b/tests/Oro/Tests/DBAL/Types/ArrayTypeTest.php index 2f8d2005b25..22db31e1b8a 100644 --- a/tests/Oro/Tests/DBAL/Types/ArrayTypeTest.php +++ b/tests/Oro/Tests/DBAL/Types/ArrayTypeTest.php @@ -55,7 +55,7 @@ protected function getType(): Type return Type::getType(Types::ARRAY); } - public function serializationDataProvider(): array + public static function serializationDataProvider(): array { return [ [['a' => 'b']], diff --git a/tests/Oro/Tests/DBAL/Types/ObjectTypeTest.php b/tests/Oro/Tests/DBAL/Types/ObjectTypeTest.php index fddfbda0033..27c32e09d6f 100644 --- a/tests/Oro/Tests/DBAL/Types/ObjectTypeTest.php +++ b/tests/Oro/Tests/DBAL/Types/ObjectTypeTest.php @@ -55,7 +55,7 @@ protected function getType(): Type return Type::getType(Types::OBJECT); } - public function serializationDataProvider(): array + public static function serializationDataProvider(): array { $object = new \stdClass(); $object->a = 'test1'; diff --git a/tests/Oro/Tests/ORM/AST/FunctionFactoryTest.php b/tests/Oro/Tests/ORM/AST/FunctionFactoryTest.php index c394d34ad17..b1841e24471 100644 --- a/tests/Oro/Tests/ORM/AST/FunctionFactoryTest.php +++ b/tests/Oro/Tests/ORM/AST/FunctionFactoryTest.php @@ -3,17 +3,29 @@ namespace Oro\Tests\ORM\AST; +use Doctrine\DBAL\Platforms\MySQLPlatform; +use Doctrine\DBAL\Platforms\OraclePlatform; +use Doctrine\DBAL\Platforms\PostgreSQLPlatform; use Doctrine\ORM\Query\QueryException; use Oro\ORM\Query\AST\FunctionFactory; use PHPUnit\Framework\TestCase; class FunctionFactoryTest extends TestCase { - public function testCreateException(): void + public function testCreateExceptionNotSupportedPlatform(): void { + $platform = $this->createMock(OraclePlatform::class); $this->expectException(QueryException::class); - $this->expectExceptionMessage('[Syntax Error] Function "TestF" does not supported for platform "Test"'); - FunctionFactory::create('Test', 'TestF', []); + $this->expectExceptionMessage(sprintf('[Syntax Error] Not supported platform "%s"', $platform::class)); + FunctionFactory::create($platform, 'date', []); + } + + public function testCreateExceptionNotSupportedFunction(): void + { + $platform = $this->createMock(PostgreSQLPlatform::class); + $this->expectException(QueryException::class); + $this->expectExceptionMessage('[Syntax Error] Function "testF" does not supported for platform "postgresql"'); + FunctionFactory::create($platform, 'testF', []); } /** @@ -23,20 +35,20 @@ public function testCreateException(): void public function testCreate(string $platform, string $function): void { $this->expectNotToPerformAssertions(); - FunctionFactory::create($platform, $function, []); + FunctionFactory::create($this->createMock($platform), $function, []); } - public function platformFunctionsDataProvider(): array + public static function platformFunctionsDataProvider(): array { return [ - ['mysql', 'date'], - ['Mysql', 'Date'], - ['MySql', 'DATE'], - ['postgresql', 'group_concat'], - ['Mysql', 'Group_Concat'], - ['postgresql', 'GROUP_CONCAT'], - ['Mysql', 'TimestampDiff'], - ['postgresql', 'TIMESTAMPDIFF'], + [MySQLPlatform::class, 'date'], + [MySQLPlatform::class, 'Date'], + [MySQLPlatform::class, 'DATE'], + [PostgreSQLPlatform::class, 'group_concat'], + [MySQLPlatform::class, 'Group_Concat'], + [PostgreSQLPlatform::class, 'GROUP_CONCAT'], + [MySQLPlatform::class, 'TimestampDiff'], + [PostgreSQLPlatform::class, 'TIMESTAMPDIFF'], ]; } } diff --git a/tests/Oro/Tests/ORM/AST/Query/Functions/FunctionsTest.php b/tests/Oro/Tests/ORM/AST/Query/Functions/FunctionsTest.php index 6603ec782ea..440949d657a 100644 --- a/tests/Oro/Tests/ORM/AST/Query/Functions/FunctionsTest.php +++ b/tests/Oro/Tests/ORM/AST/Query/Functions/FunctionsTest.php @@ -32,8 +32,7 @@ public function testDqlFunction(array $functions, string $dql, $sql, array $expe foreach ($sql as $sqlVariant) { $constraints[] = static::equalTo($sqlVariant); } - $constraint = new LogicalOr(); - $constraint->setConstraints($constraints); + $constraint = LogicalOr::fromConstraints($constraints); static::assertThat($query->getSQL(), $constraint); } else { static::assertEquals($sql, $query->getSQL(), \sprintf('Unexpected SQL for "%s"', $dql)); @@ -50,10 +49,9 @@ public function testDqlFunction(array $functions, string $dql, $sql, array $expe /** * @throws \Exception */ - public function functionsDataProvider(): array + public static function functionsDataProvider(): \Generator { $platform = TestUtil::getPlatformName(); - $data = []; $files = new \FilesystemIterator( __DIR__ . '/fixtures/' . $platform, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME @@ -63,14 +61,9 @@ public function functionsDataProvider(): array if (!\is_array($fileData)) { throw new \RuntimeException(\sprintf('Could not parse file %s', $file)); } - $data[] = $fileData; - } - if (!$data) { - return []; + yield from $fileData; } - - return array_merge(...$data); } protected function registerDqlFunction( diff --git a/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/postgresql/cast.yml b/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/postgresql/cast.yml index fb86b9ce724..61be10b0169 100644 --- a/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/postgresql/cast.yml +++ b/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/postgresql/cast.yml @@ -84,11 +84,9 @@ - functions: - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } dql: "SELECT CAST(CONCAT('{\"a\":', f.id, '}') as json) FROM Oro\\Entities\\Foo f WHERE f.id = 1" - sql: - - "SELECT CAST('{\"a\":' || t0_.id || '}' AS json) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" - - "SELECT CAST('{\"a\":' || t0_.id || '}' AS text) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" + sql: "SELECT CAST('{\"a\":' || t0_.id || '}' AS jsonb) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - - '{"a":1}' + - '{"a": 1}' #DECIMAL - functions: diff --git a/tests/config/mysql.phpunit.xml b/tests/config/mysql.phpunit.xml index b727c27087a..d8e106eb0db 100644 --- a/tests/config/mysql.phpunit.xml +++ b/tests/config/mysql.phpunit.xml @@ -1,27 +1,17 @@ - - - - - - - - - - - - - - ../Oro/Tests/ORM - ../Oro/Tests/DBAL - - + + + + + + + + + + + + ../Oro/Tests/ORM + ../Oro/Tests/DBAL + + diff --git a/tests/config/pgsql.phpunit.xml b/tests/config/pgsql.phpunit.xml index 06e798c2dc3..939e9d7a736 100644 --- a/tests/config/pgsql.phpunit.xml +++ b/tests/config/pgsql.phpunit.xml @@ -1,27 +1,17 @@ - - - - - - - - - - - - - - ../Oro/Tests/ORM - ../Oro/Tests/DBAL - - + + + + + + + + + + + + ../Oro/Tests/ORM + ../Oro/Tests/DBAL + +