From b3678c40f29566a69ef6512b75e0167d3e1a000d Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Fri, 18 Apr 2025 00:47:55 +0100 Subject: [PATCH 1/5] refactor: allow multiple node mapping patterns to be used and their arguments to be validated in variadic functions --- .../Doctrine/ORM/Query/AST/Functions/Arr.php | 22 ++++--- .../ORM/Query/AST/Functions/ArrayToJson.php | 24 ++++--- .../AST/Functions/BaseComparisonFunction.php | 15 +++++ .../AST/Functions/BaseVariadicFunction.php | 65 ++++++++++++++----- .../ORM/Query/AST/Functions/DateAdd.php | 24 ++++--- .../ORM/Query/AST/Functions/DateSubtract.php | 24 ++++--- ...idArgumentForVariadicFunctionException.php | 10 +++ .../ORM/Query/AST/Functions/Greatest.php | 15 +---- .../Query/AST/Functions/JsonBuildObject.php | 21 ++++-- .../Query/AST/Functions/JsonbBuildObject.php | 21 ++++-- .../ORM/Query/AST/Functions/JsonbInsert.php | 24 ++++--- .../Query/AST/Functions/JsonbPathExists.php | 24 ++++--- .../Query/AST/Functions/JsonbPathMatch.php | 24 ++++--- .../Query/AST/Functions/JsonbPathQuery.php | 24 ++++--- .../AST/Functions/JsonbPathQueryArray.php | 24 ++++--- .../AST/Functions/JsonbPathQueryFirst.php | 24 ++++--- .../ORM/Query/AST/Functions/JsonbSet.php | 24 ++++--- .../ORM/Query/AST/Functions/Least.php | 15 +---- .../Doctrine/ORM/Query/AST/Functions/Row.php | 19 +++--- .../ORM/Query/AST/Functions/RowToJson.php | 24 ++++--- .../ORM/Query/AST/Functions/ToTsquery.php | 19 +++--- .../ORM/Query/AST/Functions/ToTsvector.php | 19 +++--- .../ORM/Query/AST/Functions/Unaccent.php | 19 +++--- .../Query/AST/Functions/ArrayToJsonTest.php | 2 +- .../BaseVariadicFunctionTestCase.php | 42 ++++++++++++ .../ORM/Query/AST/Functions/DateAddTest.php | 4 +- .../Query/AST/Functions/DateSubtractTest.php | 4 +- .../ORM/Query/AST/Functions/GreatestTest.php | 8 +-- .../Query/AST/Functions/JsonbInsertTest.php | 4 +- .../AST/Functions/JsonbPathExistsTest.php | 4 +- .../AST/Functions/JsonbPathMatchTest.php | 4 +- .../AST/Functions/JsonbPathQueryArrayTest.php | 4 +- .../AST/Functions/JsonbPathQueryFirstTest.php | 4 +- .../AST/Functions/JsonbPathQueryTest.php | 4 +- .../ORM/Query/AST/Functions/JsonbSetTest.php | 4 +- .../ORM/Query/AST/Functions/LeastTest.php | 8 +-- .../ORM/Query/AST/Functions/RowToJsonTest.php | 2 +- 37 files changed, 388 insertions(+), 234 deletions(-) create mode 100644 tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunctionTestCase.php diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Arr.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Arr.php index 533cd141..c203e5c3 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Arr.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Arr.php @@ -4,9 +4,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; -use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; - /** * Implementation of PostgreSQL ARRAY[]. * @@ -22,16 +19,23 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } + protected function getFunctionName(): string + { + return 'ARRAY'; + } + protected function customizeFunction(): void { - $this->setFunctionPrototype('ARRAY[%s]'); + $this->setFunctionPrototype(\sprintf('%s[%%s]', $this->getFunctionName())); + } + + protected function getMinArgumentCount(): int + { + return 1; } - protected function validateArguments(Node ...$arguments): void + protected function getMaxArgumentCount(): int { - $argumentCount = \count($arguments); - if ($argumentCount === 0) { - throw InvalidArgumentForVariadicFunctionException::atLeast('ARRAY', 1); - } + return PHP_INT_MAX; // No upper limit } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJson.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJson.php index 05c16deb..191a1151 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJson.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJson.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\BooleanValidationTrait; /** @@ -31,21 +30,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('array_to_json(%s)'); + return 'array_to_json'; + } + + protected function getMinArgumentCount(): int + { + return 1; + } + + protected function getMaxArgumentCount(): int + { + return 2; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 1 || $argumentCount > 2) { - throw InvalidArgumentForVariadicFunctionException::between('array_to_json', 1, 2); - } + parent::validateArguments(...$arguments); // Validate that the second parameter is a valid boolean if provided - if ($argumentCount === 2) { - $this->validateBoolean($arguments[1], 'ARRAY_TO_JSON'); + if (\count($arguments) === 2) { + $this->validateBoolean($arguments[1], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseComparisonFunction.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseComparisonFunction.php index 225ae271..8795c3d8 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseComparisonFunction.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseComparisonFunction.php @@ -15,4 +15,19 @@ protected function getNodeMappingPattern(): array { return ['SimpleArithmeticExpression']; } + + protected function customizeFunction(): void + { + $this->setFunctionPrototype(\sprintf('%s(%%s)', $this->getFunctionName())); + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return PHP_INT_MAX; // No hard limit apart the PHP internals + } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php index 6df0345c..7e521b9e 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php @@ -19,14 +19,22 @@ */ abstract class BaseVariadicFunction extends BaseFunction { + protected function customizeFunction(): void + { + $this->setFunctionPrototype(\sprintf('%s(%%s)', $this->getFunctionName())); + } + + abstract protected function getFunctionName(): string; + /** - * @return array + * @return array */ abstract protected function getNodeMappingPattern(): array; - /** - * @throws ParserException - */ + abstract protected function getMinArgumentCount(): int; + + abstract protected function getMaxArgumentCount(): int; + protected function feedParserWithNodes(Parser $parser): void { foreach ($this->getNodeMappingPattern() as $nodeMappingPattern) { @@ -38,10 +46,12 @@ protected function feedParserWithNodes(Parser $parser): void // swallow and continue with next pattern } } - - $this->validateArguments(...$this->nodes); // @phpstan-ignore-line } + /** + * @throws InvalidArgumentForVariadicFunctionException + * @throws ParserException + */ private function feedParserWithNodesForNodeMappingPattern(Parser $parser, string $nodeMappingPattern): void { $nodeMapping = \explode(',', $nodeMappingPattern); @@ -52,7 +62,7 @@ private function feedParserWithNodesForNodeMappingPattern(Parser $parser, string $this->nodes[] = $parser->{$nodeMapping[0]}(); $lookaheadType = DoctrineLexer::getLookaheadType($lexer); if ($lookaheadType === null) { - throw ParserException::missingLookaheadType(); + throw InvalidArgumentForVariadicFunctionException::atLeast($this->getFunctionName(), $this->getMinArgumentCount()); } } catch (\Throwable $throwable) { throw ParserException::withThrowable($throwable); @@ -64,13 +74,43 @@ private function feedParserWithNodesForNodeMappingPattern(Parser $parser, string while (($shouldUseLexer ? Lexer::T_CLOSE_PARENTHESIS : TokenType::T_CLOSE_PARENTHESIS) !== $lookaheadType) { if (($shouldUseLexer ? Lexer::T_COMMA : TokenType::T_COMMA) === $lookaheadType) { $parser->match($shouldUseLexer ? Lexer::T_COMMA : TokenType::T_COMMA); - // @phpstan-ignore-next-line - $this->nodes[] = $parser->{$nodeMapping[$isNodeMappingASimplePattern ? 0 : $nodeIndex]}(); + + // Check if we're about to exceed the maximum number of arguments + // nodeIndex starts at 1 and counts up for each argument after the first + // So when nodeIndex=1, we're about to add the 2nd argument (total: 2) + // When nodeIndex=2, we're about to add the 3rd argument (total: 3) + $foundMoreNodesThanMappingExpected = ($nodeIndex + 1) > $this->getMaxArgumentCount(); + if ($foundMoreNodesThanMappingExpected) { + throw InvalidArgumentForVariadicFunctionException::between($this->getFunctionName(), $this->getMinArgumentCount(), $this->getMaxArgumentCount()); + } + + $expectedNodeIndex = $isNodeMappingASimplePattern ? 0 : $nodeIndex; + $this->nodes[] = $parser->{$nodeMapping[$expectedNodeIndex]}(); // @phpstan-ignore-line $nodeIndex++; } $lookaheadType = DoctrineLexer::getLookaheadType($lexer); } + + $this->validateArguments(...$this->nodes); // @phpstan-ignore-line + } + + /** + * @throws InvalidArgumentForVariadicFunctionException + */ + protected function validateArguments(Node ...$arguments): void + { + $minArgumentCount = $this->getMinArgumentCount(); + $maxArgumentCount = $this->getMaxArgumentCount(); + $argumentCount = \count($arguments); + + if ($argumentCount < $minArgumentCount) { + throw InvalidArgumentForVariadicFunctionException::atLeast($this->getFunctionName(), $this->getMinArgumentCount()); + } + + if ($argumentCount > $maxArgumentCount) { + throw InvalidArgumentForVariadicFunctionException::between($this->getFunctionName(), $this->getMinArgumentCount(), $this->getMaxArgumentCount()); + } } public function getSql(SqlWalker $sqlWalker): string @@ -82,11 +122,4 @@ public function getSql(SqlWalker $sqlWalker): string return \sprintf($this->functionPrototype, \implode(', ', $dispatched)); } - - /** - * Validates the arguments passed to the function. - * - * @throws InvalidArgumentForVariadicFunctionException - */ - abstract protected function validateArguments(Node ...$arguments): void; } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAdd.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAdd.php index 72904239..6526c0a2 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAdd.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAdd.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\TimezoneValidationTrait; /** @@ -30,21 +29,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('date_add(%s)'); + return 'date_add'; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 3; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 2 || $argumentCount > 3) { - throw InvalidArgumentForVariadicFunctionException::between('date_add', 2, 3); - } + parent::validateArguments(...$arguments); // Validate that the third parameter is a valid timezone if provided - if ($argumentCount === 3) { - $this->validateTimezone($arguments[2], 'DATE_ADD'); + if (\count($arguments) === 3) { + $this->validateTimezone($arguments[2], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtract.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtract.php index 8a5c917d..50e9f9c5 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtract.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtract.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\TimezoneValidationTrait; /** @@ -30,21 +29,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('date_subtract(%s)'); + return 'date_subtract'; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 3; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 2 || $argumentCount > 3) { - throw InvalidArgumentForVariadicFunctionException::between('date_subtract', 2, 3); - } + parent::validateArguments(...$arguments); // Validate that the third parameter is a valid timezone if provided - if ($argumentCount === 3) { - $this->validateTimezone($arguments[2], 'DATE_SUBTRACT'); + if (\count($arguments) === 3) { + $this->validateTimezone($arguments[2], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidArgumentForVariadicFunctionException.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidArgumentForVariadicFunctionException.php index 74b787b4..6bf3e868 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidArgumentForVariadicFunctionException.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidArgumentForVariadicFunctionException.php @@ -43,4 +43,14 @@ public static function evenNumber(string $functionName): self $functionName )); } + + public static function unsupportedCombination(string $functionName, int $count, string $note): self + { + return new self(\sprintf( + '%s() cannot be called with %d arguments, because %s', + $functionName, + $count, + $note, + )); + } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Greatest.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Greatest.php index 89a07cf8..fbf252bd 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Greatest.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Greatest.php @@ -4,9 +4,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; -use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; - /** * Implementation of PostgreSQL GREATEST(). * @@ -17,16 +14,8 @@ */ class Greatest extends BaseComparisonFunction { - protected function customizeFunction(): void - { - $this->setFunctionPrototype('greatest(%s)'); - } - - protected function validateArguments(Node ...$arguments): void + protected function getFunctionName(): string { - $argumentCount = \count($arguments); - if ($argumentCount < 2) { - throw InvalidArgumentForVariadicFunctionException::atLeast('greatest', 2); - } + return 'greatest'; } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonBuildObject.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonBuildObject.php index b89e9a60..39ab8ea6 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonBuildObject.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonBuildObject.php @@ -22,16 +22,27 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('json_build_object(%s)'); + return 'json_build_object'; + } + + protected function getMinArgumentCount(): int + { + return 2; // At least one key-value pair + } + + protected function getMaxArgumentCount(): int + { + return PHP_INT_MAX; // No upper limit, but must be even } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount === 0 || $argumentCount % 2 !== 0) { - throw InvalidArgumentForVariadicFunctionException::evenNumber('json_build_object'); + parent::validateArguments(...$arguments); + + if (\count($arguments) % 2 !== 0) { + throw InvalidArgumentForVariadicFunctionException::evenNumber($this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbBuildObject.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbBuildObject.php index 8ca5192c..b8bf0103 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbBuildObject.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbBuildObject.php @@ -22,16 +22,27 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('jsonb_build_object(%s)'); + return 'jsonb_build_object'; + } + + protected function getMinArgumentCount(): int + { + return 2; // At least one key-value pair + } + + protected function getMaxArgumentCount(): int + { + return PHP_INT_MAX; // No upper limit, but must be even } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount === 0 || $argumentCount % 2 !== 0) { - throw InvalidArgumentForVariadicFunctionException::evenNumber('jsonb_build_object'); + parent::validateArguments(...$arguments); + + if (\count($arguments) % 2 !== 0) { + throw InvalidArgumentForVariadicFunctionException::evenNumber($this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsert.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsert.php index 44e70e11..9d788f9a 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsert.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsert.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\BooleanValidationTrait; /** @@ -31,21 +30,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('jsonb_insert(%s)'); + return 'jsonb_insert'; + } + + protected function getMinArgumentCount(): int + { + return 3; + } + + protected function getMaxArgumentCount(): int + { + return 4; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 3 || $argumentCount > 4) { - throw InvalidArgumentForVariadicFunctionException::between('jsonb_insert', 3, 4); - } + parent::validateArguments(...$arguments); // Validate that the fourth parameter is a valid boolean if provided - if ($argumentCount === 4) { - $this->validateBoolean($arguments[3], 'JSONB_INSERT'); + if (\count($arguments) === 4) { + $this->validateBoolean($arguments[3], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExists.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExists.php index cd2a5230..6454bc8c 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExists.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExists.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\BooleanValidationTrait; /** @@ -29,21 +28,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('jsonb_path_exists(%s)'); + return 'jsonb_path_exists'; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 4; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 2 || $argumentCount > 4) { - throw InvalidArgumentForVariadicFunctionException::between('jsonb_path_exists', 2, 4); - } + parent::validateArguments(...$arguments); // Validate that the fourth parameter is a valid boolean if provided - if ($argumentCount === 4) { - $this->validateBoolean($arguments[3], 'JSONB_PATH_EXISTS'); + if (\count($arguments) === 4) { + $this->validateBoolean($arguments[3], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatch.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatch.php index dec46af7..d3aa09e2 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatch.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatch.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\BooleanValidationTrait; /** @@ -31,21 +30,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('jsonb_path_match(%s)'); + return 'jsonb_path_match'; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 4; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 2 || $argumentCount > 4) { - throw InvalidArgumentForVariadicFunctionException::between('jsonb_path_match', 2, 4); - } + parent::validateArguments(...$arguments); // Validate that the fourth parameter is a valid boolean if provided - if ($argumentCount === 4) { - $this->validateBoolean($arguments[3], 'JSONB_PATH_MATCH'); + if (\count($arguments) === 4) { + $this->validateBoolean($arguments[3], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQuery.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQuery.php index c3535842..e6f8cba9 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQuery.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQuery.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\BooleanValidationTrait; /** @@ -30,21 +29,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('jsonb_path_query(%s)'); + return 'jsonb_path_query'; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 4; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 2 || $argumentCount > 4) { - throw InvalidArgumentForVariadicFunctionException::between('jsonb_path_query', 2, 4); - } + parent::validateArguments(...$arguments); // Validate that the fourth parameter is a valid boolean if provided - if ($argumentCount === 4) { - $this->validateBoolean($arguments[3], 'JSONB_PATH_QUERY'); + if (\count($arguments) === 4) { + $this->validateBoolean($arguments[3], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArray.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArray.php index 9bd2ad64..db6df603 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArray.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArray.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\BooleanValidationTrait; /** @@ -29,21 +28,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('jsonb_path_query_array(%s)'); + return 'jsonb_path_query_array'; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 4; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 2 || $argumentCount > 4) { - throw InvalidArgumentForVariadicFunctionException::between('jsonb_path_query_array', 2, 4); - } + parent::validateArguments(...$arguments); // Validate that the fourth parameter is a valid boolean if provided - if ($argumentCount === 4) { - $this->validateBoolean($arguments[3], 'JSONB_PATH_QUERY_ARRAY'); + if (\count($arguments) === 4) { + $this->validateBoolean($arguments[3], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirst.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirst.php index ad3af1d2..11bfd365 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirst.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirst.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\BooleanValidationTrait; /** @@ -30,21 +29,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('jsonb_path_query_first(%s)'); + return 'jsonb_path_query_first'; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 4; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 2 || $argumentCount > 4) { - throw InvalidArgumentForVariadicFunctionException::between('jsonb_path_query_first', 2, 4); - } + parent::validateArguments(...$arguments); // Validate that the fourth parameter is a valid boolean if provided - if ($argumentCount === 4) { - $this->validateBoolean($arguments[3], 'JSONB_PATH_QUERY_FIRST'); + if (\count($arguments) === 4) { + $this->validateBoolean($arguments[3], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSet.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSet.php index bb499506..5965fa19 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSet.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSet.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\BooleanValidationTrait; /** @@ -35,21 +34,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('jsonb_set(%s)'); + return 'jsonb_set'; + } + + protected function getMinArgumentCount(): int + { + return 3; + } + + protected function getMaxArgumentCount(): int + { + return 4; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 3 || $argumentCount > 4) { - throw InvalidArgumentForVariadicFunctionException::between('jsonb_set', 3, 4); - } + parent::validateArguments(...$arguments); // Validate that the fourth parameter is a valid boolean if provided - if ($argumentCount === 4) { - $this->validateBoolean($arguments[3], 'JSONB_SET'); + if (\count($arguments) === 4) { + $this->validateBoolean($arguments[3], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Least.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Least.php index b52e1f79..238a5c75 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Least.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Least.php @@ -4,9 +4,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; -use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; - /** * Implementation of PostgreSQL LEAST(). * @@ -17,16 +14,8 @@ */ class Least extends BaseComparisonFunction { - protected function customizeFunction(): void - { - $this->setFunctionPrototype('least(%s)'); - } - - protected function validateArguments(Node ...$arguments): void + protected function getFunctionName(): string { - $argumentCount = \count($arguments); - if ($argumentCount < 2) { - throw InvalidArgumentForVariadicFunctionException::atLeast('least', 2); - } + return 'least'; } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Row.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Row.php index e04dcdd2..df583f51 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Row.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Row.php @@ -4,9 +4,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; -use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; - /** * Implementation of PostgreSQL Row Constructor expression. * @@ -19,16 +16,18 @@ protected function getNodeMappingPattern(): array return ['InParameter']; } - protected function customizeFunction(): void + protected function getFunctionName(): string + { + return 'ROW'; + } + + protected function getMinArgumentCount(): int { - $this->setFunctionPrototype('ROW(%s)'); + return 1; } - protected function validateArguments(Node ...$arguments): void + protected function getMaxArgumentCount(): int { - $argumentCount = \count($arguments); - if ($argumentCount === 0) { - throw InvalidArgumentForVariadicFunctionException::atLeast('ROW', 1); - } + return PHP_INT_MAX; // No upper limit } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJson.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJson.php index 83213fb7..56ed6802 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJson.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJson.php @@ -5,7 +5,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Traits\BooleanValidationTrait; /** @@ -30,21 +29,28 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('row_to_json(%s)'); + return 'row_to_json'; + } + + protected function getMinArgumentCount(): int + { + return 1; + } + + protected function getMaxArgumentCount(): int + { + return 2; } protected function validateArguments(Node ...$arguments): void { - $argumentCount = \count($arguments); - if ($argumentCount < 1 || $argumentCount > 2) { - throw InvalidArgumentForVariadicFunctionException::between('row_to_json', 1, 2); - } + parent::validateArguments(...$arguments); // Validate that the second parameter is a valid boolean if provided - if ($argumentCount === 2) { - $this->validateBoolean($arguments[1], 'ROW_TO_JSON'); + if (\count($arguments) === 2) { + $this->validateBoolean($arguments[1], $this->getFunctionName()); } } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsquery.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsquery.php index 265b844d..dbf149f7 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsquery.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsquery.php @@ -4,9 +4,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; -use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; - /** * Implementation of PostgreSQL TO_TSQUERY(). * @@ -22,16 +19,18 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string + { + return 'to_tsquery'; + } + + protected function getMinArgumentCount(): int { - $this->setFunctionPrototype('to_tsquery(%s)'); + return 1; } - protected function validateArguments(Node ...$arguments): void + protected function getMaxArgumentCount(): int { - $argumentCount = \count($arguments); - if ($argumentCount < 1 || $argumentCount > 2) { - throw InvalidArgumentForVariadicFunctionException::between('to_tsquery', 1, 2); - } + return 2; } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsvector.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsvector.php index 444436a0..12e79102 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsvector.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsvector.php @@ -4,9 +4,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; -use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; - /** * Implementation of PostgreSQL TO_TSVECTOR(). * @@ -22,16 +19,18 @@ protected function getNodeMappingPattern(): array return ['StringExpression']; } - protected function customizeFunction(): void + protected function getFunctionName(): string + { + return 'to_tsvector'; + } + + protected function getMinArgumentCount(): int { - $this->setFunctionPrototype('to_tsvector(%s)'); + return 1; } - protected function validateArguments(Node ...$arguments): void + protected function getMaxArgumentCount(): int { - $argumentCount = \count($arguments); - if ($argumentCount < 1 || $argumentCount > 2) { - throw InvalidArgumentForVariadicFunctionException::between('to_tsvector', 1, 2); - } + return 2; } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Unaccent.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Unaccent.php index 3d92433f..0d1a0f4a 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Unaccent.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Unaccent.php @@ -4,9 +4,6 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; -use Doctrine\ORM\Query\AST\Node; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; - /** * Implementation of PostgreSQL UNACCENT. * @@ -21,16 +18,18 @@ protected function getNodeMappingPattern(): array return ['StringPrimary']; } - protected function customizeFunction(): void + protected function getFunctionName(): string + { + return 'unaccent'; + } + + protected function getMinArgumentCount(): int { - $this->setFunctionPrototype('unaccent(%s)'); + return 1; } - protected function validateArguments(Node ...$arguments): void + protected function getMaxArgumentCount(): int { - $argumentCount = \count($arguments); - if ($argumentCount < 1 || $argumentCount > 2) { - throw InvalidArgumentForVariadicFunctionException::between('unaccent', 1, 2); - } + return 2; } } diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJsonTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJsonTest.php index 987c0e3c..cc153a03 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJsonTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJsonTest.php @@ -37,7 +37,7 @@ protected function getDqlStatements(): array public function test_invalid_boolean_throws_exception(): void { $this->expectException(InvalidBooleanException::class); - $this->expectExceptionMessage('Invalid boolean value "invalid" provided for ARRAY_TO_JSON. Must be "true" or "false".'); + $this->expectExceptionMessage('Invalid boolean value "invalid" provided for array_to_json. Must be "true" or "false".'); $dql = \sprintf("SELECT ARRAY_TO_JSON(e.array1, 'invalid') FROM %s e", ContainsArrays::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunctionTestCase.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunctionTestCase.php new file mode 100644 index 00000000..18a0e1ee --- /dev/null +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunctionTestCase.php @@ -0,0 +1,42 @@ +expectException(InvalidArgumentForVariadicFunctionException::class); + + $em = $this->createMock(EntityManager::class); + $em->expects($this->any()) + ->method('getConfiguration') + ->willReturn(new Configuration()); + + $query = new Query($em); + $query->setDQL('TRUE'); + + $parser = new Parser($query); + $parser->getLexer()->moveNext(); + + $baseVariadicFunction = $this->createFixture(); + + $reflectionMethod = new \ReflectionMethod($baseVariadicFunction::class, 'feedParserWithNodesForNodeMappingPattern'); + $reflectionMethod->setAccessible(true); + $reflectionMethod->invoke($baseVariadicFunction, $parser, 'ArithmeticPrimary'); + } +} diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAddTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAddTest.php index 67ecad2f..46f7fb19 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAddTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAddTest.php @@ -41,7 +41,7 @@ protected function getDqlStatements(): array public function test_invalid_timezone_throws_exception(): void { $this->expectException(InvalidTimezoneException::class); - $this->expectExceptionMessage('Invalid timezone "Invalid/Timezone" provided for DATE_ADD'); + $this->expectExceptionMessage('Invalid timezone "Invalid/Timezone" provided for date_add'); $dql = \sprintf("SELECT DATE_ADD(e.datetimetz1, '1 day', 'Invalid/Timezone') FROM %s e", ContainsDates::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); @@ -50,7 +50,7 @@ public function test_invalid_timezone_throws_exception(): void public function test_too_few_arguments_throws_exception(): void { $this->expectException(InvalidArgumentForVariadicFunctionException::class); - $this->expectExceptionMessage('date_add() requires between 2 and 3 arguments'); + $this->expectExceptionMessage('date_add() requires at least 2 arguments'); $dql = \sprintf('SELECT DATE_ADD(e.datetimetz1) FROM %s e', ContainsDates::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtractTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtractTest.php index 73f1409a..57720c32 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtractTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtractTest.php @@ -39,7 +39,7 @@ protected function getDqlStatements(): array public function test_invalid_timezone_throws_exception(): void { $this->expectException(InvalidTimezoneException::class); - $this->expectExceptionMessage('Invalid timezone "Invalid/Timezone" provided for DATE_SUBTRACT'); + $this->expectExceptionMessage('Invalid timezone "Invalid/Timezone" provided for date_subtract'); $dql = \sprintf("SELECT DATE_SUBTRACT(e.datetimetz1, '1 day', 'Invalid/Timezone') FROM %s e", ContainsDates::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); @@ -48,7 +48,7 @@ public function test_invalid_timezone_throws_exception(): void public function test_too_few_arguments_throws_exception(): void { $this->expectException(InvalidArgumentForVariadicFunctionException::class); - $this->expectExceptionMessage('date_subtract() requires between 2 and 3 arguments'); + $this->expectExceptionMessage('date_subtract() requires at least 2 arguments'); $dql = \sprintf('SELECT DATE_SUBTRACT(e.datetimetz1) FROM %s e', ContainsDates::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/GreatestTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/GreatestTest.php index 2f9c3fe6..53b7aa38 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/GreatestTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/GreatestTest.php @@ -5,17 +5,11 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsIntegers; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseComparisonFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Greatest; -class GreatestTest extends BaseComparisonFunctionTestCase +class GreatestTest extends TestCase { - protected function createFixture(): BaseComparisonFunction - { - return new Greatest('greatest'); - } - protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php index be2e3160..2ee8302e 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php @@ -37,7 +37,7 @@ protected function getDqlStatements(): array public function test_invalid_boolean_throws_exception(): void { $this->expectException(InvalidBooleanException::class); - $this->expectExceptionMessage('Invalid boolean value "invalid" provided for JSONB_INSERT. Must be "true" or "false".'); + $this->expectExceptionMessage('Invalid boolean value "invalid" provided for jsonb_insert. Must be "true" or "false".'); $dql = \sprintf("SELECT JSONB_INSERT(e.object1, '{country}', '{\"iso_3166_a3_code\":\"bgr\"}', 'invalid') FROM %s e", ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); @@ -46,7 +46,7 @@ public function test_invalid_boolean_throws_exception(): void public function test_too_few_arguments_throws_exception(): void { $this->expectException(InvalidArgumentForVariadicFunctionException::class); - $this->expectExceptionMessage('jsonb_insert() requires between 3 and 4 arguments'); + $this->expectExceptionMessage('jsonb_insert() requires at least 3 arguments'); $dql = \sprintf('SELECT JSONB_INSERT(e.object1) FROM %s e', ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExistsTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExistsTest.php index b594a7ab..b0eb091c 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExistsTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExistsTest.php @@ -41,7 +41,7 @@ protected function getDqlStatements(): array public function test_invalid_boolean_throws_exception(): void { $this->expectException(InvalidBooleanException::class); - $this->expectExceptionMessage('Invalid boolean value "invalid" provided for JSONB_PATH_EXISTS. Must be "true" or "false".'); + $this->expectExceptionMessage('Invalid boolean value "invalid" provided for jsonb_path_exists. Must be "true" or "false".'); $dql = \sprintf("SELECT JSONB_PATH_EXISTS(e.object1, '$.items[*].id', '{\"strict\": false}', 'invalid') FROM %s e", ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); @@ -50,7 +50,7 @@ public function test_invalid_boolean_throws_exception(): void public function test_too_few_arguments_throws_exception(): void { $this->expectException(InvalidArgumentForVariadicFunctionException::class); - $this->expectExceptionMessage('jsonb_path_exists() requires between 2 and 4 arguments'); + $this->expectExceptionMessage('jsonb_path_exists() requires at least 2 arguments'); $dql = \sprintf('SELECT JSONB_PATH_EXISTS(e.object1) FROM %s e', ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatchTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatchTest.php index 8bfb46b4..1e45cb4c 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatchTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatchTest.php @@ -41,7 +41,7 @@ protected function getDqlStatements(): array public function test_invalid_boolean_throws_exception(): void { $this->expectException(InvalidBooleanException::class); - $this->expectExceptionMessage('Invalid boolean value "invalid" provided for JSONB_PATH_MATCH. Must be "true" or "false".'); + $this->expectExceptionMessage('Invalid boolean value "invalid" provided for jsonb_path_match. Must be "true" or "false".'); $dql = \sprintf("SELECT JSONB_PATH_MATCH(e.object1, '$.items[*].id', '{\"strict\": false}', 'invalid') FROM %s e", ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); @@ -50,7 +50,7 @@ public function test_invalid_boolean_throws_exception(): void public function test_too_few_arguments_throws_exception(): void { $this->expectException(InvalidArgumentForVariadicFunctionException::class); - $this->expectExceptionMessage('jsonb_path_match() requires between 2 and 4 arguments'); + $this->expectExceptionMessage('jsonb_path_match() requires at least 2 arguments'); $dql = \sprintf('SELECT JSONB_PATH_MATCH(e.object1) FROM %s e', ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php index 440d21f7..4aebb220 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php @@ -41,7 +41,7 @@ protected function getDqlStatements(): array public function test_invalid_boolean_throws_exception(): void { $this->expectException(InvalidBooleanException::class); - $this->expectExceptionMessage('Invalid boolean value "invalid" provided for JSONB_PATH_QUERY_ARRAY. Must be "true" or "false".'); + $this->expectExceptionMessage('Invalid boolean value "invalid" provided for jsonb_path_query_array. Must be "true" or "false".'); $dql = \sprintf("SELECT JSONB_PATH_QUERY_ARRAY(e.object1, '$.items[*].id', '{\"strict\": false}', 'invalid') FROM %s e", ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); @@ -50,7 +50,7 @@ public function test_invalid_boolean_throws_exception(): void public function test_too_few_arguments_throws_exception(): void { $this->expectException(InvalidArgumentForVariadicFunctionException::class); - $this->expectExceptionMessage('jsonb_path_query_array() requires between 2 and 4 arguments'); + $this->expectExceptionMessage('jsonb_path_query_array() requires at least 2 arguments'); $dql = \sprintf('SELECT JSONB_PATH_QUERY_ARRAY(e.object1) FROM %s e', ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php index 9a467ab5..4147f490 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php @@ -41,7 +41,7 @@ protected function getDqlStatements(): array public function test_invalid_boolean_throws_exception(): void { $this->expectException(InvalidBooleanException::class); - $this->expectExceptionMessage('Invalid boolean value "invalid" provided for JSONB_PATH_QUERY_FIRST. Must be "true" or "false".'); + $this->expectExceptionMessage('Invalid boolean value "invalid" provided for jsonb_path_query_first. Must be "true" or "false".'); $dql = \sprintf("SELECT JSONB_PATH_QUERY_FIRST(e.object1, '$.items[*].id', '{\"strict\": false}', 'invalid') FROM %s e", ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); @@ -50,7 +50,7 @@ public function test_invalid_boolean_throws_exception(): void public function test_too_few_arguments_throws_exception(): void { $this->expectException(InvalidArgumentForVariadicFunctionException::class); - $this->expectExceptionMessage('jsonb_path_query_first() requires between 2 and 4 arguments'); + $this->expectExceptionMessage('jsonb_path_query_first() requires at least 2 arguments'); $dql = \sprintf('SELECT JSONB_PATH_QUERY_FIRST(e.object1) FROM %s e', ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php index 1b470eb1..08790953 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php @@ -41,7 +41,7 @@ protected function getDqlStatements(): array public function test_invalid_boolean_throws_exception(): void { $this->expectException(InvalidBooleanException::class); - $this->expectExceptionMessage('Invalid boolean value "invalid" provided for JSONB_PATH_QUERY. Must be "true" or "false".'); + $this->expectExceptionMessage('Invalid boolean value "invalid" provided for jsonb_path_query. Must be "true" or "false".'); $dql = \sprintf("SELECT JSONB_PATH_QUERY(e.object1, '$.items[*].id', '{\"strict\": false}', 'invalid') FROM %s e", ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); @@ -50,7 +50,7 @@ public function test_invalid_boolean_throws_exception(): void public function test_too_few_arguments_throws_exception(): void { $this->expectException(InvalidArgumentForVariadicFunctionException::class); - $this->expectExceptionMessage('jsonb_path_query() requires between 2 and 4 arguments'); + $this->expectExceptionMessage('jsonb_path_query() requires at least 2 arguments'); $dql = \sprintf('SELECT JSONB_PATH_QUERY(e.object1) FROM %s e', ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php index edbcf998..cf133638 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php @@ -37,7 +37,7 @@ protected function getDqlStatements(): array public function test_invalid_boolean_throws_exception(): void { $this->expectException(InvalidBooleanException::class); - $this->expectExceptionMessage('Invalid boolean value "invalid" provided for JSONB_SET. Must be "true" or "false".'); + $this->expectExceptionMessage('Invalid boolean value "invalid" provided for jsonb_set. Must be "true" or "false".'); $dql = \sprintf("SELECT JSONB_SET(e.object1, '{country}', '{\"iso_3166_a3_code\":\"bgr\"}', 'invalid') FROM %s e", ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); @@ -46,7 +46,7 @@ public function test_invalid_boolean_throws_exception(): void public function test_too_few_arguments_throws_exception(): void { $this->expectException(InvalidArgumentForVariadicFunctionException::class); - $this->expectExceptionMessage('jsonb_set() requires between 3 and 4 arguments'); + $this->expectExceptionMessage('jsonb_set() requires at least 3 arguments'); $dql = \sprintf('SELECT JSONB_SET(e.object1) FROM %s e', ContainsJsons::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LeastTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LeastTest.php index 6d99df1c..71b1ad1c 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LeastTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LeastTest.php @@ -5,17 +5,11 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsIntegers; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseComparisonFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Least; -class LeastTest extends BaseComparisonFunctionTestCase +class LeastTest extends TestCase { - protected function createFixture(): BaseComparisonFunction - { - return new Least('least'); - } - protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJsonTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJsonTest.php index 74a64080..d60b73d2 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJsonTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJsonTest.php @@ -39,7 +39,7 @@ protected function getDqlStatements(): array public function test_invalid_boolean_throws_exception(): void { $this->expectException(InvalidBooleanException::class); - $this->expectExceptionMessage('Invalid boolean value "invalid" provided for ROW_TO_JSON. Must be "true" or "false".'); + $this->expectExceptionMessage('Invalid boolean value "invalid" provided for row_to_json. Must be "true" or "false".'); $dql = \sprintf("SELECT ROW_TO_JSON(e.text1, 'invalid') FROM %s e", ContainsTexts::class); $this->buildEntityManager()->createQuery($dql)->getSQL(); From e53af4acbd8092afd4e54a4868649b412a853be8 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Fri, 18 Apr 2025 00:50:16 +0100 Subject: [PATCH 2/5] no message --- .../BaseComparisonFunctionTestCase.php | 42 ------------------- 1 file changed, 42 deletions(-) delete mode 100644 tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseComparisonFunctionTestCase.php diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseComparisonFunctionTestCase.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseComparisonFunctionTestCase.php deleted file mode 100644 index ad1974d7..00000000 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseComparisonFunctionTestCase.php +++ /dev/null @@ -1,42 +0,0 @@ -expectException(InvalidArgumentForVariadicFunctionException::class); - - $em = $this->createMock(EntityManager::class); - $em->expects($this->any()) - ->method('getConfiguration') - ->willReturn(new Configuration()); - - $query = new Query($em); - $query->setDQL('TRUE'); - - $parser = new Parser($query); - $parser->getLexer()->moveNext(); - - $baseComparisonFunction = $this->createFixture(); - - $reflectionMethod = new \ReflectionMethod($baseComparisonFunction::class, 'feedParserWithNodes'); - $reflectionMethod->setAccessible(true); - $reflectionMethod->invoke($baseComparisonFunction, $parser); - } -} From 2d95734960f0678af885d0f0fc34040d7a14b48e Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Fri, 18 Apr 2025 23:13:50 +0100 Subject: [PATCH 3/5] no message --- .../Function/TestVariadicFunction.php | 39 +++++++++++++++++++ .../AST/Functions/BaseComparisonFunction.php | 5 --- .../AST/Functions/BaseVariadicFunction.php | 4 +- .../ORM/Query/AST/Functions/ArrTest.php | 8 +++- .../Query/AST/Functions/ArrayToJsonTest.php | 8 +++- .../BaseVariadicFunctionTestCase.php | 4 +- .../ORM/Query/AST/Functions/DateAddTest.php | 8 +++- .../Query/AST/Functions/DateSubtractTest.php | 8 +++- .../ORM/Query/AST/Functions/GreatestTest.php | 8 +++- .../AST/Functions/JsonBuildObjectTest.php | 8 +++- .../AST/Functions/JsonbBuildObjectTest.php | 8 +++- .../AST/Functions/JsonbPathExistsTest.php | 8 +++- .../AST/Functions/JsonbPathMatchTest.php | 8 +++- .../AST/Functions/JsonbPathQueryArrayTest.php | 8 +++- .../AST/Functions/JsonbPathQueryFirstTest.php | 8 +++- .../AST/Functions/JsonbPathQueryTest.php | 8 +++- .../ORM/Query/AST/Functions/JsonbSetTest.php | 8 +++- .../ORM/Query/AST/Functions/LeastTest.php | 8 +++- .../ORM/Query/AST/Functions/RowTest.php | 8 +++- .../ORM/Query/AST/Functions/RowToJsonTest.php | 8 +++- .../ORM/Query/AST/Functions/ToTsqueryTest.php | 8 +++- .../Query/AST/Functions/ToTsvectorTest.php | 8 +++- .../ORM/Query/AST/Functions/UnaccentTest.php | 8 +++- 23 files changed, 176 insertions(+), 28 deletions(-) create mode 100644 fixtures/MartinGeorgiev/Doctrine/Function/TestVariadicFunction.php diff --git a/fixtures/MartinGeorgiev/Doctrine/Function/TestVariadicFunction.php b/fixtures/MartinGeorgiev/Doctrine/Function/TestVariadicFunction.php new file mode 100644 index 00000000..bed4cc69 --- /dev/null +++ b/fixtures/MartinGeorgiev/Doctrine/Function/TestVariadicFunction.php @@ -0,0 +1,39 @@ +setFunctionPrototype(\sprintf('%s(%%s)', $this->getFunctionName())); - } - protected function getMinArgumentCount(): int { return 2; diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php index 7e521b9e..72c4fbc0 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php @@ -58,12 +58,12 @@ private function feedParserWithNodesForNodeMappingPattern(Parser $parser, string $lexer = $parser->getLexer(); try { - // @phpstan-ignore-next-line - $this->nodes[] = $parser->{$nodeMapping[0]}(); $lookaheadType = DoctrineLexer::getLookaheadType($lexer); if ($lookaheadType === null) { throw InvalidArgumentForVariadicFunctionException::atLeast($this->getFunctionName(), $this->getMinArgumentCount()); } + + $this->nodes[] = $parser->{$nodeMapping[0]}(); // @phpstan-ignore-line } catch (\Throwable $throwable) { throw ParserException::withThrowable($throwable); } diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrTest.php index f3e6285b..550e0024 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrTest.php @@ -6,9 +6,15 @@ use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsArrays; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Arr; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; -class ArrTest extends TestCase +class ArrTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new Arr('ARRAY'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJsonTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJsonTest.php index cc153a03..ad279474 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJsonTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayToJsonTest.php @@ -6,11 +6,17 @@ use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsArrays; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayToJson; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidBooleanException; -class ArrayToJsonTest extends TestCase +class ArrayToJsonTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new ArrayToJson('ARRAY_TO_JSON'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunctionTestCase.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunctionTestCase.php index 18a0e1ee..d262b1ff 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunctionTestCase.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunctionTestCase.php @@ -9,7 +9,7 @@ use Doctrine\ORM\Query; use Doctrine\ORM\Query\Parser; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; -use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\ParserException; abstract class BaseVariadicFunctionTestCase extends TestCase { @@ -20,7 +20,7 @@ abstract protected function createFixture(): BaseVariadicFunction; */ public function throws_an_exception_when_lexer_is_not_populated_with_a_lookahead_type(): void { - $this->expectException(InvalidArgumentForVariadicFunctionException::class); + $this->expectException(ParserException::class); $em = $this->createMock(EntityManager::class); $em->expects($this->any()) diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAddTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAddTest.php index 46f7fb19..b14a3f67 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAddTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateAddTest.php @@ -5,12 +5,18 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDates; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateAdd; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidTimezoneException; -class DateAddTest extends TestCase +class DateAddTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new DateAdd('DATE_ADD'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtractTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtractTest.php index 57720c32..00d1cdb2 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtractTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateSubtractTest.php @@ -5,12 +5,18 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDates; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateSubtract; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidTimezoneException; -class DateSubtractTest extends TestCase +class DateSubtractTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new DateSubtract('DATE_SUBTRACT'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/GreatestTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/GreatestTest.php index 53b7aa38..b96b7f4c 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/GreatestTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/GreatestTest.php @@ -5,11 +5,17 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsIntegers; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Greatest; -class GreatestTest extends TestCase +class GreatestTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new Greatest('GREATEST'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonBuildObjectTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonBuildObjectTest.php index 3e7f9f7f..acf32fcc 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonBuildObjectTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonBuildObjectTest.php @@ -5,11 +5,17 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonBuildObject; -class JsonBuildObjectTest extends TestCase +class JsonBuildObjectTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new JsonBuildObject('JSON_BUILD_OBJECT'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbBuildObjectTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbBuildObjectTest.php index fa0a64ed..8549fbe5 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbBuildObjectTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbBuildObjectTest.php @@ -5,11 +5,17 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbBuildObject; -class JsonbBuildObjectTest extends TestCase +class JsonbBuildObjectTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new JsonbBuildObject('JSONB_BUILD_OBJECT'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExistsTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExistsTest.php index b0eb091c..f36d42c3 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExistsTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathExistsTest.php @@ -5,12 +5,18 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidBooleanException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathExists; -class JsonbPathExistsTest extends TestCase +class JsonbPathExistsTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new JsonbPathExists('JSONB_PATH_EXISTS'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatchTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatchTest.php index 1e45cb4c..5df3551d 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatchTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathMatchTest.php @@ -5,12 +5,18 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidBooleanException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathMatch; -class JsonbPathMatchTest extends TestCase +class JsonbPathMatchTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new JsonbPathMatch('JSONB_PATH_MATCH'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php index 4aebb220..c717e99e 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php @@ -5,12 +5,18 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidBooleanException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQueryArray; -class JsonbPathQueryArrayTest extends TestCase +class JsonbPathQueryArrayTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new JsonbPathQueryArray('JSONB_PATH_QUERY_ARRAY'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php index 4147f490..e847a555 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php @@ -5,12 +5,18 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidBooleanException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQueryFirst; -class JsonbPathQueryFirstTest extends TestCase +class JsonbPathQueryFirstTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new JsonbPathQueryFirst('JSONB_PATH_QUERY_FIRST'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php index 08790953..4f023a90 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php @@ -5,12 +5,18 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidBooleanException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQuery; -class JsonbPathQueryTest extends TestCase +class JsonbPathQueryTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new JsonbPathQuery('JSONB_PATH_QUERY'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php index cf133638..05a88a8a 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php @@ -5,12 +5,18 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidBooleanException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbSet; -class JsonbSetTest extends TestCase +class JsonbSetTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new JsonbSet('JSONB_SET'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LeastTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LeastTest.php index 71b1ad1c..ec8b298d 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LeastTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LeastTest.php @@ -5,11 +5,17 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsIntegers; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Least; -class LeastTest extends TestCase +class LeastTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new Least('LEAST'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowTest.php index 6b75d9d2..3997c1fc 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowTest.php @@ -8,10 +8,16 @@ use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsIntegers; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsTexts; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Row; -class RowTest extends TestCase +class RowTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new Row('ROW'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJsonTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJsonTest.php index d60b73d2..84bef437 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJsonTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RowToJsonTest.php @@ -5,12 +5,18 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsTexts; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidBooleanException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RowToJson; -class RowToJsonTest extends TestCase +class RowToJsonTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new RowToJson('ROW_TO_JSON'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsqueryTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsqueryTest.php index a0194678..33bb2e59 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsqueryTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsqueryTest.php @@ -5,11 +5,17 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsTexts; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsquery; -class ToTsqueryTest extends TestCase +class ToTsqueryTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new ToTsquery('TO_TSQUERY'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsvectorTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsvectorTest.php index 387b9e69..cf02ac61 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsvectorTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTsvectorTest.php @@ -5,11 +5,17 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsTexts; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsvector; -class ToTsvectorTest extends TestCase +class ToTsvectorTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new ToTsvector('TO_TSVECTOR'); + } + protected function getStringFunctions(): array { return [ diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/UnaccentTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/UnaccentTest.php index 9261e4b5..01586341 100644 --- a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/UnaccentTest.php +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/UnaccentTest.php @@ -5,11 +5,17 @@ namespace Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsTexts; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Unaccent; -class UnaccentTest extends TestCase +class UnaccentTest extends BaseVariadicFunctionTestCase { + protected function createFixture(): BaseVariadicFunction + { + return new Unaccent('UNACCENT'); + } + protected function getStringFunctions(): array { return [ From 2aa63ee7f1974ce2e5736a480501af0e8b18eb77 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Sat, 19 Apr 2025 01:31:44 +0100 Subject: [PATCH 4/5] no message --- .../ORM/Query/AST/Functions/BaseVariadicFunction.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php index 72c4fbc0..5f0cdc53 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php @@ -85,6 +85,15 @@ private function feedParserWithNodesForNodeMappingPattern(Parser $parser, string } $expectedNodeIndex = $isNodeMappingASimplePattern ? 0 : $nodeIndex; + $argumentCountExceedsMappingPatternExpectation = !isset($nodeMapping[$expectedNodeIndex]); + if ($argumentCountExceedsMappingPatternExpectation) { + throw InvalidArgumentForVariadicFunctionException::unsupportedCombination( + $this->getFunctionName(), + \count($this->nodes) + 1, + 'implementation defines fewer node mappings than the actually provided argument count' + ); + } + $this->nodes[] = $parser->{$nodeMapping[$expectedNodeIndex]}(); // @phpstan-ignore-line $nodeIndex++; } From b0c19e7b9a6477c7b6bf11428df48515b113f8aa Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Sat, 19 Apr 2025 01:38:08 +0100 Subject: [PATCH 5/5] no message --- .../Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php index 5f0cdc53..79c31dfb 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php @@ -85,7 +85,7 @@ private function feedParserWithNodesForNodeMappingPattern(Parser $parser, string } $expectedNodeIndex = $isNodeMappingASimplePattern ? 0 : $nodeIndex; - $argumentCountExceedsMappingPatternExpectation = !isset($nodeMapping[$expectedNodeIndex]); + $argumentCountExceedsMappingPatternExpectation = !\array_key_exists($expectedNodeIndex, $nodeMapping); if ($argumentCountExceedsMappingPatternExpectation) { throw InvalidArgumentForVariadicFunctionException::unsupportedCombination( $this->getFunctionName(), @@ -101,6 +101,7 @@ private function feedParserWithNodesForNodeMappingPattern(Parser $parser, string $lookaheadType = DoctrineLexer::getLookaheadType($lexer); } + // Final validation ensures all arguments meet requirements, including any special rules in subclass implementations $this->validateArguments(...$this->nodes); // @phpstan-ignore-line }