From 36ca58fa22ba6c77f01f2a86a788e2a3ae2cfd37 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 27 Feb 2024 11:29:25 +0100 Subject: [PATCH] fix: components split dependencies --- .github/workflows/ci.yml | 46 +- components.php | 168 ------ composer.json | 48 +- src/Doctrine/Common/composer.json | 133 +++-- src/Doctrine/Odm/Tests/AppKernel.php | 2 - .../Odm/Tests/Filter/BooleanFilterTest.php | 1 - .../Tests/Filter/BooleanFilterTestTrait.php | 2 +- .../Odm/Tests/Filter/DateFilterTest.php | 1 - .../Tests/Filter/DateFilterTestTrait.php | 2 +- .../Odm/Tests/Filter/ExistsFilterTest.php | 1 - .../Tests/Filter/ExistsFilterTestTrait.php | 2 +- .../Odm/Tests/Filter/NumericFilterTest.php | 1 - .../Tests/Filter/NumericFilterTestTrait.php | 2 +- .../Odm/Tests/Filter/OrderFilterTest.php | 1 - .../Tests/Filter/OrderFilterTestTrait.php | 2 +- .../Odm/Tests/Filter/RangeFilterTest.php | 1 - .../Tests/Filter/RangeFilterTestTrait.php | 2 +- .../Odm/Tests/Filter/SearchFilterTest.php | 1 - .../Tests/Filter/SearchFilterTestTrait.php | 2 +- src/Doctrine/Odm/Tests/config.yml | 10 - src/Doctrine/Odm/composer.json | 147 +++-- src/Doctrine/Orm/Tests/AppKernel.php | 2 - .../Orm/Tests/Filter/BooleanFilterTest.php | 1 - .../Tests/Filter/BooleanFilterTestTrait.php | 170 ++++++ .../Orm/Tests/Filter/DateFilterTest.php | 1 - .../Orm/Tests/Filter/DateFilterTestTrait.php | 229 ++++++++ .../Orm/Tests/Filter/ExistsFilterTest.php | 1 - .../Tests/Filter/ExistsFilterTestTrait.php | 280 ++++++++++ .../Orm/Tests/Filter/NumericFilterTest.php | 1 - .../Tests/Filter/NumericFilterTestTrait.php | 206 +++++++ .../Orm/Tests/Filter/OrderFilterTest.php | 1 - .../Orm/Tests/Filter/OrderFilterTestTrait.php | 338 ++++++++++++ .../Orm/Tests/Filter/RangeFilterTest.php | 1 - .../Orm/Tests/Filter/RangeFilterTestTrait.php | 139 +++++ .../Orm/Tests/Filter/SearchFilterTest.php | 1 - .../Tests/Filter/SearchFilterTestTrait.php | 517 ++++++++++++++++++ src/Doctrine/Orm/Tests/config.yml | 9 - src/Doctrine/Orm/composer.json | 147 +++-- .../Action/DocumentationAction.php | 2 + src/Documentation/Action/EntrypointAction.php | 2 + src/Documentation/composer.json | 30 +- ...viderResourceMetadataCollectionFactory.php | 2 +- src/Elasticsearch/composer.json | 19 +- .../State/Processor/NormalizeProcessor.php | 2 +- src/GraphQl/composer.json | 35 +- src/HttpCache/composer.json | 15 +- src/Hydra/composer.json | 44 +- src/JsonLd/composer.json | 18 +- src/JsonSchema/composer.json | 11 +- .../Tests/Fixtures/ApiResource/DummyCar.php | 6 +- src/Metadata/composer.json | 19 +- src/OpenApi/composer.json | 31 +- src/ParameterValidator/FilterLocatorTrait.php | 2 +- src/ParameterValidator/composer.json | 18 +- src/RamseyUuid/composer.json | 11 +- .../SerializerContextBuilderInterface.php | 11 +- src/Serializer/composer.json | 27 +- src/State/ApiResource/Error.php | 3 +- src/State/Processor/SerializeProcessor.php | 4 +- src/{Serializer => State}/ResourceList.php | 2 +- .../SerializerContextBuilderInterface.php | 55 ++ .../Tests/ResourceListTest.php | 4 +- src/State/composer.json | 37 +- src/Symfony/Action/DocumentationAction.php | 133 +++++ src/Symfony/Action/EntrypointAction.php | 68 +++ .../PayloadArgumentResolver.php | 2 +- .../Resources/config/symfony/controller.xml | 4 +- .../Resources/config/symfony/events.xml | 4 +- .../EventListener/SerializeListener.php | 4 +- src/Symfony/composer.json | 72 +-- .../Exception/ValidationException.php | 3 +- src/Validator/composer.json | 12 +- .../TestBundle/Entity/Issue5662/Book.php | 2 +- .../TestBundle/Entity/Issue5662/Review.php | 2 +- .../EventListener/SerializeListenerTest.php | 4 +- 75 files changed, 2517 insertions(+), 822 deletions(-) delete mode 100644 components.php rename src/Doctrine/{Common => Odm}/Tests/Filter/BooleanFilterTestTrait.php (98%) rename src/Doctrine/{Common => Odm}/Tests/Filter/DateFilterTestTrait.php (99%) rename src/Doctrine/{Common => Odm}/Tests/Filter/ExistsFilterTestTrait.php (99%) rename src/Doctrine/{Common => Odm}/Tests/Filter/NumericFilterTestTrait.php (99%) rename src/Doctrine/{Common => Odm}/Tests/Filter/OrderFilterTestTrait.php (99%) rename src/Doctrine/{Common => Odm}/Tests/Filter/RangeFilterTestTrait.php (98%) rename src/Doctrine/{Common => Odm}/Tests/Filter/SearchFilterTestTrait.php (99%) create mode 100644 src/Doctrine/Orm/Tests/Filter/BooleanFilterTestTrait.php create mode 100644 src/Doctrine/Orm/Tests/Filter/DateFilterTestTrait.php create mode 100644 src/Doctrine/Orm/Tests/Filter/ExistsFilterTestTrait.php create mode 100644 src/Doctrine/Orm/Tests/Filter/NumericFilterTestTrait.php create mode 100644 src/Doctrine/Orm/Tests/Filter/OrderFilterTestTrait.php create mode 100644 src/Doctrine/Orm/Tests/Filter/RangeFilterTestTrait.php create mode 100644 src/Doctrine/Orm/Tests/Filter/SearchFilterTestTrait.php rename src/{Serializer => State}/ResourceList.php (90%) create mode 100644 src/State/SerializerContextBuilderInterface.php rename src/{Serializer => State}/Tests/ResourceListTest.php (88%) create mode 100644 src/Symfony/Action/DocumentationAction.php create mode 100644 src/Symfony/Action/EntrypointAction.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29dddc320c6..5178376d65b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,9 +62,8 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer- - name: Update project dependencies - run: | - composer update --no-interaction --no-progress --ansi - - run: php components.php + run: composer update --no-interaction --no-progress --ansi + - run: composer check-dependencies php-cs-fixer: name: PHP CS Fixer (PHP ${{ matrix.php }}) @@ -227,19 +226,21 @@ jobs: - '8.2' - '8.3' component: - - JsonSchema - - OpenApi - - Metadata - - ParameterValidator - - Elasticsearch - - HttpCache - - RamseyUuid - - GraphQl - - Serializer - - Symfony - - Doctrine/Common - - Doctrine/Orm - - Doctrine/Odm + - api-platform/doctrine-common + - api-platform/doctrine-orm + - api-platform/doctrine-odm + - api-platform/metadata + - api-platform/json-schema + - api-platform/elasticsearch + - api-platform/openapi + - api-platform/graphql + - api-platform/http-cache + - api-platform/parameter-validator + - api-platform/ramsey-uuid + - api-platform/serializer + - api-platform/state + - api-platform/symfony + - api-platform/validator include: - php: '8.1' coverage: true @@ -259,23 +260,23 @@ jobs: extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite, mongodb ini-values: memory_limit=-1 - name: Run ${{ matrix.component }} tests - working-directory: src/${{ matrix.component }} run: | composer update - mkdir -p build/logs/phpunit - vendor/bin/phpunit --log-junit "build/logs/phpunit/junit.xml" ${{ matrix.coverage && '--coverage-clover build/logs/phpunit/clover.xml' || '' }} + composer ${{matrix.component}} update + mkdir -p /tmp/build/logs/phpunit + composer ${{matrix.component}} test --log-junit "/tmp/build/logs/phpunit/junit.xml" ${{ matrix.coverage && '--coverage-clover /tmp/build/logs/phpunit/clover.xml' || '' }} - name: Upload test artifacts if: always() uses: actions/upload-artifact@v4 with: name: phpunit-logs-php${{ matrix.php }} - path: src/${{ matrix.component }}/build/logs/phpunit + path: /tmp/build/logs/phpunit continue-on-error: true - name: Upload coverage results to Codecov if: matrix.coverage uses: codecov/codecov-action@v3 with: - directory: src/${{ matrix.component }}/build/logs/phpunit + directory: /tmp/build/logs/phpunit name: phpunit-php${{ matrix.php }} flags: phpunit fail_ci_if_error: true @@ -284,11 +285,10 @@ jobs: if: matrix.coverage env: COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - working-directory: src/${{ matrix.component }} run: | composer global require --prefer-dist --no-interaction --no-progress --ansi php-coveralls/php-coveralls export PATH="$PATH:$HOME/.composer/vendor/bin" - php-coveralls --coverage_clover=build/logs/phpunit/clover.xml + php-coveralls --coverage_clover=/tmp/build/logs/phpunit/clover.xml continue-on-error: true behat: diff --git a/components.php b/components.php deleted file mode 100644 index 3f58cf3c74e..00000000000 --- a/components.php +++ /dev/null @@ -1,168 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -/* - * This script checks for dependencies between our components - * and fails if a component has a wrong dependency. - */ -use Symfony\Component\Filesystem\Path; -use Symfony\Component\Finder\Finder; - -$loader = require './vendor/autoload.php'; -$namespace = 'ApiPlatform'; -$prefix = 'api-platform'; -$ignoreList = ['ApiPlatform\\Api', 'ApiPlatform\\Exception', 'ApiPlatform\\Util']; -$stopOnFailure = in_array('--stop-on-failure', $_SERVER['argv'], true); -$skipPaths = [__DIR__.'/src/GraphQl/Resolver/Stage']; - -/** - * Reads the beginning of a PHP class and returns "use" instructions matching our namespace. - */ -$class_uses_namespaces = function (ReflectionClass $r) use ($namespace): \Generator { - $fp = fopen($r->getFileName(), 'r'); - $u = 'use'; - $c = false; - while (($buffer = fgets($fp, 4096)) !== false) { - if ($c && \PHP_EOL === $buffer) { - break; - } - - if (!str_starts_with($buffer, $u)) { - continue; - } - - $c = true; - $buffer = substr($buffer, 4, -2); - if (str_starts_with($buffer, $namespace)) { - yield substr($buffer, 0, strpos($buffer, ' ') ?: null); - } - } - - fclose($fp); -}; - -// Creates and require the map of dependencies -$directories = []; -$map = []; -foreach (Finder::create()->in('src')->notPath('vendor')->name('composer.json') as $f) { - if (null === ($component = json_decode($f->getContents(), true))) { - continue; - } - - $filter = fn ($v) => str_starts_with($v, $prefix); - $dependencies = - array_merge( - array_filter(array_keys((array) $component['require']), $filter), - array_filter(array_keys((array) $component['require-dev'] ?? []), $filter) - ); - - $map[$component['name']] = ['namespace' => substr(key($component['autoload']['psr-4']), 0, -1), 'dependencies' => $dependencies]; - $directories[] = substr($f->getRealPath(), 0, -14); - - foreach (Finder::create()->in($f->getPath())->notPath('vendor')->notPath('var')->name('*.php')->notName('*.tpl.php')->notName('bootstrap.php') as $f) { - require_once $f->getRealPath(); - } -} - -// create a PSR map of dependencies -$psrMap = []; -foreach ($map as $component) { - $depsPsr = []; - foreach ($component['dependencies'] as $d) { - $depsPsr[] = $map[$d]['namespace']; - } - - $psrMap[$component['namespace']] = $depsPsr; -} - -$warned = []; -$getComponentNamespace = function (ReflectionClass $r, ?ReflectionClass $inside = null) use ($psrMap, $warned, $ignoreList, $namespace) { - $ns = $r->getNamespaceName(); - // Find this components namespace - $nsParts = explode('\\', $ns); - $n = count($nsParts); - $componentNs = $nsParts[0].'\\'.$nsParts[1]; - $i = 2; - - while (!isset($psrMap[$componentNs]) && $i < $n) { - if ($part = ($nsParts[$i++] ?? null)) { - $componentNs .= '\\'.$part; - } - } - - if (!isset($psrMap[$componentNs])) { - if (in_array($componentNs, $ignoreList, true)) { - return null; - } - - $guess = $nsParts[0].'\\'.$nsParts[1]; - if ($warned[$guess] ?? true) { - echo sprintf('"%s" is not an %s component at "%s" %s', $guess, $namespace, ($inside ?? $r)->getFileName(), \PHP_EOL); - $warned[$guess] = false; - } - - return null; - } - - return $componentNs; -}; - -$exitCode = 0; -$lnamespace = strlen($namespace); -foreach (array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()) as $className) { - $r = new ReflectionClass($className); - $ns = $r->getNamespaceName(); - - foreach ($skipPaths as $base) { - if (!($fileName = $r->getFileName())) { - continue; - } - - if (Path::isBasePath($skipPaths[0], $fileName)) { - continue 2; - } - } - - if (!str_starts_with($ns, $namespace)) { - continue; - } - - $componentNs = $getComponentNamespace($r); - - if (!$componentNs) { - continue; - } - - foreach ($class_uses_namespaces($r) as $u) { - if (str_starts_with($u, $componentNs)) { - continue; - } - - $useNs = $getComponentNamespace(new ReflectionClass($u), $r); - - if (!$useNs || $useNs === $componentNs) { - continue; - } - - if (!in_array($useNs, $psrMap[$componentNs], true)) { - echo sprintf('"%s" uses "%s" although "%s" is not one of its dependencies %s', $className, $u, $useNs, \PHP_EOL); - $exitCode = 1; - - if ($stopOnFailure) { - exit($exitCode); - } - } - } -} - -exit($exitCode); diff --git a/composer.json b/composer.json index a7efa293cc6..76cee5becd5 100644 --- a/composer.json +++ b/composer.json @@ -38,6 +38,7 @@ "willdurand/negotiation": "^3.0" }, "require-dev": { + "soyuka/pmu": "^0.0.2", "behat/behat": "^3.11", "behat/mink": "^1.9", "doctrine/cache": "^1.11 || ^2.1", @@ -149,7 +150,8 @@ "allow-plugins": { "composer/package-versions-deprecated": true, "phpstan/extension-installer": true, - "php-http/discovery": true + "php-http/discovery": true, + "soyuka/pmu": true } }, "extra": { @@ -158,6 +160,46 @@ }, "symfony": { "require": "^6.4 || ^7.0" - } - } + }, + "projects": [ + "api-platform/doctrine-common", + "api-platform/doctrine-orm", + "api-platform/doctrine-odm", + "api-platform/metadata", + "api-platform/json-schema", + "api-platform/elasticsearch", + "api-platform/jsonld", + "api-platform/hydra", + "api-platform/openapi", + "api-platform/graphql", + "api-platform/http-cache", + "api-platform/documentation", + "api-platform/parameter-validator", + "api-platform/ramsey-uuid", + "api-platform/serializer", + "api-platform/state", + "api-platform/symfony", + "api-platform/validator" + ] + }, + "repositories": [ + {"type": "path", "url": "./src/Doctrine/Common"}, + {"type": "path", "url": "./src/Doctrine/Orm"}, + {"type": "path", "url": "./src/Doctrine/Odm"}, + {"type": "path", "url": "./src/Metadata"}, + {"type": "path", "url": "./src/JsonSchema"}, + {"type": "path", "url": "./src/Elasticsearch"}, + {"type": "path", "url": "./src/JsonLd"}, + {"type": "path", "url": "./src/Hydra"}, + {"type": "path", "url": "./src/OpenApi"}, + {"type": "path", "url": "./src/GraphQl"}, + {"type": "path", "url": "./src/HttpCache"}, + {"type": "path", "url": "./src/Documentation"}, + {"type": "path", "url": "./src/ParameterValidator"}, + {"type": "path", "url": "./src/RamseyUuid"}, + {"type": "path", "url": "./src/Serializer"}, + {"type": "path", "url": "./src/State"}, + {"type": "path", "url": "./src/Symfony"}, + {"type": "path", "url": "./src/Validator"} + ] } diff --git a/src/Doctrine/Common/composer.json b/src/Doctrine/Common/composer.json index 9f5353a1a27..b53f3fe02b5 100644 --- a/src/Doctrine/Common/composer.json +++ b/src/Doctrine/Common/composer.json @@ -1,76 +1,69 @@ { - "name": "api-platform/doctrine-common", - "description": "Common files used by api-platform/doctrine-orm and api-platform/doctrine-odm", - "type": "library", - "keywords": [ - "DOCTRINE", - "ORM", - "ODM", - "COMMON" - ], - "homepage": "https://api-platform.com", - "license": "MIT", - "authors": [ - { - "name": "Kévin Dunglas", - "email": "kevin@dunglas.fr", - "homepage": "https://dunglas.fr" + "name": "api-platform/doctrine-common", + "description": "Common files used by api-platform/doctrine-orm and api-platform/doctrine-odm", + "type": "library", + "keywords": [ + "DOCTRINE", + "ORM", + "ODM", + "COMMON" + ], + "homepage": "https://api-platform.com", + "license": "MIT", + "authors": [ + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr", + "homepage": "https://dunglas.fr" + }, + { + "name": "API Platform Community", + "homepage": "https://api-platform.com/community/contributors" + } + ], + "require": { + "php": ">=8.1", + "api-platform/metadata": "@dev", + "api-platform/state": "@dev", + "doctrine/collections": "^2.1", + "doctrine/common": "^3.2.2", + "doctrine/persistence": "^3.2" }, - { - "name": "API Platform Community", - "homepage": "https://api-platform.com/community/contributors" - } - ], - "require": { - "php": ">=8.1", - "api-platform/metadata": "*@dev || ^3.1", - "api-platform/state": "*@dev || ^3.1", - "doctrine/collections": "^2.1", - "doctrine/common": "^3.2.2", - "doctrine/persistence": "^3.2" - }, - "require-dev": { - "doctrine/mongodb-odm": "^2.6", - "doctrine/orm": "^2.17", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^10.0", - "symfony/phpunit-bridge": "^6.4 || ^7.0" - }, - "conflict": { - "doctrine/persistence": "<1.3" - }, - "suggest": { - "phpstan/phpdoc-parser": "For PHP documentation support.", - "symfony/yaml": "For YAML resource configuration.", - "symfony/config": "For XML resource configuration." - }, - "autoload": { - "psr-4": { - "ApiPlatform\\Doctrine\\Common\\": "" - } - }, - "config": { - "preferred-install": { - "*": "dist" + "require-dev": { + "doctrine/mongodb-odm": "^2.6", + "doctrine/orm": "^2.17", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^10.0", + "symfony/phpunit-bridge": "^6.4 || ^7.0" + }, + "conflict": { + "doctrine/persistence": "<1.3" + }, + "suggest": { + "phpstan/phpdoc-parser": "For PHP documentation support.", + "symfony/yaml": "For YAML resource configuration.", + "symfony/config": "For XML resource configuration." + }, + "autoload": { + "psr-4": { + "ApiPlatform\\Doctrine\\Common\\": "" + } + }, + "config": { + "preferred-install": { + "*": "dist" + }, + "sort-packages": true }, - "sort-packages": true - }, - "extra": { - "branch-alias": { - "dev-main": "3.2.x-dev" + "extra": { + "branch-alias": { + "dev-main": "3.3.x-dev" + }, + "symfony": { + "require": "^6.4" + } }, - "symfony": { - "require": "^6.4" + "scripts": { + "test": "./vendor/bin/phpunit" } - }, - "repositories": [ - { - "type": "path", - "url": "../../Metadata" - }, - { - "type": "path", - "url": "../../State" - } - ] } diff --git a/src/Doctrine/Odm/Tests/AppKernel.php b/src/Doctrine/Odm/Tests/AppKernel.php index 6a07f359d97..1b9481a50b2 100644 --- a/src/Doctrine/Odm/Tests/AppKernel.php +++ b/src/Doctrine/Odm/Tests/AppKernel.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Odm\Tests; -use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; use Doctrine\Bundle\MongoDBBundle\DoctrineMongoDBBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; @@ -41,7 +40,6 @@ public function __construct(string $environment, bool $debug) public function registerBundles(): array { return [ - new ApiPlatformBundle(), new FrameworkBundle(), new DoctrineMongoDBBundle(), ]; diff --git a/src/Doctrine/Odm/Tests/Filter/BooleanFilterTest.php b/src/Doctrine/Odm/Tests/Filter/BooleanFilterTest.php index 0b52592ea85..4dce86ef25d 100644 --- a/src/Doctrine/Odm/Tests/Filter/BooleanFilterTest.php +++ b/src/Doctrine/Odm/Tests/Filter/BooleanFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Odm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\BooleanFilterTestTrait; use ApiPlatform\Doctrine\Odm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Odm\Tests\DoctrineMongoDbOdmFilterTestCase; use ApiPlatform\Doctrine\Odm\Tests\Fixtures\Document\Dummy; diff --git a/src/Doctrine/Common/Tests/Filter/BooleanFilterTestTrait.php b/src/Doctrine/Odm/Tests/Filter/BooleanFilterTestTrait.php similarity index 98% rename from src/Doctrine/Common/Tests/Filter/BooleanFilterTestTrait.php rename to src/Doctrine/Odm/Tests/Filter/BooleanFilterTestTrait.php index 090ef4b0667..f2b2645326f 100644 --- a/src/Doctrine/Common/Tests/Filter/BooleanFilterTestTrait.php +++ b/src/Doctrine/Odm/Tests/Filter/BooleanFilterTestTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Doctrine\Common\Tests\Filter; +namespace ApiPlatform\Doctrine\Odm\Tests\Filter; /** * @author Amrouche Hamza diff --git a/src/Doctrine/Odm/Tests/Filter/DateFilterTest.php b/src/Doctrine/Odm/Tests/Filter/DateFilterTest.php index f36b87ce128..170082d17dd 100644 --- a/src/Doctrine/Odm/Tests/Filter/DateFilterTest.php +++ b/src/Doctrine/Odm/Tests/Filter/DateFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Odm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\DateFilterTestTrait; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; use ApiPlatform\Doctrine\Odm\Tests\DoctrineMongoDbOdmFilterTestCase; use ApiPlatform\Doctrine\Odm\Tests\Fixtures\Document\Dummy; diff --git a/src/Doctrine/Common/Tests/Filter/DateFilterTestTrait.php b/src/Doctrine/Odm/Tests/Filter/DateFilterTestTrait.php similarity index 99% rename from src/Doctrine/Common/Tests/Filter/DateFilterTestTrait.php rename to src/Doctrine/Odm/Tests/Filter/DateFilterTestTrait.php index e47b22517f2..445d5e92acf 100644 --- a/src/Doctrine/Common/Tests/Filter/DateFilterTestTrait.php +++ b/src/Doctrine/Odm/Tests/Filter/DateFilterTestTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Doctrine\Common\Tests\Filter; +namespace ApiPlatform\Doctrine\Odm\Tests\Filter; /** * @author Théo FIDRY diff --git a/src/Doctrine/Odm/Tests/Filter/ExistsFilterTest.php b/src/Doctrine/Odm/Tests/Filter/ExistsFilterTest.php index 70240f39ebd..0bf87b0a7fe 100644 --- a/src/Doctrine/Odm/Tests/Filter/ExistsFilterTest.php +++ b/src/Doctrine/Odm/Tests/Filter/ExistsFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Odm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\ExistsFilterTestTrait; use ApiPlatform\Doctrine\Odm\Filter\ExistsFilter; use ApiPlatform\Doctrine\Odm\Tests\DoctrineMongoDbOdmFilterTestCase; use ApiPlatform\Doctrine\Odm\Tests\Fixtures\Document\Dummy; diff --git a/src/Doctrine/Common/Tests/Filter/ExistsFilterTestTrait.php b/src/Doctrine/Odm/Tests/Filter/ExistsFilterTestTrait.php similarity index 99% rename from src/Doctrine/Common/Tests/Filter/ExistsFilterTestTrait.php rename to src/Doctrine/Odm/Tests/Filter/ExistsFilterTestTrait.php index f7e294b6e3f..652359b059d 100644 --- a/src/Doctrine/Common/Tests/Filter/ExistsFilterTestTrait.php +++ b/src/Doctrine/Odm/Tests/Filter/ExistsFilterTestTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Doctrine\Common\Tests\Filter; +namespace ApiPlatform\Doctrine\Odm\Tests\Filter; /** * @author Antoine Bluchet diff --git a/src/Doctrine/Odm/Tests/Filter/NumericFilterTest.php b/src/Doctrine/Odm/Tests/Filter/NumericFilterTest.php index e14732b1691..3dd6b22d87f 100644 --- a/src/Doctrine/Odm/Tests/Filter/NumericFilterTest.php +++ b/src/Doctrine/Odm/Tests/Filter/NumericFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Odm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\NumericFilterTestTrait; use ApiPlatform\Doctrine\Odm\Filter\NumericFilter; use ApiPlatform\Doctrine\Odm\Tests\DoctrineMongoDbOdmFilterTestCase; use ApiPlatform\Doctrine\Odm\Tests\Fixtures\Document\Dummy; diff --git a/src/Doctrine/Common/Tests/Filter/NumericFilterTestTrait.php b/src/Doctrine/Odm/Tests/Filter/NumericFilterTestTrait.php similarity index 99% rename from src/Doctrine/Common/Tests/Filter/NumericFilterTestTrait.php rename to src/Doctrine/Odm/Tests/Filter/NumericFilterTestTrait.php index 91b63e4b2ff..0a78554f816 100644 --- a/src/Doctrine/Common/Tests/Filter/NumericFilterTestTrait.php +++ b/src/Doctrine/Odm/Tests/Filter/NumericFilterTestTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Doctrine\Common\Tests\Filter; +namespace ApiPlatform\Doctrine\Odm\Tests\Filter; /** * @author Amrouche Hamza diff --git a/src/Doctrine/Odm/Tests/Filter/OrderFilterTest.php b/src/Doctrine/Odm/Tests/Filter/OrderFilterTest.php index 852862dd98f..4c6666c3573 100644 --- a/src/Doctrine/Odm/Tests/Filter/OrderFilterTest.php +++ b/src/Doctrine/Odm/Tests/Filter/OrderFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Odm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\OrderFilterTestTrait; use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; use ApiPlatform\Doctrine\Odm\Tests\DoctrineMongoDbOdmFilterTestCase; use ApiPlatform\Doctrine\Odm\Tests\Fixtures\CustomConverter; diff --git a/src/Doctrine/Common/Tests/Filter/OrderFilterTestTrait.php b/src/Doctrine/Odm/Tests/Filter/OrderFilterTestTrait.php similarity index 99% rename from src/Doctrine/Common/Tests/Filter/OrderFilterTestTrait.php rename to src/Doctrine/Odm/Tests/Filter/OrderFilterTestTrait.php index 374e0ba239d..1d079f9e1ae 100644 --- a/src/Doctrine/Common/Tests/Filter/OrderFilterTestTrait.php +++ b/src/Doctrine/Odm/Tests/Filter/OrderFilterTestTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Doctrine\Common\Tests\Filter; +namespace ApiPlatform\Doctrine\Odm\Tests\Filter; /** * @author Théo FIDRY diff --git a/src/Doctrine/Odm/Tests/Filter/RangeFilterTest.php b/src/Doctrine/Odm/Tests/Filter/RangeFilterTest.php index 177ae9f6c59..51fd7744fe0 100644 --- a/src/Doctrine/Odm/Tests/Filter/RangeFilterTest.php +++ b/src/Doctrine/Odm/Tests/Filter/RangeFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Odm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\RangeFilterTestTrait; use ApiPlatform\Doctrine\Odm\Filter\RangeFilter; use ApiPlatform\Doctrine\Odm\Tests\DoctrineMongoDbOdmFilterTestCase; use ApiPlatform\Doctrine\Odm\Tests\Fixtures\Document\Dummy; diff --git a/src/Doctrine/Common/Tests/Filter/RangeFilterTestTrait.php b/src/Doctrine/Odm/Tests/Filter/RangeFilterTestTrait.php similarity index 98% rename from src/Doctrine/Common/Tests/Filter/RangeFilterTestTrait.php rename to src/Doctrine/Odm/Tests/Filter/RangeFilterTestTrait.php index 029b938caa3..91500dae11f 100644 --- a/src/Doctrine/Common/Tests/Filter/RangeFilterTestTrait.php +++ b/src/Doctrine/Odm/Tests/Filter/RangeFilterTestTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Doctrine\Common\Tests\Filter; +namespace ApiPlatform\Doctrine\Odm\Tests\Filter; /** * @author Lee Siong Chan diff --git a/src/Doctrine/Odm/Tests/Filter/SearchFilterTest.php b/src/Doctrine/Odm/Tests/Filter/SearchFilterTest.php index 0624b4d47e0..307c622145e 100644 --- a/src/Doctrine/Odm/Tests/Filter/SearchFilterTest.php +++ b/src/Doctrine/Odm/Tests/Filter/SearchFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Odm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\SearchFilterTestTrait; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; use ApiPlatform\Doctrine\Odm\Tests\DoctrineMongoDbOdmFilterTestCase; use ApiPlatform\Doctrine\Odm\Tests\Fixtures\CustomConverter; diff --git a/src/Doctrine/Common/Tests/Filter/SearchFilterTestTrait.php b/src/Doctrine/Odm/Tests/Filter/SearchFilterTestTrait.php similarity index 99% rename from src/Doctrine/Common/Tests/Filter/SearchFilterTestTrait.php rename to src/Doctrine/Odm/Tests/Filter/SearchFilterTestTrait.php index 5cf9cd54f26..a812f7f20f8 100644 --- a/src/Doctrine/Common/Tests/Filter/SearchFilterTestTrait.php +++ b/src/Doctrine/Odm/Tests/Filter/SearchFilterTestTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Doctrine\Common\Tests\Filter; +namespace ApiPlatform\Doctrine\Odm\Tests\Filter; /** * @author Julien Deniau diff --git a/src/Doctrine/Odm/Tests/config.yml b/src/Doctrine/Odm/Tests/config.yml index 572657cbc8e..e87436195b1 100644 --- a/src/Doctrine/Odm/Tests/config.yml +++ b/src/Doctrine/Odm/Tests/config.yml @@ -16,16 +16,6 @@ doctrine_mongodb: dir: '%kernel.project_dir%/Fixtures/Document' prefix: 'ApiPlatform\Doctrine\Odm\Tests\Fixtures\Document' -api_platform: - formats: - json: ['application/json'] - doctrine: false - doctrine_mongodb_odm: true - keep_legacy_inflector: false - mapping: - paths: - - '%kernel.project_dir%/Fixtures/Document' - services: test.property_accessor: alias: property_accessor diff --git a/src/Doctrine/Odm/composer.json b/src/Doctrine/Odm/composer.json index 29718fd5cee..7e7fc7a7cd2 100644 --- a/src/Doctrine/Odm/composer.json +++ b/src/Doctrine/Odm/composer.json @@ -1,88 +1,71 @@ { - "name": "api-platform/doctrine-odm", - "description": "Doctrine MongoDB ODM bridge", - "type": "library", - "keywords": [ - "Doctrine", - "ODM", - "MongoDB" - ], - "homepage": "https://api-platform.com", - "license": "MIT", - "authors": [ - { - "name": "Kévin Dunglas", - "email": "kevin@dunglas.fr", - "homepage": "https://dunglas.fr" + "name": "api-platform/doctrine-odm", + "description": "Doctrine MongoDB ODM bridge", + "type": "library", + "keywords": [ + "Doctrine", + "ODM", + "MongoDB" + ], + "homepage": "https://api-platform.com", + "license": "MIT", + "authors": [ + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr", + "homepage": "https://dunglas.fr" + }, + { + "name": "API Platform Community", + "homepage": "https://api-platform.com/community/contributors" + } + ], + "require": { + "php": ">=8.1", + "api-platform/doctrine-common": "*@dev || ^3.1", + "api-platform/metadata": "*@dev || ^3.1", + "api-platform/state": "*@dev || ^3.1", + "doctrine/mongodb-odm": "^2.2", + "doctrine/mongodb-odm-bundle": "^5.0", + "symfony/property-info": "^6.4 || ^7.0" }, - { - "name": "API Platform Community", - "homepage": "https://api-platform.com/community/contributors" - } - ], - "require": { - "php": ">=8.1", - "api-platform/doctrine-common": "*@dev || ^3.1", - "api-platform/metadata": "*@dev || ^3.1", - "api-platform/state": "*@dev || ^3.1", - "doctrine/mongodb-odm": "^2.2", - "doctrine/mongodb-odm-bundle": "^5.0", - "symfony/property-info": "^6.4 || ^7.0" - }, - "require-dev": { - "api-platform/parameter-validator": "*@dev || ^3.2", - "api-platform/symfony": "*@dev || ^3.2", - "doctrine/doctrine-bundle": "^2.11", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^10.0", - "symfony/cache": "^6.4 || ^7.0", - "symfony/framework-bundle": "^6.4 || ^7.0", - "symfony/phpunit-bridge": "^6.4 || ^7.0", - "symfony/serializer": "^6.4 || ^7.0", - "symfony/yaml": "^6.4 || ^7.0" - }, - "autoload": { - "psr-4": { - "ApiPlatform\\Doctrine\\Odm\\": "" - } - }, - "config": { - "preferred-install": { - "*": "dist" + "require-dev": { + "api-platform/parameter-validator": "*@dev || ^3.2", + "doctrine/doctrine-bundle": "^2.11", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^10.0", + "symfony/cache": "^6.4 || ^7.0", + "symfony/framework-bundle": "^6.4 || ^7.0", + "symfony/phpunit-bridge": "^6.4 || ^7.0", + "symfony/property-access": "^6.4 || ^7.0", + "symfony/serializer": "^6.4 || ^7.0", + "symfony/uid": "^6.4 || ^7.0", + "symfony/validator": "^6.4 || ^7.0", + "symfony/yaml": "^6.4 || ^7.0" }, - "sort-packages": true, - "allow-plugins": { - "php-http/discovery": false - } - }, - "extra": { - "branch-alias": { - "dev-main": "3.2.x-dev" + "autoload": { + "psr-4": { + "ApiPlatform\\Doctrine\\Odm\\": "" + } + }, + "config": { + "preferred-install": { + "*": "dist" + }, + "sort-packages": true, + "allow-plugins": { + "php-http/discovery": false + } + }, + "extra": { + "branch-alias": { + "dev-main": "3.3.x-dev" + }, + "symfony": { + "require": "^6.4" + } }, - "symfony": { - "require": "^6.4" + "scripts": { + "test": "./vendor/bin/phpunit" } - }, - "repositories": [ - { - "type": "path", - "url": "../../Metadata" - }, - { - "type": "path", - "url": "../../State" - }, - { - "type": "path", - "url": "../Common" - }, - { - "type": "path", - "url": "../../Symfony" - }, - { - "type": "path", - "url": "../../ParameterValidator" - } - ] } diff --git a/src/Doctrine/Orm/Tests/AppKernel.php b/src/Doctrine/Orm/Tests/AppKernel.php index 22409c74f2f..29229e2f5bd 100644 --- a/src/Doctrine/Orm/Tests/AppKernel.php +++ b/src/Doctrine/Orm/Tests/AppKernel.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Tests; -use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; @@ -41,7 +40,6 @@ public function __construct(string $environment, bool $debug) public function registerBundles(): array { return [ - new ApiPlatformBundle(), new FrameworkBundle(), new DoctrineBundle(), new TestBundle(), diff --git a/src/Doctrine/Orm/Tests/Filter/BooleanFilterTest.php b/src/Doctrine/Orm/Tests/Filter/BooleanFilterTest.php index fa9425b746f..1fdd6aa46e8 100644 --- a/src/Doctrine/Orm/Tests/Filter/BooleanFilterTest.php +++ b/src/Doctrine/Orm/Tests/Filter/BooleanFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\BooleanFilterTestTrait; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Orm\Tests\DoctrineOrmFilterTestCase; use ApiPlatform\Doctrine\Orm\Tests\Fixtures\Entity\Dummy; diff --git a/src/Doctrine/Orm/Tests/Filter/BooleanFilterTestTrait.php b/src/Doctrine/Orm/Tests/Filter/BooleanFilterTestTrait.php new file mode 100644 index 00000000000..26c4ef232db --- /dev/null +++ b/src/Doctrine/Orm/Tests/Filter/BooleanFilterTestTrait.php @@ -0,0 +1,170 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Doctrine\Orm\Tests\Filter; + +/** + * @author Amrouche Hamza + */ +trait BooleanFilterTestTrait +{ + public function testGetDescription(): void + { + $filter = $this->buildFilter([ + 'id' => null, + 'name' => null, + 'foo' => null, + 'dummyBoolean' => null, + ]); + + $this->assertEquals([ + 'dummyBoolean' => [ + 'property' => 'dummyBoolean', + 'type' => 'bool', + 'required' => false, + ], + ], $filter->getDescription($this->resourceClass)); + } + + public function testGetDescriptionDefaultFields(): void + { + $filter = $this->buildFilter(); + + $this->assertEquals([ + 'dummyBoolean' => [ + 'property' => 'dummyBoolean', + 'type' => 'bool', + 'required' => false, + ], + ], $filter->getDescription($this->resourceClass)); + } + + private static function provideApplyTestArguments(): array + { + return [ + 'string ("true")' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'dummyBoolean' => 'true', + ], + ], + 'string ("false")' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'dummyBoolean' => 'false', + ], + ], + 'non-boolean' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'dummyBoolean' => 'toto', + ], + ], + 'numeric string ("0")' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'dummyBoolean' => '0', + ], + ], + 'numeric string ("1")' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'dummyBoolean' => '1', + ], + ], + 'nested properties' => [ + [ + 'id' => null, + 'name' => null, + 'relatedDummy.dummyBoolean' => null, + ], + [ + 'relatedDummy.dummyBoolean' => '1', + ], + ], + 'numeric string ("1") on non-boolean property' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'name' => '1', + ], + ], + 'numeric string ("0") on non-boolean property' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'name' => '0', + ], + ], + 'string ("true") on non-boolean property' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'name' => 'true', + ], + ], + 'string ("false") on non-boolean property' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'name' => 'false', + ], + ], + 'mixed boolean, non-boolean and invalid property' => [ + [ + 'id' => null, + 'name' => null, + 'dummyBoolean' => null, + ], + [ + 'dummyBoolean' => 'false', + 'toto' => 'toto', + 'name' => 'true', + 'id' => '0', + ], + ], + ]; + } +} diff --git a/src/Doctrine/Orm/Tests/Filter/DateFilterTest.php b/src/Doctrine/Orm/Tests/Filter/DateFilterTest.php index 91e6aa4fd27..01d5e72f483 100644 --- a/src/Doctrine/Orm/Tests/Filter/DateFilterTest.php +++ b/src/Doctrine/Orm/Tests/Filter/DateFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\DateFilterTestTrait; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Doctrine\Orm\Tests\DoctrineOrmFilterTestCase; use ApiPlatform\Doctrine\Orm\Tests\Fixtures\Entity\Dummy; diff --git a/src/Doctrine/Orm/Tests/Filter/DateFilterTestTrait.php b/src/Doctrine/Orm/Tests/Filter/DateFilterTestTrait.php new file mode 100644 index 00000000000..24c00e4a6a4 --- /dev/null +++ b/src/Doctrine/Orm/Tests/Filter/DateFilterTestTrait.php @@ -0,0 +1,229 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Doctrine\Orm\Tests\Filter; + +/** + * @author Théo FIDRY + * @author Vincent CHALAMON + */ +trait DateFilterTestTrait +{ + public function testGetDescription(): void + { + $filter = $this->buildFilter(); + + $this->assertEquals([ + 'dummyDate[before]' => [ + 'property' => 'dummyDate', + 'type' => \DateTimeInterface::class, + 'required' => false, + ], + 'dummyDate[strictly_before]' => [ + 'property' => 'dummyDate', + 'type' => \DateTimeInterface::class, + 'required' => false, + ], + 'dummyDate[after]' => [ + 'property' => 'dummyDate', + 'type' => \DateTimeInterface::class, + 'required' => false, + ], + 'dummyDate[strictly_after]' => [ + 'property' => 'dummyDate', + 'type' => \DateTimeInterface::class, + 'required' => false, + ], + ], $filter->getDescription($this->resourceClass)); + } + + private static function provideApplyTestArguments(): array + { + return [ + 'after (all properties enabled)' => [ + null, + [ + 'dummyDate' => [ + 'after' => '2015-04-05', + ], + ], + ], + 'after but not equals (all properties enabled)' => [ + null, + [ + 'dummyDate' => [ + 'strictly_after' => '2015-04-05', + ], + ], + ], + 'after' => [ + [ + 'dummyDate' => null, + ], + [ + 'dummyDate' => [ + 'after' => '2015-04-05', + ], + ], + ], + 'after but not equals' => [ + [ + 'dummyDate' => null, + ], + [ + 'dummyDate' => [ + 'strictly_after' => '2015-04-05', + ], + ], + ], + 'before (all properties enabled)' => [ + null, + [ + 'dummyDate' => [ + 'before' => '2015-04-05', + ], + ], + ], + 'before but not equals (all properties enabled)' => [ + null, + [ + 'dummyDate' => [ + 'strictly_before' => '2015-04-05', + ], + ], + ], + 'before' => [ + [ + 'dummyDate' => null, + ], + [ + 'dummyDate' => [ + 'before' => '2015-04-05', + ], + ], + ], + 'before but not equals' => [ + [ + 'dummyDate' => null, + ], + [ + 'dummyDate' => [ + 'strictly_before' => '2015-04-05', + ], + ], + ], + 'before + after (all properties enabled)' => [ + null, + [ + 'dummyDate' => [ + 'after' => '2015-04-05', + 'before' => '2015-04-05', + ], + ], + ], + 'before but not equals + after but not equals (all properties enabled)' => [ + null, + [ + 'dummyDate' => [ + 'strictly_after' => '2015-04-05', + 'strictly_before' => '2015-04-05', + ], + ], + ], + 'before + after' => [ + [ + 'dummyDate' => null, + ], + [ + 'dummyDate' => [ + 'after' => '2015-04-05', + 'before' => '2015-04-05', + ], + ], + ], + 'before but not equals + after but not equals' => [ + [ + 'dummyDate' => null, + ], + [ + 'dummyDate' => [ + 'strictly_after' => '2015-04-05', + 'strictly_before' => '2015-04-05', + ], + ], + ], + 'property not enabled' => [ + [ + 'unknown' => null, + ], + [ + 'dummyDate' => [ + 'after' => '2015-04-05', + 'before' => '2015-04-05', + ], + ], + ], + 'nested property' => [ + [ + 'relatedDummy.dummyDate' => null, + ], + [ + 'relatedDummy.dummyDate' => [ + 'after' => '2015-04-05', + ], + ], + ], + 'after (exclude_null)' => [ + [ + 'dummyDate' => 'exclude_null', + ], + [ + 'dummyDate' => [ + 'after' => '2015-04-05', + ], + ], + ], + 'after (include_null_after)' => [ + [ + 'dummyDate' => 'include_null_after', + ], + [ + 'dummyDate' => [ + 'after' => '2015-04-05', + ], + ], + ], + 'include null before and after (include_null_before_and_after)' => [ + [ + 'dummyDate' => 'include_null_before_and_after', + ], + [ + 'dummyDate' => [ + 'after' => '2015-04-05', + ], + ], + ], + 'bad date format' => [ + [ + 'dummyDate' => null, + ], + [ + 'dummyDate' => [ + 'after' => '1932iur123ufqe', + 'before' => [], + ], + ], + ], + ]; + } +} diff --git a/src/Doctrine/Orm/Tests/Filter/ExistsFilterTest.php b/src/Doctrine/Orm/Tests/Filter/ExistsFilterTest.php index eb2e30add8f..9f3f345b284 100644 --- a/src/Doctrine/Orm/Tests/Filter/ExistsFilterTest.php +++ b/src/Doctrine/Orm/Tests/Filter/ExistsFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\ExistsFilterTestTrait; use ApiPlatform\Doctrine\Orm\Filter\ExistsFilter; use ApiPlatform\Doctrine\Orm\Tests\DoctrineOrmFilterTestCase; use ApiPlatform\Doctrine\Orm\Tests\Fixtures\CustomConverter; diff --git a/src/Doctrine/Orm/Tests/Filter/ExistsFilterTestTrait.php b/src/Doctrine/Orm/Tests/Filter/ExistsFilterTestTrait.php new file mode 100644 index 00000000000..1fcf2d51756 --- /dev/null +++ b/src/Doctrine/Orm/Tests/Filter/ExistsFilterTestTrait.php @@ -0,0 +1,280 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Doctrine\Orm\Tests\Filter; + +/** + * @author Antoine Bluchet + */ +trait ExistsFilterTestTrait +{ + public function testGetDescription(): void + { + $filter = $this->buildFilter(['name' => null, 'description' => null]); + + $this->assertEquals([ + 'exists[description]' => [ + 'property' => 'description', + 'type' => 'bool', + 'required' => false, + ], + ], $filter->getDescription($this->resourceClass)); + } + + private static function provideApplyTestArguments(): array + { + return [ + 'valid values' => [ + [ + 'description' => null, + ], + [ + 'exists' => [ + 'description' => 'true', + ], + ], + ], + + 'valid values (empty for true)' => [ + [ + 'description' => null, + ], + [ + 'exists' => [ + 'description' => '', + ], + ], + ], + + 'valid values (1 for true)' => [ + [ + 'description' => null, + ], + [ + 'exists' => [ + 'description' => '1', + ], + ], + ], + + 'invalid values' => [ + [ + 'description' => null, + ], + [ + 'exists' => [ + 'description' => 'invalid', + ], + ], + ], + + 'negative values' => [ + [ + 'description' => null, + ], + [ + 'exists' => [ + 'description' => 'false', + ], + ], + ], + + 'negative values (0)' => [ + [ + 'description' => null, + ], + [ + 'exists' => [ + 'description' => '0', + ], + ], + ], + + 'multiple values (true and true)' => [ + [ + 'alias' => null, + 'description' => null, + ], + [ + 'exists' => [ + 'alias' => 'true', + 'description' => 'true', + ], + ], + ], + + 'multiple values (1 and 0)' => [ + [ + 'alias' => null, + 'description' => null, + ], + [ + 'exists' => [ + 'alias' => '1', + 'description' => '0', + ], + ], + ], + + 'multiple values (false and 0)' => [ + [ + 'alias' => null, + 'description' => null, + ], + [ + 'exists' => [ + 'alias' => 'false', + 'description' => '0', + ], + ], + ], + + 'custom exists parameter name' => [ + [ + 'alias' => null, + 'description' => null, + ], + [ + 'exists' => [ + 'alias' => 'true', + ], + 'customExists' => [ + 'description' => 'true', + ], + ], + ], + + 'related values' => [ + [ + 'description' => null, + 'relatedDummy.name' => null, + ], + [ + 'exists' => [ + 'description' => '1', + 'relatedDummy.name' => '1', + ], + ], + ], + + 'not nullable values' => [ + [ + 'description' => null, + 'name' => null, + ], + [ + 'exists' => [ + 'description' => '1', + 'name' => '0', + ], + ], + ], + + 'related collection not empty' => [ + [ + 'description' => null, + 'relatedDummies' => null, + ], + [ + 'exists' => [ + 'description' => '1', + 'relatedDummies' => '1', + ], + ], + ], + + 'related collection empty' => [ + [ + 'description' => null, + 'relatedDummies' => null, + ], + [ + 'exists' => [ + 'description' => '1', + 'relatedDummies' => '0', + ], + ], + ], + + 'related association exists' => [ + [ + 'description' => null, + 'relatedDummy' => null, + ], + [ + 'exists' => [ + 'description' => '1', + 'relatedDummy' => '1', + ], + ], + ], + + 'related association does not exist' => [ + [ + 'description' => null, + 'relatedDummy' => null, + ], + [ + 'exists' => [ + 'description' => '1', + 'relatedDummy' => '0', + ], + ], + ], + + 'related owned association does not exist' => [ + [ + 'relatedOwnedDummy' => null, + ], + [ + 'exists' => [ + 'relatedOwnedDummy' => '0', + ], + ], + ], + + 'related owned association exists' => [ + [ + 'relatedOwnedDummy' => null, + ], + [ + 'exists' => [ + 'relatedOwnedDummy' => '1', + ], + ], + ], + + 'related owning association does not exist' => [ + [ + 'relatedOwningDummy' => null, + ], + [ + 'exists' => [ + 'relatedOwningDummy' => '0', + ], + ], + ], + + 'related owning association exists' => [ + [ + 'relatedOwningDummy' => null, + ], + [ + 'exists' => [ + 'relatedOwningDummy' => '1', + ], + ], + ], + ]; + } +} diff --git a/src/Doctrine/Orm/Tests/Filter/NumericFilterTest.php b/src/Doctrine/Orm/Tests/Filter/NumericFilterTest.php index d3322ce064c..d5a4eda625b 100644 --- a/src/Doctrine/Orm/Tests/Filter/NumericFilterTest.php +++ b/src/Doctrine/Orm/Tests/Filter/NumericFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\NumericFilterTestTrait; use ApiPlatform\Doctrine\Orm\Filter\NumericFilter; use ApiPlatform\Doctrine\Orm\Tests\DoctrineOrmFilterTestCase; use ApiPlatform\Doctrine\Orm\Tests\Fixtures\Entity\Dummy; diff --git a/src/Doctrine/Orm/Tests/Filter/NumericFilterTestTrait.php b/src/Doctrine/Orm/Tests/Filter/NumericFilterTestTrait.php new file mode 100644 index 00000000000..3941852784c --- /dev/null +++ b/src/Doctrine/Orm/Tests/Filter/NumericFilterTestTrait.php @@ -0,0 +1,206 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Doctrine\Orm\Tests\Filter; + +/** + * @author Amrouche Hamza + */ +trait NumericFilterTestTrait +{ + public function testGetDescription(): void + { + $filter = $this->buildFilter([ + 'id' => null, + 'name' => null, + 'foo' => null, + 'dummyBoolean' => null, + ]); + + $this->assertEquals([ + 'id' => [ + 'property' => 'id', + 'type' => 'int', + 'required' => false, + 'is_collection' => false, + ], + 'id[]' => [ + 'property' => 'id', + 'type' => 'int', + 'required' => false, + 'is_collection' => true, + ], + ], $filter->getDescription($this->resourceClass)); + } + + public function testGetDescriptionDefaultFields(): void + { + $filter = $this->buildFilter(); + + $this->assertEquals([ + 'id' => [ + 'property' => 'id', + 'type' => 'int', + 'required' => false, + 'is_collection' => false, + ], + 'id[]' => [ + 'property' => 'id', + 'type' => 'int', + 'required' => false, + 'is_collection' => true, + ], + 'dummyFloat' => [ + 'property' => 'dummyFloat', + 'type' => 'float', + 'required' => false, + 'is_collection' => false, + ], + 'dummyFloat[]' => [ + 'property' => 'dummyFloat', + 'type' => 'float', + 'required' => false, + 'is_collection' => true, + ], + 'dummyPrice' => [ + 'property' => 'dummyPrice', + 'type' => 'string', + 'required' => false, + 'is_collection' => false, + ], + 'dummyPrice[]' => [ + 'property' => 'dummyPrice', + 'type' => 'string', + 'required' => false, + 'is_collection' => true, + ], + ], $filter->getDescription($this->resourceClass)); + } + + private static function provideApplyTestArguments(): array + { + return [ + 'numeric string (positive integer)' => [ + [ + 'id' => null, + 'name' => null, + 'dummyPrice' => null, + ], + [ + 'dummyPrice' => '21', + ], + ], + 'multiple numeric string (positive integer)' => [ + [ + 'id' => null, + 'name' => null, + 'dummyPrice' => null, + ], + [ + 'dummyPrice' => ['21', '22'], + ], + ], + 'multiple numeric string with one invalid property key' => [ + [ + 'id' => null, + 'name' => null, + 'dummyPrice' => null, + ], + [ + 'dummyPrice' => ['invalid' => '21', '22'], + ], + ], + 'multiple numeric string with invalid value keys' => [ + [ + 'id' => null, + 'name' => null, + 'dummyPrice' => null, + ], + [ + 'dummyPrice' => ['invalid' => '21', 'invalid2' => '22'], + ], + ], + 'multiple non-numeric' => [ + [ + 'id' => null, + 'name' => null, + 'dummyPrice' => null, + ], + [ + 'dummyPrice' => ['test', 'invalid'], + ], + ], + 'numeric string (negative integer)' => [ + [ + 'id' => null, + 'name' => null, + 'dummyPrice' => null, + ], + [ + 'dummyPrice' => '-21', + ], + ], + 'non-numeric' => [ + [ + 'id' => null, + ], + [ + 'id' => 'toto', + ], + ], + 'numeric string ("0")' => [ + [ + 'id' => null, + 'name' => null, + 'dummyPrice' => null, + ], + [ + 'dummyPrice' => 0, + ], + ], + 'nested property' => [ + [ + 'id' => null, + 'name' => null, + 'relatedDummy.id' => null, + ], + [ + 'relatedDummy.id' => 0, + ], + ], + 'mixed numeric and non-numeric' => [ + [ + 'id' => null, + 'name' => null, + 'dummyPrice' => null, + ], + [ + 'dummyPrice' => 10, + 'name' => '15toto', + ], + ], + 'mixed numeric, non-numeric and invalid property' => [ + [ + 'id' => null, + 'name' => null, + 'dummyPrice' => null, + ], + [ + 'toto' => 'toto', + 'name' => 'gerard', + 'dummyPrice' => '0', + ], + ], + ]; + } +} diff --git a/src/Doctrine/Orm/Tests/Filter/OrderFilterTest.php b/src/Doctrine/Orm/Tests/Filter/OrderFilterTest.php index c83142cd2fe..3838290c669 100644 --- a/src/Doctrine/Orm/Tests/Filter/OrderFilterTest.php +++ b/src/Doctrine/Orm/Tests/Filter/OrderFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\OrderFilterTestTrait; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Tests\DoctrineOrmFilterTestCase; use ApiPlatform\Doctrine\Orm\Tests\Fixtures\CustomConverter; diff --git a/src/Doctrine/Orm/Tests/Filter/OrderFilterTestTrait.php b/src/Doctrine/Orm/Tests/Filter/OrderFilterTestTrait.php new file mode 100644 index 00000000000..2409ae8b083 --- /dev/null +++ b/src/Doctrine/Orm/Tests/Filter/OrderFilterTestTrait.php @@ -0,0 +1,338 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Doctrine\Orm\Tests\Filter; + +/** + * @author Théo FIDRY + * @author Vincent CHALAMON + */ +trait OrderFilterTestTrait +{ + public function testGetDescription(): void + { + $filter = $this->buildFilter(['id' => null, 'name' => null, 'foo' => null]); + + $this->assertEquals([ + 'order[id]' => [ + 'property' => 'id', + 'type' => 'string', + 'required' => false, + 'schema' => [ + 'type' => 'string', + 'enum' => [ + 'asc', + 'desc', + ], + ], + ], + 'order[name]' => [ + 'property' => 'name', + 'type' => 'string', + 'required' => false, + 'schema' => [ + 'type' => 'string', + 'enum' => [ + 'asc', + 'desc', + ], + ], + ], + ], $filter->getDescription($this->resourceClass)); + } + + private static function provideApplyTestArguments(): array + { + return [ + 'valid values' => [ + [ + 'id' => null, + 'name' => null, + ], + [ + 'order' => [ + 'id' => 'asc', + 'name' => 'desc', + ], + ], + ], + 'invalid values' => [ + [ + 'id' => null, + 'name' => null, + ], + [ + 'order' => [ + 'id' => 'asc', + 'name' => 'invalid', + ], + ], + ], + 'valid values (properties not enabled)' => [ + [ + 'id' => null, + 'name' => null, + ], + [ + 'order' => [ + 'id' => 'asc', + 'alias' => 'asc', + ], + ], + ], + 'invalid values (properties not enabled)' => [ + [ + 'id' => null, + 'name' => null, + ], + [ + 'order' => [ + 'id' => 'invalid', + 'name' => 'asc', + 'alias' => 'invalid', + ], + ], + ], + 'invalid property (property not enabled)' => [ + [ + 'id' => null, + 'name' => null, + ], + [ + 'order' => [ + 'unknown' => 'asc', + ], + ], + ], + 'invalid property (property enabled)' => [ + [ + 'id' => null, + 'name' => null, + 'unknown' => null, + ], + [ + 'order' => [ + 'unknown' => 'asc', + ], + ], + ], + 'custom order parameter name' => [ + [ + 'id' => null, + 'name' => null, + ], + [ + 'order' => [ + 'id' => 'asc', + 'name' => 'asc', + ], + 'customOrder' => [ + 'name' => 'desc', + ], + ], + ], + 'valid values (all properties enabled)' => [ + null, + [ + 'order' => [ + 'id' => 'asc', + 'name' => 'asc', + ], + ], + ], + 'nested property' => [ + [ + 'id' => null, + 'name' => null, + 'relatedDummy.symfony' => null, + ], + [ + 'order' => [ + 'id' => 'asc', + 'name' => 'desc', + 'relatedDummy.symfony' => 'desc', + ], + ], + ], + 'empty values with default sort direction' => [ + [ + 'id' => 'asc', + 'name' => 'desc', + ], + [ + 'order' => [ + 'id' => null, + 'name' => null, + ], + ], + ], + 'nulls_smallest (asc)' => [ + [ + 'dummyDate' => [ + 'nulls_comparison' => 'nulls_smallest', + ], + 'name' => null, + ], + [ + 'order' => [ + 'dummyDate' => 'asc', + 'name' => 'desc', + ], + ], + ], + 'nulls_smallest (desc)' => [ + [ + 'dummyDate' => [ + 'nulls_comparison' => 'nulls_smallest', + ], + 'name' => null, + ], + [ + 'order' => [ + 'dummyDate' => 'desc', + 'name' => 'desc', + ], + ], + ], + 'nulls_largest (asc)' => [ + [ + 'dummyDate' => [ + 'nulls_comparison' => 'nulls_largest', + ], + 'name' => null, + ], + [ + 'order' => [ + 'dummyDate' => 'asc', + 'name' => 'desc', + ], + ], + ], + 'nulls_largest (desc)' => [ + [ + 'dummyDate' => [ + 'nulls_comparison' => 'nulls_largest', + ], + 'name' => null, + ], + [ + 'order' => [ + 'dummyDate' => 'desc', + 'name' => 'desc', + ], + ], + ], + 'nulls_always_first (asc)' => [ + [ + 'dummyDate' => [ + 'nulls_comparison' => 'nulls_always_first', + ], + 'name' => null, + ], + [ + 'order' => [ + 'dummyDate' => 'asc', + 'name' => 'desc', + ], + ], + ], + 'nulls_always_first (desc)' => [ + [ + 'dummyDate' => [ + 'nulls_comparison' => 'nulls_always_first', + ], + 'name' => null, + ], + [ + 'order' => [ + 'dummyDate' => 'desc', + 'name' => 'desc', + ], + ], + ], + 'nulls_always_last (asc)' => [ + [ + 'dummyDate' => [ + 'nulls_comparison' => 'nulls_always_last', + ], + 'name' => null, + ], + [ + 'order' => [ + 'dummyDate' => 'asc', + 'name' => 'desc', + ], + ], + ], + 'nulls_always_last (desc)' => [ + [ + 'dummyDate' => [ + 'nulls_comparison' => 'nulls_always_last', + ], + 'name' => null, + ], + [ + 'order' => [ + 'dummyDate' => 'desc', + 'name' => 'desc', + ], + ], + ], + 'not having order should not throw a deprecation (select unchanged)' => [ + [ + 'id' => null, + 'name' => null, + ], + [ + 'name' => 'q', + ], + ], + 'not nullable relation will be a LEFT JOIN' => [ + [ + 'relatedDummy.name' => 'ASC', + ], + [ + 'order' => ['relatedDummy.name' => 'ASC'], + ], + ], + 'embedded' => [ + [ + 'embeddedDummy.dummyName' => 'ASC', + ], + [ + 'order' => ['embeddedDummy.dummyName' => 'ASC'], + ], + ], + 'embedded with nulls_comparison' => [ + [ + 'embeddedDummy.dummyName' => [ + 'nulls_comparison' => 'nulls_largest', + ], + ], + [ + 'order' => [ + 'embeddedDummy.dummyName' => 'ASC', + ], + ], + ], + 'nullable field in relation will be a LEFT JOIN' => [ + [ + 'relatedDummy.name' => null, + ], + [ + 'order' => ['relatedDummy.name' => 'ASC'], + ], + ], + ]; + } +} diff --git a/src/Doctrine/Orm/Tests/Filter/RangeFilterTest.php b/src/Doctrine/Orm/Tests/Filter/RangeFilterTest.php index 82305807c06..ac31b95ecb4 100644 --- a/src/Doctrine/Orm/Tests/Filter/RangeFilterTest.php +++ b/src/Doctrine/Orm/Tests/Filter/RangeFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\RangeFilterTestTrait; use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; use ApiPlatform\Doctrine\Orm\Tests\DoctrineOrmFilterTestCase; use ApiPlatform\Doctrine\Orm\Tests\Fixtures\Entity\Dummy; diff --git a/src/Doctrine/Orm/Tests/Filter/RangeFilterTestTrait.php b/src/Doctrine/Orm/Tests/Filter/RangeFilterTestTrait.php new file mode 100644 index 00000000000..1d2646c231b --- /dev/null +++ b/src/Doctrine/Orm/Tests/Filter/RangeFilterTestTrait.php @@ -0,0 +1,139 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Doctrine\Orm\Tests\Filter; + +/** + * @author Lee Siong Chan + */ +trait RangeFilterTestTrait +{ + private static function provideApplyTestArguments(): array + { + return [ + 'between' => [ + null, + [ + 'dummyPrice' => [ + 'between' => '9.99..15.99', + ], + ], + ], + 'between (same values)' => [ + null, + [ + 'dummyPrice' => [ + 'between' => '9.99..9.99', + ], + ], + ], + 'between (too many operands)' => [ + null, + [ + 'dummyPrice' => [ + 'between' => '9.99..15.99..99.99', + ], + ], + ], + 'between (too few operands)' => [ + null, + [ + 'dummyPrice' => [ + 'between' => '15.99', + ], + ], + ], + 'between (non-numeric operands)' => [ + null, + [ + 'dummyPrice' => [ + 'between' => 'abc..def', + ], + ], + ], + 'lt' => [ + null, + [ + 'dummyPrice' => [ + 'lt' => '9.99', + ], + ], + ], + 'lt (non-numeric)' => [ + null, + [ + 'dummyPrice' => [ + 'lt' => '127.0.0.1', + ], + ], + ], + 'lte' => [ + null, + [ + 'dummyPrice' => [ + 'lte' => '9.99', + ], + ], + ], + 'lte (non-numeric)' => [ + null, + [ + 'dummyPrice' => [ + 'lte' => '127.0.0.1', + ], + ], + ], + 'gt' => [ + null, + [ + 'dummyPrice' => [ + 'gt' => '9.99', + ], + ], + ], + 'gt (non-numeric)' => [ + null, + [ + 'dummyPrice' => [ + 'gt' => '127.0.0.1', + ], + ], + ], + 'gte' => [ + null, + [ + 'dummyPrice' => [ + 'gte' => '9.99', + ], + ], + ], + 'gte (non-numeric)' => [ + null, + [ + 'dummyPrice' => [ + 'gte' => '127.0.0.1', + ], + ], + ], + 'lte + gte' => [ + null, + [ + 'dummyPrice' => [ + 'gte' => '9.99', + 'lte' => '19.99', + ], + ], + ], + ]; + } +} diff --git a/src/Doctrine/Orm/Tests/Filter/SearchFilterTest.php b/src/Doctrine/Orm/Tests/Filter/SearchFilterTest.php index 7b81fdce7d3..89f2e3f372e 100644 --- a/src/Doctrine/Orm/Tests/Filter/SearchFilterTest.php +++ b/src/Doctrine/Orm/Tests/Filter/SearchFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Tests\Filter; -use ApiPlatform\Doctrine\Common\Tests\Filter\SearchFilterTestTrait; use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Tests\DoctrineOrmFilterTestCase; use ApiPlatform\Doctrine\Orm\Tests\Fixtures\CustomConverter; diff --git a/src/Doctrine/Orm/Tests/Filter/SearchFilterTestTrait.php b/src/Doctrine/Orm/Tests/Filter/SearchFilterTestTrait.php new file mode 100644 index 00000000000..a538ddbcd46 --- /dev/null +++ b/src/Doctrine/Orm/Tests/Filter/SearchFilterTestTrait.php @@ -0,0 +1,517 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Doctrine\Orm\Tests\Filter; + +/** + * @author Julien Deniau + * @author Vincent CHALAMON + */ +trait SearchFilterTestTrait +{ + public function testGetDescription(): void + { + $filter = $this->buildSearchFilter($this, $this->managerRegistry, [ + 'id' => null, + 'name' => null, + 'alias' => null, + 'dummy' => null, + 'dummyDate' => null, + 'jsonData' => null, + 'arrayData' => null, + 'nameConverted' => null, + 'foo' => null, + 'relatedDummies.dummyDate' => null, + 'relatedDummy' => null, + ]); + + $this->assertEquals([ + 'id' => [ + 'property' => 'id', + 'type' => 'int', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'id[]' => [ + 'property' => 'id', + 'type' => 'int', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + 'name' => [ + 'property' => 'name', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'name[]' => [ + 'property' => 'name', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + 'alias' => [ + 'property' => 'alias', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'alias[]' => [ + 'property' => 'alias', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + 'dummy' => [ + 'property' => 'dummy', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'dummy[]' => [ + 'property' => 'dummy', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + 'dummyDate' => [ + 'property' => 'dummyDate', + 'type' => \DateTimeInterface::class, + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'dummyDate[]' => [ + 'property' => 'dummyDate', + 'type' => \DateTimeInterface::class, + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + 'jsonData' => [ + 'property' => 'jsonData', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'jsonData[]' => [ + 'property' => 'jsonData', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + 'arrayData' => [ + 'property' => 'arrayData', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'arrayData[]' => [ + 'property' => 'arrayData', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + 'name_converted' => [ + 'property' => 'name_converted', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'name_converted[]' => [ + 'property' => 'name_converted', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + 'relatedDummies.dummyDate' => [ + 'property' => 'relatedDummies.dummyDate', + 'type' => \DateTimeInterface::class, + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'relatedDummies.dummyDate[]' => [ + 'property' => 'relatedDummies.dummyDate', + 'type' => \DateTimeInterface::class, + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + 'relatedDummy' => [ + 'property' => 'relatedDummy', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => false, + ], + 'relatedDummy[]' => [ + 'property' => 'relatedDummy', + 'type' => 'string', + 'required' => false, + 'strategy' => 'exact', + 'is_collection' => true, + ], + ], $filter->getDescription($this->resourceClass)); + } + + private static function provideApplyTestArguments(): array + { + return [ + 'exact' => [ + [ + 'id' => null, + 'name' => null, + ], + [ + 'name' => 'exact', + ], + ], + 'exact (case insensitive)' => [ + [ + 'id' => null, + 'name' => 'iexact', + ], + [ + 'name' => 'exact', + ], + ], + 'exact (case insensitive, with special characters)' => [ + [ + 'id' => null, + 'name' => 'iexact', + ], + [ + 'name' => 'exact (special)', + ], + ], + 'exact (multiple values)' => [ + [ + 'id' => null, + 'name' => 'exact', + ], + [ + 'name' => [ + 'CaSE', + 'SENSitive', + ], + ], + ], + 'exact (multiple values; case insensitive)' => [ + [ + 'id' => null, + 'name' => 'iexact', + ], + [ + 'name' => [ + 'CaSE', + 'inSENSitive', + ], + ], + ], + 'invalid property' => [ + [ + 'id' => null, + 'name' => null, + ], + [ + 'foo' => 'exact', + ], + ], + 'invalid values for relations' => [ + [ + 'id' => null, + 'name' => null, + 'relatedDummy' => null, + 'relatedDummies' => null, + ], + [ + 'name' => ['foo'], + 'relatedDummy' => ['foo'], + 'relatedDummies' => [['foo']], + ], + ], + 'partial' => [ + [ + 'id' => null, + 'name' => 'partial', + ], + [ + 'name' => 'partial', + ], + ], + 'partial (case insensitive)' => [ + [ + 'id' => null, + 'name' => 'ipartial', + ], + [ + 'name' => 'partial', + ], + ], + 'partial (multiple values)' => [ + [ + 'id' => null, + 'name' => 'partial', + ], + [ + 'name' => [ + 'CaSE', + 'SENSitive', + ], + ], + ], + 'partial (multiple values; case insensitive)' => [ + [ + 'id' => null, + 'name' => 'ipartial', + ], + [ + 'name' => [ + 'CaSE', + 'inSENSitive', + ], + ], + ], + 'partial (multiple almost same values; case insensitive)' => [ + [ + 'id' => null, + 'name' => 'ipartial', + ], + [ + 'name' => [ + 'blue car', + 'Blue Car', + ], + ], + ], + 'start' => [ + [ + 'id' => null, + 'name' => 'start', + ], + [ + 'name' => 'partial', + ], + ], + 'start (case insensitive)' => [ + [ + 'id' => null, + 'name' => 'istart', + ], + [ + 'name' => 'partial', + ], + ], + 'start (multiple values)' => [ + [ + 'id' => null, + 'name' => 'start', + ], + [ + 'name' => [ + 'CaSE', + 'SENSitive', + ], + ], + ], + 'start (multiple values; case insensitive)' => [ + [ + 'id' => null, + 'name' => 'istart', + ], + [ + 'name' => [ + 'CaSE', + 'inSENSitive', + ], + ], + ], + 'end' => [ + [ + 'id' => null, + 'name' => 'end', + ], + [ + 'name' => 'partial', + ], + ], + 'end (case insensitive)' => [ + [ + 'id' => null, + 'name' => 'iend', + ], + [ + 'name' => 'partial', + ], + ], + 'end (multiple values)' => [ + [ + 'id' => null, + 'name' => 'end', + ], + [ + 'name' => [ + 'CaSE', + 'SENSitive', + ], + ], + ], + 'end (multiple values; case insensitive)' => [ + [ + 'id' => null, + 'name' => 'iend', + ], + [ + 'name' => [ + 'CaSE', + 'inSENSitive', + ], + ], + ], + 'word_start' => [ + [ + 'id' => null, + 'name' => 'word_start', + ], + [ + 'name' => 'partial', + ], + ], + 'word_start (case insensitive)' => [ + [ + 'id' => null, + 'name' => 'iword_start', + ], + [ + 'name' => 'partial', + ], + ], + 'word_start (multiple values)' => [ + [ + 'id' => null, + 'name' => 'word_start', + ], + [ + 'name' => [ + 'CaSE', + 'SENSitive', + ], + ], + ], + 'word_start (multiple values; case insensitive)' => [ + [ + 'id' => null, + 'name' => 'iword_start', + ], + [ + 'name' => [ + 'CaSE', + 'inSENSitive', + ], + ], + ], + 'invalid value for relation' => [ + [ + 'id' => null, + 'name' => null, + 'relatedDummy' => null, + ], + [ + 'relatedDummy' => 'exact', + ], + ], + 'IRI value for relation' => [ + [ + 'id' => null, + 'name' => null, + 'relatedDummy.id' => null, + ], + [ + 'relatedDummy.id' => '/related_dummies/1', + ], + ], + 'mixed IRI and entity ID values for relations' => [ + [ + 'id' => null, + 'name' => null, + 'relatedDummy' => null, + 'relatedDummies' => null, + ], + [ + 'relatedDummy' => ['/related_dummies/1', '2'], + 'relatedDummies' => '1', + ], + ], + 'nested property' => [ + [ + 'id' => null, + 'name' => null, + 'relatedDummy.symfony' => null, + ], + [ + 'name' => 'exact', + 'relatedDummy.symfony' => 'exact', + ], + ], + 'empty nested property' => [ + [ + 'relatedDummy.symfony' => null, + ], + [ + 'relatedDummy.symfony' => [], + ], + ], + 'integer value' => [ + [ + 'age' => 'exact', + ], + [ + 'age' => 46, + ], + ], + 'related owned one-to-one association' => [ + [ + 'id' => null, + 'relatedOwnedDummy' => null, + ], + [ + 'relatedOwnedDummy' => 1, + ], + ], + 'related owning one-to-one association' => [ + [ + 'id' => null, + 'relatedOwningDummy' => null, + ], + [ + 'relatedOwningDummy' => 1, + ], + ], + ]; + } +} diff --git a/src/Doctrine/Orm/Tests/config.yml b/src/Doctrine/Orm/Tests/config.yml index 120b389c639..700332dc95a 100644 --- a/src/Doctrine/Orm/Tests/config.yml +++ b/src/Doctrine/Orm/Tests/config.yml @@ -17,15 +17,6 @@ doctrine: prefix: ApiPlatform\Doctrine\Orm\Tests\Fixtures\Entity alias: App -api_platform: - formats: - json: ['application/json'] - doctrine: true - keep_legacy_inflector: false - mapping: - paths: - - '%kernel.project_dir%/Fixtures/Entity' - services: test.property_accessor: alias: property_accessor diff --git a/src/Doctrine/Orm/composer.json b/src/Doctrine/Orm/composer.json index 982e56fdd90..58a490d9bc1 100644 --- a/src/Doctrine/Orm/composer.json +++ b/src/Doctrine/Orm/composer.json @@ -1,88 +1,71 @@ { - "name": "api-platform/doctrine-orm", - "description": "Doctrine ORM bridge", - "type": "library", - "keywords": [ - "Doctrine", - "ORM" - ], - "homepage": "https://api-platform.com", - "license": "MIT", - "authors": [ - { - "name": "Kévin Dunglas", - "email": "kevin@dunglas.fr", - "homepage": "https://dunglas.fr" + "name": "api-platform/doctrine-orm", + "description": "Doctrine ORM bridge", + "type": "library", + "keywords": [ + "Doctrine", + "ORM" + ], + "homepage": "https://api-platform.com", + "license": "MIT", + "authors": [ + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr", + "homepage": "https://dunglas.fr" + }, + { + "name": "API Platform Community", + "homepage": "https://api-platform.com/community/contributors" + } + ], + "require": { + "php": ">=8.1", + "api-platform/doctrine-common": "*@dev || ^3.1", + "api-platform/metadata": "*@dev || ^3.1", + "api-platform/state": "*@dev || ^3.1", + "doctrine/doctrine-bundle": "^2.11", + "doctrine/orm": "^2.17", + "symfony/property-info": "^6.4 || ^7.0" }, - { - "name": "API Platform Community", - "homepage": "https://api-platform.com/community/contributors" - } - ], - "require": { - "php": ">=8.1", - "api-platform/doctrine-common": "*@dev || ^3.1", - "api-platform/metadata": "*@dev || ^3.1", - "api-platform/state": "*@dev || ^3.1", - "doctrine/doctrine-bundle": "^2.11", - "doctrine/orm": "^2.17", - "symfony/property-info": "^6.4 || ^7.0" - }, - "require-dev": { - "api-platform/parameter-validator": "*@dev || ^3.2", - "api-platform/symfony": "*@dev || ^3.2", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^10.0", - "ramsey/uuid": "^4.7", - "ramsey/uuid-doctrine": "^2.0", - "symfony/cache": "^6.4 || ^7.0", - "symfony/framework-bundle": "^6.4 || ^7.0", - "symfony/phpunit-bridge": "^6.4 || ^7.0", - "symfony/serializer": "^6.4 || ^7.0", - "symfony/yaml": "^6.4 || ^7.0" - }, - "autoload": { - "psr-4": { - "ApiPlatform\\Doctrine\\Orm\\": "" - } - }, - "config": { - "preferred-install": { - "*": "dist" + "require-dev": { + "api-platform/parameter-validator": "*@dev || ^3.2", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^10.0", + "ramsey/uuid": "^4.7", + "ramsey/uuid-doctrine": "^2.0", + "symfony/cache": "^6.4 || ^7.0", + "symfony/framework-bundle": "^6.4 || ^7.0", + "symfony/phpunit-bridge": "^6.4 || ^7.0", + "symfony/property-access": "^6.4 || ^7.0", + "symfony/serializer": "^6.4 || ^7.0", + "symfony/uid": "^6.4 || ^7.0", + "symfony/validator": "^6.4 || ^7.0", + "symfony/yaml": "^6.4 || ^7.0" }, - "sort-packages": true, - "allow-plugins": { - "php-http/discovery": false - } - }, - "extra": { - "branch-alias": { - "dev-main": "3.2.x-dev" + "autoload": { + "psr-4": { + "ApiPlatform\\Doctrine\\Orm\\": "" + } + }, + "config": { + "preferred-install": { + "*": "dist" + }, + "sort-packages": true, + "allow-plugins": { + "php-http/discovery": false + } + }, + "extra": { + "branch-alias": { + "dev-main": "3.3.x-dev" + }, + "symfony": { + "require": "^6.4" + } }, - "symfony": { - "require": "^6.4" + "scripts": { + "test": "./vendor/bin/phpunit" } - }, - "repositories": [ - { - "type": "path", - "url": "../../Metadata" - }, - { - "type": "path", - "url": "../../State" - }, - { - "type": "path", - "url": "../Common" - }, - { - "type": "path", - "url": "../../Symfony" - }, - { - "type": "path", - "url": "../../ParameterValidator" - } - ] } diff --git a/src/Documentation/Action/DocumentationAction.php b/src/Documentation/Action/DocumentationAction.php index 5a3a51f24ee..54e4a35fb83 100644 --- a/src/Documentation/Action/DocumentationAction.php +++ b/src/Documentation/Action/DocumentationAction.php @@ -32,6 +32,8 @@ /** * Generates the API documentation. * + * @deprecated use ApiPlatform\Symfony\DocumentationAction instead + * * @author Amrouche Hamza */ final class DocumentationAction diff --git a/src/Documentation/Action/EntrypointAction.php b/src/Documentation/Action/EntrypointAction.php index dd6204f67d1..9798ceb21f0 100644 --- a/src/Documentation/Action/EntrypointAction.php +++ b/src/Documentation/Action/EntrypointAction.php @@ -25,6 +25,8 @@ /** * Generates the API entrypoint. * + * @deprecated use ApiPlatform\Symfony\EntrypointAction instead + * * @author Kévin Dunglas */ final class EntrypointAction diff --git a/src/Documentation/composer.json b/src/Documentation/composer.json index 8520a879d51..2b67643f070 100644 --- a/src/Documentation/composer.json +++ b/src/Documentation/composer.json @@ -6,25 +6,25 @@ "autoload": { "psr-4": { "ApiPlatform\\Documentation\\": "" - } + } }, "authors": [ - { - "name": "Kévin Dunglas", - "email": "kevin@dunglas.fr", - "homepage": "https://dunglas.fr" - }, - { - "name": "API Platform Community", - "homepage": "https://api-platform.com/community/contributors" - } + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr", + "homepage": "https://dunglas.fr" + }, + { + "name": "API Platform Community", + "homepage": "https://api-platform.com/community/contributors" + } ], "require": { - "api-platform/openapi": "*@dev || ^3.1", - "api-platform/metadata": "*@dev || ^3.1", - "api-platform/state": "*@dev || ^3.1" + "api-platform/metadata": "*@dev || ^3.1" }, - "require-dev": { - "sebastian/comparator": "<5.0" + "extra": { + "branch-alias": { + "dev-main": "3.3.x-dev" + } } } diff --git a/src/Elasticsearch/Metadata/Resource/Factory/ElasticsearchProviderResourceMetadataCollectionFactory.php b/src/Elasticsearch/Metadata/Resource/Factory/ElasticsearchProviderResourceMetadataCollectionFactory.php index 8b72f26162f..fcde0f85302 100644 --- a/src/Elasticsearch/Metadata/Resource/Factory/ElasticsearchProviderResourceMetadataCollectionFactory.php +++ b/src/Elasticsearch/Metadata/Resource/Factory/ElasticsearchProviderResourceMetadataCollectionFactory.php @@ -27,7 +27,7 @@ final class ElasticsearchProviderResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface { - public function __construct(private readonly Client|null $client, private readonly ResourceMetadataCollectionFactoryInterface $decorated, private readonly bool $triggerDeprecation = true) // @phpstan-ignore-line + public function __construct(private readonly ?Client $client, private readonly ResourceMetadataCollectionFactoryInterface $decorated, private readonly bool $triggerDeprecation = true) // @phpstan-ignore-line { } diff --git a/src/Elasticsearch/composer.json b/src/Elasticsearch/composer.json index 08bc79a9e94..f7289857dc7 100644 --- a/src/Elasticsearch/composer.json +++ b/src/Elasticsearch/composer.json @@ -59,24 +59,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - }, - { - "type": "path", - "url": "../State" - }, - { - "type": "path", - "url": "../Serializer" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/GraphQl/State/Processor/NormalizeProcessor.php b/src/GraphQl/State/Processor/NormalizeProcessor.php index a502c12ff5c..c0baf855382 100644 --- a/src/GraphQl/State/Processor/NormalizeProcessor.php +++ b/src/GraphQl/State/Processor/NormalizeProcessor.php @@ -40,7 +40,7 @@ public function __construct(private readonly NormalizerInterface $normalizer, pr { } - public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): array|null + public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): ?array { if (!$operation instanceof GraphQlOperation) { return $data; diff --git a/src/GraphQl/composer.json b/src/GraphQl/composer.json index 2cdd36942d8..1af7931f975 100644 --- a/src/GraphQl/composer.json +++ b/src/GraphQl/composer.json @@ -64,40 +64,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - }, - { - "type": "path", - "url": "../State" - }, - { - "type": "path", - "url": "../Serializer" - }, - { - "type": "path", - "url": "../Validator" - }, - { - "type": "path", - "url": "../Doctrine/Orm" - }, - { - "type": "path", - "url": "../Doctrine/Odm" - }, - { - "type": "path", - "url": "../Doctrine/Common" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/HttpCache/composer.json b/src/HttpCache/composer.json index 2f47dd3d6d2..cedf81c473b 100644 --- a/src/HttpCache/composer.json +++ b/src/HttpCache/composer.json @@ -53,20 +53,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - }, - { - "type": "path", - "url": "../State" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/Hydra/composer.json b/src/Hydra/composer.json index d1c5b6629d8..456a487c961 100644 --- a/src/Hydra/composer.json +++ b/src/Hydra/composer.json @@ -36,7 +36,6 @@ "api-platform/serializer": "*@dev || ^3.1" }, "require-dev": { - "sebastian/comparator": "<5.0", "api-platform/doctrine-odm": "*@dev || ^3.2", "api-platform/doctrine-orm": "*@dev || ^3.2", "api-platform/doctrine-common": "*@dev || ^3.2" @@ -61,48 +60,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.1" } }, - "repositories": [ - { - "type": "path", - "url": "../State" - }, - { - "type": "path", - "url": "../Metadata" - }, - { - "type": "path", - "url": "../JsonLd" - }, - { - "type": "path", - "url": "../Serializer" - }, - { - "type": "path", - "url": "../JsonSchema" - }, - { - "type": "path", - "url": "../Documentation" - }, - { - "type": "path", - "url": "../Doctrine/Orm" - }, - { - "type": "path", - "url": "../Doctrine/Odm" - }, - { - "type": "path", - "url": "../Doctrine/Common" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/JsonLd/composer.json b/src/JsonLd/composer.json index a0b976d1994..e57022afecb 100644 --- a/src/JsonLd/composer.json +++ b/src/JsonLd/composer.json @@ -32,9 +32,6 @@ "api-platform/metadata": "*@dev || ^3.1", "api-platform/serializer": "*@dev || ^3.1" }, - "require-dev": { - "sebastian/comparator": "<5.0" - }, "autoload": { "psr-4": { "ApiPlatform\\JsonLd\\": "" @@ -55,20 +52,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.1" } }, - "repositories": [ - { - "type": "path", - "url": "../State" - }, - { - "type": "path", - "url": "../Metadata" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/JsonSchema/composer.json b/src/JsonSchema/composer.json index e022cdd8153..69133a14cb5 100644 --- a/src/JsonSchema/composer.json +++ b/src/JsonSchema/composer.json @@ -56,16 +56,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/Metadata/Tests/Fixtures/ApiResource/DummyCar.php b/src/Metadata/Tests/Fixtures/ApiResource/DummyCar.php index 1efab025752..619fd479343 100644 --- a/src/Metadata/Tests/Fixtures/ApiResource/DummyCar.php +++ b/src/Metadata/Tests/Fixtures/ApiResource/DummyCar.php @@ -32,11 +32,11 @@ class DummyCar #[Serializer\Groups(['colors'])] private iterable $colors; #[Serializer\Groups(['colors'])] - private iterable|null $secondColors = null; + private ?iterable $secondColors = null; #[Serializer\Groups(['colors'])] - private iterable|null $thirdColors = null; + private ?iterable $thirdColors = null; #[Serializer\Groups(['colors'])] - private iterable|null $uuid = null; + private ?iterable $uuid = null; private string $name; private bool $canSell; diff --git a/src/Metadata/composer.json b/src/Metadata/composer.json index 73f8aea2f91..27039b5ba4f 100644 --- a/src/Metadata/composer.json +++ b/src/Metadata/composer.json @@ -73,24 +73,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../OpenApi" - }, - { - "type": "path", - "url": "../JsonSchema" - }, - { - "type": "path", - "url": "../State" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/OpenApi/composer.json b/src/OpenApi/composer.json index 076ae9975aa..d77aad93f85 100644 --- a/src/OpenApi/composer.json +++ b/src/OpenApi/composer.json @@ -66,36 +66,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - }, - { - "type": "path", - "url": "../JsonSchema" - }, - { - "type": "path", - "url": "../State" - }, - { - "type": "path", - "url": "../Doctrine/Orm" - }, - { - "type": "path", - "url": "../Doctrine/Odm" - }, - { - "type": "path", - "url": "../Doctrine/Common" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/ParameterValidator/FilterLocatorTrait.php b/src/ParameterValidator/FilterLocatorTrait.php index 986d22a20b1..6b833bd43f6 100644 --- a/src/ParameterValidator/FilterLocatorTrait.php +++ b/src/ParameterValidator/FilterLocatorTrait.php @@ -45,7 +45,7 @@ private function setFilterLocator(?ContainerInterface $filterLocator, bool $allo /** * Gets a filter with a backward compatibility. */ - private function getFilter(string $filterId): FilterInterface|null + private function getFilter(string $filterId): ?FilterInterface { if ($this->filterLocator && $this->filterLocator->has($filterId)) { return $this->filterLocator->get($filterId); diff --git a/src/ParameterValidator/composer.json b/src/ParameterValidator/composer.json index 5065c3104ed..efca49d9d1d 100644 --- a/src/ParameterValidator/composer.json +++ b/src/ParameterValidator/composer.json @@ -38,8 +38,7 @@ "sebastian/comparator": "<5.0", "symfony/phpunit-bridge": "^6.4 || ^7.0" }, - "suggest": { - }, + "suggest": {}, "autoload": { "psr-4": { "ApiPlatform\\ParameterValidator\\": "" @@ -60,20 +59,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../State" - }, - { - "type": "path", - "url": "../Metadata" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/RamseyUuid/composer.json b/src/RamseyUuid/composer.json index fbb9d33a194..db5679dc318 100644 --- a/src/RamseyUuid/composer.json +++ b/src/RamseyUuid/composer.json @@ -48,16 +48,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/Serializer/SerializerContextBuilderInterface.php b/src/Serializer/SerializerContextBuilderInterface.php index ba6eb4707f4..8dfd0454c2f 100644 --- a/src/Serializer/SerializerContextBuilderInterface.php +++ b/src/Serializer/SerializerContextBuilderInterface.php @@ -13,20 +13,13 @@ namespace ApiPlatform\Serializer; -use ApiPlatform\Exception\RuntimeException; -use Symfony\Component\HttpFoundation\Request; +use ApiPlatform\State\SerializerContextBuilderInterface as StateSerializerContextBuilderInterface; /** * Builds the context used by the Symfony Serializer. * * @author Kévin Dunglas */ -interface SerializerContextBuilderInterface +interface SerializerContextBuilderInterface extends StateSerializerContextBuilderInterface { - /** - * Creates a serialization context from a Request. - * - * @throws RuntimeException - */ - public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array; } diff --git a/src/Serializer/composer.json b/src/Serializer/composer.json index 0ac51490705..b0e5d882751 100644 --- a/src/Serializer/composer.json +++ b/src/Serializer/composer.json @@ -60,32 +60,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - }, - { - "type": "path", - "url": "../State" - }, - { - "type": "path", - "url": "../Doctrine/Orm" - }, - { - "type": "path", - "url": "../Doctrine/Odm" - }, - { - "type": "path", - "url": "../Doctrine/Common" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/State/ApiResource/Error.php b/src/State/ApiResource/Error.php index 3141026c0d2..62970a078f6 100644 --- a/src/State/ApiResource/Error.php +++ b/src/State/ApiResource/Error.php @@ -13,7 +13,6 @@ namespace ApiPlatform\State\ApiResource; -use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Error as Operation; use ApiPlatform\Metadata\ErrorResource; @@ -48,7 +47,7 @@ 'skip_null_values' => true, 'rfc_7807_compliant_errors' => true, ], - links: [new Link(rel: ContextBuilderInterface::JSONLD_NS.'error', href: 'http://www.w3.org/ns/hydra/error')], + links: [new Link(rel: 'http://www.w3.org/ns/json-ld#error', href: 'http://www.w3.org/ns/hydra/error')], ), new Operation( name: '_api_errors_jsonapi', diff --git a/src/State/Processor/SerializeProcessor.php b/src/State/Processor/SerializeProcessor.php index 63d395773f8..bb86f4965e6 100644 --- a/src/State/Processor/SerializeProcessor.php +++ b/src/State/Processor/SerializeProcessor.php @@ -14,9 +14,9 @@ namespace ApiPlatform\State\Processor; use ApiPlatform\Metadata\Operation; -use ApiPlatform\Serializer\ResourceList; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\State\ResourceList; +use ApiPlatform\State\SerializerContextBuilderInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; use Symfony\Component\Serializer\SerializerInterface; diff --git a/src/Serializer/ResourceList.php b/src/State/ResourceList.php similarity index 90% rename from src/Serializer/ResourceList.php rename to src/State/ResourceList.php index 3817529da26..847939bbd03 100644 --- a/src/Serializer/ResourceList.php +++ b/src/State/ResourceList.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Serializer; +namespace ApiPlatform\State; /** * @internal diff --git a/src/State/SerializerContextBuilderInterface.php b/src/State/SerializerContextBuilderInterface.php new file mode 100644 index 00000000000..35aaeb3a071 --- /dev/null +++ b/src/State/SerializerContextBuilderInterface.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\State; + +use ApiPlatform\Metadata\Exception\RuntimeException; +use ApiPlatform\Metadata\HttpOperation; +use Symfony\Component\HttpFoundation\Request; + +/** + * Builds the context used by the Symfony Serializer. + * + * @author Kévin Dunglas + */ +interface SerializerContextBuilderInterface +{ + /** + * Creates a serialization context from a Request. + * + * @throws RuntimeException + * + * @return array&array{ + * groups?: string[]|string, + * operation_name?: string, + * operation?: HttpOperation, + * resource_class?: class-string, + * skip_null_values?: bool, + * iri_only?: bool, + * request_uri?: string, + * uri?: string, + * input?: array{class: class-string|null}, + * output?: array{class: class-string|null}, + * item_uri_template?: string, + * types?: string[], + * uri_variables?: array, + * force_resource_class?: class-string, + * api_allow_update?: bool, + * deep_object_to_populate?: bool, + * collect_denormalization_errors?: bool, + * exclude_from_cache_key?: string[], + * api_included?: bool + * } + */ + public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array; +} diff --git a/src/Serializer/Tests/ResourceListTest.php b/src/State/Tests/ResourceListTest.php similarity index 88% rename from src/Serializer/Tests/ResourceListTest.php rename to src/State/Tests/ResourceListTest.php index b87821e45ac..cd4f6550522 100644 --- a/src/Serializer/Tests/ResourceListTest.php +++ b/src/State/Tests/ResourceListTest.php @@ -11,9 +11,9 @@ declare(strict_types=1); -namespace ApiPlatform\Serializer\Tests; +namespace ApiPlatform\State\Tests; -use ApiPlatform\Serializer\ResourceList; +use ApiPlatform\State\ResourceList; use PHPUnit\Framework\TestCase; class ResourceListTest extends TestCase diff --git a/src/State/composer.json b/src/State/composer.json index e5526fa6f45..4495bbe5dbb 100644 --- a/src/State/composer.json +++ b/src/State/composer.json @@ -2,7 +2,17 @@ "name": "api-platform/state", "description": "API Platform State component ", "type": "library", - "keywords": ["REST", "GraphQL", "API", "JSON-LD", "Hydra", "JSONAPI", "OpenAPI", "HAL", "Swagger"], + "keywords": [ + "REST", + "GraphQL", + "API", + "JSON-LD", + "Hydra", + "JSONAPI", + "OpenAPI", + "HAL", + "Swagger" + ], "homepage": "https://api-platform.com", "license": "MIT", "authors": [ @@ -19,7 +29,6 @@ "require": { "php": ">=8.1", "api-platform/metadata": "*@dev || ^3.1", - "api-platform/jsonld": "*@dev || ^3.1", "psr/container": "^2.0" }, "require-dev": { @@ -27,7 +36,6 @@ "symfony/web-link": "^6.4 || ^7.0", "symfony/http-foundation": "^6.4 || 7.0", "willdurand/negotiation": "^3.1", - "api-platform/serializer": "*@dev || ^3.1", "api-platform/validator": "*@dev || ^3.1" }, "autoload": { @@ -50,7 +58,7 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" @@ -63,22 +71,7 @@ "api-platform/serializer": "To use API Platform serializer.", "api-platform/validator": "To use API Platform validation." }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - }, - { - "type": "path", - "url": "../Serializer" - }, - { - "type": "path", - "url": "../Validator" - }, - { - "type": "path", - "url": "../JsonLd" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/Symfony/Action/DocumentationAction.php b/src/Symfony/Action/DocumentationAction.php new file mode 100644 index 00000000000..64b26c6ec68 --- /dev/null +++ b/src/Symfony/Action/DocumentationAction.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Symfony\Action; + +use ApiPlatform\Documentation\Documentation; +use ApiPlatform\Documentation\DocumentationInterface; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Util\ContentNegotiationTrait; +use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; +use ApiPlatform\OpenApi\OpenApi; +use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; +use ApiPlatform\OpenApi\Serializer\LegacyOpenApiNormalizer; +use ApiPlatform\OpenApi\Serializer\OpenApiNormalizer; +use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\State\ProviderInterface; +use Negotiation\Negotiator; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Generates the API documentation. + * + * @author Amrouche Hamza + */ +final class DocumentationAction +{ + use ContentNegotiationTrait; + + public function __construct( + private readonly ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, + private readonly string $title = '', + private readonly string $description = '', + private readonly string $version = '', + private readonly ?OpenApiFactoryInterface $openApiFactory = null, + private readonly ?ProviderInterface $provider = null, + private readonly ?ProcessorInterface $processor = null, + ?Negotiator $negotiator = null, + private readonly array $documentationFormats = [OpenApiNormalizer::JSON_FORMAT => ['application/vnd.openapi+json'], OpenApiNormalizer::FORMAT => ['application/json']] + ) { + $this->negotiator = $negotiator ?? new Negotiator(); + } + + /** + * @return DocumentationInterface|OpenApi|Response + */ + public function __invoke(?Request $request = null) + { + if (null === $request) { + return new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version); + } + + $context = [ + 'api_gateway' => $request->query->getBoolean(ApiGatewayNormalizer::API_GATEWAY), + 'base_url' => $request->getBaseUrl(), + 'spec_version' => (string) $request->query->get(LegacyOpenApiNormalizer::SPEC_VERSION), + ]; + $request->attributes->set('_api_normalization_context', $request->attributes->get('_api_normalization_context', []) + $context); + $format = $this->getRequestFormat($request, $this->documentationFormats); + + if (null !== $this->openApiFactory && ('html' === $format || OpenApiNormalizer::FORMAT === $format || OpenApiNormalizer::JSON_FORMAT === $format || OpenApiNormalizer::YAML_FORMAT === $format)) { + return $this->getOpenApiDocumentation($context, $format, $request); + } + + return $this->getHydraDocumentation($context, $request); + } + + /** + * @param array $context + */ + private function getOpenApiDocumentation(array $context, string $format, Request $request): OpenApi|Response + { + if ($this->provider && $this->processor) { + $context['request'] = $request; + $operation = new Get( + class: OpenApi::class, + read: true, + serialize: true, + provider: fn () => $this->openApiFactory->__invoke($context), + normalizationContext: [ + ApiGatewayNormalizer::API_GATEWAY => $context['api_gateway'] ?? null, + LegacyOpenApiNormalizer::SPEC_VERSION => $context['spec_version'] ?? null, + ], + outputFormats: $this->documentationFormats + ); + + if ('html' === $format) { + $operation = $operation->withProcessor('api_platform.swagger_ui.processor')->withWrite(true); + } + if ('json' === $format) { + trigger_deprecation('api-platform/core', '3.2', 'The "json" format is too broad, use "jsonopenapi" instead.'); + } + + return $this->processor->process($this->provider->provide($operation, [], $context), $operation, [], $context); + } + + return $this->openApiFactory->__invoke($context); + } + + /** + * TODO: the logic behind the Hydra Documentation is done in a ApiPlatform\Hydra\Serializer\DocumentationNormalizer. + * We should transform this to a provider, it'd improve performances also by a bit. + * + * @param array $context + */ + private function getHydraDocumentation(array $context, Request $request): DocumentationInterface|Response + { + if ($this->provider && $this->processor) { + $context['request'] = $request; + $operation = new Get( + class: Documentation::class, + read: true, + serialize: true, + provider: fn () => new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version) + ); + + return $this->processor->process($this->provider->provide($operation, [], $context), $operation, [], $context); + } + + return new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version); + } +} diff --git a/src/Symfony/Action/EntrypointAction.php b/src/Symfony/Action/EntrypointAction.php new file mode 100644 index 00000000000..95c65f4ae01 --- /dev/null +++ b/src/Symfony/Action/EntrypointAction.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Symfony\Action; + +use ApiPlatform\Documentation\Entrypoint; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\OpenApi\Serializer\LegacyOpenApiNormalizer; +use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\State\ProviderInterface; +use Symfony\Component\HttpFoundation\Request; + +/** + * Generates the API entrypoint. + * + * @author Kévin Dunglas + */ +final class EntrypointAction +{ + private static ResourceNameCollection $resourceNameCollection; + + public function __construct( + private readonly ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, + private readonly ProviderInterface $provider, + private readonly ProcessorInterface $processor, + private readonly array $documentationFormats = [] + ) { + } + + public function __invoke(Request $request) + { + static::$resourceNameCollection = $this->resourceNameCollectionFactory->create(); + $context = [ + 'request' => $request, + 'spec_version' => (string) $request->query->get(LegacyOpenApiNormalizer::SPEC_VERSION), + ]; + $request->attributes->set('_api_platform_disable_listeners', true); + $operation = new Get( + outputFormats: $this->documentationFormats, + read: true, + serialize: true, + class: Entrypoint::class, + provider: [self::class, 'provide'] + ); + $request->attributes->set('_api_operation', $operation); + $body = $this->provider->provide($operation, [], $context); + $operation = $request->attributes->get('_api_operation'); + + return $this->processor->process($body, $operation, [], $context); + } + + public static function provide(): Entrypoint + { + return new Entrypoint(static::$resourceNameCollection); + } +} diff --git a/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php b/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php index c0669c470d5..25bd8f91572 100644 --- a/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php +++ b/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Symfony\Bundle\ArgumentResolver; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; +use ApiPlatform\State\SerializerContextBuilderInterface; use ApiPlatform\State\Util\OperationRequestInitiatorTrait; use ApiPlatform\Symfony\Util\RequestAttributesExtractor; use Symfony\Component\HttpFoundation\Request; diff --git a/src/Symfony/Bundle/Resources/config/symfony/controller.xml b/src/Symfony/Bundle/Resources/config/symfony/controller.xml index e37e87c2faf..d12617dd958 100644 --- a/src/Symfony/Bundle/Resources/config/symfony/controller.xml +++ b/src/Symfony/Bundle/Resources/config/symfony/controller.xml @@ -13,14 +13,14 @@ - + %api_platform.docs_formats% - + %api_platform.title% %api_platform.description% diff --git a/src/Symfony/Bundle/Resources/config/symfony/events.xml b/src/Symfony/Bundle/Resources/config/symfony/events.xml index 4e86b56780e..5b705cc3e63 100644 --- a/src/Symfony/Bundle/Resources/config/symfony/events.xml +++ b/src/Symfony/Bundle/Resources/config/symfony/events.xml @@ -129,14 +129,14 @@ - + %api_platform.docs_formats% - + %api_platform.title% %api_platform.description% diff --git a/src/Symfony/EventListener/SerializeListener.php b/src/Symfony/EventListener/SerializeListener.php index 356d8b62f91..0cd5ef8604b 100644 --- a/src/Symfony/EventListener/SerializeListener.php +++ b/src/Symfony/EventListener/SerializeListener.php @@ -18,9 +18,9 @@ use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\Error; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Serializer\ResourceList; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\State\ResourceList; +use ApiPlatform\State\SerializerContextBuilderInterface; use ApiPlatform\State\Util\OperationRequestInitiatorTrait; use ApiPlatform\Symfony\Util\RequestAttributesExtractor; use ApiPlatform\Util\ErrorFormatGuesser; diff --git a/src/Symfony/composer.json b/src/Symfony/composer.json index 48fe9a2daa8..0567969836e 100644 --- a/src/Symfony/composer.json +++ b/src/Symfony/composer.json @@ -21,6 +21,7 @@ "require": { "php": ">=8.1", "api-platform/documentation": "*@dev || ^3.1", + "api-platform/doctrine-common": "*@dev || ^3.1", "api-platform/elasticsearch": "*@dev || ^3.1", "api-platform/graphql": "*@dev || ^3.1", "api-platform/http-cache": "*@dev || ^3.1", @@ -71,76 +72,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - }, - { - "type": "path", - "url": "../ParameterValidator" - }, - { - "type": "path", - "url": "../State" - }, - { - "type": "path", - "url": "../Doctrine/Common" - }, - { - "type": "path", - "url": "../Documentation" - }, - { - "type": "path", - "url": "../Elasticsearch" - }, - { - "type": "path", - "url": "../GraphQl" - }, - { - "type": "path", - "url": "../JsonLd" - }, - { - "type": "path", - "url": "../HttpCache" - }, - { - "type": "path", - "url": "../JsonSchema" - }, - { - "type": "path", - "url": "../Serializer" - }, - { - "type": "path", - "url": "../Validator" - }, - { - "type": "path", - "url": "../OpenApi" - }, - { - "type": "path", - "url": "../Doctrine/Orm" - }, - { - "type": "path", - "url": "../Doctrine/Odm" - }, - { - "type": "path", - "url": "../Hydra" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/src/Validator/Exception/ValidationException.php b/src/Validator/Exception/ValidationException.php index 45c38cb731f..bc667373546 100644 --- a/src/Validator/Exception/ValidationException.php +++ b/src/Validator/Exception/ValidationException.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Validator\Exception; -use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\Error as ErrorOperation; use ApiPlatform\Metadata\ErrorResource; use ApiPlatform\Metadata\Exception\HttpExceptionInterface; @@ -49,7 +48,7 @@ new ErrorOperation( name: '_api_validation_errors_hydra', outputFormats: ['jsonld' => ['application/problem+json']], - links: [new Link(rel: ContextBuilderInterface::JSONLD_NS.'error', href: 'http://www.w3.org/ns/hydra/error')], + links: [new Link(rel: 'http://www.w3.org/ns/json-ld#error', href: 'http://www.w3.org/ns/hydra/error')], normalizationContext: [ 'groups' => ['jsonld'], 'skip_null_values' => true, diff --git a/src/Validator/composer.json b/src/Validator/composer.json index 36df45e992d..f48c07613b4 100644 --- a/src/Validator/composer.json +++ b/src/Validator/composer.json @@ -22,7 +22,6 @@ "require": { "php": ">=8.1", "api-platform/metadata": "*@dev || ^3.1", - "api-platform/jsonld": "*@dev || ^3.1", "symfony/web-link": "^6.4 || ^7.0" }, "require-dev": { @@ -50,16 +49,13 @@ }, "extra": { "branch-alias": { - "dev-main": "3.2.x-dev" + "dev-main": "3.3.x-dev" }, "symfony": { "require": "^6.4" } }, - "repositories": [ - { - "type": "path", - "url": "../Metadata" - } - ] + "scripts": { + "test": "./vendor/bin/phpunit" + } } diff --git a/tests/Fixtures/TestBundle/Entity/Issue5662/Book.php b/tests/Fixtures/TestBundle/Entity/Issue5662/Book.php index 322ae4a58ae..bc930384fb2 100644 --- a/tests/Fixtures/TestBundle/Entity/Issue5662/Book.php +++ b/tests/Fixtures/TestBundle/Entity/Issue5662/Book.php @@ -37,7 +37,7 @@ public static function getData(Operation $operation, array $uriVariables = [], a return [new self('a', 'hello'), new self('b', 'you')]; } - public static function getDatum(Operation $operation, array $uriVariables = [], array $context = []): self|null + public static function getDatum(Operation $operation, array $uriVariables = [], array $context = []): ?self { $id = $uriVariables['id']; foreach (static::getData($operation, $uriVariables, $context) as $datum) { diff --git a/tests/Fixtures/TestBundle/Entity/Issue5662/Review.php b/tests/Fixtures/TestBundle/Entity/Issue5662/Review.php index ff29d33eae0..f769515c8ff 100644 --- a/tests/Fixtures/TestBundle/Entity/Issue5662/Review.php +++ b/tests/Fixtures/TestBundle/Entity/Issue5662/Review.php @@ -75,7 +75,7 @@ public static function getData(Operation $operation, array $uriVariables = [], a ]; } - public static function getDatum(Operation $operation, array $uriVariables = [], array $context = []): self|null + public static function getDatum(Operation $operation, array $uriVariables = [], array $context = []): ?self { $id = (int) $uriVariables['id']; foreach (static::getData($operation, $uriVariables, $context) as $datum) { diff --git a/tests/Symfony/EventListener/SerializeListenerTest.php b/tests/Symfony/EventListener/SerializeListenerTest.php index f7f29ce8d7f..145846dbd33 100644 --- a/tests/Symfony/EventListener/SerializeListenerTest.php +++ b/tests/Symfony/EventListener/SerializeListenerTest.php @@ -17,8 +17,8 @@ use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; -use ApiPlatform\Serializer\ResourceList; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; +use ApiPlatform\State\ResourceList; +use ApiPlatform\State\SerializerContextBuilderInterface; use ApiPlatform\Symfony\EventListener\SerializeListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase;