diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f126380..98f28b08 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ permissions: jobs: tests: - name: "PHP ${{ matrix.php }} + Doctrine ORM ${{ matrix.doctrine-orm }} + Composer ${{ matrix.composer-flags }}" + name: "PHP ${{ matrix.php }} + Doctrine ORM ${{ matrix.doctrine-orm }}" runs-on: ubuntu-latest strategy: @@ -22,7 +22,6 @@ jobs: - php: '8.2' - php: '8.3' - php: '8.4' - ignore-php-version: true calculate-code-coverage: true - doctrine-orm: '2.14' - doctrine-orm: '3.0' @@ -54,11 +53,11 @@ jobs: - name: Install composer dependencies run: | if [ "${{ matrix.doctrine-orm }}" == "2.14" ]; then - composer require doctrine/orm "~2.14" --prefer-dist --no-interaction --no-progress ${{ matrix.composer-flags }} + composer require doctrine/orm "~2.14" --prefer-dist --no-interaction --no-progress elif [ "${{ matrix.doctrine-orm }}" == "3.0" ]; then - composer require doctrine/orm "~3.0" --prefer-dist --no-interaction --no-progress ${{ matrix.composer-flags }} + composer require doctrine/orm "~3.0" --prefer-dist --no-interaction --no-progress else - composer update --prefer-dist --no-interaction --no-progress ${{ matrix.composer-flags }} + composer update --prefer-dist --no-interaction --no-progress fi - name: Run static analysis @@ -67,9 +66,6 @@ jobs: - name: Check code style run: composer check-code-style - if: matrix.ignore-php-version == true - env: - PHP_CS_FIXER_IGNORE_ENV: 1 - name: Check for security vulnerabilities in 3rd party dependencies run: composer audit @@ -84,4 +80,4 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} fail-on-error: false base-path: ./var/logs/test-coverage/ - flag-name: "PHP ${{ matrix.php }} + Composer@${{ matrix.composer-flags || '*' }}" + flag-name: "PHP ${{ matrix.php }}" diff --git a/ci/phpstan/config.neon b/ci/phpstan/config.neon index 571ed447..5ffbffea 100644 --- a/ci/phpstan/config.neon +++ b/ci/phpstan/config.neon @@ -5,12 +5,15 @@ includes: parameters: level: max paths: + - ../../ci - ../../src - ../../tests - checkMissingIterableValueType: false reportUnmatchedIgnoredErrors: false + ignoreErrors: + - identifier: missingType.iterableValue + - '#Parameter \#1 \$phpArray of method MartinGeorgiev\\Doctrine\\DBAL\\Types\\BaseArray::convertToDatabaseValue\(\) expects array\|null, string given.#' - '#Parameter \#1 \$postgresArray of method MartinGeorgiev\\Doctrine\\DBAL\\Types\\BaseArray::convertToPHPValue\(\) expects string\|null, int given.#' - '#Property MartinGeorgiev\\Doctrine\\ORM\\Query\\AST\\Functions\\Cast::\$sourceType \(Doctrine\\ORM\\Query\\AST\\Node\) does not accept Doctrine\\ORM\\Query\\AST\\Node\|string#' diff --git a/composer.json b/composer.json index 01191247..3b4d4255 100644 --- a/composer.json +++ b/composer.json @@ -59,23 +59,39 @@ }, "scripts": { + "deptrac": [ + "deptrac analyze --config-file=./ci/deptrac/config.yml --cache-file=./ci/deptrac/.cache --no-interaction --no-progress" + ], + "php-cs-fixer": [ + "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix --config=./ci/php-cs-fixer/config.php --show-progress=none --no-interaction --diff -v" + ], + "phpstan": [ + "phpstan analyse --configuration=./ci/phpstan/config.neon" + ], + "phpunit": [ + "XDEBUG_MODE=coverage phpunit --configuration=./ci/phpunit/config.xml" + ], + "rector": [ + "rector --config=./ci/rector/config.php --ansi --no-progress-bar" + ], + "check-code-style": [ - "php-cs-fixer fix --config='./ci/php-cs-fixer/config.php' --show-progress=none --dry-run --no-interaction --diff -v", - "rector --config='./ci/rector/config.php' --ansi --no-progress-bar --dry-run" + "@php-cs-fixer --dry-run", + "@rector --dry-run" ], "fix-code-style": [ - "rector --config='./ci/rector/config.php' --ansi --no-progress-bar", - "php-cs-fixer fix --config='./ci/php-cs-fixer/config.php' --show-progress=none --no-interaction --diff -v" + "@rector", + "@php-cs-fixer" ], "run-static-analysis": [ - "phpstan analyse --configuration='./ci/phpstan/config.neon'", - "deptrac analyze --config-file='./ci/deptrac/config.yml' --cache-file='./ci/deptrac/.cache' --no-interaction --no-progress" + "@phpstan", + "@deptrac" ], "run-tests": [ - "phpunit --configuration='./ci/phpunit/config.xml'" + "@phpunit" ], "run-tests-with-clover": [ - "phpunit --configuration='./ci/phpunit/config.xml' --coverage-clover './var/logs/test-coverage/clover.xml'" + "@phpunit --coverage-clover=./var/logs/test-coverage/clover.xml" ] }, diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Arr.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Arr.php index 848b9e51..daf731ef 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Arr.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Arr.php @@ -4,6 +4,8 @@ namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions; +use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException; + /** * Implementation of PostgreSQL ARRAY[]. * @@ -12,11 +14,20 @@ * * @author Martin Georgiev */ -class Arr extends BaseFunction +class Arr extends BaseVariadicFunction { + protected string $commonNodeMapping = 'StringPrimary'; + protected function customizeFunction(): void { $this->setFunctionPrototype('ARRAY[%s]'); - $this->addNodeMapping('StringPrimary'); + } + + protected function validateArguments(array $arguments): void + { + $argumentCount = \count($arguments); + if ($argumentCount === 0) { + throw InvalidArgumentForVariadicFunctionException::atLeast('ARRAY', 1); + } } } diff --git a/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrTest.php b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrTest.php new file mode 100644 index 00000000..12b1d12c --- /dev/null +++ b/tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrTest.php @@ -0,0 +1,42 @@ + Arr::class, + ]; + } + + protected function getExpectedSqlStatements(): array + { + return [ + // Multiple literal values + "SELECT ARRAY['foo', 'bar', 'baz'] AS sclr_0 FROM ContainsArrays c0_", + // Column references + 'SELECT ARRAY[c0_.array1] AS sclr_0 FROM ContainsArrays c0_', + // Mix of column references and literals + "SELECT ARRAY[c0_.array1, 'test-value', c0_.array2] AS sclr_0 FROM ContainsArrays c0_", + ]; + } + + protected function getDqlStatements(): array + { + return [ + // Multiple literal values + \sprintf("SELECT ARRAY('foo', 'bar', 'baz') FROM %s e", ContainsArrays::class), + // Column references + \sprintf('SELECT ARRAY(e.array1) FROM %s e', ContainsArrays::class), + // Mix of column references and literals + \sprintf("SELECT ARRAY(e.array1, 'test-value', e.array2) FROM %s e", ContainsArrays::class), + ]; + } +}