diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a0199050ce..1e9700c08cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,11 +98,6 @@ jobs: strategy: matrix: php: - - '7.1' - - '7.2' - - '7.3' - - '7.4' - - '8.0' - '8.1' include: - php: '8.1' @@ -131,16 +126,9 @@ jobs: - name: Enable code coverage if: matrix.coverage run: echo "COVERAGE=1" >> $GITHUB_ENV - - name: Remove Doctrine MongoDB ODM - if: (startsWith(matrix.php, '7.1')) - run: | - composer remove --dev --no-interaction --no-progress --no-update --ansi \ - doctrine/mongodb-odm \ - doctrine/mongodb-odm-bundle - name: Update project dependencies run: composer update --no-interaction --no-progress --ansi - name: Require Symfony components - if: (!startsWith(matrix.php, '7.1')) run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - name: Install PHPUnit run: vendor/bin/simple-phpunit --version @@ -154,9 +142,6 @@ jobs: else vendor/bin/simple-phpunit --log-junit build/logs/phpunit/junit.xml fi - - name: Run PHPUnit 8.1+ tests - if: (startsWith(matrix.php, '8.1')) - run: ./vendor/bin/simple-phpunit --stop-on-failure tests/Metadata/Resource/Factory/ - name: Upload test artifacts if: always() uses: actions/upload-artifact@v1 @@ -189,11 +174,6 @@ jobs: strategy: matrix: php: - - '7.1' - - '7.2' - - '7.3' - - '7.4' - - '8.0' - '8.1' include: - php: '8.1' @@ -222,40 +202,15 @@ jobs: - name: Enable code coverage if: matrix.coverage run: echo "COVERAGE=1" >> $GITHUB_ENV - - name: Remove Doctrine MongoDB ODM - if: startsWith(matrix.php, '7.1') - run: | - composer remove --dev --no-interaction --no-progress --no-update --ansi \ - doctrine/mongodb-odm \ - doctrine/mongodb-odm-bundle - name: Update project dependencies run: composer update --no-interaction --no-progress --ansi - name: Require Symfony components - if: (!startsWith(matrix.php, '7.1')) run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - name: Install PHPUnit run: vendor/bin/simple-phpunit --version - name: Clear test app cache - if: (!startsWith(matrix.php, '8.')) run: tests/Fixtures/app/console cache:clear --ansi - - name: Clear test app cache (php 8.0) - if: (startsWith(matrix.php, '8.')) - run: rm -Rf tests/Fixtures/app/var/cache/* - - name: Run Behat tests (PHP < 8) - if: (!startsWith(matrix.php, '8.')) - run: | - mkdir -p build/logs/behat - if [ "$COVERAGE" = '1' ]; then - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default-coverage --no-interaction --tags='~@php8' - else - if [ "${{ matrix.php }}" = '7.1' ]; then - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction --tags='~@symfony/uid&&~@php8' - else - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction --tags='~@php8' - fi - fi - name: Run Behat tests (PHP 8) - if: (startsWith(matrix.php, '8.')) run: | mkdir -p build/logs/behat if [ "$COVERAGE" = '1' ]; then @@ -320,87 +275,6 @@ jobs: path: build/out/openapi continue-on-error: true - phpunit-lowest: - name: PHPUnit (PHP ${{ matrix.php }} lowest) - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '7.4' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring - coverage: none - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Require Symfony components - run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi --no-update - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi --prefer-lowest - - name: Clear test app cache - run: tests/Fixtures/app/console cache:clear --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Run PHPUnit tests - run: vendor/bin/simple-phpunit - - behat-lowest: - name: Behat (PHP ${{ matrix.php }} lowest) - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '7.4' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite - coverage: none - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Require Symfony components - run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi --no-update - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi --prefer-lowest - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: tests/Fixtures/app/console cache:clear --ansi - - name: Run Behat tests - # @TODO remove the tag "@symfony/uid" in 3.0 - run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction --tags='~@symfony/uid&&~php8' - postgresql: name: Behat (PHP ${{ matrix.php }}) (PostgreSQL) runs-on: ubuntu-latest @@ -408,7 +282,7 @@ jobs: strategy: matrix: php: - - '7.4' + - '8.1' fail-fast: false env: APP_ENV: postgres @@ -459,7 +333,7 @@ jobs: strategy: matrix: php: - - '7.4' + - '8.1' fail-fast: false services: mysql: @@ -510,7 +384,7 @@ jobs: strategy: matrix: php: - - '8' + - '8.1' fail-fast: false env: APP_ENV: mongodb @@ -596,8 +470,6 @@ jobs: strategy: matrix: php: - - '7.4' - - '8.0' - '8.1' fail-fast: false env: @@ -650,7 +522,7 @@ jobs: strategy: matrix: php: - - '7.4' + - '8.1' fail-fast: false env: SYMFONY_DEPRECATIONS_HELPER: max[total]=0 @@ -779,148 +651,6 @@ jobs: - name: Run Behat tests run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction - behat-rector-upgrade: - name: Behat (PHP ${{ matrix.php }}) (upgrade script) - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '8.1' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi - - name: Require Symfony components - run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: rm -Rf tests/Fixtures/app/var/cache/* - - name: Convert metadata to API Platform 3 - run: | - tests/Fixtures/app/console api:upgrade-resource -f - - name: Apply behat features patch (IRIs update) - run: | - git apply .github/patch/v3_features.patch - - name: clear test app cache - run: rm -rf tests/Fixtures/app/var/cache/* - - name: Run Behat tests - run: | - mkdir -p build/logs/behat - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction - - name: Upload test artifacts - if: always() - uses: actions/upload-artifact@v1 - with: - name: behat-logs-php${{ matrix.php }} - path: build/logs/behat - continue-on-error: true - - name: Export OpenAPI documents - run: | - mkdir -p build/out/openapi - tests/Fixtures/app/console api:openapi:export --spec-version=2 -o build/out/openapi/swagger_v2.json - tests/Fixtures/app/console api:openapi:export --spec-version=2 --yaml -o build/out/openapi/swagger_v2.yaml - tests/Fixtures/app/console api:openapi:export --spec-version=3 -o build/out/openapi/openapi_v3.json - tests/Fixtures/app/console api:openapi:export --spec-version=3 --yaml -o build/out/openapi/openapi_v3.yaml - - name: Setup node - uses: actions/setup-node@v2 - with: - node-version: '14' - - name: Validate OpenAPI documents - run: | - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/swagger_v2.json - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/swagger_v2.yaml - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/openapi_v3.json - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/openapi_v3.yaml - - name: Upload OpenAPI artifacts - if: always() - uses: actions/upload-artifact@v1 - with: - name: openapi-docs-php${{ matrix.php }} - path: build/out/openapi - continue-on-error: true - - behat-rector-upgrade-mongodb: - name: Behat (PHP ${{ matrix.php }}) (upgrade script / MongoDB) - runs-on: ubuntu-latest - env: - APP_ENV: mongodb - MONGODB_URL: mongodb://localhost:27017 - timeout-minutes: 20 - strategy: - matrix: - php: - - '8.1' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Check - run: | - sudo systemctl start mongod.service - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, mongodb - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi - - name: Require Symfony components - run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: rm -Rf tests/Fixtures/app/var/cache/* - - name: Convert metadata to API Platform 3 - run: | - tests/Fixtures/app/console api:upgrade-resource -f - - name: Apply behat features patch (IRIs update) - run: | - git apply .github/patch/v3_features.patch - - name: Clear test app cache - run: rm -Rf tests/Fixtures/app/var/cache/* - - name: Run Behat tests - run: | - mkdir -p build/logs/behat - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=mongodb --no-interaction - - name: Upload test artifacts - if: always() - uses: actions/upload-artifact@v1 - with: - name: behat-logs-php${{ matrix.php }} - path: build/logs/behat - continue-on-error: true - windows-phpunit: name: Windows PHPUnit (PHP ${{ matrix.php }}) (SQLite) runs-on: windows-latest @@ -928,8 +658,6 @@ jobs: strategy: matrix: php: - - '7.4' - - '8.0' - '8.1' fail-fast: false env: @@ -955,10 +683,6 @@ jobs: path: ${{ steps.composercache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer- - - name: Set Composer platform config - if: (startsWith(matrix.php, '8.')) - run: | - composer config platform.php 7.4.99 - name: Update project dependencies run: composer update --no-interaction --no-progress --ansi - name: Require Symfony components @@ -977,8 +701,6 @@ jobs: strategy: matrix: php: - - '7.4' - - '8.0' - '8.1' fail-fast: false env: @@ -1004,10 +726,6 @@ jobs: path: ${{ steps.composercache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer- - - name: Set Composer platform config - if: (startsWith(matrix.php, '8.')) - run: | - composer config platform.php 7.4.99 - name: Update project dependencies run: composer update --no-interaction --no-progress --ansi - name: Require Symfony components @@ -1017,119 +735,4 @@ jobs: - name: Clear test app cache run: tests/Fixtures/app/console cache:clear --ansi - name: Run Behat tests - run: | - if ( "${{ matrix.php }}" -eq '7.4' ) { - vendor/bin/behat --out=std --format=progress --profile=default --no-interaction --tags='~@php8' - } else { - vendor/bin/behat --out=std --format=progress --profile=default --no-interaction - } - - phpunit_legacy_metadata: - name: PHPUnit (PHP ${{ matrix.php }}) 2.7 BC layer - env: - METADATA_BACKWARD_COMPATIBILITY_LAYER: 1 - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '7.4' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite - coverage: pcov - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi - - name: Require Symfony components - run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: tests/Fixtures/app/console cache:clear --ansi - - name: Run PHPUnit tests - run: | - mkdir -p build/logs/phpunit - vendor/bin/simple-phpunit --log-junit build/logs/phpunit/junit.xml - - behat_legacy_metadata: - name: Behat (PHP ${{ matrix.php }}) 2.7 BC layer - env: - METADATA_BACKWARD_COMPATIBILITY_LAYER: 1 - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '7.4' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite - coverage: pcov - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi - - name: Require Symfony components - run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: tests/Fixtures/app/console cache:clear --ansi - - name: Run Behat tests - run: | - mkdir -p build/logs/behat - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction --tags='~@php8' --tags='~@v3' - - name: Run Behat tests (PHP 8) - if: (startsWith(matrix.php, '8.')) - run: | - mkdir -p build/logs/behat - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction - - name: Export OpenAPI documents - run: | - mkdir -p build/out/openapi - tests/Fixtures/app/console api:openapi:export --spec-version=2 -o build/out/openapi/swagger_v2.json - tests/Fixtures/app/console api:openapi:export --spec-version=2 --yaml -o build/out/openapi/swagger_v2.yaml - tests/Fixtures/app/console api:openapi:export --spec-version=3 -o build/out/openapi/openapi_v3.json - tests/Fixtures/app/console api:openapi:export --spec-version=3 --yaml -o build/out/openapi/openapi_v3.yaml - - name: Setup node - uses: actions/setup-node@v2 - with: - node-version: '14' - - name: Validate OpenAPI documents - run: | - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/swagger_v2.json - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/swagger_v2.yaml - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/openapi_v3.json - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/openapi_v3.yaml + run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction diff --git a/behat.yml.dist b/behat.yml.dist index 2ecdb71e7c6..7675928087b 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -2,17 +2,17 @@ default: suites: default: contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -38,17 +38,17 @@ postgres: default: false postgres: &postgres-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -59,17 +59,17 @@ mongodb: default: false mongodb: &mongodb-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -82,9 +82,9 @@ elasticsearch: paths: - '%paths.base%/features/elasticsearch' contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\ElasticsearchContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\ElasticsearchContext' + - 'ApiPlatform\Tests\Behat\JsonContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -94,18 +94,18 @@ default-coverage: suites: default: &default-coverage-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\CoverageContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' @@ -115,18 +115,18 @@ mongodb-coverage: mongodb: &mongodb-coverage-suite <<: *mongodb-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\CoverageContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' @@ -136,9 +136,9 @@ elasticsearch-coverage: elasticsearch: &elasticsearch-coverage-suite <<: *elasticsearch-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\ElasticsearchContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\CoverageContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\ElasticsearchContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\CoverageContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' diff --git a/composer.json b/composer.json index 5826a3a7400..f17c1ee757f 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,6 @@ "require-dev": { "behat/behat": "^3.1", "behat/mink": "^1.9@dev", - "doctrine/annotations": "^1.7", "doctrine/cache": "^1.11 || ^2.1", "doctrine/common": "^2.11 || ^3.0", "doctrine/data-fixtures": "^1.2.2", @@ -115,14 +114,10 @@ "autoload": { "psr-4": { "ApiPlatform\\": "src/" - }, - "files": [ - "src/deprecation.php" - ] + } }, "autoload-dev": { "psr-4": { - "ApiPlatform\\Core\\Tests\\": "tests/Core/", "ApiPlatform\\Tests\\": "tests/", "App\\": "tests/Fixtures/app/var/tmp/src/" } @@ -139,7 +134,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.7.x-dev" + "dev-main": "3.0.x-dev" }, "symfony": { "require": "^3.4 || ^4.4 || ^5.1 || ^6.0" diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b687076cfda..b73ea695c19 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,8 +16,6 @@ tests - tests/Metadata/Resource/Factory - tests/Metadata/Resource/Factory @@ -29,9 +27,6 @@ features tests vendor - src/Core/Bridge/NelmioApiDoc - src/Core/Bridge/FosUser - src/Core/Bridge/Symfony/Maker/Resources/skeleton .php-cs-fixer.dist.php src/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php diff --git a/src/Action/EntrypointAction.php b/src/Action/EntrypointAction.php index 1771db220d3..c256865f35a 100644 --- a/src/Action/EntrypointAction.php +++ b/src/Action/EntrypointAction.php @@ -35,5 +35,3 @@ public function __invoke(): Entrypoint return new Entrypoint($this->resourceNameCollectionFactory->create()); } } - -class_alias(EntrypointAction::class, \ApiPlatform\Core\Action\EntrypointAction::class); diff --git a/src/Action/ExceptionAction.php b/src/Action/ExceptionAction.php index b5fd5f63ef9..ac9d4106fc3 100644 --- a/src/Action/ExceptionAction.php +++ b/src/Action/ExceptionAction.php @@ -116,5 +116,3 @@ private function getOperationExceptionToStatus(Request $request): array ); } } - -class_alias(ExceptionAction::class, \ApiPlatform\Core\Action\ExceptionAction::class); diff --git a/src/Action/NotFoundAction.php b/src/Action/NotFoundAction.php index 2e5e1d2cf95..546811fee66 100644 --- a/src/Action/NotFoundAction.php +++ b/src/Action/NotFoundAction.php @@ -25,5 +25,3 @@ public function __invoke() throw new NotFoundHttpException(); } } - -class_alias(NotFoundAction::class, \ApiPlatform\Core\Action\NotFoundAction::class); diff --git a/src/Action/PlaceholderAction.php b/src/Action/PlaceholderAction.php index 5ed07426db2..79cc83f8371 100644 --- a/src/Action/PlaceholderAction.php +++ b/src/Action/PlaceholderAction.php @@ -30,5 +30,3 @@ public function __invoke($data) return $data; } } - -class_alias(PlaceholderAction::class, \ApiPlatform\Core\Action\PlaceholderAction::class); diff --git a/src/Api/Entrypoint.php b/src/Api/Entrypoint.php index e3289f62559..ed654c01cdb 100644 --- a/src/Api/Entrypoint.php +++ b/src/Api/Entrypoint.php @@ -34,5 +34,3 @@ public function getResourceNameCollection(): ResourceNameCollection return $this->resourceNameCollection; } } - -class_alias(Entrypoint::class, \ApiPlatform\Core\Api\Entrypoint::class); diff --git a/src/Api/FilterLocatorTrait.php b/src/Api/FilterLocatorTrait.php index 10f3ab96d2d..f7281f92003 100644 --- a/src/Api/FilterLocatorTrait.php +++ b/src/Api/FilterLocatorTrait.php @@ -62,5 +62,3 @@ private function getFilter(string $filterId): ?FilterInterface return null; } } - -class_alias(FilterLocatorTrait::class, \ApiPlatform\Core\Api\FilterLocatorTrait::class); diff --git a/src/Api/FormatMatcher.php b/src/Api/FormatMatcher.php index a5aed0185ab..c86270c10de 100644 --- a/src/Api/FormatMatcher.php +++ b/src/Api/FormatMatcher.php @@ -62,5 +62,3 @@ public function getFormat(string $mimeType): ?string return null; } } - -class_alias(FormatMatcher::class, \ApiPlatform\Core\Api\FormatMatcher::class); diff --git a/src/Api/QueryParameterValidator/QueryParameterValidator.php b/src/Api/QueryParameterValidator/QueryParameterValidator.php index 67f3c725209..53c0d8c73d0 100644 --- a/src/Api/QueryParameterValidator/QueryParameterValidator.php +++ b/src/Api/QueryParameterValidator/QueryParameterValidator.php @@ -64,5 +64,3 @@ public function validateFilters(string $resourceClass, array $resourceFilters, a } } } - -class_alias(QueryParameterValidator::class, \ApiPlatform\Core\Filter\QueryParameterValidator::class); diff --git a/src/Api/QueryParameterValidator/Validator/ArrayItems.php b/src/Api/QueryParameterValidator/Validator/ArrayItems.php index c2e65758de1..af8851377ef 100644 --- a/src/Api/QueryParameterValidator/Validator/ArrayItems.php +++ b/src/Api/QueryParameterValidator/Validator/ArrayItems.php @@ -84,5 +84,3 @@ private static function getSeparator(string $collectionFormat): string } } } - -class_alias(ArrayItems::class, \ApiPlatform\Core\Filter\Validator\ArrayItems::class); diff --git a/src/Api/QueryParameterValidator/Validator/Bounds.php b/src/Api/QueryParameterValidator/Validator/Bounds.php index 1cef0ba9ad4..eebc40b3eca 100644 --- a/src/Api/QueryParameterValidator/Validator/Bounds.php +++ b/src/Api/QueryParameterValidator/Validator/Bounds.php @@ -49,5 +49,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return $errorList; } } - -class_alias(Bounds::class, \ApiPlatform\Core\Filter\Validator\Bounds::class); diff --git a/src/Api/QueryParameterValidator/Validator/Enum.php b/src/Api/QueryParameterValidator/Validator/Enum.php index 72ad2056268..2e0bf5c277b 100644 --- a/src/Api/QueryParameterValidator/Validator/Enum.php +++ b/src/Api/QueryParameterValidator/Validator/Enum.php @@ -36,5 +36,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } } - -class_alias(Enum::class, \ApiPlatform\Core\Filter\Validator\Enum::class); diff --git a/src/Api/QueryParameterValidator/Validator/Length.php b/src/Api/QueryParameterValidator/Validator/Length.php index 4d658898bdd..0b0c67e5595 100644 --- a/src/Api/QueryParameterValidator/Validator/Length.php +++ b/src/Api/QueryParameterValidator/Validator/Length.php @@ -41,5 +41,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return $errorList; } } - -class_alias(Length::class, \ApiPlatform\Core\Filter\Validator\Length::class); diff --git a/src/Api/QueryParameterValidator/Validator/MultipleOf.php b/src/Api/QueryParameterValidator/Validator/MultipleOf.php index 197d081bcd0..6da33972688 100644 --- a/src/Api/QueryParameterValidator/Validator/MultipleOf.php +++ b/src/Api/QueryParameterValidator/Validator/MultipleOf.php @@ -36,5 +36,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } } - -class_alias(MultipleOf::class, \ApiPlatform\Core\Filter\Validator\MultipleOf::class); diff --git a/src/Api/QueryParameterValidator/Validator/Pattern.php b/src/Api/QueryParameterValidator/Validator/Pattern.php index 414b7cc8da8..a585fd8b321 100644 --- a/src/Api/QueryParameterValidator/Validator/Pattern.php +++ b/src/Api/QueryParameterValidator/Validator/Pattern.php @@ -36,5 +36,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } } - -class_alias(Pattern::class, \ApiPlatform\Core\Filter\Validator\Pattern::class); diff --git a/src/Api/QueryParameterValidator/Validator/Required.php b/src/Api/QueryParameterValidator/Validator/Required.php index 308bdbf354d..0045b0513b4 100644 --- a/src/Api/QueryParameterValidator/Validator/Required.php +++ b/src/Api/QueryParameterValidator/Validator/Required.php @@ -100,5 +100,3 @@ private function requestGetQueryParameter(array $queryParameters, string $name) return $queryParameters[(string) $rootName]; } } - -class_alias(Required::class, \ApiPlatform\Core\Filter\Validator\Required::class); diff --git a/src/Api/ResourceClassResolver.php b/src/Api/ResourceClassResolver.php index e0f9243458c..b1bec160917 100644 --- a/src/Api/ResourceClassResolver.php +++ b/src/Api/ResourceClassResolver.php @@ -109,5 +109,3 @@ public function isResourceClass(string $type): bool return $this->localIsResourceClassCache[$type] = false; } } - -class_alias(ResourceClassResolver::class, \ApiPlatform\Core\Api\ResourceClassResolver::class); diff --git a/src/Core/Action/EntrypointAction.php b/src/Core/Action/EntrypointAction.php deleted file mode 100644 index 7a82b6cfc98..00000000000 --- a/src/Core/Action/EntrypointAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Action; - -class_exists(\ApiPlatform\Action\EntrypointAction::class); - -if (false) { - final class EntrypointAction extends \ApiPlatform\Action\EntrypointAction - { - } -} diff --git a/src/Core/Action/ExceptionAction.php b/src/Core/Action/ExceptionAction.php deleted file mode 100644 index 7272c7d1cb2..00000000000 --- a/src/Core/Action/ExceptionAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Action; - -class_exists(\ApiPlatform\Action\ExceptionAction::class); - -if (false) { - final class ExceptionAction extends \ApiPlatform\Action\ExceptionAction - { - } -} diff --git a/src/Core/Action/NotFoundAction.php b/src/Core/Action/NotFoundAction.php deleted file mode 100644 index cb413a942b9..00000000000 --- a/src/Core/Action/NotFoundAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Action; - -class_exists(\ApiPlatform\Action\NotFoundAction::class); - -if (false) { - final class NotFoundAction extends \ApiPlatform\Action\NotFoundAction - { - } -} diff --git a/src/Core/Action/PlaceholderAction.php b/src/Core/Action/PlaceholderAction.php deleted file mode 100644 index 830ad04323d..00000000000 --- a/src/Core/Action/PlaceholderAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Action; - -class_exists(\ApiPlatform\Action\PlaceholderAction::class); - -if (false) { - final class PlaceholderAction extends \ApiPlatform\Action\PlaceholderAction - { - } -} diff --git a/src/Core/Annotation/ApiFilter.php b/src/Core/Annotation/ApiFilter.php deleted file mode 100644 index c759e8e0526..00000000000 --- a/src/Core/Annotation/ApiFilter.php +++ /dev/null @@ -1,96 +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); - -namespace ApiPlatform\Core\Annotation; - -use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * Filter annotation. - * - * @author Antoine Bluchet - * - * @Annotation - * @Target({"PROPERTY", "CLASS"}) - */ -#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] -final class ApiFilter -{ - /** - * @var string - */ - public $id; - - /** - * @var string - */ - public $strategy; - - /** - * @var string|FilterInterface - */ - public $filterClass; - - /** - * @var array - */ - public $properties = []; - - /** - * @var array raw arguments for the filter - */ - public $arguments = []; - - /** - * @param string $filterClass - * @param string $id - * @param string $strategy - */ - public function __construct( - $filterClass, - ?string $id = null, - ?string $strategy = null, - array $properties = [], - array $arguments = [] - ) { - if (\is_array($filterClass)) { /** @phpstan-ignore-line Doctrine annotations */ - $options = $filterClass; - $this->filterClass = $options['value'] ?? null; /* @phpstan-ignore-line Doctrine annotations */ - unset($options['value']); - - foreach ($options as $key => $value) { - if (!property_exists($this, $key)) { - throw new InvalidArgumentException(sprintf('Property "%s" does not exist on the ApiFilter annotation.', $key)); - } - - $this->{$key} = $value; - } - } else { - // PHP attribute - $this->filterClass = $filterClass; - $this->id = $id; - $this->strategy = $strategy; - $this->properties = $properties; - $this->arguments = $arguments; - } - - if (!\is_string($this->filterClass)) { - throw new InvalidArgumentException('This annotation needs a value representing the filter class.'); - } - - if (!is_a($this->filterClass, FilterInterface::class, true)) { - throw new InvalidArgumentException(sprintf('The filter class "%s" does not implement "%s". Did you forget a use statement?', $this->filterClass, FilterInterface::class)); - } - } -} diff --git a/src/Core/Annotation/ApiProperty.php b/src/Core/Annotation/ApiProperty.php deleted file mode 100644 index 7070b81a175..00000000000 --- a/src/Core/Annotation/ApiProperty.php +++ /dev/null @@ -1,165 +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); - -namespace ApiPlatform\Core\Annotation; - -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * ApiProperty annotation. - * - * @author Kévin Dunglas - * - * @Annotation - * @Target({"METHOD", "PROPERTY"}) - * @Attributes( - * @Attribute("deprecationReason", type="string"), - * @Attribute("fetchable", type="bool"), - * @Attribute("fetchEager", type="bool"), - * @Attribute("openapiContext", type="array"), - * @Attribute("jsonldContext", type="array"), - * @Attribute("push", type="bool"), - * @Attribute("security", type="string"), - * @Attribute("securityPostDenormalize", type="string"), - * @Attribute("swaggerContext", type="array") - * ) - */ -#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::TARGET_PARAMETER)] -final class ApiProperty -{ - use AttributesHydratorTrait; - - /** - * @var array - */ - private static $deprecatedAttributes = []; - - /** - * @var string - */ - public $description; - - /** - * @var bool - */ - public $readable; - - /** - * @var bool - */ - public $writable; - - /** - * @var bool - */ - public $readableLink; - - /** - * @var bool - */ - public $writableLink; - - /** - * @var bool - */ - public $required; - - /** - * @var string - */ - public $iri; - - /** - * @var bool - */ - public $identifier; - - /** - * @var string|int|float|bool|array|null - */ - public $default; - - /** - * @var string|int|float|bool|array|null - */ - public $example; - - public $types; - public $builtinTypes; - - /** - * @param string $description - * @param bool $readable - * @param bool $writable - * @param bool $readableLink - * @param bool $writableLink - * @param bool $required - * @param string $iri - * @param bool $identifier - * @param string|int|float|bool|array $default - * @param string|int|float|bool|array|null $example - * @param string $deprecationReason - * @param bool $fetchable - * @param bool $fetchEager - * @param array $jsonldContext - * @param array $openapiContext - * @param bool $push - * @param string $security - * @param array $swaggerContext - * @param string $securityPostDenormalize - * - * @throws InvalidArgumentException - */ - public function __construct( - $description = null, - ?bool $readable = null, - ?bool $writable = null, - ?bool $readableLink = null, - ?bool $writableLink = null, - ?bool $required = null, - ?string $iri = null, - ?bool $identifier = null, - $default = null, - $example = null, - - // attributes - ?array $attributes = null, - ?string $deprecationReason = null, - ?bool $fetchable = null, - ?bool $fetchEager = null, - ?array $jsonldContext = null, - ?array $openapiContext = null, - ?bool $push = null, - ?string $security = null, - ?array $swaggerContext = null, - ?string $securityPostDenormalize = null, - - ?array $types = [], - ?array $builtinTypes = [] - ) { - if (!\is_array($description)) { // @phpstan-ignore-line Doctrine annotations support - [$publicProperties, $configurableAttributes] = self::getConfigMetadata(); - - foreach ($publicProperties as $prop => $_) { - $this->{$prop} = ${$prop}; - } - - $description = []; - foreach ($configurableAttributes as $attribute => $_) { - $description[$attribute] = ${$attribute}; - } - } - - $this->hydrateAttributes($description); - } -} diff --git a/src/Core/Annotation/ApiResource.php b/src/Core/Annotation/ApiResource.php deleted file mode 100644 index 8f3a9c69887..00000000000 --- a/src/Core/Annotation/ApiResource.php +++ /dev/null @@ -1,251 +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); - -namespace ApiPlatform\Core\Annotation; - -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * ApiResource annotation. - * - * @author Kévin Dunglas - * - * @Annotation - * @Target({"CLASS"}) - * @Attributes( - * @Attribute("accessControl", type="string"), - * @Attribute("accessControlMessage", type="string"), - * @Attribute("attributes", type="array"), - * @Attribute("cacheHeaders", type="array"), - * @Attribute("collectionOperations", type="array"), - * @Attribute("compositeIdentifier", type="bool"), - * @Attribute("denormalizationContext", type="array"), - * @Attribute("deprecationReason", type="string"), - * @Attribute("description", type="string"), - * @Attribute("elasticsearch", type="bool"), - * @Attribute("fetchPartial", type="bool"), - * @Attribute("forceEager", type="bool"), - * @Attribute("formats", type="array"), - * @Attribute("filters", type="string[]"), - * @Attribute("graphql", type="array"), - * @Attribute("hydraContext", type="array"), - * @Attribute("input", type="mixed"), - * @Attribute("iri", type="string"), - * @Attribute("itemOperations", type="array"), - * @Attribute("mercure", type="mixed"), - * @Attribute("messenger", type="mixed"), - * @Attribute("normalizationContext", type="array"), - * @Attribute("openapiContext", type="array"), - * @Attribute("order", type="array"), - * @Attribute("output", type="mixed"), - * @Attribute("paginationClientEnabled", type="bool"), - * @Attribute("paginationClientItemsPerPage", type="bool"), - * @Attribute("paginationClientPartial", type="bool"), - * @Attribute("paginationEnabled", type="bool"), - * @Attribute("paginationFetchJoinCollection", type="bool"), - * @Attribute("paginationItemsPerPage", type="int"), - * @Attribute("maximumItemsPerPage", type="int"), - * @Attribute("paginationMaximumItemsPerPage", type="int"), - * @Attribute("paginationPartial", type="bool"), - * @Attribute("paginationViaCursor", type="array"), - * @Attribute("routePrefix", type="string"), - * @Attribute("security", type="string"), - * @Attribute("securityMessage", type="string"), - * @Attribute("securityPostDenormalize", type="string"), - * @Attribute("securityPostDenormalizeMessage", type="string"), - * @Attribute("securityPostValidation", type="string"), - * @Attribute("securityPostValidationMessage", type="string"), - * @Attribute("shortName", type="string"), - * @Attribute("stateless", type="bool"), - * @Attribute("subresourceOperations", type="array"), - * @Attribute("sunset", type="string"), - * @Attribute("swaggerContext", type="array"), - * @Attribute("urlGenerationStrategy", type="int"), - * @Attribute("validationGroups", type="mixed"), - * @Attribute("exceptionToStatus", type="array"), - * @Attribute("queryParameterValidationEnabled", type="bool") - * ) - */ -#[\Attribute(\Attribute::TARGET_CLASS)] -final class ApiResource -{ - use AttributesHydratorTrait; - - /** - * @var array - */ - private static $deprecatedAttributes = [ - 'accessControl' => ['security', '2.5'], - 'accessControlMessage' => ['securityMessage', '2.5'], - 'maximumItemsPerPage' => ['paginationMaximumItemsPerPage', '2.6'], - ]; - - /** - * @see https://api-platform.com/docs/core/operations - * - * @var array - */ - public $collectionOperations; - - /** - * @var string - */ - public $description; - - /** - * @see https://api-platform.com/docs/core/graphql - * - * @var array - */ - public $graphql; - - /** - * @var string - */ - public $iri; - - /** - * @see https://api-platform.com/docs/core/operations - * - * @var array - */ - public $itemOperations; - - /** - * @var string - */ - public $shortName; - - /** - * @see https://api-platform.com/docs/core/subresources - * - * @var array - */ - public $subresourceOperations; - - /** - * @param string $description - * @param array $collectionOperations https://api-platform.com/docs/core/operations - * @param array $graphql https://api-platform.com/docs/core/graphql - * @param array $itemOperations https://api-platform.com/docs/core/operations - * @param array $subresourceOperations https://api-platform.com/docs/core/subresources - * @param array $cacheHeaders https://api-platform.com/docs/core/performance/#setting-custom-http-cache-headers - * @param array $denormalizationContext https://api-platform.com/docs/core/serialization/#using-serialization-groups - * @param string $deprecationReason https://api-platform.com/docs/core/deprecations/#deprecating-resource-classes-operations-and-properties - * @param bool $elasticsearch https://api-platform.com/docs/core/elasticsearch/ - * @param bool $fetchPartial https://api-platform.com/docs/core/performance/#fetch-partial - * @param bool $forceEager https://api-platform.com/docs/core/performance/#force-eager - * @param array $formats https://api-platform.com/docs/core/content-negotiation/#configuring-formats-for-a-specific-resource-or-operation - * @param string[] $filters https://api-platform.com/docs/core/filters/#doctrine-orm-and-mongodb-odm-filters - * @param string[] $hydraContext https://api-platform.com/docs/core/extending-jsonld-context/#hydra - * @param string|false $input https://api-platform.com/docs/core/dto/#specifying-an-input-or-an-output-data-representation - * @param bool|array $mercure https://api-platform.com/docs/core/mercure - * @param bool $messenger https://api-platform.com/docs/core/messenger/#dispatching-a-resource-through-the-message-bus - * @param array $normalizationContext https://api-platform.com/docs/core/serialization/#using-serialization-groups - * @param array $openapiContext https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts - * @param array $order https://api-platform.com/docs/core/default-order/#overriding-default-order - * @param string|false $output https://api-platform.com/docs/core/dto/#specifying-an-input-or-an-output-data-representation - * @param bool $paginationClientEnabled https://api-platform.com/docs/core/pagination/#for-a-specific-resource-1 - * @param bool $paginationClientItemsPerPage https://api-platform.com/docs/core/pagination/#for-a-specific-resource-3 - * @param bool $paginationClientPartial https://api-platform.com/docs/core/pagination/#for-a-specific-resource-6 - * @param array $paginationViaCursor https://api-platform.com/docs/core/pagination/#cursor-based-pagination - * @param bool $paginationEnabled https://api-platform.com/docs/core/pagination/#for-a-specific-resource - * @param bool $paginationFetchJoinCollection https://api-platform.com/docs/core/pagination/#controlling-the-behavior-of-the-doctrine-orm-paginator - * @param int $paginationItemsPerPage https://api-platform.com/docs/core/pagination/#changing-the-number-of-items-per-page - * @param int $paginationMaximumItemsPerPage https://api-platform.com/docs/core/pagination/#changing-maximum-items-per-page - * @param bool $paginationPartial https://api-platform.com/docs/core/performance/#partial-pagination - * @param string $routePrefix https://api-platform.com/docs/core/operations/#prefixing-all-routes-of-all-operations - * @param string $security https://api-platform.com/docs/core/security - * @param string $securityMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message - * @param string $securityPostDenormalize https://api-platform.com/docs/core/security/#executing-access-control-rules-after-denormalization - * @param string $securityPostDenormalizeMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message - * @param string $securityPostValidation https://api-platform.com/docs/core/security/#executing-access-control-rules-after-validation - * @param string $securityPostValidationMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message - * @param bool $stateless - * @param string $sunset https://api-platform.com/docs/core/deprecations/#setting-the-sunset-http-header-to-indicate-when-a-resource-or-an-operation-will-be-removed - * @param array $swaggerContext https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts - * @param array $validationGroups https://api-platform.com/docs/core/validation/#using-validation-groups - * @param int $urlGenerationStrategy - * @param array $exceptionToStatus https://api-platform.com/docs/core/errors/#fine-grained-configuration - * @param bool $queryParameterValidationEnabled - * - * @throws InvalidArgumentException - */ - public function __construct( - $description = null, - ?array $collectionOperations = null, - ?array $graphql = null, - ?string $iri = null, - ?array $itemOperations = null, - ?string $shortName = null, - ?array $subresourceOperations = null, - - // attributes - ?array $attributes = null, - ?array $cacheHeaders = null, - ?array $denormalizationContext = null, - ?string $deprecationReason = null, - ?bool $elasticsearch = null, - ?bool $fetchPartial = null, - ?bool $forceEager = null, - ?array $formats = null, - ?array $filters = null, - ?array $hydraContext = null, - $input = null, - $mercure = null, - $messenger = null, - ?array $normalizationContext = null, - ?array $openapiContext = null, - ?array $order = null, - $output = null, - ?bool $paginationClientEnabled = null, - ?bool $paginationClientItemsPerPage = null, - ?bool $paginationClientPartial = null, - ?array $paginationViaCursor = null, - ?bool $paginationEnabled = null, - ?bool $paginationFetchJoinCollection = null, - ?int $paginationItemsPerPage = null, - ?int $paginationMaximumItemsPerPage = null, - ?bool $paginationPartial = null, - ?string $routePrefix = null, - ?string $security = null, - ?string $securityMessage = null, - ?string $securityPostDenormalize = null, - ?string $securityPostDenormalizeMessage = null, - ?string $securityPostValidation = null, - ?string $securityPostValidationMessage = null, - ?bool $stateless = null, - ?string $sunset = null, - ?array $swaggerContext = null, - ?array $validationGroups = null, - ?int $urlGenerationStrategy = null, - ?bool $compositeIdentifier = null, - ?array $exceptionToStatus = null, - ?bool $queryParameterValidationEnabled = null - ) { - if (!\is_array($description)) { // @phpstan-ignore-line Doctrine annotations support - [$publicProperties, $configurableAttributes] = self::getConfigMetadata(); - - foreach ($publicProperties as $prop => $_) { - $this->{$prop} = ${$prop}; - } - - $description = []; - foreach ($configurableAttributes as $attribute => $_) { - $description[$attribute] = ${$attribute}; - } - } - - $this->hydrateAttributes($description ?? []); // @phpstan-ignore-line - } -} diff --git a/src/Core/Annotation/ApiSubresource.php b/src/Core/Annotation/ApiSubresource.php deleted file mode 100644 index 27e321505f6..00000000000 --- a/src/Core/Annotation/ApiSubresource.php +++ /dev/null @@ -1,48 +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); - -namespace ApiPlatform\Core\Annotation; - -/** - * ApiSubresource annotation. - * - * @author Antoine Bluchet - * - * @Annotation - * @Target({"METHOD", "PROPERTY"}) - * @Attributes( - * @Attribute("maxDepth", type="int"), - * ) - */ -#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD)] -final class ApiSubresource -{ - /** - * @var int - */ - public $maxDepth; - - /** - * @param int $maxDepth - */ - public function __construct($maxDepth = null) - { - if (\is_array($maxDepth)) { // @phpstan-ignore-line - $this->maxDepth = $maxDepth['maxDepth'] ?? null; // @phpstan-ignore-line - - return; - } - - $this->maxDepth = $maxDepth; - } -} diff --git a/src/Core/Annotation/AttributesHydratorTrait.php b/src/Core/Annotation/AttributesHydratorTrait.php deleted file mode 100644 index 00fe7481994..00000000000 --- a/src/Core/Annotation/AttributesHydratorTrait.php +++ /dev/null @@ -1,99 +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); - -namespace ApiPlatform\Core\Annotation; - -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Util\Inflector; - -/** - * Hydrates attributes from annotation's parameters. - * - * @internal - * - * @author Baptiste Meyer - * @author Kévin Dunglas - */ -trait AttributesHydratorTrait -{ - private static $configMetadata; - - /** - * @internal - */ - public static function getConfigMetadata(): array - { - if (null !== self::$configMetadata) { - return self::$configMetadata; - } - - $rc = new \ReflectionClass(self::class); - - $publicProperties = []; - foreach ($rc->getProperties(\ReflectionProperty::IS_PUBLIC) as $reflectionProperty) { - $publicProperties[$reflectionProperty->getName()] = true; - } - - $configurableAttributes = []; - foreach ($rc->getConstructor()->getParameters() as $param) { - if (!isset($publicProperties[$name = $param->getName()])) { - $configurableAttributes[$name] = true; - } - } - - return [$publicProperties, $configurableAttributes]; - } - - /** - * @var array - */ - public $attributes = null; - - /** - * @throws InvalidArgumentException - */ - private function hydrateAttributes(array $values): void - { - if (isset($values['attributes'])) { - $this->attributes = $values['attributes']; - unset($values['attributes']); - } - - foreach (self::$deprecatedAttributes as $deprecatedAttribute => $options) { - if (\array_key_exists($deprecatedAttribute, $values)) { - $values[$options[0]] = $values[$deprecatedAttribute]; - @trigger_error(sprintf('Attribute "%s" is deprecated in annotation since API Platform %s, prefer using "%s" attribute instead', $deprecatedAttribute, $options[1], $options[0]), \E_USER_DEPRECATED); - unset($values[$deprecatedAttribute]); - } - } - - [$publicProperties, $configurableAttributes] = self::getConfigMetadata(); - foreach ($values as $key => $value) { - $key = (string) $key; - if (!isset($publicProperties[$key]) && !isset($configurableAttributes[$key]) && !isset(self::$deprecatedAttributes[$key])) { - throw new InvalidArgumentException(sprintf('Unknown property "%s" on annotation "%s".', $key, self::class)); - } - - if (isset($publicProperties[$key])) { - $this->{$key} = $value; - continue; - } - - if (!\is_array($this->attributes)) { - $this->attributes = []; - } - - $this->attributes += [Inflector::tableize($key) => $value]; - } - } -} diff --git a/src/Core/Annotation/TemporaryApiResource.php b/src/Core/Annotation/TemporaryApiResource.php deleted file mode 100644 index e54a5442888..00000000000 --- a/src/Core/Annotation/TemporaryApiResource.php +++ /dev/null @@ -1,21 +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); - -namespace ApiPlatform\Core\Annotation; - -final class TemporaryApiResource -{ - public function __construct() - { - } -} diff --git a/src/Core/Api/CachedIdentifiersExtractor.php b/src/Core/Api/CachedIdentifiersExtractor.php deleted file mode 100644 index 13d772a4c25..00000000000 --- a/src/Core/Api/CachedIdentifiersExtractor.php +++ /dev/null @@ -1,132 +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); - -namespace ApiPlatform\Core\Api; - -use ApiPlatform\Util\ResourceClassInfoTrait; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; - -/** - * {@inheritdoc} - * - * @author Antoine Bluchet - */ -final class CachedIdentifiersExtractor implements IdentifiersExtractorInterface -{ - use ResourceClassInfoTrait; - - public const CACHE_KEY_PREFIX = 'iri_identifiers'; - - private $cacheItemPool; - private $propertyAccessor; - private $decorated; - private $localCache = []; - private $localResourceCache = []; - - public function __construct(CacheItemPoolInterface $cacheItemPool, IdentifiersExtractorInterface $decorated, PropertyAccessorInterface $propertyAccessor = null, ResourceClassResolverInterface $resourceClassResolver = null) - { - $this->cacheItemPool = $cacheItemPool; - $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor(); - $this->decorated = $decorated; - $this->resourceClassResolver = $resourceClassResolver; - - if (null === $this->resourceClassResolver) { - @trigger_error(sprintf('Not injecting %s in the CachedIdentifiersExtractor might introduce cache issues with object identifiers.', ResourceClassResolverInterface::class), \E_USER_DEPRECATED); - } - } - - /** - * {@inheritdoc} - */ - public function getIdentifiersFromResourceClass(string $resourceClass): array - { - if (isset($this->localResourceCache[$resourceClass])) { - return $this->localResourceCache[$resourceClass]; - } - - return $this->localResourceCache[$resourceClass] = $this->decorated->getIdentifiersFromResourceClass($resourceClass); - } - - /** - * {@inheritdoc} - */ - public function getIdentifiersFromItem($item): array - { - $keys = $this->getKeys($item, function ($item) use (&$identifiers) { - return $identifiers = $this->decorated->getIdentifiersFromItem($item); - }); - - if (null !== $identifiers) { - return $identifiers; - } - - $identifiers = []; - foreach ($keys as $propertyName) { - $identifiers[$propertyName] = $this->propertyAccessor->getValue($item, $propertyName); - - if (!\is_object($identifiers[$propertyName])) { - continue; - } - - if (null === $relatedResourceClass = $this->getResourceClass($identifiers[$propertyName])) { - continue; - } - - if (!$relatedIdentifiers = $this->localCache[$relatedResourceClass] ?? false) { - $relatedCacheKey = self::CACHE_KEY_PREFIX.md5($relatedResourceClass); - try { - $relatedCacheItem = $this->cacheItemPool->getItem($relatedCacheKey); - if (!$relatedCacheItem->isHit()) { - return $this->decorated->getIdentifiersFromItem($item); - } - } catch (CacheException $e) { - return $this->decorated->getIdentifiersFromItem($item); - } - - $relatedIdentifiers = $relatedCacheItem->get(); - } - - $identifiers[$propertyName] = $this->propertyAccessor->getValue($identifiers[$propertyName], $relatedIdentifiers[0]); - } - - return $identifiers; - } - - private function getKeys($item, callable $retriever): array - { - $resourceClass = $this->getObjectClass($item); - if (isset($this->localCache[$resourceClass])) { - return $this->localCache[$resourceClass]; - } - - try { - $cacheItem = $this->cacheItemPool->getItem(self::CACHE_KEY_PREFIX.md5($resourceClass)); - } catch (CacheException $e) { - return $this->localCache[$resourceClass] = array_keys($retriever($item)); - } - - if ($cacheItem->isHit()) { - return $this->localCache[$resourceClass] = $cacheItem->get(); - } - - $keys = array_keys($retriever($item)); - - $cacheItem->set($keys); - $this->cacheItemPool->save($cacheItem); - - return $this->localCache[$resourceClass] = $keys; - } -} diff --git a/src/Core/Api/Entrypoint.php b/src/Core/Api/Entrypoint.php deleted file mode 100644 index af2588bfb28..00000000000 --- a/src/Core/Api/Entrypoint.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Api; - -class_exists(\ApiPlatform\Api\Entrypoint::class); - -if (false) { - final class Entrypoint extends \ApiPlatform\Api\Entrypoint - { - } -} diff --git a/src/Core/Api/FilterCollection.php b/src/Core/Api/FilterCollection.php deleted file mode 100644 index b1bcc1c3584..00000000000 --- a/src/Core/Api/FilterCollection.php +++ /dev/null @@ -1,33 +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); - -namespace ApiPlatform\Core\Api; - -use Psr\Container\ContainerInterface; - -/** - * A list of filters. - * - * @author Kévin Dunglas - * - * @deprecated since version 2.1, to be removed in 3.0. Use a service locator {@see \Psr\Container\ContainerInterface}. - */ -final class FilterCollection extends \ArrayObject -{ - public function __construct($input = [], $flags = 0, $iterator_class = 'ArrayIterator') - { - @trigger_error(sprintf('The %s class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of %s instead.', self::class, ContainerInterface::class), \E_USER_DEPRECATED); - - parent::__construct($input, $flags, $iterator_class); - } -} diff --git a/src/Core/Api/FilterCollectionFactory.php b/src/Core/Api/FilterCollectionFactory.php deleted file mode 100644 index 20da8ee17cf..00000000000 --- a/src/Core/Api/FilterCollectionFactory.php +++ /dev/null @@ -1,54 +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); - -namespace ApiPlatform\Core\Api; - -use Psr\Container\ContainerInterface; - -/** - * Filter collection factory. - * - * @author Baptiste Meyer - * - * @deprecated see FilterCollection - * - * @internal - */ -class FilterCollectionFactory -{ - private $filtersIds; - - /** - * @param string[] $filtersIds - */ - public function __construct(array $filtersIds) - { - $this->filtersIds = $filtersIds; - } - - /** - * Creates a filter collection from a filter locator. - */ - public function createFilterCollectionFromLocator(ContainerInterface $filterLocator): FilterCollection - { - $filters = []; - - foreach ($this->filtersIds as $filterId) { - if ($filterLocator->has($filterId)) { - $filters[$filterId] = $filterLocator->get($filterId); - } - } - - return new FilterCollection($filters); - } -} diff --git a/src/Core/Api/FilterLocatorTrait.php b/src/Core/Api/FilterLocatorTrait.php deleted file mode 100644 index b11504fbe15..00000000000 --- a/src/Core/Api/FilterLocatorTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Api; - -class_exists(\ApiPlatform\Api\FilterLocatorTrait::class); - -if (false) { - trait FilterLocatorTrait - { - use \ApiPlatform\Api\FilterLocatorTrait; - } -} diff --git a/src/Core/Api/FormatMatcher.php b/src/Core/Api/FormatMatcher.php deleted file mode 100644 index 38cc12cf6df..00000000000 --- a/src/Core/Api/FormatMatcher.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Api; - -class_exists(\ApiPlatform\Api\FormatMatcher::class); - -if (false) { - final class FormatMatcher extends \ApiPlatform\Api\FormatMatcher - { - } -} diff --git a/src/Core/Api/FormatsProvider.php b/src/Core/Api/FormatsProvider.php deleted file mode 100644 index 2c6ae254c73..00000000000 --- a/src/Core/Api/FormatsProvider.php +++ /dev/null @@ -1,109 +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); - -namespace ApiPlatform\Core\Api; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * {@inheritdoc} - * - * @author Anthony GRASSIOT - * - * @deprecated since API Platform 2.5, use the "formats" attribute instead - */ -final class FormatsProvider implements FormatsProviderInterface, OperationAwareFormatsProviderInterface -{ - private $configuredFormats; - private $resourceMetadataFactory; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, array $configuredFormats) - { - @trigger_error(sprintf('The "%s" class is deprecated since API Platform 2.5, use the "formats" attribute instead.', __CLASS__), \E_USER_DEPRECATED); - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->configuredFormats = $configuredFormats; - } - - /** - * {@inheritdoc} - * - * @throws InvalidArgumentException - */ - public function getFormatsFromAttributes(array $attributes): array - { - if (!$attributes || !isset($attributes['resource_class'])) { - return $this->configuredFormats; - } - - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - - if (!$formats = $resourceMetadata->getOperationAttribute($attributes, 'formats', [], true)) { - return $this->configuredFormats; - } - - if (!\is_array($formats)) { - throw new InvalidArgumentException(sprintf("The 'formats' attributes must be an array, %s given for resource class '%s'.", \gettype($formats), $attributes['resource_class'])); - } - - return $this->getOperationFormats($formats); - } - - /** - * {@inheritdoc} - * - * @throws InvalidArgumentException - */ - public function getFormatsFromOperation(string $resourceClass, string $operationName, string $operationType): array - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if (!$formats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'formats', [], true)) { - return $this->configuredFormats; - } - - if (!\is_array($formats)) { - throw new InvalidArgumentException(sprintf("The 'formats' attributes must be an array, %s given for resource class '%s'.", \gettype($formats), $resourceClass)); - } - - return $this->getOperationFormats($formats); - } - - /** - * Filter and populate the acceptable formats. - * - * @throws InvalidArgumentException - */ - private function getOperationFormats(array $annotationFormats): array - { - $resourceFormats = []; - foreach ($annotationFormats as $format => $value) { - if (!is_numeric($format)) { - $resourceFormats[$format] = (array) $value; - continue; - } - if (!\is_string($value)) { - throw new InvalidArgumentException(sprintf("The 'formats' attributes value must be a string when trying to include an already configured format, %s given.", \gettype($value))); - } - if (\array_key_exists($value, $this->configuredFormats)) { - $resourceFormats[$value] = $this->configuredFormats[$value]; - continue; - } - - throw new InvalidArgumentException(sprintf("You either need to add the format '%s' to your project configuration or declare a mime type for it in your annotation.", $value)); - } - - return $resourceFormats; - } -} diff --git a/src/Core/Api/FormatsProviderInterface.php b/src/Core/Api/FormatsProviderInterface.php deleted file mode 100644 index ea979141a28..00000000000 --- a/src/Core/Api/FormatsProviderInterface.php +++ /dev/null @@ -1,29 +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); - -namespace ApiPlatform\Core\Api; - -/** - * Extracts formats for a given operation according to the retrieved Metadata. - * - * @author Anthony GRASSIOT - * - * @deprecated since API Platform 2.5, use the "formats" attribute instead - */ -interface FormatsProviderInterface -{ - /** - * Finds formats for an operation. - */ - public function getFormatsFromAttributes(array $attributes): array; -} diff --git a/src/Core/Api/IdentifiersExtractor.php b/src/Core/Api/IdentifiersExtractor.php deleted file mode 100644 index f6bbf3f43fb..00000000000 --- a/src/Core/Api/IdentifiersExtractor.php +++ /dev/null @@ -1,121 +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); - -namespace ApiPlatform\Core\Api; - -use ApiPlatform\Api\IdentifiersExtractor as NewIdentifiersExtractor; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Util\ResourceClassInfoTrait; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; - -/** - * {@inheritdoc} - * - * @author Antoine Bluchet - */ -final class IdentifiersExtractor implements IdentifiersExtractorInterface -{ - use ResourceClassInfoTrait; - - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $propertyAccessor; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, PropertyAccessorInterface $propertyAccessor = null, ResourceClassResolverInterface $resourceClassResolver = null, bool $metadataBackwardCompatibilityLayer = null) - { - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor(); - $this->resourceClassResolver = $resourceClassResolver; - - if (null === $this->resourceClassResolver) { - @trigger_error(sprintf('Not injecting %s in the IdentifiersExtractor might introduce cache issues with object identifiers.', ResourceClassResolverInterface::class), \E_USER_DEPRECATED); - } - - if ($metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The service "%s" is deprecated, use %s instead.', self::class, NewIdentifiersExtractor::class)); - } - } - - /** - * {@inheritdoc} - */ - public function getIdentifiersFromResourceClass(string $resourceClass): array - { - $identifiers = []; - foreach ($properties = $this->propertyNameCollectionFactory->create($resourceClass) as $property) { - if ($this->propertyMetadataFactory->create($resourceClass, $property)->isIdentifier() ?? false) { - $identifiers[] = $property; - } - } - - if (!$identifiers) { - if (\in_array('id', iterator_to_array($properties), true)) { - return ['id']; - } - - throw new RuntimeException(sprintf('No identifier defined in "%s". You should add #[\ApiPlatform\Core\Annotation\ApiProperty(identifier: true)]" on the property identifying the resource."', $resourceClass)); - } - - return $identifiers; - } - - /** - * {@inheritdoc} - */ - public function getIdentifiersFromItem($item): array - { - $identifiers = []; - $resourceClass = $this->getResourceClass($item, true); - $identifierProperties = $this->getIdentifiersFromResourceClass($resourceClass); - - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - if (!\in_array($propertyName, $identifierProperties, true)) { - continue; - } - - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - $identifier = $identifiers[$propertyName] = $this->propertyAccessor->getValue($item, $propertyName); - - if (!\is_object($identifier)) { - continue; - } - - if (null === $relatedResourceClass = $this->getResourceClass($identifier)) { - continue; - } - - $relatedItem = $identifier; - unset($identifiers[$propertyName]); - foreach ($this->propertyNameCollectionFactory->create($relatedResourceClass) as $relatedPropertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($relatedResourceClass, $relatedPropertyName); - if ($propertyMetadata->isIdentifier()) { - if (isset($identifiers[$propertyName])) { - throw new RuntimeException(sprintf('Composite identifiers not supported in "%s" through relation "%s" of "%s" used as identifier', $relatedResourceClass, $propertyName, $resourceClass)); - } - - $identifiers[$propertyName] = $this->propertyAccessor->getValue($relatedItem, $relatedPropertyName); - } - } - - if (!isset($identifiers[$propertyName])) { - throw new RuntimeException(sprintf('No identifier found in "%s" through relation "%s" of "%s" used as identifier', $relatedResourceClass, $propertyName, $resourceClass)); - } - } - - return $identifiers; - } -} diff --git a/src/Core/Api/IdentifiersExtractorInterface.php b/src/Core/Api/IdentifiersExtractorInterface.php deleted file mode 100644 index 2a964d489ad..00000000000 --- a/src/Core/Api/IdentifiersExtractorInterface.php +++ /dev/null @@ -1,38 +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); - -namespace ApiPlatform\Core\Api; - -use ApiPlatform\Exception\RuntimeException; - -/** - * Extracts identifiers for a given Resource according to the retrieved Metadata. - * - * @author Antoine Bluchet - */ -interface IdentifiersExtractorInterface -{ - /** - * Finds identifiers from a Resource class. - */ - public function getIdentifiersFromResourceClass(string $resourceClass): array; - - /** - * Finds identifiers from an Item (object). - * - * @param object $item - * - * @throws RuntimeException - */ - public function getIdentifiersFromItem($item): array; -} diff --git a/src/Core/Api/IriConverterInterface.php b/src/Core/Api/IriConverterInterface.php deleted file mode 100644 index 85af6b3024f..00000000000 --- a/src/Core/Api/IriConverterInterface.php +++ /dev/null @@ -1,68 +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); - -namespace ApiPlatform\Core\Api; - -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ItemNotFoundException; -use ApiPlatform\Exception\RuntimeException; - -/** - * Converts item and resources to IRI and vice versa. - * - * @author Kévin Dunglas - */ -interface IriConverterInterface -{ - /** - * Retrieves an item from its IRI. - * - * @throws InvalidArgumentException - * @throws ItemNotFoundException - * - * @return object - */ - public function getItemFromIri(string $iri, array $context = []); - - /** - * Gets the IRI associated with the given item. - * - * @param object $item - * - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function getIriFromItem($item, int $referenceType = UrlGeneratorInterface::ABS_PATH): string; - - /** - * Gets the IRI associated with the given resource collection. - * - * @throws InvalidArgumentException - */ - public function getIriFromResourceClass(string $resourceClass, int $referenceType = UrlGeneratorInterface::ABS_PATH): string; - - /** - * Gets the item IRI associated with the given resource. - * - * @throws InvalidArgumentException - */ - public function getItemIriFromResourceClass(string $resourceClass, array $identifiers, int $referenceType = UrlGeneratorInterface::ABS_PATH): string; - - /** - * Gets the IRI associated with the given resource subresource. - * - * @throws InvalidArgumentException - */ - public function getSubresourceIriFromResourceClass(string $resourceClass, array $identifiers, int $referenceType = UrlGeneratorInterface::ABS_PATH): string; -} diff --git a/src/Core/Api/OperationAwareFormatsProviderInterface.php b/src/Core/Api/OperationAwareFormatsProviderInterface.php deleted file mode 100644 index 7860aa1ff0f..00000000000 --- a/src/Core/Api/OperationAwareFormatsProviderInterface.php +++ /dev/null @@ -1,29 +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); - -namespace ApiPlatform\Core\Api; - -/** - * Extracts formats for a given operation according to the retrieved Metadata. - * - * @author Anthony GRASSIOT - * - * @deprecated since API Platform 2.5, use the "formats" attribute instead - */ -interface OperationAwareFormatsProviderInterface extends FormatsProviderInterface -{ - /** - * Finds formats for an operation. - */ - public function getFormatsFromOperation(string $resourceClass, string $operationName, string $operationType): array; -} diff --git a/src/Core/Api/OperationMethodResolverInterface.php b/src/Core/Api/OperationMethodResolverInterface.php deleted file mode 100644 index a9f95c9706e..00000000000 --- a/src/Core/Api/OperationMethodResolverInterface.php +++ /dev/null @@ -1,40 +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); - -namespace ApiPlatform\Core\Api; - -use ApiPlatform\Exception\RuntimeException; - -/** - * Resolves the uppercased HTTP method associated with an operation. - * - * @author Kévin Dunglas - * - * @deprecated since API Platform 2.5, use the "method" attribute instead - */ -interface OperationMethodResolverInterface -{ - /** - * Resolves the uppercased HTTP method associated with a collection operation. - * - * @throws RuntimeException - */ - public function getCollectionOperationMethod(string $resourceClass, string $operationName): string; - - /** - * Resolves the uppercased HTTP method associated with an item operation. - * - * @throws RuntimeException - */ - public function getItemOperationMethod(string $resourceClass, string $operationName): string; -} diff --git a/src/Core/Api/OperationType.php b/src/Core/Api/OperationType.php deleted file mode 100644 index f1daa8b016b..00000000000 --- a/src/Core/Api/OperationType.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Api; - -final class OperationType -{ - public const ITEM = 'item'; - public const COLLECTION = 'collection'; - public const SUBRESOURCE = 'subresource'; - public const TYPES = [self::ITEM, self::COLLECTION, self::SUBRESOURCE]; -} diff --git a/src/Core/Api/OperationTypeDeprecationHelper.php b/src/Core/Api/OperationTypeDeprecationHelper.php deleted file mode 100644 index 4d8c35e873e..00000000000 --- a/src/Core/Api/OperationTypeDeprecationHelper.php +++ /dev/null @@ -1,44 +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); - -namespace ApiPlatform\Core\Api; - -/** - * Class OperationTypeDeprecationHelper - * Before API Platform 2.1, the operation type was one of: - * - "collection" (true) - * - "item" (false). - * - * Because we introduced a third type in API Platform 2.1, we're using a string with OperationType constants: - * - OperationType::ITEM - * - OperationType::COLLECTION - * - OperationType::SUBRESOURCE - * - * @internal - */ -final class OperationTypeDeprecationHelper -{ - /** - * @param string|bool $operationType - */ - public static function getOperationType($operationType): string - { - if (\is_bool($operationType)) { - @trigger_error('Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3', \E_USER_DEPRECATED); - - $operationType = $operationType ? OperationType::COLLECTION : OperationType::ITEM; - } - - return $operationType; - } -} diff --git a/src/Core/Api/ResourceClassResolver.php b/src/Core/Api/ResourceClassResolver.php deleted file mode 100644 index 9eff13927b7..00000000000 --- a/src/Core/Api/ResourceClassResolver.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Api; - -class_exists(\ApiPlatform\Api\ResourceClassResolver::class); - -if (false) { - final class ResourceClassResolver extends \ApiPlatform\Api\ResourceClassResolver - { - } -} diff --git a/src/Core/Bridge/Doctrine/Common/DataPersister.php b/src/Core/Bridge/Doctrine/Common/DataPersister.php deleted file mode 100644 index a13d92fc5f7..00000000000 --- a/src/Core/Bridge/Doctrine/Common/DataPersister.php +++ /dev/null @@ -1,105 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common; - -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Util\ClassInfoTrait; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager as DoctrineObjectManager; - -/** - * Data persister for Doctrine. - * - * @author Baptiste Meyer - * - * @deprecated - */ -final class DataPersister implements ContextAwareDataPersisterInterface -{ - use ClassInfoTrait; - - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry) - { - $this->managerRegistry = $managerRegistry; - } - - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - return null !== $this->getManager($data); - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []) - { - if (!$manager = $this->getManager($data)) { - return $data; - } - - if (!$manager->contains($data) || $this->isDeferredExplicit($manager, $data)) { - $manager->persist($data); - } - - $manager->flush(); - $manager->refresh($data); - - return $data; - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []) - { - if (!$manager = $this->getManager($data)) { - return; - } - - $manager->remove($data); - $manager->flush(); - } - - /** - * Gets the Doctrine object manager associated with given data. - * - * @param mixed $data - */ - private function getManager($data): ?DoctrineObjectManager - { - return \is_object($data) ? $this->managerRegistry->getManagerForClass($this->getObjectClass($data)) : null; - } - - /** - * Checks if doctrine does not manage data automatically. - * - * @param mixed $data - */ - private function isDeferredExplicit(DoctrineObjectManager $manager, $data): bool - { - $classMetadata = $manager->getClassMetadata($this->getObjectClass($data)); - if (($classMetadata instanceof ClassMetadataInfo || $classMetadata instanceof ClassMetadata) && method_exists($classMetadata, 'isChangeTrackingDeferredExplicit')) { - return $classMetadata->isChangeTrackingDeferredExplicit(); - } - - return false; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/BooleanFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/BooleanFilterTrait.php deleted file mode 100644 index a010295a6ca..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/BooleanFilterTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\BooleanFilterTrait::class); - -if (false) { - trait BooleanFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\BooleanFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/DateFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/DateFilterTrait.php deleted file mode 100644 index e3af076d8b2..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/DateFilterTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\DateFilterTrait::class); - -if (false) { - trait DateFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\DateFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/ExistsFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/ExistsFilterTrait.php deleted file mode 100644 index 6fb083c5238..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/ExistsFilterTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\ExistsFilterTrait::class); - -if (false) { - trait ExistsFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\ExistsFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/NumericFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/NumericFilterTrait.php deleted file mode 100644 index bdb714063d2..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/NumericFilterTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\NumericFilterTrait::class); - -if (false) { - trait NumericFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\NumericFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/OrderFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/OrderFilterTrait.php deleted file mode 100644 index 96a3664ffdb..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/OrderFilterTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\OrderFilterTrait::class); - -if (false) { - trait OrderFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\OrderFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/RangeFilterTrait.php deleted file mode 100644 index 32d985d341d..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/RangeFilterTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\RangeFilterTrait::class); - -if (false) { - trait RangeFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\RangeFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/SearchFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/SearchFilterTrait.php deleted file mode 100644 index 9a37121ceed..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/SearchFilterTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait::class); - -if (false) { - trait SearchFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/PropertyHelperTrait.php b/src/Core/Bridge/Doctrine/Common/PropertyHelperTrait.php deleted file mode 100644 index 3695281abe2..00000000000 --- a/src/Core/Bridge/Doctrine/Common/PropertyHelperTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common; - -class_exists(\ApiPlatform\Doctrine\Common\PropertyHelperTrait::class); - -if (false) { - trait PropertyHelperTrait - { - use \ApiPlatform\Doctrine\Common\PropertyHelperTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTrait.php b/src/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTrait.php deleted file mode 100644 index 3ecb1f9dfff..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTrait.php +++ /dev/null @@ -1,113 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Common\Util; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\PropertyNotFoundException; -use Doctrine\DBAL\Types\ConversionException; -use Doctrine\DBAL\Types\Type as DBALType; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\ObjectManager; - -/** - * @internal - */ -trait IdentifierManagerTrait -{ - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $resourceMetadataFactory; - - /** - * Transform and check the identifier, composite or not. - * - * @param int|string $id - * - * @throws PropertyNotFoundException - * @throws InvalidIdentifierException - */ - private function normalizeIdentifiers($id, ObjectManager $manager, string $resourceClass): array - { - $identifierValues = [$id]; - $doctrineClassMetadata = $manager->getClassMetadata($resourceClass); - $doctrineIdentifierFields = $doctrineClassMetadata->getIdentifier(); - $isOrm = $manager instanceof EntityManagerInterface; - $isOdm = $manager instanceof DocumentManager; - $platform = $isOrm ? $manager->getConnection()->getDatabasePlatform() : null; - $identifiersMap = null; - - if (\count($doctrineIdentifierFields) > 1) { - $identifiersMap = []; - - // first transform identifiers to a proper key/value array - foreach (explode(';', (string) $id) as $identifier) { - if (!$identifier) { - continue; - } - - $identifierPair = explode('=', $identifier); - $identifiersMap[$identifierPair[0]] = $identifierPair[1]; - } - } - - $identifiers = []; - $i = 0; - - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - - if (!$propertyMetadata->isIdentifier()) { - continue; - } - - $identifier = null === $identifiersMap ? $identifierValues[$i] ?? null : $identifiersMap[$propertyName] ?? null; - if (null === $identifier) { - $exceptionMessage = sprintf('Invalid identifier "%s", "%s" was not found', $id, $propertyName); - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $exceptionMessage .= sprintf(' for resource "%s"', $resourceMetadata->getShortName()); - } - - throw new PropertyNotFoundException($exceptionMessage.'.'); - } - - $doctrineTypeName = $doctrineClassMetadata->getTypeOfField($propertyName); - - try { - if ($isOrm && null !== $doctrineTypeName && DBALType::hasType($doctrineTypeName)) { - $identifier = DBALType::getType($doctrineTypeName)->convertToPHPValue($identifier, $platform); - } - if ($isOdm && null !== $doctrineTypeName && MongoDbType::hasType($doctrineTypeName)) { - $identifier = MongoDbType::getType($doctrineTypeName)->convertToPHPValue($identifier); - } - } catch (ConversionException $e) { - $exceptionMessage = sprintf('Invalid value "%s" provided for an identifier', $propertyName); - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $exceptionMessage .= sprintf(' for resource "%s"', $resourceMetadata->getShortName()); - } - - throw new InvalidIdentifierException($exceptionMessage.'.', $e->getCode(), $e); - } - - $identifiers[$propertyName] = $identifier; - ++$i; - } - - return $identifiers; - } -} diff --git a/src/Core/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php b/src/Core/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php deleted file mode 100644 index 2cf6b56b204..00000000000 --- a/src/Core/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php +++ /dev/null @@ -1,285 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\EventListener; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Bridge\Symfony\Messenger\DispatchTrait; -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Core\Exception\RuntimeException; -use ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface as GraphQlMercureSubscriptionIriGeneratorInterface; -use ApiPlatform\Core\GraphQl\Subscription\SubscriptionManagerInterface as GraphQlSubscriptionManagerInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ResourceClassInfoTrait; -use Doctrine\Common\EventArgs; -use Doctrine\ODM\MongoDB\Event\OnFlushEventArgs as MongoDbOdmOnFlushEventArgs; -use Doctrine\ORM\Event\OnFlushEventArgs as OrmOnFlushEventArgs; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\Mercure\HubRegistry; -use Symfony\Component\Mercure\Update; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Serializer\SerializerInterface; - -/** - * Publishes resources updates to the Mercure hub. - * - * @author Kévin Dunglas - * - * @experimental - */ -final class PublishMercureUpdatesListener -{ - use DispatchTrait; - use ResourceClassInfoTrait; - - private const ALLOWED_KEYS = [ - 'topics' => true, - 'data' => true, - 'private' => true, - 'id' => true, - 'type' => true, - 'retry' => true, - 'normalization_context' => true, - 'hub' => true, - 'enable_async_update' => true, - ]; - - private $iriConverter; - private $serializer; - private $hubRegistry; - private $expressionLanguage; - private $createdObjects; - private $updatedObjects; - private $deletedObjects; - private $formats; - private $graphQlSubscriptionManager; - private $graphQlMercureSubscriptionIriGenerator; - - /** - * @param array $formats - * @param HubRegistry|callable $hubRegistry - */ - public function __construct(ResourceClassResolverInterface $resourceClassResolver, IriConverterInterface $iriConverter, ResourceMetadataFactoryInterface $resourceMetadataFactory, SerializerInterface $serializer, array $formats, MessageBusInterface $messageBus = null, $hubRegistry = null, ?GraphQlSubscriptionManagerInterface $graphQlSubscriptionManager = null, ?GraphQlMercureSubscriptionIriGeneratorInterface $graphQlMercureSubscriptionIriGenerator = null, ExpressionLanguage $expressionLanguage = null) - { - if (null === $messageBus && null === $hubRegistry) { - throw new InvalidArgumentException('A message bus or a hub registry must be provided.'); - } - - $this->resourceClassResolver = $resourceClassResolver; - $this->iriConverter = $iriConverter; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->serializer = $serializer; - $this->formats = $formats; - $this->messageBus = $messageBus; - $this->hubRegistry = $hubRegistry; - $this->expressionLanguage = $expressionLanguage ?? (class_exists(ExpressionLanguage::class) ? new ExpressionLanguage() : null); - $this->graphQlSubscriptionManager = $graphQlSubscriptionManager; - $this->graphQlMercureSubscriptionIriGenerator = $graphQlMercureSubscriptionIriGenerator; - $this->reset(); - } - - /** - * Collects created, updated and deleted objects. - */ - public function onFlush(EventArgs $eventArgs): void - { - if ($eventArgs instanceof OrmOnFlushEventArgs) { - $uow = $eventArgs->getEntityManager()->getUnitOfWork(); - } elseif ($eventArgs instanceof MongoDbOdmOnFlushEventArgs) { - $uow = $eventArgs->getDocumentManager()->getUnitOfWork(); - } else { - return; - } - - $methodName = $eventArgs instanceof OrmOnFlushEventArgs ? 'getScheduledEntityInsertions' : 'getScheduledDocumentInsertions'; - foreach ($uow->{$methodName}() as $object) { - $this->storeObjectToPublish($object, 'createdObjects'); - } - - $methodName = $eventArgs instanceof OrmOnFlushEventArgs ? 'getScheduledEntityUpdates' : 'getScheduledDocumentUpdates'; - foreach ($uow->{$methodName}() as $object) { - $this->storeObjectToPublish($object, 'updatedObjects'); - } - - $methodName = $eventArgs instanceof OrmOnFlushEventArgs ? 'getScheduledEntityDeletions' : 'getScheduledDocumentDeletions'; - foreach ($uow->{$methodName}() as $object) { - $this->storeObjectToPublish($object, 'deletedObjects'); - } - } - - /** - * Publishes updates for changes collected on flush, and resets the store. - */ - public function postFlush(): void - { - try { - foreach ($this->createdObjects as $object) { - $this->publishUpdate($object, $this->createdObjects[$object], 'create'); - } - - foreach ($this->updatedObjects as $object) { - $this->publishUpdate($object, $this->updatedObjects[$object], 'update'); - } - - foreach ($this->deletedObjects as $object) { - $this->publishUpdate($object, $this->deletedObjects[$object], 'delete'); - } - } finally { - $this->reset(); - } - } - - private function reset(): void - { - $this->createdObjects = new \SplObjectStorage(); - $this->updatedObjects = new \SplObjectStorage(); - $this->deletedObjects = new \SplObjectStorage(); - } - - /** - * @param object $object - */ - private function storeObjectToPublish($object, string $property): void - { - if (null === $resourceClass = $this->getResourceClass($object)) { - return; - } - - $options = $this->resourceMetadataFactory->create($resourceClass)->getAttribute('mercure', false); - - if (\is_string($options)) { - if (null === $this->expressionLanguage) { - throw new RuntimeException('The Expression Language component is not installed. Try running "composer require symfony/expression-language".'); - } - - $options = $this->expressionLanguage->evaluate($options, ['object' => $object]); - } - - if (false === $options) { - return; - } - - if (true === $options) { - $options = []; - } - - if (!\is_array($options)) { - throw new InvalidArgumentException(sprintf('The value of the "mercure" attribute of the "%s" resource class must be a boolean, an array of options or an expression returning this array, "%s" given.', $resourceClass, \gettype($options))); - } - - foreach ($options as $key => $value) { - if (0 === $key) { - if (method_exists(Update::class, 'isPrivate')) { - throw new \InvalidArgumentException('Targets do not exist anymore since Mercure 0.10. Mark the update as private instead or downgrade the Mercure Component to version 0.3'); - } - - @trigger_error('Targets do not exist anymore since Mercure 0.10. Mark the update as private instead.', \E_USER_DEPRECATED); - break; - } - - if (!isset(self::ALLOWED_KEYS[$key])) { - throw new InvalidArgumentException(sprintf('The option "%s" set in the "mercure" attribute of the "%s" resource does not exist. Existing options: "%s"', $key, $resourceClass, implode('", "', self::ALLOWED_KEYS))); - } - - if ('hub' === $key && !$this->hubRegistry instanceof HubRegistry) { - throw new InvalidArgumentException(sprintf('The option "hub" of the "mercure" attribute cannot be set on the "%s" resource . Try running "composer require symfony/mercure:^0.5".', $resourceClass)); - } - } - - $options['enable_async_update'] = $options['enable_async_update'] ?? true; - - if ('deletedObjects' === $property) { - $this->deletedObjects[(object) [ - 'id' => $this->iriConverter->getIriFromItem($object), - 'iri' => $this->iriConverter->getIriFromItem($object, UrlGeneratorInterface::ABS_URL), - ]] = $options; - - return; - } - - $this->{$property}[$object] = $options; - } - - /** - * @param object $object - */ - private function publishUpdate($object, array $options, string $type): void - { - if ($object instanceof \stdClass) { - // By convention, if the object has been deleted, we send only its IRI. - // This may change in the feature, because it's not JSON Merge Patch compliant, - // and I'm not a fond of this approach. - $iri = $options['topics'] ?? $object->iri; - /** @var string $data */ - $data = json_encode(['@id' => $object->id]); - } else { - $resourceClass = $this->getObjectClass($object); - $context = $options['normalization_context'] ?? $this->resourceMetadataFactory->create($resourceClass)->getAttribute('normalization_context', []); - - $iri = $options['topics'] ?? $this->iriConverter->getIriFromItem($object, UrlGeneratorInterface::ABS_URL); - $data = $options['data'] ?? $this->serializer->serialize($object, key($this->formats), $context); - } - - $updates = array_merge([$this->buildUpdate($iri, $data, $options)], $this->getGraphQlSubscriptionUpdates($object, $options, $type)); - - foreach ($updates as $update) { - if ($options['enable_async_update'] && $this->messageBus) { - $this->dispatch($update); - continue; - } - - $this->hubRegistry instanceof HubRegistry ? $this->hubRegistry->getHub($options['hub'] ?? null)->publish($update) : ($this->hubRegistry)($update); - } - } - - /** - * @param object $object - * - * @return Update[] - */ - private function getGraphQlSubscriptionUpdates($object, array $options, string $type): array - { - if ('update' !== $type || !$this->graphQlSubscriptionManager || !$this->graphQlMercureSubscriptionIriGenerator) { - return []; - } - - $payloads = $this->graphQlSubscriptionManager->getPushPayloads($object); - - $updates = []; - foreach ($payloads as [$subscriptionId, $data]) { - $updates[] = $this->buildUpdate( - $this->graphQlMercureSubscriptionIriGenerator->generateTopicIri($subscriptionId), - (string) (new JsonResponse($data))->getContent(), - $options - ); - } - - return $updates; - } - - /** - * @param string|string[] $iri - */ - private function buildUpdate($iri, string $data, array $options): Update - { - if (method_exists(Update::class, 'isPrivate')) { - return new Update($iri, $data, $options['private'] ?? false, $options['id'] ?? null, $options['type'] ?? null, $options['retry'] ?? null); - } - - // Mercure Component < 0.4. - return new Update($iri, $data, $options); // @phpstan-ignore-line - } -} diff --git a/src/Core/Bridge/Doctrine/EventListener/PurgeHttpCacheListener.php b/src/Core/Bridge/Doctrine/EventListener/PurgeHttpCacheListener.php deleted file mode 100644 index 32c6875e788..00000000000 --- a/src/Core/Bridge/Doctrine/EventListener/PurgeHttpCacheListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\EventListener; - -class_exists(\ApiPlatform\Doctrine\EventListener\PurgeHttpCacheListener::class); - -if (false) { - final class PurgeHttpCacheListener extends \ApiPlatform\Doctrine\EventListener\PurgeHttpCacheListener - { - } -} diff --git a/src/Core/Bridge/Doctrine/EventListener/WriteListener.php b/src/Core/Bridge/Doctrine/EventListener/WriteListener.php deleted file mode 100644 index 68ac5b04e9f..00000000000 --- a/src/Core/Bridge/Doctrine/EventListener/WriteListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\EventListener; - -class_exists(\ApiPlatform\Doctrine\EventListener\WriteListener::class); - -if (false) { - final class WriteListener extends \ApiPlatform\Doctrine\EventListener\WriteListener - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProvider.php b/src/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProvider.php deleted file mode 100644 index a2693cdc9d9..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProvider.php +++ /dev/null @@ -1,108 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; - -/** - * Collection data provider for the Doctrine MongoDB ODM. - * - * @experimental - * - * @author Alan Poulain - */ -final class CollectionDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface -{ - private $managerRegistry; - private $resourceMetadataFactory; - private $collectionExtensions; - - /** - * @param AggregationCollectionExtensionInterface[] $collectionExtensions - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - */ - public function __construct(ManagerRegistry $managerRegistry, $resourceMetadataFactory, iterable $collectionExtensions = []) - { - $this->managerRegistry = $managerRegistry; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->collectionExtensions = $collectionExtensions; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return $this->managerRegistry->getManagerForClass($resourceClass) instanceof DocumentManager; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - /** @var DocumentManager $manager */ - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - - /** @var ObjectRepository $repository */ - $repository = $manager->getRepository($resourceClass); - if (!$repository instanceof DocumentRepository) { - throw new RuntimeException(sprintf('The repository for "%s" must be an instance of "%s".', $resourceClass, DocumentRepository::class)); - } - - $aggregationBuilder = $repository->createAggregationBuilder(); - foreach ($this->collectionExtensions as $extension) { - $extension->applyToCollection($aggregationBuilder, $resourceClass, $operationName, $context); - - if ($extension instanceof AggregationResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context); - } - } - - $attribute = []; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName); - $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; - } catch (OperationNotFoundException $e) { - $attribute = $resourceMetadata->getOperation()->getExtraProperties()['doctrine_mongodb'] ?? []; - } - } else { - /** @var ResourceMetadata */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $attribute = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'doctrine_mongodb', [], true); - } - - $executeOptions = $attribute['execute_options'] ?? []; - $builder = $aggregationBuilder->hydrate($resourceClass); - - if (method_exists($builder, 'getAggregation')) { - return $builder->getAggregation($executeOptions)->getIterator(); - } - - return $builder->execute($executeOptions); - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtension.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtension.php deleted file mode 100644 index 64831aa4452..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension; - -class_exists(\ApiPlatform\Doctrine\Odm\Extension\FilterExtension::class); - -if (false) { - final class FilterExtension extends \ApiPlatform\Doctrine\Odm\Extension\FilterExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtension.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtension.php deleted file mode 100644 index 959ecee541f..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\OrderExtension::class); - -if (false) { - final class OrderExtension extends \ApiPlatform\Doctrine\Orm\Extension\OrderExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php deleted file mode 100644 index 0d784d22a4c..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\PaginationExtension::class); - -if (false) { - final class PaginationExtension extends \ApiPlatform\Doctrine\Orm\Extension\PaginationExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/AbstractFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/AbstractFilter.php deleted file mode 100644 index 50a21cda197..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/AbstractFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\AbstractFilter::class); - -if (false) { - class AbstractFilter extends \ApiPlatform\Doctrine\Odm\Filter\AbstractFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/BooleanFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/BooleanFilter.php deleted file mode 100644 index 3c9e06559f4..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/BooleanFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\BooleanFilter::class); - -if (false) { - final class BooleanFilter extends \ApiPlatform\Doctrine\Odm\Filter\BooleanFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/DateFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/DateFilter.php deleted file mode 100644 index 8a4da83c350..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/DateFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\DateFilter::class); - -if (false) { - class DateFilter extends \ApiPlatform\Doctrine\Odm\Filter\DateFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/ExistsFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/ExistsFilter.php deleted file mode 100644 index c03ca561946..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/ExistsFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\ExistsFilter::class); - -if (false) { - final class ExistsFilter extends \ApiPlatform\Doctrine\Odm\Filter\ExistsFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/NumericFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/NumericFilter.php deleted file mode 100644 index 8b190ea6e5f..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/NumericFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\NumericFilter::class); - -if (false) { - final class NumericFilter extends \ApiPlatform\Doctrine\Odm\Filter\NumericFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/OrderFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/OrderFilter.php deleted file mode 100644 index 9c050013229..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/OrderFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\OrderFilter::class); - -if (false) { - final class OrderFilter extends \ApiPlatform\Doctrine\Odm\Filter\OrderFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/RangeFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/RangeFilter.php deleted file mode 100644 index 2846094e7df..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/RangeFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\RangeFilter::class); - -if (false) { - final class RangeFilter extends \ApiPlatform\Doctrine\Odm\Filter\RangeFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php deleted file mode 100644 index 5e1e323ea4e..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php +++ /dev/null @@ -1,223 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface; -use ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait; -use ApiPlatform\Doctrine\Odm\Filter\AbstractFilter; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MongoDBClassMetadata; -use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\Mapping\ClassMetadata; -use MongoDB\BSON\Regex; -use Psr\Log\LoggerInterface; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Filter the collection by given properties. - * - * @experimental - * - * @author Kévin Dunglas - * @author Alan Poulain - */ -final class SearchFilter extends AbstractFilter implements SearchFilterInterface -{ - use SearchFilterTrait; - - public const DOCTRINE_INTEGER_TYPE = [MongoDbType::INTEGER, MongoDbType::INT]; - - public function __construct(ManagerRegistry $managerRegistry, IriConverterInterface $iriConverter, IdentifiersExtractorInterface $identifiersExtractor, PropertyAccessorInterface $propertyAccessor = null, LoggerInterface $logger = null, array $properties = null, NameConverterInterface $nameConverter = null) - { - parent::__construct($managerRegistry, $logger, $properties, $nameConverter); - - $this->iriConverter = $iriConverter; - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - $this->identifiersExtractor = $identifiersExtractor; - } - - protected function getIriConverter(): IriConverterInterface - { - return $this->iriConverter; - } - - protected function getPropertyAccessor(): PropertyAccessorInterface - { - return $this->propertyAccessor; - } - - /** - * {@inheritdoc} - */ - protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) - { - if ( - null === $value || - !$this->isPropertyEnabled($property, $resourceClass) || - !$this->isPropertyMapped($property, $resourceClass, true) - ) { - return; - } - - $matchField = $field = $property; - - $values = $this->normalizeValues((array) $value, $property); - if (null === $values) { - return; - } - - $associations = []; - if ($this->isPropertyNested($property, $resourceClass)) { - [$matchField, $field, $associations] = $this->addLookupsForNestedProperty($property, $aggregationBuilder, $resourceClass); - } - - $caseSensitive = true; - $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; - - // prefixing the strategy with i makes it case insensitive - if (0 === strpos($strategy, 'i')) { - $strategy = substr($strategy, 1); - $caseSensitive = false; - } - - /** @var MongoDBClassMetadata */ - $metadata = $this->getNestedMetadata($resourceClass, $associations); - - if ($metadata->hasField($field) && !$metadata->hasAssociation($field)) { - if ('id' === $field) { - $values = array_map([$this, 'getIdFromValue'], $values); - } - - if (!$this->hasValidValues($values, $this->getDoctrineFieldType($property, $resourceClass))) { - $this->logger->notice('Invalid filter ignored', [ - 'exception' => new InvalidArgumentException(sprintf('Values for field "%s" are not valid according to the doctrine type.', $field)), - ]); - - return; - } - - $this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata); - - return; - } - - // metadata doesn't have the field, nor an association on the field - if (!$metadata->hasAssociation($field)) { - return; - } - - $values = array_map([$this, 'getIdFromValue'], $values); - $doctrineTypeField = $this->getDoctrineFieldType($property, $resourceClass); - - if (null !== $this->identifiersExtractor) { - $associationResourceClass = $metadata->getAssociationTargetClass($field); - $associationFieldIdentifier = $this->identifiersExtractor->getIdentifiersFromResourceClass($associationResourceClass)[0]; - $doctrineTypeField = $this->getDoctrineFieldType($associationFieldIdentifier, $associationResourceClass); - } - - if (!$this->hasValidValues($values, $doctrineTypeField)) { - $this->logger->notice('Invalid filter ignored', [ - 'exception' => new InvalidArgumentException(sprintf('Values for field "%s" are not valid according to the doctrine type.', $property)), - ]); - - return; - } - - $this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata); - } - - /** - * Add equality match stage according to the strategy. - * - * @param mixed $values - */ - private function addEqualityMatchStrategy(string $strategy, Builder $aggregationBuilder, string $field, string $matchField, $values, bool $caseSensitive, ClassMetadata $metadata): void - { - $inValues = []; - foreach ($values as $inValue) { - $inValues[] = $this->getEqualityMatchStrategyValue($strategy, $field, $inValue, $caseSensitive, $metadata); - } - - $aggregationBuilder - ->match() - ->field($matchField) - ->in($inValues); - } - - /** - * Get equality match value according to the strategy. - * - * @param mixed $value - * - * @throws InvalidArgumentException If strategy does not exist - * - * @return Regex|string - */ - private function getEqualityMatchStrategyValue(string $strategy, string $field, $value, bool $caseSensitive, ClassMetadata $metadata) - { - $type = $metadata->getTypeOfField($field); - - if (!MongoDbType::hasType($type)) { - return $value; - } - if (MongoDbType::STRING !== $type) { - return MongoDbType::getType($type)->convertToDatabaseValue($value); - } - - $quotedValue = preg_quote($value); - - switch ($strategy) { - case null: - case self::STRATEGY_EXACT: - return $caseSensitive ? $value : new Regex("^$quotedValue$", 'i'); - case self::STRATEGY_PARTIAL: - return new Regex($quotedValue, $caseSensitive ? '' : 'i'); - case self::STRATEGY_START: - return new Regex("^$quotedValue", $caseSensitive ? '' : 'i'); - case self::STRATEGY_END: - return new Regex("$quotedValue$", $caseSensitive ? '' : 'i'); - case self::STRATEGY_WORD_START: - return new Regex("(^$quotedValue.*|.*\s$quotedValue.*)", $caseSensitive ? '' : 'i'); - default: - throw new InvalidArgumentException(sprintf('strategy %s does not exist.', $strategy)); - } - } - - /** - * {@inheritdoc} - */ - protected function getType(string $doctrineType): string - { - switch ($doctrineType) { - case MongoDbType::INT: - case MongoDbType::INTEGER: - return 'int'; - case MongoDbType::BOOL: - case MongoDbType::BOOLEAN: - return 'bool'; - case MongoDbType::DATE: - return \DateTimeInterface::class; - case MongoDbType::FLOAT: - return 'float'; - } - - return 'string'; - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProvider.php b/src/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProvider.php deleted file mode 100644 index 75e7050339d..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProvider.php +++ /dev/null @@ -1,131 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; - -/** - * Item data provider for the Doctrine MongoDB ODM. - * - * @experimental - * - * @author Alan Poulain - */ -final class ItemDataProvider implements DenormalizedIdentifiersAwareItemDataProviderInterface, RestrictedDataProviderInterface -{ - use IdentifierManagerTrait; - - private $managerRegistry; - private $resourceMetadataFactory; - private $itemExtensions; - - /** - * @param AggregationItemExtensionInterface[] $itemExtensions - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - */ - public function __construct(ManagerRegistry $managerRegistry, $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $itemExtensions = []) - { - $this->managerRegistry = $managerRegistry; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->itemExtensions = $itemExtensions; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return $this->managerRegistry->getManagerForClass($resourceClass) instanceof DocumentManager; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - /** @var DocumentManager $manager */ - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - - if (!\is_array($id) && !($context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] ?? false)) { - $id = $this->normalizeIdentifiers($id, $manager, $resourceClass); - } - - $id = (array) $id; - - if (!($context['fetch_data'] ?? true)) { - return $manager->getReference($resourceClass, reset($id)); - } - - $repository = $manager->getRepository($resourceClass); - /** @var ObjectRepository $repository */ - if (!$repository instanceof DocumentRepository) { - throw new RuntimeException(sprintf('The repository for "%s" must be an instance of "%s".', $resourceClass, DocumentRepository::class)); - } - - $aggregationBuilder = $repository->createAggregationBuilder(); - - foreach ($id as $propertyName => $value) { - $aggregationBuilder->match()->field($propertyName)->equals($value); - } - - foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($aggregationBuilder, $resourceClass, $id, $operationName, $context); - - if ($extension instanceof AggregationResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context); - } - } - - $attribute = []; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName); - $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; - } catch (OperationNotFoundException $e) { - $attribute = $resourceMetadata->getOperation()->getExtraProperties()['doctrine_mongodb'] ?? []; - } - } else { - /** @var ResourceMetadata */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $attribute = $resourceMetadata->getItemOperationAttribute($operationName, 'doctrine_mongodb', [], true); - } - - $executeOptions = $attribute['execute_options'] ?? []; - - return $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions)->current() ?: null; - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php deleted file mode 100644 index 24b0c1cc081..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php +++ /dev/null @@ -1,79 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Metadata\Property; - -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\Persistence\ManagerRegistry; - -/** - * Use Doctrine metadata to populate the identifier property. - * - * @experimental - * - * @author Kévin Dunglas - * @author Alan Poulain - */ -final class DoctrineMongoDbOdmPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $decorated; - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry, PropertyMetadataFactoryInterface $decorated) - { - $this->managerRegistry = $managerRegistry; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - if (null !== $propertyMetadata->isIdentifier()) { - return $propertyMetadata; - } - - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - if (!$manager instanceof DocumentManager) { - return $propertyMetadata; - } - - $doctrineClassMetadata = $manager->getClassMetadata($resourceClass); - $identifiers = $doctrineClassMetadata->getIdentifier(); - - foreach ($identifiers as $identifier) { - if ($identifier === $property) { - $propertyMetadata = $propertyMetadata->withIdentifier(true); - - if (null !== $propertyMetadata->isWritable()) { - break; - } - - $propertyMetadata = $propertyMetadata->withWritable(false); - - break; - } - } - - if (null === $propertyMetadata->isIdentifier()) { - $propertyMetadata = $propertyMetadata->withIdentifier(false); - } - - return $propertyMetadata; - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Paginator.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Paginator.php deleted file mode 100644 index b963af12c6f..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Paginator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm; - -class_exists(\ApiPlatform\Doctrine\Odm\Paginator::class); - -if (false) { - final class Paginator extends \ApiPlatform\Doctrine\Odm\Paginator - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyHelperTrait.php b/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyHelperTrait.php deleted file mode 100644 index b8d78a8e27d..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyHelperTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm; - -class_exists(\ApiPlatform\Doctrine\Odm\PropertyHelperTrait::class); - -if (false) { - trait PropertyHelperTrait - { - use \ApiPlatform\Doctrine\Odm\PropertyHelperTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractor.php b/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractor.php deleted file mode 100644 index f216aa2b1a8..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractor.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\PropertyInfo; - -class_exists(\ApiPlatform\Doctrine\Odm\PropertyInfo\DoctrineExtractor::class); - -if (false) { - final class DoctrineExtractor extends \ApiPlatform\Doctrine\Odm\PropertyInfo\DoctrineExtractor - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProvider.php b/src/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProvider.php deleted file mode 100644 index 1934400b210..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProvider.php +++ /dev/null @@ -1,213 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; - -/** - * Subresource data provider for the Doctrine MongoDB ODM. - * - * @experimental - * - * @author Antoine Bluchet - * @author Alan Poulain - */ -final class SubresourceDataProvider implements SubresourceDataProviderInterface -{ - use IdentifierManagerTrait; - - private $managerRegistry; - private $resourceMetadataFactory; - private $collectionExtensions; - private $itemExtensions; - - /** - * @param AggregationCollectionExtensionInterface[] $collectionExtensions - * @param AggregationItemExtensionInterface[] $itemExtensions - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - */ - public function __construct(ManagerRegistry $managerRegistry, $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $collectionExtensions = [], iterable $itemExtensions = []) - { - $this->managerRegistry = $managerRegistry; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->collectionExtensions = $collectionExtensions; - $this->itemExtensions = $itemExtensions; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - if (!$manager instanceof DocumentManager) { - throw new ResourceClassNotSupportedException(sprintf('The manager for "%s" must be an instance of "%s".', $resourceClass, DocumentManager::class)); - } - - $repository = $manager->getRepository($resourceClass); - /** @var ObjectRepository $repository */ - if (!$repository instanceof DocumentRepository) { - throw new RuntimeException(sprintf('The repository for "%s" must be an instance of "%s".', $resourceClass, DocumentRepository::class)); - } - - if (isset($context['identifiers'], $context['operation']) && !isset($context['property'])) { - $context['property'] = $context['operation']->getExtraProperties()['legacy_subresource_property'] ?? null; - $context['collection'] = $context['operation']->isCollection(); - } - - if (!isset($context['identifiers'], $context['property'])) { - throw new ResourceClassNotSupportedException('The given resource class is not a subresource.'); - } - - $attribute = []; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName); - $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; - } catch (OperationNotFoundException $e) { - $attribute = $resourceMetadata->getOperation()->getExtraProperties()['doctrine_mongodb'] ?? []; - } - } else { - /** @var ResourceMetadata */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $attribute = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'doctrine_mongodb', [], true); - } - - $executeOptions = $attribute['execute_options'] ?? []; - - $aggregationBuilder = $this->buildAggregation($identifiers, $context, $executeOptions, $repository->createAggregationBuilder(), \count($context['identifiers'])); - - if (true === $context['collection']) { - foreach ($this->collectionExtensions as $extension) { - $extension->applyToCollection($aggregationBuilder, $resourceClass, $operationName, $context); - if ($extension instanceof AggregationResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context); - } - } - } else { - foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($aggregationBuilder, $resourceClass, $identifiers, $operationName, $context); - if ($extension instanceof AggregationResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context); - } - } - } - - $iterator = $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions); - - return $context['collection'] ? $iterator->toArray() : ($iterator->current() ?: null); - } - - /** - * @throws RuntimeException - */ - private function buildAggregation(array $identifiers, array $context, array $executeOptions, Builder $previousAggregationBuilder, int $remainingIdentifiers, Builder $topAggregationBuilder = null): Builder - { - if ($remainingIdentifiers <= 0) { - return $previousAggregationBuilder; - } - - $topAggregationBuilder = $topAggregationBuilder ?? $previousAggregationBuilder; - - if (\is_string(key($context['identifiers']))) { - $contextIdentifiers = array_keys($context['identifiers']); - $identifier = $contextIdentifiers[$remainingIdentifiers - 1]; - $identifierResourceClass = $context['identifiers'][$identifier][0]; - $previousAssociationProperty = $contextIdentifiers[$remainingIdentifiers] ?? $context['property']; - } else { - @trigger_error('Identifiers should match the convention introduced in ADR 0001-resource-identifiers, this behavior will be removed in 3.0.', \E_USER_DEPRECATED); - [$identifier, $identifierResourceClass] = $context['identifiers'][$remainingIdentifiers - 1]; - $previousAssociationProperty = $context['identifiers'][$remainingIdentifiers][0] ?? $context['property']; - } - - $manager = $this->managerRegistry->getManagerForClass($identifierResourceClass); - if (!$manager instanceof DocumentManager) { - throw new RuntimeException(sprintf('The manager for "%s" must be an instance of "%s".', $identifierResourceClass, DocumentManager::class)); - } - - $classMetadata = $manager->getClassMetadata($identifierResourceClass); - - if (!$classMetadata instanceof ClassMetadata) { - throw new RuntimeException(sprintf('The class metadata for "%s" must be an instance of "%s".', $identifierResourceClass, ClassMetadata::class)); - } - - $aggregation = $manager->createAggregationBuilder($identifierResourceClass); - $normalizedIdentifiers = []; - - if (isset($identifiers[$identifier])) { - // if it's an array it's already normalized, the IdentifierManagerTrait is deprecated - if ($context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] ?? false) { - $normalizedIdentifiers = $identifiers[$identifier]; - } else { - $normalizedIdentifiers = $this->normalizeIdentifiers($identifiers[$identifier], $manager, $identifierResourceClass); - } - } - - if ($classMetadata->hasAssociation($previousAssociationProperty)) { - $aggregation->lookup($previousAssociationProperty)->alias($previousAssociationProperty); - foreach ($normalizedIdentifiers as $key => $value) { - $aggregation->match()->field($key)->equals($value); - } - } elseif ($classMetadata->isIdentifier($previousAssociationProperty)) { - foreach ($normalizedIdentifiers as $key => $value) { - $aggregation->match()->field($key)->equals($value); - } - - return $aggregation; - } - - // Recurse aggregations - $aggregation = $this->buildAggregation($identifiers, $context, $executeOptions, $aggregation, --$remainingIdentifiers, $topAggregationBuilder); - - $results = $aggregation->execute($executeOptions)->toArray(); - $in = array_reduce($results, static function ($in, $result) use ($previousAssociationProperty) { - return $in + array_map(static function ($result) { - return $result['_id']; - }, $result[$previousAssociationProperty] ?? []); - }, []); - $previousAggregationBuilder->match()->field('_id')->in($in); - - return $previousAggregationBuilder; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/AbstractPaginator.php b/src/Core/Bridge/Doctrine/Orm/AbstractPaginator.php deleted file mode 100644 index 28ceb260039..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/AbstractPaginator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm; - -class_exists(\ApiPlatform\Doctrine\Orm\AbstractPaginator::class); - -if (false) { - class AbstractPaginator extends \ApiPlatform\Doctrine\Orm\AbstractPaginator - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/CollectionDataProvider.php b/src/Core/Bridge/Doctrine/Orm/CollectionDataProvider.php deleted file mode 100644 index 380d104f50e..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/CollectionDataProvider.php +++ /dev/null @@ -1,78 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm; - -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; -use ApiPlatform\Exception\RuntimeException; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\ManagerRegistry; - -/** - * Collection data provider for the Doctrine ORM. - * - * @author Kévin Dunglas - * @author Samuel ROZE - * @final - */ -class CollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - private $managerRegistry; - private $collectionExtensions; - - /** - * @param QueryCollectionExtensionInterface[] $collectionExtensions - */ - public function __construct(ManagerRegistry $managerRegistry, iterable $collectionExtensions = []) - { - $this->managerRegistry = $managerRegistry; - $this->collectionExtensions = $collectionExtensions; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return $this->managerRegistry->getManagerForClass($resourceClass) instanceof EntityManagerInterface; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - /** @var EntityManagerInterface $manager */ - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - - $repository = $manager->getRepository($resourceClass); - if (!method_exists($repository, 'createQueryBuilder')) { - throw new RuntimeException('The repository class must have a "createQueryBuilder" method.'); - } - - $queryBuilder = $repository->createQueryBuilder('o'); - $queryNameGenerator = new QueryNameGenerator(); - foreach ($this->collectionExtensions as $extension) { - $extension->applyToCollection($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); - - if ($extension instanceof QueryResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context); - } - } - - return $queryBuilder->getQuery()->getResult(); - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php deleted file mode 100644 index fc71aa77885..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension::class); - -if (false) { - final class EagerLoadingExtension extends \ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php deleted file mode 100644 index 779e8186012..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension::class); - -if (false) { - final class FilterEagerLoadingExtension extends \ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/FilterExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/FilterExtension.php deleted file mode 100644 index 1f2effff3cb..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/FilterExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\FilterExtension::class); - -if (false) { - final class FilterExtension extends \ApiPlatform\Doctrine\Orm\Extension\FilterExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/OrderExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/OrderExtension.php deleted file mode 100644 index d1452c1421c..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/OrderExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\OrderExtension::class); - -if (false) { - final class OrderExtension extends \ApiPlatform\Doctrine\Orm\Extension\OrderExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/PaginationExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/PaginationExtension.php deleted file mode 100644 index 5e5f4e1d6fe..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/PaginationExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\PaginationExtension::class); - -if (false) { - final class PaginationExtension extends \ApiPlatform\Doctrine\Orm\Extension\PaginationExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/AbstractContextAwareFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/AbstractContextAwareFilter.php deleted file mode 100644 index de3227b34d4..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/AbstractContextAwareFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\AbstractContextAwareFilter::class); - -if (false) { - class AbstractContextAwareFilter extends \ApiPlatform\Doctrine\Orm\Filter\AbstractContextAwareFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/AbstractFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/AbstractFilter.php deleted file mode 100644 index e67cd6f7456..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/AbstractFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\AbstractFilter::class); - -if (false) { - class AbstractFilter extends \ApiPlatform\Doctrine\Orm\Filter\AbstractFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/BooleanFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/BooleanFilter.php deleted file mode 100644 index 043582d79b0..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/BooleanFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\BooleanFilter::class); - -if (false) { - class BooleanFilter extends \ApiPlatform\Doctrine\Orm\Filter\BooleanFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/DateFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/DateFilter.php deleted file mode 100644 index 5c2ebf78f2d..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/DateFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\DateFilter::class); - -if (false) { - class DateFilter extends \ApiPlatform\Doctrine\Orm\Filter\DateFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/ExistsFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/ExistsFilter.php deleted file mode 100644 index c9adf3d9a11..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/ExistsFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\ExistsFilter::class); - -if (false) { - class ExistsFilter extends \ApiPlatform\Doctrine\Orm\Filter\ExistsFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/NumericFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/NumericFilter.php deleted file mode 100644 index 2a66623c1c5..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/NumericFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\NumericFilter::class); - -if (false) { - class NumericFilter extends \ApiPlatform\Doctrine\Orm\Filter\NumericFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/OrderFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/OrderFilter.php deleted file mode 100644 index 5b3cf9af579..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/OrderFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\OrderFilter::class); - -if (false) { - class OrderFilter extends \ApiPlatform\Doctrine\Orm\Filter\OrderFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/RangeFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/RangeFilter.php deleted file mode 100644 index a696863c5d4..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/RangeFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\RangeFilter::class); - -if (false) { - class RangeFilter extends \ApiPlatform\Doctrine\Orm\Filter\RangeFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/SearchFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/SearchFilter.php deleted file mode 100644 index 21081029653..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/SearchFilter.php +++ /dev/null @@ -1,275 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Filter; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterInterface; -use ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterTrait; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryBuilderHelper; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Doctrine\Orm\Filter\AbstractContextAwareFilter; -use Doctrine\DBAL\Types\Types; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Filter the collection by given properties. - * - * @author Kévin Dunglas - */ -class SearchFilter extends AbstractContextAwareFilter implements SearchFilterInterface -{ - use SearchFilterTrait; - - public const DOCTRINE_INTEGER_TYPE = Types::INTEGER; - - public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $requestStack, IriConverterInterface $iriConverter, PropertyAccessorInterface $propertyAccessor = null, LoggerInterface $logger = null, array $properties = null, IdentifiersExtractorInterface $identifiersExtractor = null, NameConverterInterface $nameConverter = null) - { - parent::__construct($managerRegistry, $requestStack, $logger, $properties, $nameConverter); - - if (null === $identifiersExtractor) { - @trigger_error('Not injecting ItemIdentifiersExtractor is deprecated since API Platform 2.5 and can lead to unexpected behaviors, it will not be possible anymore in API Platform 3.0.', \E_USER_DEPRECATED); - } - - $this->iriConverter = $iriConverter; - $this->identifiersExtractor = $identifiersExtractor; - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - } - - protected function getIriConverter(): IriConverterInterface - { - return $this->iriConverter; - } - - protected function getPropertyAccessor(): PropertyAccessorInterface - { - return $this->propertyAccessor; - } - - /** - * {@inheritdoc} - */ - protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) - { - if ( - null === $value || - !$this->isPropertyEnabled($property, $resourceClass) || - !$this->isPropertyMapped($property, $resourceClass, true) - ) { - return; - } - - $alias = $queryBuilder->getRootAliases()[0]; - $field = $property; - - $values = $this->normalizeValues((array) $value, $property); - if (null === $values) { - return; - } - - $associations = []; - if ($this->isPropertyNested($property, $resourceClass)) { - [$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); - } - - $caseSensitive = true; - $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; - - // prefixing the strategy with i makes it case insensitive - if (0 === strpos($strategy, 'i')) { - $strategy = substr($strategy, 1); - $caseSensitive = false; - } - - $metadata = $this->getNestedMetadata($resourceClass, $associations); - - if ($metadata->hasField($field)) { - if ('id' === $field) { - $values = array_map([$this, 'getIdFromValue'], $values); - } - - if (!$this->hasValidValues($values, $this->getDoctrineFieldType($property, $resourceClass))) { - $this->logger->notice('Invalid filter ignored', [ - 'exception' => new InvalidArgumentException(sprintf('Values for field "%s" are not valid according to the doctrine type.', $field)), - ]); - - return; - } - - $this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $alias, $field, $values, $caseSensitive); - - return; - } - - // metadata doesn't have the field, nor an association on the field - if (!$metadata->hasAssociation($field)) { - return; - } - - $values = array_map([$this, 'getIdFromValue'], $values); - $associationFieldIdentifier = 'id'; - $doctrineTypeField = $this->getDoctrineFieldType($property, $resourceClass); - - if (null !== $this->identifiersExtractor) { - $associationResourceClass = $metadata->getAssociationTargetClass($field); - $associationFieldIdentifier = $this->identifiersExtractor->getIdentifiersFromResourceClass($associationResourceClass)[0]; - $doctrineTypeField = $this->getDoctrineFieldType($associationFieldIdentifier, $associationResourceClass); - } - - if (!$this->hasValidValues($values, $doctrineTypeField)) { - $this->logger->notice('Invalid filter ignored', [ - 'exception' => new InvalidArgumentException(sprintf('Values for field "%s" are not valid according to the doctrine type.', $field)), - ]); - - return; - } - - $associationAlias = $alias; - $associationField = $field; - if ($metadata->isCollectionValuedAssociation($associationField) || $metadata->isAssociationInverseSide($field)) { - $associationAlias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $alias, $associationField); - $associationField = $associationFieldIdentifier; - } - - $this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $associationAlias, $associationField, $values, $caseSensitive); - } - - /** - * Adds where clause according to the strategy. - * - * @param mixed $values - * - * @throws InvalidArgumentException If strategy does not exist - */ - protected function addWhereByStrategy(string $strategy, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, $values, bool $caseSensitive) - { - if (!\is_array($values)) { - $values = [$values]; - } - - $wrapCase = $this->createWrapCase($caseSensitive); - $valueParameter = ':'.$queryNameGenerator->generateParameterName($field); - $aliasedField = sprintf('%s.%s', $alias, $field); - - if (!$strategy || self::STRATEGY_EXACT === $strategy) { - if (1 === \count($values)) { - $queryBuilder - ->andWhere($queryBuilder->expr()->eq($wrapCase($aliasedField), $wrapCase($valueParameter))) - ->setParameter($valueParameter, $values[0]); - - return; - } - - $queryBuilder - ->andWhere($queryBuilder->expr()->in($wrapCase($aliasedField), $valueParameter)) - ->setParameter($valueParameter, $caseSensitive ? $values : array_map('strtolower', $values)); - - return; - } - - $ors = []; - $parameters = []; - foreach ($values as $key => $value) { - $keyValueParameter = sprintf('%s_%s', $valueParameter, $key); - $parameters[$caseSensitive ? $value : strtolower($value)] = $keyValueParameter; - - switch ($strategy) { - case self::STRATEGY_PARTIAL: - $ors[] = $queryBuilder->expr()->like( - $wrapCase($aliasedField), - $wrapCase((string) $queryBuilder->expr()->concat("'%'", $keyValueParameter, "'%'")) - ); - break; - case self::STRATEGY_START: - $ors[] = $queryBuilder->expr()->like( - $wrapCase($aliasedField), - $wrapCase((string) $queryBuilder->expr()->concat($keyValueParameter, "'%'")) - ); - break; - case self::STRATEGY_END: - $ors[] = $queryBuilder->expr()->like( - $wrapCase($aliasedField), - $wrapCase((string) $queryBuilder->expr()->concat("'%'", $keyValueParameter)) - ); - break; - case self::STRATEGY_WORD_START: - $ors[] = $queryBuilder->expr()->orX( - $queryBuilder->expr()->like($wrapCase($aliasedField), $wrapCase((string) $queryBuilder->expr()->concat($keyValueParameter, "'%'"))), - $queryBuilder->expr()->like($wrapCase($aliasedField), $wrapCase((string) $queryBuilder->expr()->concat("'% '", $keyValueParameter, "'%'"))) - ); - break; - default: - throw new InvalidArgumentException(sprintf('strategy %s does not exist.', $strategy)); - } - } - - $queryBuilder->andWhere($queryBuilder->expr()->orX(...$ors)); - array_walk($parameters, [$queryBuilder, 'setParameter']); - } - - /** - * Creates a function that will wrap a Doctrine expression according to the - * specified case sensitivity. - * - * For example, "o.name" will get wrapped into "LOWER(o.name)" when $caseSensitive - * is false. - */ - protected function createWrapCase(bool $caseSensitive): \Closure - { - return static function (string $expr) use ($caseSensitive): string { - if ($caseSensitive) { - return $expr; - } - - return sprintf('LOWER(%s)', $expr); - }; - } - - /** - * {@inheritdoc} - */ - protected function getType(string $doctrineType): string - { - switch ($doctrineType) { - case Types::ARRAY: - return 'array'; - case Types::BIGINT: - case Types::INTEGER: - case Types::SMALLINT: - return 'int'; - case Types::BOOLEAN: - return 'bool'; - case Types::DATE_MUTABLE: - case Types::TIME_MUTABLE: - case Types::DATETIME_MUTABLE: - case Types::DATETIMETZ_MUTABLE: - case Types::DATE_IMMUTABLE: - case Types::TIME_IMMUTABLE: - case Types::DATETIME_IMMUTABLE: - case Types::DATETIMETZ_IMMUTABLE: - return \DateTimeInterface::class; - case Types::FLOAT: - return 'float'; - } - - return 'string'; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/ItemDataProvider.php b/src/Core/Bridge/Doctrine/Orm/ItemDataProvider.php deleted file mode 100644 index dd91a1984fd..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/ItemDataProvider.php +++ /dev/null @@ -1,136 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\Mapping\ClassMetadata; - -/** - * Item data provider for the Doctrine ORM. - * - * @author Kévin Dunglas - * @author Samuel ROZE - * @final - */ -class ItemDataProvider implements DenormalizedIdentifiersAwareItemDataProviderInterface, RestrictedDataProviderInterface -{ - use IdentifierManagerTrait; - - private $managerRegistry; - private $itemExtensions; - - /** - * @param QueryItemExtensionInterface[] $itemExtensions - * @param ResourceMetadataCollectionFactoryInterface|null $resourceMetadataFactory - */ - public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $itemExtensions = [], $resourceMetadataFactory = null) - { - $this->managerRegistry = $managerRegistry; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->itemExtensions = $itemExtensions; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return $this->managerRegistry->getManagerForClass($resourceClass) instanceof EntityManagerInterface; - } - - /** - * {@inheritdoc} - * - * The context may contain a `fetch_data` key representing whether the value should be fetched by Doctrine or if we should return a reference. - * - * @throws RuntimeException - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - /** @var EntityManagerInterface $manager */ - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - - if ((\is_int($id) || \is_string($id)) && !($context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] ?? false)) { - $id = $this->normalizeIdentifiers($id, $manager, $resourceClass); - } - if (!\is_array($id)) { - throw new \InvalidArgumentException(sprintf('$id must be array when "%s" key is set to true in the $context', IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER)); - } - $identifiers = $id; - - $fetchData = $context['fetch_data'] ?? true; - if (!$fetchData) { - return $manager->getReference($resourceClass, $identifiers); - } - - $repository = $manager->getRepository($resourceClass); - if (!method_exists($repository, 'createQueryBuilder')) { - throw new RuntimeException('The repository class must have a "createQueryBuilder" method.'); - } - - $queryBuilder = $repository->createQueryBuilder('o'); - $queryNameGenerator = new QueryNameGenerator(); - $doctrineClassMetadata = $manager->getClassMetadata($resourceClass); - - $this->addWhereForIdentifiers($identifiers, $queryBuilder, $doctrineClassMetadata, $queryNameGenerator); - - foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($queryBuilder, $queryNameGenerator, $resourceClass, $identifiers, $operationName, $context); - - if ($extension instanceof QueryResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context); - } - } - - return $queryBuilder->getQuery()->getOneOrNullResult(); - } - - /** - * Add WHERE conditions to the query for one or more identifiers (simple or composite). - * - * @param mixed $queryNameGenerator - */ - private function addWhereForIdentifiers(array $identifiers, QueryBuilder $queryBuilder, ClassMetadata $classMetadata, $queryNameGenerator) - { - $alias = $queryBuilder->getRootAliases()[0]; - foreach ($identifiers as $identifier => $value) { - $placeholder = $queryNameGenerator->generateParameterName($identifier); - $expression = $queryBuilder->expr()->eq( - "{$alias}.{$identifier}", - ':'.$placeholder - ); - - $queryBuilder->andWhere($expression); - $queryBuilder->setParameter($placeholder, $value, $classMetadata->getTypeOfField($identifier)); - } - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php b/src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php deleted file mode 100644 index 986c86ecf8e..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php +++ /dev/null @@ -1,87 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Metadata\Property; - -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\Persistence\ManagerRegistry; - -/** - * Use Doctrine metadata to populate the identifier property. - * - * @author Kévin Dunglas - */ -final class DoctrineOrmPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $decorated; - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry, PropertyMetadataFactoryInterface $decorated) - { - $this->managerRegistry = $managerRegistry; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - if (null !== $propertyMetadata->isIdentifier()) { - return $propertyMetadata; - } - - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - if (!$manager) { - return $propertyMetadata; - } - $doctrineClassMetadata = $manager->getClassMetadata($resourceClass); - - $identifiers = $doctrineClassMetadata->getIdentifier(); - foreach ($identifiers as $identifier) { - if ($identifier === $property) { - $propertyMetadata = $propertyMetadata->withIdentifier(true); - - if (null !== $propertyMetadata->isWritable()) { - break; - } - - if ($doctrineClassMetadata instanceof ClassMetadataInfo) { - $writable = $doctrineClassMetadata->isIdentifierNatural(); - } else { - $writable = false; - } - - $propertyMetadata = $propertyMetadata->withWritable($writable); - - break; - } - } - - if (null === $propertyMetadata->isIdentifier()) { - $propertyMetadata = $propertyMetadata->withIdentifier(false); - } - - if ($doctrineClassMetadata instanceof ClassMetadataInfo && \in_array($property, $doctrineClassMetadata->getFieldNames(), true)) { - /** @var mixed[] */ - $fieldMapping = $doctrineClassMetadata->getFieldMapping($property); - $propertyMetadata = $propertyMetadata->withDefault($fieldMapping['options']['default'] ?? $propertyMetadata->getDefault()); - } - - return $propertyMetadata; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Paginator.php b/src/Core/Bridge/Doctrine/Orm/Paginator.php deleted file mode 100644 index 2777ef9c1ee..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Paginator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm; - -class_exists(\ApiPlatform\Doctrine\Orm\Paginator::class); - -if (false) { - final class Paginator extends \ApiPlatform\Doctrine\Orm\Paginator - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/PropertyHelperTrait.php b/src/Core/Bridge/Doctrine/Orm/PropertyHelperTrait.php deleted file mode 100644 index e33a8b10e5c..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/PropertyHelperTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm; - -class_exists(\ApiPlatform\Doctrine\Orm\PropertyHelperTrait::class); - -if (false) { - trait PropertyHelperTrait - { - use \ApiPlatform\Doctrine\Orm\PropertyHelperTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/SubresourceDataProvider.php b/src/Core/Bridge/Doctrine/Orm/SubresourceDataProvider.php deleted file mode 100644 index 2d2a9d8c209..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/SubresourceDataProvider.php +++ /dev/null @@ -1,240 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension; -use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Exception\RuntimeException; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; - -/** - * Subresource data provider for the Doctrine ORM. - * - * @author Antoine Bluchet - */ -final class SubresourceDataProvider implements SubresourceDataProviderInterface -{ - use IdentifierManagerTrait; - - private $managerRegistry; - private $collectionExtensions; - private $itemExtensions; - - /** - * @param QueryCollectionExtensionInterface[] $collectionExtensions - * @param QueryItemExtensionInterface[] $itemExtensions - */ - public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $collectionExtensions = [], iterable $itemExtensions = []) - { - $this->managerRegistry = $managerRegistry; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->collectionExtensions = $collectionExtensions; - $this->itemExtensions = $itemExtensions; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - if (null === $manager) { - throw new ResourceClassNotSupportedException(sprintf('The object manager associated with the "%s" resource class cannot be retrieved.', $resourceClass)); - } - - $repository = $manager->getRepository($resourceClass); - if (!method_exists($repository, 'createQueryBuilder')) { - throw new RuntimeException('The repository class must have a "createQueryBuilder" method.'); - } - - if (!isset($context['identifiers'], $context['property'])) { - throw new ResourceClassNotSupportedException('The given resource class is not a subresource.'); - } - - $queryNameGenerator = new QueryNameGenerator(); - - /* - * The following recursively translates to this pseudo-dql: - * - * SELECT thirdLevel WHERE thirdLevel IN ( - * SELECT thirdLevel FROM relatedDummies WHERE relatedDummies = ? AND relatedDummies IN ( - * SELECT relatedDummies FROM Dummy WHERE Dummy = ? - * ) - * ) - * - * By using subqueries, we're forcing the SQL execution plan to go through indexes on doctrine identifiers. - */ - $queryBuilder = $this->buildQuery($identifiers, $context, $queryNameGenerator, $repository->createQueryBuilder($alias = 'o'), $alias, \count($context['identifiers'])); - - if (true === $context['collection']) { - foreach ($this->collectionExtensions as $extension) { - // We don't need this anymore because we already made sub queries to ensure correct results - if ($extension instanceof FilterEagerLoadingExtension) { - continue; - } - - $extension->applyToCollection($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); - if ($extension instanceof QueryResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context); - } - } - } else { - foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($queryBuilder, $queryNameGenerator, $resourceClass, $identifiers, $operationName, $context); - if ($extension instanceof QueryResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context); - } - } - } - - $query = $queryBuilder->getQuery(); - - return $context['collection'] ? $query->getResult() : $query->getOneOrNullResult(); - } - - /** - * @throws RuntimeException - */ - private function buildQuery(array $identifiers, array $context, QueryNameGenerator $queryNameGenerator, QueryBuilder $previousQueryBuilder, string $previousAlias, int $remainingIdentifiers, QueryBuilder $topQueryBuilder = null): QueryBuilder - { - if ($remainingIdentifiers <= 0) { - return $previousQueryBuilder; - } - - $topQueryBuilder = $topQueryBuilder ?? $previousQueryBuilder; - - if (\is_string(key($context['identifiers']))) { - $contextIdentifiers = array_keys($context['identifiers']); - $identifier = $contextIdentifiers[$remainingIdentifiers - 1]; - $identifierResourceClass = $context['identifiers'][$identifier][0]; - $previousAssociationProperty = $contextIdentifiers[$remainingIdentifiers] ?? $context['property']; - } else { - @trigger_error('Identifiers should match the convention introduced in ADR 0001-resource-identifiers, this behavior will be removed in 3.0.', \E_USER_DEPRECATED); - [$identifier, $identifierResourceClass] = $context['identifiers'][$remainingIdentifiers - 1]; - $previousAssociationProperty = $context['identifiers'][$remainingIdentifiers][0] ?? $context['property']; - } - - $manager = $this->managerRegistry->getManagerForClass($identifierResourceClass); - - if (!$manager instanceof EntityManagerInterface) { - throw new RuntimeException("The manager for $identifierResourceClass must be an EntityManager."); - } - - $classMetadata = $manager->getClassMetadata($identifierResourceClass); - - if (!$classMetadata instanceof ClassMetadataInfo) { - throw new RuntimeException("The class metadata for $identifierResourceClass must be an instance of ClassMetadataInfo."); - } - - $qb = $manager->createQueryBuilder(); - $alias = $queryNameGenerator->generateJoinAlias($identifier); - $normalizedIdentifiers = []; - - if (isset($identifiers[$identifier])) { - // if it's an array it's already normalized, the IdentifierManagerTrait is deprecated - if ($context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] ?? false) { - $normalizedIdentifiers = $identifiers[$identifier]; - } else { - $normalizedIdentifiers = $this->normalizeIdentifiers($identifiers[$identifier], $manager, $identifierResourceClass); - } - } - - if ($classMetadata->hasAssociation($previousAssociationProperty)) { - $relationType = $classMetadata->getAssociationMapping($previousAssociationProperty)['type']; - switch ($relationType) { - // MANY_TO_MANY relations need an explicit join so that the identifier part can be retrieved - case ClassMetadataInfo::MANY_TO_MANY: - $joinAlias = $queryNameGenerator->generateJoinAlias($previousAssociationProperty); - - $qb->select($joinAlias) - ->from($identifierResourceClass, $alias) - ->innerJoin("$alias.$previousAssociationProperty", $joinAlias); - break; - case ClassMetadataInfo::ONE_TO_MANY: - $mappedBy = $classMetadata->getAssociationMapping($previousAssociationProperty)['mappedBy']; - $previousAlias = "$previousAlias.$mappedBy"; - - $qb->select($alias) - ->from($identifierResourceClass, $alias); - break; - case ClassMetadataInfo::ONE_TO_ONE: - $association = $classMetadata->getAssociationMapping($previousAssociationProperty); - if (!isset($association['mappedBy'])) { - $qb->select("IDENTITY($alias.$previousAssociationProperty)") - ->from($identifierResourceClass, $alias); - break; - } - $mappedBy = $association['mappedBy']; - $previousAlias = "$previousAlias.$mappedBy"; - - $qb->select($alias) - ->from($identifierResourceClass, $alias); - break; - default: - $qb->select("IDENTITY($alias.$previousAssociationProperty)") - ->from($identifierResourceClass, $alias); - } - } elseif ($classMetadata->isIdentifier($previousAssociationProperty)) { - $qb->select($alias) - ->from($identifierResourceClass, $alias); - } - - $isLeaf = 1 === $remainingIdentifiers; - - // Add where clause for identifiers - foreach ($normalizedIdentifiers as $key => $value) { - $placeholder = $queryNameGenerator->generateParameterName($key); - $topQueryBuilder->setParameter($placeholder, $value, (string) $classMetadata->getTypeOfField($key)); - - // Optimization: add where clause for identifiers, but not via a WHERE ... IN ( ...subquery... ). - // Instead we use a direct identifier equality clause, to speed things up when dealing with large tables. - // We may do so if there is no more recursion levels from here, and if relation allows it. - $association = $classMetadata->hasAssociation($previousAssociationProperty) ? $classMetadata->getAssociationMapping($previousAssociationProperty) : []; - $oneToOneBidirectional = isset($association['inversedBy']) && ClassMetadataInfo::ONE_TO_ONE === $association['type']; - $oneToManyBidirectional = isset($association['mappedBy']) && ClassMetadataInfo::ONE_TO_MANY === $association['type']; - if ($isLeaf && $oneToOneBidirectional) { - $joinAlias = $queryNameGenerator->generateJoinAlias($association['inversedBy']); - - return $previousQueryBuilder->innerJoin("$previousAlias.{$association['inversedBy']}", $joinAlias) - ->andWhere("$joinAlias.$key = :$placeholder"); - } - if ($isLeaf && $oneToManyBidirectional && \in_array($key, $classMetadata->getIdentifier(), true)) { - return $previousQueryBuilder->andWhere("IDENTITY($previousAlias) = :$placeholder"); - } - - $qb->andWhere("$alias.$key = :$placeholder"); - } - - // Recurse queries - $qb = $this->buildQuery($identifiers, $context, $queryNameGenerator, $qb, $alias, --$remainingIdentifiers, $topQueryBuilder); - - return $previousQueryBuilder->andWhere($qb->expr()->in($previousAlias, $qb->getDQL())); - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/EagerLoadingTrait.php b/src/Core/Bridge/Doctrine/Orm/Util/EagerLoadingTrait.php deleted file mode 100644 index 38b07cc1006..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/EagerLoadingTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait::class); - -if (false) { - trait EagerLoadingTrait - { - use \ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/QueryBuilderHelper.php b/src/Core/Bridge/Doctrine/Orm/Util/QueryBuilderHelper.php deleted file mode 100644 index 5f244f5398c..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/QueryBuilderHelper.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper::class); - -if (false) { - final class QueryBuilderHelper extends \ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php b/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php deleted file mode 100644 index dc257831403..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\QueryChecker::class); - -if (false) { - final class QueryChecker extends \ApiPlatform\Doctrine\Orm\Util\QueryChecker - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/QueryJoinParser.php b/src/Core/Bridge/Doctrine/Orm/Util/QueryJoinParser.php deleted file mode 100644 index 923aeaad669..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/QueryJoinParser.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\QueryJoinParser::class); - -if (false) { - final class QueryJoinParser extends \ApiPlatform\Doctrine\Orm\Util\QueryJoinParser - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/QueryNameGenerator.php b/src/Core/Bridge/Doctrine/Orm/Util/QueryNameGenerator.php deleted file mode 100644 index 9939dc4f7cb..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/QueryNameGenerator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator::class); - -if (false) { - final class QueryNameGenerator extends \ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractor.php b/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractor.php deleted file mode 100644 index 137709bd584..00000000000 --- a/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractor.php +++ /dev/null @@ -1,52 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Api; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; - -/** - * {@inheritdoc} - * - * @experimental - * - * @author Baptiste Meyer - */ -final class IdentifierExtractor implements IdentifierExtractorInterface -{ - private $identifiersExtractor; - - public function __construct(IdentifiersExtractorInterface $identifiersExtractor) - { - $this->identifiersExtractor = $identifiersExtractor; - } - - /** - * {@inheritdoc} - */ - public function getIdentifierFromResourceClass(string $resourceClass): string - { - $identifiers = $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass); - - if (0 >= $totalIdentifiers = \count($identifiers)) { - throw new NonUniqueIdentifierException(sprintf('Resource "%s" has no identifiers.', $resourceClass)); - } - - if (1 < $totalIdentifiers) { - throw new NonUniqueIdentifierException('Composite identifiers not supported.'); - } - - return reset($identifiers); - } -} diff --git a/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractorInterface.php b/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractorInterface.php deleted file mode 100644 index da0dd931fb9..00000000000 --- a/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractorInterface.php +++ /dev/null @@ -1,33 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Api; - -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; - -/** - * Extracts identifier for a given resource. - * - * @experimental - * - * @author Baptiste Meyer - */ -interface IdentifierExtractorInterface -{ - /** - * Finds identifier from a resource class. - * - * @throws NonUniqueIdentifierException - */ - public function getIdentifierFromResourceClass(string $resourceClass): string; -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProvider.php b/src/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProvider.php deleted file mode 100644 index 669eae33a7c..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProvider.php +++ /dev/null @@ -1,152 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider; - -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\Pagination as LegacyPagination; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; -use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Util\ElasticsearchVersion; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\State\Pagination\Pagination; -use Elasticsearch\Client; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Collection data provider for Elasticsearch. - * - * @experimental - * - * @author Baptiste Meyer - */ -final class CollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - private $client; - private $documentMetadataFactory; - private $identifierExtractor; - private $denormalizer; - private $pagination; - private $resourceMetadataFactory; - - /** - * @param RequestBodySearchCollectionExtensionInterface[] $collectionExtensions - * @param ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory - * @param Pagination|LegacyPagination $pagination - */ - public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, IdentifierExtractorInterface $identifierExtractor = null, DenormalizerInterface $denormalizer, $pagination, $resourceMetadataFactory, iterable $collectionExtensions = []) - { - $this->client = $client; - $this->documentMetadataFactory = $documentMetadataFactory; - - if ($this->identifierExtractor) { - trigger_deprecation('api-platform', '2.7', sprintf('Passing an instance of "%s" is deprecated and will not be supported in 3.0.', IdentifierExtractorInterface::class)); - } - - $this->identifierExtractor = $identifierExtractor; - $this->denormalizer = $denormalizer; - $this->pagination = $pagination; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->collectionExtensions = $collectionExtensions; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, ?string $operationName = null, array $context = []): bool - { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (false === $resourceMetadata->getCollectionOperationAttribute($operationName, 'elasticsearch', true, true)) { - return false; - } - } catch (ResourceClassNotFoundException $e) { - return false; - } - - try { - $this->documentMetadataFactory->create($resourceClass); - } catch (IndexNotFoundException $e) { - return false; - } - - if ($this->identifierExtractor) { - try { - $this->identifierExtractor->getIdentifierFromResourceClass($resourceClass); - } catch (NonUniqueIdentifierException $e) { - return false; - } - } else { - $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation($operationName); - - if (\count($operation->getIdentifiers()) > 1) { - return false; - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, ?string $operationName = null, array $context = []): iterable - { - $documentMetadata = $this->documentMetadataFactory->create($resourceClass); - $body = []; - - foreach ($this->collectionExtensions as $collectionExtension) { - $body = $collectionExtension->applyToCollection($body, $resourceClass, $operationName, $context); - } - - if (!isset($body['query']) && !isset($body['aggs'])) { - $body['query'] = ['match_all' => new \stdClass()]; - } - - $limit = $body['size'] = $body['size'] ?? $this->pagination->getLimit($resourceClass, $operationName, $context); - $offset = $body['from'] = $body['from'] ?? $this->pagination->getOffset($resourceClass, $operationName, $context); - - $params = [ - 'index' => $documentMetadata->getIndex(), - 'body' => $body, - ]; - - if (ElasticsearchVersion::supportsMappingType()) { - $params['type'] = $documentMetadata->getType(); - } - - $documents = $this->client->search($params); - - return new Paginator( - $this->denormalizer, - $documents, - $resourceClass, - $limit, - $offset, - $context - ); - } - - private $collectionExtensions; -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/AbstractFilterExtension.php b/src/Core/Bridge/Elasticsearch/DataProvider/Extension/AbstractFilterExtension.php deleted file mode 100644 index 4db73e50a48..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/AbstractFilterExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension; - -class_exists(\ApiPlatform\Elasticsearch\Extension\AbstractFilterExtension::class); - -if (false) { - class AbstractFilterExtension extends \ApiPlatform\Elasticsearch\Extension\AbstractFilterExtension - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtension.php b/src/Core/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtension.php deleted file mode 100644 index 34c17757c37..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension; - -class_exists(\ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension::class); - -if (false) { - final class ConstantScoreFilterExtension extends \ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortExtension.php b/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortExtension.php deleted file mode 100644 index efaac85fe8f..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension; - -class_exists(\ApiPlatform\Elasticsearch\Extension\SortExtension::class); - -if (false) { - final class SortExtension extends \ApiPlatform\Elasticsearch\Extension\SortExtension - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtension.php b/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtension.php deleted file mode 100644 index 41d41d46eee..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension; - -class_exists(\ApiPlatform\Elasticsearch\Extension\SortFilterExtension::class); - -if (false) { - final class SortFilterExtension extends \ApiPlatform\Elasticsearch\Extension\SortFilterExtension - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractFilter.php deleted file mode 100644 index 4be367ca6e0..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractFilter.php +++ /dev/null @@ -1,145 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter; - -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Util\FieldDatatypeTrait; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Exception\ResourceClassNotFoundException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Abstract class with helpers for easing the implementation of a filter. - * - * @experimental - * - * @author Baptiste Meyer - */ -abstract class AbstractFilter implements FilterInterface -{ - use FieldDatatypeTrait { getNestedFieldPath as protected; } - - protected $properties; - protected $propertyNameCollectionFactory; - protected $nameConverter; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, ?array $properties = null) - { - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->resourceClassResolver = $resourceClassResolver; - $this->nameConverter = $nameConverter; - $this->properties = $properties; - } - - /** - * Gets all enabled properties for the given resource class. - */ - protected function getProperties(string $resourceClass): \Traversable - { - if (null !== $this->properties) { - return yield from array_keys($this->properties); - } - - try { - yield from $this->propertyNameCollectionFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - } - } - - /** - * Is the given property enabled? - */ - protected function hasProperty(string $resourceClass, string $property): bool - { - return \in_array($property, iterator_to_array($this->getProperties($resourceClass)), true); - } - - /** - * Gets info about the decomposed given property for the given resource class. - * - * Returns an array with the following info as values: - * - the {@see Type} of the decomposed given property - * - is the decomposed given property an association? - * - the resource class of the decomposed given property - * - the property name of the decomposed given property - */ - protected function getMetadata(string $resourceClass, string $property): array - { - $noop = [null, null, null, null]; - - if (!$this->hasProperty($resourceClass, $property)) { - return $noop; - } - - $properties = explode('.', $property); - $totalProperties = \count($properties); - $currentResourceClass = $resourceClass; - $hasAssociation = false; - $currentProperty = null; - $type = null; - - foreach ($properties as $index => $currentProperty) { - try { - $propertyMetadata = $this->propertyMetadataFactory->create($currentResourceClass, $currentProperty); - } catch (PropertyNotFoundException $e) { - return $noop; - } - - if (null === $type = $propertyMetadata->getType()) { - return $noop; - } - - ++$index; - $builtinType = $type->getBuiltinType(); - - if (Type::BUILTIN_TYPE_OBJECT !== $builtinType && Type::BUILTIN_TYPE_ARRAY !== $builtinType) { - if ($totalProperties === $index) { - break; - } - - return $noop; - } - - if ($type->isCollection() && null === $type = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType()) { - return $noop; - } - - if (Type::BUILTIN_TYPE_ARRAY === $builtinType && Type::BUILTIN_TYPE_OBJECT !== $type->getBuiltinType()) { - if ($totalProperties === $index) { - break; - } - - return $noop; - } - - if (null === $className = $type->getClassName()) { - return $noop; - } - - if ($isResourceClass = $this->resourceClassResolver->isResourceClass($className)) { - $currentResourceClass = $className; - } elseif ($totalProperties !== $index) { - return $noop; - } - - $hasAssociation = $totalProperties === $index && $isResourceClass; - } - - return [$type, $hasAssociation, $currentResourceClass, $currentProperty]; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractSearchFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractSearchFilter.php deleted file mode 100644 index 6596dd6eeba..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractSearchFilter.php +++ /dev/null @@ -1,187 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Abstract class with helpers for easing the implementation of a search filter like a term filter or a match filter. - * - * @experimental - * - * @internal - * - * @author Baptiste Meyer - */ -abstract class AbstractSearchFilter extends AbstractFilter implements ConstantScoreFilterInterface -{ - protected $identifierExtractor; - protected $iriConverter; - protected $propertyAccessor; - - /** - * {@inheritdoc} - */ - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, IdentifierExtractorInterface $identifierExtractor, IriConverterInterface $iriConverter, PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter = null, ?array $properties = null) - { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceClassResolver, $nameConverter, $properties); - - $this->identifierExtractor = $identifierExtractor; - $this->iriConverter = $iriConverter; - $this->propertyAccessor = $propertyAccessor; - } - - /** - * {@inheritdoc} - */ - public function apply(array $clauseBody, string $resourceClass, ?string $operationName = null, array $context = []): array - { - $searches = []; - - foreach ($context['filters'] ?? [] as $property => $values) { - [$type, $hasAssociation, $nestedResourceClass, $nestedProperty] = $this->getMetadata($resourceClass, $property); - - if (!$type || !$values = (array) $values) { - continue; - } - - if ($hasAssociation || $this->isIdentifier($nestedResourceClass, $nestedProperty)) { - $values = array_map([$this, 'getIdentifierValue'], $values, array_fill(0, \count($values), $nestedProperty)); - } - - if (!$this->hasValidValues($values, $type)) { - continue; - } - - $property = null === $this->nameConverter ? $property : $this->nameConverter->normalize($property, $resourceClass, null, $context); - $nestedPath = $this->getNestedFieldPath($resourceClass, $property); - $nestedPath = null === $nestedPath || null === $this->nameConverter ? $nestedPath : $this->nameConverter->normalize($nestedPath, $resourceClass, null, $context); - - $searches[] = $this->getQuery($property, $values, $nestedPath); - } - - if (!$searches) { - return $clauseBody; - } - - return array_merge_recursive($clauseBody, [ - 'bool' => [ - 'must' => $searches, - ], - ]); - } - - /** - * {@inheritdoc} - */ - public function getDescription(string $resourceClass): array - { - $description = []; - - foreach ($this->getProperties($resourceClass) as $property) { - [$type, $hasAssociation] = $this->getMetadata($resourceClass, $property); - - if (!$type) { - continue; - } - - foreach ([$property, "${property}[]"] as $filterParameterName) { - $description[$filterParameterName] = [ - 'property' => $property, - 'type' => $hasAssociation ? 'string' : $this->getPhpType($type), - 'required' => false, - ]; - } - } - - return $description; - } - - /** - * Gets the Elasticsearch query corresponding to the current search filter. - */ - abstract protected function getQuery(string $property, array $values, ?string $nestedPath): array; - - /** - * Converts the given {@see Type} in PHP type. - */ - protected function getPhpType(Type $type): string - { - switch ($builtinType = $type->getBuiltinType()) { - case Type::BUILTIN_TYPE_ARRAY: - case Type::BUILTIN_TYPE_INT: - case Type::BUILTIN_TYPE_FLOAT: - case Type::BUILTIN_TYPE_BOOL: - case Type::BUILTIN_TYPE_STRING: - return $builtinType; - case Type::BUILTIN_TYPE_OBJECT: - if (null !== ($className = $type->getClassName()) && is_a($className, \DateTimeInterface::class, true)) { - return \DateTimeInterface::class; - } - - // no break - default: - return 'string'; - } - } - - /** - * Is the given property of the given resource class an identifier? - */ - protected function isIdentifier(string $resourceClass, string $property): bool - { - return $property === $this->identifierExtractor->getIdentifierFromResourceClass($resourceClass); - } - - /** - * Gets the ID from an IRI or a raw ID. - */ - protected function getIdentifierValue(string $iri, string $property) - { - try { - if ($item = $this->iriConverter->getItemFromIri($iri, ['fetch_data' => false])) { - return $this->propertyAccessor->getValue($item, $property); - } - } catch (InvalidArgumentException $e) { - } - - return $iri; - } - - /** - * Are the given values valid according to the given {@see Type}? - */ - protected function hasValidValues(array $values, Type $type): bool - { - foreach ($values as $value) { - if ( - null !== $value - && Type::BUILTIN_TYPE_INT === $type->getBuiltinType() - && false === filter_var($value, \FILTER_VALIDATE_INT) - ) { - return false; - } - } - - return true; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/MatchFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/MatchFilter.php deleted file mode 100644 index c3d9f9a82d1..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/MatchFilter.php +++ /dev/null @@ -1,46 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter; - -/** - * Filter the collection by given properties using a full text query. - * - * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html - * - * @experimental - * - * @author Baptiste Meyer - */ -final class MatchFilter extends AbstractSearchFilter -{ - /** - * {@inheritdoc} - */ - protected function getQuery(string $property, array $values, ?string $nestedPath): array - { - $matches = []; - - foreach ($values as $value) { - $matches[] = ['match' => [$property => $value]]; - } - - $matchQuery = isset($matches[1]) ? ['bool' => ['should' => $matches]] : $matches[0]; - - if (null !== $nestedPath) { - $matchQuery = ['nested' => ['path' => $nestedPath, 'query' => $matchQuery]]; - } - - return $matchQuery; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/OrderFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/OrderFilter.php deleted file mode 100644 index a1c78f3f06d..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/OrderFilter.php +++ /dev/null @@ -1,111 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter; - -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Order the collection by given properties. - * - * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html - * - * @experimental - * - * @author Baptiste Meyer - */ -final class OrderFilter extends AbstractFilter implements SortFilterInterface -{ - private $orderParameterName; - - /** - * {@inheritdoc} - */ - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, string $orderParameterName = 'order', ?array $properties = null) - { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceClassResolver, $nameConverter, $properties); - - $this->orderParameterName = $orderParameterName; - } - - /** - * {@inheritdoc} - */ - public function apply(array $clauseBody, string $resourceClass, ?string $operationName = null, array $context = []): array - { - if (!\is_array($properties = $context['filters'][$this->orderParameterName] ?? [])) { - return $clauseBody; - } - - $orders = []; - - foreach ($properties as $property => $direction) { - [$type] = $this->getMetadata($resourceClass, $property); - - if (!$type) { - continue; - } - - if (empty($direction) && null !== $defaultDirection = $this->properties[$property] ?? null) { - $direction = $defaultDirection; - } - - if (!\in_array($direction = strtolower($direction), ['asc', 'desc'], true)) { - continue; - } - - $order = ['order' => $direction]; - - if (null !== $nestedPath = $this->getNestedFieldPath($resourceClass, $property)) { - $nestedPath = null === $this->nameConverter ? $nestedPath : $this->nameConverter->normalize($nestedPath, $resourceClass, null, $context); - $order['nested'] = ['path' => $nestedPath]; - } - - $property = null === $this->nameConverter ? $property : $this->nameConverter->normalize($property, $resourceClass, null, $context); - $orders[] = [$property => $order]; - } - - if (!$orders) { - return $clauseBody; - } - - return array_merge_recursive($clauseBody, $orders); - } - - /** - * {@inheritdoc} - */ - public function getDescription(string $resourceClass): array - { - $description = []; - - foreach ($this->getProperties($resourceClass) as $property) { - [$type] = $this->getMetadata($resourceClass, $property); - - if (!$type) { - continue; - } - - $description["$this->orderParameterName[$property]"] = [ - 'property' => $property, - 'type' => 'string', - 'required' => false, - ]; - } - - return $description; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/TermFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/TermFilter.php deleted file mode 100644 index 3afc8e357dd..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/TermFilter.php +++ /dev/null @@ -1,45 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter; - -/** - * Filter the collection by given properties using a term level query. - * - * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html - * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html - * - * @experimental - * - * @author Baptiste Meyer - */ -final class TermFilter extends AbstractSearchFilter -{ - /** - * {@inheritdoc} - */ - protected function getQuery(string $property, array $values, ?string $nestedPath): array - { - if (1 === \count($values)) { - $termQuery = ['term' => [$property => reset($values)]]; - } else { - $termQuery = ['terms' => [$property => $values]]; - } - - if (null !== $nestedPath) { - $termQuery = ['nested' => ['path' => $nestedPath, 'query' => $termQuery]]; - } - - return $termQuery; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/ItemDataProvider.php b/src/Core/Bridge/Elasticsearch/DataProvider/ItemDataProvider.php deleted file mode 100644 index 1a47a480720..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/ItemDataProvider.php +++ /dev/null @@ -1,117 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider; - -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; -use ApiPlatform\Elasticsearch\Util\ElasticsearchVersion; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use Elasticsearch\Client; -use Elasticsearch\Common\Exceptions\Missing404Exception; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Item data provider for Elasticsearch. - * - * @experimental - * - * @author Baptiste Meyer - */ -final class ItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - private $client; - private $documentMetadataFactory; - private $identifierExtractor; - private $denormalizer; - private $resourceMetadataFactory; - - public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, IdentifierExtractorInterface $identifierExtractor, DenormalizerInterface $denormalizer, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - $this->client = $client; - $this->documentMetadataFactory = $documentMetadataFactory; - $this->identifierExtractor = $identifierExtractor; - $this->denormalizer = $denormalizer; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, ?string $operationName = null, array $context = []): bool - { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (false === $resourceMetadata->getItemOperationAttribute($operationName, 'elasticsearch', true, true)) { - return false; - } - } catch (ResourceClassNotFoundException $e) { - return false; - } - - try { - $this->documentMetadataFactory->create($resourceClass); - } catch (IndexNotFoundException $e) { - return false; - } - - try { - $this->identifierExtractor->getIdentifierFromResourceClass($resourceClass); - } catch (NonUniqueIdentifierException $e) { - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, ?string $operationName = null, array $context = []) - { - if (\is_array($id)) { - $id = $id[$this->identifierExtractor->getIdentifierFromResourceClass($resourceClass)]; - } - - $documentMetadata = $this->documentMetadataFactory->create($resourceClass); - - try { - $params = [ - 'index' => $documentMetadata->getIndex(), - 'id' => (string) $id, - ]; - - if (ElasticsearchVersion::supportsMappingType()) { - $params['type'] = $documentMetadata->getType(); - } - - $document = $this->client->get($params); - } catch (Missing404Exception $e) { - return null; - } - - $item = $this->denormalizer->denormalize($document, $resourceClass, DocumentNormalizer::FORMAT, [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => true]); - if (!\is_object($item) && null !== $item) { - throw new \UnexpectedValueException('Expected item to be an object or null.'); - } - - return $item; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Paginator.php b/src/Core/Bridge/Elasticsearch/DataProvider/Paginator.php deleted file mode 100644 index 4e0fb589221..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Paginator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider; - -class_exists(\ApiPlatform\Elasticsearch\Paginator::class); - -if (false) { - final class Paginator extends \ApiPlatform\Elasticsearch\Paginator - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Exception/IndexNotFoundException.php b/src/Core/Bridge/Elasticsearch/Exception/IndexNotFoundException.php deleted file mode 100644 index e0763c4c81a..00000000000 --- a/src/Core/Bridge/Elasticsearch/Exception/IndexNotFoundException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Exception; - -class_exists(\ApiPlatform\Elasticsearch\Exception\IndexNotFoundException::class); - -if (false) { - final class IndexNotFoundException extends \ApiPlatform\Elasticsearch\Exception\IndexNotFoundException - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Exception/NonUniqueIdentifierException.php b/src/Core/Bridge/Elasticsearch/Exception/NonUniqueIdentifierException.php deleted file mode 100644 index 9ea219a8237..00000000000 --- a/src/Core/Bridge/Elasticsearch/Exception/NonUniqueIdentifierException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Exception; - -class_exists(\ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException::class); - -if (false) { - final class NonUniqueIdentifierException extends \ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/DocumentMetadata.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/DocumentMetadata.php deleted file mode 100644 index ec74aea8ca2..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/DocumentMetadata.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata::class); - -if (false) { - final class DocumentMetadata extends \ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php deleted file mode 100644 index 57e6ab8689c..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory::class); - -if (false) { - final class AttributeDocumentMetadataFactory extends \ApiPlatform\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php deleted file mode 100644 index 904c2b63bc8..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory::class); - -if (false) { - final class CachedDocumentMetadataFactory extends \ApiPlatform\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php deleted file mode 100644 index 09c9e6500aa..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory::class); - -if (false) { - final class CatDocumentMetadataFactory extends \ApiPlatform\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php deleted file mode 100644 index 2f126d745fa..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory::class); - -if (false) { - final class ConfiguredDocumentMetadataFactory extends \ApiPlatform\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php deleted file mode 100644 index d7cf855da08..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php +++ /dev/null @@ -1,52 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Creates read-only operations for Elasticsearch. - * - * @experimental - * - * @author Baptiste Meyer - */ -final class ElasticsearchOperationResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - - public function __construct(ResourceMetadataFactoryInterface $decorated) - { - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - - if (null === $resourceMetadata->getCollectionOperations()) { - $resourceMetadata = $resourceMetadata->withCollectionOperations(['get' => ['method' => 'GET']]); - } - - if (null === $resourceMetadata->getItemOperations()) { - $resourceMetadata = $resourceMetadata->withItemOperations(['get' => ['method' => 'GET']]); - } - - return $resourceMetadata; - } -} diff --git a/src/Core/Bridge/Elasticsearch/Serializer/DocumentNormalizer.php b/src/Core/Bridge/Elasticsearch/Serializer/DocumentNormalizer.php deleted file mode 100644 index eb59f592f40..00000000000 --- a/src/Core/Bridge/Elasticsearch/Serializer/DocumentNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Serializer; - -class_exists(\ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer::class); - -if (false) { - final class DocumentNormalizer extends \ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Serializer/ItemNormalizer.php b/src/Core/Bridge/Elasticsearch/Serializer/ItemNormalizer.php deleted file mode 100644 index d263305ffe6..00000000000 --- a/src/Core/Bridge/Elasticsearch/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Serializer; - -class_exists(\ApiPlatform\Elasticsearch\Serializer\ItemNormalizer::class); - -if (false) { - final class ItemNormalizer extends \ApiPlatform\Elasticsearch\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php b/src/Core/Bridge/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php deleted file mode 100644 index ee7a3d14880..00000000000 --- a/src/Core/Bridge/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Serializer\NameConverter; - -class_exists(\ApiPlatform\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter::class); - -if (false) { - final class InnerFieldsNameConverter extends \ApiPlatform\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Util/FieldDatatypeTrait.php b/src/Core/Bridge/Elasticsearch/Util/FieldDatatypeTrait.php deleted file mode 100644 index 71dd32bd3fb..00000000000 --- a/src/Core/Bridge/Elasticsearch/Util/FieldDatatypeTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Elasticsearch\Util; - -class_exists(\ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait::class); - -if (false) { - trait FieldDatatypeTrait - { - use \ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait; - } -} diff --git a/src/Core/Bridge/FosUser/EventListener.php b/src/Core/Bridge/FosUser/EventListener.php deleted file mode 100644 index 41b77dd78a4..00000000000 --- a/src/Core/Bridge/FosUser/EventListener.php +++ /dev/null @@ -1,58 +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); - -namespace ApiPlatform\Core\Bridge\FosUser; - -use ApiPlatform\Util\RequestAttributesExtractor; -use FOS\UserBundle\Model\UserInterface; -use FOS\UserBundle\Model\UserManagerInterface; -use Symfony\Component\HttpKernel\Event\ViewEvent; - -/** - * Bridges between FOSUserBundle and API Platform Core. - * - * @author Kévin Dunglas - * @author Théo FIDRY - */ -final class EventListener -{ - private $userManager; - - public function __construct(UserManagerInterface $userManager) - { - $this->userManager = $userManager; - } - - /** - * Persists, updates or delete data return by the controller if applicable. - */ - public function onKernelView(ViewEvent $event): void - { - $request = $event->getRequest(); - if (!RequestAttributesExtractor::extractAttributes($request)) { - return; - } - - $user = $event->getControllerResult(); - if (!$user instanceof UserInterface || $request->isMethodSafe()) { - return; - } - - if ('DELETE' === $request->getMethod()) { - $this->userManager->deleteUser($user); - $event->setControllerResult(null); - } else { - $this->userManager->updateUser($user); - } - } -} diff --git a/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php b/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php deleted file mode 100644 index 7fec3d40f61..00000000000 --- a/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php +++ /dev/null @@ -1,215 +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); - -namespace ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider; - -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\FilterLocatorTrait; -use ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser; -use ApiPlatform\Core\Bridge\Symfony\Routing\OperationMethodResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use Nelmio\ApiDocBundle\Annotation\ApiDoc; -use Nelmio\ApiDocBundle\Extractor\AnnotationsProviderInterface; -use Psr\Container\ContainerInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -if (interface_exists(AnnotationsProviderInterface::class)) { - /** - * Creates Nelmio ApiDoc annotations for the api platform. - * - * @author Kévin Dunglas - * @author Teoh Han Hui - * - * @deprecated since version 2.2, to be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - final class ApiPlatformProvider implements AnnotationsProviderInterface - { - use FilterLocatorTrait; - - private $resourceNameCollectionFactory; - private $documentationNormalizer; - private $resourceMetadataFactory; - private $operationMethodResolver; - - /** - * @param ContainerInterface|FilterCollection $filterLocator The new filter locator or the deprecated filter collection - */ - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, NormalizerInterface $documentationNormalizer, ResourceMetadataFactoryInterface $resourceMetadataFactory, $filterLocator, OperationMethodResolverInterface $operationMethodResolver) - { - @trigger_error('The '.__CLASS__.' class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.', \E_USER_DEPRECATED); - - $this->setFilterLocator($filterLocator); - - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->documentationNormalizer = $documentationNormalizer; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->operationMethodResolver = $operationMethodResolver; - } - - /** - * {@inheritdoc} - */ - public function getAnnotations(): array - { - $resourceNameCollection = $this->resourceNameCollectionFactory->create(); - - $hydraDoc = $this->documentationNormalizer->normalize(new Documentation($resourceNameCollection)); - if (!\is_array($hydraDoc)) { - throw new \UnexpectedValueException('Expected data to be an array'); - } - - if (empty($hydraDoc)) { - return []; - } - - $entrypointHydraDoc = $this->getResourceHydraDoc($hydraDoc, '#Entrypoint'); - if (null === $entrypointHydraDoc) { - return []; - } - - $annotations = []; - foreach ($resourceNameCollection as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $prefixedShortName = ($iri = $resourceMetadata->getIri()) ? $iri : '#'.$resourceMetadata->getShortName(); - $resourceHydraDoc = $this->getResourceHydraDoc($hydraDoc, $prefixedShortName); - if (null === $resourceHydraDoc) { - continue; - } - - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - foreach ($collectionOperations as $operationName => $operation) { - $annotations[] = $this->getApiDoc(true, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc, $entrypointHydraDoc); - } - } - - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - foreach ($itemOperations as $operationName => $operation) { - $annotations[] = $this->getApiDoc(false, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc); - } - } - } - - return $annotations; - } - - /** - * Builds ApiDoc annotation from ApiPlatform data. - */ - private function getApiDoc(bool $collection, string $resourceClass, ResourceMetadata $resourceMetadata, string $operationName, array $resourceHydraDoc, array $entrypointHydraDoc = []): ApiDoc - { - if ($collection) { - $method = $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName); - $route = $this->operationMethodResolver->getCollectionOperationRoute($resourceClass, $operationName); - $operationHydraDoc = $this->getCollectionOperationHydraDoc($resourceMetadata->getShortName(), $method, $entrypointHydraDoc); - } else { - $method = $this->operationMethodResolver->getItemOperationMethod($resourceClass, $operationName); - $route = $this->operationMethodResolver->getItemOperationRoute($resourceClass, $operationName); - $operationHydraDoc = $this->getOperationHydraDoc($method, $resourceHydraDoc); - } - - $data = [ - 'resource' => $route->getPath(), - 'description' => $operationHydraDoc['hydra:title'] ?? '', - 'resourceDescription' => $resourceHydraDoc['hydra:title'] ?? '', - 'section' => $resourceHydraDoc['hydra:title'] ?? '', - ]; - - if (isset($operationHydraDoc['expects']) && 'owl:Nothing' !== $operationHydraDoc['expects']) { - $data['input'] = sprintf('%s:%s:%s', ApiPlatformParser::IN_PREFIX, $resourceClass, $operationName); - } - - if (isset($operationHydraDoc['returns']) && 'owl:Nothing' !== $operationHydraDoc['returns']) { - $data['output'] = sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, $resourceClass, $operationName); - } - - if ($collection && 'GET' === $method) { - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); - - $data['filters'] = []; - foreach ($resourceFilters as $filterId) { - if ($filter = $this->getFilter($filterId)) { - foreach ($filter->getDescription($resourceClass) as $name => $definition) { - $data['filters'][] = ['name' => $name] + $definition; - } - } - } - } - - $apiDoc = new ApiDoc($data); - $apiDoc->setRoute($route); - - return $apiDoc; - } - - /** - * Gets Hydra documentation for the given resource. - */ - private function getResourceHydraDoc(array $hydraApiDoc, string $prefixedShortName): ?array - { - if (!isset($hydraApiDoc['hydra:supportedClass']) || !\is_array($hydraApiDoc['hydra:supportedClass'])) { - return null; - } - - foreach ($hydraApiDoc['hydra:supportedClass'] as $supportedClass) { - if (isset($supportedClass['@id']) && $supportedClass['@id'] === $prefixedShortName) { - return $supportedClass; - } - } - - return null; - } - - /** - * Gets the Hydra documentation of a given operation. - */ - private function getOperationHydraDoc(string $method, array $hydraDoc): array - { - if (!isset($hydraDoc['hydra:supportedOperation']) || !\is_array($hydraDoc['hydra:supportedOperation'])) { - return []; - } - - foreach ($hydraDoc['hydra:supportedOperation'] as $supportedOperation) { - if ($supportedOperation['hydra:method'] === $method) { - return $supportedOperation; - } - } - - return []; - } - - /** - * Gets the Hydra documentation for the collection operation. - */ - private function getCollectionOperationHydraDoc(string $shortName, string $method, array $hydraEntrypointDoc): array - { - if (!isset($hydraEntrypointDoc['hydra:supportedProperty']) || !\is_array($hydraEntrypointDoc['hydra:supportedProperty'])) { - return []; - } - - $propertyName = '#Entrypoint/'.lcfirst($shortName); - - foreach ($hydraEntrypointDoc['hydra:supportedProperty'] as $supportedProperty) { - if (isset($supportedProperty['hydra:property']['@id']) - && $supportedProperty['hydra:property']['@id'] === $propertyName) { - return $this->getOperationHydraDoc($method, $supportedProperty['hydra:property']); - } - } - - return []; - } - } -} diff --git a/src/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParser.php b/src/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParser.php deleted file mode 100644 index fc591363d64..00000000000 --- a/src/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParser.php +++ /dev/null @@ -1,280 +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); - -namespace ApiPlatform\Core\Bridge\NelmioApiDoc\Parser; - -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\ApiProperty; -use Nelmio\ApiDocBundle\DataTypes; -use Nelmio\ApiDocBundle\Parser\ParserInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -if (interface_exists(ParserInterface::class)) { - /** - * Extract input and output information for the NelmioApiDocBundle. - * - * @author Kévin Dunglas - * @author Teoh Han Hui - * - * @deprecated since version 2.2, to be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - final class ApiPlatformParser implements ParserInterface - { - public const IN_PREFIX = 'api_platform_in'; - public const OUT_PREFIX = 'api_platform_out'; - public const TYPE_IRI = 'IRI'; - public const TYPE_MAP = [ - Type::BUILTIN_TYPE_BOOL => DataTypes::BOOLEAN, - Type::BUILTIN_TYPE_FLOAT => DataTypes::FLOAT, - Type::BUILTIN_TYPE_INT => DataTypes::INTEGER, - Type::BUILTIN_TYPE_STRING => DataTypes::STRING, - ]; - - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $nameConverter; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, NameConverterInterface $nameConverter = null) - { - @trigger_error('The '.__CLASS__.' class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.', \E_USER_DEPRECATED); - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->nameConverter = $nameConverter; - } - - /** - * {@inheritdoc} - */ - public function supports(array $item) - { - $data = explode(':', $item['class'], 3); - if (!\in_array($data[0], [self::IN_PREFIX, self::OUT_PREFIX], true)) { - return false; - } - if (!isset($data[1])) { - return false; - } - - try { - $this->resourceMetadataFactory->create($data[1]); - - return true; - } catch (ResourceClassNotFoundException $e) { - // return false - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function parse(array $item): array - { - [$io, $resourceClass, $operationName] = explode(':', $item['class'], 3); - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $classOperations = $this->getGroupsForItemAndCollectionOperation($resourceMetadata, $operationName, $io); - - if (!empty($classOperations['serializer_groups'])) { - return $this->getPropertyMetadata($resourceMetadata, $resourceClass, $io, [], $classOperations); - } - - return $this->parseResource($resourceMetadata, $resourceClass, $io); - } - - /** - * Parses a class. - * - * @param string[] $visited - */ - private function parseResource(ResourceMetadata $resourceMetadata, string $resourceClass, string $io, array $visited = []): array - { - $visited[] = $resourceClass; - - $options = []; - $attributes = $resourceMetadata->getAttributes(); - - if (isset($attributes['normalization_context'][AbstractNormalizer::GROUPS])) { - $options['serializer_groups'] = (array) $attributes['normalization_context'][AbstractNormalizer::GROUPS]; - } - - if (isset($attributes['denormalization_context'][AbstractNormalizer::GROUPS])) { - if (isset($options['serializer_groups'])) { - $options['serializer_groups'] += $attributes['denormalization_context'][AbstractNormalizer::GROUPS]; - } else { - $options['serializer_groups'] = (array) $attributes['denormalization_context'][AbstractNormalizer::GROUPS]; - } - } - - return $this->getPropertyMetadata($resourceMetadata, $resourceClass, $io, $visited, $options); - } - - private function getGroupsContext(ResourceMetadata $resourceMetadata, string $operationName, bool $isNormalization): array - { - $groupsContext = $isNormalization ? 'normalization_context' : 'denormalization_context'; - $itemOperationAttribute = $resourceMetadata->getItemOperationAttribute($operationName, $groupsContext, [AbstractNormalizer::GROUPS => []], true)[AbstractNormalizer::GROUPS]; - $collectionOperationAttribute = $resourceMetadata->getCollectionOperationAttribute($operationName, $groupsContext, [AbstractNormalizer::GROUPS => []], true)[AbstractNormalizer::GROUPS]; - - return [ - $groupsContext => [ - AbstractNormalizer::GROUPS => array_merge((array) ($itemOperationAttribute ?? []), (array) ($collectionOperationAttribute ?? [])), - ], - ]; - } - - /** - * Returns groups of item & collection. - */ - private function getGroupsForItemAndCollectionOperation(ResourceMetadata $resourceMetadata, string $operationName, string $io): array - { - $operation = $this->getGroupsContext($resourceMetadata, $operationName, true); - $operation += $this->getGroupsContext($resourceMetadata, $operationName, false); - - if (self::OUT_PREFIX === $io) { - return [ - 'serializer_groups' => !empty($operation['normalization_context']) ? $operation['normalization_context'][AbstractNormalizer::GROUPS] : [], - ]; - } - - if (self::IN_PREFIX === $io) { - return [ - 'serializer_groups' => !empty($operation['denormalization_context']) ? $operation['denormalization_context'][AbstractNormalizer::GROUPS] : [], - ]; - } - - return []; - } - - /** - * Returns a property metadata. - * - * @param string[] $visited - * @param string[] $options - */ - private function getPropertyMetadata(ResourceMetadata $resourceMetadata, string $resourceClass, string $io, array $visited, array $options): array - { - $data = []; - - foreach ($this->propertyNameCollectionFactory->create($resourceClass, $options) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - if ( - ($propertyMetadata->isReadable() && self::OUT_PREFIX === $io) || - ($propertyMetadata->isWritable() && self::IN_PREFIX === $io) - ) { - $normalizedPropertyName = $this->nameConverter ? $this->nameConverter->normalize($propertyName, $resourceClass) : $propertyName; - $data[$normalizedPropertyName] = $this->parseProperty($resourceMetadata, $propertyMetadata, $io, null, $visited); - } - } - - return $data; - } - - /** - * Parses a property. - * - * @param string $io - * @param string[] $visited - * @param ApiProperty|PropertyMetadata $propertyMetadata - */ - private function parseProperty(ResourceMetadata $resourceMetadata, $propertyMetadata, $io, Type $type = null, array $visited = []): array - { - $data = [ - 'dataType' => null, - 'required' => $propertyMetadata->isRequired(), - 'description' => $propertyMetadata->getDescription(), - 'readonly' => !$propertyMetadata->isWritable(), - ]; - - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : $propertyMetadata->getBuiltinTypes()[0] ?? null; - if (null === $type && null === $type) { - // Default to string - $data['dataType'] = DataTypes::STRING; - - return $data; - } - - if ($type->isCollection()) { - $data['actualType'] = DataTypes::COLLECTION; - - if ($collectionType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType()) { - $subProperty = $this->parseProperty($resourceMetadata, $propertyMetadata, $io, $collectionType, $visited); - if (self::TYPE_IRI === $subProperty['dataType']) { - $data['dataType'] = 'array of IRIs'; - $data['subType'] = DataTypes::STRING; - - return $data; - } - - $data['subType'] = $subProperty['subType'] ?? null; - if (isset($subProperty['children'])) { - $data['children'] = $subProperty['children']; - } - } - - return $data; - } - - $builtinType = $type->getBuiltinType(); - if ('object' === $builtinType) { - $className = $type->getClassName(); - - if (is_a($className, \DateTimeInterface::class, true)) { - $data['dataType'] = DataTypes::DATETIME; - $data['format'] = sprintf('{DateTime %s}', \DateTime::RFC3339); - - return $data; - } - - try { - $this->resourceMetadataFactory->create($className); - } catch (ResourceClassNotFoundException $e) { - $data['actualType'] = DataTypes::MODEL; - $data['subType'] = $className; - - return $data; - } - - if ( - (self::OUT_PREFIX === $io && true !== $propertyMetadata->isReadableLink()) || - (self::IN_PREFIX === $io && true !== $propertyMetadata->isWritableLink()) - ) { - $data['dataType'] = self::TYPE_IRI; - $data['actualType'] = DataTypes::STRING; - - return $data; - } - - $data['actualType'] = DataTypes::MODEL; - $data['subType'] = $className; - $data['children'] = \in_array($className, $visited, true) ? [] : $this->parseResource($resourceMetadata, $className, $io, $visited); - - return $data; - } - - $data['dataType'] = self::TYPE_MAP[$builtinType] ?? DataTypes::STRING; - - return $data; - } - } -} diff --git a/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php b/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php deleted file mode 100644 index 10c0743f0c3..00000000000 --- a/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php +++ /dev/null @@ -1,56 +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); - -namespace ApiPlatform\Core\Bridge\RamseyUuid\Identifier\Normalizer; - -use ApiPlatform\Exception\InvalidIdentifierException; -use Ramsey\Uuid\Exception\InvalidUuidStringException; -use Ramsey\Uuid\Uuid; -use Ramsey\Uuid\UuidInterface; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Denormalizes an UUID string to an instance of Ramsey\Uuid. - * - * @author Antoine Bluchet - */ -final class UuidNormalizer implements DenormalizerInterface -{ - /** - * {@inheritdoc} - * - * @param mixed $data - * @param string $class - * @param null $format - * - * @throws InvalidIdentifierException - * - * @return mixed - */ - public function denormalize($data, $class, $format = null, array $context = []) - { - try { - return Uuid::fromString($data); - } catch (InvalidUuidStringException $e) { - throw new InvalidIdentifierException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return \is_string($data) && is_a($type, UuidInterface::class, true); - } -} diff --git a/src/Core/Bridge/RamseyUuid/Serializer/UuidDenormalizer.php b/src/Core/Bridge/RamseyUuid/Serializer/UuidDenormalizer.php deleted file mode 100644 index f9e8ece6a91..00000000000 --- a/src/Core/Bridge/RamseyUuid/Serializer/UuidDenormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\RamseyUuid\Serializer; - -class_exists(\ApiPlatform\RamseyUuid\Serializer\UuidDenormalizer::class); - -if (false) { - final class UuidDenormalizer extends \ApiPlatform\RamseyUuid\Serializer\UuidDenormalizer - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php b/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php deleted file mode 100644 index d0865adb0b5..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php +++ /dev/null @@ -1,229 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Action; - -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction as OpenApiSwaggerUiAction; -use ApiPlatform\Util\RequestAttributesExtractor; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Twig\Environment as TwigEnvironment; - -/** - * Displays the documentation. - * - * @deprecated please refer to ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction for further changes - * - * @author Kévin Dunglas - */ -final class SwaggerUiAction -{ - private $resourceNameCollectionFactory; - /** @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface */ - private $resourceMetadataFactory; - private $normalizer; - private $twig; - private $urlGenerator; - private $title; - private $description; - private $version; - private $showWebby; - private $formats; - private $oauthEnabled; - private $oauthClientId; - private $oauthClientSecret; - private $oauthType; - private $oauthFlow; - private $oauthTokenUrl; - private $oauthAuthorizationUrl; - private $oauthScopes; - private $oauthPkce; - private $formatsProvider; - private $swaggerUiEnabled; - private $reDocEnabled; - private $graphqlEnabled; - private $graphiQlEnabled; - private $graphQlPlaygroundEnabled; - private $swaggerVersions; - private $swaggerUiAction; - private $assetPackage; - private $swaggerUiExtraConfiguration; - - /** - * @param int[] $swaggerVersions - * @param mixed|null $assetPackage - * @param mixed $formats - * @param mixed $oauthEnabled - * @param mixed $oauthClientId - * @param mixed $oauthClientSecret - * @param mixed $oauthType - * @param mixed $oauthFlow - * @param mixed $oauthTokenUrl - * @param mixed $oauthAuthorizationUrl - * @param mixed $oauthScopes - * @param mixed $resourceMetadataFactory - */ - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, $resourceMetadataFactory, NormalizerInterface $normalizer, ?TwigEnvironment $twig, UrlGeneratorInterface $urlGenerator, string $title = '', string $description = '', string $version = '', $formats = [], $oauthEnabled = false, $oauthClientId = '', $oauthClientSecret = '', $oauthType = '', $oauthFlow = '', $oauthTokenUrl = '', $oauthAuthorizationUrl = '', $oauthScopes = [], bool $showWebby = true, bool $swaggerUiEnabled = false, bool $reDocEnabled = false, bool $graphqlEnabled = false, bool $graphiQlEnabled = false, bool $graphQlPlaygroundEnabled = false, array $swaggerVersions = [2, 3], OpenApiSwaggerUiAction $swaggerUiAction = null, $assetPackage = null, array $swaggerUiExtraConfiguration = [], bool $oauthPkce = false) - { - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->normalizer = $normalizer; - $this->twig = $twig; - $this->urlGenerator = $urlGenerator; - $this->title = $title; - $this->showWebby = $showWebby; - $this->description = $description; - $this->version = $version; - $this->oauthEnabled = $oauthEnabled; - $this->oauthClientId = $oauthClientId; - $this->oauthClientSecret = $oauthClientSecret; - $this->oauthType = $oauthType; - $this->oauthFlow = $oauthFlow; - $this->oauthTokenUrl = $oauthTokenUrl; - $this->oauthAuthorizationUrl = $oauthAuthorizationUrl; - $this->oauthScopes = $oauthScopes; - $this->swaggerUiEnabled = $swaggerUiEnabled; - $this->reDocEnabled = $reDocEnabled; - $this->graphqlEnabled = $graphqlEnabled; - $this->graphiQlEnabled = $graphiQlEnabled; - $this->graphQlPlaygroundEnabled = $graphQlPlaygroundEnabled; - $this->swaggerVersions = $swaggerVersions; - $this->swaggerUiAction = $swaggerUiAction; - $this->swaggerUiExtraConfiguration = $swaggerUiExtraConfiguration; - $this->assetPackage = $assetPackage; - $this->oauthPkce = $oauthPkce; - - if (null === $this->twig) { - throw new \RuntimeException('The documentation cannot be displayed since the Twig bundle is not installed. Try running "composer require symfony/twig-bundle".'); - } - - if (null === $this->swaggerUiAction) { - @trigger_error(sprintf('The use of "%s" is deprecated since API Platform 2.6, use "%s" instead.', __CLASS__, OpenApiSwaggerUiAction::class), \E_USER_DEPRECATED); - } - - if (\is_array($formats)) { - $this->formats = $formats; - - return; - } - - @trigger_error(sprintf('Passing an array or an instance of "%s" as 5th parameter of the constructor of "%s" is deprecated since API Platform 2.5, pass an array instead', FormatsProviderInterface::class, __CLASS__), \E_USER_DEPRECATED); - $this->formatsProvider = $formats; - } - - public function __invoke(Request $request) - { - if ($this->swaggerUiAction) { - return $this->swaggerUiAction->__invoke($request); - } - - $attributes = RequestAttributesExtractor::extractAttributes($request); - - // BC check to be removed in 3.0 - if (null === $this->formatsProvider) { - $formats = $attributes ? $this - ->resourceMetadataFactory - ->create($attributes['resource_class']) - ->getOperationAttribute($attributes, 'output_formats', [], true) : $this->formats; - } else { - $formats = $this->formatsProvider->getFormatsFromAttributes($attributes); - } - - $documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version); - - return new Response($this->twig->render('@ApiPlatform/SwaggerUi/index.html.twig', $this->getContext($request, $documentation) + ['formats' => $formats])); - } - - /** - * Gets the base Twig context. - */ - private function getContext(Request $request, Documentation $documentation): array - { - $context = [ - 'title' => $this->title, - 'description' => $this->description, - 'showWebby' => $this->showWebby, - 'swaggerUiEnabled' => $this->swaggerUiEnabled, - 'reDocEnabled' => $this->reDocEnabled, - 'graphqlEnabled' => $this->graphqlEnabled, - 'graphiQlEnabled' => $this->graphiQlEnabled, - 'graphQlPlaygroundEnabled' => $this->graphQlPlaygroundEnabled, - 'assetPackage' => $this->assetPackage, - ]; - - $swaggerContext = ['spec_version' => $request->query->getInt('spec_version', $this->swaggerVersions[0] ?? 2)]; - if ('' !== $baseUrl = $request->getBaseUrl()) { - $swaggerContext['base_url'] = $baseUrl; - } - - $swaggerData = [ - 'url' => $this->urlGenerator->generate('api_doc', ['format' => 'json']), - 'spec' => $this->normalizer->normalize($documentation, 'json', $swaggerContext), - 'extraConfiguration' => $this->swaggerUiExtraConfiguration, - ]; - - $swaggerData['oauth'] = [ - 'enabled' => $this->oauthEnabled, - 'clientId' => $this->oauthClientId, - 'clientSecret' => $this->oauthClientSecret, - 'pkce' => $this->oauthPkce, - 'type' => $this->oauthType, - 'flow' => $this->oauthFlow, - 'tokenUrl' => $this->oauthTokenUrl, - 'authorizationUrl' => $this->oauthAuthorizationUrl, - 'scopes' => $this->oauthScopes, - ]; - - if ($request->isMethodSafe() && null !== $resourceClass = $request->attributes->get('_api_resource_class')) { - $swaggerData['id'] = $request->attributes->get('id'); - $swaggerData['queryParameters'] = $request->query->all(); - - $metadata = $this->resourceMetadataFactory->create($resourceClass); - $swaggerData['shortName'] = $metadata instanceof ResourceMetadata ? $metadata->getShortName() : $metadata[0]->getShortName(); - - if (null !== $collectionOperationName = $request->attributes->get('_api_collection_operation_name')) { - $swaggerData['operationId'] = sprintf('%s%sCollection', $collectionOperationName, ucfirst($swaggerData['shortName'])); - } elseif (null !== $itemOperationName = $request->attributes->get('_api_item_operation_name')) { - $swaggerData['operationId'] = sprintf('%s%sItem', $itemOperationName, ucfirst($swaggerData['shortName'])); - } elseif (null !== $subresourceOperationContext = $request->attributes->get('_api_subresource_context')) { - $swaggerData['operationId'] = $subresourceOperationContext['operationId']; - } - - [$swaggerData['path'], $swaggerData['method']] = $this->getPathAndMethod($swaggerData); - } - - return $context + ['swagger_data' => $swaggerData]; - } - - private function getPathAndMethod(array $swaggerData): array - { - foreach ($swaggerData['spec']['paths'] as $path => $operations) { - foreach ($operations as $method => $operation) { - if ($operation['operationId'] === $swaggerData['operationId']) { - return [$path, $method]; - } - } - } - - throw new RuntimeException(sprintf('The operation "%s" cannot be found in the Swagger specification.', $swaggerData['operationId'])); - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/ApiPlatformBundle.php b/src/Core/Bridge/Symfony/Bundle/ApiPlatformBundle.php deleted file mode 100644 index f766d5ca6ac..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/ApiPlatformBundle.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle; - -class_exists(\ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class); - -if (false) { - final class ApiPlatformBundle extends \ApiPlatform\Symfony\Bundle\ApiPlatformBundle - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php b/src/Core/Bridge/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php deleted file mode 100644 index 8b8eedc7b3b..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\ArgumentResolver; - -class_exists(\ApiPlatform\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver::class); - -if (false) { - final class PayloadArgumentResolver extends \ApiPlatform\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php b/src/Core/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php deleted file mode 100644 index 5cc4c49cb6d..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\CacheWarmer; - -class_exists(\ApiPlatform\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer::class); - -if (false) { - final class CachePoolClearerCacheWarmer extends \ApiPlatform\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Command/GraphQlExportCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/GraphQlExportCommand.php deleted file mode 100644 index 3cbf77c8e19..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Command/GraphQlExportCommand.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Command; - -class_exists(\ApiPlatform\Symfony\Bundle\Command\GraphQlExportCommand::class); - -if (false) { - class GraphQlExportCommand extends \ApiPlatform\Symfony\Bundle\Command\GraphQlExportCommand - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Command/OpenApiCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/OpenApiCommand.php deleted file mode 100644 index d35c3c7216f..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Command/OpenApiCommand.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Command; - -class_exists(\ApiPlatform\Symfony\Bundle\Command\OpenApiCommand::class); - -if (false) { - final class OpenApiCommand extends \ApiPlatform\Symfony\Bundle\Command\OpenApiCommand - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php deleted file mode 100644 index 9666b5fa5b2..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php +++ /dev/null @@ -1,118 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Command; - -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidOptionException; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Yaml\Yaml; - -/** - * Console command to dump Swagger API documentations. - * - * @author Amrouche Hamza - */ -final class SwaggerCommand extends Command -{ - protected static $defaultName = 'api:swagger:export'; - - private $normalizer; - private $resourceNameCollectionFactory; - private $apiTitle; - private $apiDescription; - private $apiVersion; - private $apiFormats; - private $swaggerVersions; - private $legacyMode; - - /** - * @param int[] $swaggerVersions - */ - public function __construct(NormalizerInterface $normalizer, ResourceNameCollectionFactoryInterface $resourceNameCollection, string $apiTitle, string $apiDescription, string $apiVersion, array $apiFormats = null, array $swaggerVersions = [2, 3], bool $legacyMode = false) - { - $this->normalizer = $normalizer; - $this->resourceNameCollectionFactory = $resourceNameCollection; - $this->apiTitle = $apiTitle; - $this->apiDescription = $apiDescription; - $this->apiVersion = $apiVersion; - $this->apiFormats = $apiFormats; - $this->swaggerVersions = $swaggerVersions; - $this->legacyMode = $legacyMode; - - if (null !== $apiFormats) { - @trigger_error(sprintf('Passing a 6th parameter to the constructor of "%s" is deprecated since API Platform 2.5', __CLASS__), \E_USER_DEPRECATED); - } - - parent::__construct(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('Dump the Swagger v2 documentation') - ->addOption('yaml', 'y', InputOption::VALUE_NONE, 'Dump the documentation in YAML') - ->addOption('spec-version', null, InputOption::VALUE_OPTIONAL, sprintf('OpenAPI version to use (%s)', implode(' or ', $this->swaggerVersions)), (string) ($this->swaggerVersions[0] ?? 2)) - ->addOption('output', 'o', InputOption::VALUE_OPTIONAL, 'Write output to file') - ->addOption('api-gateway', null, InputOption::VALUE_NONE, 'API Gateway compatibility'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - /** @var string $version */ - $version = $input->getOption('spec-version'); - - if (!\in_array((int) $version, $this->swaggerVersions, true)) { - throw new InvalidOptionException(sprintf('This tool only supports versions %s of the OpenAPI specification ("%s" given).', implode(', ', $this->swaggerVersions), $version)); - } - - if (3 === (int) $version) { - @trigger_error('The command "api:swagger:export" is deprecated for the spec version 3 use "api:openapi:export".', \E_USER_DEPRECATED); - } - - if (!$this->legacyMode) { - @trigger_error('The command "api:swagger:export" is using pre-2.7 metadata, new metadata will not appear, use "api:openapi:export" instead.', \E_USER_DEPRECATED); - } - - $documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->apiTitle, $this->apiDescription, $this->apiVersion, $this->apiFormats); - $data = $this->normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['spec_version' => (int) $version, ApiGatewayNormalizer::API_GATEWAY => $input->getOption('api-gateway')]); - $content = $input->getOption('yaml') - ? Yaml::dump($data, 10, 2, Yaml::DUMP_OBJECT_AS_MAP | Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK) - : (json_encode($data, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES) ?: ''); - - if (!empty($filename = $input->getOption('output')) && \is_string($filename)) { - file_put_contents($filename, $content); - $io->success(sprintf('Data written to %s (specification version %s).', $filename, $version)); - } else { - $output->writeln($content); - } - - return 0; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php deleted file mode 100644 index dc65594ad0b..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php +++ /dev/null @@ -1,257 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Command; - -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Upgrade\ColorConsoleDiffFormatter; -use ApiPlatform\Core\Upgrade\SubresourceTransformer; -use ApiPlatform\Core\Upgrade\UpgradeApiResourceVisitor; -use ApiPlatform\Core\Upgrade\UpgradeApiSubresourceVisitor; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use Doctrine\Common\Annotations\AnnotationReader; -use PhpParser\Lexer\Emulative; -use PhpParser\NodeTraverser; -use PhpParser\Parser\Php7; -use PhpParser\PrettyPrinter\Standard; -use SebastianBergmann\Diff\Differ; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -final class UpgradeApiResourceCommand extends Command -{ - protected static $defaultName = 'api:upgrade-resource'; - - private $resourceNameCollectionFactory; - private $resourceMetadataFactory; - private $subresourceOperationFactory; - private $subresourceTransformer; - private $reader; - private $identifiersExtractor; - private $localCache = []; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, SubresourceOperationFactoryInterface $subresourceOperationFactory, SubresourceTransformer $subresourceTransformer, IdentifiersExtractorInterface $identifiersExtractor, AnnotationReader $reader = null) - { - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->subresourceOperationFactory = $subresourceOperationFactory; - $this->subresourceTransformer = $subresourceTransformer; - $this->identifiersExtractor = $identifiersExtractor; - $this->reader = $reader; - - parent::__construct(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('The "api:upgrade-resource" command upgrades your API Platform metadata from versions below 2.6 to the new metadata from versions above 2.7. -Once you executed this script, make sure that the "metadata_backward_compatibility_layer" flag is set to "false" in the API Platform configuration. -This will remove "ApiPlatform\Core\Annotation\ApiResource" annotation/attribute and use the "ApiPlatform\Metadata\ApiResource" attribute instead.') - ->addOption('dry-run', '-d', InputOption::VALUE_NEGATABLE, 'Dry mode outputs a diff instead of writing files.', true) - ->addOption('silent', '-s', InputOption::VALUE_NONE, 'Silent output.') - ->addOption('force', '-f', InputOption::VALUE_NONE, 'Writes the files in place and skips PHP version check.'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - if (!$input->getOption('force') && \PHP_VERSION_ID < 80100) { - $output->write('The new metadata system only works with PHP 8.1 and above.'); - - return Command::INVALID; - } - - $this->transformApiSubresource($input, $output); - $this->transformApiResource($input, $output); - - return Command::SUCCESS; - } - - /** - * This computes a local cache with resource classes having subresources. - * We first loop over all the classes and re-map the metadata on the correct Resource class. - * Then we transform the ApiSubresource to an ApiResource class. - */ - private function transformApiSubresource(InputInterface $input, OutputInterface $output): void - { - foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - try { - new \ReflectionClass($resourceClass); - } catch (\Exception $e) { - continue; - } - - if (!isset($this->localCache[$resourceClass])) { - $this->localCache[$resourceClass] = []; - } - - foreach ($this->subresourceOperationFactory->create($resourceClass) as $subresourceMetadata) { - if (!isset($this->localCache[$subresourceMetadata['resource_class']])) { - $this->localCache[$subresourceMetadata['resource_class']] = []; - } - - foreach ($this->localCache[$subresourceMetadata['resource_class']] as $currentSubresourceMetadata) { - if ($currentSubresourceMetadata['path'] === $subresourceMetadata['path']) { - continue 2; - } - } - $this->localCache[$subresourceMetadata['resource_class']][] = $subresourceMetadata; - } - } - - // Compute URI variables - foreach ($this->localCache as $class => $subresources) { - if (!$subresources) { - unset($this->localCache[$class]); - continue; - } - - foreach ($subresources as $i => $subresourceMetadata) { - $this->localCache[$class][$i]['uri_variables'] = $this->subresourceTransformer->toUriVariables($subresourceMetadata); - } - } - - foreach ($this->localCache as $resourceClass => $linkedSubresourceMetadata) { - $fileName = (new \ReflectionClass($resourceClass))->getFilename(); - - $referenceType = null; - try { - $metadata = $this->resourceMetadataFactory->create($resourceClass); - $referenceType = $metadata->getAttribute('url_generation_strategy'); - } catch (\Exception $e) { - } - - foreach ($linkedSubresourceMetadata as $subresourceMetadata) { - $lexer = new Emulative([ - 'usedAttributes' => [ - 'comments', - 'startLine', 'endLine', - 'startTokenPos', 'endTokenPos', - ], - ]); - $parser = new Php7($lexer); - - $traverser = new NodeTraverser(); - $traverser->addVisitor(new UpgradeApiSubresourceVisitor($subresourceMetadata, $referenceType)); - $prettyPrinter = new Standard(); - - $oldCode = file_get_contents($fileName); - $oldStmts = $parser->parse($oldCode); - $oldTokens = $lexer->getTokens(); - - $newStmts = $traverser->traverse($oldStmts); - - $newCode = $prettyPrinter->printFormatPreserving($newStmts, $oldStmts, $oldTokens); - - if (!$input->getOption('force') && $input->getOption('dry-run')) { - if ($input->getOption('silent')) { - continue; - } - - $this->printDiff($oldCode, $newCode, $output); - continue; - } - - file_put_contents($fileName, $newCode); - } - } - } - - private function transformApiResource(InputInterface $input, OutputInterface $output): void - { - $prettyPrinter = new Standard(); - foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - continue; - } - $lexer = new Emulative([ - 'usedAttributes' => [ - 'comments', - 'startLine', - 'endLine', - 'startTokenPos', - 'endTokenPos', - ], - ]); - $parser = new Php7($lexer); - $fileName = (new \ReflectionClass($resourceClass))->getFilename(); - - $traverser = new NodeTraverser(); - [$attribute, $isAnnotation] = $this->readApiResource($resourceClass); - - if (!$attribute) { - continue; - } - - $traverser->addVisitor(new UpgradeApiResourceVisitor($attribute, $isAnnotation, $this->identifiersExtractor, $resourceClass)); - - $oldCode = file_get_contents($fileName); - $oldStmts = $parser->parse($oldCode); - $oldTokens = $lexer->getTokens(); - - $newStmts = $traverser->traverse($oldStmts); - $newCode = $prettyPrinter->printFormatPreserving($newStmts, $oldStmts, $oldTokens); - - if (!$input->getOption('force') && $input->getOption('dry-run')) { - if ($input->getOption('silent')) { - continue; - } - - $this->printDiff($oldCode, $newCode, $output); - continue; - } - - file_put_contents($fileName, $newCode); - } - } - - private function printDiff(string $oldCode, string $newCode, OutputInterface $output): void - { - $consoleFormatter = new ColorConsoleDiffFormatter(); - $differ = new Differ(); - $diff = $differ->diff($oldCode, $newCode); - $output->write($consoleFormatter->format($diff)); - } - - /** - * @return array[ApiResource, bool] - */ - private function readApiResource(string $resourceClass): array - { - $reflectionClass = new \ReflectionClass($resourceClass); - - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionClass->getAttributes(ApiResource::class)) { - return [$attributes[0]->newInstance(), false]; - } - - if (null === $this->reader) { - throw new \RuntimeException(sprintf('Resource "%s" not found.', $resourceClass)); - } - - return [$this->reader->getClassAnnotation($reflectionClass, ApiResource::class), true]; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataCollector/RequestDataCollector.php b/src/Core/Bridge/Symfony/Bundle/DataCollector/RequestDataCollector.php deleted file mode 100644 index 2b7c993cf5d..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataCollector/RequestDataCollector.php +++ /dev/null @@ -1,194 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DataCollector; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister\TraceableChainDataPersister; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainCollectionDataProvider; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainItemDataProvider; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainSubresourceDataProvider; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\RequestAttributesExtractor; -use PackageVersions\Versions; -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\DataCollector; - -/** - * @author Julien DENIAU - * @author Anthony GRASSIOT - */ -final class RequestDataCollector extends DataCollector -{ - private $metadataFactory; - private $filterLocator; - private $collectionDataProvider; - private $itemDataProvider; - private $subresourceDataProvider; - private $dataPersister; - - public function __construct(ResourceMetadataFactoryInterface $metadataFactory, ContainerInterface $filterLocator, CollectionDataProviderInterface $collectionDataProvider = null, ItemDataProviderInterface $itemDataProvider = null, SubresourceDataProviderInterface $subresourceDataProvider = null, DataPersisterInterface $dataPersister = null) - { - $this->metadataFactory = $metadataFactory; - $this->filterLocator = $filterLocator; - $this->collectionDataProvider = $collectionDataProvider; - $this->itemDataProvider = $itemDataProvider; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->dataPersister = $dataPersister; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $counters = ['ignored_filters' => 0]; - $resourceClass = $request->attributes->get('_api_resource_class'); - $resourceMetadata = $resourceClass ? $this->metadataFactory->create($resourceClass) : null; - - $filters = []; - foreach ($resourceMetadata ? $resourceMetadata->getAttribute('filters', []) : [] as $id) { - if ($this->filterLocator->has($id)) { - $filters[$id] = \get_class($this->filterLocator->get($id)); - continue; - } - - $filters[$id] = null; - ++$counters['ignored_filters']; - } - - $requestAttributes = RequestAttributesExtractor::extractAttributes($request); - if (isset($requestAttributes['previous_data'])) { - $requestAttributes['previous_data'] = $this->cloneVar($requestAttributes['previous_data']); - } - - $this->data = [ - 'resource_class' => $resourceClass, - 'resource_metadata' => $resourceMetadata ? $this->cloneVar($resourceMetadata) : null, - 'acceptable_content_types' => $request->getAcceptableContentTypes(), - 'filters' => $filters, - 'counters' => $counters, - 'dataProviders' => [], - 'dataPersisters' => ['responses' => []], - 'request_attributes' => $requestAttributes, - ]; - - if ($this->collectionDataProvider instanceof TraceableChainCollectionDataProvider) { - $this->data['dataProviders']['collection'] = [ - 'context' => $this->cloneVar($this->collectionDataProvider->getContext()), - 'responses' => $this->collectionDataProvider->getProvidersResponse(), - ]; - } - - if ($this->itemDataProvider instanceof TraceableChainItemDataProvider) { - $this->data['dataProviders']['item'] = [ - 'context' => $this->cloneVar($this->itemDataProvider->getContext()), - 'responses' => $this->itemDataProvider->getProvidersResponse(), - ]; - } - - if ($this->subresourceDataProvider instanceof TraceableChainSubresourceDataProvider) { - $this->data['dataProviders']['subresource'] = [ - 'context' => $this->cloneVar($this->subresourceDataProvider->getContext()), - 'responses' => $this->subresourceDataProvider->getProvidersResponse(), - ]; - } - - if ($this->dataPersister instanceof TraceableChainDataPersister) { - $this->data['dataPersisters']['responses'] = $this->dataPersister->getPersistersResponse(); - } - } - - public function getAcceptableContentTypes(): array - { - return $this->data['acceptable_content_types'] ?? []; - } - - public function getResourceClass() - { - return $this->data['resource_class'] ?? null; - } - - public function getResourceMetadata() - { - return $this->data['resource_metadata'] ?? null; - } - - public function getRequestAttributes(): array - { - return $this->data['request_attributes'] ?? []; - } - - public function getFilters(): array - { - return $this->data['filters'] ?? []; - } - - public function getCounters(): array - { - return $this->data['counters'] ?? []; - } - - public function getCollectionDataProviders(): array - { - return $this->data['dataProviders']['collection'] ?? ['context' => [], 'responses' => []]; - } - - public function getItemDataProviders(): array - { - return $this->data['dataProviders']['item'] ?? ['context' => [], 'responses' => []]; - } - - public function getSubresourceDataProviders(): array - { - return $this->data['dataProviders']['subresource'] ?? ['context' => [], 'responses' => []]; - } - - public function getDataPersisters(): array - { - return $this->data['dataPersisters'] ?? ['responses' => []]; - } - - public function getVersion(): ?string - { - if (!class_exists(Versions::class)) { - return null; - } - - $version = Versions::getVersion('api-platform/core'); - preg_match('/^v(.*?)@/', $version, $output); - - return $output[1] ?? strtok($version, '@'); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'api_platform.data_collector.request'; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = []; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersister.php b/src/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersister.php deleted file mode 100644 index a85a79f2219..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersister.php +++ /dev/null @@ -1,84 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister; - -use ApiPlatform\Core\DataPersister\ChainDataPersister; -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataPersister\ResumableDataPersisterInterface; - -/** - * @author Anthony GRASSIOT - */ -final class TraceableChainDataPersister implements ContextAwareDataPersisterInterface -{ - private $persisters = []; - private $persistersResponse = []; - private $decorated; - - public function __construct(DataPersisterInterface $dataPersister) - { - if ($dataPersister instanceof ChainDataPersister) { - $this->decorated = $dataPersister; - $this->persisters = $dataPersister->persisters; - } - } - - public function getPersistersResponse(): array - { - return $this->persistersResponse; - } - - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - return $this->decorated->supports($data, $context); - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []) - { - $this->tracePersisters($data, $context); - - return $this->decorated->persist($data, $context); - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []) - { - $this->tracePersisters($data, $context); - - return $this->decorated->remove($data, $context); - } - - private function tracePersisters($data, array $context = []) - { - $found = false; - foreach ($this->persisters as $persister) { - if ( - ($this->persistersResponse[\get_class($persister)] = $found ? false : $persister->supports($data, $context)) - && - !($persister instanceof ResumableDataPersisterInterface && $persister->resumable()) && !$found - ) { - $found = true; - } - } - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataProvider.php b/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataProvider.php deleted file mode 100644 index 836270f040f..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataProvider.php +++ /dev/null @@ -1,77 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainCollectionDataProvider; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictDataProviderTrait; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * @author Anthony GRASSIOT - */ -final class TraceableChainCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - use RestrictDataProviderTrait; - - private $context = []; - private $providersResponse = []; - - public function __construct(CollectionDataProviderInterface $collectionDataProvider) - { - if ($collectionDataProvider instanceof ChainCollectionDataProvider) { - $this->dataProviders = $collectionDataProvider->dataProviders; - } - } - - public function getProvidersResponse(): array - { - return $this->providersResponse; - } - - public function getContext(): array - { - return $this->context; - } - - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - $this->context = $context; - $results = null; - $match = false; - - foreach ($this->dataProviders as $dataProvider) { - $this->providersResponse[\get_class($dataProvider)] = $match ? null : false; - if ($match) { - continue; - } - try { - if ($dataProvider instanceof RestrictedDataProviderInterface - && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - $results = $dataProvider->getCollection($resourceClass, $operationName, $context); - $this->providersResponse[\get_class($dataProvider)] = $match = true; - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"', ResourceClassNotSupportedException::class, RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return $results ?? []; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataProvider.php b/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataProvider.php deleted file mode 100644 index a3116cf882e..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataProvider.php +++ /dev/null @@ -1,87 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainItemDataProvider; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictDataProviderTrait; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * @author Anthony GRASSIOT - */ -final class TraceableChainItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - use RestrictDataProviderTrait; - - private $context = []; - private $providersResponse = []; - - public function __construct(ItemDataProviderInterface $itemDataProvider) - { - if ($itemDataProvider instanceof ChainItemDataProvider) { - $this->dataProviders = $itemDataProvider->dataProviders; - } - } - - public function getProvidersResponse(): array - { - return $this->providersResponse; - } - - public function getContext(): array - { - return $this->context; - } - - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - $this->context = $context; - $match = false; - $result = null; - - foreach ($this->dataProviders as $dataProvider) { - $this->providersResponse[\get_class($dataProvider)] = $match ? null : false; - if ($match) { - continue; - } - try { - if ($dataProvider instanceof RestrictedDataProviderInterface - && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - $identifier = $id; - if (!$dataProvider instanceof DenormalizedIdentifiersAwareItemDataProviderInterface && $identifier && \is_array($identifier)) { - if (\count($identifier) > 1) { - @trigger_error(sprintf('Receiving "$id" as non-array in an item data provider is deprecated in 2.3 in favor of implementing "%s".', DenormalizedIdentifiersAwareItemDataProviderInterface::class), \E_USER_DEPRECATED); - $identifier = http_build_query($identifier, '', ';'); - } else { - $identifier = current($identifier); - } - } - - $result = $dataProvider->getItem($resourceClass, $identifier, $operationName, $context); - $this->providersResponse[\get_class($dataProvider)] = $match = true; - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" is deprecated in favor of implementing "%s"', \get_class($e), RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return $result; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataProvider.php b/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataProvider.php deleted file mode 100644 index 867375b4785..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataProvider.php +++ /dev/null @@ -1,77 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainSubresourceDataProvider; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * @author Anthony GRASSIOT - */ -final class TraceableChainSubresourceDataProvider implements SubresourceDataProviderInterface -{ - private $dataProviders = []; - private $context = []; - private $providersResponse = []; - - public function __construct(SubresourceDataProviderInterface $subresourceDataProvider) - { - if ($subresourceDataProvider instanceof ChainSubresourceDataProvider) { - $this->dataProviders = $subresourceDataProvider->dataProviders; - } - } - - public function getProvidersResponse(): array - { - return $this->providersResponse; - } - - public function getContext(): array - { - return $this->context; - } - - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - $this->context = $context; - $match = false; - $result = null; - - foreach ($this->dataProviders as $dataProvider) { - $this->providersResponse[\get_class($dataProvider)] = $match ? null : false; - if ($match) { - continue; - } - try { - if ($dataProvider instanceof RestrictedDataProviderInterface && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - $result = $dataProvider->getSubresource($resourceClass, $identifiers, $context, $operationName); - $this->providersResponse[\get_class($dataProvider)] = $match = true; - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"', ResourceClassNotSupportedException::class, RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - if ($match) { - return $result; - } - - return ($context['collection'] ?? false) ? [] : null; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php deleted file mode 100644 index 3f87256cfa1..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\ApiPlatformExtension::class); - -if (false) { - final class ApiPlatformExtension extends \ApiPlatform\Symfony\Bundle\DependencyInjection\ApiPlatformExtension - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php deleted file mode 100644 index 155f4b25721..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass::class); - -if (false) { - final class AnnotationFilterPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php deleted file mode 100644 index 1ade44a2bb3..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass::class); - -if (false) { - final class AuthenticatorManagerPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php deleted file mode 100644 index 0eb98670e35..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass::class); - -if (false) { - final class DataProviderPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php deleted file mode 100644 index 0a416411a9c..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass::class); - -if (false) { - final class DeprecateMercurePublisherPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php deleted file mode 100644 index 21403760cdf..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass::class); - -if (false) { - final class ElasticsearchClientPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php deleted file mode 100644 index d38e09b6b88..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass::class); - -if (false) { - final class FilterPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php deleted file mode 100644 index aa64933292b..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass::class); - -if (false) { - final class GraphQlMutationResolverPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php deleted file mode 100644 index 69f3eda55ba..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass::class); - -if (false) { - final class GraphQlQueryResolverPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php deleted file mode 100644 index fa6edee6809..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass::class); - -if (false) { - final class GraphQlTypePass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php deleted file mode 100644 index ae891b50bff..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass::class); - -if (false) { - final class MetadataAwareNameConverterPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php deleted file mode 100644 index ada12cd16c4..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass::class); - -if (false) { - final class TestClientPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php deleted file mode 100644 index 39a8c39c4b2..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Configuration::class); - -if (false) { - final class Configuration extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Configuration - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php b/src/Core/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php deleted file mode 100644 index 934dad77e94..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener; - -class_exists(\ApiPlatform\Symfony\Bundle\EventListener\SwaggerUiListener::class); - -if (false) { - final class SwaggerUiListener extends \ApiPlatform\Symfony\Bundle\EventListener\SwaggerUiListener - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php b/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php deleted file mode 100644 index 2fb7f4ace0c..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi; - -class_exists(\ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction::class); - -if (false) { - final class SwaggerUiAction extends \ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php b/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php deleted file mode 100644 index 729a84e3298..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi; - -class_exists(\ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiContext::class); - -if (false) { - final class SwaggerUiContext extends \ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiContext - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php b/src/Core/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php deleted file mode 100644 index a616e27ec37..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test; - -class_exists(\ApiPlatform\Symfony\Bundle\Test\ApiTestAssertionsTrait::class); - -if (false) { - trait ApiTestAssertionsTrait - { - use \ApiPlatform\Symfony\Bundle\Test\ApiTestAssertionsTrait; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/ApiTestCase.php b/src/Core/Bridge/Symfony/Bundle/Test/ApiTestCase.php deleted file mode 100644 index d2835b4fe54..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/ApiTestCase.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test; - -class_exists(\ApiPlatform\Symfony\Bundle\Test\ApiTestCase::class); - -if (false) { - class ApiTestCase extends \ApiPlatform\Symfony\Bundle\Test\ApiTestCase - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Client.php b/src/Core/Bridge/Symfony/Bundle/Test/Client.php deleted file mode 100644 index 4399df64840..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Client.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test; - -class_exists(\ApiPlatform\Symfony\Bundle\Test\Client::class); - -if (false) { - final class Client extends \ApiPlatform\Symfony\Bundle\Test\Client - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php deleted file mode 100644 index a55455514fb..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php +++ /dev/null @@ -1,31 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint; - -use PHPUnit\Runner\Version; -use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure; -use SebastianBergmann\Comparator\ComparisonFailure as LegacyComparisonFailure; - -if (!class_exists(ComparisonFailure::class)) { - class_alias(LegacyComparisonFailure::class, 'PHPUnit\SebastianBergmann\Comparator\ComparisonFailure'); -} - -trigger_deprecation('api-platform/core', '2.7', sprintf('The class %s is deprecated, use %s instead.', 'ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset', 'ApiPlatform\Symfony\Bundle\Test\Constraint')); - -// Aliases as string to avoid loading the class -if (\PHP_VERSION_ID >= 80000 || (float) Version::series() >= 9) { - class_alias('ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetV9', 'ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset'); -} else { - class_alias('ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetLegacy', 'ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset'); -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php deleted file mode 100644 index 0911672ce01..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php +++ /dev/null @@ -1,34 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; - -/** - * Is used for phpunit < 8. - * - * @internal - */ -final class ArraySubsetLegacy extends Constraint -{ - use ArraySubsetTrait; - - /** - * {@inheritdoc} - */ - public function evaluate($other, $description = '', $returnResult = false) - { - return $this->_evaluate($other, $description, $returnResult); - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php deleted file mode 100644 index cebb2217c31..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php +++ /dev/null @@ -1,98 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure; - -/** - * Constraint that asserts that the array it is evaluated for has a specified subset. - * - * Uses array_replace_recursive() to check if a key value subset is part of the - * subject array. - * - * Imported from dms/phpunit-arraysubset-asserts, because the original constraint has been deprecated. - * - * @copyright Sebastian Bergmann - * @copyright Rafael Dohms - * - * @see https://github.com/sebastianbergmann/phpunit/issues/3494 - */ -trait ArraySubsetTrait -{ - private $subset; - private $strict; - - public function __construct(iterable $subset, bool $strict = false) - { - $this->strict = $strict; - $this->subset = $subset; - } - - private function _evaluate($other, string $description = '', bool $returnResult = false): ?bool - { - // type cast $other & $this->subset as an array to allow - // support in standard array functions. - $other = $this->toArray($other); - $this->subset = $this->toArray($this->subset); - $patched = array_replace_recursive($other, $this->subset); - if ($this->strict) { - $result = $other === $patched; - } else { - $result = $other == $patched; - } - if ($returnResult) { - return $result; - } - if ($result) { - return null; - } - - $f = new ComparisonFailure( - $patched, - $other, - var_export($patched, true), - var_export($other, true) - ); - $this->fail($other, $description, $f); - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'has the subset '.$this->exporter()->export($this->subset); - } - - /** - * {@inheritdoc} - */ - protected function failureDescription($other): string - { - return 'an array '.$this->toString(); - } - - private function toArray(iterable $other): array - { - if (\is_array($other)) { - return $other; - } - if ($other instanceof \ArrayObject) { - return $other->getArrayCopy(); - } - - return iterator_to_array($other); - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php deleted file mode 100644 index ccb16def0e6..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php +++ /dev/null @@ -1,34 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; - -/** - * Is used for phpunit >= 9. - * - * @internal - */ -final class ArraySubsetV9 extends Constraint -{ - use ArraySubsetTrait; - - /** - * {@inheritdoc} - */ - public function evaluate($other, string $description = '', bool $returnResult = false): ?bool - { - return $this->_evaluate($other, $description, $returnResult); - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php deleted file mode 100644 index 910d3990a87..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php +++ /dev/null @@ -1,116 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint; - -use JsonSchema\Validator; -use PHPUnit\Framework\Constraint\Constraint; - -/** - * Asserts that a JSON document matches a given JSON Schema. - * - * @author Kévin Dunglas - * - * @experimental - */ -final class MatchesJsonSchema extends Constraint -{ - /** - * @var object|array - */ - private $schema; - private $checkMode; - - /** - * @param object|array|string $schema - */ - public function __construct($schema, ?int $checkMode = null) - { - $this->schema = \is_string($schema) ? json_decode($schema) : $schema; - $this->checkMode = $checkMode; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'matches the provided JSON Schema'; - } - - /** - * {@inheritdoc} - */ - protected function matches($other): bool - { - if (!class_exists(Validator::class)) { - throw new \LogicException('The "justinrainbow/json-schema" library must be installed to use "assertMatchesJsonSchema()". Try running "composer require --dev justinrainbow/json-schema".'); - } - - $other = $this->normalizeJson($other); - - $validator = new Validator(); - $validator->validate($other, $this->schema, $this->checkMode); - - return $validator->isValid(); - } - - /** - * {@inheritdoc} - */ - protected function additionalFailureDescription($other): string - { - $other = $this->normalizeJson($other); - - $validator = new Validator(); - $validator->validate($other, $this->schema, $this->checkMode); - - $errors = []; - foreach ($validator->getErrors() as $error) { - $property = $error['property'] ? $error['property'].': ' : ''; - $errors[] = $property.$error['message']; - } - - return implode("\n", $errors); - } - - /** - * Normalizes a JSON document. - * - * Specifically, we should ensure that: - * 1. a JSON object is represented as a PHP object, not as an associative array. - * - * @param mixed $document - */ - private function normalizeJson($document) - { - if (\is_scalar($document) || \is_object($document)) { - return $document; - } - - if (!\is_array($document)) { - throw new \InvalidArgumentException('Document must be scalar, array or object.'); - } - - $document = json_encode($document); - if (!\is_string($document)) { - throw new \UnexpectedValueException('JSON encode failed.'); - } - $document = json_decode($document); - if (!\is_array($document) && !\is_object($document)) { - throw new \UnexpectedValueException('JSON decode failed.'); - } - - return $document; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Response.php b/src/Core/Bridge/Symfony/Bundle/Test/Response.php deleted file mode 100644 index d1b77770bdf..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Response.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test; - -class_exists(\ApiPlatform\Symfony\Bundle\Test\Response::class); - -if (false) { - final class Response extends \ApiPlatform\Symfony\Bundle\Test\Response - { - } -} diff --git a/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php b/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php deleted file mode 100644 index c1675e87d94..00000000000 --- a/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php +++ /dev/null @@ -1,46 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer; - -use ApiPlatform\Exception\InvalidIdentifierException; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Uid\Ulid; - -/** - * Denormalizes an ULID string to an instance of Symfony\Component\Uid\Ulid. - */ -final class UlidNormalizer implements DenormalizerInterface -{ - /** - * {@inheritdoc} - * - * @return mixed - */ - public function denormalize($data, $class, $format = null, array $context = []) - { - try { - return Ulid::fromString($data); - } catch (\InvalidArgumentException $e) { - throw new InvalidIdentifierException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return \is_string($data) && is_a($type, Ulid::class, true); - } -} diff --git a/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php b/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php deleted file mode 100644 index a51f074a316..00000000000 --- a/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php +++ /dev/null @@ -1,46 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer; - -use ApiPlatform\Exception\InvalidIdentifierException; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Uid\Uuid; - -/** - * Denormalizes an UUID string to an instance of Symfony\Component\Uid\Uuid. - */ -final class UuidNormalizer implements DenormalizerInterface -{ - /** - * {@inheritdoc} - * - * @return mixed - */ - public function denormalize($data, $class, $format = null, array $context = []) - { - try { - return Uuid::fromString($data); - } catch (\InvalidArgumentException|\ValueError $e) { // catching ValueError will not be necessary anymore when https://github.com/symfony/symfony/pull/39636 will be released - throw new InvalidIdentifierException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return \is_string($data) && is_a($type, Uuid::class, true); - } -} diff --git a/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php b/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php deleted file mode 100644 index 13daf7d6a74..00000000000 --- a/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php +++ /dev/null @@ -1,116 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Maker; - -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use Symfony\Bundle\MakerBundle\ConsoleStyle; -use Symfony\Bundle\MakerBundle\DependencyBuilder; -use Symfony\Bundle\MakerBundle\Generator; -use Symfony\Bundle\MakerBundle\InputConfiguration; -use Symfony\Bundle\MakerBundle\Maker\AbstractMaker; -use Symfony\Bundle\MakerBundle\Str; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Question\Question; - -final class MakeDataPersister extends AbstractMaker -{ - private $resourceNameCollection; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollection) - { - $this->resourceNameCollection = $resourceNameCollection; - } - - /** - * {@inheritdoc} - */ - public static function getCommandName(): string - { - return 'make:data-persister'; - } - - /** - * {@inheritdoc} - */ - public static function getCommandDescription(): string - { - return 'Creates an API Platform data persister'; - } - - /** - * {@inheritdoc} - */ - public function configureCommand(Command $command, InputConfiguration $inputConfig) - { - $command - ->addArgument('name', InputArgument::OPTIONAL, 'Choose a class name for your data persister (e.g. AwesomeDataPersister)') - ->addArgument('resource-class', InputArgument::OPTIONAL, 'Choose a Resource class') - ->setHelp(file_get_contents(__DIR__.'/Resources/help/MakeDataPersister.txt')); - - $inputConfig->setArgumentAsNonInteractive('resource-class'); - } - - /** - * {@inheritdoc} - */ - public function configureDependencies(DependencyBuilder $dependencies) - { - } - - public function interact(InputInterface $input, ConsoleStyle $io, Command $command) - { - if (null === $input->getArgument('resource-class')) { - $argument = $command->getDefinition()->getArgument('resource-class'); - - $resourceClasses = $this->resourceNameCollection->create(); - - $question = new Question($argument->getDescription()); - $question->setAutocompleterValues($resourceClasses); - - $value = $io->askQuestion($question); - - $input->setArgument('resource-class', $value); - } - } - - /** - * {@inheritdoc} - */ - public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator) - { - $dataPersisterClassNameDetails = $generator->createClassNameDetails( - $input->getArgument('name'), - 'DataPersister\\' - ); - $resourceClass = $input->getArgument('resource-class'); - - $generator->generateClass( - $dataPersisterClassNameDetails->getFullName(), - __DIR__.'/Resources/skeleton/DataPersister.tpl.php', - [ - 'resource_class' => null !== $resourceClass ? Str::getShortClassName($resourceClass) : null, - 'resource_full_class_name' => $resourceClass, - ] - ); - $generator->writeChanges(); - - $this->writeSuccessMessage($io); - $io->text([ - 'Next: Open your new data persister class and start customizing it.', - 'Find the documentation at https://api-platform.com/docs/core/data-persisters/', - ]); - } -} diff --git a/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php b/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php deleted file mode 100644 index 9db71ced56f..00000000000 --- a/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php +++ /dev/null @@ -1,122 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Maker; - -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use Symfony\Bundle\MakerBundle\ConsoleStyle; -use Symfony\Bundle\MakerBundle\DependencyBuilder; -use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException; -use Symfony\Bundle\MakerBundle\Generator; -use Symfony\Bundle\MakerBundle\InputConfiguration; -use Symfony\Bundle\MakerBundle\Maker\AbstractMaker; -use Symfony\Bundle\MakerBundle\Str; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Question\Question; - -class MakeDataProvider extends AbstractMaker -{ - private $resourceNameCollection; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollection) - { - $this->resourceNameCollection = $resourceNameCollection; - } - - /** - * {@inheritdoc} - */ - public static function getCommandName(): string - { - return 'make:data-provider'; - } - - /** - * {@inheritdoc} - */ - public static function getCommandDescription(): string - { - return 'Creates an API Platform data provider'; - } - - /** - * {@inheritdoc} - */ - public function configureCommand(Command $command, InputConfiguration $inputConfig) - { - $command - ->addArgument('name', InputArgument::OPTIONAL, 'Choose a class name for your data provider (e.g. AwesomeDataProvider)') - ->addArgument('resource-class', InputArgument::OPTIONAL, 'Choose a Resource class') - ->addOption('item-only', null, InputOption::VALUE_NONE, 'Generate only an item data provider') - ->addOption('collection-only', null, InputOption::VALUE_NONE, 'Generate only a collection data provider') - ->setHelp(file_get_contents(__DIR__.'/Resources/help/MakeDataProvider.txt')); - - $inputConfig->setArgumentAsNonInteractive('resource-class'); - } - - /** - * {@inheritdoc} - */ - public function configureDependencies(DependencyBuilder $dependencies) - { - } - - public function interact(InputInterface $input, ConsoleStyle $io, Command $command) - { - if ($input->getOption('item-only') && $input->getOption('collection-only')) { - throw new RuntimeCommandException('You should at least generate an item or a collection data provider'); - } - - if (null === $input->getArgument('resource-class')) { - $argument = $command->getDefinition()->getArgument('resource-class'); - - $question = new Question($argument->getDescription()); - $question->setAutocompleterValues($this->resourceNameCollection->create()); - - $input->setArgument('resource-class', $io->askQuestion($question)); - } - } - - /** - * {@inheritdoc} - */ - public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator) - { - $dataProviderClassNameDetails = $generator->createClassNameDetails( - $input->getArgument('name'), - 'DataProvider\\' - ); - $resourceClass = $input->getArgument('resource-class'); - - $generator->generateClass( - $dataProviderClassNameDetails->getFullName(), - __DIR__.'/Resources/skeleton/DataProvider.tpl.php', - [ - 'resource_class' => null !== $resourceClass ? Str::getShortClassName($resourceClass) : null, - 'resource_full_class_name' => $resourceClass, - 'generate_collection' => !$input->getOption('item-only'), - 'generate_item' => !$input->getOption('collection-only'), - ] - ); - $generator->writeChanges(); - - $this->writeSuccessMessage($io); - $io->text([ - 'Next: Open your new data provider class and start customizing it.', - 'Find the documentation at https://api-platform.com/docs/core/data-providers/', - ]); - } -} diff --git a/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataPersister.txt b/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataPersister.txt deleted file mode 100644 index 7afe500d462..00000000000 --- a/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataPersister.txt +++ /dev/null @@ -1,5 +0,0 @@ -The %command.name% command generates a new API Platform data persister class. - -php %command.full_name% AwesomeDataPersister - -If the argument is missing, the command will ask for the class name interactively. diff --git a/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataProvider.txt b/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataProvider.txt deleted file mode 100644 index 73064481560..00000000000 --- a/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataProvider.txt +++ /dev/null @@ -1,5 +0,0 @@ -The %command.name% command generates a new API Platform data provider class. - -php %command.full_name% AwesomeDataProvider - -If the argument is missing, the command will ask for the class name interactively. diff --git a/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataPersister.tpl.php b/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataPersister.tpl.php deleted file mode 100644 index 5ed85510a77..00000000000 --- a/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataPersister.tpl.php +++ /dev/null @@ -1,57 +0,0 @@ - - -namespace ; - -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Core\DataPersister\ResumableDataPersisterInterface; - -use ; - - -final class implements ContextAwareDataPersisterInterface, ResumableDataPersisterInterface -{ - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - - return $data instanceof ::class; // Add your custom conditions here - - return false; // Add your custom conditions here - - } - - /** - * {@inheritdoc} - */ - public function resumable(array $context = []): bool - { - return false; // Set it to true if you want to call the other data persisters - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = [])= 70200) { - echo ': object'; - }?> - - { - // Call your persistence layer to save $data - - return $data; - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []): void - { - // Call your persistence layer to delete $data - } -} diff --git a/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataProvider.tpl.php b/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataProvider.tpl.php deleted file mode 100644 index 0d8160c8589..00000000000 --- a/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataProvider.tpl.php +++ /dev/null @@ -1,64 +0,0 @@ - - -namespace ; - - -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; - - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; - -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; - -use ; - - -final class implements RestrictedDataProviderInterface -{ - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - - return ::class === $resourceClass; // Add your custom conditions here - - return false; // Add your custom conditions here - - } - - - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - // Retrieve the collection from somewhere - } - - - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])= 70200) { - echo ': ?object'; - }?> - - { - // Retrieve the item from somewhere then return it or null if not found - } - -} diff --git a/src/Core/Bridge/Symfony/Messenger/ContextStamp.php b/src/Core/Bridge/Symfony/Messenger/ContextStamp.php deleted file mode 100644 index a127b3dd06f..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/ContextStamp.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Messenger; - -class_exists(\ApiPlatform\Symfony\Messenger\ContextStamp::class); - -if (false) { - final class ContextStamp extends \ApiPlatform\Symfony\Messenger\ContextStamp - { - } -} diff --git a/src/Core/Bridge/Symfony/Messenger/DataPersister.php b/src/Core/Bridge/Symfony/Messenger/DataPersister.php deleted file mode 100644 index f2b13d85a74..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/DataPersister.php +++ /dev/null @@ -1,122 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Messenger; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Symfony\Messenger\DispatchTrait; -use ApiPlatform\Util\ClassInfoTrait; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Messenger\Stamp\HandledStamp; - -/** - * Dispatches the given resource using the message bus of Symfony Messenger. - * - * @experimental - * - * @author Kévin Dunglas - */ -final class DataPersister implements ContextAwareDataPersisterInterface -{ - use ClassInfoTrait; - use DispatchTrait; - - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface - */ - private $resourceMetadataFactory; - - public function __construct($resourceMetadataFactory, MessageBusInterface $messageBus) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->messageBus = $messageBus; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - } - - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - try { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($context['resource_class'] ?? $this->getObjectClass($data)); - $operation = $resourceMetadataCollection->getOperation($context['operation_name'] ?? null); - - return false !== ($operation->getMessenger() ?? false); - } catch (OperationNotFoundException $e) { - return false; - } - } - - try { - $resourceMetadata = $this->resourceMetadataFactory->create($context['resource_class'] ?? $this->getObjectClass($data)); - } catch (ResourceClassNotFoundException $e) { - return false; - } - - if (null !== $operationName = $context['collection_operation_name'] ?? $context['item_operation_name'] ?? null) { - return false !== $resourceMetadata->getTypedOperationAttribute( - $context['collection_operation_name'] ?? false ? OperationType::COLLECTION : OperationType::ITEM, - $operationName, - 'messenger', - false, - true - ); - } - - if (isset($context['graphql_operation_name'])) { - return false !== $resourceMetadata->getGraphqlAttribute($context['graphql_operation_name'], 'messenger', false, true); - } - - return false !== $resourceMetadata->getAttribute('messenger', false); - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []) - { - $envelope = $this->dispatch( - (new Envelope($data)) - ->with(new ContextStamp($context)) - ); - - $handledStamp = $envelope->last(HandledStamp::class); - if (!$handledStamp instanceof HandledStamp) { - return $data; - } - - return $handledStamp->getResult(); - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []) - { - $this->dispatch( - (new Envelope($data)) - ->with(new RemoveStamp()) - ); - } -} diff --git a/src/Core/Bridge/Symfony/Messenger/DataTransformer.php b/src/Core/Bridge/Symfony/Messenger/DataTransformer.php deleted file mode 100644 index d940788fbf9..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/DataTransformer.php +++ /dev/null @@ -1,98 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Messenger; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Util\ClassInfoTrait; - -/** - * Transforms an Input to itself. This gives the ability to send the Input to a - * message handler and process it asynchronously. - * - * @author Antoine Bluchet - */ -final class DataTransformer implements DataTransformerInterface -{ - use ClassInfoTrait; - - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface - */ - private $resourceMetadataFactory; - - public function __construct($resourceMetadataFactory) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - } - - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - return $object; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - if ( - \is_object($data) // data is not normalized yet, it should be an array - || - null === ($context['input']['class'] ?? null) - ) { - return false; - } - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - try { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($context['resource_class'] ?? $to); - $operation = $resourceMetadataCollection->getOperation($context['operation_name'] ?? null); - - return 'input' === $operation->getMessenger(); - } catch (OperationNotFoundException $e) { - return false; - } - } - - $metadata = $this->resourceMetadataFactory->create($context['resource_class'] ?? $to); - - if (isset($context['graphql_operation_name'])) { - return 'input' === $metadata->getGraphqlAttribute($context['graphql_operation_name'], 'messenger', null, true); - } - - if (!isset($context['operation_type'])) { - return 'input' === $metadata->getAttribute('messenger'); - } - - return 'input' === $metadata->getTypedOperationAttribute( - $context['operation_type'], - $context[$context['operation_type'].'_operation_name'] ?? '', - 'messenger', - null, - true - ); - } -} diff --git a/src/Core/Bridge/Symfony/Messenger/DispatchTrait.php b/src/Core/Bridge/Symfony/Messenger/DispatchTrait.php deleted file mode 100644 index 7ae211cd77f..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/DispatchTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Messenger; - -class_exists(\ApiPlatform\Symfony\Messenger\DispatchTrait::class); - -if (false) { - trait DispatchTrait - { - use \ApiPlatform\Symfony\Messenger\DispatchTrait; - } -} diff --git a/src/Core/Bridge/Symfony/Messenger/RemoveStamp.php b/src/Core/Bridge/Symfony/Messenger/RemoveStamp.php deleted file mode 100644 index e5f1dc898ad..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/RemoveStamp.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Messenger; - -class_exists(\ApiPlatform\Symfony\Messenger\RemoveStamp::class); - -if (false) { - final class RemoveStamp extends \ApiPlatform\Symfony\Messenger\RemoveStamp - { - } -} diff --git a/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php b/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php deleted file mode 100644 index 26d7a76b657..00000000000 --- a/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php +++ /dev/null @@ -1,89 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property; - -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; - -/** - * PropertyInfo metadata loader decorator. - * - * @author Kévin Dunglas - */ -final class PropertyInfoPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $propertyInfo; - private $decorated; - - public function __construct(PropertyInfoExtractorInterface $propertyInfo, PropertyMetadataFactoryInterface $decorated = null) - { - $this->propertyInfo = $propertyInfo; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - if (null === $this->decorated) { - $propertyMetadata = new PropertyMetadata(); - } else { - try { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - } catch (PropertyNotFoundException $propertyNotFoundException) { - $propertyMetadata = new PropertyMetadata(); - } - } - - if (null === $propertyMetadata->getType()) { - $types = $this->propertyInfo->getTypes($resourceClass, $property, $options); - if (isset($types[0])) { - $propertyMetadata = $propertyMetadata->withType($types[0]); - } - } - - if (null === $propertyMetadata->getDescription() && null !== $description = $this->propertyInfo->getShortDescription($resourceClass, $property, $options)) { - $propertyMetadata = $propertyMetadata->withDescription($description); - } - - if (null === $propertyMetadata->isReadable() && null !== $readable = $this->propertyInfo->isReadable($resourceClass, $property, $options)) { - $propertyMetadata = $propertyMetadata->withReadable($readable); - } - - if (null === $propertyMetadata->isWritable() && null !== $writable = $this->propertyInfo->isWritable($resourceClass, $property, $options)) { - $propertyMetadata = $propertyMetadata->withWritable($writable); - } - - if (method_exists($this->propertyInfo, 'isInitializable')) { - if (null === $propertyMetadata->isInitializable() && null !== $initializable = $this->propertyInfo->isInitializable($resourceClass, $property, $options)) { - $propertyMetadata = $propertyMetadata->withInitializable($initializable); - } - } else { - // BC layer for Symfony < 4.2 - $ref = new \ReflectionClass($resourceClass); - if ($ref->isInstantiable() && $constructor = $ref->getConstructor()) { - foreach ($constructor->getParameters() as $constructorParameter) { - if ($constructorParameter->name === $property && null === $propertyMetadata->isInitializable()) { - $propertyMetadata = $propertyMetadata->withInitializable(true); - } - } - } - } - - return $propertyMetadata; - } -} diff --git a/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php b/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php deleted file mode 100644 index 6e1839aa845..00000000000 --- a/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property; - -class_exists(\ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory::class); - -if (false) { - final class PropertyInfoPropertyNameCollectionFactory extends \ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory - { - } -} diff --git a/src/Core/Bridge/Symfony/Routing/ApiLoader.php b/src/Core/Bridge/Symfony/Routing/ApiLoader.php deleted file mode 100644 index 5265467c555..00000000000 --- a/src/Core/Bridge/Symfony/Routing/ApiLoader.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -class_exists(\ApiPlatform\Symfony\Routing\ApiLoader::class); - -if (false) { - final class ApiLoader extends \ApiPlatform\Symfony\Routing\ApiLoader - { - } -} diff --git a/src/Core/Bridge/Symfony/Routing/CachedRouteNameResolver.php b/src/Core/Bridge/Symfony/Routing/CachedRouteNameResolver.php deleted file mode 100644 index 7cdcf4461c5..00000000000 --- a/src/Core/Bridge/Symfony/Routing/CachedRouteNameResolver.php +++ /dev/null @@ -1,50 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -use ApiPlatform\Util\CachedTrait; -use Psr\Cache\CacheItemPoolInterface; - -/** - * {@inheritdoc} - * - * @author Teoh Han Hui - */ -final class CachedRouteNameResolver implements RouteNameResolverInterface -{ - use CachedTrait; - - public const CACHE_KEY_PREFIX = 'route_name_'; - - private $decorated; - - public function __construct(CacheItemPoolInterface $cacheItemPool, RouteNameResolverInterface $decorated) - { - $this->cacheItemPool = $cacheItemPool; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function getRouteName(string $resourceClass, $operationType /* , array $context = [] */): string - { - $context = \func_num_args() > 2 ? func_get_arg(2) : []; - $cacheKey = self::CACHE_KEY_PREFIX.md5(serialize([$resourceClass, $operationType, $context['subresource_resources'] ?? null])); - - return $this->getCached($cacheKey, function () use ($resourceClass, $operationType, $context) { - return $this->decorated->getRouteName($resourceClass, $operationType, $context); - }); - } -} diff --git a/src/Core/Bridge/Symfony/Routing/IriConverter.php b/src/Core/Bridge/Symfony/Routing/IriConverter.php deleted file mode 100644 index a3c0bfc3533..00000000000 --- a/src/Core/Bridge/Symfony/Routing/IriConverter.php +++ /dev/null @@ -1,186 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\IdentifiersExtractor; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\UrlGeneratorInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\OperationDataProviderTrait; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\CompositeIdentifierParser; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\ItemNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Symfony\Routing\IriConverter as NewIriConverter; -use ApiPlatform\Util\AttributesExtractor; -use ApiPlatform\Util\ResourceClassInfoTrait; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Routing\Exception\ExceptionInterface as RoutingExceptionInterface; -use Symfony\Component\Routing\RouterInterface; - -/** - * {@inheritdoc} - * - * @author Kévin Dunglas - */ -final class IriConverter implements IriConverterInterface -{ - use OperationDataProviderTrait; - use ResourceClassInfoTrait; - - private $routeNameResolver; - private $router; - private $identifiersExtractor; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ItemDataProviderInterface $itemDataProvider, RouteNameResolverInterface $routeNameResolver, RouterInterface $router, PropertyAccessorInterface $propertyAccessor = null, IdentifiersExtractorInterface $identifiersExtractor = null, SubresourceDataProviderInterface $subresourceDataProvider = null, IdentifierConverterInterface $identifierConverter = null, ResourceClassResolverInterface $resourceClassResolver = null, ResourceMetadataFactoryInterface $resourceMetadataFactory = null) - { - $this->itemDataProvider = $itemDataProvider; - $this->routeNameResolver = $routeNameResolver; - $this->router = $router; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->identifierConverter = $identifierConverter; - $this->resourceClassResolver = $resourceClassResolver; - $this->identifiersExtractor = $identifiersExtractor ?: new IdentifiersExtractor($propertyNameCollectionFactory, $propertyMetadataFactory, $propertyAccessor ?? PropertyAccess::createPropertyAccessor()); - $this->resourceMetadataFactory = $resourceMetadataFactory; - - trigger_deprecation('api-platform/core', '2.7', sprintf('The service "%s" is deprecated, use %s instead.', self::class, NewIriConverter::class)); - } - - /** - * {@inheritdoc} - * - * @return object - */ - public function getItemFromIri(string $iri, array $context = []) - { - try { - $parameters = $this->router->match($iri); - } catch (RoutingExceptionInterface $e) { - throw new InvalidArgumentException(sprintf('No route matches "%s".', $iri), $e->getCode(), $e); - } - - if (!isset($parameters['_api_resource_class'])) { - throw new InvalidArgumentException(sprintf('No resource associated to "%s".', $iri)); - } - - if (isset($parameters['_api_collection_operation_name'])) { - throw new InvalidArgumentException(sprintf('The iri "%s" references a collection not an item.', $iri)); - } - - $attributes = AttributesExtractor::extractAttributes($parameters); - - try { - $identifiers = $this->extractIdentifiers($parameters, $attributes); - } catch (InvalidIdentifierException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - - if ($this->identifierConverter) { - $context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] = true; - } - - if (isset($attributes['subresource_operation_name'])) { - if (($item = $this->getSubresourceData($identifiers, $attributes, $context)) && !\is_array($item)) { - return $item; - } - - throw new ItemNotFoundException(sprintf('Item not found for "%s".', $iri)); - } - - if ($item = $this->getItemData($identifiers, $attributes, $context)) { - return $item; - } - - throw new ItemNotFoundException(sprintf('Item not found for "%s".', $iri)); - } - - /** - * {@inheritdoc} - */ - public function getIriFromItem($item, int $referenceType = null): string - { - $resourceClass = $this->getResourceClass($item, true); - - try { - $identifiers = $this->identifiersExtractor->getIdentifiersFromItem($item); - } catch (RuntimeException $e) { - throw new InvalidArgumentException(sprintf('Unable to generate an IRI for the item of type "%s"', $resourceClass), $e->getCode(), $e); - } - - return $this->getItemIriFromResourceClass($resourceClass, $identifiers, $this->getReferenceType($resourceClass, $referenceType)); - } - - /** - * {@inheritdoc} - */ - public function getIriFromResourceClass(string $resourceClass, int $referenceType = null): string - { - try { - return $this->router->generate($this->routeNameResolver->getRouteName($resourceClass, OperationType::COLLECTION), [], $this->getReferenceType($resourceClass, $referenceType)); - } catch (RoutingExceptionInterface $e) { - throw new InvalidArgumentException(sprintf('Unable to generate an IRI for "%s".', $resourceClass), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function getItemIriFromResourceClass(string $resourceClass, array $identifiers, int $referenceType = null): string - { - $routeName = $this->routeNameResolver->getRouteName($resourceClass, OperationType::ITEM); - $metadata = $this->resourceMetadataFactory->create($resourceClass); - - if (\count($identifiers) > 1 && true === $metadata->getAttribute('composite_identifier', true)) { - $identifiers = ['id' => CompositeIdentifierParser::stringify($identifiers)]; - } - - try { - return $this->router->generate($routeName, $identifiers, $this->getReferenceType($resourceClass, $referenceType)); - } catch (RoutingExceptionInterface $e) { - throw new InvalidArgumentException(sprintf('Unable to generate an IRI for "%s".', $resourceClass), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function getSubresourceIriFromResourceClass(string $resourceClass, array $context, int $referenceType = null): string - { - try { - return $this->router->generate($this->routeNameResolver->getRouteName($resourceClass, OperationType::SUBRESOURCE, $context), $context['subresource_identifiers'], $this->getReferenceType($resourceClass, $referenceType)); - } catch (RoutingExceptionInterface $e) { - throw new InvalidArgumentException(sprintf('Unable to generate an IRI for "%s".', $resourceClass), $e->getCode(), $e); - } - } - - private function getReferenceType(string $resourceClass, ?int $referenceType): ?int - { - if (null === $referenceType && null !== $this->resourceMetadataFactory) { - $metadata = $this->resourceMetadataFactory->create($resourceClass); - $referenceType = $metadata->getAttribute('url_generation_strategy'); - } - - return $referenceType ?? UrlGeneratorInterface::ABS_PATH; - } -} diff --git a/src/Core/Bridge/Symfony/Routing/OperationMethodResolver.php b/src/Core/Bridge/Symfony/Routing/OperationMethodResolver.php deleted file mode 100644 index d236b4534c0..00000000000 --- a/src/Core/Bridge/Symfony/Routing/OperationMethodResolver.php +++ /dev/null @@ -1,153 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\RuntimeException; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouterInterface; - -/** - * Resolves the HTTP method associated with an operation, extended for Symfony routing. - * - * @author Kévin Dunglas - * @author Teoh Han Hui - * - * @deprecated since API Platform 2.5, use the "method" attribute instead - */ -final class OperationMethodResolver implements OperationMethodResolverInterface -{ - private $router; - private $resourceMetadataFactory; - - public function __construct(RouterInterface $router, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - @trigger_error(sprintf('The "%s" class is deprecated since API Platform 2.5, use the "method" attribute instead.', __CLASS__), \E_USER_DEPRECATED); - - $this->router = $router; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - /** - * {@inheritdoc} - */ - public function getCollectionOperationMethod(string $resourceClass, string $operationName): string - { - return $this->getOperationMethod($resourceClass, $operationName, OperationType::COLLECTION); - } - - /** - * {@inheritdoc} - */ - public function getItemOperationMethod(string $resourceClass, string $operationName): string - { - return $this->getOperationMethod($resourceClass, $operationName, OperationType::ITEM); - } - - /** - * {@inheritdoc} - */ - public function getCollectionOperationRoute(string $resourceClass, string $operationName): Route - { - return $this->getOperationRoute($resourceClass, $operationName, OperationType::COLLECTION); - } - - /** - * {@inheritdoc} - */ - public function getItemOperationRoute(string $resourceClass, string $operationName): Route - { - return $this->getOperationRoute($resourceClass, $operationName, OperationType::ITEM); - } - - /** - * @throws RuntimeException - */ - private function getOperationMethod(string $resourceClass, string $operationName, string $operationType): string - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if (OperationType::ITEM === $operationType) { - $method = $resourceMetadata->getItemOperationAttribute($operationName, 'method'); - } else { - $method = $resourceMetadata->getCollectionOperationAttribute($operationName, 'method'); - } - - if (null !== $method) { - return strtoupper($method); - } - - if (null === $routeName = $this->getRouteName($resourceMetadata, $operationName, $operationType)) { - throw new RuntimeException(sprintf('Either a "route_name" or a "method" operation attribute must exist for the operation "%s" of the resource "%s".', $operationName, $resourceClass)); - } - - return $this->getRoute($routeName)->getMethods()[0] ?? 'GET'; - } - - /** - * Gets the route related to the given operation. - * - * @throws RuntimeException - */ - private function getOperationRoute(string $resourceClass, string $operationName, string $operationType): Route - { - $routeName = $this->getRouteName($this->resourceMetadataFactory->create($resourceClass), $operationName, $operationType); - if (null !== $routeName) { - return $this->getRoute($routeName); - } - - $operationNameKey = sprintf('_api_%s_operation_name', $operationType); - - foreach ($this->router->getRouteCollection()->all() as $routeName => $route) { - $currentResourceClass = $route->getDefault('_api_resource_class'); - $currentOperationName = $route->getDefault($operationNameKey); - - if ($resourceClass === $currentResourceClass && $operationName === $currentOperationName) { - return $route; - } - } - - throw new RuntimeException(sprintf('No route found for operation "%s" for type "%s".', $operationName, $resourceClass)); - } - - /** - * Gets the route name or null if not defined. - */ - private function getRouteName(ResourceMetadata $resourceMetadata, string $operationName, string $operationType): ?string - { - if (OperationType::ITEM === $operationType) { - return $resourceMetadata->getItemOperationAttribute($operationName, 'route_name'); - } - - return $resourceMetadata->getCollectionOperationAttribute($operationName, 'route_name'); - } - - /** - * Gets the route with the given name. - * - * @throws RuntimeException - */ - private function getRoute(string $routeName): Route - { - foreach ($this->router->getRouteCollection() as $name => $route) { - if ($routeName === $name) { - return $route; - } - } - - throw new RuntimeException(sprintf('The route "%s" does not exist.', $routeName)); - } -} diff --git a/src/Core/Bridge/Symfony/Routing/OperationMethodResolverInterface.php b/src/Core/Bridge/Symfony/Routing/OperationMethodResolverInterface.php deleted file mode 100644 index 1b17511229c..00000000000 --- a/src/Core/Bridge/Symfony/Routing/OperationMethodResolverInterface.php +++ /dev/null @@ -1,38 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\OperationMethodResolverInterface as BaseOperationMethodResolverInterface; -use ApiPlatform\Exception\RuntimeException; -use Symfony\Component\Routing\Route; - -/** - * Resolves the HTTP method associated with an operation, extended for Symfony routing. - * - * @author Teoh Han Hui - * - * @deprecated since API Platform 2.5, use the "method" attribute instead - */ -interface OperationMethodResolverInterface extends BaseOperationMethodResolverInterface -{ - /** - * @throws RuntimeException - */ - public function getCollectionOperationRoute(string $resourceClass, string $operationName): Route; - - /** - * @throws RuntimeException - */ - public function getItemOperationRoute(string $resourceClass, string $operationName): Route; -} diff --git a/src/Core/Bridge/Symfony/Routing/RouteNameGenerator.php b/src/Core/Bridge/Symfony/Routing/RouteNameGenerator.php deleted file mode 100644 index 4fce8174b38..00000000000 --- a/src/Core/Bridge/Symfony/Routing/RouteNameGenerator.php +++ /dev/null @@ -1,77 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Util\Inflector; - -/** - * Generates the Symfony route name associated with an operation name and a resource short name. - * - * @internal - * - * @author Baptiste Meyer - */ -final class RouteNameGenerator -{ - public const ROUTE_NAME_PREFIX = 'api_'; - - private function __construct() - { - } - - /** - * Generates a Symfony route name. - * - * @param string|bool $operationType - * - * @throws InvalidArgumentException - */ - public static function generate(string $operationName, string $resourceShortName, $operationType): string - { - if (OperationType::SUBRESOURCE === $operationType = OperationTypeDeprecationHelper::getOperationType($operationType)) { - throw new InvalidArgumentException('Subresource operations are not supported by the RouteNameGenerator.'); - } - - $operationName = sprintf( - '%s%s_%s', - static::ROUTE_NAME_PREFIX, - self::inflector($resourceShortName), - $operationName - ); - - // prevent api_foo_get_collection_collection - if ("_$operationType" !== substr($operationName, -\strlen("_$operationType"))) { - $operationName .= "_$operationType"; - } - - return $operationName; - } - - /** - * Transforms a given string to a tableized, pluralized string. - * - * @param string $name usually a ResourceMetadata shortname - * - * @return string A string that is a part of the route name - */ - public static function inflector(string $name, bool $pluralize = true): string - { - $name = Inflector::tableize($name); - - return $pluralize ? Inflector::pluralize($name) : $name; - } -} diff --git a/src/Core/Bridge/Symfony/Routing/RouteNameResolver.php b/src/Core/Bridge/Symfony/Routing/RouteNameResolver.php deleted file mode 100644 index 5034f959556..00000000000 --- a/src/Core/Bridge/Symfony/Routing/RouteNameResolver.php +++ /dev/null @@ -1,76 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; -use ApiPlatform\Exception\InvalidArgumentException; -use Symfony\Component\Routing\RouterInterface; - -/** - * {@inheritdoc} - * - * @author Kévin Dunglas - */ -final class RouteNameResolver implements RouteNameResolverInterface -{ - private $router; - - public function __construct(RouterInterface $router) - { - $this->router = $router; - } - - /** - * {@inheritdoc} - */ - public function getRouteName(string $resourceClass, $operationType /* , array $context = [] */): string - { - if (\func_num_args() > 2) { - $context = func_get_arg(2); - } else { - $context = []; - } - - $operationType = OperationTypeDeprecationHelper::getOperationType($operationType); - - foreach ($this->router->getRouteCollection()->all() as $routeName => $route) { - $currentResourceClass = $route->getDefault('_api_resource_class'); - $operation = $route->getDefault(sprintf('_api_%s_operation_name', $operationType)); - $methods = $route->getMethods(); - - if ($resourceClass === $currentResourceClass && null !== $operation && (empty($methods) || \in_array('GET', $methods, true))) { - if (OperationType::SUBRESOURCE === $operationType && false === $this->isSameSubresource($context, $route->getDefault('_api_subresource_context'))) { - continue; - } - - return $routeName; - } - } - - throw new InvalidArgumentException(sprintf('No %s route associated with the type "%s".', $operationType, $resourceClass)); - } - - private function isSameSubresource(array $context, array $currentContext): bool - { - $subresources = array_keys($context['subresource_resources']); - $currentSubresources = []; - - foreach ($currentContext['identifiers'] as [$class]) { - $currentSubresources[] = $class; - } - - return $currentSubresources === $subresources; - } -} diff --git a/src/Core/Bridge/Symfony/Routing/RouteNameResolverInterface.php b/src/Core/Bridge/Symfony/Routing/RouteNameResolverInterface.php deleted file mode 100644 index 91078b25cc8..00000000000 --- a/src/Core/Bridge/Symfony/Routing/RouteNameResolverInterface.php +++ /dev/null @@ -1,33 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * Resolves the Symfony route name associated with a resource. - * - * @author Teoh Han Hui - */ -interface RouteNameResolverInterface -{ - /** - * Finds the route name for a resource. - * - * @param bool|string $operationType - * - * @throws InvalidArgumentException - */ - public function getRouteName(string $resourceClass, $operationType /* , array $context = [] */): string; -} diff --git a/src/Core/Bridge/Symfony/Routing/Router.php b/src/Core/Bridge/Symfony/Routing/Router.php deleted file mode 100644 index 52326c81c3f..00000000000 --- a/src/Core/Bridge/Symfony/Routing/Router.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -class_exists(\ApiPlatform\Symfony\Routing\Router::class); - -if (false) { - final class Router extends \ApiPlatform\Symfony\Routing\Router - { - } -} diff --git a/src/Core/Bridge/Symfony/Routing/RouterOperationPathResolver.php b/src/Core/Bridge/Symfony/Routing/RouterOperationPathResolver.php deleted file mode 100644 index dd2d9c95399..00000000000 --- a/src/Core/Bridge/Symfony/Routing/RouterOperationPathResolver.php +++ /dev/null @@ -1,72 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use Symfony\Component\Routing\RouterInterface; - -/** - * Resolves the operations path using a Symfony route. - * TODO: remove this in 3.0. - * - * @author Guilhem N. - */ -final class RouterOperationPathResolver implements OperationPathResolverInterface -{ - private $router; - private $deferred; - - public function __construct(RouterInterface $router, OperationPathResolverInterface $deferred) - { - $this->router = $router; - $this->deferred = $deferred; - } - - /** - * {@inheritdoc} - * - * @throws InvalidArgumentException - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() >= 4) { - $operationName = (string) func_get_arg(3); - } else { - @trigger_error(sprintf('Method %s() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1.', __METHOD__), \E_USER_DEPRECATED); - - $operationName = null; - } - - if (isset($operation['route_name'])) { - $routeName = $operation['route_name']; - } elseif (OperationType::SUBRESOURCE === $operationType) { - throw new InvalidArgumentException('Subresource operations are not supported by the RouterOperationPathResolver without a route name.'); - } elseif (null === $operationName) { - return $this->deferred->resolveOperationPath($resourceShortName, $operation, OperationTypeDeprecationHelper::getOperationType($operationType), $operationName); - } elseif (isset($operation['uri_template'])) { - return $operation['uri_template']; - } else { - $routeName = RouteNameGenerator::generate($operationName, $resourceShortName, $operationType); - } - - if (!$route = $this->router->getRouteCollection()->get($routeName)) { - throw new InvalidArgumentException(sprintf('The route "%s" of the resource "%s" was not found.', $routeName, $resourceShortName)); - } - - return $route->getPath(); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/EventListener/ValidateListener.php b/src/Core/Bridge/Symfony/Validator/EventListener/ValidateListener.php deleted file mode 100644 index 7cb7f162fee..00000000000 --- a/src/Core/Bridge/Symfony/Validator/EventListener/ValidateListener.php +++ /dev/null @@ -1,90 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\EventListener; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Symfony\EventListener\ValidateListener as MainValidateListener; -use ApiPlatform\Symfony\Validator\Exception\ValidationException; -use ApiPlatform\Util\RequestAttributesExtractor; -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\Validator\Validator\ValidatorInterface; - -/** - * Validates data. - * - * @deprecated - * - * @author Kévin Dunglas - */ -final class ValidateListener -{ - private $validator; - private $resourceMetadataFactory; - private $container; - - public function __construct(ValidatorInterface $validator, ResourceMetadataFactoryInterface $resourceMetadataFactory, ContainerInterface $container = null) - { - @trigger_error(sprintf('Using "%s" is deprecated since API Platform 2.2 and will not be possible anymore in API Platform 3. Use "%s" instead.', __CLASS__, MainValidateListener::class), \E_USER_DEPRECATED); - - $this->validator = $validator; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->container = $container; - } - - /** - * Validates data returned by the controller if applicable. - * - * @throws ValidationException - */ - public function onKernelView(ViewEvent $event): void - { - $request = $event->getRequest(); - if ( - $request->isMethodSafe() - || $request->isMethod('DELETE') - || !($attributes = RequestAttributesExtractor::extractAttributes($request)) - || !$attributes['receive'] - ) { - return; - } - - $data = $event->getControllerResult(); - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - - $validationGroups = $resourceMetadata->getOperationAttribute($attributes, 'validation_groups'); - - if (!$validationGroups) { - // Fallback to the resource - $validationGroups = $resourceMetadata->getAttributes()['validation_groups'] ?? null; - } - - if ( - $this->container && - \is_string($validationGroups) && - $this->container->has($validationGroups) && - ($service = $this->container->get($validationGroups)) && - \is_callable($service) - ) { - $validationGroups = $service($data); - } elseif (\is_callable($validationGroups)) { - $validationGroups = $validationGroups($data); - } - - $violations = $this->validator->validate($data, null, (array) $validationGroups); - if (0 !== \count($violations)) { - throw new ValidationException($violations); - } - } -} diff --git a/src/Core/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php b/src/Core/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php deleted file mode 100644 index a78906ea488..00000000000 --- a/src/Core/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\EventListener; - -class_exists(\ApiPlatform\Symfony\Validator\EventListener\ValidationExceptionListener::class); - -if (false) { - final class ValidationExceptionListener extends \ApiPlatform\Symfony\Validator\EventListener\ValidationExceptionListener - { - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Exception/ValidationException.php b/src/Core/Bridge/Symfony/Validator/Exception/ValidationException.php deleted file mode 100644 index 7893d93d87b..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Exception/ValidationException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Exception; - -class_exists(\ApiPlatform\Symfony\Validator\Exception\ValidationException::class); - -if (false) { - final class ValidationException extends \ApiPlatform\Symfony\Validator\Exception\ValidationException - { - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestriction.php deleted file mode 100644 index 527f0efb1c8..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestriction.php +++ /dev/null @@ -1,78 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Choice; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaChoiceRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param Choice $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $choices = []; - - if (\is_callable($constraint->callback)) { - $choices = ($constraint->callback)(); - } elseif (\is_array($constraint->choices)) { - $choices = $constraint->choices; - } - - if (!$choices) { - return []; - } - - $restriction = []; - - if (!$constraint->multiple) { - $restriction['enum'] = $choices; - - return $restriction; - } - - $restriction['type'] = 'array'; - - $type = $propertyMetadata->getType() ?? null; - if ($type) { - $restriction['items'] = ['type' => Type::BUILTIN_TYPE_STRING === $type->getBuiltinType() ? 'string' : 'number', 'enum' => $choices]; - } - - if (null !== $constraint->min) { - $restriction['minItems'] = $constraint->min; - } - - if (null !== $constraint->max) { - $restriction['maxItems'] = $constraint->max; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Choice && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_STRING, Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestriction.php deleted file mode 100644 index eecad4e891a..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestriction.php +++ /dev/null @@ -1,96 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Collection; -use Symfony\Component\Validator\Constraints\Optional; -use Symfony\Component\Validator\Constraints\Required; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaCollectionRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * @var iterable - */ - private $restrictionsMetadata; - - /** - * @param iterable $restrictionsMetadata - */ - public function __construct(iterable $restrictionsMetadata = []) - { - $this->restrictionsMetadata = $restrictionsMetadata; - } - - /** - * {@inheritdoc} - * - * @param Collection $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $restriction = [ - 'type' => 'object', - 'properties' => [], - 'additionalProperties' => $constraint->allowExtraFields, - ]; - $required = []; - - foreach ($constraint->fields as $field => $baseConstraint) { - /** @var Required|Optional $baseConstraint */ - if ($baseConstraint instanceof Required && !$constraint->allowMissingFields) { - $required[] = $field; - } - - $restriction['properties'][$field] = $this->mergeConstraintRestrictions($baseConstraint, $propertyMetadata); - } - - if ($required) { - $restriction['required'] = $required; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Collection; - } - - /** - * @param Required|Optional $constraint - */ - private function mergeConstraintRestrictions(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $propertyRestrictions = []; - $nestedConstraints = method_exists($constraint, 'getNestedContraints') ? $constraint->getNestedContraints() : $constraint->constraints; - - foreach ($nestedConstraints as $nestedConstraint) { - foreach ($this->restrictionsMetadata as $restrictionMetadata) { - if ($restrictionMetadata->supports($nestedConstraint, $propertyMetadata) && !empty($nestedConstraintRestriction = $restrictionMetadata->create($nestedConstraint, $propertyMetadata))) { - $propertyRestrictions[] = $nestedConstraintRestriction; - } - } - } - - return array_merge([], ...$propertyRestrictions); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestriction.php deleted file mode 100644 index d09f5835b0b..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestriction.php +++ /dev/null @@ -1,52 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Count; - -/** - * @author Tomas Norkūnas - */ -class PropertySchemaCountRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param Count $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $restriction = []; - - if (null !== $constraint->min) { - $restriction['minItems'] = $constraint->min; - } - - if (null !== $constraint->max) { - $restriction['maxItems'] = $constraint->max; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Count; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormat.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormat.php deleted file mode 100644 index c6cec232b6f..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormat.php +++ /dev/null @@ -1,67 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Email; -use Symfony\Component\Validator\Constraints\Ip; -use Symfony\Component\Validator\Constraints\Ulid; -use Symfony\Component\Validator\Constraints\Uuid; - -/** - * Class PropertySchemaFormat. - * - * @author Andrii Penchuk penja7@gmail.com - */ -class PropertySchemaFormat implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - if ($constraint instanceof Email) { - return ['format' => 'email']; - } - - if ($constraint instanceof Uuid) { - return ['format' => 'uuid']; - } - - if ($constraint instanceof Ulid) { - return ['format' => 'ulid']; - } - - if ($constraint instanceof Ip) { - if ($constraint->version === $constraint::V4) { - return ['format' => 'ipv4']; - } - - return ['format' => 'ipv6']; - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - $schema = $propertyMetadata->getSchema(); - - return empty($schema['format']) && ($constraint instanceof Email || $constraint instanceof Uuid || $constraint instanceof Ulid || $constraint instanceof Ip); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestriction.php deleted file mode 100644 index c3d63b5a9e0..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestriction.php +++ /dev/null @@ -1,45 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaGreaterThanOrEqualRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param GreaterThanOrEqual $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return [ - 'minimum' => $constraint->value, - ]; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof GreaterThanOrEqual && is_numeric($constraint->value) && ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestriction.php deleted file mode 100644 index edde8500593..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestriction.php +++ /dev/null @@ -1,46 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\GreaterThan; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaGreaterThanRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param GreaterThan $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return [ - 'minimum' => $constraint->value, - 'exclusiveMinimum' => true, - ]; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof GreaterThan && is_numeric($constraint->value) && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLengthRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLengthRestriction.php deleted file mode 100644 index 47acf0d8f9e..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLengthRestriction.php +++ /dev/null @@ -1,53 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Length; - -/** - * Class PropertySchemaLengthRestrictions. - * - * @author Andrii Penchuk penja7@gmail.com - */ -class PropertySchemaLengthRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $restriction = []; - - if (isset($constraint->min)) { - $restriction['minLength'] = (int) $constraint->min; - } - - if (isset($constraint->max)) { - $restriction['maxLength'] = (int) $constraint->max; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Length && null !== ($type = $propertyMetadata->getType()) && Type::BUILTIN_TYPE_STRING === $type->getBuiltinType(); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestriction.php deleted file mode 100644 index 1cb0cbfe99d..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestriction.php +++ /dev/null @@ -1,45 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\LessThanOrEqual; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaLessThanOrEqualRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param LessThanOrEqual $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return [ - 'maximum' => $constraint->value, - ]; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof LessThanOrEqual && is_numeric($constraint->value) && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestriction.php deleted file mode 100644 index ee1aee51580..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestriction.php +++ /dev/null @@ -1,46 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\LessThan; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaLessThanRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param LessThan $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return [ - 'maximum' => $constraint->value, - 'exclusiveMaximum' => true, - ]; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof LessThan && is_numeric($constraint->value) && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestriction.php deleted file mode 100644 index badbbcf7a25..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestriction.php +++ /dev/null @@ -1,70 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\AtLeastOneOf; - -/** - * @author Alan Poulain - */ -final class PropertySchemaOneOfRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * @var iterable - */ - private $restrictionsMetadata; - - /** - * @param iterable $restrictionsMetadata - */ - public function __construct(iterable $restrictionsMetadata = []) - { - $this->restrictionsMetadata = $restrictionsMetadata; - } - - /** - * {@inheritdoc} - * - * @param AtLeastOneOf $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $oneOfConstraints = method_exists($constraint, 'getNestedContraints') ? $constraint->getNestedContraints() : $constraint->constraints; - $oneOfRestrictions = []; - - foreach ($oneOfConstraints as $oneOfConstraint) { - foreach ($this->restrictionsMetadata as $restrictionMetadata) { - if ($restrictionMetadata->supports($oneOfConstraint, $propertyMetadata) && !empty($oneOfRestriction = $restrictionMetadata->create($oneOfConstraint, $propertyMetadata))) { - $oneOfRestrictions[] = $oneOfRestriction; - } - } - } - - if (!empty($oneOfRestrictions)) { - return ['oneOf' => $oneOfRestrictions]; - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof AtLeastOneOf; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestriction.php deleted file mode 100644 index 51f78cf3e36..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestriction.php +++ /dev/null @@ -1,51 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Range; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaRangeRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $restriction = []; - - if (isset($constraint->min) && is_numeric($constraint->min)) { - $restriction['minimum'] = $constraint->min; - } - - if (isset($constraint->max) && is_numeric($constraint->max)) { - $restriction['maximum'] = $constraint->max; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Range && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestriction.php deleted file mode 100644 index 5a075b9398e..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestriction.php +++ /dev/null @@ -1,42 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Regex; - -/** - * Class PropertySchemaRegexRestriction. - * - * @author Andrii Penchuk penja7@gmail.com - */ -class PropertySchemaRegexRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return $constraint instanceof Regex && $constraint->getHtmlPattern() ? ['pattern' => '^('.$constraint->getHtmlPattern().')$'] : []; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Regex && $constraint->match; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRestrictionMetadataInterface.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRestrictionMetadataInterface.php deleted file mode 100644 index 2486342de40..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRestrictionMetadataInterface.php +++ /dev/null @@ -1,43 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\Validator\Constraint; - -/** - * Interface PropertySchemaRestrictionsInterface. - * - * @author Andrii Penchuk penja7@gmail.com - */ -interface PropertySchemaRestrictionMetadataInterface -{ - /** - * Creates json schema restrictions based on the validation constraints. - * - * @param Constraint $constraint The validation constraint - * @param PropertyMetadata $propertyMetadata The property metadata - * - * @return array The array of restrictions - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array; - - /** - * Is the constraint supported by the schema restriction? - * - * @param Constraint $constraint The validation constraint - * @param PropertyMetadata $propertyMetadata The property metadata - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool; -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestriction.php deleted file mode 100644 index 8a7a0359669..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestriction.php +++ /dev/null @@ -1,40 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Unique; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaUniqueRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return ['uniqueItems' => true]; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Unique; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php deleted file mode 100644 index b5953ace1bf..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php +++ /dev/null @@ -1,199 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property; - -use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Bic; -use Symfony\Component\Validator\Constraints\CardScheme; -use Symfony\Component\Validator\Constraints\Compound; -use Symfony\Component\Validator\Constraints\Currency; -use Symfony\Component\Validator\Constraints\Date; -use Symfony\Component\Validator\Constraints\DateTime; -use Symfony\Component\Validator\Constraints\Email; -use Symfony\Component\Validator\Constraints\File; -use Symfony\Component\Validator\Constraints\Iban; -use Symfony\Component\Validator\Constraints\Image; -use Symfony\Component\Validator\Constraints\Isbn; -use Symfony\Component\Validator\Constraints\Issn; -use Symfony\Component\Validator\Constraints\NotBlank; -use Symfony\Component\Validator\Constraints\NotNull; -use Symfony\Component\Validator\Constraints\Sequentially; -use Symfony\Component\Validator\Constraints\Time; -use Symfony\Component\Validator\Constraints\Url; -use Symfony\Component\Validator\Constraints\Uuid; -use Symfony\Component\Validator\Mapping\ClassMetadataInterface as ValidatorClassMetadataInterface; -use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface as ValidatorMetadataFactoryInterface; -use Symfony\Component\Validator\Mapping\PropertyMetadataInterface as ValidatorPropertyMetadataInterface; - -/** - * Decorates a metadata loader using the validator. - * - * @author Kévin Dunglas - */ -final class ValidatorPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - /** - * @var string[] A list of constraint classes making the entity required - */ - public const REQUIRED_CONSTRAINTS = [NotBlank::class, NotNull::class]; - - public const SCHEMA_MAPPED_CONSTRAINTS = [ - Url::class => 'http://schema.org/url', - Email::class => 'http://schema.org/email', - Uuid::class => 'http://schema.org/identifier', - CardScheme::class => 'http://schema.org/identifier', - Bic::class => 'http://schema.org/identifier', - Iban::class => 'http://schema.org/identifier', - Date::class => 'http://schema.org/Date', - DateTime::class => 'http://schema.org/DateTime', - Time::class => 'http://schema.org/Time', - Image::class => 'http://schema.org/image', - File::class => 'http://schema.org/MediaObject', - Currency::class => 'http://schema.org/priceCurrency', - Isbn::class => 'http://schema.org/isbn', - Issn::class => 'http://schema.org/issn', - ]; - - private $decorated; - private $validatorMetadataFactory; - /** - * @var iterable - */ - private $restrictionsMetadata; - - /** - * @param PropertySchemaRestrictionMetadataInterface[] $restrictionsMetadata - */ - public function __construct(ValidatorMetadataFactoryInterface $validatorMetadataFactory, PropertyMetadataFactoryInterface $decorated, iterable $restrictionsMetadata = []) - { - $this->validatorMetadataFactory = $validatorMetadataFactory; - $this->decorated = $decorated; - $this->restrictionsMetadata = $restrictionsMetadata; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - $required = $propertyMetadata->isRequired(); - $iri = $propertyMetadata->getIri(); - $schema = $propertyMetadata->getSchema(); - - if (null !== $required && null !== $iri && null !== $schema) { - return $propertyMetadata; - } - - $validatorClassMetadata = $this->validatorMetadataFactory->getMetadataFor($resourceClass); - - if (!$validatorClassMetadata instanceof ValidatorClassMetadataInterface) { - throw new \UnexpectedValueException(sprintf('Validator class metadata expected to be of type "%s".', ValidatorClassMetadataInterface::class)); - } - - $validationGroups = $this->getValidationGroups($validatorClassMetadata, $options); - $restrictions = []; - - foreach ($validatorClassMetadata->getPropertyMetadata($property) as $validatorPropertyMetadata) { - foreach ($this->getPropertyConstraints($validatorPropertyMetadata, $validationGroups) as $constraint) { - if (null === $required && $this->isRequired($constraint)) { - $required = true; - } - - if (null === $iri) { - $iri = self::SCHEMA_MAPPED_CONSTRAINTS[\get_class($constraint)] ?? null; - } - - foreach ($this->restrictionsMetadata as $restrictionMetadata) { - if ($restrictionMetadata->supports($constraint, $propertyMetadata)) { - $restrictions[] = $restrictionMetadata->create($constraint, $propertyMetadata); - } - } - } - } - - $propertyMetadata = $propertyMetadata->withIri($iri)->withRequired($required ?? false); - - if (!empty($restrictions)) { - if (null === $schema) { - $schema = []; - } - - $schema += array_merge(...$restrictions); - $propertyMetadata = $propertyMetadata->withSchema($schema); - } - - return $propertyMetadata; - } - - /** - * Returns the list of validation groups. - */ - private function getValidationGroups(ValidatorClassMetadataInterface $classMetadata, array $options): array - { - if (isset($options['validation_groups'])) { - return $options['validation_groups']; - } - - if (!method_exists($classMetadata, 'getDefaultGroup')) { - throw new \UnexpectedValueException(sprintf('Validator class metadata expected to have method "%s".', 'getDefaultGroup')); - } - - return [$classMetadata->getDefaultGroup()]; - } - - /** - * Tests if the property is required because of its validation groups. - */ - private function getPropertyConstraints( - ValidatorPropertyMetadataInterface $validatorPropertyMetadata, - array $groups - ): array { - $constraints = []; - - foreach ($groups as $validationGroup) { - if (!\is_string($validationGroup)) { - continue; - } - - foreach ($validatorPropertyMetadata->findConstraints($validationGroup) as $propertyConstraint) { - if ($propertyConstraint instanceof Sequentially || $propertyConstraint instanceof Compound) { - $constraints[] = method_exists($propertyConstraint, 'getNestedContraints') ? $propertyConstraint->getNestedContraints() : $propertyConstraint->getNestedConstraints(); - } else { - $constraints[] = [$propertyConstraint]; - } - } - } - - return array_merge([], ...$constraints); - } - - /** - * Is this constraint making the related property required? - */ - private function isRequired(Constraint $constraint): bool - { - foreach (self::REQUIRED_CONSTRAINTS as $requiredConstraint) { - if ($constraint instanceof $requiredConstraint) { - return true; - } - } - - return false; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Validator.php b/src/Core/Bridge/Symfony/Validator/Validator.php deleted file mode 100644 index 2fb61bd0647..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Validator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Bridge\Symfony\Validator; - -class_exists(\ApiPlatform\Symfony\Validator\Validator::class); - -if (false) { - class Validator extends \ApiPlatform\Symfony\Validator\Validator - { - } -} diff --git a/src/Core/Cache/CachedTrait.php b/src/Core/Cache/CachedTrait.php deleted file mode 100644 index 3f6ec41f861..00000000000 --- a/src/Core/Cache/CachedTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Cache; - -class_exists(\ApiPlatform\Util\CachedTrait::class); - -if (false) { - trait CachedTrait - { - use \ApiPlatform\Util\CachedTrait; - } -} diff --git a/src/Core/DataPersister/ChainDataPersister.php b/src/Core/DataPersister/ChainDataPersister.php deleted file mode 100644 index 85e44bb4949..00000000000 --- a/src/Core/DataPersister/ChainDataPersister.php +++ /dev/null @@ -1,87 +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); - -namespace ApiPlatform\Core\DataPersister; - -/** - * Chained data persisters. - * - * @author Baptiste Meyer - */ -final class ChainDataPersister implements ContextAwareDataPersisterInterface -{ - /** - * @var iterable - * - * @internal - */ - public $persisters; - - /** - * @param DataPersisterInterface[] $persisters - */ - public function __construct(iterable $persisters) - { - $this->persisters = $persisters; - } - - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - foreach ($this->persisters as $persister) { - if ($persister->supports($data, $context)) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []) - { - foreach ($this->persisters as $persister) { - if ($persister->supports($data, $context)) { - $data = $persister->persist($data, $context); - if ($persister instanceof ResumableDataPersisterInterface && $persister->resumable($context)) { - continue; - } - - return $data; - } - } - - return $data; - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []) - { - foreach ($this->persisters as $persister) { - if ($persister->supports($data, $context)) { - $persister->remove($data, $context); - if ($persister instanceof ResumableDataPersisterInterface && $persister->resumable($context)) { - continue; - } - - return; - } - } - } -} diff --git a/src/Core/DataPersister/ContextAwareDataPersisterInterface.php b/src/Core/DataPersister/ContextAwareDataPersisterInterface.php deleted file mode 100644 index a581418710b..00000000000 --- a/src/Core/DataPersister/ContextAwareDataPersisterInterface.php +++ /dev/null @@ -1,37 +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); - -namespace ApiPlatform\Core\DataPersister; - -/** - * Manages data persistence. - * - * @author Antoine Bluchet - */ -interface ContextAwareDataPersisterInterface extends DataPersisterInterface -{ - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool; - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []); - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []); -} diff --git a/src/Core/DataPersister/DataPersisterInterface.php b/src/Core/DataPersister/DataPersisterInterface.php deleted file mode 100644 index dc2cee68362..00000000000 --- a/src/Core/DataPersister/DataPersisterInterface.php +++ /dev/null @@ -1,45 +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); - -namespace ApiPlatform\Core\DataPersister; - -/** - * Manages data persistence. - * - * @author Baptiste Meyer - */ -interface DataPersisterInterface -{ - /** - * Is the data supported by the persister? - * - * @param mixed $data - */ - public function supports($data): bool; - - /** - * Persists the data. - * - * @param mixed $data - * - * @return object|void Void will not be supported in API Platform 3, an object should always be returned - */ - public function persist($data); - - /** - * Removes the data. - * - * @param mixed $data - */ - public function remove($data); -} diff --git a/src/Core/DataPersister/ResumableDataPersisterInterface.php b/src/Core/DataPersister/ResumableDataPersisterInterface.php deleted file mode 100644 index abfc39c1f84..00000000000 --- a/src/Core/DataPersister/ResumableDataPersisterInterface.php +++ /dev/null @@ -1,26 +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); - -namespace ApiPlatform\Core\DataPersister; - -/** - * Control the resumability of the data persister chain. - */ -interface ResumableDataPersisterInterface -{ - /** - * Should we continue calling the next DataPersister or stop after this one? - * Defaults to stop the ChainDatapersister if this interface is not implemented. - */ - public function resumable(array $context = []): bool; -} diff --git a/src/Core/DataProvider/ArrayPaginator.php b/src/Core/DataProvider/ArrayPaginator.php deleted file mode 100644 index c80512b2e21..00000000000 --- a/src/Core/DataProvider/ArrayPaginator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\DataProvider; - -class_exists(\ApiPlatform\State\Pagination\ArrayPaginator::class); - -if (false) { - final class ArrayPaginator extends \ApiPlatform\State\Pagination\ArrayPaginator - { - } -} diff --git a/src/Core/DataProvider/ChainCollectionDataProvider.php b/src/Core/DataProvider/ChainCollectionDataProvider.php deleted file mode 100644 index 0f0d402a267..00000000000 --- a/src/Core/DataProvider/ChainCollectionDataProvider.php +++ /dev/null @@ -1,56 +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); - -namespace ApiPlatform\Core\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Tries each configured data provider and returns the result of the first able to handle the resource class. - * - * @author Kévin Dunglas - */ -final class ChainCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - use RestrictDataProviderTrait; - - /** - * @param CollectionDataProviderInterface[] $dataProviders - */ - public function __construct(iterable $dataProviders) - { - $this->dataProviders = $dataProviders; - } - - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - foreach ($this->dataProviders as $dataProvider) { - try { - if ($dataProvider instanceof RestrictedDataProviderInterface - && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - return $dataProvider->getCollection($resourceClass, $operationName, $context); - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"', ResourceClassNotSupportedException::class, RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return []; - } -} diff --git a/src/Core/DataProvider/ChainItemDataProvider.php b/src/Core/DataProvider/ChainItemDataProvider.php deleted file mode 100644 index 5be72883a41..00000000000 --- a/src/Core/DataProvider/ChainItemDataProvider.php +++ /dev/null @@ -1,66 +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); - -namespace ApiPlatform\Core\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Tries each configured data provider and returns the result of the first able to handle the resource class. - * - * @author Kévin Dunglas - */ -final class ChainItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - use RestrictDataProviderTrait; - - /** - * @param ItemDataProviderInterface[] $dataProviders - */ - public function __construct(iterable $dataProviders) - { - $this->dataProviders = $dataProviders; - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - foreach ($this->dataProviders as $dataProvider) { - try { - if ($dataProvider instanceof RestrictedDataProviderInterface - && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - $identifier = $id; - if (!$dataProvider instanceof DenormalizedIdentifiersAwareItemDataProviderInterface && $identifier && \is_array($identifier)) { - if (\count($identifier) > 1) { - @trigger_error(sprintf('Receiving "$id" as non-array in an item data provider is deprecated in 2.3 in favor of implementing "%s".', DenormalizedIdentifiersAwareItemDataProviderInterface::class), \E_USER_DEPRECATED); - $identifier = http_build_query($identifier, '', ';'); - } else { - $identifier = current($identifier); - } - } - - return $dataProvider->getItem($resourceClass, $identifier, $operationName, $context); - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" is deprecated in favor of implementing "%s"', \get_class($e), RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return null; - } -} diff --git a/src/Core/DataProvider/ChainSubresourceDataProvider.php b/src/Core/DataProvider/ChainSubresourceDataProvider.php deleted file mode 100644 index 2a44219b459..00000000000 --- a/src/Core/DataProvider/ChainSubresourceDataProvider.php +++ /dev/null @@ -1,60 +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); - -namespace ApiPlatform\Core\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Tries each configured data provider and returns the result of the first able to handle the resource class. - * - * @author Antoine Bluchet - */ -final class ChainSubresourceDataProvider implements SubresourceDataProviderInterface -{ - /** - * @var iterable - * - * @internal - */ - public $dataProviders; - - /** - * @param SubresourceDataProviderInterface[] $dataProviders - */ - public function __construct(iterable $dataProviders) - { - $this->dataProviders = $dataProviders; - } - - /** - * {@inheritdoc} - */ - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - foreach ($this->dataProviders as $dataProvider) { - try { - if ($dataProvider instanceof RestrictedDataProviderInterface && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - return $dataProvider->getSubresource($resourceClass, $identifiers, $context, $operationName); - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"', ResourceClassNotSupportedException::class, RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return ($context['collection'] ?? false) ? [] : null; - } -} diff --git a/src/Core/DataProvider/CollectionDataProviderInterface.php b/src/Core/DataProvider/CollectionDataProviderInterface.php deleted file mode 100644 index abd765cf758..00000000000 --- a/src/Core/DataProvider/CollectionDataProviderInterface.php +++ /dev/null @@ -1,33 +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); - -namespace ApiPlatform\Core\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Retrieves items from a persistence layer. - * - * @author Kévin Dunglas - */ -interface CollectionDataProviderInterface -{ - /** - * Retrieves a collection. - * - * @throws ResourceClassNotSupportedException - * - * @return iterable - */ - public function getCollection(string $resourceClass, string $operationName = null); -} diff --git a/src/Core/DataProvider/ContextAwareCollectionDataProviderInterface.php b/src/Core/DataProvider/ContextAwareCollectionDataProviderInterface.php deleted file mode 100644 index 5389ec9bf5d..00000000000 --- a/src/Core/DataProvider/ContextAwareCollectionDataProviderInterface.php +++ /dev/null @@ -1,27 +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); - -namespace ApiPlatform\Core\DataProvider; - -/** - * Retrieves items from a persistence layer and allow to pass a context to it. - * - * @author Kévin Dunglas - */ -interface ContextAwareCollectionDataProviderInterface extends CollectionDataProviderInterface -{ - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []); -} diff --git a/src/Core/DataProvider/DenormalizedIdentifiersAwareItemDataProviderInterface.php b/src/Core/DataProvider/DenormalizedIdentifiersAwareItemDataProviderInterface.php deleted file mode 100644 index 07067dc0b25..00000000000 --- a/src/Core/DataProvider/DenormalizedIdentifiersAwareItemDataProviderInterface.php +++ /dev/null @@ -1,27 +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); - -namespace ApiPlatform\Core\DataProvider; - -/** - * Marks data providers able to deal with complex identifiers denormalized as an array. - * - * @author Anthony GRASSIOT - */ -interface DenormalizedIdentifiersAwareItemDataProviderInterface extends ItemDataProviderInterface -{ - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, /* array */ $id, string $operationName = null, array $context = []); -} diff --git a/src/Core/DataProvider/ItemDataProviderInterface.php b/src/Core/DataProvider/ItemDataProviderInterface.php deleted file mode 100644 index 5fde5bfbe55..00000000000 --- a/src/Core/DataProvider/ItemDataProviderInterface.php +++ /dev/null @@ -1,35 +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); - -namespace ApiPlatform\Core\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Retrieves items from a persistence layer. - * - * @author Kévin Dunglas - */ -interface ItemDataProviderInterface -{ - /** - * Retrieves an item. - * - * @param array|int|object|string $id - * - * @throws ResourceClassNotSupportedException - * - * @return object|null - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []); -} diff --git a/src/Core/DataProvider/OperationDataProviderTrait.php b/src/Core/DataProvider/OperationDataProviderTrait.php deleted file mode 100644 index 32ad28166d8..00000000000 --- a/src/Core/DataProvider/OperationDataProviderTrait.php +++ /dev/null @@ -1,132 +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); - -namespace ApiPlatform\Core\DataProvider; - -use ApiPlatform\Core\Identifier\CompositeIdentifierParser; -use ApiPlatform\Core\Identifier\ContextAwareIdentifierConverterInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\RuntimeException; - -/** - * @internal - */ -trait OperationDataProviderTrait -{ - /** - * @var CollectionDataProviderInterface - */ - private $collectionDataProvider; - - /** - * @var ItemDataProviderInterface - */ - private $itemDataProvider; - - /** - * @var SubresourceDataProviderInterface|null - */ - private $subresourceDataProvider; - - /** - * @var IdentifierConverterInterface|null - */ - private $identifierConverter; - - /** - * Retrieves data for a collection operation. - */ - private function getCollectionData(array $attributes, array $context): iterable - { - return $this->collectionDataProvider->getCollection($attributes['resource_class'], $attributes['collection_operation_name'], $context); - } - - /** - * Gets data for an item operation. - * - * @param mixed $identifiers - * - * @return object|null - */ - private function getItemData($identifiers, array $attributes, array $context) - { - return $this->itemDataProvider->getItem($attributes['resource_class'], $identifiers, $attributes['item_operation_name'], $context); - } - - /** - * Gets data for a nested operation. - * - * @param mixed $identifiers - * - * @throws RuntimeException - * - * @return array|object|null - */ - private function getSubresourceData($identifiers, array $attributes, array $context) - { - if (null === $this->subresourceDataProvider) { - throw new RuntimeException('Subresources not supported'); - } - - // TODO: SubresourceDataProvider wants: ['id' => ['id' => 1], 'relatedDummies' => ['id' => 2]], identifiers is ['id' => 1, 'relatedDummies' => 2] - $subresourceIdentifiers = []; - foreach ($attributes['identifiers'] as $parameterName => [$class, $property]) { - if (false !== ($attributes['identifiers'][$parameterName][2] ?? null)) { - $subresourceIdentifiers[$parameterName] = [$property => $identifiers[$parameterName]]; - } - } - - return $this->subresourceDataProvider->getSubresource($attributes['resource_class'], $subresourceIdentifiers, $attributes['subresource_context'] + $context, $attributes['subresource_operation_name']); - } - - /** - * @param array $parameters - usually comes from $request->attributes->all() - * - * @throws InvalidIdentifierException - */ - private function extractIdentifiers(array $parameters, array $attributes) - { - $identifiersKeys = $attributes['identifiers'] ?? ['id' => [$attributes['resource_class'], 'id']]; - $identifiers = []; - - $identifiersNumber = \count($identifiersKeys); - foreach ($identifiersKeys as $parameterName => $identifiedBy) { - if (!isset($parameters[$parameterName])) { - if ($attributes['has_composite_identifier']) { - $identifiers = CompositeIdentifierParser::parse($parameters['id']); - if (($currentIdentifiersNumber = \count($identifiers)) !== $identifiersNumber) { - throw new InvalidIdentifierException(sprintf('Expected %d identifiers, got %d', $identifiersNumber, $currentIdentifiersNumber)); - } - - return $this->identifierConverter->convert($identifiers, $identifiedBy[0]); - } - - // TODO: Subresources tuple may have a third item representing if it is a "collection", this behavior will be removed in 3.0 - if (false === ($identifiedBy[2] ?? null)) { - continue; - } - - throw new InvalidIdentifierException(sprintf('Parameter "%s" not found', $parameterName)); - } - - $identifiers[$parameterName] = $parameters[$parameterName]; - } - - if ($this->identifierConverter instanceof ContextAwareIdentifierConverterInterface) { - return $this->identifierConverter->convert($identifiers, $attributes['resource_class'], ['identifiers' => $identifiersKeys]); - } - - return $this->identifierConverter->convert($identifiers, $attributes['resource_class']); - } -} diff --git a/src/Core/DataProvider/Pagination.php b/src/Core/DataProvider/Pagination.php deleted file mode 100644 index f80907cf548..00000000000 --- a/src/Core/DataProvider/Pagination.php +++ /dev/null @@ -1,271 +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); - -namespace ApiPlatform\Core\DataProvider; - -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Core\Exception\ResourceClassNotFoundException; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; - -/** - * Pagination configuration. - * - * @author Baptiste Meyer - */ -final class Pagination -{ - private $options; - private $graphQlOptions; - private $resourceMetadataFactory; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, array $options = [], array $graphQlOptions = []) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->options = array_merge([ - 'enabled' => true, - 'client_enabled' => false, - 'client_items_per_page' => false, - 'items_per_page' => 30, - 'page_default' => 1, - 'page_parameter_name' => 'page', - 'enabled_parameter_name' => 'pagination', - 'items_per_page_parameter_name' => 'itemsPerPage', - 'maximum_items_per_page' => null, - 'partial' => false, - 'client_partial' => false, - 'partial_parameter_name' => 'partial', - ], $options); - $this->graphQlOptions = array_merge([ - 'enabled' => true, - ], $graphQlOptions); - } - - /** - * Gets the current page. - * - * @throws InvalidArgumentException - */ - public function getPage(array $context = []): int - { - $page = (int) $this->getParameterFromContext( - $context, - $this->options['page_parameter_name'], - $this->options['page_default'] - ); - - if (1 > $page) { - throw new InvalidArgumentException('Page should not be less than 1'); - } - - return $page; - } - - /** - * Gets the current offset. - */ - public function getOffset(string $resourceClass = null, string $operationName = null, array $context = []): int - { - $graphql = (bool) ($context['graphql_operation_name'] ?? false); - - $limit = $this->getLimit($resourceClass, $operationName, $context); - - if ($graphql && null !== ($after = $this->getParameterFromContext($context, 'after'))) { - return false === ($after = base64_decode($after, true)) ? 0 : (int) $after + 1; - } - - if ($graphql && null !== ($before = $this->getParameterFromContext($context, 'before'))) { - return ($offset = (false === ($before = base64_decode($before, true)) ? 0 : (int) $before - $limit)) < 0 ? 0 : $offset; - } - - if ($graphql && null !== ($last = $this->getParameterFromContext($context, 'last'))) { - return ($offset = ($context['count'] ?? 0) - $last) < 0 ? 0 : $offset; - } - - $offset = ($this->getPage($context) - 1) * $limit; - - if (!\is_int($offset)) { - throw new InvalidArgumentException('Page parameter is too large.'); - } - - return $offset; - } - - /** - * Gets the current limit. - * - * @throws InvalidArgumentException - */ - public function getLimit(string $resourceClass = null, string $operationName = null, array $context = []): int - { - $graphql = (bool) ($context['graphql_operation_name'] ?? false); - - $limit = $this->options['items_per_page']; - $clientLimit = $this->options['client_items_per_page']; - - if (null !== $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $limit = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', $limit, true); - $clientLimit = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $clientLimit, true); - } - - if ($graphql && null !== ($first = $this->getParameterFromContext($context, 'first'))) { - $limit = $first; - } - - if ($graphql && null !== ($last = $this->getParameterFromContext($context, 'last'))) { - $limit = $last; - } - - if ($graphql && null !== ($before = $this->getParameterFromContext($context, 'before')) - && (false === ($before = base64_decode($before, true)) ? 0 : (int) $before - $limit) < 0) { - $limit = (int) $before; - } - - if ($clientLimit) { - $limit = (int) $this->getParameterFromContext($context, $this->options['items_per_page_parameter_name'], $limit); - $maxItemsPerPage = null; - - if (null !== $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'maximum_items_per_page', null, true); - if (null !== $maxItemsPerPage) { - @trigger_error('The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3.', \E_USER_DEPRECATED); - } - $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_maximum_items_per_page', $maxItemsPerPage ?? $this->options['maximum_items_per_page'], true); - } - - if (null !== $maxItemsPerPage && $limit > $maxItemsPerPage) { - $limit = $maxItemsPerPage; - } - } - - if (0 > $limit) { - throw new InvalidArgumentException('Limit should not be less than 0'); - } - - return $limit; - } - - /** - * Gets info about the pagination. - * - * Returns an array with the following info as values: - * - the page {@see Pagination::getPage()} - * - the offset {@see Pagination::getOffset()} - * - the limit {@see Pagination::getLimit()} - * - * @throws InvalidArgumentException - */ - public function getPagination(string $resourceClass = null, string $operationName = null, array $context = []): array - { - $page = $this->getPage($context); - $limit = $this->getLimit($resourceClass, $operationName, $context); - - if (0 === $limit && 1 < $page) { - throw new InvalidArgumentException('Page should not be greater than 1 if limit is equal to 0'); - } - - return [$page, $this->getOffset($resourceClass, $operationName, $context), $limit]; - } - - /** - * Is the pagination enabled? - */ - public function isEnabled(string $resourceClass = null, string $operationName = null, array $context = []): bool - { - return $this->getEnabled($context, $resourceClass, $operationName); - } - - /** - * Is the pagination enabled for GraphQL? - */ - public function isGraphQlEnabled(?string $resourceClass = null, ?string $operationName = null, array $context = []): bool - { - return $this->getGraphQlEnabled($resourceClass, $operationName); - } - - /** - * Is the partial pagination enabled? - */ - public function isPartialEnabled(string $resourceClass = null, string $operationName = null, array $context = []): bool - { - return $this->getEnabled($context, $resourceClass, $operationName, true); - } - - public function getOptions(): array - { - return $this->options; - } - - public function getGraphQlPaginationType(string $resourceClass, string $operationName): string - { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - return 'cursor'; - } - - return (string) $resourceMetadata->getGraphqlAttribute($operationName, 'pagination_type', 'cursor', true); - } - - /** - * Is the classic or partial pagination enabled? - */ - private function getEnabled(array $context, string $resourceClass = null, string $operationName = null, bool $partial = false): bool - { - $enabled = $this->options[$partial ? 'partial' : 'enabled']; - $clientEnabled = $this->options[$partial ? 'client_partial' : 'client_enabled']; - - if (null !== $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $enabled = $resourceMetadata->getCollectionOperationAttribute($operationName, $partial ? 'pagination_partial' : 'pagination_enabled', $enabled, true); - - $clientEnabled = $resourceMetadata->getCollectionOperationAttribute($operationName, $partial ? 'pagination_client_partial' : 'pagination_client_enabled', $clientEnabled, true); - } - - if ($clientEnabled) { - return filter_var($this->getParameterFromContext($context, $this->options[$partial ? 'partial_parameter_name' : 'enabled_parameter_name'], $enabled), \FILTER_VALIDATE_BOOLEAN); - } - - return (bool) $enabled; - } - - private function getGraphQlEnabled(?string $resourceClass, ?string $operationName): bool - { - $enabled = $this->graphQlOptions['enabled']; - - if (null !== $resourceClass) { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - return $enabled; - } - - return (bool) $resourceMetadata->getGraphqlAttribute($operationName, 'pagination_enabled', $enabled, true); - } - - return $enabled; - } - - /** - * Gets the given pagination parameter name from the given context. - * - * @param mixed|null $default - */ - private function getParameterFromContext(array $context, string $parameterName, $default = null) - { - $filters = $context['filters'] ?? []; - - return \array_key_exists($parameterName, $filters) ? $filters[$parameterName] : $default; - } -} diff --git a/src/Core/DataProvider/PaginationOptions.php b/src/Core/DataProvider/PaginationOptions.php deleted file mode 100644 index 504ef049c8a..00000000000 --- a/src/Core/DataProvider/PaginationOptions.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\DataProvider; - -class_exists(\ApiPlatform\State\Pagination\PaginationOptions::class); - -if (false) { - final class PaginationOptions extends \ApiPlatform\State\Pagination\PaginationOptions - { - } -} diff --git a/src/Core/DataProvider/RestrictDataProviderTrait.php b/src/Core/DataProvider/RestrictDataProviderTrait.php deleted file mode 100644 index 4e2570b16f4..00000000000 --- a/src/Core/DataProvider/RestrictDataProviderTrait.php +++ /dev/null @@ -1,32 +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); - -namespace ApiPlatform\Core\DataProvider; - -trait RestrictDataProviderTrait -{ - /** @internal */ - public $dataProviders = []; - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - foreach ($this->dataProviders as $dataProvider) { - if ($dataProvider instanceof RestrictedDataProviderInterface - && $dataProvider->supports($resourceClass, $operationName, $context)) { - return true; - } - } - - return false; - } -} diff --git a/src/Core/DataProvider/RestrictedDataProviderInterface.php b/src/Core/DataProvider/RestrictedDataProviderInterface.php deleted file mode 100644 index 5eb5a560540..00000000000 --- a/src/Core/DataProvider/RestrictedDataProviderInterface.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\DataProvider; - -/** - * Restricts a data provider based on a condition. - */ -interface RestrictedDataProviderInterface -{ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool; -} diff --git a/src/Core/DataProvider/SerializerAwareDataProviderInterface.php b/src/Core/DataProvider/SerializerAwareDataProviderInterface.php deleted file mode 100644 index b3989c5d52d..00000000000 --- a/src/Core/DataProvider/SerializerAwareDataProviderInterface.php +++ /dev/null @@ -1,26 +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); - -namespace ApiPlatform\Core\DataProvider; - -use Psr\Container\ContainerInterface; - -/** - * Injects serializer in data providers. - * - * @author Vincent Chalamon - */ -interface SerializerAwareDataProviderInterface -{ - public function setSerializerLocator(ContainerInterface $serializerLocator); -} diff --git a/src/Core/DataProvider/SerializerAwareDataProviderTrait.php b/src/Core/DataProvider/SerializerAwareDataProviderTrait.php deleted file mode 100644 index 014012bad08..00000000000 --- a/src/Core/DataProvider/SerializerAwareDataProviderTrait.php +++ /dev/null @@ -1,42 +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); - -namespace ApiPlatform\Core\DataProvider; - -use Psr\Container\ContainerInterface; -use Symfony\Component\Serializer\SerializerInterface; - -/** - * Injects serializer in data providers. - * - * @author Vincent Chalamon - */ -trait SerializerAwareDataProviderTrait -{ - /** - * @internal - * - * @var ContainerInterface - */ - private $serializerLocator; - - public function setSerializerLocator(ContainerInterface $serializerLocator): void - { - $this->serializerLocator = $serializerLocator; - } - - private function getSerializer(): SerializerInterface - { - return $this->serializerLocator->get('serializer'); - } -} diff --git a/src/Core/DataProvider/SubresourceDataProviderInterface.php b/src/Core/DataProvider/SubresourceDataProviderInterface.php deleted file mode 100644 index 1b569c0bded..00000000000 --- a/src/Core/DataProvider/SubresourceDataProviderInterface.php +++ /dev/null @@ -1,38 +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); - -namespace ApiPlatform\Core\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Retrieves subresources from a persistence layer. - * - * @author Antoine Bluchet - */ -interface SubresourceDataProviderInterface -{ - /** - * Retrieves a subresource of an item. - * - * @param string $resourceClass The root resource class - * @param array $identifiers Identifiers and their values - * @param array $context The context indicates the conjunction between collection properties (identifiers) and their class - * @param string $operationName - * - * @throws ResourceClassNotSupportedException - * - * @return iterable|object|null - */ - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null); -} diff --git a/src/Core/DataProvider/TraversablePaginator.php b/src/Core/DataProvider/TraversablePaginator.php deleted file mode 100644 index 0a0cd9c791c..00000000000 --- a/src/Core/DataProvider/TraversablePaginator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\DataProvider; - -class_exists(\ApiPlatform\State\Pagination\TraversablePaginator::class); - -if (false) { - final class TraversablePaginator extends \ApiPlatform\State\Pagination\TraversablePaginator - { - } -} diff --git a/src/Core/DataTransformer/DataTransformerInitializerInterface.php b/src/Core/DataTransformer/DataTransformerInitializerInterface.php deleted file mode 100644 index 85007c818e1..00000000000 --- a/src/Core/DataTransformer/DataTransformerInitializerInterface.php +++ /dev/null @@ -1,26 +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); - -namespace ApiPlatform\Core\DataTransformer; - -interface DataTransformerInitializerInterface extends DataTransformerInterface -{ - /** - * Creates a new DTO object that the data will then be serialized into (using object_to_populate). - * - * This is useful to "initialize" the DTO object based on the current resource's data. - * - * @return object|null - */ - public function initialize(string $inputClass, array $context = []); -} diff --git a/src/Core/DataTransformer/DataTransformerInterface.php b/src/Core/DataTransformer/DataTransformerInterface.php deleted file mode 100644 index 156c0ffe437..00000000000 --- a/src/Core/DataTransformer/DataTransformerInterface.php +++ /dev/null @@ -1,39 +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); - -namespace ApiPlatform\Core\DataTransformer; - -/** - * Transforms a DTO or an Anonymous class to a Resource object. - * - * @author Antoine Bluchet - */ -interface DataTransformerInterface -{ - /** - * Transforms the given object to something else, usually another object. - * This must return the original object if no transformations have been done. - * - * @param object $object - * - * @return object - */ - public function transform($object, string $to, array $context = []); - - /** - * Checks whether the transformation is supported for a given data and context. - * - * @param object|array $data object on normalize / array on denormalize - */ - public function supportsTransformation($data, string $to, array $context = []): bool; -} diff --git a/src/Core/Documentation/Action/DocumentationAction.php b/src/Core/Documentation/Action/DocumentationAction.php deleted file mode 100644 index e8993c4c910..00000000000 --- a/src/Core/Documentation/Action/DocumentationAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Documentation\Action; - -class_exists(\ApiPlatform\Documentation\Action\DocumentationAction::class); - -if (false) { - final class DocumentationAction extends \ApiPlatform\Documentation\Action\DocumentationAction - { - } -} diff --git a/src/Core/Documentation/Documentation.php b/src/Core/Documentation/Documentation.php deleted file mode 100644 index 190348f24bc..00000000000 --- a/src/Core/Documentation/Documentation.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Documentation; - -class_exists(\ApiPlatform\Documentation\Documentation::class); - -if (false) { - final class Documentation extends \ApiPlatform\Documentation\Documentation - { - } -} diff --git a/src/Core/EventListener/AddFormatListener.php b/src/Core/EventListener/AddFormatListener.php deleted file mode 100644 index c7f8a0849f6..00000000000 --- a/src/Core/EventListener/AddFormatListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\AddFormatListener::class); - -if (false) { - final class AddFormatListener extends \ApiPlatform\Symfony\EventListener\AddFormatListener - { - } -} diff --git a/src/Core/EventListener/DeserializeListener.php b/src/Core/EventListener/DeserializeListener.php deleted file mode 100644 index 82b852022aa..00000000000 --- a/src/Core/EventListener/DeserializeListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\DeserializeListener::class); - -if (false) { - final class DeserializeListener extends \ApiPlatform\Symfony\EventListener\DeserializeListener - { - } -} diff --git a/src/Core/EventListener/EventPriorities.php b/src/Core/EventListener/EventPriorities.php deleted file mode 100644 index 48b44ea76e6..00000000000 --- a/src/Core/EventListener/EventPriorities.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\EventPriorities::class); - -if (false) { - final class EventPriorities extends \ApiPlatform\Symfony\EventListener\EventPriorities - { - } -} diff --git a/src/Core/EventListener/ExceptionListener.php b/src/Core/EventListener/ExceptionListener.php deleted file mode 100644 index 1e5a20e9413..00000000000 --- a/src/Core/EventListener/ExceptionListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\ExceptionListener::class); - -if (false) { - final class ExceptionListener extends \ApiPlatform\Symfony\EventListener\ExceptionListener - { - } -} diff --git a/src/Core/EventListener/QueryParameterValidateListener.php b/src/Core/EventListener/QueryParameterValidateListener.php deleted file mode 100644 index 9db39bd2db2..00000000000 --- a/src/Core/EventListener/QueryParameterValidateListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\QueryParameterValidateListener::class); - -if (false) { - final class QueryParameterValidateListener extends \ApiPlatform\Symfony\EventListener\QueryParameterValidateListener - { - } -} diff --git a/src/Core/EventListener/ReadListener.php b/src/Core/EventListener/ReadListener.php deleted file mode 100644 index b795c81ea03..00000000000 --- a/src/Core/EventListener/ReadListener.php +++ /dev/null @@ -1,143 +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); - -namespace ApiPlatform\Core\EventListener; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\OperationDataProviderTrait; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Symfony\EventListener\ReadListener as SymfonyReadListener; -use ApiPlatform\Util\CloneTrait; -use ApiPlatform\Util\OperationRequestInitiatorTrait; -use ApiPlatform\Util\RequestAttributesExtractor; -use ApiPlatform\Util\RequestParser; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -/** - * Retrieves data from the applicable data provider and sets it as a request parameter called data. - * - * @author Kévin Dunglas - * - * @deprecated - */ -final class ReadListener -{ - use CloneTrait; - use OperationDataProviderTrait; - use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; - - public const OPERATION_ATTRIBUTE_KEY = 'read'; - - private $serializerContextBuilder; - private $metadataBackwardCompatibilityLayer; - - public function __construct(CollectionDataProviderInterface $collectionDataProvider, ItemDataProviderInterface $itemDataProvider, SubresourceDataProviderInterface $subresourceDataProvider = null, SerializerContextBuilderInterface $serializerContextBuilder = null, IdentifierConverterInterface $identifierConverter = null, ResourceMetadataFactoryInterface $resourceMetadataFactory = null, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, bool $metadataBackwardCompatibilityLayer = null) - { - $this->collectionDataProvider = $collectionDataProvider; - $this->itemDataProvider = $itemDataProvider; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->serializerContextBuilder = $serializerContextBuilder; - $this->identifierConverter = $identifierConverter; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; - $this->metadataBackwardCompatibilityLayer = $metadataBackwardCompatibilityLayer; - - if ($metadataBackwardCompatibilityLayer || null === $metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The listener "%s" is deprecated and will be replaced by "%s" in 3.0.', __CLASS__, SymfonyReadListener::class)); - } - } - - /** - * Calls the data provider and sets the data attribute. - * - * @throws NotFoundHttpException - */ - public function onKernelRequest(RequestEvent $event): void - { - $request = $event->getRequest(); - $operation = $this->initializeOperation($request); - - if ( - !($attributes = RequestAttributesExtractor::extractAttributes($request)) - || !$attributes['receive'] - || ($request->isMethod('POST') && isset($attributes['collection_operation_name'])) - || ($operation && !($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) && !($operation->getExtraProperties()['is_legacy_subresource'] ?? false)) - || ($operation && false === $operation->canRead()) - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) - ) { - return; - } - - if (false === $this->metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', 'The operation you requested uses legacy metadata, switch to #[ApiPlatform\Metadata\ApiResource].'); - } - - if (null === $filters = $request->attributes->get('_api_filters')) { - $queryString = RequestParser::getQueryString($request); - $filters = $queryString ? RequestParser::parseRequestParams($queryString) : null; - } - - $context = null === $filters ? [] : ['filters' => $filters]; - if ($this->serializerContextBuilder) { - // Builtin data providers are able to use the serialization context to automatically add join clauses - $context += $normalizationContext = $this->serializerContextBuilder->createFromRequest($request, true, $attributes); - $request->attributes->set('_api_normalization_context', $normalizationContext); - } - - if (isset($attributes['collection_operation_name'])) { - $request->attributes->set('data', $this->getCollectionData($attributes, $context)); - - return; - } - - $data = []; - - if ($this->identifierConverter) { - $context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] = true; - } - - try { - $identifiers = $this->extractIdentifiers($request->attributes->all(), $attributes); - - if (isset($attributes['item_operation_name'])) { - $data = $this->getItemData($identifiers, $attributes, $context); - } elseif (isset($attributes['subresource_operation_name'])) { - // Legacy - if (null === $this->subresourceDataProvider) { - throw new RuntimeException('No subresource data provider.'); - } - - $data = $this->getSubresourceData($identifiers, $attributes, $context); - } - } catch (InvalidIdentifierException $e) { - throw new NotFoundHttpException('Invalid identifier value or configuration.', $e); - } - - if (null === $data) { - throw new NotFoundHttpException('Not Found'); - } - - $request->attributes->set('data', $data); - $request->attributes->set('previous_data', $this->clone($data)); - } -} diff --git a/src/Core/EventListener/RespondListener.php b/src/Core/EventListener/RespondListener.php deleted file mode 100644 index 26530c66564..00000000000 --- a/src/Core/EventListener/RespondListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\RespondListener::class); - -if (false) { - final class RespondListener extends \ApiPlatform\Symfony\EventListener\RespondListener - { - } -} diff --git a/src/Core/EventListener/SerializeListener.php b/src/Core/EventListener/SerializeListener.php deleted file mode 100644 index 470982b00c1..00000000000 --- a/src/Core/EventListener/SerializeListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\SerializeListener::class); - -if (false) { - final class SerializeListener extends \ApiPlatform\Symfony\EventListener\SerializeListener - { - } -} diff --git a/src/Core/EventListener/WriteListener.php b/src/Core/EventListener/WriteListener.php deleted file mode 100644 index 870687bfd1e..00000000000 --- a/src/Core/EventListener/WriteListener.php +++ /dev/null @@ -1,134 +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); - -namespace ApiPlatform\Core\EventListener; - -use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Util\OperationRequestInitiatorTrait; -use ApiPlatform\Util\RequestAttributesExtractor; -use ApiPlatform\Util\ResourceClassInfoTrait; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\ViewEvent; - -/** - * Bridges persistence and the API system. - * - * @author Kévin Dunglas - * @author Baptiste Meyer - * - * @deprecated - */ -final class WriteListener -{ - use OperationRequestInitiatorTrait; - use ResourceClassInfoTrait; - use ToggleableOperationAttributeTrait; - - public const OPERATION_ATTRIBUTE_KEY = 'write'; - - private $dataPersister; - /** @var LegacyIriConverterInterface|IriConverterInterface|null */ - private $iriConverter; - private $metadataBackwardCompatibilityLayer; - - public function __construct(DataPersisterInterface $dataPersister, $iriConverter = null, ResourceMetadataFactoryInterface $resourceMetadataFactory = null, ResourceClassResolverInterface $resourceClassResolver = null, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ?bool $metadataBackwardCompatibilityLayer = null) - { - $this->dataPersister = $dataPersister; - $this->iriConverter = $iriConverter; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->resourceClassResolver = $resourceClassResolver; - $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; - $this->metadataBackwardCompatibilityLayer = $metadataBackwardCompatibilityLayer; - - if ($metadataBackwardCompatibilityLayer || null === $metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The listener "%s" is deprecated and will be removed in 3.0, use "%s" instead', __CLASS__, \ApiPlatform\Symfony\EventListener\WriteListener::class)); - } - } - - /** - * Persists, updates or delete data return by the controller if applicable. - */ - public function onKernelView(ViewEvent $event): void - { - $controllerResult = $event->getControllerResult(); - $request = $event->getRequest(); - $operation = $this->initializeOperation($request); - - if ( - $controllerResult instanceof Response - || $request->isMethodSafe() - || !($attributes = RequestAttributesExtractor::extractAttributes($request)) - || !$attributes['persist'] - || ($operation && !($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false)) - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) - ) { - return; - } - - if (false === $this->metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', 'The operation you requested uses legacy metadata, switch to #[ApiPlatform\Metadata\ApiResource].'); - } - - if (!$this->dataPersister->supports($controllerResult, $attributes)) { - return; - } - - switch ($request->getMethod()) { - case 'PUT': - case 'PATCH': - case 'POST': - $persistResult = $this->dataPersister->persist($controllerResult, $attributes); - - if (!\is_object($persistResult)) { - @trigger_error(sprintf('Not returning an object from %s::persist() is deprecated since API Platform 2.3 and will not be supported in API Platform 3.', DataPersisterInterface::class), \E_USER_DEPRECATED); - } else { - $controllerResult = $persistResult; - $event->setControllerResult($controllerResult); - } - - if ($controllerResult instanceof Response) { - break; - } - - $hasOutput = true; - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - $outputMetadata = $resourceMetadata->getOperationAttribute($attributes, 'output', [ - 'class' => $attributes['resource_class'], - ], true); - - $hasOutput = \array_key_exists('class', $outputMetadata) && null !== $outputMetadata['class']; - } - - if (!$hasOutput) { - break; - } - - if ($this->isResourceClass($this->getObjectClass($controllerResult))) { - $request->attributes->set('_api_write_item_iri', $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($controllerResult) : $this->iriConverter->getIriFromResource($controllerResult)); - } - - break; - case 'DELETE': - $this->dataPersister->remove($controllerResult, $attributes); - $event->setControllerResult(null); - break; - } - } -} diff --git a/src/Core/Exception/DeserializationException.php b/src/Core/Exception/DeserializationException.php deleted file mode 100644 index eb4ba833f02..00000000000 --- a/src/Core/Exception/DeserializationException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\DeserializationException::class); - -if (false) { - class DeserializationException extends \ApiPlatform\Exception\DeserializationException - { - } -} diff --git a/src/Core/Exception/FilterValidationException.php b/src/Core/Exception/FilterValidationException.php deleted file mode 100644 index 3fe044a9f10..00000000000 --- a/src/Core/Exception/FilterValidationException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\FilterValidationException::class); - -if (false) { - final class FilterValidationException extends \ApiPlatform\Exception\FilterValidationException - { - } -} diff --git a/src/Core/Exception/InvalidArgumentException.php b/src/Core/Exception/InvalidArgumentException.php deleted file mode 100644 index 6b2be87d603..00000000000 --- a/src/Core/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\InvalidArgumentException::class); - -if (false) { - class InvalidArgumentException extends \ApiPlatform\Exception\InvalidArgumentException - { - } -} diff --git a/src/Core/Exception/InvalidIdentifierException.php b/src/Core/Exception/InvalidIdentifierException.php deleted file mode 100644 index 2ab797b1b3b..00000000000 --- a/src/Core/Exception/InvalidIdentifierException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\InvalidIdentifierException::class); - -if (false) { - final class InvalidIdentifierException extends \ApiPlatform\Exception\InvalidIdentifierException - { - } -} diff --git a/src/Core/Exception/InvalidResourceException.php b/src/Core/Exception/InvalidResourceException.php deleted file mode 100644 index dafb4df9a64..00000000000 --- a/src/Core/Exception/InvalidResourceException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\InvalidResourceException::class); - -if (false) { - class InvalidResourceException extends \ApiPlatform\Exception\InvalidResourceException - { - } -} diff --git a/src/Core/Exception/InvalidValueException.php b/src/Core/Exception/InvalidValueException.php deleted file mode 100644 index a0fc7cc2bc3..00000000000 --- a/src/Core/Exception/InvalidValueException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\InvalidValueException::class); - -if (false) { - class InvalidValueException extends \ApiPlatform\Exception\InvalidValueException - { - } -} diff --git a/src/Core/Exception/ItemNotFoundException.php b/src/Core/Exception/ItemNotFoundException.php deleted file mode 100644 index d6d83fb3d7c..00000000000 --- a/src/Core/Exception/ItemNotFoundException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\ItemNotFoundException::class); - -if (false) { - class ItemNotFoundException extends \ApiPlatform\Exception\ItemNotFoundException - { - } -} diff --git a/src/Core/Exception/PropertyNotFoundException.php b/src/Core/Exception/PropertyNotFoundException.php deleted file mode 100644 index 1bc4ac9c520..00000000000 --- a/src/Core/Exception/PropertyNotFoundException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\PropertyNotFoundException::class); - -if (false) { - class PropertyNotFoundException extends \ApiPlatform\Exception\PropertyNotFoundException - { - } -} diff --git a/src/Core/Exception/ResourceClassNotFoundException.php b/src/Core/Exception/ResourceClassNotFoundException.php deleted file mode 100644 index 1becbf78554..00000000000 --- a/src/Core/Exception/ResourceClassNotFoundException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\ResourceClassNotFoundException::class); - -if (false) { - class ResourceClassNotFoundException extends \ApiPlatform\Exception\ResourceClassNotFoundException - { - } -} diff --git a/src/Core/Exception/ResourceClassNotSupportedException.php b/src/Core/Exception/ResourceClassNotSupportedException.php deleted file mode 100644 index a30cdcf38e4..00000000000 --- a/src/Core/Exception/ResourceClassNotSupportedException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\ResourceClassNotSupportedException::class); - -if (false) { - class ResourceClassNotSupportedException extends \ApiPlatform\Exception\ResourceClassNotSupportedException - { - } -} diff --git a/src/Core/Exception/RuntimeException.php b/src/Core/Exception/RuntimeException.php deleted file mode 100644 index 3fc53363342..00000000000 --- a/src/Core/Exception/RuntimeException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Exception; - -class_exists(\ApiPlatform\Exception\RuntimeException::class); - -if (false) { - class RuntimeException extends \ApiPlatform\Exception\RuntimeException - { - } -} diff --git a/src/Core/Filter/QueryParameterValidator.php b/src/Core/Filter/QueryParameterValidator.php deleted file mode 100644 index 0d080b6be1b..00000000000 --- a/src/Core/Filter/QueryParameterValidator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Filter; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator::class); - -if (false) { - class QueryParameterValidator extends \ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator - { - } -} diff --git a/src/Core/Filter/Validator/ArrayItems.php b/src/Core/Filter/Validator/ArrayItems.php deleted file mode 100644 index 99e914f9ec9..00000000000 --- a/src/Core/Filter/Validator/ArrayItems.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\ArrayItems::class); - -if (false) { - final class ArrayItems extends \ApiPlatform\Api\QueryParameterValidator\Validator\ArrayItems - { - } -} diff --git a/src/Core/Filter/Validator/Bounds.php b/src/Core/Filter/Validator/Bounds.php deleted file mode 100644 index 6b27ba69bda..00000000000 --- a/src/Core/Filter/Validator/Bounds.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Bounds::class); - -if (false) { - final class Bounds extends \ApiPlatform\Api\QueryParameterValidator\Validator\Bounds - { - } -} diff --git a/src/Core/Filter/Validator/Enum.php b/src/Core/Filter/Validator/Enum.php deleted file mode 100644 index ad3ee478608..00000000000 --- a/src/Core/Filter/Validator/Enum.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Enum::class); - -if (false) { - final class Enum extends \ApiPlatform\Api\QueryParameterValidator\Validator\Enum - { - } -} diff --git a/src/Core/Filter/Validator/Length.php b/src/Core/Filter/Validator/Length.php deleted file mode 100644 index 6c743c0a997..00000000000 --- a/src/Core/Filter/Validator/Length.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Length::class); - -if (false) { - final class Length extends \ApiPlatform\Api\QueryParameterValidator\Validator\Length - { - } -} diff --git a/src/Core/Filter/Validator/MultipleOf.php b/src/Core/Filter/Validator/MultipleOf.php deleted file mode 100644 index fa4f3180cc6..00000000000 --- a/src/Core/Filter/Validator/MultipleOf.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\MultipleOf::class); - -if (false) { - final class MultipleOf extends \ApiPlatform\Api\QueryParameterValidator\Validator\MultipleOf - { - } -} diff --git a/src/Core/Filter/Validator/Pattern.php b/src/Core/Filter/Validator/Pattern.php deleted file mode 100644 index bbb0aaa1cdd..00000000000 --- a/src/Core/Filter/Validator/Pattern.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Pattern::class); - -if (false) { - final class Pattern extends \ApiPlatform\Api\QueryParameterValidator\Validator\Pattern - { - } -} diff --git a/src/Core/Filter/Validator/Required.php b/src/Core/Filter/Validator/Required.php deleted file mode 100644 index 71f13283d90..00000000000 --- a/src/Core/Filter/Validator/Required.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Required::class); - -if (false) { - final class Required extends \ApiPlatform\Api\QueryParameterValidator\Validator\Required - { - } -} diff --git a/src/Core/GraphQl/Action/EntrypointAction.php b/src/Core/GraphQl/Action/EntrypointAction.php deleted file mode 100644 index 771447e1ef9..00000000000 --- a/src/Core/GraphQl/Action/EntrypointAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl\Action; - -class_exists(\ApiPlatform\GraphQl\Action\EntrypointAction::class); - -if (false) { - final class EntrypointAction extends \ApiPlatform\GraphQl\Action\EntrypointAction - { - } -} diff --git a/src/Core/GraphQl/Action/GraphQlPlaygroundAction.php b/src/Core/GraphQl/Action/GraphQlPlaygroundAction.php deleted file mode 100644 index ff553d7aa31..00000000000 --- a/src/Core/GraphQl/Action/GraphQlPlaygroundAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl\Action; - -class_exists(\ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction::class); - -if (false) { - final class GraphQlPlaygroundAction extends \ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction - { - } -} diff --git a/src/Core/GraphQl/Action/GraphiQlAction.php b/src/Core/GraphQl/Action/GraphiQlAction.php deleted file mode 100644 index ee069ed2b08..00000000000 --- a/src/Core/GraphQl/Action/GraphiQlAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl\Action; - -class_exists(\ApiPlatform\GraphQl\Action\GraphiQlAction::class); - -if (false) { - final class GraphiQlAction extends \ApiPlatform\GraphQl\Action\GraphiQlAction - { - } -} diff --git a/src/Core/GraphQl/Error/ErrorHandler.php b/src/Core/GraphQl/Error/ErrorHandler.php deleted file mode 100644 index 1061371edeb..00000000000 --- a/src/Core/GraphQl/Error/ErrorHandler.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl\Error; - -class_exists(\ApiPlatform\GraphQl\Error\ErrorHandler::class); - -if (false) { - final class ErrorHandler extends \ApiPlatform\GraphQl\Error\ErrorHandler - { - } -} diff --git a/src/Core/GraphQl/Executor.php b/src/Core/GraphQl/Executor.php deleted file mode 100644 index f0cc9948085..00000000000 --- a/src/Core/GraphQl/Executor.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl; - -class_exists(\ApiPlatform\GraphQl\Executor::class); - -if (false) { - final class Executor extends \ApiPlatform\GraphQl\Executor - { - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/CollectionResolverFactory.php b/src/Core/GraphQl/Resolver/Factory/CollectionResolverFactory.php deleted file mode 100644 index 8fff34f5643..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/CollectionResolverFactory.php +++ /dev/null @@ -1,105 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Factory; - -use ApiPlatform\Core\GraphQl\Resolver\QueryCollectionResolverInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\CloneTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\RequestStack; - -/** - * Creates a function retrieving a collection to resolve a GraphQL query or a field returned by a mutation. - * - * @experimental - * - * @author Alan Poulain - * @author Kévin Dunglas - * @author Vincent Chalamon - */ -final class CollectionResolverFactory implements ResolverFactoryInterface -{ - use CloneTrait; - - private $readStage; - private $securityStage; - private $securityPostDenormalizeStage; - private $serializeStage; - private $queryResolverLocator; - private $requestStack; - private $resourceMetadataFactory; - - public function __construct(ReadStageInterface $readStage, SecurityStageInterface $securityStage, SecurityPostDenormalizeStageInterface $securityPostDenormalizeStage, SerializeStageInterface $serializeStage, ContainerInterface $queryResolverLocator, ResourceMetadataFactoryInterface $resourceMetadataFactory, RequestStack $requestStack = null) - { - $this->readStage = $readStage; - $this->securityStage = $securityStage; - $this->securityPostDenormalizeStage = $securityPostDenormalizeStage; - $this->serializeStage = $serializeStage; - $this->queryResolverLocator = $queryResolverLocator; - $this->requestStack = $requestStack; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable - { - return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) { - if (null === $resourceClass || null === $rootClass) { - return null; - } - - if ($this->requestStack && null !== $request = $this->requestStack->getCurrentRequest()) { - $request->attributes->set( - '_graphql_collections_args', - [$resourceClass => $args] + $request->attributes->get('_graphql_collections_args', []) - ); - } - - $operationName = $operationName ?? 'collection_query'; - $resolverContext = ['source' => $source, 'args' => $args, 'info' => $info, 'is_collection' => true, 'is_mutation' => false, 'is_subscription' => false]; - - $collection = ($this->readStage)($resourceClass, $rootClass, $operationName, $resolverContext); - if (!is_iterable($collection)) { - throw new \LogicException('Collection from read stage should be iterable.'); - } - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $queryResolverId = $resourceMetadata->getGraphqlAttribute($operationName, 'collection_query'); - if (null !== $queryResolverId) { - /** @var QueryCollectionResolverInterface $queryResolver */ - $queryResolver = $this->queryResolverLocator->get($queryResolverId); - $collection = $queryResolver($collection, $resolverContext); - } - - ($this->securityStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $collection, - ], - ]); - ($this->securityPostDenormalizeStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $collection, - 'previous_object' => $this->clone($collection), - ], - ]); - - return ($this->serializeStage)($collection, $resourceClass, $operationName, $resolverContext); - }; - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/ItemMutationResolverFactory.php b/src/Core/GraphQl/Resolver/Factory/ItemMutationResolverFactory.php deleted file mode 100644 index 45fc233f00a..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/ItemMutationResolverFactory.php +++ /dev/null @@ -1,128 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Factory; - -use ApiPlatform\Core\GraphQl\Resolver\MutationResolverInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\DeserializeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\ValidateStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\WriteStageInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ClassInfoTrait; -use ApiPlatform\Core\Util\CloneTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Psr\Container\ContainerInterface; - -/** - * Creates a function resolving a GraphQL mutation of an item. - * - * @experimental - * - * @author Alan Poulain - * @author Vincent Chalamon - */ -final class ItemMutationResolverFactory implements ResolverFactoryInterface -{ - use ClassInfoTrait; - use CloneTrait; - - private $readStage; - private $securityStage; - private $securityPostDenormalizeStage; - private $serializeStage; - private $deserializeStage; - private $writeStage; - private $validateStage; - private $mutationResolverLocator; - private $resourceMetadataFactory; - - public function __construct(ReadStageInterface $readStage, SecurityStageInterface $securityStage, SecurityPostDenormalizeStageInterface $securityPostDenormalizeStage, SerializeStageInterface $serializeStage, DeserializeStageInterface $deserializeStage, WriteStageInterface $writeStage, ValidateStageInterface $validateStage, ContainerInterface $mutationResolverLocator, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - $this->readStage = $readStage; - $this->securityStage = $securityStage; - $this->securityPostDenormalizeStage = $securityPostDenormalizeStage; - $this->serializeStage = $serializeStage; - $this->deserializeStage = $deserializeStage; - $this->writeStage = $writeStage; - $this->validateStage = $validateStage; - $this->mutationResolverLocator = $mutationResolverLocator; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable - { - return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) { - if (null === $resourceClass || null === $operationName) { - return null; - } - - $resolverContext = ['source' => $source, 'args' => $args, 'info' => $info, 'is_collection' => false, 'is_mutation' => true, 'is_subscription' => false]; - - $item = ($this->readStage)($resourceClass, $rootClass, $operationName, $resolverContext); - if (null !== $item && !\is_object($item)) { - throw new \LogicException('Item from read stage should be a nullable object.'); - } - ($this->securityStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - ], - ]); - $previousItem = $this->clone($item); - - if ('delete' === $operationName) { - ($this->securityPostDenormalizeStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - 'previous_object' => $previousItem, - ], - ]); - $item = ($this->writeStage)($item, $resourceClass, $operationName, $resolverContext); - - return ($this->serializeStage)($item, $resourceClass, $operationName, $resolverContext); - } - - $item = ($this->deserializeStage)($item, $resourceClass, $operationName, $resolverContext); - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $mutationResolverId = $resourceMetadata->getGraphqlAttribute($operationName, 'mutation'); - if (null !== $mutationResolverId) { - /** @var MutationResolverInterface $mutationResolver */ - $mutationResolver = $this->mutationResolverLocator->get($mutationResolverId); - $item = $mutationResolver($item, $resolverContext); - if (null !== $item && $resourceClass !== $itemClass = $this->getObjectClass($item)) { - throw new \LogicException(sprintf('Custom mutation resolver "%s" has to return an item of class %s but returned an item of class %s.', $mutationResolverId, $resourceMetadata->getShortName(), (new \ReflectionClass($itemClass))->getShortName())); - } - } - - ($this->securityPostDenormalizeStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - 'previous_object' => $previousItem, - ], - ]); - - if (null !== $item) { - ($this->validateStage)($item, $resourceClass, $operationName, $resolverContext); - - $persistResult = ($this->writeStage)($item, $resourceClass, $operationName, $resolverContext); - } - - return ($this->serializeStage)($persistResult ?? $item, $resourceClass, $operationName, $resolverContext); - }; - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/ItemResolverFactory.php b/src/Core/GraphQl/Resolver/Factory/ItemResolverFactory.php deleted file mode 100644 index f96794dd964..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/ItemResolverFactory.php +++ /dev/null @@ -1,128 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Factory; - -use ApiPlatform\Core\GraphQl\Resolver\QueryItemResolverInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ClassInfoTrait; -use ApiPlatform\Core\Util\CloneTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Psr\Container\ContainerInterface; - -/** - * Creates a function retrieving an item to resolve a GraphQL query. - * - * @experimental - * - * @author Alan Poulain - * @author Kévin Dunglas - * @author Vincent Chalamon - */ -final class ItemResolverFactory implements ResolverFactoryInterface -{ - use ClassInfoTrait; - use CloneTrait; - - private $readStage; - private $securityStage; - private $securityPostDenormalizeStage; - private $serializeStage; - private $queryResolverLocator; - private $resourceMetadataFactory; - - public function __construct(ReadStageInterface $readStage, SecurityStageInterface $securityStage, SecurityPostDenormalizeStageInterface $securityPostDenormalizeStage, SerializeStageInterface $serializeStage, ContainerInterface $queryResolverLocator, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - $this->readStage = $readStage; - $this->securityStage = $securityStage; - $this->securityPostDenormalizeStage = $securityPostDenormalizeStage; - $this->serializeStage = $serializeStage; - $this->queryResolverLocator = $queryResolverLocator; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable - { - return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) { - // Data already fetched and normalized (field or nested resource) - if ($source && \array_key_exists($info->fieldName, $source)) { - return $source[$info->fieldName]; - } - - $operationName = $operationName ?? 'item_query'; - $resolverContext = ['source' => $source, 'args' => $args, 'info' => $info, 'is_collection' => false, 'is_mutation' => false, 'is_subscription' => false]; - - $item = ($this->readStage)($resourceClass, $rootClass, $operationName, $resolverContext); - if (null !== $item && !\is_object($item)) { - throw new \LogicException('Item from read stage should be a nullable object.'); - } - - $resourceClass = $this->getResourceClass($item, $resourceClass); - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $queryResolverId = $resourceMetadata->getGraphqlAttribute($operationName, 'item_query'); - if (null !== $queryResolverId) { - /** @var QueryItemResolverInterface $queryResolver */ - $queryResolver = $this->queryResolverLocator->get($queryResolverId); - $item = $queryResolver($item, $resolverContext); - $resourceClass = $this->getResourceClass($item, $resourceClass, sprintf('Custom query resolver "%s"', $queryResolverId).' has to return an item of class %s but returned an item of class %s.'); - } - - ($this->securityStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - ], - ]); - ($this->securityPostDenormalizeStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - 'previous_object' => $this->clone($item), - ], - ]); - - return ($this->serializeStage)($item, $resourceClass, $operationName, $resolverContext); - }; - } - - /** - * @param object|null $item - * - * @throws \UnexpectedValueException - */ - private function getResourceClass($item, ?string $resourceClass, string $errorMessage = 'Resolver only handles items of class %s but retrieved item is of class %s.'): string - { - if (null === $item) { - if (null === $resourceClass) { - throw new \UnexpectedValueException('Resource class cannot be determined.'); - } - - return $resourceClass; - } - - $itemClass = $this->getObjectClass($item); - - if (null === $resourceClass) { - return $itemClass; - } - - if ($resourceClass !== $itemClass) { - throw new \UnexpectedValueException(sprintf($errorMessage, (new \ReflectionClass($resourceClass))->getShortName(), (new \ReflectionClass($itemClass))->getShortName())); - } - - return $resourceClass; - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactory.php b/src/Core/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactory.php deleted file mode 100644 index 33b86c409ec..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactory.php +++ /dev/null @@ -1,92 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Factory; - -use ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface; -use ApiPlatform\Core\GraphQl\Subscription\SubscriptionManagerInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ClassInfoTrait; -use ApiPlatform\Core\Util\CloneTrait; -use GraphQL\Type\Definition\ResolveInfo; - -/** - * Creates a function resolving a GraphQL subscription of an item. - * - * @experimental - * - * @author Alan Poulain - */ -final class ItemSubscriptionResolverFactory implements ResolverFactoryInterface -{ - use ClassInfoTrait; - use CloneTrait; - - private $readStage; - private $securityStage; - private $serializeStage; - private $resourceMetadataFactory; - private $subscriptionManager; - private $mercureSubscriptionIriGenerator; - - public function __construct(ReadStageInterface $readStage, SecurityStageInterface $securityStage, SerializeStageInterface $serializeStage, ResourceMetadataFactoryInterface $resourceMetadataFactory, SubscriptionManagerInterface $subscriptionManager, ?MercureSubscriptionIriGeneratorInterface $mercureSubscriptionIriGenerator) - { - $this->readStage = $readStage; - $this->securityStage = $securityStage; - $this->serializeStage = $serializeStage; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->subscriptionManager = $subscriptionManager; - $this->mercureSubscriptionIriGenerator = $mercureSubscriptionIriGenerator; - } - - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable - { - return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) { - if (null === $resourceClass || null === $operationName) { - return null; - } - - $resolverContext = ['source' => $source, 'args' => $args, 'info' => $info, 'is_collection' => false, 'is_mutation' => false, 'is_subscription' => true]; - - $item = ($this->readStage)($resourceClass, $rootClass, $operationName, $resolverContext); - if (null !== $item && !\is_object($item)) { - throw new \LogicException('Item from read stage should be a nullable object.'); - } - ($this->securityStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - ], - ]); - - $result = ($this->serializeStage)($item, $resourceClass, $operationName, $resolverContext); - - $subscriptionId = $this->subscriptionManager->retrieveSubscriptionId($resolverContext, $result); - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($subscriptionId && ($mercure = $resourceMetadata->getAttribute('mercure', false))) { - if (!$this->mercureSubscriptionIriGenerator) { - throw new \LogicException('Cannot use Mercure for subscriptions when MercureBundle is not installed. Try running "composer require mercure".'); - } - - $hub = \is_array($mercure) ? ($mercure['hub'] ?? null) : null; - $result['mercureUrl'] = $this->mercureSubscriptionIriGenerator->generateMercureUrl($subscriptionId, $hub); - } - - return $result; - }; - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/ResolverFactoryInterface.php b/src/Core/GraphQl/Resolver/Factory/ResolverFactoryInterface.php deleted file mode 100644 index f406bc7a3b2..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/ResolverFactoryInterface.php +++ /dev/null @@ -1,26 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Factory; - -/** - * Builds a GraphQL resolver. - * - * @experimental - * - * @author Kévin Dunglas - */ -interface ResolverFactoryInterface -{ - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable; -} diff --git a/src/Core/GraphQl/Resolver/ResourceFieldResolver.php b/src/Core/GraphQl/Resolver/ResourceFieldResolver.php deleted file mode 100644 index 1e1f846e705..00000000000 --- a/src/Core/GraphQl/Resolver/ResourceFieldResolver.php +++ /dev/null @@ -1,56 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\Core\Util\ClassInfoTrait; -use GraphQL\Type\Definition\ResolveInfo; - -/** - * A field resolver that resolves IDs to IRIs and allow to access to the raw ID using the "#id" field. - * - * @experimental - * - * @author Kévin Dunglas - */ -final class ResourceFieldResolver -{ - use ClassInfoTrait; - - private $iriConverter; - - public function __construct(IriConverterInterface $iriConverter) - { - $this->iriConverter = $iriConverter; - } - - public function __invoke(?array $source, array $args, $context, ResolveInfo $info) - { - $property = null; - if ('id' === $info->fieldName && !isset($source['_id']) && isset($source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY], $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY])) { - return $this->iriConverter->getItemIriFromResourceClass($source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY], $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY]); - } - - if ('_id' === $info->fieldName && !isset($source['_id']) && isset($source['id'])) { - $property = $source['id']; - } elseif (\is_array($source) && isset($source[$info->fieldName])) { - $property = $source[$info->fieldName]; - } elseif (isset($source->{$info->fieldName})) { - $property = $source->{$info->fieldName}; - } - - return $property instanceof \Closure ? $property($source, $args, $context) : $property; - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/DeserializeStage.php b/src/Core/GraphQl/Resolver/Stage/DeserializeStage.php deleted file mode 100644 index 6786a03f191..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/DeserializeStage.php +++ /dev/null @@ -1,65 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Deserialize stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class DeserializeStage implements DeserializeStageInterface -{ - private $resourceMetadataFactory; - private $denormalizer; - private $serializerContextBuilder; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, DenormalizerInterface $denormalizer, SerializerContextBuilderInterface $serializerContextBuilder) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->denormalizer = $denormalizer; - $this->serializerContextBuilder = $serializerContextBuilder; - } - - /** - * {@inheritdoc} - */ - public function __invoke($objectToPopulate, string $resourceClass, string $operationName, array $context) - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (!$resourceMetadata->getGraphqlAttribute($operationName, 'deserialize', true, true)) { - return $objectToPopulate; - } - - $denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, false); - if (null !== $objectToPopulate) { - $denormalizationContext[AbstractNormalizer::OBJECT_TO_POPULATE] = $objectToPopulate; - } - - $item = $this->denormalizer->denormalize($context['args']['input'], $resourceClass, ItemNormalizer::FORMAT, $denormalizationContext); - - if (!\is_object($item)) { - throw new \UnexpectedValueException('Expected item to be an object.'); - } - - return $item; - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/DeserializeStageInterface.php b/src/Core/GraphQl/Resolver/Stage/DeserializeStageInterface.php deleted file mode 100644 index be57bbe4126..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/DeserializeStageInterface.php +++ /dev/null @@ -1,31 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -/** - * Deserialize stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface DeserializeStageInterface -{ - /** - * @param object|null $objectToPopulate - * - * @return object|null - */ - public function __invoke($objectToPopulate, string $resourceClass, string $operationName, array $context); -} diff --git a/src/Core/GraphQl/Resolver/Stage/ReadStage.php b/src/Core/GraphQl/Resolver/Stage/ReadStage.php deleted file mode 100644 index 344b2f49df0..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/ReadStage.php +++ /dev/null @@ -1,188 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Exception\ItemNotFoundException; -use ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait; -use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ArrayTrait; -use ApiPlatform\Core\Util\ClassInfoTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -/** - * Read stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class ReadStage implements ReadStageInterface -{ - use ArrayTrait; - use ClassInfoTrait; - use IdentifierTrait; - - private $resourceMetadataFactory; - private $iriConverter; - private $collectionDataProvider; - private $subresourceDataProvider; - private $serializerContextBuilder; - private $nestingSeparator; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, IriConverterInterface $iriConverter, ContextAwareCollectionDataProviderInterface $collectionDataProvider, SubresourceDataProviderInterface $subresourceDataProvider, SerializerContextBuilderInterface $serializerContextBuilder, string $nestingSeparator) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->iriConverter = $iriConverter; - $this->collectionDataProvider = $collectionDataProvider; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->serializerContextBuilder = $serializerContextBuilder; - $this->nestingSeparator = $nestingSeparator; - } - - /** - * {@inheritdoc} - */ - public function __invoke(?string $resourceClass, ?string $rootClass, string $operationName, array $context) - { - $resourceMetadata = $resourceClass ? $this->resourceMetadataFactory->create($resourceClass) : null; - if ($resourceMetadata && !$resourceMetadata->getGraphqlAttribute($operationName, 'read', true, true)) { - return $context['is_collection'] ? [] : null; - } - - $args = $context['args']; - $normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, true); - - if (!$context['is_collection']) { - $identifier = $this->getIdentifierFromContext($context); - $item = $this->getItem($identifier, $normalizationContext); - - if ($identifier && ($context['is_mutation'] || $context['is_subscription'])) { - if (null === $item) { - throw new NotFoundHttpException(sprintf('Item "%s" not found.', $args['input']['id'])); - } - - if ($resourceClass !== $this->getObjectClass($item)) { - throw new \UnexpectedValueException(sprintf('Item "%s" did not match expected type "%s".', $args['input']['id'], $resourceMetadata->getShortName())); - } - } - - return $item; - } - - if (null === $rootClass) { - return []; - } - - $normalizationContext['filters'] = $this->getNormalizedFilters($args); - - $source = $context['source']; - /** @var ResolveInfo $info */ - $info = $context['info']; - if (isset($source[$rootProperty = $info->fieldName], $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY], $source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY])) { - $rootResolvedFields = $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY]; - $rootResolvedClass = $source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY]; - $subresourceCollection = $this->getSubresource($rootResolvedClass, $rootResolvedFields, $rootProperty, $resourceClass, $normalizationContext, $operationName); - if (!is_iterable($subresourceCollection)) { - throw new \UnexpectedValueException('Expected subresource collection to be iterable.'); - } - - return $subresourceCollection; - } - - return $this->collectionDataProvider->getCollection($resourceClass, $operationName, $normalizationContext); - } - - /** - * @return object|null - */ - private function getItem(?string $identifier, array $normalizationContext) - { - if (null === $identifier) { - return null; - } - - try { - $item = $this->iriConverter->getItemFromIri($identifier, $normalizationContext); - } catch (ItemNotFoundException $e) { - return null; - } - - return $item; - } - - private function getNormalizedFilters(array $args): array - { - $filters = $args; - - foreach ($filters as $name => $value) { - if (\is_array($value)) { - if (strpos($name, '_list')) { - $name = substr($name, 0, \strlen($name) - \strlen('_list')); - } - - // If the value contains arrays, we need to merge them for the filters to understand this syntax, proper to GraphQL to preserve the order of the arguments. - if ($this->isSequentialArrayOfArrays($value)) { - if (\count($value[0]) > 1) { - $deprecationMessage = "The filter syntax \"$name: {"; - $filterArgsOld = []; - $filterArgsNew = []; - foreach ($value[0] as $filterArgName => $filterArgValue) { - $filterArgsOld[] = "$filterArgName: \"$filterArgValue\""; - $filterArgsNew[] = sprintf('{%s: "%s"}', $filterArgName, $filterArgValue); - } - $deprecationMessage .= sprintf('%s}" is deprecated since API Platform 2.6, use the following syntax instead: "%s: [%s]".', implode(', ', $filterArgsOld), $name, implode(', ', $filterArgsNew)); - @trigger_error($deprecationMessage, \E_USER_DEPRECATED); - } - $value = array_merge(...$value); - } - $filters[$name] = $this->getNormalizedFilters($value); - } - - if (\is_string($name) && strpos($name, $this->nestingSeparator)) { - // Gives a chance to relations/nested fields. - $index = array_search($name, array_keys($filters), true); - $filters = - \array_slice($filters, 0, $index + 1) + - [str_replace($this->nestingSeparator, '.', $name) => $value] + - \array_slice($filters, $index + 1); - } - } - - return $filters; - } - - /** - * @return iterable|object|null - */ - private function getSubresource(string $rootResolvedClass, array $rootResolvedFields, string $rootProperty, string $subresourceClass, array $normalizationContext, string $operationName) - { - $resolvedIdentifiers = []; - $rootIdentifiers = array_keys($rootResolvedFields); - foreach ($rootIdentifiers as $rootIdentifier) { - $resolvedIdentifiers[$rootIdentifier] = [$rootResolvedClass, $rootIdentifier]; - } - - return $this->subresourceDataProvider->getSubresource($subresourceClass, $rootResolvedFields, $normalizationContext + [ - 'property' => $rootProperty, - 'identifiers' => $resolvedIdentifiers, - 'collection' => true, - ], $operationName); - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/ReadStageInterface.php b/src/Core/GraphQl/Resolver/Stage/ReadStageInterface.php deleted file mode 100644 index 7acc16101be..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/ReadStageInterface.php +++ /dev/null @@ -1,29 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -/** - * Read stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface ReadStageInterface -{ - /** - * @return object|iterable|null - */ - public function __invoke(?string $resourceClass, ?string $rootClass, string $operationName, array $context); -} diff --git a/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php b/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php deleted file mode 100644 index a5db9f35bde..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php +++ /dev/null @@ -1,65 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Security\ResourceAccessCheckerInterface; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; - -/** - * Security post denormalize stage of GraphQL resolvers. - * - * @experimental - * - * @author Vincent Chalamon - */ -final class SecurityPostDenormalizeStage implements SecurityPostDenormalizeStageInterface -{ - private $resourceMetadataFactory; - private $resourceAccessChecker; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ?ResourceAccessCheckerInterface $resourceAccessChecker) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->resourceAccessChecker = $resourceAccessChecker; - } - - /** - * {@inheritdoc} - */ - public function __invoke(string $resourceClass, string $operationName, array $context): void - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $isGranted = $resourceMetadata->getGraphqlAttribute($operationName, 'security_post_denormalize', null, true); - - if (null === $isGranted) { - // Backward compatibility - $isGranted = $resourceMetadata->getGraphqlAttribute($operationName, 'access_control', null, true); - if (null !== $isGranted) { - @trigger_error('Attribute "access_control" is deprecated since API Platform 2.5, prefer using "security" attribute instead', \E_USER_DEPRECATED); - } - } - - if (null !== $isGranted && null === $this->resourceAccessChecker) { - throw new \LogicException('Cannot check security expression when SecurityBundle is not installed. Try running "composer require symfony/security-bundle".'); - } - - if (null === $isGranted || $this->resourceAccessChecker->isGranted($resourceClass, (string) $isGranted, $context['extra_variables'])) { - return; - } - - throw new AccessDeniedHttpException($resourceMetadata->getGraphqlAttribute($operationName, 'security_post_denormalize_message', 'Access Denied.')); - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageInterface.php b/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageInterface.php deleted file mode 100644 index d60b951cd8e..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageInterface.php +++ /dev/null @@ -1,31 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use GraphQL\Error\Error; - -/** - * Security post deserialization stage of GraphQL resolvers. - * - * @experimental - * - * @author Vincent Chalamon - */ -interface SecurityPostDenormalizeStageInterface -{ - /** - * @throws Error - */ - public function __invoke(string $resourceClass, string $operationName, array $context): void; -} diff --git a/src/Core/GraphQl/Resolver/Stage/SecurityStage.php b/src/Core/GraphQl/Resolver/Stage/SecurityStage.php deleted file mode 100644 index 6297c6eba4d..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SecurityStage.php +++ /dev/null @@ -1,57 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Security\ResourceAccessCheckerInterface; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; - -/** - * Security stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class SecurityStage implements SecurityStageInterface -{ - private $resourceMetadataFactory; - private $resourceAccessChecker; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ?ResourceAccessCheckerInterface $resourceAccessChecker) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->resourceAccessChecker = $resourceAccessChecker; - } - - /** - * {@inheritdoc} - */ - public function __invoke(string $resourceClass, string $operationName, array $context): void - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $isGranted = $resourceMetadata->getGraphqlAttribute($operationName, 'security', null, true); - - if (null !== $isGranted && null === $this->resourceAccessChecker) { - throw new \LogicException('Cannot check security expression when SecurityBundle is not installed. Try running "composer require symfony/security-bundle".'); - } - - if (null === $isGranted || $this->resourceAccessChecker->isGranted($resourceClass, (string) $isGranted, $context['extra_variables'])) { - return; - } - - throw new AccessDeniedHttpException($resourceMetadata->getGraphqlAttribute($operationName, 'security_message', 'Access Denied.')); - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/SecurityStageInterface.php b/src/Core/GraphQl/Resolver/Stage/SecurityStageInterface.php deleted file mode 100644 index 1e0c4acbb20..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SecurityStageInterface.php +++ /dev/null @@ -1,32 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use GraphQL\Error\Error; - -/** - * Security stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - * @author Vincent Chalamon - */ -interface SecurityStageInterface -{ - /** - * @throws Error - */ - public function __invoke(string $resourceClass, string $operationName, array $context): void; -} diff --git a/src/Core/GraphQl/Resolver/Stage/SerializeStage.php b/src/Core/GraphQl/Resolver/Stage/SerializeStage.php deleted file mode 100644 index 56484bc1c1d..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SerializeStage.php +++ /dev/null @@ -1,223 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\DataProvider\Pagination; -use ApiPlatform\Core\DataProvider\PaginatorInterface; -use ApiPlatform\Core\DataProvider\PartialPaginatorInterface; -use ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait; -use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Serialize stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class SerializeStage implements SerializeStageInterface -{ - use IdentifierTrait; - - private $resourceMetadataFactory; - private $normalizer; - private $serializerContextBuilder; - private $pagination; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, NormalizerInterface $normalizer, SerializerContextBuilderInterface $serializerContextBuilder, Pagination $pagination) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->normalizer = $normalizer; - $this->serializerContextBuilder = $serializerContextBuilder; - $this->pagination = $pagination; - } - - /** - * {@inheritdoc} - */ - public function __invoke($itemOrCollection, string $resourceClass, string $operationName, array $context): ?array - { - $isCollection = $context['is_collection']; - $isMutation = $context['is_mutation']; - $isSubscription = $context['is_subscription']; - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (!$resourceMetadata->getGraphqlAttribute($operationName, 'serialize', true, true)) { - if ($isCollection) { - if ($this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context)) { - return 'cursor' === $this->pagination->getGraphQlPaginationType($resourceClass, $operationName) ? - $this->getDefaultCursorBasedPaginatedData() : - $this->getDefaultPageBasedPaginatedData(); - } - - return []; - } - - if ($isMutation) { - return $this->getDefaultMutationData($context); - } - - if ($isSubscription) { - return $this->getDefaultSubscriptionData($context); - } - - return null; - } - - $normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, true); - - $data = null; - if (!$isCollection) { - if ($isMutation && 'delete' === $operationName) { - $data = ['id' => $this->getIdentifierFromContext($context)]; - } else { - $data = $this->normalizer->normalize($itemOrCollection, ItemNormalizer::FORMAT, $normalizationContext); - } - } - - if ($isCollection && is_iterable($itemOrCollection)) { - if (!$this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context)) { - $data = []; - foreach ($itemOrCollection as $index => $object) { - $data[$index] = $this->normalizer->normalize($object, ItemNormalizer::FORMAT, $normalizationContext); - } - } else { - $data = 'cursor' === $this->pagination->getGraphQlPaginationType($resourceClass, $operationName) ? - $this->serializeCursorBasedPaginatedCollection($itemOrCollection, $normalizationContext, $context) : - $this->serializePageBasedPaginatedCollection($itemOrCollection, $normalizationContext); - } - } - - if (null !== $data && !\is_array($data)) { - throw new \UnexpectedValueException('Expected serialized data to be a nullable array.'); - } - - if ($isMutation || $isSubscription) { - $wrapFieldName = lcfirst($resourceMetadata->getShortName()); - - return [$wrapFieldName => $data] + ($isMutation ? $this->getDefaultMutationData($context) : $this->getDefaultSubscriptionData($context)); - } - - return $data; - } - - /** - * @throws \LogicException - * @throws \UnexpectedValueException - */ - private function serializeCursorBasedPaginatedCollection(iterable $collection, array $normalizationContext, array $context): array - { - $args = $context['args']; - - if (!($collection instanceof PartialPaginatorInterface)) { - throw new \LogicException(sprintf('Collection returned by the collection data provider must implement %s or %s.', PaginatorInterface::class, PartialPaginatorInterface::class)); - } - - $offset = 0; - $totalItems = 1; // For partial pagination, always consider there is at least one item. - $nbPageItems = $collection->count(); - if (isset($args['after'])) { - $after = base64_decode($args['after'], true); - if (false === $after || '' === $args['after']) { - throw new \UnexpectedValueException('' === $args['after'] ? 'Empty cursor is invalid' : sprintf('Cursor %s is invalid', $args['after'])); - } - $offset = 1 + (int) $after; - } - - if ($collection instanceof PaginatorInterface) { - $totalItems = $collection->getTotalItems(); - - if (isset($args['before'])) { - $before = base64_decode($args['before'], true); - if (false === $before || '' === $args['before']) { - throw new \UnexpectedValueException('' === $args['before'] ? 'Empty cursor is invalid' : sprintf('Cursor %s is invalid', $args['before'])); - } - $offset = (int) $before - $nbPageItems; - } - if (isset($args['last']) && !isset($args['before'])) { - $offset = $totalItems - $args['last']; - } - } - - $offset = 0 > $offset ? 0 : $offset; - - $data = $this->getDefaultCursorBasedPaginatedData(); - if ($totalItems > 0) { - $data['pageInfo']['startCursor'] = base64_encode((string) $offset); - $end = $offset + $nbPageItems - 1; - $data['pageInfo']['endCursor'] = base64_encode((string) ($end >= 0 ? $end : 0)); - $data['pageInfo']['hasPreviousPage'] = $offset > 0; - if ($collection instanceof PaginatorInterface) { - $data['totalCount'] = $totalItems; - $itemsPerPage = $collection->getItemsPerPage(); - $data['pageInfo']['hasNextPage'] = (float) ($itemsPerPage > 0 ? $offset % $itemsPerPage : $offset) + $itemsPerPage * $collection->getCurrentPage() < $totalItems; - } - } - - $index = 0; - foreach ($collection as $object) { - $data['edges'][$index] = [ - 'node' => $this->normalizer->normalize($object, ItemNormalizer::FORMAT, $normalizationContext), - 'cursor' => base64_encode((string) ($index + $offset)), - ]; - ++$index; - } - - return $data; - } - - /** - * @throws \LogicException - */ - private function serializePageBasedPaginatedCollection(iterable $collection, array $normalizationContext): array - { - if (!($collection instanceof PaginatorInterface)) { - throw new \LogicException(sprintf('Collection returned by the collection data provider must implement %s.', PaginatorInterface::class)); - } - - $data = $this->getDefaultPageBasedPaginatedData(); - $data['paginationInfo']['totalCount'] = $collection->getTotalItems(); - $data['paginationInfo']['lastPage'] = $collection->getLastPage(); - $data['paginationInfo']['itemsPerPage'] = $collection->getItemsPerPage(); - - foreach ($collection as $object) { - $data['collection'][] = $this->normalizer->normalize($object, ItemNormalizer::FORMAT, $normalizationContext); - } - - return $data; - } - - private function getDefaultCursorBasedPaginatedData(): array - { - return ['totalCount' => 0., 'edges' => [], 'pageInfo' => ['startCursor' => null, 'endCursor' => null, 'hasNextPage' => false, 'hasPreviousPage' => false]]; - } - - private function getDefaultPageBasedPaginatedData(): array - { - return ['collection' => [], 'paginationInfo' => ['itemsPerPage' => 0., 'totalCount' => 0., 'lastPage' => 0.]]; - } - - private function getDefaultMutationData(array $context): array - { - return ['clientMutationId' => $context['args']['input']['clientMutationId'] ?? null]; - } - - private function getDefaultSubscriptionData(array $context): array - { - return ['clientSubscriptionId' => $context['args']['input']['clientSubscriptionId'] ?? null]; - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/SerializeStageInterface.php b/src/Core/GraphQl/Resolver/Stage/SerializeStageInterface.php deleted file mode 100644 index be96883832e..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SerializeStageInterface.php +++ /dev/null @@ -1,29 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -/** - * Serialize stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface SerializeStageInterface -{ - /** - * @param object|iterable|null $itemOrCollection - */ - public function __invoke($itemOrCollection, string $resourceClass, string $operationName, array $context): ?array; -} diff --git a/src/Core/GraphQl/Resolver/Stage/ValidateStage.php b/src/Core/GraphQl/Resolver/Stage/ValidateStage.php deleted file mode 100644 index 3c46aea7746..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/ValidateStage.php +++ /dev/null @@ -1,50 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Validator\ValidatorInterface; - -/** - * Validate stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class ValidateStage implements ValidateStageInterface -{ - private $resourceMetadataFactory; - private $validator; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ValidatorInterface $validator) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->validator = $validator; - } - - /** - * {@inheritdoc} - */ - public function __invoke($object, string $resourceClass, string $operationName, array $context): void - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (!$resourceMetadata->getGraphqlAttribute($operationName, 'validate', true, true)) { - return; - } - - $validationGroups = $resourceMetadata->getGraphqlAttribute($operationName, 'validation_groups', null, true); - $this->validator->validate($object, ['groups' => $validationGroups]); - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/ValidateStageInterface.php b/src/Core/GraphQl/Resolver/Stage/ValidateStageInterface.php deleted file mode 100644 index e798a820671..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/ValidateStageInterface.php +++ /dev/null @@ -1,33 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use GraphQL\Error\Error; - -/** - * Validate stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface ValidateStageInterface -{ - /** - * @param object $object - * - * @throws Error - */ - public function __invoke($object, string $resourceClass, string $operationName, array $context): void; -} diff --git a/src/Core/GraphQl/Resolver/Stage/WriteStage.php b/src/Core/GraphQl/Resolver/Stage/WriteStage.php deleted file mode 100644 index 5d0b9842941..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/WriteStage.php +++ /dev/null @@ -1,68 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; - -/** - * Write stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class WriteStage implements WriteStageInterface -{ - private $resourceMetadataFactory; - private $dataPersister; - private $serializerContextBuilder; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ContextAwareDataPersisterInterface $dataPersister, SerializerContextBuilderInterface $serializerContextBuilder) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->dataPersister = $dataPersister; - $this->serializerContextBuilder = $serializerContextBuilder; - } - - /** - * {@inheritdoc} - */ - public function __invoke($data, string $resourceClass, string $operationName, array $context) - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (null === $data || !$resourceMetadata->getGraphqlAttribute($operationName, 'write', true, true)) { - return $data; - } - - $denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, false); - - if ('delete' === $operationName) { - $this->dataPersister->remove($data, $denormalizationContext); - - return null; - } - - $persistResult = $this->dataPersister->persist($data, $denormalizationContext); - - if (!\is_object($persistResult)) { - @trigger_error(sprintf('Not returning an object from %s::persist() is deprecated since API Platform 2.3 and will not be supported in API Platform 3.', DataPersisterInterface::class), \E_USER_DEPRECATED); - $persistResult = null; - } - - return $persistResult; - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/WriteStageInterface.php b/src/Core/GraphQl/Resolver/Stage/WriteStageInterface.php deleted file mode 100644 index 1b54363d443..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/WriteStageInterface.php +++ /dev/null @@ -1,31 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Stage; - -/** - * Write stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface WriteStageInterface -{ - /** - * @param object|null $data - * - * @return object|null - */ - public function __invoke($data, string $resourceClass, string $operationName, array $context); -} diff --git a/src/Core/GraphQl/Resolver/Util/IdentifierTrait.php b/src/Core/GraphQl/Resolver/Util/IdentifierTrait.php deleted file mode 100644 index 225074b0254..00000000000 --- a/src/Core/GraphQl/Resolver/Util/IdentifierTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\GraphQl\Resolver\Util; - -class_exists(\ApiPlatform\GraphQl\Resolver\Util\IdentifierTrait::class); - -if (false) { - trait IdentifierTrait - { - use \ApiPlatform\GraphQl\Resolver\Util\IdentifierTrait; - } -} diff --git a/src/Core/GraphQl/Serializer/Exception/ErrorNormalizer.php b/src/Core/GraphQl/Serializer/Exception/ErrorNormalizer.php deleted file mode 100644 index 05b214f1c58..00000000000 --- a/src/Core/GraphQl/Serializer/Exception/ErrorNormalizer.php +++ /dev/null @@ -1,44 +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); - -namespace ApiPlatform\Core\GraphQl\Serializer\Exception; - -use GraphQL\Error\Error; -use GraphQL\Error\FormattedError; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Normalize GraphQL error (fallback). - * - * @experimental - * - * @author Alan Poulain - */ -final class ErrorNormalizer implements NormalizerInterface -{ - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []): array - { - return FormattedError::createFromException($object); - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return $data instanceof Error; - } -} diff --git a/src/Core/GraphQl/Serializer/Exception/HttpExceptionNormalizer.php b/src/Core/GraphQl/Serializer/Exception/HttpExceptionNormalizer.php deleted file mode 100644 index 4c7e97c2b90..00000000000 --- a/src/Core/GraphQl/Serializer/Exception/HttpExceptionNormalizer.php +++ /dev/null @@ -1,52 +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); - -namespace ApiPlatform\Core\GraphQl\Serializer\Exception; - -use GraphQL\Error\Error; -use GraphQL\Error\FormattedError; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Normalize HTTP exceptions. - * - * @experimental - * - * @author Alan Poulain - */ -final class HttpExceptionNormalizer implements NormalizerInterface -{ - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []): array - { - /** @var HttpExceptionInterface */ - $httpException = $object->getPrevious(); - $error = FormattedError::createFromException($object); - $error['message'] = $httpException->getMessage(); - $error['extensions']['status'] = $statusCode = $httpException->getStatusCode(); - $error['extensions']['category'] = $statusCode < 500 ? 'user' : Error::CATEGORY_INTERNAL; - - return $error; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return $data instanceof Error && $data->getPrevious() instanceof HttpExceptionInterface; - } -} diff --git a/src/Core/GraphQl/Serializer/Exception/RuntimeExceptionNormalizer.php b/src/Core/GraphQl/Serializer/Exception/RuntimeExceptionNormalizer.php deleted file mode 100644 index 61bc85fe7e8..00000000000 --- a/src/Core/GraphQl/Serializer/Exception/RuntimeExceptionNormalizer.php +++ /dev/null @@ -1,49 +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); - -namespace ApiPlatform\Core\GraphQl\Serializer\Exception; - -use GraphQL\Error\Error; -use GraphQL\Error\FormattedError; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Normalize runtime exceptions to have the right message in production mode. - * - * @experimental - * - * @author Alan Poulain - */ -final class RuntimeExceptionNormalizer implements NormalizerInterface -{ - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []): array - { - /** @var \RuntimeException */ - $runtimeException = $object->getPrevious(); - $error = FormattedError::createFromException($object); - $error['message'] = $runtimeException->getMessage(); - - return $error; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return $data instanceof Error && $data->getPrevious() instanceof \RuntimeException; - } -} diff --git a/src/Core/GraphQl/Serializer/Exception/ValidationExceptionNormalizer.php b/src/Core/GraphQl/Serializer/Exception/ValidationExceptionNormalizer.php deleted file mode 100644 index 6e4ad1117dd..00000000000 --- a/src/Core/GraphQl/Serializer/Exception/ValidationExceptionNormalizer.php +++ /dev/null @@ -1,82 +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); - -namespace ApiPlatform\Core\GraphQl\Serializer\Exception; - -use ApiPlatform\Symfony\Validator\Exception\ValidationException; -use GraphQL\Error\Error; -use GraphQL\Error\FormattedError; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Validator\ConstraintViolation; - -/** - * Normalize validation exceptions. - * - * @experimental - * - * @author Mahmood Bazdar - * @author Alan Poulain - */ -final class ValidationExceptionNormalizer implements NormalizerInterface -{ - private $exceptionToStatus; - - public function __construct(array $exceptionToStatus = []) - { - $this->exceptionToStatus = $exceptionToStatus; - } - - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []): array - { - /** @var ValidationException */ - $validationException = $object->getPrevious(); - $error = FormattedError::createFromException($object); - $error['message'] = $validationException->getMessage(); - - $exceptionClass = \get_class($validationException); - $statusCode = Response::HTTP_UNPROCESSABLE_ENTITY; - - foreach ($this->exceptionToStatus as $class => $status) { - if (is_a($exceptionClass, $class, true)) { - $statusCode = $status; - - break; - } - } - $error['extensions']['status'] = $statusCode; - $error['extensions']['category'] = 'user'; - $error['extensions']['violations'] = []; - - /** @var ConstraintViolation $violation */ - foreach ($validationException->getConstraintViolationList() as $violation) { - $error['extensions']['violations'][] = [ - 'path' => $violation->getPropertyPath(), - 'message' => $violation->getMessage(), - ]; - } - - return $error; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return $data instanceof Error && $data->getPrevious() instanceof ValidationException; - } -} diff --git a/src/Core/GraphQl/Serializer/ItemNormalizer.php b/src/Core/GraphQl/Serializer/ItemNormalizer.php deleted file mode 100644 index 738c4040bdd..00000000000 --- a/src/Core/GraphQl/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,133 +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); - -namespace ApiPlatform\Core\GraphQl\Serializer; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Serializer\ItemNormalizer as BaseItemNormalizer; -use ApiPlatform\Core\Util\ClassInfoTrait; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * GraphQL normalizer. - * - * @author Kévin Dunglas - */ -final class ItemNormalizer extends BaseItemNormalizer -{ - use ClassInfoTrait; - - public const FORMAT = 'graphql'; - public const ITEM_RESOURCE_CLASS_KEY = '#itemResourceClass'; - public const ITEM_IDENTIFIERS_KEY = '#itemIdentifiers'; - - private $identifiersExtractor; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, IdentifiersExtractorInterface $identifiersExtractor, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, ItemDataProviderInterface $itemDataProvider = null, bool $allowPlainIdentifiers = false, LoggerInterface $logger = null, iterable $dataTransformers = [], ResourceMetadataFactoryInterface $resourceMetadataFactory = null) - { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $itemDataProvider, $allowPlainIdentifiers, $logger ?: new NullLogger(), $dataTransformers, $resourceMetadataFactory); - - $this->identifiersExtractor = $identifiersExtractor; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return self::FORMAT === $format && parent::supportsNormalization($data, $format); - } - - /** - * {@inheritdoc} - * - * @throws UnexpectedValueException - * - * @return array|string|int|float|bool|\ArrayObject|null - */ - public function normalize($object, $format = null, array $context = []) - { - if (null !== $this->getOutputClass($this->getObjectClass($object), $context)) { - return parent::normalize($object, $format, $context); - } - - $data = parent::normalize($object, $format, $context); - if (!\is_array($data)) { - throw new UnexpectedValueException('Expected data to be an array.'); - } - - if (!($context['no_resolver_data'] ?? false)) { - $data[self::ITEM_RESOURCE_CLASS_KEY] = $this->getObjectClass($object); - $data[self::ITEM_IDENTIFIERS_KEY] = $this->identifiersExtractor->getIdentifiersFromItem($object); - } - - return $data; - } - - /** - * {@inheritdoc} - */ - protected function normalizeCollectionOfRelations($propertyMetadata, $attributeValue, string $resourceClass, ?string $format, array $context): array - { - // to-many are handled directly by the GraphQL resolver - return []; - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format); - } - - /** - * {@inheritdoc} - * - * @return array|bool - */ - protected function getAllowedAttributes($classOrObject, array $context, $attributesAsString = false) - { - $allowedAttributes = parent::getAllowedAttributes($classOrObject, $context, $attributesAsString); - - if (($context['api_denormalize'] ?? false) && \is_array($allowedAttributes) && false !== ($indexId = array_search('id', $allowedAttributes, true))) { - $allowedAttributes[] = '_id'; - array_splice($allowedAttributes, (int) $indexId, 1); - } - - return $allowedAttributes; - } - - /** - * {@inheritdoc} - */ - protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = []): void - { - if ('_id' === $attribute) { - $attribute = 'id'; - } - - parent::setAttributeValue($object, $attribute, $value, $format, $context); - } -} diff --git a/src/Core/GraphQl/Serializer/ObjectNormalizer.php b/src/Core/GraphQl/Serializer/ObjectNormalizer.php deleted file mode 100644 index fe0547429c4..00000000000 --- a/src/Core/GraphQl/Serializer/ObjectNormalizer.php +++ /dev/null @@ -1,97 +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); - -namespace ApiPlatform\Core\GraphQl\Serializer; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Util\ClassInfoTrait; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; -use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Decorates the output with GraphQL metadata when appropriate, but otherwise just - * passes through to the decorated normalizer. - */ -final class ObjectNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface -{ - use ClassInfoTrait; - - public const FORMAT = 'graphql'; - public const ITEM_RESOURCE_CLASS_KEY = '#itemResourceClass'; - public const ITEM_IDENTIFIERS_KEY = '#itemIdentifiers'; - - private $decorated; - private $iriConverter; - private $identifiersExtractor; - - public function __construct(NormalizerInterface $decorated, IriConverterInterface $iriConverter, IdentifiersExtractorInterface $identifiersExtractor) - { - $this->decorated = $decorated; - $this->iriConverter = $iriConverter; - $this->identifiersExtractor = $identifiersExtractor; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null, array $context = []): bool - { - return self::FORMAT === $format && $this->decorated->supportsNormalization($data, $format, $context); - } - - /** - * {@inheritdoc} - */ - public function hasCacheableSupportsMethod(): bool - { - return $this->decorated instanceof CacheableSupportsMethodInterface && $this->decorated->hasCacheableSupportsMethod(); - } - - /** - * {@inheritdoc} - * - * @throws UnexpectedValueException - * - * @return array|string|int|float|bool|\ArrayObject|null - */ - public function normalize($object, $format = null, array $context = []) - { - if (isset($context['api_resource'])) { - $originalResource = $context['api_resource']; - unset($context['api_resource']); - } - - $data = $this->decorated->normalize($object, $format, $context); - if (!\is_array($data)) { - throw new UnexpectedValueException('Expected data to be an array.'); - } - - if (!isset($originalResource)) { - return $data; - } - - if (isset($data['id'])) { - $data['_id'] = $data['id']; - $data['id'] = $this->iriConverter->getIriFromItem($originalResource); - } - - if (!($context['no_resolver_data'] ?? false)) { - $data[self::ITEM_RESOURCE_CLASS_KEY] = $this->getObjectClass($originalResource); - $data[self::ITEM_IDENTIFIERS_KEY] = $this->identifiersExtractor->getIdentifiersFromItem($originalResource); - } - - return $data; - } -} diff --git a/src/Core/GraphQl/Serializer/SerializerContextBuilder.php b/src/Core/GraphQl/Serializer/SerializerContextBuilder.php deleted file mode 100644 index eeeccdabcb6..00000000000 --- a/src/Core/GraphQl/Serializer/SerializerContextBuilder.php +++ /dev/null @@ -1,124 +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); - -namespace ApiPlatform\Core\GraphQl\Serializer; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use GraphQL\Type\Definition\ResolveInfo; -use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Builds the context used by the Symfony Serializer. - * - * @experimental - * - * @author Alan Poulain - */ -final class SerializerContextBuilder implements SerializerContextBuilderInterface -{ - private $resourceMetadataFactory; - private $nameConverter; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ?NameConverterInterface $nameConverter) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->nameConverter = $nameConverter; - } - - public function create(?string $resourceClass, string $operationName, array $resolverContext, bool $normalization): array - { - $resourceMetadata = $resourceClass ? $this->resourceMetadataFactory->create($resourceClass) : null; - - $context = [ - 'resource_class' => $resourceClass, - 'graphql_operation_name' => $operationName, - ]; - - if (isset($resolverContext['fields'])) { - $context['no_resolver_data'] = true; - } - - if ($resourceMetadata) { - $context['input'] = $resourceMetadata->getGraphqlAttribute($operationName, 'input', null, true); - $context['output'] = $resourceMetadata->getGraphqlAttribute($operationName, 'output', null, true); - - $key = $normalization ? 'normalization_context' : 'denormalization_context'; - $context = array_merge($resourceMetadata->getGraphqlAttribute($operationName, $key, [], true), $context); - } - - if ($normalization) { - $context['attributes'] = $this->fieldsToAttributes($resourceClass, $resourceMetadata, $resolverContext, $context); - } - - return $context; - } - - /** - * Retrieves fields, recursively replaces the "_id" key (the raw id) by "id" (the name of the property expected by the Serializer) and flattens edge and node structures (pagination). - */ - private function fieldsToAttributes(?string $resourceClass, ?ResourceMetadata $resourceMetadata, array $resolverContext, array $context): array - { - if (isset($resolverContext['fields'])) { - $fields = $resolverContext['fields']; - } else { - /** @var ResolveInfo $info */ - $info = $resolverContext['info']; - $fields = $info->getFieldSelection(\PHP_INT_MAX); - } - - $attributes = $this->replaceIdKeys($fields['edges']['node'] ?? $fields['collection'] ?? $fields, $resourceClass, $context); - - if ($resolverContext['is_mutation'] || $resolverContext['is_subscription']) { - if (!$resourceMetadata) { - throw new \LogicException('ResourceMetadata should always exist for a mutation or a subscription.'); - } - - $wrapFieldName = lcfirst($resourceMetadata->getShortName()); - - return $attributes[$wrapFieldName] ?? []; - } - - return $attributes; - } - - private function replaceIdKeys(array $fields, ?string $resourceClass, array $context): array - { - $denormalizedFields = []; - - foreach ($fields as $key => $value) { - if ('_id' === $key) { - $denormalizedFields['id'] = $fields['_id']; - - continue; - } - - $denormalizedFields[$this->denormalizePropertyName((string) $key, $resourceClass, $context)] = \is_array($fields[$key]) ? $this->replaceIdKeys($fields[$key], $resourceClass, $context) : $value; - } - - return $denormalizedFields; - } - - private function denormalizePropertyName(string $property, ?string $resourceClass, array $context): string - { - if (null === $this->nameConverter) { - return $property; - } - if ($this->nameConverter instanceof AdvancedNameConverterInterface) { - return $this->nameConverter->denormalize($property, $resourceClass, null, $context); - } - - return $this->nameConverter->denormalize($property); - } -} diff --git a/src/Core/GraphQl/Serializer/SerializerContextBuilderInterface.php b/src/Core/GraphQl/Serializer/SerializerContextBuilderInterface.php deleted file mode 100644 index cacf362fd28..00000000000 --- a/src/Core/GraphQl/Serializer/SerializerContextBuilderInterface.php +++ /dev/null @@ -1,26 +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); - -namespace ApiPlatform\Core\GraphQl\Serializer; - -/** - * Builds the context used by the Symfony Serializer. - * - * @experimental - * - * @author Alan Poulain - */ -interface SerializerContextBuilderInterface -{ - public function create(string $resourceClass, string $operationName, array $resolverContext, bool $normalization): array; -} diff --git a/src/Core/GraphQl/Subscription/MercureSubscriptionIriGenerator.php b/src/Core/GraphQl/Subscription/MercureSubscriptionIriGenerator.php deleted file mode 100644 index 7e0b49897de..00000000000 --- a/src/Core/GraphQl/Subscription/MercureSubscriptionIriGenerator.php +++ /dev/null @@ -1,60 +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); - -namespace ApiPlatform\Core\GraphQl\Subscription; - -use Symfony\Component\Mercure\HubRegistry; -use Symfony\Component\Routing\RequestContext; - -/** - * Generates Mercure-related IRIs from a subscription ID. - * - * @experimental - * - * @author Alan Poulain - */ -final class MercureSubscriptionIriGenerator implements MercureSubscriptionIriGeneratorInterface -{ - private $requestContext; - private $registry; - - /** - * @param HubRegistry|string $registry - */ - public function __construct(RequestContext $requestContext, $registry) - { - $this->requestContext = $requestContext; - $this->registry = $registry; - } - - public function generateTopicIri(string $subscriptionId): string - { - if ('' === $scheme = $this->requestContext->getScheme()) { - $scheme = 'https'; - } - if ('' === $host = $this->requestContext->getHost()) { - $host = 'api-platform.com'; - } - - return "$scheme://$host/subscriptions/$subscriptionId"; - } - - public function generateMercureUrl(string $subscriptionId, ?string $hub = null): string - { - if (!$this->registry instanceof HubRegistry) { - return sprintf('%s?topic=%s', $this->registry, $this->generateTopicIri($subscriptionId)); - } - - return sprintf('%s?topic=%s', $this->registry->getHub($hub)->getUrl(), $this->generateTopicIri($subscriptionId)); - } -} diff --git a/src/Core/GraphQl/Subscription/MercureSubscriptionIriGeneratorInterface.php b/src/Core/GraphQl/Subscription/MercureSubscriptionIriGeneratorInterface.php deleted file mode 100644 index 8f6d0920fa6..00000000000 --- a/src/Core/GraphQl/Subscription/MercureSubscriptionIriGeneratorInterface.php +++ /dev/null @@ -1,28 +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); - -namespace ApiPlatform\Core\GraphQl\Subscription; - -/** - * Generates Mercure-related IRIs from a subscription ID. - * - * @experimental - * - * @author Alan Poulain - */ -interface MercureSubscriptionIriGeneratorInterface -{ - public function generateTopicIri(string $subscriptionId): string; - - public function generateMercureUrl(string $subscriptionId, ?string $hub = null): string; -} diff --git a/src/Core/GraphQl/Subscription/SubscriptionIdentifierGenerator.php b/src/Core/GraphQl/Subscription/SubscriptionIdentifierGenerator.php deleted file mode 100644 index b64786e45b5..00000000000 --- a/src/Core/GraphQl/Subscription/SubscriptionIdentifierGenerator.php +++ /dev/null @@ -1,31 +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); - -namespace ApiPlatform\Core\GraphQl\Subscription; - -/** - * Generates an identifier used to identify a subscription. - * - * @experimental - * - * @author Alan Poulain - */ -final class SubscriptionIdentifierGenerator implements SubscriptionIdentifierGeneratorInterface -{ - public function generateSubscriptionIdentifier(array $fields): string - { - unset($fields['mercureUrl'], $fields['clientSubscriptionId']); - - return hash('sha256', print_r($fields, true)); - } -} diff --git a/src/Core/GraphQl/Subscription/SubscriptionIdentifierGeneratorInterface.php b/src/Core/GraphQl/Subscription/SubscriptionIdentifierGeneratorInterface.php deleted file mode 100644 index bcef927f80f..00000000000 --- a/src/Core/GraphQl/Subscription/SubscriptionIdentifierGeneratorInterface.php +++ /dev/null @@ -1,26 +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); - -namespace ApiPlatform\Core\GraphQl\Subscription; - -/** - * Generates an identifier used to identify a subscription. - * - * @experimental - * - * @author Alan Poulain - */ -interface SubscriptionIdentifierGeneratorInterface -{ - public function generateSubscriptionIdentifier(array $fields): string; -} diff --git a/src/Core/GraphQl/Subscription/SubscriptionManager.php b/src/Core/GraphQl/Subscription/SubscriptionManager.php deleted file mode 100644 index f8aae7ce6b6..00000000000 --- a/src/Core/GraphQl/Subscription/SubscriptionManager.php +++ /dev/null @@ -1,124 +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); - -namespace ApiPlatform\Core\GraphQl\Subscription; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait; -use ApiPlatform\Core\Util\ResourceClassInfoTrait; -use ApiPlatform\Core\Util\SortTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Psr\Cache\CacheItemPoolInterface; - -/** - * Manages all the queried subscriptions by creating their ID - * and saving to a cache the information needed to publish updated data. - * - * @experimental - * - * @author Alan Poulain - */ -final class SubscriptionManager implements SubscriptionManagerInterface -{ - use IdentifierTrait; - use ResourceClassInfoTrait; - use SortTrait; - - private $subscriptionsCache; - private $subscriptionIdentifierGenerator; - private $serializeStage; - private $iriConverter; - - public function __construct(CacheItemPoolInterface $subscriptionsCache, SubscriptionIdentifierGeneratorInterface $subscriptionIdentifierGenerator, SerializeStageInterface $serializeStage, IriConverterInterface $iriConverter) - { - $this->subscriptionsCache = $subscriptionsCache; - $this->subscriptionIdentifierGenerator = $subscriptionIdentifierGenerator; - $this->serializeStage = $serializeStage; - $this->iriConverter = $iriConverter; - } - - public function retrieveSubscriptionId(array $context, ?array $result): ?string - { - /** @var ResolveInfo $info */ - $info = $context['info']; - $fields = $info->getFieldSelection(\PHP_INT_MAX); - $this->arrayRecursiveSort($fields, 'ksort'); - $iri = $this->getIdentifierFromContext($context); - if (null === $iri) { - return null; - } - $subscriptionsCacheItem = $this->subscriptionsCache->getItem($this->encodeIriToCacheKey($iri)); - $subscriptions = []; - if ($subscriptionsCacheItem->isHit()) { - $subscriptions = $subscriptionsCacheItem->get(); - foreach ($subscriptions as [$subscriptionId, $subscriptionFields, $subscriptionResult]) { - if ($subscriptionFields === $fields) { - return $subscriptionId; - } - } - } - - $subscriptionId = $this->subscriptionIdentifierGenerator->generateSubscriptionIdentifier($fields); - unset($result['clientSubscriptionId']); - $subscriptions[] = [$subscriptionId, $fields, $result]; - $subscriptionsCacheItem->set($subscriptions); - $this->subscriptionsCache->save($subscriptionsCacheItem); - - return $subscriptionId; - } - - /** - * @param object $object - */ - public function getPushPayloads($object): array - { - $iri = $this->iriConverter->getIriFromItem($object); - $subscriptions = $this->getSubscriptionsFromIri($iri); - - $resourceClass = $this->getObjectClass($object); - - $payloads = []; - foreach ($subscriptions as [$subscriptionId, $subscriptionFields, $subscriptionResult]) { - $resolverContext = ['fields' => $subscriptionFields, 'is_collection' => false, 'is_mutation' => false, 'is_subscription' => true]; - - $data = ($this->serializeStage)($object, $resourceClass, 'update', $resolverContext); - unset($data['clientSubscriptionId']); - - if ($data !== $subscriptionResult) { - $payloads[] = [$subscriptionId, $data]; - } - } - - return $payloads; - } - - /** - * @return array - */ - private function getSubscriptionsFromIri(string $iri): array - { - $subscriptionsCacheItem = $this->subscriptionsCache->getItem($this->encodeIriToCacheKey($iri)); - - if ($subscriptionsCacheItem->isHit()) { - return $subscriptionsCacheItem->get(); - } - - return []; - } - - private function encodeIriToCacheKey(string $iri): string - { - return str_replace('/', '_', $iri); - } -} diff --git a/src/Core/GraphQl/Subscription/SubscriptionManagerInterface.php b/src/Core/GraphQl/Subscription/SubscriptionManagerInterface.php deleted file mode 100644 index e745b754b51..00000000000 --- a/src/Core/GraphQl/Subscription/SubscriptionManagerInterface.php +++ /dev/null @@ -1,28 +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); - -namespace ApiPlatform\Core\GraphQl\Subscription; - -/** - * Manages all the queried subscriptions and creates their ID. - * - * @experimental - * - * @author Alan Poulain - */ -interface SubscriptionManagerInterface -{ - public function retrieveSubscriptionId(array $context, ?array $result): ?string; - - public function getPushPayloads($object): array; -} diff --git a/src/Core/GraphQl/Type/Definition/IterableType.php b/src/Core/GraphQl/Type/Definition/IterableType.php deleted file mode 100644 index f51fbd7f437..00000000000 --- a/src/Core/GraphQl/Type/Definition/IterableType.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl\Type\Definition; - -class_exists(\ApiPlatform\GraphQl\Type\Definition\IterableType::class); - -if (false) { - final class IterableType extends \ApiPlatform\GraphQl\Type\Definition\IterableType - { - } -} diff --git a/src/Core/GraphQl/Type/Definition/UploadType.php b/src/Core/GraphQl/Type/Definition/UploadType.php deleted file mode 100644 index e1222e7f789..00000000000 --- a/src/Core/GraphQl/Type/Definition/UploadType.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl\Type\Definition; - -class_exists(\ApiPlatform\GraphQl\Type\Definition\UploadType::class); - -if (false) { - final class UploadType extends \ApiPlatform\GraphQl\Type\Definition\UploadType - { - } -} diff --git a/src/Core/GraphQl/Type/FieldsBuilder.php b/src/Core/GraphQl/Type/FieldsBuilder.php deleted file mode 100644 index ee549828262..00000000000 --- a/src/Core/GraphQl/Type/FieldsBuilder.php +++ /dev/null @@ -1,530 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -use ApiPlatform\Core\DataProvider\Pagination; -use ApiPlatform\Core\GraphQl\Resolver\Factory\ResolverFactoryInterface as ResolverFactoryLegacyInterface; -use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface as TypesContainerLegacyInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface; -use ApiPlatform\GraphQl\Type\Definition\TypeInterface; -use ApiPlatform\GraphQl\Type\TypesContainerInterface; -use ApiPlatform\Util\Inflector; -use GraphQL\Type\Definition\InputObjectType; -use GraphQL\Type\Definition\NullableType; -use GraphQL\Type\Definition\Type as GraphQLType; -use GraphQL\Type\Definition\WrappingType; -use Psr\Container\ContainerInterface; -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Builds the GraphQL fields. - * - * @author Alan Poulain - */ -final class FieldsBuilder implements FieldsBuilderInterface -{ - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $resourceMetadataFactory; - /** @var TypesContainerLegacyInterface|TypesContainerInterface */ - private $typesContainer; - private $typeBuilder; - /** @var TypeConverterInterface */ - private $typeConverter; - /** @var ResolverFactoryLegacyInterface|ResolverFactoryInterface */ - private $itemResolverFactory; - /** @var ResolverFactoryLegacyInterface|ResolverFactoryInterface */ - private $collectionResolverFactory; - /** @var ResolverFactoryLegacyInterface|ResolverFactoryInterface */ - private $itemMutationResolverFactory; - /** @var ResolverFactoryLegacyInterface|ResolverFactoryInterface */ - private $itemSubscriptionResolverFactory; - private $filterLocator; - private $pagination; - private $nameConverter; - private $nestingSeparator; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, $typesContainer, TypeBuilderInterface $typeBuilder, $typeConverter, $itemResolverFactory, $collectionResolverFactory, $itemMutationResolverFactory, $itemSubscriptionResolverFactory, ContainerInterface $filterLocator, Pagination $pagination, ?NameConverterInterface $nameConverter, string $nestingSeparator) - { - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->typesContainer = $typesContainer; - $this->typeBuilder = $typeBuilder; - $this->typeConverter = $typeConverter; - $this->itemResolverFactory = $itemResolverFactory; - $this->collectionResolverFactory = $collectionResolverFactory; - $this->itemMutationResolverFactory = $itemMutationResolverFactory; - $this->itemSubscriptionResolverFactory = $itemSubscriptionResolverFactory; - $this->filterLocator = $filterLocator; - $this->pagination = $pagination; - $this->nameConverter = $nameConverter; - $this->nestingSeparator = $nestingSeparator; - } - - /** - * {@inheritdoc} - */ - public function getNodeQueryFields(): array - { - return [ - 'type' => $this->typeBuilder->getNodeInterface(), - 'args' => [ - 'id' => ['type' => GraphQLType::nonNull(GraphQLType::id())], - ], - 'resolve' => ($this->itemResolverFactory)(), - ]; - } - - /** - * {@inheritdoc} - */ - public function getItemQueryFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $queryName, array $configuration): array - { - $shortName = $resourceMetadata->getShortName(); - $fieldName = lcfirst('item_query' === $queryName ? $shortName : $queryName.$shortName); - $description = $resourceMetadata->getGraphqlAttribute($queryName, 'description'); - $deprecationReason = $resourceMetadata->getGraphqlAttribute($queryName, 'deprecation_reason', null, true); - - if ($fieldConfiguration = $this->getResourceFieldConfiguration(null, $description, $deprecationReason, new Type(Type::BUILTIN_TYPE_OBJECT, true, $resourceClass), $resourceClass, false, $queryName, null, null)) { - $args = $this->resolveResourceArgs($configuration['args'] ?? [], $queryName, $shortName); - $configuration['args'] = $args ?: $configuration['args'] ?? ['id' => ['type' => GraphQLType::nonNull(GraphQLType::id())]]; - - return [$fieldName => array_merge($fieldConfiguration, $configuration)]; - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function getCollectionQueryFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $queryName, array $configuration): array - { - $shortName = $resourceMetadata->getShortName(); - $fieldName = lcfirst('collection_query' === $queryName ? $shortName : $queryName.$shortName); - $description = $resourceMetadata->getGraphqlAttribute($queryName, 'description'); - $deprecationReason = $resourceMetadata->getGraphqlAttribute($queryName, 'deprecation_reason', null, true); - - if ($fieldConfiguration = $this->getResourceFieldConfiguration(null, $description, $deprecationReason, new Type(Type::BUILTIN_TYPE_OBJECT, false, null, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, $resourceClass)), $resourceClass, false, $queryName, null, null)) { - $args = $this->resolveResourceArgs($configuration['args'] ?? [], $queryName, $shortName); - $configuration['args'] = $args ?: $configuration['args'] ?? $fieldConfiguration['args']; - - return [Inflector::pluralize($fieldName) => array_merge($fieldConfiguration, $configuration)]; - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function getMutationFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $mutationName): array - { - $mutationFields = []; - $shortName = $resourceMetadata->getShortName(); - $resourceType = new Type(Type::BUILTIN_TYPE_OBJECT, true, $resourceClass); - $description = $resourceMetadata->getGraphqlAttribute($mutationName, 'description', ucfirst("{$mutationName}s a $shortName."), false); - $deprecationReason = $resourceMetadata->getGraphqlAttribute($mutationName, 'deprecation_reason', null, true); - - if ($fieldConfiguration = $this->getResourceFieldConfiguration(null, $description, $deprecationReason, $resourceType, $resourceClass, false, null, $mutationName, null)) { - $fieldConfiguration['args'] += ['input' => $this->getResourceFieldConfiguration(null, null, $deprecationReason, $resourceType, $resourceClass, true, null, $mutationName, null)]; - } - - $mutationFields[$mutationName.$resourceMetadata->getShortName()] = $fieldConfiguration ?? []; - - return $mutationFields; - } - - /** - * {@inheritdoc} - */ - public function getSubscriptionFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $subscriptionName): array - { - $subscriptionFields = []; - $shortName = $resourceMetadata->getShortName(); - $resourceType = new Type(Type::BUILTIN_TYPE_OBJECT, true, $resourceClass); - $description = $resourceMetadata->getGraphqlAttribute($subscriptionName, 'description', "Subscribes to the $subscriptionName event of a $shortName.", false); - $deprecationReason = $resourceMetadata->getGraphqlAttribute($subscriptionName, 'deprecation_reason', null, true); - - if ($fieldConfiguration = $this->getResourceFieldConfiguration(null, $description, $deprecationReason, $resourceType, $resourceClass, false, null, null, $subscriptionName)) { - $fieldConfiguration['args'] += ['input' => $this->getResourceFieldConfiguration(null, null, $deprecationReason, $resourceType, $resourceClass, true, null, null, $subscriptionName)]; - } - - if (!$fieldConfiguration) { - return []; - } - - $subscriptionFields[$subscriptionName.$resourceMetadata->getShortName().'Subscribe'] = $fieldConfiguration; - - return $subscriptionFields; - } - - /** - * {@inheritdoc} - */ - public function getResourceObjectTypeFields(?string $resourceClass, ResourceMetadata $resourceMetadata, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, int $depth = 0, ?array $ioMetadata = null): array - { - $fields = []; - $idField = ['type' => GraphQLType::nonNull(GraphQLType::id())]; - $optionalIdField = ['type' => GraphQLType::id()]; - $clientMutationId = GraphQLType::string(); - $clientSubscriptionId = GraphQLType::string(); - - if (null !== $ioMetadata && \array_key_exists('class', $ioMetadata) && null === $ioMetadata['class']) { - if ($input) { - return ['clientMutationId' => $clientMutationId]; - } - - return []; - } - - if (null !== $subscriptionName && $input) { - return [ - 'id' => $idField, - 'clientSubscriptionId' => $clientSubscriptionId, - ]; - } - - if ('delete' === $mutationName) { - $fields = [ - 'id' => $idField, - ]; - - if ($input) { - $fields['clientMutationId'] = $clientMutationId; - } - - return $fields; - } - - if (!$input || 'create' !== $mutationName) { - $fields['id'] = $idField; - } - if ($input && $depth >= 1) { - $fields['id'] = $optionalIdField; - } - - ++$depth; // increment the depth for the call to getResourceFieldConfiguration. - - if (null !== $resourceClass) { - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $property) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $property, ['graphql_operation_name' => $subscriptionName ?? $mutationName ?? $queryName]); - if ( - null === ($propertyType = $propertyMetadata->getType()) - || (!$input && false === $propertyMetadata->isReadable()) - || ($input && null !== $mutationName && false === $propertyMetadata->isWritable()) - ) { - continue; - } - - if ($fieldConfiguration = $this->getResourceFieldConfiguration($property, $propertyMetadata->getDescription(), $propertyMetadata->getAttribute('deprecation_reason', null), $propertyType, $resourceClass, $input, $queryName, $mutationName, $subscriptionName, $depth, null !== $propertyMetadata->getAttribute('security'))) { - $fields['id' === $property ? '_id' : $this->normalizePropertyName($property, $resourceClass)] = $fieldConfiguration; - } - } - } - - if (null !== $mutationName && $input) { - $fields['clientMutationId'] = $clientMutationId; - } - - return $fields; - } - - /** - * {@inheritdoc} - */ - public function resolveResourceArgs(array $args, string $operationName, string $shortName): array - { - foreach ($args as $id => $arg) { - if (!isset($arg['type'])) { - throw new \InvalidArgumentException(sprintf('The argument "%s" of the custom operation "%s" in %s needs a "type" option.', $id, $operationName, $shortName)); - } - - $args[$id]['type'] = $this->typeConverter->resolveType($arg['type']); - } - - return $args; - } - - /** - * Get the field configuration of a resource. - * - * @see http://webonyx.github.io/graphql-php/type-system/object-types/ - */ - private function getResourceFieldConfiguration(?string $property, ?string $fieldDescription, ?string $deprecationReason, Type $type, string $rootResource, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, int $depth = 0, bool $forceNullable = false): ?array - { - try { - if ( - $this->typeBuilder->isCollection($type) && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $resourceClass = $collectionValueType->getClassName(); - } else { - $resourceClass = $type->getClassName(); - } - - if (null === $graphqlType = $this->convertType($type, $input, $queryName, $mutationName, $subscriptionName, $resourceClass ?? '', $rootResource, $property, $depth, $forceNullable)) { - return null; - } - - $graphqlWrappedType = $graphqlType instanceof WrappingType ? $graphqlType->getWrappedType(true) : $graphqlType; - $isStandardGraphqlType = \in_array($graphqlWrappedType, GraphQLType::getStandardTypes(), true); - if ($isStandardGraphqlType) { - $resourceClass = ''; - } - - $resourceMetadata = null; - if (!empty($resourceClass)) { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - } - } - - // Check mercure attribute if it's a subscription at the root level. - if ($subscriptionName && null === $property && (!$resourceMetadata || !$resourceMetadata->getAttribute('mercure', false))) { - return null; - } - - $args = []; - if (!$input && null === $mutationName && null === $subscriptionName && !$isStandardGraphqlType && $this->typeBuilder->isCollection($type)) { - if ($this->pagination->isGraphQlEnabled($resourceClass, $queryName)) { - $args = $this->getGraphQlPaginationArgs($resourceClass, $queryName); - } - - $args = $this->getFilterArgs($args, $resourceClass, $resourceMetadata, $rootResource, $property, $queryName, $mutationName, $depth); - } - - if ($isStandardGraphqlType || $input) { - $resolve = null; - } elseif (($mutationName || $subscriptionName) && $depth <= 0) { - if ($mutationName) { - $resolve = ($this->itemMutationResolverFactory)($resourceClass, $rootResource, $mutationName); - } else { - $resolve = ($this->itemSubscriptionResolverFactory)($resourceClass, $rootResource, $subscriptionName); - } - } elseif ($this->typeBuilder->isCollection($type)) { - $resolve = ($this->collectionResolverFactory)($resourceClass, $rootResource, $queryName); - } else { - $resolve = ($this->itemResolverFactory)($resourceClass, $rootResource, $queryName); - } - - return [ - 'type' => $graphqlType, - 'description' => $fieldDescription, - 'args' => $args, - 'resolve' => $resolve, - 'deprecationReason' => $deprecationReason, - ]; - } catch (InvalidTypeException $e) { - // just ignore invalid types - } - - return null; - } - - private function getGraphQlPaginationArgs(string $resourceClass, string $queryName): array - { - $paginationType = $this->pagination->getGraphQlPaginationType($resourceClass, $queryName); - - if ('cursor' === $paginationType) { - return [ - 'first' => [ - 'type' => GraphQLType::int(), - 'description' => 'Returns the first n elements from the list.', - ], - 'last' => [ - 'type' => GraphQLType::int(), - 'description' => 'Returns the last n elements from the list.', - ], - 'before' => [ - 'type' => GraphQLType::string(), - 'description' => 'Returns the elements in the list that come before the specified cursor.', - ], - 'after' => [ - 'type' => GraphQLType::string(), - 'description' => 'Returns the elements in the list that come after the specified cursor.', - ], - ]; - } - - $paginationOptions = $this->pagination->getOptions(); - - $args = [ - $paginationOptions['page_parameter_name'] => [ - 'type' => GraphQLType::int(), - 'description' => 'Returns the current page.', - ], - ]; - - if ($paginationOptions['client_items_per_page']) { - $args[$paginationOptions['items_per_page_parameter_name']] = [ - 'type' => GraphQLType::int(), - 'description' => 'Returns the number of items per page.', - ]; - } - - return $args; - } - - private function getFilterArgs(array $args, ?string $resourceClass, ?ResourceMetadata $resourceMetadata, string $rootResource, ?string $property, ?string $queryName, ?string $mutationName, int $depth): array - { - if (null === $resourceMetadata || null === $resourceClass) { - return $args; - } - - foreach ($resourceMetadata->getGraphqlAttribute($queryName, 'filters', [], true) as $filterId) { - if (null === $this->filterLocator || !$this->filterLocator->has($filterId)) { - continue; - } - - foreach ($this->filterLocator->get($filterId)->getDescription($resourceClass) as $key => $value) { - $nullable = isset($value['required']) ? !$value['required'] : true; - $filterType = \in_array($value['type'], Type::$builtinTypes, true) ? new Type($value['type'], $nullable) : new Type('object', $nullable, $value['type']); - $graphqlFilterType = $this->convertType($filterType, false, $queryName, $mutationName, null, $resourceClass, $rootResource, $property, $depth); - - if ('[]' === substr($key, -2)) { - $graphqlFilterType = GraphQLType::listOf($graphqlFilterType); - $key = substr($key, 0, -2).'_list'; - } - - /** @var string $key */ - $key = str_replace('.', $this->nestingSeparator, $key); - - parse_str($key, $parsed); - if (\array_key_exists($key, $parsed) && \is_array($parsed[$key])) { - $parsed = [$key => '']; - } - array_walk_recursive($parsed, static function (&$value) use ($graphqlFilterType) { - $value = $graphqlFilterType; - }); - $args = $this->mergeFilterArgs($args, $parsed, $resourceMetadata, $key); - } - } - - return $this->convertFilterArgsToTypes($args); - } - - private function mergeFilterArgs(array $args, array $parsed, ResourceMetadata $resourceMetadata = null, $original = ''): array - { - foreach ($parsed as $key => $value) { - // Never override keys that cannot be merged - if (isset($args[$key]) && !\is_array($args[$key])) { - continue; - } - - if (\is_array($value)) { - $value = $this->mergeFilterArgs($args[$key] ?? [], $value); - if (!isset($value['#name'])) { - $name = (false === $pos = strrpos($original, '[')) ? $original : substr($original, 0, (int) $pos); - $value['#name'] = ($resourceMetadata ? $resourceMetadata->getShortName() : '').'Filter_'.strtr($name, ['[' => '_', ']' => '', '.' => '__']); - } - } - - $args[$key] = $value; - } - - return $args; - } - - private function convertFilterArgsToTypes(array $args): array - { - foreach ($args as $key => $value) { - if (strpos($key, '.')) { - // Declare relations/nested fields in a GraphQL compatible syntax. - $args[str_replace('.', $this->nestingSeparator, $key)] = $value; - unset($args[$key]); - } - } - - foreach ($args as $key => $value) { - if (!\is_array($value) || !isset($value['#name'])) { - continue; - } - - $name = $value['#name']; - - if ($this->typesContainer->has($name)) { - $args[$key] = $this->typesContainer->get($name); - continue; - } - - unset($value['#name']); - - $filterArgType = GraphQLType::listOf(new InputObjectType([ - 'name' => $name, - 'fields' => $this->convertFilterArgsToTypes($value), - ])); - - $this->typesContainer->set($name, $filterArgType); - - $args[$key] = $filterArgType; - } - - return $args; - } - - /** - * Converts a built-in type to its GraphQL equivalent. - * - * @throws InvalidTypeException - */ - private function convertType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $resourceClass, string $rootResource, ?string $property, int $depth, bool $forceNullable = false) - { - $graphqlType = $this->typeConverter->convertType($type, $input, $queryName, $mutationName, $subscriptionName, $resourceClass, $rootResource, $property, $depth); - - if (null === $graphqlType) { - throw new InvalidTypeException(sprintf('The type "%s" is not supported.', $type->getBuiltinType())); - } - - if (\is_string($graphqlType)) { - if (!$this->typesContainer->has($graphqlType)) { - throw new InvalidTypeException(sprintf('The GraphQL type %s is not valid. Valid types are: %s. Have you registered this type by implementing %s?', $graphqlType, implode(', ', array_keys($this->typesContainer->all())), TypeInterface::class)); - } - - $graphqlType = $this->typesContainer->get($graphqlType); - } - - if ($this->typeBuilder->isCollection($type)) { - $operationName = $queryName ?? $mutationName ?? $subscriptionName; - - return $this->pagination->isGraphQlEnabled($resourceClass, $operationName) && !$input ? $this->typeBuilder->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $operationName) : GraphQLType::listOf($graphqlType); - } - - return $forceNullable || !$graphqlType instanceof NullableType || $type->isNullable() || (null !== $mutationName && 'update' === $mutationName) - ? $graphqlType - : GraphQLType::nonNull($graphqlType); - } - - private function normalizePropertyName(string $property, string $resourceClass): string - { - if (null === $this->nameConverter) { - return $property; - } - if ($this->nameConverter instanceof AdvancedNameConverterInterface) { - return $this->nameConverter->normalize($property, $resourceClass); - } - - return $this->nameConverter->normalize($property); - } -} diff --git a/src/Core/GraphQl/Type/FieldsBuilderInterface.php b/src/Core/GraphQl/Type/FieldsBuilderInterface.php deleted file mode 100644 index c693b9a5e9a..00000000000 --- a/src/Core/GraphQl/Type/FieldsBuilderInterface.php +++ /dev/null @@ -1,59 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Interface implemented to build GraphQL fields. - * - * @author Alan Poulain - */ -interface FieldsBuilderInterface -{ - /** - * Gets the fields of a node for a query. - */ - public function getNodeQueryFields(): array; - - /** - * Gets the item query fields of the schema. - */ - public function getItemQueryFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $queryName, array $configuration): array; - - /** - * Gets the collection query fields of the schema. - */ - public function getCollectionQueryFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $queryName, array $configuration): array; - - /** - * Gets the mutation fields of the schema. - */ - public function getMutationFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $mutationName): array; - - /** - * Gets the subscription fields of the schema. - */ - public function getSubscriptionFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $subscriptionName): array; - - /** - * Gets the fields of the type of the given resource. - */ - public function getResourceObjectTypeFields(?string $resourceClass, ResourceMetadata $resourceMetadata, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, int $depth, ?array $ioMetadata): array; - - /** - * Resolve the args of a resource by resolving its types. - */ - public function resolveResourceArgs(array $args, string $operationName, string $shortName): array; -} diff --git a/src/Core/GraphQl/Type/SchemaBuilder.php b/src/Core/GraphQl/Type/SchemaBuilder.php deleted file mode 100644 index f9107e55f28..00000000000 --- a/src/Core/GraphQl/Type/SchemaBuilder.php +++ /dev/null @@ -1,132 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface as TypesContainerLegacyInterface; -use ApiPlatform\Core\GraphQl\Type\TypesFactoryInterface as TypesFactoryLegacyInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\GraphQl\Type\TypesContainerInterface; -use ApiPlatform\GraphQl\Type\TypesFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use GraphQL\Type\Definition\ObjectType; -use GraphQL\Type\Definition\WrappingType; -use GraphQL\Type\Schema; - -/** - * Builds the GraphQL schema. - * - * @author Raoul Clais - * @author Alan Poulain - * @author Kévin Dunglas - */ -final class SchemaBuilder implements SchemaBuilderInterface -{ - private $resourceNameCollectionFactory; - private $resourceMetadataFactory; - /** @var TypesFactoryLegacyInterface|TypesFactoryInterface */ - private $typesFactory; - /** @var TypesContainerLegacyInterface|TypesContainerInterface */ - private $typesContainer; - private $fieldsBuilder; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, $typesFactory, $typesContainer, FieldsBuilderInterface $fieldsBuilder) - { - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->typesFactory = $typesFactory; - $this->typesContainer = $typesContainer; - $this->fieldsBuilder = $fieldsBuilder; - } - - public function getSchema(): Schema - { - $types = $this->typesFactory->getTypes(); - foreach ($types as $typeId => $type) { - $this->typesContainer->set($typeId, $type); - } - - $queryFields = ['node' => $this->fieldsBuilder->getNodeQueryFields()]; - $mutationFields = []; - $subscriptionFields = []; - - foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - /** @var array $graphqlConfiguration */ - $graphqlConfiguration = $resourceMetadata->getGraphql() ?? []; - foreach ($graphqlConfiguration as $operationName => $value) { - if ('item_query' === $operationName) { - $queryFields += $this->fieldsBuilder->getItemQueryFields($resourceClass, $resourceMetadata, $operationName, []); - - continue; - } - - if ('collection_query' === $operationName) { - $queryFields += $this->fieldsBuilder->getCollectionQueryFields($resourceClass, $resourceMetadata, $operationName, []); - - continue; - } - - if ($resourceMetadata->getGraphqlAttribute($operationName, 'item_query')) { - $queryFields += $this->fieldsBuilder->getItemQueryFields($resourceClass, $resourceMetadata, $operationName, $value); - - continue; - } - - if ($resourceMetadata->getGraphqlAttribute($operationName, 'collection_query')) { - $queryFields += $this->fieldsBuilder->getCollectionQueryFields($resourceClass, $resourceMetadata, $operationName, $value); - - continue; - } - - if ('update' === $operationName) { - $subscriptionFields += $this->fieldsBuilder->getSubscriptionFields($resourceClass, $resourceMetadata, $operationName); - } - - $mutationFields += $this->fieldsBuilder->getMutationFields($resourceClass, $resourceMetadata, $operationName); - } - } - - $schema = [ - 'query' => new ObjectType([ - 'name' => 'Query', - 'fields' => $queryFields, - ]), - 'typeLoader' => function ($name) { - $type = $this->typesContainer->get($name); - - if ($type instanceof WrappingType) { - return $type->getWrappedType(true); - } - - return $type; - }, - ]; - - if ($mutationFields) { - $schema['mutation'] = new ObjectType([ - 'name' => 'Mutation', - 'fields' => $mutationFields, - ]); - } - - if ($subscriptionFields) { - $schema['subscription'] = new ObjectType([ - 'name' => 'Subscription', - 'fields' => $subscriptionFields, - ]); - } - - return new Schema($schema); - } -} diff --git a/src/Core/GraphQl/Type/SchemaBuilderInterface.php b/src/Core/GraphQl/Type/SchemaBuilderInterface.php deleted file mode 100644 index 69fd7f7748a..00000000000 --- a/src/Core/GraphQl/Type/SchemaBuilderInterface.php +++ /dev/null @@ -1,26 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -use GraphQL\Type\Schema; - -/** - * Builds a GraphQL schema. - * - * @author Alan Poulain - */ -interface SchemaBuilderInterface -{ - public function getSchema(): Schema; -} diff --git a/src/Core/GraphQl/Type/TypeBuilder.php b/src/Core/GraphQl/Type/TypeBuilder.php deleted file mode 100644 index 93cc3491836..00000000000 --- a/src/Core/GraphQl/Type/TypeBuilder.php +++ /dev/null @@ -1,286 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -use ApiPlatform\Core\DataProvider\Pagination; -use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface as TypesContainerLegacyInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\GraphQl\Type\TypesContainerInterface; -use GraphQL\Type\Definition\InputObjectType; -use GraphQL\Type\Definition\InterfaceType; -use GraphQL\Type\Definition\NonNull; -use GraphQL\Type\Definition\ObjectType; -use GraphQL\Type\Definition\Type as GraphQLType; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; - -/** - * Builds the GraphQL types. - * - * @author Alan Poulain - */ -final class TypeBuilder implements TypeBuilderInterface -{ - /** @var TypesContainerLegacyInterface|TypesContainerInterface */ - private $typesContainer; - private $defaultFieldResolver; - private $fieldsBuilderLocator; - private $pagination; - - public function __construct($typesContainer, callable $defaultFieldResolver, ContainerInterface $fieldsBuilderLocator, Pagination $pagination) - { - $this->typesContainer = $typesContainer; - $this->defaultFieldResolver = $defaultFieldResolver; - $this->fieldsBuilderLocator = $fieldsBuilderLocator; - $this->pagination = $pagination; - } - - /** - * {@inheritdoc} - */ - public function getResourceObjectType(?string $resourceClass, ResourceMetadata $resourceMetadata, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, bool $wrapped = false, int $depth = 0): GraphQLType - { - $shortName = $resourceMetadata->getShortName(); - - if (null !== $mutationName) { - $shortName = $mutationName.ucfirst($shortName); - } - if (null !== $subscriptionName) { - $shortName = $subscriptionName.ucfirst($shortName).'Subscription'; - } - if ($input) { - if ($depth > 0) { - $shortName .= 'Nested'; - } - $shortName .= 'Input'; - } elseif (null !== $mutationName || null !== $subscriptionName) { - if ($depth > 0) { - $shortName .= 'Nested'; - } - $shortName .= 'Payload'; - } - if (('item_query' === $queryName || 'collection_query' === $queryName) - && $resourceMetadata->getGraphqlAttribute('item_query', 'normalization_context', [], true) !== $resourceMetadata->getGraphqlAttribute('collection_query', 'normalization_context', [], true)) { - if ('item_query' === $queryName) { - $shortName .= 'Item'; - } - if ('collection_query' === $queryName) { - $shortName .= 'Collection'; - } - } - if ($wrapped && (null !== $mutationName || null !== $subscriptionName)) { - $shortName .= 'Data'; - } - - if ($this->typesContainer->has($shortName)) { - $resourceObjectType = $this->typesContainer->get($shortName); - if (!($resourceObjectType instanceof ObjectType || $resourceObjectType instanceof NonNull)) { - throw new \LogicException(sprintf('Expected GraphQL type "%s" to be %s.', $shortName, implode('|', [ObjectType::class, NonNull::class]))); - } - - return $resourceObjectType; - } - - $ioMetadata = $resourceMetadata->getGraphqlAttribute($subscriptionName ?? $mutationName ?? $queryName, $input ? 'input' : 'output', null, true); - if (null !== $ioMetadata && \array_key_exists('class', $ioMetadata) && null !== $ioMetadata['class']) { - $resourceClass = $ioMetadata['class']; - } - - $wrapData = !$wrapped && (null !== $mutationName || null !== $subscriptionName) && !$input && $depth < 1; - - $configuration = [ - 'name' => $shortName, - 'description' => $resourceMetadata->getDescription(), - 'resolveField' => $this->defaultFieldResolver, - 'fields' => function () use ($resourceClass, $resourceMetadata, $input, $queryName, $mutationName, $subscriptionName, $wrapData, $depth, $ioMetadata) { - if ($wrapData) { - $queryNormalizationContext = $resourceMetadata->getGraphqlAttribute($queryName ?? '', 'normalization_context', [], true); - $mutationNormalizationContext = $resourceMetadata->getGraphqlAttribute($mutationName ?? $subscriptionName ?? '', 'normalization_context', [], true); - // Use a new type for the wrapped object only if there is a specific normalization context for the mutation or the subscription. - // If not, use the query type in order to ensure the client cache could be used. - $useWrappedType = $queryNormalizationContext !== $mutationNormalizationContext; - - $fields = [ - lcfirst($resourceMetadata->getShortName()) => $useWrappedType ? - $this->getResourceObjectType($resourceClass, $resourceMetadata, $input, $queryName, $mutationName, $subscriptionName, true, $depth) : - $this->getResourceObjectType($resourceClass, $resourceMetadata, $input, $queryName ?? 'item_query', null, null, true, $depth), - ]; - - if (null !== $subscriptionName) { - $fields['clientSubscriptionId'] = GraphQLType::string(); - if ($resourceMetadata->getAttribute('mercure', false)) { - $fields['mercureUrl'] = GraphQLType::string(); - } - - return $fields; - } - - return $fields + ['clientMutationId' => GraphQLType::string()]; - } - - /** @var FieldsBuilderInterface $fieldsBuilder */ - $fieldsBuilder = $this->fieldsBuilderLocator->get('api_platform.graphql.fields_builder'); - $fields = $fieldsBuilder->getResourceObjectTypeFields($resourceClass, $resourceMetadata, $input, $queryName, $mutationName, $subscriptionName, $depth, $ioMetadata); - - if ($input && null !== $mutationName && null !== $mutationArgs = $resourceMetadata->getGraphql()[$mutationName]['args'] ?? null) { - return $fieldsBuilder->resolveResourceArgs($mutationArgs, $mutationName, $resourceMetadata->getShortName()) + ['clientMutationId' => $fields['clientMutationId']]; - } - - return $fields; - }, - 'interfaces' => $wrapData ? [] : [$this->getNodeInterface()], - ]; - - $resourceObjectType = $input ? GraphQLType::nonNull(new InputObjectType($configuration)) : new ObjectType($configuration); - $this->typesContainer->set($shortName, $resourceObjectType); - - return $resourceObjectType; - } - - /** - * {@inheritdoc} - */ - public function getNodeInterface(): InterfaceType - { - if ($this->typesContainer->has('Node')) { - $nodeInterface = $this->typesContainer->get('Node'); - if (!$nodeInterface instanceof InterfaceType) { - throw new \LogicException(sprintf('Expected GraphQL type "Node" to be %s.', InterfaceType::class)); - } - - return $nodeInterface; - } - - $nodeInterface = new InterfaceType([ - 'name' => 'Node', - 'description' => 'A node, according to the Relay specification.', - 'fields' => [ - 'id' => [ - 'type' => GraphQLType::nonNull(GraphQLType::id()), - 'description' => 'The id of this node.', - ], - ], - 'resolveType' => function ($value) { - if (!isset($value[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY])) { - return null; - } - - $shortName = (new \ReflectionClass($value[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY]))->getShortName(); - - return $this->typesContainer->has($shortName) ? $this->typesContainer->get($shortName) : null; - }, - ]); - - $this->typesContainer->set('Node', $nodeInterface); - - return $nodeInterface; - } - - /** - * {@inheritdoc} - */ - public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, string $operationName): GraphQLType - { - $shortName = $resourceType->name; - $paginationType = $this->pagination->getGraphQlPaginationType($resourceClass, $operationName); - - $connectionTypeKey = sprintf('%s%sConnection', $shortName, ucfirst($paginationType)); - if ($this->typesContainer->has($connectionTypeKey)) { - return $this->typesContainer->get($connectionTypeKey); - } - - $paginationType = $this->pagination->getGraphQlPaginationType($resourceClass, $operationName); - - $fields = 'cursor' === $paginationType ? - $this->getCursorBasedPaginationFields($resourceType) : - $this->getPageBasedPaginationFields($resourceType); - - $configuration = [ - 'name' => $connectionTypeKey, - 'description' => sprintf("%s connection for $shortName.", ucfirst($paginationType)), - 'fields' => $fields, - ]; - - $resourcePaginatedCollectionType = new ObjectType($configuration); - $this->typesContainer->set($connectionTypeKey, $resourcePaginatedCollectionType); - - return $resourcePaginatedCollectionType; - } - - /** - * {@inheritdoc} - */ - public function isCollection(Type $type): bool - { - return $type->isCollection() && ($collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType()) && null !== $collectionValueType->getClassName(); - } - - private function getCursorBasedPaginationFields(GraphQLType $resourceType): array - { - $shortName = $resourceType->name; - - $edgeObjectTypeConfiguration = [ - 'name' => "{$shortName}Edge", - 'description' => "Edge of $shortName.", - 'fields' => [ - 'node' => $resourceType, - 'cursor' => GraphQLType::nonNull(GraphQLType::string()), - ], - ]; - $edgeObjectType = new ObjectType($edgeObjectTypeConfiguration); - $this->typesContainer->set("{$shortName}Edge", $edgeObjectType); - - $pageInfoObjectTypeConfiguration = [ - 'name' => "{$shortName}PageInfo", - 'description' => 'Information about the current page.', - 'fields' => [ - 'endCursor' => GraphQLType::string(), - 'startCursor' => GraphQLType::string(), - 'hasNextPage' => GraphQLType::nonNull(GraphQLType::boolean()), - 'hasPreviousPage' => GraphQLType::nonNull(GraphQLType::boolean()), - ], - ]; - $pageInfoObjectType = new ObjectType($pageInfoObjectTypeConfiguration); - $this->typesContainer->set("{$shortName}PageInfo", $pageInfoObjectType); - - return [ - 'edges' => GraphQLType::listOf($edgeObjectType), - 'pageInfo' => GraphQLType::nonNull($pageInfoObjectType), - 'totalCount' => GraphQLType::nonNull(GraphQLType::int()), - ]; - } - - private function getPageBasedPaginationFields(GraphQLType $resourceType): array - { - $shortName = $resourceType->name; - - $paginationInfoObjectTypeConfiguration = [ - 'name' => "{$shortName}PaginationInfo", - 'description' => 'Information about the pagination.', - 'fields' => [ - 'itemsPerPage' => GraphQLType::nonNull(GraphQLType::int()), - 'lastPage' => GraphQLType::nonNull(GraphQLType::int()), - 'totalCount' => GraphQLType::nonNull(GraphQLType::int()), - ], - ]; - $paginationInfoObjectType = new ObjectType($paginationInfoObjectTypeConfiguration); - $this->typesContainer->set("{$shortName}PaginationInfo", $paginationInfoObjectType); - - return [ - 'collection' => GraphQLType::listOf($resourceType), - 'paginationInfo' => GraphQLType::nonNull($paginationInfoObjectType), - ]; - } -} diff --git a/src/Core/GraphQl/Type/TypeBuilderInterface.php b/src/Core/GraphQl/Type/TypeBuilderInterface.php deleted file mode 100644 index 3270a8d881c..00000000000 --- a/src/Core/GraphQl/Type/TypeBuilderInterface.php +++ /dev/null @@ -1,51 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use GraphQL\Type\Definition\InterfaceType; -use GraphQL\Type\Definition\NonNull; -use GraphQL\Type\Definition\ObjectType; -use GraphQL\Type\Definition\Type as GraphQLType; -use Symfony\Component\PropertyInfo\Type; - -/** - * Interface implemented to build a GraphQL type. - * - * @author Alan Poulain - */ -interface TypeBuilderInterface -{ - /** - * Gets the object type of the given resource. - * - * @return ObjectType|NonNull the object type, possibly wrapped by NonNull - */ - public function getResourceObjectType(?string $resourceClass, ResourceMetadata $resourceMetadata, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, bool $wrapped, int $depth): GraphQLType; - - /** - * Get the interface type of a node. - */ - public function getNodeInterface(): InterfaceType; - - /** - * Gets the type of a paginated collection of the given resource type. - */ - public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, string $operationName): GraphQLType; - - /** - * Returns true if a type is a collection. - */ - public function isCollection(Type $type): bool; -} diff --git a/src/Core/GraphQl/Type/TypeConverter.php b/src/Core/GraphQl/Type/TypeConverter.php deleted file mode 100644 index 96e58ad2502..00000000000 --- a/src/Core/GraphQl/Type/TypeConverter.php +++ /dev/null @@ -1,205 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface as TypesContainerLegacyInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\GraphQl\Type\TypesContainerInterface; -use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use GraphQL\Error\SyntaxError; -use GraphQL\Language\AST\ListTypeNode; -use GraphQL\Language\AST\NamedTypeNode; -use GraphQL\Language\AST\NonNullTypeNode; -use GraphQL\Language\AST\TypeNode; -use GraphQL\Language\Parser; -use GraphQL\Type\Definition\NullableType; -use GraphQL\Type\Definition\Type as GraphQLType; -use Symfony\Component\PropertyInfo\Type; - -/** - * Converts a type to its GraphQL equivalent. - * - * @author Alan Poulain - */ -final class TypeConverter implements TypeConverterInterface -{ - private $typeBuilder; - /** @var TypesContainerLegacyInterface|TypesContainerInterface */ - private $typesContainer; - private $resourceMetadataFactory; - /** @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface|null */ - private $propertyMetadataFactory; - - public function __construct(TypeBuilderInterface $typeBuilder, $typesContainer, ResourceMetadataFactoryInterface $resourceMetadataFactory, $propertyMetadataFactory = null) - { - $this->typeBuilder = $typeBuilder; - $this->typesContainer = $typesContainer; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - - if (null === $this->propertyMetadataFactory) { - @trigger_error(sprintf('Not injecting %s in the TypeConverter is deprecated since 2.7 and will not be supported in 3.0.', PropertyMetadataFactoryInterface::class), \E_USER_DEPRECATED); - } - } - - /** - * {@inheritdoc} - */ - public function convertType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $resourceClass, string $rootResource, ?string $property, int $depth) - { - switch ($type->getBuiltinType()) { - case Type::BUILTIN_TYPE_BOOL: - return GraphQLType::boolean(); - case Type::BUILTIN_TYPE_INT: - return GraphQLType::int(); - case Type::BUILTIN_TYPE_FLOAT: - return GraphQLType::float(); - case Type::BUILTIN_TYPE_STRING: - return GraphQLType::string(); - case Type::BUILTIN_TYPE_ARRAY: - case Type::BUILTIN_TYPE_ITERABLE: - if ($resourceType = $this->getResourceType($type, $input, $queryName, $mutationName, $subscriptionName, $rootResource, $property, $depth)) { - return $resourceType; - } - - return 'Iterable'; - case Type::BUILTIN_TYPE_OBJECT: - if (is_a($type->getClassName(), \DateTimeInterface::class, true)) { - return GraphQLType::string(); - } - - return $this->getResourceType($type, $input, $queryName, $mutationName, $subscriptionName, $rootResource, $property, $depth); - default: - return null; - } - } - - /** - * {@inheritdoc} - */ - public function resolveType(string $type): ?GraphQLType - { - try { - $astTypeNode = Parser::parseType($type); - } catch (SyntaxError $e) { - throw new InvalidArgumentException(sprintf('"%s" is not a valid GraphQL type.', $type), 0, $e); - } - - if ($graphQlType = $this->resolveAstTypeNode($astTypeNode, $type)) { - return $graphQlType; - } - - throw new InvalidArgumentException(sprintf('The type "%s" was not resolved.', $type)); - } - - private function getResourceType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $rootResource, ?string $property, int $depth): ?GraphQLType - { - if ( - $this->typeBuilder->isCollection($type) && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $resourceClass = $collectionValueType->getClassName(); - } else { - $resourceClass = $type->getClassName(); - } - - if (null === $resourceClass) { - return null; - } - - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (null === $resourceMetadata->getGraphql()) { - return null; - } - if ('Node' === $resourceMetadata->getShortName()) { - throw new \UnexpectedValueException('A "Node" resource cannot be used with GraphQL because the type is already used by the Relay specification.'); - } - } catch (ResourceClassNotFoundException $e) { - // Skip objects that are not resources for now - return null; - } - - $propertyMetadata = null; - if ($property && $this->propertyMetadataFactory) { - $rootResourceMetadata = null; - try { - $rootResourceMetadata = $this->resourceMetadataFactory->create($rootResource); - } catch (ResourceClassNotFoundException $e) { - } - - $context = [ - 'normalization_groups' => $rootResourceMetadata ? $rootResourceMetadata->getGraphqlAttribute($queryName ?? $mutationName ?? $subscriptionName, 'normalization_context', [], true)['groups'] ?? null : null, - 'denormalization_groups' => $rootResourceMetadata ? $rootResourceMetadata->getGraphqlAttribute($queryName ?? $mutationName ?? $subscriptionName, 'denormalization_context', [], true)['groups'] ?? null : null, - ]; - $propertyMetadata = $this->propertyMetadataFactory->create($rootResource, $property, $context); - } - - if ($input && $depth > 0 && (!$propertyMetadata || !$propertyMetadata->isWritableLink())) { - return GraphQLType::string(); - } - - return $this->typeBuilder->getResourceObjectType($resourceClass, $resourceMetadata, $input, $queryName, $mutationName, $subscriptionName, false, $depth); - } - - private function resolveAstTypeNode(TypeNode $astTypeNode, string $fromType): ?GraphQLType - { - if ($astTypeNode instanceof NonNullTypeNode) { - /** @var NullableType|null $nullableAstTypeNode */ - $nullableAstTypeNode = $this->resolveNullableAstTypeNode($astTypeNode->type, $fromType); - - return $nullableAstTypeNode ? GraphQLType::nonNull($nullableAstTypeNode) : null; - } - - return $this->resolveNullableAstTypeNode($astTypeNode, $fromType); - } - - private function resolveNullableAstTypeNode(TypeNode $astTypeNode, string $fromType): ?GraphQLType - { - if ($astTypeNode instanceof ListTypeNode) { - /** @var TypeNode $astTypeNodeElement */ - $astTypeNodeElement = $astTypeNode->type; - - return GraphQLType::listOf($this->resolveAstTypeNode($astTypeNodeElement, $fromType)); - } - - if (!$astTypeNode instanceof NamedTypeNode) { - return null; - } - - $typeName = $astTypeNode->name->value; - - switch ($typeName) { - case GraphQLType::STRING: - return GraphQLType::string(); - case GraphQLType::INT: - return GraphQLType::int(); - case GraphQLType::BOOLEAN: - return GraphQLType::boolean(); - case GraphQLType::FLOAT: - return GraphQLType::float(); - case GraphQLType::ID: - return GraphQLType::id(); - default: - if ($this->typesContainer->has($typeName)) { - return $this->typesContainer->get($typeName); - } - - return null; - } - } -} diff --git a/src/Core/GraphQl/Type/TypeConverterInterface.php b/src/Core/GraphQl/Type/TypeConverterInterface.php deleted file mode 100644 index 53c65c1c592..00000000000 --- a/src/Core/GraphQl/Type/TypeConverterInterface.php +++ /dev/null @@ -1,38 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -use GraphQL\Type\Definition\Type as GraphQLType; -use Symfony\Component\PropertyInfo\Type; - -/** - * Converts a type to its GraphQL equivalent. - * - * @author Alan Poulain - */ -interface TypeConverterInterface -{ - /** - * Converts a built-in type to its GraphQL equivalent. - * A string can be returned for a custom registered type. - * - * @return string|GraphQLType|null - */ - public function convertType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $resourceClass, string $rootResource, ?string $property, int $depth); - - /** - * Resolves a type written with the GraphQL type system to its object representation. - */ - public function resolveType(string $type): ?GraphQLType; -} diff --git a/src/Core/GraphQl/Type/TypeNotFoundException.php b/src/Core/GraphQl/Type/TypeNotFoundException.php deleted file mode 100644 index b09ea7634f1..00000000000 --- a/src/Core/GraphQl/Type/TypeNotFoundException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -class_exists(\ApiPlatform\GraphQl\Type\TypeNotFoundException::class); - -if (false) { - final class TypeNotFoundException extends \ApiPlatform\GraphQl\Type\TypeNotFoundException - { - } -} diff --git a/src/Core/GraphQl/Type/TypesContainer.php b/src/Core/GraphQl/Type/TypesContainer.php deleted file mode 100644 index ae852470804..00000000000 --- a/src/Core/GraphQl/Type/TypesContainer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -class_exists(\ApiPlatform\GraphQl\Type\TypesContainer::class); - -if (false) { - final class TypesContainer extends \ApiPlatform\GraphQl\Type\TypesContainer - { - } -} diff --git a/src/Core/GraphQl/Type/TypesFactory.php b/src/Core/GraphQl/Type/TypesFactory.php deleted file mode 100644 index b359c63adda..00000000000 --- a/src/Core/GraphQl/Type/TypesFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\GraphQl\Type; - -class_exists(\ApiPlatform\GraphQl\Type\TypesFactory::class); - -if (false) { - final class TypesFactory extends \ApiPlatform\GraphQl\Type\TypesFactory - { - } -} diff --git a/src/Core/Hal/JsonSchema/SchemaFactory.php b/src/Core/Hal/JsonSchema/SchemaFactory.php deleted file mode 100644 index 4cba3d38752..00000000000 --- a/src/Core/Hal/JsonSchema/SchemaFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hal\JsonSchema; - -class_exists(\ApiPlatform\Hal\JsonSchema\SchemaFactory::class); - -if (false) { - final class SchemaFactory extends \ApiPlatform\Hal\JsonSchema\SchemaFactory - { - } -} diff --git a/src/Core/Hal/Serializer/CollectionNormalizer.php b/src/Core/Hal/Serializer/CollectionNormalizer.php deleted file mode 100644 index f3eb171ef3b..00000000000 --- a/src/Core/Hal/Serializer/CollectionNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hal\Serializer; - -class_exists(\ApiPlatform\Hal\Serializer\CollectionNormalizer::class); - -if (false) { - final class CollectionNormalizer extends \ApiPlatform\Hal\Serializer\CollectionNormalizer - { - } -} diff --git a/src/Core/Hal/Serializer/EntrypointNormalizer.php b/src/Core/Hal/Serializer/EntrypointNormalizer.php deleted file mode 100644 index 1ab80f92df8..00000000000 --- a/src/Core/Hal/Serializer/EntrypointNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hal\Serializer; - -class_exists(\ApiPlatform\Hal\Serializer\EntrypointNormalizer::class); - -if (false) { - final class EntrypointNormalizer extends \ApiPlatform\Hal\Serializer\EntrypointNormalizer - { - } -} diff --git a/src/Core/Hal/Serializer/ItemNormalizer.php b/src/Core/Hal/Serializer/ItemNormalizer.php deleted file mode 100644 index 33a67f551b2..00000000000 --- a/src/Core/Hal/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hal\Serializer; - -class_exists(\ApiPlatform\Hal\Serializer\ItemNormalizer::class); - -if (false) { - final class ItemNormalizer extends \ApiPlatform\Hal\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/Hal/Serializer/ObjectNormalizer.php b/src/Core/Hal/Serializer/ObjectNormalizer.php deleted file mode 100644 index b418b891813..00000000000 --- a/src/Core/Hal/Serializer/ObjectNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hal\Serializer; - -class_exists(\ApiPlatform\Hal\Serializer\ObjectNormalizer::class); - -if (false) { - final class ObjectNormalizer extends \ApiPlatform\Hal\Serializer\ObjectNormalizer - { - } -} diff --git a/src/Core/HttpCache/EventListener/AddHeadersListener.php b/src/Core/HttpCache/EventListener/AddHeadersListener.php deleted file mode 100644 index 7dd640e01bf..00000000000 --- a/src/Core/HttpCache/EventListener/AddHeadersListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\HttpCache\EventListener; - -class_exists(\ApiPlatform\HttpCache\EventListener\AddHeadersListener::class); - -if (false) { - final class AddHeadersListener extends \ApiPlatform\HttpCache\EventListener\AddHeadersListener - { - } -} diff --git a/src/Core/HttpCache/EventListener/AddTagsListener.php b/src/Core/HttpCache/EventListener/AddTagsListener.php deleted file mode 100644 index 27d74e1f9ca..00000000000 --- a/src/Core/HttpCache/EventListener/AddTagsListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\HttpCache\EventListener; - -class_exists(\ApiPlatform\HttpCache\EventListener\AddTagsListener::class); - -if (false) { - final class AddTagsListener extends \ApiPlatform\HttpCache\EventListener\AddTagsListener - { - } -} diff --git a/src/Core/HttpCache/PurgerInterface.php b/src/Core/HttpCache/PurgerInterface.php deleted file mode 100644 index b1c14ccd911..00000000000 --- a/src/Core/HttpCache/PurgerInterface.php +++ /dev/null @@ -1,31 +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); - -namespace ApiPlatform\Core\HttpCache; - -/** - * Purges resources from the cache. - * - * @author Kévin Dunglas - * - * @experimental - */ -interface PurgerInterface -{ - /** - * Purges all responses containing the given resources from the cache. - * - * @param string[] $iris - */ - public function purge(array $iris): void; -} diff --git a/src/Core/HttpCache/VarnishPurger.php b/src/Core/HttpCache/VarnishPurger.php deleted file mode 100644 index 944b66b965d..00000000000 --- a/src/Core/HttpCache/VarnishPurger.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\HttpCache; - -class_exists(\ApiPlatform\HttpCache\VarnishPurger::class); - -if (false) { - final class VarnishPurger extends \ApiPlatform\HttpCache\VarnishPurger - { - } -} diff --git a/src/Core/HttpCache/VarnishXKeyPurger.php b/src/Core/HttpCache/VarnishXKeyPurger.php deleted file mode 100644 index 06f19ee752e..00000000000 --- a/src/Core/HttpCache/VarnishXKeyPurger.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\HttpCache; - -class_exists(\ApiPlatform\HttpCache\VarnishXKeyPurger::class); - -if (false) { - final class VarnishXKeyPurger extends \ApiPlatform\HttpCache\VarnishXKeyPurger - { - } -} diff --git a/src/Core/Hydra/EventListener/AddLinkHeaderListener.php b/src/Core/Hydra/EventListener/AddLinkHeaderListener.php deleted file mode 100644 index 0a02983bd4a..00000000000 --- a/src/Core/Hydra/EventListener/AddLinkHeaderListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hydra\EventListener; - -class_exists(\ApiPlatform\Hydra\EventListener\AddLinkHeaderListener::class); - -if (false) { - final class AddLinkHeaderListener extends \ApiPlatform\Hydra\EventListener\AddLinkHeaderListener - { - } -} diff --git a/src/Core/Hydra/JsonSchema/SchemaFactory.php b/src/Core/Hydra/JsonSchema/SchemaFactory.php deleted file mode 100644 index 5af22519fb5..00000000000 --- a/src/Core/Hydra/JsonSchema/SchemaFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hydra\JsonSchema; - -class_exists(\ApiPlatform\Hydra\JsonSchema\SchemaFactory::class); - -if (false) { - final class SchemaFactory extends \ApiPlatform\Hydra\JsonSchema\SchemaFactory - { - } -} diff --git a/src/Core/Hydra/Serializer/CollectionFiltersNormalizer.php b/src/Core/Hydra/Serializer/CollectionFiltersNormalizer.php deleted file mode 100644 index b0e8deda7fd..00000000000 --- a/src/Core/Hydra/Serializer/CollectionFiltersNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer::class); - -if (false) { - final class CollectionFiltersNormalizer extends \ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/CollectionNormalizer.php b/src/Core/Hydra/Serializer/CollectionNormalizer.php deleted file mode 100644 index d3a43938f1d..00000000000 --- a/src/Core/Hydra/Serializer/CollectionNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\CollectionNormalizer::class); - -if (false) { - final class CollectionNormalizer extends \ApiPlatform\Hydra\Serializer\CollectionNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/ConstraintViolationListNormalizer.php b/src/Core/Hydra/Serializer/ConstraintViolationListNormalizer.php deleted file mode 100644 index 631ae16dc87..00000000000 --- a/src/Core/Hydra/Serializer/ConstraintViolationListNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\ConstraintViolationListNormalizer::class); - -if (false) { - final class ConstraintViolationListNormalizer extends \ApiPlatform\Hydra\Serializer\ConstraintViolationListNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/DocumentationNormalizer.php b/src/Core/Hydra/Serializer/DocumentationNormalizer.php deleted file mode 100644 index 26824ab3a40..00000000000 --- a/src/Core/Hydra/Serializer/DocumentationNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\DocumentationNormalizer::class); - -if (false) { - final class DocumentationNormalizer extends \ApiPlatform\Hydra\Serializer\DocumentationNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/EntrypointNormalizer.php b/src/Core/Hydra/Serializer/EntrypointNormalizer.php deleted file mode 100644 index a7682e82fae..00000000000 --- a/src/Core/Hydra/Serializer/EntrypointNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\EntrypointNormalizer::class); - -if (false) { - final class EntrypointNormalizer extends \ApiPlatform\Hydra\Serializer\EntrypointNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/ErrorNormalizer.php b/src/Core/Hydra/Serializer/ErrorNormalizer.php deleted file mode 100644 index 57de73d96c4..00000000000 --- a/src/Core/Hydra/Serializer/ErrorNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\ErrorNormalizer::class); - -if (false) { - final class ErrorNormalizer extends \ApiPlatform\Hydra\Serializer\ErrorNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/PartialCollectionViewNormalizer.php b/src/Core/Hydra/Serializer/PartialCollectionViewNormalizer.php deleted file mode 100644 index 6f8e6e1095c..00000000000 --- a/src/Core/Hydra/Serializer/PartialCollectionViewNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer::class); - -if (false) { - final class PartialCollectionViewNormalizer extends \ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer - { - } -} diff --git a/src/Core/Identifier/CompositeIdentifierParser.php b/src/Core/Identifier/CompositeIdentifierParser.php deleted file mode 100644 index f95c1191f07..00000000000 --- a/src/Core/Identifier/CompositeIdentifierParser.php +++ /dev/null @@ -1,63 +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); - -namespace ApiPlatform\Core\Identifier; - -/** - * Normalizes a composite identifier. - * - * @author Antoine Bluchet - */ -final class CompositeIdentifierParser -{ - public const COMPOSITE_IDENTIFIER_REGEXP = '/(\w+)=(?<=\w=)(.*?)(?=;\w+=)|(\w+)=([^;]*);?$/'; - - private function __construct() - { - } - - /* - * Normalize takes a string and gives back an array of identifiers. - * - * For example: foo=0;bar=2 returns ['foo' => 0, 'bar' => 2]. - */ - public static function parse(string $identifier): array - { - $matches = []; - $identifiers = []; - $num = preg_match_all(self::COMPOSITE_IDENTIFIER_REGEXP, $identifier, $matches, \PREG_SET_ORDER); - - foreach ($matches as $i => $match) { - if ($i === $num - 1) { - $identifiers[$match[3]] = $match[4]; - continue; - } - $identifiers[$match[1]] = $match[2]; - } - - return $identifiers; - } - - /** - * Renders composite identifiers to string using: key=value;key2=value2. - */ - public static function stringify(array $identifiers): string - { - $composite = []; - foreach ($identifiers as $name => $value) { - $composite[] = sprintf('%s=%s', $name, $value); - } - - return implode(';', $composite); - } -} diff --git a/src/Core/Identifier/ContextAwareIdentifierConverterInterface.php b/src/Core/Identifier/ContextAwareIdentifierConverterInterface.php deleted file mode 100644 index 76f33ad81f0..00000000000 --- a/src/Core/Identifier/ContextAwareIdentifierConverterInterface.php +++ /dev/null @@ -1,27 +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); - -namespace ApiPlatform\Core\Identifier; - -/** - * Gives access to the context in the IdentifierConverter. - * - * @author Antoine Bluchet - */ -interface ContextAwareIdentifierConverterInterface extends IdentifierConverterInterface -{ - /** - * {@inheritdoc} - */ - public function convert($data, string $class, array $context = []): array; -} diff --git a/src/Core/Identifier/IdentifierConverter.php b/src/Core/Identifier/IdentifierConverter.php deleted file mode 100644 index 9af469b4f96..00000000000 --- a/src/Core/Identifier/IdentifierConverter.php +++ /dev/null @@ -1,91 +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); - -namespace ApiPlatform\Core\Identifier; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidIdentifierException; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Identifier converter that chains identifier denormalizers. - * - * @author Antoine Bluchet - */ -final class IdentifierConverter implements ContextAwareIdentifierConverterInterface -{ - private $propertyMetadataFactory; - private $identifiersExtractor; - private $identifierDenormalizers; - private $resourceMetadataFactory; - - /** - * TODO: rename identifierDenormalizers to identifierTransformers in 3.0 and change their interfaces to a IdentifierTransformerInterface. - * - * @param iterable $identifierDenormalizers - */ - public function __construct(IdentifiersExtractorInterface $identifiersExtractor, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $identifierDenormalizers, ResourceMetadataFactoryInterface $resourceMetadataFactory = null) - { - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->identifiersExtractor = $identifiersExtractor; - $this->identifierDenormalizers = $identifierDenormalizers; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - /** - * {@inheritdoc} - */ - public function convert($data, string $class, array $context = []): array - { - if (!\is_array($data)) { - @trigger_error(sprintf('Not using an array as the first argument of "%s->convert" is deprecated since API Platform 2.6 and will not be possible anymore in API Platform 3', self::class), \E_USER_DEPRECATED); - $data = ['id' => $data]; - } - - $identifiers = $data; - - foreach ($data as $parameter => $value) { - if (null === $type = $this->getIdentifierType($context['identifiers'][$parameter][0] ?? $class, $context['identifiers'][$parameter][1] ?? $parameter)) { - continue; - } - - /* @var DenormalizerInterface[] */ - foreach ($this->identifierDenormalizers as $identifierTransformer) { - if (!$identifierTransformer->supportsDenormalization($value, $type)) { - continue; - } - - try { - $identifiers[$parameter] = $identifierTransformer->denormalize($value, $type); - break; - } catch (InvalidIdentifierException $e) { - throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $parameter), $e->getCode(), $e); - } - } - } - - return $identifiers; - } - - private function getIdentifierType(string $resourceClass, string $property): ?string - { - if (!$type = $this->propertyMetadataFactory->create($resourceClass, $property)->getType()) { - return null; - } - - return Type::BUILTIN_TYPE_OBJECT === ($builtinType = $type->getBuiltinType()) ? $type->getClassName() : $builtinType; - } -} diff --git a/src/Core/Identifier/IdentifierConverterInterface.php b/src/Core/Identifier/IdentifierConverterInterface.php deleted file mode 100644 index 983525fc132..00000000000 --- a/src/Core/Identifier/IdentifierConverterInterface.php +++ /dev/null @@ -1,41 +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); - -namespace ApiPlatform\Core\Identifier; - -use ApiPlatform\Exception\InvalidIdentifierException; - -/** - * Identifier converter. - * - * @author Antoine Bluchet - */ -interface IdentifierConverterInterface -{ - /** - * @internal - */ - public const HAS_IDENTIFIER_CONVERTER = 'has_identifier_converter'; - - /** - * Takes an array of strings representing identifiers and transform their values to the expected type. - * - * @param mixed $data Identifier to convert to php values - * @param string $class The class to which the identifiers belong - * - * @throws InvalidIdentifierException - * - * @return array Indexed by identifiers properties with their values denormalized - */ - public function convert($data, string $class): array; -} diff --git a/src/Core/Identifier/Normalizer/DateTimeIdentifierDenormalizer.php b/src/Core/Identifier/Normalizer/DateTimeIdentifierDenormalizer.php deleted file mode 100644 index 9b73c1eca2a..00000000000 --- a/src/Core/Identifier/Normalizer/DateTimeIdentifierDenormalizer.php +++ /dev/null @@ -1,43 +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); - -namespace ApiPlatform\Core\Identifier\Normalizer; - -use ApiPlatform\Exception\InvalidIdentifierException; -use Symfony\Component\Serializer\Exception\NotNormalizableValueException; -use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; - -final class DateTimeIdentifierDenormalizer extends DateTimeNormalizer -{ - /** - * @param mixed|null $format - * @param mixed $data - * @param mixed $class - */ - public function denormalize($data, $class, $format = null, array $context = []): \DateTimeInterface - { - try { - return parent::denormalize($data, $class, $format, $context); - } catch (NotNormalizableValueException $e) { - throw new InvalidIdentifierException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function hasCacheableSupportsMethod(): bool - { - return true; - } -} diff --git a/src/Core/Identifier/Normalizer/IntegerDenormalizer.php b/src/Core/Identifier/Normalizer/IntegerDenormalizer.php deleted file mode 100644 index d75e1e9cf00..00000000000 --- a/src/Core/Identifier/Normalizer/IntegerDenormalizer.php +++ /dev/null @@ -1,45 +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); - -namespace ApiPlatform\Core\Identifier\Normalizer; - -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -final class IntegerDenormalizer implements DenormalizerInterface, CacheableSupportsMethodInterface -{ - /** - * {@inheritdoc} - */ - public function denormalize($data, $class, $format = null, array $context = []): int - { - return (int) $data; - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return Type::BUILTIN_TYPE_INT === $type && \is_string($data); - } - - /** - * {@inheritdoc} - */ - public function hasCacheableSupportsMethod(): bool - { - return true; - } -} diff --git a/src/Core/JsonApi/EventListener/TransformFieldsetsParametersListener.php b/src/Core/JsonApi/EventListener/TransformFieldsetsParametersListener.php deleted file mode 100644 index f2b5cb4d7ce..00000000000 --- a/src/Core/JsonApi/EventListener/TransformFieldsetsParametersListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener::class); - -if (false) { - final class TransformFieldsetsParametersListener extends \ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener - { - } -} diff --git a/src/Core/JsonApi/EventListener/TransformFilteringParametersListener.php b/src/Core/JsonApi/EventListener/TransformFilteringParametersListener.php deleted file mode 100644 index efbc636de69..00000000000 --- a/src/Core/JsonApi/EventListener/TransformFilteringParametersListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\JsonApi\TransformFilteringParametersListener::class); - -if (false) { - final class TransformFilteringParametersListener extends \ApiPlatform\Symfony\EventListener\JsonApi\TransformFilteringParametersListener - { - } -} diff --git a/src/Core/JsonApi/EventListener/TransformPaginationParametersListener.php b/src/Core/JsonApi/EventListener/TransformPaginationParametersListener.php deleted file mode 100644 index c8757daf9b9..00000000000 --- a/src/Core/JsonApi/EventListener/TransformPaginationParametersListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\JsonApi\TransformPaginationParametersListener::class); - -if (false) { - final class TransformPaginationParametersListener extends \ApiPlatform\Symfony\EventListener\JsonApi\TransformPaginationParametersListener - { - } -} diff --git a/src/Core/JsonApi/EventListener/TransformSortingParametersListener.php b/src/Core/JsonApi/EventListener/TransformSortingParametersListener.php deleted file mode 100644 index ad743feb683..00000000000 --- a/src/Core/JsonApi/EventListener/TransformSortingParametersListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\JsonApi\TransformSortingParametersListener::class); - -if (false) { - final class TransformSortingParametersListener extends \ApiPlatform\Symfony\EventListener\JsonApi\TransformSortingParametersListener - { - } -} diff --git a/src/Core/JsonApi/Serializer/CollectionNormalizer.php b/src/Core/JsonApi/Serializer/CollectionNormalizer.php deleted file mode 100644 index c82d3bcf872..00000000000 --- a/src/Core/JsonApi/Serializer/CollectionNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\CollectionNormalizer::class); - -if (false) { - final class CollectionNormalizer extends \ApiPlatform\JsonApi\Serializer\CollectionNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ConstraintViolationListNormalizer.php b/src/Core/JsonApi/Serializer/ConstraintViolationListNormalizer.php deleted file mode 100644 index 1b8ad3247bc..00000000000 --- a/src/Core/JsonApi/Serializer/ConstraintViolationListNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ConstraintViolationListNormalizer::class); - -if (false) { - final class ConstraintViolationListNormalizer extends \ApiPlatform\JsonApi\Serializer\ConstraintViolationListNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/EntrypointNormalizer.php b/src/Core/JsonApi/Serializer/EntrypointNormalizer.php deleted file mode 100644 index 0edf014ac61..00000000000 --- a/src/Core/JsonApi/Serializer/EntrypointNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\EntrypointNormalizer::class); - -if (false) { - final class EntrypointNormalizer extends \ApiPlatform\JsonApi\Serializer\EntrypointNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ErrorNormalizer.php b/src/Core/JsonApi/Serializer/ErrorNormalizer.php deleted file mode 100644 index d30771f80a8..00000000000 --- a/src/Core/JsonApi/Serializer/ErrorNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ErrorNormalizer::class); - -if (false) { - final class ErrorNormalizer extends \ApiPlatform\JsonApi\Serializer\ErrorNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ItemNormalizer.php b/src/Core/JsonApi/Serializer/ItemNormalizer.php deleted file mode 100644 index 45df1a32192..00000000000 --- a/src/Core/JsonApi/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ItemNormalizer::class); - -if (false) { - final class ItemNormalizer extends \ApiPlatform\JsonApi\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ObjectNormalizer.php b/src/Core/JsonApi/Serializer/ObjectNormalizer.php deleted file mode 100644 index 5e838cfbe62..00000000000 --- a/src/Core/JsonApi/Serializer/ObjectNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ObjectNormalizer::class); - -if (false) { - final class ObjectNormalizer extends \ApiPlatform\JsonApi\Serializer\ObjectNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ReservedAttributeNameConverter.php b/src/Core/JsonApi/Serializer/ReservedAttributeNameConverter.php deleted file mode 100644 index ec61d3df8df..00000000000 --- a/src/Core/JsonApi/Serializer/ReservedAttributeNameConverter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ReservedAttributeNameConverter::class); - -if (false) { - final class ReservedAttributeNameConverter extends \ApiPlatform\JsonApi\Serializer\ReservedAttributeNameConverter - { - } -} diff --git a/src/Core/JsonLd/Action/ContextAction.php b/src/Core/JsonLd/Action/ContextAction.php deleted file mode 100644 index f2e668a3ab8..00000000000 --- a/src/Core/JsonLd/Action/ContextAction.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonLd\Action; - -class_exists(\ApiPlatform\JsonLd\Action\ContextAction::class); - -if (false) { - final class ContextAction extends \ApiPlatform\JsonLd\Action\ContextAction - { - } -} diff --git a/src/Core/JsonLd/ContextBuilder.php b/src/Core/JsonLd/ContextBuilder.php deleted file mode 100644 index a65df6d2e1e..00000000000 --- a/src/Core/JsonLd/ContextBuilder.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonLd; - -class_exists(\ApiPlatform\JsonLd\ContextBuilder::class); - -if (false) { - final class ContextBuilder extends \ApiPlatform\JsonLd\ContextBuilder - { - } -} diff --git a/src/Core/JsonLd/Serializer/ItemNormalizer.php b/src/Core/JsonLd/Serializer/ItemNormalizer.php deleted file mode 100644 index ceef30d9f9f..00000000000 --- a/src/Core/JsonLd/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonLd\Serializer; - -class_exists(\ApiPlatform\JsonLd\Serializer\ItemNormalizer::class); - -if (false) { - final class ItemNormalizer extends \ApiPlatform\JsonLd\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/JsonLd/Serializer/JsonLdContextTrait.php b/src/Core/JsonLd/Serializer/JsonLdContextTrait.php deleted file mode 100644 index 84a6f94c001..00000000000 --- a/src/Core/JsonLd/Serializer/JsonLdContextTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\JsonLd\Serializer; - -class_exists(\ApiPlatform\JsonLd\Serializer\JsonLdContextTrait::class); - -if (false) { - trait JsonLdContextTrait - { - use \ApiPlatform\JsonLd\Serializer\JsonLdContextTrait; - } -} diff --git a/src/Core/JsonLd/Serializer/ObjectNormalizer.php b/src/Core/JsonLd/Serializer/ObjectNormalizer.php deleted file mode 100644 index cca5348c115..00000000000 --- a/src/Core/JsonLd/Serializer/ObjectNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonLd\Serializer; - -class_exists(\ApiPlatform\JsonLd\Serializer\ObjectNormalizer::class); - -if (false) { - final class ObjectNormalizer extends \ApiPlatform\JsonLd\Serializer\ObjectNormalizer - { - } -} diff --git a/src/Core/JsonSchema/Command/JsonSchemaGenerateCommand.php b/src/Core/JsonSchema/Command/JsonSchemaGenerateCommand.php deleted file mode 100644 index 5427bd17c6a..00000000000 --- a/src/Core/JsonSchema/Command/JsonSchemaGenerateCommand.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonSchema\Command; - -class_exists(\ApiPlatform\JsonSchema\Command\JsonSchemaGenerateCommand::class); - -if (false) { - final class JsonSchemaGenerateCommand extends \ApiPlatform\JsonSchema\Command\JsonSchemaGenerateCommand - { - } -} diff --git a/src/Core/JsonSchema/Schema.php b/src/Core/JsonSchema/Schema.php deleted file mode 100644 index 759a42ee924..00000000000 --- a/src/Core/JsonSchema/Schema.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonSchema; - -class_exists(\ApiPlatform\JsonSchema\Schema::class); - -if (false) { - final class Schema extends \ApiPlatform\JsonSchema\Schema - { - } -} diff --git a/src/Core/JsonSchema/SchemaFactory.php b/src/Core/JsonSchema/SchemaFactory.php deleted file mode 100644 index 0e96b4e23fe..00000000000 --- a/src/Core/JsonSchema/SchemaFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonSchema; - -class_exists(\ApiPlatform\JsonSchema\SchemaFactory::class); - -if (false) { - final class SchemaFactory extends \ApiPlatform\JsonSchema\SchemaFactory - { - } -} diff --git a/src/Core/JsonSchema/TypeFactory.php b/src/Core/JsonSchema/TypeFactory.php deleted file mode 100644 index 11a4af3f803..00000000000 --- a/src/Core/JsonSchema/TypeFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\JsonSchema; - -class_exists(\ApiPlatform\JsonSchema\TypeFactory::class); - -if (false) { - final class TypeFactory extends \ApiPlatform\JsonSchema\TypeFactory - { - } -} diff --git a/src/Core/Mercure/EventListener/AddLinkHeaderListener.php b/src/Core/Mercure/EventListener/AddLinkHeaderListener.php deleted file mode 100644 index d629f8e9601..00000000000 --- a/src/Core/Mercure/EventListener/AddLinkHeaderListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Mercure\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\AddLinkHeaderListener::class); - -if (false) { - final class AddLinkHeaderListener extends \ApiPlatform\Symfony\EventListener\AddLinkHeaderListener - { - } -} diff --git a/src/Core/Metadata/Extractor/XmlExtractor.php b/src/Core/Metadata/Extractor/XmlExtractor.php deleted file mode 100644 index e852c9472d4..00000000000 --- a/src/Core/Metadata/Extractor/XmlExtractor.php +++ /dev/null @@ -1,212 +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); - -namespace ApiPlatform\Core\Metadata\Extractor; - -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Metadata\Extractor\AbstractResourceExtractor; -use ApiPlatform\Metadata\Extractor\PropertyExtractorInterface; -use ApiPlatform\Metadata\Extractor\XmlPropertyExtractor; -use ApiPlatform\Metadata\Extractor\XmlResourceExtractor; -use Symfony\Component\Config\Util\XmlUtils; - -/** - * Extracts an array of metadata from a list of XML files. - * - * @author Kévin Dunglas - * @author Antoine Bluchet - * @author Baptiste Meyer - * @author Vincent Chalamon - * - * @deprecated since 2.7, to remove in 3.0 (replaced by ApiPlatform\Metadata\Extractor\XmlExtractor) - */ -final class XmlExtractor extends AbstractResourceExtractor implements PropertyExtractorInterface -{ - public const RESOURCE_SCHEMA = __DIR__.'/../schema/metadata.xsd'; - - private $properties; - - /** - * {@inheritdoc} - */ - public function getProperties(): array - { - if (null !== $this->properties) { - return $this->properties; - } - - $this->properties = []; - foreach ($this->paths as $path) { - $this->extractPath($path); - } - - return $this->properties; - } - - /** - * {@inheritdoc} - */ - protected function extractPath(string $path) - { - try { - /** @var \SimpleXMLElement $xml */ - $xml = simplexml_import_dom(XmlUtils::loadFile($path, self::RESOURCE_SCHEMA)); - } catch (\InvalidArgumentException $e) { - // Test if this is a new resource - try { - $xml = XmlUtils::loadFile($path, XmlResourceExtractor::SCHEMA); - - return; - } catch (\InvalidArgumentException $newResourceException) { - try { - $xml = XmlUtils::loadFile($path, XmlPropertyExtractor::SCHEMA); - - return; - } catch (\InvalidArgumentException $newPropertyException) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } - } - - foreach ($xml->resource as $resource) { - $resourceClass = $this->resolve((string) $resource['class']); - - $this->resources[$resourceClass] = [ - 'shortName' => $this->phpizeAttribute($resource, 'shortName', 'string'), - 'description' => $this->phpizeAttribute($resource, 'description', 'string'), - 'iri' => $this->phpizeAttribute($resource, 'iri', 'string'), - 'itemOperations' => $this->extractOperations($resource, 'itemOperation'), - 'collectionOperations' => $this->extractOperations($resource, 'collectionOperation'), - 'subresourceOperations' => $this->extractOperations($resource, 'subresourceOperation'), - 'graphql' => $this->extractOperations($resource, 'operation'), - 'attributes' => $this->extractAttributes($resource, 'attribute') ?: null, - 'properties' => $this->extractProperties($resource) ?: null, - ]; - $this->properties[$resourceClass] = $this->resources[$resourceClass]['properties']; - } - } - - /** - * Returns the array containing configured operations. Returns NULL if there is no operation configuration. - */ - private function extractOperations(\SimpleXMLElement $resource, string $operationType): ?array - { - $graphql = 'operation' === $operationType; - if (!$graphql && $legacyOperations = $this->extractAttributes($resource, $operationType)) { - @trigger_error( - sprintf('Configuring "%1$s" tags without using a parent "%1$ss" tag is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3', $operationType), - \E_USER_DEPRECATED - ); - - return $legacyOperations; - } - - $operationsParent = $graphql ? 'graphql' : "{$operationType}s"; - if (!isset($resource->{$operationsParent})) { - return null; - } - - return $this->extractAttributes($resource->{$operationsParent}, $operationType, true); - } - - /** - * Recursively transforms an attribute structure into an associative array. - */ - private function extractAttributes(\SimpleXMLElement $resource, string $elementName, bool $topLevel = false): array - { - $attributes = []; - foreach ($resource->{$elementName} as $attribute) { - $value = isset($attribute->attribute[0]) ? $this->extractAttributes($attribute, 'attribute') : $this->phpizeContent($attribute); - // allow empty operations definition, like - if ($topLevel && '' === $value) { - $value = []; - } - if (isset($attribute['name'])) { - $attributes[(string) $attribute['name']] = $value; - } else { - $attributes[] = $value; - } - } - - return $attributes; - } - - /** - * Gets metadata of a property. - */ - private function extractProperties(\SimpleXMLElement $resource): array - { - $properties = []; - foreach ($resource->property as $property) { - $properties[(string) $property['name']] = [ - 'description' => $this->phpizeAttribute($property, 'description', 'string'), - 'readable' => $this->phpizeAttribute($property, 'readable', 'bool'), - 'writable' => $this->phpizeAttribute($property, 'writable', 'bool'), - 'readableLink' => $this->phpizeAttribute($property, 'readableLink', 'bool'), - 'writableLink' => $this->phpizeAttribute($property, 'writableLink', 'bool'), - 'required' => $this->phpizeAttribute($property, 'required', 'bool'), - 'identifier' => $this->phpizeAttribute($property, 'identifier', 'bool'), - 'iri' => $this->phpizeAttribute($property, 'iri', 'string'), - 'attributes' => $this->extractAttributes($property, 'attribute'), - 'subresource' => $property->subresource ? [ - 'collection' => $this->phpizeAttribute($property->subresource, 'collection', 'bool'), - 'resourceClass' => $this->resolve($this->phpizeAttribute($property->subresource, 'resourceClass', 'string')), - 'maxDepth' => $this->phpizeAttribute($property->subresource, 'maxDepth', 'integer'), - ] : null, - ]; - } - - return $properties; - } - - /** - * Transforms an XML attribute's value in a PHP value. - * - * @return string|int|bool|null - */ - private function phpizeAttribute(\SimpleXMLElement $array, string $key, string $type) - { - if (!isset($array[$key])) { - return null; - } - - switch ($type) { - case 'string': - return (string) $array[$key]; - case 'integer': - return (int) $array[$key]; - case 'bool': - return (bool) XmlUtils::phpize($array[$key]); - } - - return null; - } - - /** - * Transforms an XML element's content in a PHP value. - */ - private function phpizeContent(\SimpleXMLElement $array) - { - $type = $array['type'] ?? null; - $value = (string) $array; - - switch ($type) { - case 'string': - return $value; - case 'constant': - return \constant($value); - default: - return XmlUtils::phpize($value); - } - } -} diff --git a/src/Core/Metadata/Extractor/YamlExtractor.php b/src/Core/Metadata/Extractor/YamlExtractor.php deleted file mode 100644 index cdd77476094..00000000000 --- a/src/Core/Metadata/Extractor/YamlExtractor.php +++ /dev/null @@ -1,183 +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); - -namespace ApiPlatform\Core\Metadata\Extractor; - -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Metadata\Extractor\AbstractResourceExtractor; -use ApiPlatform\Metadata\Extractor\PropertyExtractorInterface; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Yaml; - -/** - * Extracts an array of metadata from a list of YAML files. - * - * @author Antoine Bluchet - * @author Baptiste Meyer - * @author Kévin Dunglas - * @author Vincent Chalamon - * - * @deprecated since 2.7, to remove in 3.0 (replaced by ApiPlatform\Metadata\Extractor\YamlExtractor) - */ -final class YamlExtractor extends AbstractResourceExtractor implements PropertyExtractorInterface -{ - private $properties; - - /** - * {@inheritdoc} - */ - public function getProperties(): array - { - if (null !== $this->properties) { - return $this->properties; - } - - $this->properties = []; - foreach ($this->paths as $path) { - $this->extractPath($path); - } - - return $this->properties; - } - - /** - * {@inheritdoc} - */ - protected function extractPath(string $path) - { - try { - $resourcesYaml = Yaml::parse((string) file_get_contents($path), Yaml::PARSE_CONSTANT); - } catch (ParseException $e) { - $e->setParsedFile($path); - - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - - if (null === $resourcesYaml = $resourcesYaml['resources'] ?? $resourcesYaml) { - return; - } - - if (!\is_array($resourcesYaml)) { - throw new InvalidArgumentException(sprintf('"resources" setting is expected to be null or an array, %s given in "%s".', \gettype($resourcesYaml), $path)); - } - - $this->extractResources($resourcesYaml, $path); - } - - private function extractResources(array $resourcesYaml, string $path): void - { - foreach ($resourcesYaml as $resourceName => $resourceYaml) { - $resourceName = $this->resolve($resourceName); - - if (null === $resourceYaml) { - $resourceYaml = []; - } - - if (!\is_array($resourceYaml)) { - throw new InvalidArgumentException(sprintf('"%s" setting is expected to be null or an array, %s given in "%s".', $resourceName, \gettype($resourceYaml), $path)); - } - - $this->resources[$resourceName] = [ - 'shortName' => $this->phpize($resourceYaml, 'shortName', 'string'), - 'description' => $this->phpize($resourceYaml, 'description', 'string'), - 'iri' => $this->phpize($resourceYaml, 'iri', 'string'), - 'itemOperations' => $resourceYaml['itemOperations'] ?? null, - 'collectionOperations' => $resourceYaml['collectionOperations'] ?? null, - 'subresourceOperations' => $resourceYaml['subresourceOperations'] ?? null, - 'graphql' => $resourceYaml['graphql'] ?? null, - 'attributes' => $resourceYaml['attributes'] ?? null, - ]; - - if (!isset($resourceYaml['properties'])) { - $this->properties[$resourceName] = $this->resources[$resourceName]['properties'] = null; - - continue; - } - - if (!\is_array($resourceYaml['properties'])) { - throw new InvalidArgumentException(sprintf('"properties" setting is expected to be null or an array, %s given in "%s".', \gettype($resourceYaml['properties']), $path)); - } - - $this->extractProperties($resourceYaml, $resourceName, $path); - } - } - - private function extractProperties(array $resourceYaml, string $resourceName, string $path): void - { - foreach ($resourceYaml['properties'] as $propertyName => $propertyValues) { - if (null === $propertyValues) { - $this->properties[$resourceName][$propertyName] = $this->resources[$resourceName]['properties'][$propertyName] = null; - - continue; - } - - if (!\is_array($propertyValues)) { - throw new InvalidArgumentException(sprintf('"%s" setting is expected to be null or an array, %s given in "%s".', $propertyName, \gettype($propertyValues), $path)); - } - if (isset($propertyValues['subresource']['resourceClass'])) { - $propertyValues['subresource']['resourceClass'] = $this->resolve($propertyValues['subresource']['resourceClass']); - } - - $this->properties[$resourceName][$propertyName] = $this->resources[$resourceName]['properties'][$propertyName] = [ - 'description' => $this->phpize($propertyValues, 'description', 'string'), - 'readable' => $this->phpize($propertyValues, 'readable', 'bool'), - 'writable' => $this->phpize($propertyValues, 'writable', 'bool'), - 'readableLink' => $this->phpize($propertyValues, 'readableLink', 'bool'), - 'writableLink' => $this->phpize($propertyValues, 'writableLink', 'bool'), - 'required' => $this->phpize($propertyValues, 'required', 'bool'), - 'identifier' => $this->phpize($propertyValues, 'identifier', 'bool'), - 'iri' => $this->phpize($propertyValues, 'iri', 'string'), - 'attributes' => $propertyValues['attributes'] ?? [], - 'subresource' => isset($propertyValues['subresource']) ? [ - 'collection' => $this->phpize($propertyValues['subresource'], 'collection', 'bool'), - 'resourceClass' => $this->phpize($propertyValues['subresource'], 'resourceClass', 'string'), - 'maxDepth' => $this->phpize($propertyValues['subresource'], 'maxDepth', 'integer'), - ] : null, - ]; - } - } - - /** - * Transforms a YAML attribute's value in PHP value. - * - * @throws InvalidArgumentException - * - * @return bool|int|string|null - */ - private function phpize(array $array, string $key, string $type) - { - if (!isset($array[$key])) { - return null; - } - - switch ($type) { - case 'bool': - if (\is_bool($array[$key])) { - return $array[$key]; - } - break; - case 'integer': - if (\is_int($array[$key])) { - return $array[$key]; - } - break; - case 'string': - if (\is_string($array[$key])) { - return $array[$key]; - } - break; - } - - throw new InvalidArgumentException(sprintf('The property "%s" must be a "%s", "%s" given.', $key, $type, \gettype($array[$key]))); - } -} diff --git a/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php deleted file mode 100644 index 255b24fb7c2..00000000000 --- a/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php +++ /dev/null @@ -1,154 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Util\Reflection; -use Doctrine\Common\Annotations\Reader; - -/** - * Creates a property metadata from {@see ApiProperty} annotations. - * - * @author Kévin Dunglas - */ -final class AnnotationPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $reader; - private $decorated; - - public function __construct(Reader $reader = null, PropertyMetadataFactoryInterface $decorated = null) - { - $this->reader = $reader; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - if (null === ($options['deprecate'] ?? null)) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Decorating the legacy %s is deprecated, use %s instead.', PropertyMetadataFactoryInterface::class, \ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface::class)); - } - - $parentPropertyMetadata = null; - if ($this->decorated) { - try { - $parentPropertyMetadata = $this->decorated->create($resourceClass, $property, $options); - } catch (PropertyNotFoundException $propertyNotFoundException) { - // Ignore not found exception from decorated factories - } - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property); - } - - if ($reflectionClass->hasProperty($property)) { - $annotation = null; - $reflectionProperty = $reflectionClass->getProperty($property); - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionProperty->getAttributes(ApiProperty::class)) { - $annotation = $attributes[0]->newInstance(); - } elseif (null !== $this->reader) { - $annotation = $this->reader->getPropertyAnnotation($reflectionProperty, ApiProperty::class); - } - - if ($annotation instanceof ApiProperty) { - return $this->createMetadata($annotation, $parentPropertyMetadata); - } - } - - foreach (array_merge(Reflection::ACCESSOR_PREFIXES, Reflection::MUTATOR_PREFIXES) as $prefix) { - $methodName = $prefix.ucfirst($property); - if (!$reflectionClass->hasMethod($methodName)) { - continue; - } - - $reflectionMethod = $reflectionClass->getMethod($methodName); - if (!$reflectionMethod->isPublic()) { - continue; - } - - $annotation = null; - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionMethod->getAttributes(ApiProperty::class)) { - $annotation = $attributes[0]->newInstance(); - } elseif (null !== $this->reader) { - $annotation = $this->reader->getMethodAnnotation($reflectionMethod, ApiProperty::class); - } - - if ($annotation instanceof ApiProperty) { - return $this->createMetadata($annotation, $parentPropertyMetadata); - } - } - - return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws PropertyNotFoundException - */ - private function handleNotFound(?PropertyMetadata $parentPropertyMetadata, string $resourceClass, string $property): PropertyMetadata - { - if (null !== $parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new PropertyNotFoundException(sprintf('Property "%s" of class "%s" not found.', $property, $resourceClass)); - } - - private function createMetadata(ApiProperty $annotation, PropertyMetadata $parentPropertyMetadata = null): PropertyMetadata - { - if (null === $parentPropertyMetadata) { - return new PropertyMetadata( - null, - $annotation->description, - $annotation->readable, - $annotation->writable, - $annotation->readableLink, - $annotation->writableLink, - $annotation->required, - $annotation->identifier, - $annotation->iri, - null, - $annotation->attributes, - null, - null, - $annotation->default, - $annotation->example - ); - } - - $propertyMetadata = $parentPropertyMetadata; - foreach ([['get', 'description'], ['is', 'readable'], ['is', 'writable'], ['is', 'readableLink'], ['is', 'writableLink'], ['is', 'required'], ['get', 'iri'], ['is', 'identifier'], ['get', 'attributes'], ['get', 'default'], ['get', 'example']] as $property) { - if (null !== $value = $annotation->{$property[1]}) { - $propertyMetadata = $this->createWith($propertyMetadata, $property, $value); - } - } - - return $propertyMetadata; - } - - private function createWith(PropertyMetadata $propertyMetadata, array $property, $value): PropertyMetadata - { - $wither = 'with'.ucfirst($property[1]); - - return $propertyMetadata->{$wither}($value); - } -} diff --git a/src/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactory.php b/src/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactory.php deleted file mode 100644 index dfd7b2c8ddd..00000000000 --- a/src/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactory.php +++ /dev/null @@ -1,108 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Util\Reflection; -use Doctrine\Common\Annotations\Reader; - -/** - * Creates a property name collection from {@see ApiProperty} annotations. - * - * @author Kévin Dunglas - */ -final class AnnotationPropertyNameCollectionFactory implements PropertyNameCollectionFactoryInterface -{ - private $reader; - private $decorated; - private $reflection; - - public function __construct(Reader $reader = null, PropertyNameCollectionFactoryInterface $decorated = null) - { - $this->reader = $reader; - $this->decorated = $decorated; - $this->reflection = new Reflection(); - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, array $options = []): PropertyNameCollection - { - $propertyNameCollection = null; - - if ($this->decorated) { - try { - $propertyNameCollection = $this->decorated->create($resourceClass, $options); - } catch (ResourceClassNotFoundException $resourceClassNotFoundException) { - // Ignore not found exceptions from decorated factory - } - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - if (null !== $propertyNameCollection) { - return $propertyNameCollection; - } - - throw new ResourceClassNotFoundException(sprintf('The resource class "%s" does not exist.', $resourceClass)); - } - - $propertyNames = []; - - // Properties - foreach ($reflectionClass->getProperties() as $reflectionProperty) { - if ( - (\PHP_VERSION_ID >= 80000 && $reflectionProperty->getAttributes(ApiProperty::class)) || - (null !== $this->reader && null !== $this->reader->getPropertyAnnotation($reflectionProperty, ApiProperty::class)) - ) { - $propertyNames[$reflectionProperty->name] = $reflectionProperty->name; - } - } - - // Methods - foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) { - if ($reflectionMethod->isStatic()) { - continue; - } - - $propertyName = $this->reflection->getProperty($reflectionMethod->name); - if (null !== $propertyName && !$reflectionClass->hasProperty($propertyName) && !preg_match('/^[A-Z]{2,}/', $propertyName)) { - $propertyName = lcfirst($propertyName); - } - - if ( - null !== $propertyName && - ( - (\PHP_VERSION_ID >= 80000 && $reflectionMethod->getAttributes(ApiProperty::class)) || - (null !== $this->reader && null !== $this->reader->getMethodAnnotation($reflectionMethod, ApiProperty::class)) - ) - ) { - $propertyNames[$propertyName] = $propertyName; - } - } - - // add property names from decorated factory - if (null !== $propertyNameCollection) { - foreach ($propertyNameCollection as $propertyName) { - $propertyNames[$propertyName] = $propertyName; - } - } - - return new PropertyNameCollection(array_values($propertyNames)); - } -} diff --git a/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php b/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php deleted file mode 100644 index a5a0bad390e..00000000000 --- a/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php +++ /dev/null @@ -1,118 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiSubresource; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Exception\InvalidResourceException; -use ApiPlatform\Util\Reflection; -use Doctrine\Common\Annotations\Reader; -use Symfony\Component\PropertyInfo\Type; - -/** - * Adds subresources to the properties metadata from {@see ApiResource} annotations. - * - * @author Antoine Bluchet - */ -final class AnnotationSubresourceMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $reader; - private $decorated; - - public function __construct(Reader $reader, PropertyMetadataFactoryInterface $decorated) - { - $this->reader = $reader; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $propertyMetadata; - } - - if ($reflectionClass->hasProperty($property)) { - $reflectionProperty = $reflectionClass->getProperty($property); - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionProperty->getAttributes(ApiSubresource::class)) { - return $this->updateMetadata($attributes[0]->newInstance(), $propertyMetadata, $resourceClass, $property); - } - - $annotation = $this->reader->getPropertyAnnotation($reflectionProperty, ApiSubresource::class); - if ($annotation instanceof ApiSubresource) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Declare a new resource instead of using ApiSubresource on the property "%s".', $property)); - - return $this->updateMetadata($annotation, $propertyMetadata, $resourceClass, $property); - } - } - - foreach (array_merge(Reflection::ACCESSOR_PREFIXES, Reflection::MUTATOR_PREFIXES) as $prefix) { - $methodName = $prefix.ucfirst($property); - if (!$reflectionClass->hasMethod($methodName)) { - continue; - } - - $reflectionMethod = $reflectionClass->getMethod($methodName); - if (!$reflectionMethod->isPublic()) { - continue; - } - - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionMethod->getAttributes(ApiSubresource::class)) { - return $this->updateMetadata($attributes[0]->newInstance(), $propertyMetadata, $resourceClass, $property); - } - - $annotation = $this->reader->getMethodAnnotation($reflectionMethod, ApiSubresource::class); - if ($annotation instanceof ApiSubresource) { - return $this->updateMetadata($annotation, $propertyMetadata, $resourceClass, $property); - } - } - - return $propertyMetadata; - } - - private function updateMetadata(ApiSubresource $annotation, PropertyMetadata $propertyMetadata, string $originResourceClass, string $propertyName): PropertyMetadata - { - // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata->getType(); - if (null === $type) { - throw new InvalidResourceException(sprintf('Property "%s" on resource "%s" is declared as a subresource, but its type could not be determined.', $propertyName, $originResourceClass)); - } - $isCollection = $type->isCollection(); - - if ( - $isCollection && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $resourceClass = $collectionValueType->getClassName(); - } else { - $resourceClass = $type->getClassName(); - } - - $maxDepth = $annotation->maxDepth; - // @ApiSubresource is on the class identifier (/collection/{id}/subcollection/{subcollectionId}) - if (null === $resourceClass) { - $resourceClass = $originResourceClass; - $isCollection = false; - } - - return $propertyMetadata->withSubresource(new SubresourceMetadata($resourceClass, $isCollection, $maxDepth)); - } -} diff --git a/src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php deleted file mode 100644 index ae3ff9c4f77..00000000000 --- a/src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php +++ /dev/null @@ -1,50 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Util\CachedTrait; -use Psr\Cache\CacheItemPoolInterface; - -/** - * Caches property metadata. - * - * @author Teoh Han Hui - */ -final class CachedPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - use CachedTrait; - - public const CACHE_KEY_PREFIX = 'property_metadata_'; - - private $decorated; - - public function __construct(CacheItemPoolInterface $cacheItemPool, PropertyMetadataFactoryInterface $decorated) - { - $this->cacheItemPool = $cacheItemPool; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $cacheKey = self::CACHE_KEY_PREFIX.md5(serialize([$resourceClass, $property, $options])); - - return $this->getCached($cacheKey, function () use ($resourceClass, $property, $options) { - return $this->decorated->create($resourceClass, $property, $options); - }); - } -} diff --git a/src/Core/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php b/src/Core/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php deleted file mode 100644 index 89b20801939..00000000000 --- a/src/Core/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -class_exists(\ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class); - -if (false) { - final class CachedPropertyNameCollectionFactory extends \ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory - { - } -} diff --git a/src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php deleted file mode 100644 index 9c951077753..00000000000 --- a/src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php +++ /dev/null @@ -1,57 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; - -/** - * Populates defaults values of the ressource properties using the default PHP values of properties. - */ -final class DefaultPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $decorated; - - public function __construct(PropertyMetadataFactoryInterface $decorated = null) - { - $this->decorated = $decorated; - } - - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - if (null === $this->decorated) { - $propertyMetadata = new PropertyMetadata(); - } else { - try { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - } catch (PropertyNotFoundException $propertyNotFoundException) { - $propertyMetadata = new PropertyMetadata(); - } - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $propertyMetadata; - } - - $defaultProperties = $reflectionClass->getDefaultProperties(); - - if (!\array_key_exists($property, $defaultProperties) || null === ($defaultProperty = $defaultProperties[$property])) { - return $propertyMetadata; - } - - return $propertyMetadata->withDefault($defaultProperty); - } -} diff --git a/src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php deleted file mode 100644 index 89f86c69cb6..00000000000 --- a/src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php +++ /dev/null @@ -1,160 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Extractor\ExtractorInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use Symfony\Component\PropertyInfo\Type; - -/** - * Creates properties's metadata using an extractor. - * - * @author Kévin Dunglas - */ -final class ExtractorPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $extractor; - private $decorated; - - public function __construct(ExtractorInterface $extractor, PropertyMetadataFactoryInterface $decorated = null) - { - $this->extractor = $extractor; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $parentPropertyMetadata = null; - if ($this->decorated) { - try { - $parentPropertyMetadata = $this->decorated->create($resourceClass, $property, $options); - } catch (PropertyNotFoundException $propertyNotFoundException) { - // Ignore not found exception from decorated factories - } - } - - $isInterface = interface_exists($resourceClass); - - if ( - !property_exists($resourceClass, $property) && !$isInterface || - null === ($propertyMetadata = $this->extractor->getResources()[$resourceClass]['properties'][$property] ?? null) - ) { - return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property); - } - - if ($parentPropertyMetadata) { - return $this->update($parentPropertyMetadata, $propertyMetadata); - } - - return ($metadata = new PropertyMetadata( - null, - $propertyMetadata['description'], - $propertyMetadata['readable'], - $propertyMetadata['writable'], - $propertyMetadata['readableLink'], - $propertyMetadata['writableLink'], - $propertyMetadata['required'], - $propertyMetadata['identifier'], - $propertyMetadata['iri'], - null, - $propertyMetadata['attributes'] - ))->withSubresource($this->createSubresourceMetadata($propertyMetadata['subresource'], $metadata)); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws PropertyNotFoundException - */ - private function handleNotFound(?PropertyMetadata $parentPropertyMetadata, string $resourceClass, string $property): PropertyMetadata - { - if ($parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new PropertyNotFoundException(sprintf('Property "%s" of the resource class "%s" not found.', $property, $resourceClass)); - } - - /** - * Creates a new instance of metadata if the property is not already set. - */ - private function update(PropertyMetadata $propertyMetadata, array $metadata): PropertyMetadata - { - $metadataAccessors = [ - 'description' => 'get', - 'readable' => 'is', - 'writable' => 'is', - 'writableLink' => 'is', - 'readableLink' => 'is', - 'required' => 'is', - 'identifier' => 'is', - 'iri' => 'get', - 'attributes' => 'get', - ]; - - foreach ($metadataAccessors as $metadataKey => $accessorPrefix) { - if (null === $metadata[$metadataKey]) { - continue; - } - - $propertyMetadata = $propertyMetadata->{'with'.ucfirst($metadataKey)}($metadata[$metadataKey]); - } - - if ($propertyMetadata->hasSubresource()) { - return $propertyMetadata; - } - - return $propertyMetadata->withSubresource($this->createSubresourceMetadata($metadata['subresource'], $propertyMetadata)); - } - - /** - * Creates a SubresourceMetadata. - * - * @param bool|array|null $subresource the subresource metadata coming from XML or YAML - * @param PropertyMetadata $propertyMetadata the current property metadata - */ - private function createSubresourceMetadata($subresource, PropertyMetadata $propertyMetadata): ?SubresourceMetadata - { - if (!$subresource) { - return null; - } - - $type = $propertyMetadata->getType(); - $maxDepth = \is_array($subresource) ? $subresource['maxDepth'] ?? null : null; - - if (null !== $type) { - $isCollection = $type->isCollection(); - if ( - $isCollection && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $resourceClass = $collectionValueType->getClassName(); - } else { - $resourceClass = $type->getClassName(); - } - } elseif (\is_array($subresource) && isset($subresource['resourceClass'])) { - $resourceClass = $subresource['resourceClass']; - $isCollection = $subresource['collection'] ?? true; - } else { - return null; - } - - return new SubresourceMetadata($resourceClass, $isCollection, $maxDepth); - } -} diff --git a/src/Core/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php b/src/Core/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php deleted file mode 100644 index 000f49f61f7..00000000000 --- a/src/Core/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -class_exists(\ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class); - -if (false) { - final class ExtractorPropertyNameCollectionFactory extends \ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory - { - } -} diff --git a/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php deleted file mode 100644 index 577abbc45d6..00000000000 --- a/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php +++ /dev/null @@ -1,58 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; - -/** - * @deprecated since 2.6, to be removed in 3.0 - */ -final class InheritedPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $resourceNameCollectionFactory; - private $decorated; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, PropertyMetadataFactoryInterface $decorated = null) - { - @trigger_error(sprintf('"%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__), \E_USER_DEPRECATED); - - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - @trigger_error(sprintf('"%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__), \E_USER_DEPRECATED); - - $propertyMetadata = $this->decorated ? $this->decorated->create($resourceClass, $property, $options) : new PropertyMetadata(); - - foreach ($this->resourceNameCollectionFactory->create() as $knownResourceClass) { - if ($resourceClass === $knownResourceClass) { - continue; - } - - if (is_subclass_of($knownResourceClass, $resourceClass)) { - $propertyMetadata = $this->create($knownResourceClass, $property, $options); - - return $propertyMetadata->withChildInherited($knownResourceClass); - } - } - - return $propertyMetadata; - } -} diff --git a/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php b/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php deleted file mode 100644 index 6c38c542420..00000000000 --- a/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php +++ /dev/null @@ -1,65 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; - -/** - * @deprecated since 2.6, to be removed in 3.0 - */ -final class InheritedPropertyNameCollectionFactory implements PropertyNameCollectionFactoryInterface -{ - private $resourceNameCollectionFactory; - private $decorated; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, PropertyNameCollectionFactoryInterface $decorated = null) - { - @trigger_error(sprintf('"%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__), \E_USER_DEPRECATED); - - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, array $options = []): PropertyNameCollection - { - @trigger_error(sprintf('"%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__), \E_USER_DEPRECATED); - - $propertyNames = []; - - // Inherited from parent - if ($this->decorated) { - foreach ($this->decorated->create($resourceClass, $options) as $propertyName) { - $propertyNames[$propertyName] = (string) $propertyName; - } - } - - foreach ($this->resourceNameCollectionFactory->create() as $knownResourceClass) { - if ($resourceClass === $knownResourceClass) { - continue; - } - - if (is_subclass_of($resourceClass, $knownResourceClass)) { - foreach ($this->create($knownResourceClass) as $propertyName) { - $propertyNames[$propertyName] = $propertyName; - } - } - } - - return new PropertyNameCollection(array_values($propertyNames)); - } -} diff --git a/src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php b/src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php deleted file mode 100644 index 5cb5cc1f76f..00000000000 --- a/src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php +++ /dev/null @@ -1,32 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; - -/** - * Creates a property metadata value object. - * - * @author Kévin Dunglas - */ -interface PropertyMetadataFactoryInterface -{ - /** - * Creates a property metadata. - * - * @throws PropertyNotFoundException - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata; -} diff --git a/src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php deleted file mode 100644 index 9c93b2051a8..00000000000 --- a/src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php +++ /dev/null @@ -1,233 +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); - -namespace ApiPlatform\Core\Metadata\Property\Factory; - -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Util\ResourceClassInfoTrait; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface as SerializerClassMetadataFactoryInterface; - -/** - * Populates read/write and link status using serialization groups. - * - * @author Kévin Dunglas - * @author Teoh Han Hui - */ -final class SerializerPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - use ResourceClassInfoTrait; - - private $serializerClassMetadataFactory; - private $decorated; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, SerializerClassMetadataFactoryInterface $serializerClassMetadataFactory, PropertyMetadataFactoryInterface $decorated, ResourceClassResolverInterface $resourceClassResolver = null) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->serializerClassMetadataFactory = $serializerClassMetadataFactory; - $this->decorated = $decorated; - $this->resourceClassResolver = $resourceClassResolver; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - // BC to be removed in 3.0 - if (null !== ($childResourceClass = $propertyMetadata->getChildInherited())) { - $resourceClass = $childResourceClass; - } - - try { - [$normalizationGroups, $denormalizationGroups] = $this->getEffectiveSerializerGroups($options, $resourceClass); - } catch (ResourceClassNotFoundException $e) { - // TODO: for input/output classes, the serializer groups must be read from the actual resource class - return $propertyMetadata; - } - - $propertyMetadata = $this->transformReadWrite($propertyMetadata, $resourceClass, $property, $normalizationGroups, $denormalizationGroups); - - return $this->transformLinkStatus($propertyMetadata, $normalizationGroups, $denormalizationGroups); - } - - /** - * Sets readable/writable based on matching normalization/denormalization groups and property's ignorance. - * - * A false value is never reset as it could be unreadable/unwritable for other reasons. - * If normalization/denormalization groups are not specified and the property is not ignored, the property is implicitly readable/writable. - * - * @param string[]|null $normalizationGroups - * @param string[]|null $denormalizationGroups - */ - private function transformReadWrite(PropertyMetadata $propertyMetadata, string $resourceClass, string $propertyName, array $normalizationGroups = null, array $denormalizationGroups = null): PropertyMetadata - { - $serializerAttributeMetadata = $this->getSerializerAttributeMetadata($resourceClass, $propertyName); - $groups = $serializerAttributeMetadata ? $serializerAttributeMetadata->getGroups() : []; - $ignored = $serializerAttributeMetadata && method_exists($serializerAttributeMetadata, 'isIgnored') ? $serializerAttributeMetadata->isIgnored() : false; - - if (false !== $propertyMetadata->isReadable()) { - $propertyMetadata = $propertyMetadata->withReadable(!$ignored && (null === $normalizationGroups || array_intersect($normalizationGroups, $groups))); - } - - if (false !== $propertyMetadata->isWritable()) { - $propertyMetadata = $propertyMetadata->withWritable(!$ignored && (null === $denormalizationGroups || array_intersect($denormalizationGroups, $groups))); - } - - return $propertyMetadata; - } - - /** - * Sets readableLink/writableLink based on matching normalization/denormalization groups. - * - * If normalization/denormalization groups are not specified, - * set link status to false since embedding of resource must be explicitly enabled - * - * @param string[]|null $normalizationGroups - * @param string[]|null $denormalizationGroups - */ - private function transformLinkStatus(PropertyMetadata $propertyMetadata, array $normalizationGroups = null, array $denormalizationGroups = null): PropertyMetadata - { - // No need to check link status if property is not readable and not writable - if (false === $propertyMetadata->isReadable() && false === $propertyMetadata->isWritable()) { - return $propertyMetadata; - } - - $type = $propertyMetadata->getType(); - if (null === $type) { - return $propertyMetadata; - } - - if ( - $type->isCollection() && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $relatedClass = $collectionValueType->getClassName(); - } else { - $relatedClass = $type->getClassName(); - } - - // if property is not a resource relation, don't set link status (as it would have no meaning) - if (null === $relatedClass || !$this->isResourceClass($relatedClass)) { - return $propertyMetadata; - } - - // find the resource class - // this prevents serializer groups on non-resource child class from incorrectly influencing the decision - if (null !== $this->resourceClassResolver) { - $relatedClass = $this->resourceClassResolver->getResourceClass(null, $relatedClass); - } - - $relatedGroups = $this->getClassSerializerGroups($relatedClass); - - if (null === $propertyMetadata->isReadableLink()) { - $propertyMetadata = $propertyMetadata->withReadableLink(null !== $normalizationGroups && !empty(array_intersect($normalizationGroups, $relatedGroups))); - } - - if (null === $propertyMetadata->isWritableLink()) { - $propertyMetadata = $propertyMetadata->withWritableLink(null !== $denormalizationGroups && !empty(array_intersect($denormalizationGroups, $relatedGroups))); - } - - return $propertyMetadata; - } - - /** - * Gets the effective serializer groups used in normalization/denormalization. - * - * Groups are extracted in the following order: - * - * - From the "serializer_groups" key of the $options array. - * - From metadata of the given operation ("collection_operation_name" and "item_operation_name" keys). - * - From metadata of the current resource. - * - * @throws ResourceClassNotFoundException - * - * @return (string[]|null)[] - */ - private function getEffectiveSerializerGroups(array $options, string $resourceClass): array - { - if (isset($options['serializer_groups'])) { - $groups = (array) $options['serializer_groups']; - - return [$groups, $groups]; - } - - if (\array_key_exists('normalization_groups', $options) && \array_key_exists('denormalization_groups', $options)) { - return [$options['normalization_groups'] ?? null, $options['denormalization_groups'] ?? null]; - } - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (isset($options['collection_operation_name'])) { - $normalizationContext = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], 'normalization_context', null, true); - $denormalizationContext = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], 'denormalization_context', null, true); - } elseif (isset($options['item_operation_name'])) { - $normalizationContext = $resourceMetadata->getItemOperationAttribute($options['item_operation_name'], 'normalization_context', null, true); - $denormalizationContext = $resourceMetadata->getItemOperationAttribute($options['item_operation_name'], 'denormalization_context', null, true); - } elseif (isset($options['graphql_operation_name'])) { - $normalizationContext = $resourceMetadata->getGraphqlAttribute($options['graphql_operation_name'], 'normalization_context', null, true); - $denormalizationContext = $resourceMetadata->getGraphqlAttribute($options['graphql_operation_name'], 'denormalization_context', null, true); - } else { - $normalizationContext = $resourceMetadata->getAttribute('normalization_context'); - $denormalizationContext = $resourceMetadata->getAttribute('denormalization_context'); - } - - return [ - isset($normalizationContext['groups']) ? (array) $normalizationContext['groups'] : null, - isset($denormalizationContext['groups']) ? (array) $denormalizationContext['groups'] : null, - ]; - } - - private function getSerializerAttributeMetadata(string $class, string $attribute): ?AttributeMetadataInterface - { - $serializerClassMetadata = $this->serializerClassMetadataFactory->getMetadataFor($class); - - foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { - if ($attribute === $serializerAttributeMetadata->getName()) { - return $serializerAttributeMetadata; - } - } - - return null; - } - - /** - * Gets all serializer groups used in a class. - * - * @return string[] - */ - private function getClassSerializerGroups(string $class): array - { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($class); - if ($outputClass = $resourceMetadata->getAttribute('output')['class'] ?? null) { - $class = $outputClass; - } - } catch (ResourceClassNotFoundException $e) { - } - - $serializerClassMetadata = $this->serializerClassMetadataFactory->getMetadataFor($class); - - $groups = []; - foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { - $groups = array_merge($groups, $serializerAttributeMetadata->getGroups()); - } - - return array_unique($groups); - } -} diff --git a/src/Core/Metadata/Property/PropertyMetadata.php b/src/Core/Metadata/Property/PropertyMetadata.php deleted file mode 100644 index b547831720f..00000000000 --- a/src/Core/Metadata/Property/PropertyMetadata.php +++ /dev/null @@ -1,435 +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); - -namespace ApiPlatform\Core\Metadata\Property; - -use Symfony\Component\PropertyInfo\Type; - -/** - * Property metadata. - * - * @author Kévin Dunglas - */ -final class PropertyMetadata -{ - /** - * @deprecated since 2.7, to be removed in 3.0, renamed as builtinTypes - */ - private $type; - private $description; - private $readable; - private $writable; - private $readableLink; - private $writableLink; - private $required; - /** - * @deprecated since 2.7, to be removed in 3.0, renamed as types - */ - private $iri; - private $identifier; - /** - * @deprecated since 2.6, to be removed in 3.0 - */ - private $childInherited; - private $attributes; - private $subresource; - private $initializable; - /** - * @var null - */ - private $default; - /** - * @var null - */ - private $example; - private $schema; - - public function __construct(Type $type = null, string $description = null, bool $readable = null, bool $writable = null, bool $readableLink = null, bool $writableLink = null, bool $required = null, bool $identifier = null, string $iri = null, $childInherited = null, array $attributes = null, SubresourceMetadata $subresource = null, bool $initializable = null, $default = null, $example = null, array $schema = null) - { - $this->type = $type; - $this->description = $description; - $this->readable = $readable; - $this->writable = $writable; - $this->readableLink = $readableLink; - $this->writableLink = $writableLink; - $this->required = $required; - $this->identifier = $identifier; - $this->iri = $iri; - if (null !== $childInherited) { - @trigger_error(sprintf('Providing a non-null value for the 10th argument ($childInherited) of the "%s" constructor is deprecated since 2.6 and will not be supported in 3.0.', __CLASS__), \E_USER_DEPRECATED); - } - $this->childInherited = $childInherited; - $this->attributes = $attributes; - $this->subresource = $subresource; - $this->initializable = $initializable; - $this->default = $default; - $this->example = $example; - $this->schema = $schema; - } - - /** - * Gets type. - * - * @deprecated since 2.7, to be removed in 3.0, renamed as getBuiltinTypes - */ - public function getType(): ?Type - { - return $this->type; - } - - /** - * Returns a new instance with the given type. - * - * @deprecated since 2.7, to be removed in 3.0, renamed as withBuiltinTypes - */ - public function withType(Type $type): self - { - $metadata = clone $this; - $metadata->type = $type; - - return $metadata; - } - - /** - * Gets description. - */ - public function getDescription(): ?string - { - return $this->description; - } - - /** - * Returns a new instance with the given description. - */ - public function withDescription(string $description): self - { - $metadata = clone $this; - $metadata->description = $description; - - return $metadata; - } - - /** - * Is readable? - */ - public function isReadable(): ?bool - { - return $this->readable; - } - - /** - * Returns a new instance of Metadata with the given readable flag. - */ - public function withReadable(bool $readable): self - { - $metadata = clone $this; - $metadata->readable = $readable; - - return $metadata; - } - - /** - * Is writable? - */ - public function isWritable(): ?bool - { - return $this->writable; - } - - /** - * Returns a new instance with the given writable flag. - */ - public function withWritable(bool $writable): self - { - $metadata = clone $this; - $metadata->writable = $writable; - - return $metadata; - } - - /** - * Is required? - */ - public function isRequired(): ?bool - { - if (true === $this->required && false === $this->writable) { - return false; - } - - return $this->required; - } - - /** - * Returns a new instance with the given required flag. - */ - public function withRequired(bool $required): self - { - $metadata = clone $this; - $metadata->required = $required; - - return $metadata; - } - - /** - * Should an IRI or an object be provided in write context? - */ - public function isWritableLink(): ?bool - { - return $this->writableLink; - } - - /** - * Returns a new instance with the given writable link flag. - */ - public function withWritableLink(bool $writableLink): self - { - $metadata = clone $this; - $metadata->writableLink = $writableLink; - - return $metadata; - } - - /** - * Is an IRI or an object generated in read context? - */ - public function isReadableLink(): ?bool - { - return $this->readableLink; - } - - /** - * Returns a new instance with the given readable link flag. - */ - public function withReadableLink(bool $readableLink): self - { - $metadata = clone $this; - $metadata->readableLink = $readableLink; - - return $metadata; - } - - /** - * Gets IRI of this property. - */ - public function getIri(): ?string - { - return $this->iri; - } - - /** - * Returns a new instance with the given IRI. - */ - public function withIri(string $iri = null): self - { - $metadata = clone $this; - $metadata->iri = $iri; - - return $metadata; - } - - /** - * Is this attribute an identifier? - */ - public function isIdentifier(): ?bool - { - return $this->identifier; - } - - /** - * Returns a new instance with the given identifier flag. - */ - public function withIdentifier(bool $identifier): self - { - $metadata = clone $this; - $metadata->identifier = $identifier; - - return $metadata; - } - - /** - * Gets attributes. - */ - public function getAttributes(): ?array - { - return $this->attributes; - } - - /** - * Gets an attribute. - * - * @param mixed|null $defaultValue - */ - public function getAttribute(string $key, $defaultValue = null) - { - return $this->attributes[$key] ?? $defaultValue; - } - - /** - * Returns a new instance with the given attribute. - */ - public function withAttributes(array $attributes): self - { - $metadata = clone $this; - $metadata->attributes = $attributes; - - return $metadata; - } - - /** - * @deprecated since 2.6, to be removed in 3.0 - */ - public function getChildInherited(): ?string - { - return $this->childInherited; - } - - /** - * @deprecated since 2.6, to be removed in 3.0 - */ - public function hasChildInherited(): bool - { - return null !== $this->childInherited; - } - - /** - * @deprecated since 2.4, to be removed in 3.0 - */ - public function isChildInherited(): ?string - { - @trigger_error(sprintf('"%s::%s" is deprecated since 2.4 and will be removed in 3.0.', __CLASS__, __METHOD__), \E_USER_DEPRECATED); - - return $this->getChildInherited(); - } - - /** - * @deprecated since 2.6, to be removed in 3.0 - */ - public function withChildInherited(string $childInherited): self - { - @trigger_error(sprintf('"%s::%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__, __METHOD__), \E_USER_DEPRECATED); - - $metadata = clone $this; - $metadata->childInherited = $childInherited; - - return $metadata; - } - - /** - * Represents whether the property has a subresource. - */ - public function hasSubresource(): bool - { - return null !== $this->subresource; - } - - /** - * Gets the subresource metadata. - */ - public function getSubresource(): ?SubresourceMetadata - { - return $this->subresource; - } - - /** - * Returns a new instance with the given subresource. - * - * @param SubresourceMetadata $subresource - */ - public function withSubresource(SubresourceMetadata $subresource = null): self - { - $metadata = clone $this; - $metadata->subresource = $subresource; - - return $metadata; - } - - /** - * Is initializable? - */ - public function isInitializable(): ?bool - { - return $this->initializable; - } - - /** - * Returns a new instance with the given initializable flag. - */ - public function withInitializable(bool $initializable): self - { - $metadata = clone $this; - $metadata->initializable = $initializable; - - return $metadata; - } - - /** - * Returns the default value of the property or NULL if the property doesn't have a default value. - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns a new instance with the given default value for the property. - * - * @param mixed $default - */ - public function withDefault($default): self - { - $metadata = clone $this; - $metadata->default = $default; - - return $metadata; - } - - /** - * Returns an example of the value of the property. - */ - public function getExample() - { - return $this->example; - } - - /** - * Returns a new instance with the given example. - * - * @param mixed $example - */ - public function withExample($example): self - { - $metadata = clone $this; - $metadata->example = $example; - - return $metadata; - } - - /** - * @return array - */ - public function getSchema(): ?array - { - return $this->schema; - } - - /** - * Returns a new instance with the given schema. - */ - public function withSchema(array $schema = null): self - { - $metadata = clone $this; - $metadata->schema = $schema; - - return $metadata; - } -} diff --git a/src/Core/Metadata/Property/PropertyNameCollection.php b/src/Core/Metadata/Property/PropertyNameCollection.php deleted file mode 100644 index 4da85d2d1b5..00000000000 --- a/src/Core/Metadata/Property/PropertyNameCollection.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Metadata\Property; - -class_exists(\ApiPlatform\Metadata\Property\PropertyNameCollection::class); - -if (false) { - final class PropertyNameCollection extends \ApiPlatform\Metadata\Property\PropertyNameCollection - { - } -} diff --git a/src/Core/Metadata/Property/SubresourceMetadata.php b/src/Core/Metadata/Property/SubresourceMetadata.php deleted file mode 100644 index f5d1c9e35aa..00000000000 --- a/src/Core/Metadata/Property/SubresourceMetadata.php +++ /dev/null @@ -1,64 +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); - -namespace ApiPlatform\Core\Metadata\Property; - -/** - * Subresource metadata. - * - * @author Antoine Bluchet - */ -final class SubresourceMetadata -{ - private $resourceClass; - private $collection; - private $maxDepth; - - public function __construct(string $resourceClass, bool $collection = false, int $maxDepth = null) - { - $this->resourceClass = $resourceClass; - $this->collection = $collection; - $this->maxDepth = $maxDepth; - } - - public function getResourceClass(): string - { - return $this->resourceClass; - } - - public function withResourceClass($resourceClass): self - { - $metadata = clone $this; - $metadata->resourceClass = $resourceClass; - - return $metadata; - } - - public function isCollection(): bool - { - return $this->collection; - } - - public function withCollection(bool $collection): self - { - $metadata = clone $this; - $metadata->collection = $collection; - - return $metadata; - } - - public function getMaxDepth(): ?int - { - return $this->maxDepth; - } -} diff --git a/src/Core/Metadata/Resource/ApiResourceToLegacyResourceMetadataTrait.php b/src/Core/Metadata/Resource/ApiResourceToLegacyResourceMetadataTrait.php deleted file mode 100644 index 482a4b2995e..00000000000 --- a/src/Core/Metadata/Resource/ApiResourceToLegacyResourceMetadataTrait.php +++ /dev/null @@ -1,126 +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); - -namespace ApiPlatform\Core\Metadata\Resource; - -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\CollectionOperationInterface; -use ApiPlatform\Metadata\HttpOperation; -use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; - -/** - * @internal - * - * @deprecated - */ -trait ApiResourceToLegacyResourceMetadataTrait -{ - private $camelCaseToSnakeCaseNameConverter; - - private function transformResourceToResourceMetadata(ApiResource $resource): ResourceMetadata - { - $collectionOperations = []; - $itemOperations = []; - foreach ($resource->getOperations() as $name => $operation) { - $arrayOperation = $this->toArray($operation); - - if (!isset($arrayOperation['openapi_context'])) { - $arrayOperation['openapi_context'] = []; - } - - $arrayOperation['openapi_context']['operationId'] = $name; - $arrayOperation['composite_identifier'] = $this->hasCompositeIdentifier($operation); - - if (HttpOperation::METHOD_POST === $operation->getMethod() && !$operation->getUriVariables()) { - $collectionOperations[$name] = $arrayOperation; - continue; - } - - if ($operation instanceof CollectionOperationInterface) { - $collectionOperations[$name] = $arrayOperation; - continue; - } - - $itemOperations[$name] = $arrayOperation; - } - - $attributes = $this->toArray($resource); - - $graphqlOperations = $resource->getGraphQlOperations() ? [] : null; - foreach ($resource->getGraphQlOperations() ?? [] as $operationName => $operation) { - $graphqlOperations[$operationName] = $this->toArray($operation); - } - - return new ResourceMetadata($resource->getShortName(), $resource->getDescription(), $resource->getTypes()[0] ?? null, $itemOperations, $collectionOperations, $attributes, null, $graphqlOperations); - } - - private function toArray($object): array - { - if (!$this->camelCaseToSnakeCaseNameConverter) { - $this->camelCaseToSnakeCaseNameConverter = new CamelCaseToSnakeCaseNameConverter(); - } - - $arr = []; - foreach (get_class_methods($object) as $methodName) { - if ('getOperations' === $methodName || 0 !== strpos($methodName, 'get')) { - continue; - } - - if (null === $value = $object->{$methodName}()) { - continue; - } - - $arr[$this->camelCaseToSnakeCaseNameConverter->normalize(lcfirst(substr($methodName, 3)))] = $value; - } - - return $this->transformUriVariablesToIdentifiers($arr); - } - - private function transformUriVariablesToIdentifiers(array $arrayOperation): array - { - if (!isset($arrayOperation['uri_variables'])) { - return $arrayOperation; - } - - if (!\is_array($arrayOperation['uri_variables'])) { - $arrayOperation['identifiers'] = $arrayOperation['uri_variables']; - - return $arrayOperation; - } - - $arrayOperation['identifiers'] = []; - foreach ($arrayOperation['uri_variables'] as $parameterName => $identifiedBy) { - if (1 === \count($identifiedBy->getIdentifiers() ?? ['id'])) { - $arrayOperation['identifiers'][$parameterName] = [$identifiedBy->getFromClass(), $identifiedBy->getIdentifiers()[0] ?? ['id']]; - continue; - } - - foreach ($identifiedBy->getIdentifiers() as $identifier) { - $arrayOperation['identifiers'][$identifier] = [$identifiedBy->getFromClass(), $identifier]; - } - } - - return $arrayOperation; - } - - private function hasCompositeIdentifier(HttpOperation $operation): bool - { - foreach ($operation->getUriVariables() ?? [] as $parameterName => $uriVariable) { - if ($uriVariable->getCompositeIdentifier()) { - return true; - } - } - - return false; - } -} diff --git a/src/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php b/src/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php deleted file mode 100644 index bdc02f52afc..00000000000 --- a/src/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php +++ /dev/null @@ -1,94 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Util\AnnotationFilterExtractorTrait; -use Doctrine\Common\Annotations\Reader; - -/** - * Adds filters to the resource metadata {@see ApiFilter} annotation. - * - * @author Antoine Bluchet - */ -final class AnnotationResourceFilterMetadataFactory implements ResourceMetadataFactoryInterface -{ - use AnnotationFilterExtractorTrait; - - private $reader; - private $decorated; - - public function __construct(?Reader $reader = null, ResourceMetadataFactoryInterface $decorated = null) - { - $this->reader = $reader; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $parentResourceMetadata = null; - if ($this->decorated) { - $parentResourceMetadata = $this->decorated->create($resourceClass); - } - - if (null === $parentResourceMetadata) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - $filters = array_keys($this->readFilterAnnotations($reflectionClass, $this->reader)); - - if (!$filters) { - return $parentResourceMetadata; - } - - $parentFilters = $parentResourceMetadata->getAttribute('filters', []); - - if ($parentFilters) { - $filters = array_merge($parentFilters, $filters); - } - - $attributes = $parentResourceMetadata->getAttributes(); - - if (!$attributes) { - $attributes = []; - } - - return $parentResourceMetadata->withAttributes(array_merge($attributes, ['filters' => $filters])); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws ResourceClassNotFoundException - */ - private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, string $resourceClass): ResourceMetadata - { - if (null !== $parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass)); - } -} diff --git a/src/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php deleted file mode 100644 index 921f9e8c4f8..00000000000 --- a/src/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php +++ /dev/null @@ -1,145 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use Doctrine\Common\Annotations\Reader; - -/** - * Creates a resource metadata from {@see ApiResource} annotations. - * - * @author Kévin Dunglas - */ -final class AnnotationResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $reader; - private $decorated; - private $defaults; - - public function __construct(Reader $reader = null, ResourceMetadataFactoryInterface $decorated = null, array $defaults = []) - { - $this->reader = $reader; - $this->decorated = $decorated; - $this->defaults = $defaults + ['attributes' => []]; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $parentResourceMetadata = null; - if ($this->decorated) { - try { - $parentResourceMetadata = $this->decorated->create($resourceClass); - } catch (ResourceClassNotFoundException $resourceNotFoundException) { - // Ignore not found exception from decorated factories - } - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionClass->getAttributes(ApiResource::class)) { - return $this->createMetadata($attributes[0]->newInstance(), $parentResourceMetadata); - } - - if (null === $this->reader) { - $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - $resourceAnnotation = $this->reader->getClassAnnotation($reflectionClass, ApiResource::class); - - if (!$resourceAnnotation instanceof ApiResource) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - return $this->createMetadata($resourceAnnotation, $parentResourceMetadata); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws ResourceClassNotFoundException - */ - private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, string $resourceClass): ResourceMetadata - { - if (null !== $parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass)); - } - - private function createMetadata(ApiResource $annotation, ResourceMetadata $parentResourceMetadata = null): ResourceMetadata - { - $attributes = null; - if (null !== $annotation->attributes || [] !== $this->defaults['attributes']) { - $attributes = (array) $annotation->attributes; - foreach ($this->defaults['attributes'] as $key => $value) { - if (!isset($attributes[$key])) { - $attributes[$key] = $value; - } - } - } - - if (!$parentResourceMetadata) { - return new ResourceMetadata( - $annotation->shortName, - $annotation->description ?? $this->defaults['description'] ?? null, // @phpstan-ignore-line - $annotation->iri ?? $this->defaults['iri'] ?? null, // @phpstan-ignore-line - $annotation->itemOperations ?? $this->defaults['item_operations'] ?? null, // @phpstan-ignore-line - $annotation->collectionOperations ?? $this->defaults['collection_operations'] ?? null, // @phpstan-ignore-line - $attributes, - $annotation->subresourceOperations, - $annotation->graphql ?? $this->defaults['graphql'] ?? null // @phpstan-ignore-line - ); - } - - $resourceMetadata = $parentResourceMetadata; - foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) { - $resourceMetadata = $this->createWith($resourceMetadata, $property, $annotation->{$property}); - } - - return $resourceMetadata; - } - - /** - * Creates a new instance of metadata if the property is not already set. - * - * @param mixed $value - */ - private function createWith(ResourceMetadata $resourceMetadata, string $property, $value): ResourceMetadata - { - $upperProperty = ucfirst($property); - $getter = "get$upperProperty"; - - if (null !== $resourceMetadata->{$getter}()) { - return $resourceMetadata; - } - - if (null === $value) { - return $resourceMetadata; - } - - $wither = "with$upperProperty"; - - return $resourceMetadata->{$wither}($value); - } -} diff --git a/src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php b/src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php deleted file mode 100644 index b99835902bd..00000000000 --- a/src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php +++ /dev/null @@ -1,67 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Util\ReflectionClassRecursiveIterator; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use Doctrine\Common\Annotations\Reader; - -/** - * Creates a resource name collection from {@see ApiResource} annotations. - * - * @author Kévin Dunglas - */ -final class AnnotationResourceNameCollectionFactory implements ResourceNameCollectionFactoryInterface -{ - private $reader; - private $paths; - private $decorated; - - /** - * @param string[] $paths - */ - public function __construct(Reader $reader = null, array $paths, ResourceNameCollectionFactoryInterface $decorated = null) - { - $this->reader = $reader; - $this->paths = $paths; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(): ResourceNameCollection - { - $classes = []; - - if ($this->decorated) { - foreach ($this->decorated->create() as $resourceClass) { - $classes[$resourceClass] = true; - } - } - - foreach (ReflectionClassRecursiveIterator::getReflectionClassesFromDirectories($this->paths) as $className => $reflectionClass) { - if ( - (\PHP_VERSION_ID >= 80000 && $reflectionClass->getAttributes(ApiResource::class)) || - (null !== $this->reader && $this->reader->getClassAnnotation($reflectionClass, ApiResource::class)) - ) { - $classes[$className] = true; - } - } - - return new ResourceNameCollection(array_keys($classes)); - } -} diff --git a/src/Core/Metadata/Resource/Factory/CachedResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/CachedResourceMetadataFactory.php deleted file mode 100644 index 1398bb2fabb..00000000000 --- a/src/Core/Metadata/Resource/Factory/CachedResourceMetadataFactory.php +++ /dev/null @@ -1,50 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Util\CachedTrait; -use Psr\Cache\CacheItemPoolInterface; - -/** - * Caches resource metadata. - * - * @author Teoh Han Hui - */ -final class CachedResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - use CachedTrait; - - public const CACHE_KEY_PREFIX = 'resource_metadata_'; - - private $decorated; - - public function __construct(CacheItemPoolInterface $cacheItemPool, ResourceMetadataFactoryInterface $decorated) - { - $this->cacheItemPool = $cacheItemPool; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $cacheKey = self::CACHE_KEY_PREFIX.md5($resourceClass); - - return $this->getCached($cacheKey, function () use ($resourceClass) { - return $this->decorated->create($resourceClass); - }); - } -} diff --git a/src/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php deleted file mode 100644 index c5992301e46..00000000000 --- a/src/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php +++ /dev/null @@ -1,104 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Exception\ResourceClassNotFoundException; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Metadata\Extractor\ResourceExtractorInterface; - -/** - * Creates resource's metadata using an extractor. - * - * @author Kévin Dunglas - * @author Antoine Bluchet - */ -final class ExtractorResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $extractor; - private $decorated; - private $defaults; - - public function __construct(ResourceExtractorInterface $extractor, ResourceMetadataFactoryInterface $decorated = null, array $defaults = []) - { - $this->extractor = $extractor; - $this->decorated = $decorated; - $this->defaults = $defaults + ['attributes' => []]; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $parentResourceMetadata = null; - if ($this->decorated) { - try { - $parentResourceMetadata = $this->decorated->create($resourceClass); - } catch (ResourceClassNotFoundException $resourceNotFoundException) { - // Ignore not found exception from decorated factories - } - } - - if (!(class_exists($resourceClass) || interface_exists($resourceClass)) || !$resource = $this->extractor->getResources()[$resourceClass] ?? false) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - $resource['description'] = $resource['description'] ?? $this->defaults['description'] ?? null; - $resource['iri'] = $resource['iri'] ?? $this->defaults['iri'] ?? null; - $resource['itemOperations'] = $resource['itemOperations'] ?? $this->defaults['item_operations'] ?? null; - $resource['collectionOperations'] = $resource['collectionOperations'] ?? $this->defaults['collection_operations'] ?? null; - $resource['graphql'] = $resource['graphql'] ?? $this->defaults['graphql'] ?? null; - - if (\array_key_exists('attributes', $resource) && (null !== $resource['attributes'] || [] !== $this->defaults['attributes'])) { - $resource['attributes'] = (array) $resource['attributes']; - foreach ($this->defaults['attributes'] as $key => $value) { - if (!isset($resource['attributes'][$key])) { - $resource['attributes'][$key] = $value; - } - } - } - - return $this->update($parentResourceMetadata ?: new ResourceMetadata(), $resource); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws ResourceClassNotFoundException - */ - private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, string $resourceClass): ResourceMetadata - { - if (null !== $parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass)); - } - - /** - * Creates a new instance of metadata if the property is not already set. - */ - private function update(ResourceMetadata $resourceMetadata, array $metadata): ResourceMetadata - { - foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) { - if (!\array_key_exists($property, $metadata) || null === $metadata[$property] || null !== $resourceMetadata->{'get'.ucfirst($property)}()) { - continue; - } - - $resourceMetadata = $resourceMetadata->{'with'.ucfirst($property)}($metadata[$property]); - } - - return $resourceMetadata; - } -} diff --git a/src/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php deleted file mode 100644 index 9b34ba45c43..00000000000 --- a/src/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php +++ /dev/null @@ -1,127 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ResourceClassNotFoundException; - -/** - * Normalizes enabled formats. - * - * Formats hierarchy: - * * resource formats - * * resource input/output formats - * * operation formats - * * operation input/output formats - * - * @author Kévin Dunglas - */ -final class FormatsResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - private $formats; - private $patchFormats; - - public function __construct(ResourceMetadataFactoryInterface $decorated, array $formats, array $patchFormats) - { - $this->decorated = $decorated; - $this->formats = $formats; - $this->patchFormats = $patchFormats; - } - - /** - * Adds the formats attributes. - * - * @see OperationResourceMetadataFactory - * - * @throws ResourceClassNotFoundException - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - $rawResourceFormats = $resourceMetadata->getAttribute('formats'); - $resourceFormats = null === $rawResourceFormats ? $this->formats : $this->normalizeFormats($rawResourceFormats); - - $rawResourceInputFormats = $resourceMetadata->getAttribute('input_formats'); - $rawResourceOutputFormats = $resourceMetadata->getAttribute('output_formats'); - - $resourceInputFormats = $rawResourceInputFormats ? $this->normalizeFormats($rawResourceInputFormats) : $resourceFormats; - $resourceOutputFormats = $rawResourceOutputFormats ? $this->normalizeFormats($rawResourceOutputFormats) : $resourceFormats; - - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - $resourceMetadata = $resourceMetadata->withCollectionOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $collectionOperations)); - } - - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - $resourceMetadata = $resourceMetadata->withItemOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $itemOperations)); - } - - if (null !== $subresourceOperations = $resourceMetadata->getSubresourceOperations()) { - $resourceMetadata = $resourceMetadata->withSubresourceOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $subresourceOperations)); - } - - return $resourceMetadata; - } - - private function normalize(array $resourceInputFormats, array $resourceOutputFormats, array $operations): array - { - $newOperations = []; - foreach ($operations as $operationName => $operation) { - if ('PATCH' === ($operation['method'] ?? '') && !isset($operation['formats']) && !isset($operation['input_formats'])) { - $operation['input_formats'] = $this->patchFormats; - } - - if (isset($operation['formats'])) { - $operation['formats'] = $this->normalizeFormats($operation['formats']); - } - - $operation['input_formats'] = isset($operation['input_formats']) ? $this->normalizeFormats($operation['input_formats']) : $operation['formats'] ?? $resourceInputFormats; - $operation['output_formats'] = isset($operation['output_formats']) ? $this->normalizeFormats($operation['output_formats']) : $operation['formats'] ?? $resourceOutputFormats; - - $newOperations[$operationName] = $operation; - } - - return $newOperations; - } - - /** - * @param array|string $currentFormats - * - * @throws InvalidArgumentException - */ - private function normalizeFormats($currentFormats): array - { - $currentFormats = (array) $currentFormats; - - $normalizedFormats = []; - foreach ($currentFormats as $format => $value) { - if (!is_numeric($format)) { - $normalizedFormats[$format] = (array) $value; - continue; - } - if (!\is_string($value)) { - throw new InvalidArgumentException(sprintf("The 'formats' attributes value must be a string when trying to include an already configured format, %s given.", \gettype($value))); - } - if (\array_key_exists($value, $this->formats)) { - $normalizedFormats[$value] = $this->formats[$value]; - continue; - } - - throw new InvalidArgumentException(sprintf("You either need to add the format '%s' to your project configuration or declare a mime type for it in your annotation.", $value)); - } - - return $normalizedFormats; - } -} diff --git a/src/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php deleted file mode 100644 index 24e7b997d72..00000000000 --- a/src/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php +++ /dev/null @@ -1,109 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Transforms the given input/output metadata to a normalized one. - * - * @author Antoine Bluchet - */ -final class InputOutputResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - - public function __construct(ResourceMetadataFactoryInterface $decorated) - { - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - - $attributes = $resourceMetadata->getAttributes() ?: []; - $attributes['input'] = isset($attributes['input']) ? $this->transformInputOutput($attributes['input']) : null; - $attributes['output'] = isset($attributes['output']) ? $this->transformInputOutput($attributes['output']) : null; - - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - $resourceMetadata = $resourceMetadata->withCollectionOperations($this->getTransformedOperations($collectionOperations, $attributes)); - } - - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - $resourceMetadata = $resourceMetadata->withItemOperations($this->getTransformedOperations($itemOperations, $attributes)); - } - - if (null !== $graphQlAttributes = $resourceMetadata->getGraphql()) { - $resourceMetadata = $resourceMetadata->withGraphql($this->getTransformedOperations($graphQlAttributes, $attributes)); - } - - return $resourceMetadata->withAttributes($attributes); - } - - private function getTransformedOperations(array $operations, array $resourceAttributes): array - { - foreach ($operations as $key => &$operation) { - if (!\is_array($operation)) { - continue; - } - - $operation['input'] = isset($operation['input']) ? $this->transformInputOutput($operation['input']) : $resourceAttributes['input']; - $operation['output'] = isset($operation['output']) ? $this->transformInputOutput($operation['output']) : $resourceAttributes['output']; - - if ( - isset($operation['input']) - && \array_key_exists('class', $operation['input']) - && null === $operation['input']['class'] - ) { - $operation['deserialize'] ?? $operation['deserialize'] = false; - $operation['validate'] ?? $operation['validate'] = false; - } - - if ( - isset($operation['output']) - && \array_key_exists('class', $operation['output']) - && null === $operation['output']['class'] - ) { - $operation['status'] ?? $operation['status'] = 204; - } - } - - return $operations; - } - - private function transformInputOutput($attribute): ?array - { - if (null === $attribute) { - return null; - } - - if (false === $attribute) { - return ['class' => null]; - } - - if (\is_string($attribute)) { - $attribute = ['class' => $attribute]; - } - - if (!isset($attribute['name']) && isset($attribute['class'])) { - $attribute['name'] = (new \ReflectionClass($attribute['class']))->getShortName(); - } - - return $attribute; - } -} diff --git a/src/Core/Metadata/Resource/Factory/OperationResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/OperationResourceMetadataFactory.php deleted file mode 100644 index 52f65fde23c..00000000000 --- a/src/Core/Metadata/Resource/Factory/OperationResourceMetadataFactory.php +++ /dev/null @@ -1,153 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Creates or completes operations. - * - * @author Kévin Dunglas - */ -final class OperationResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - /** - * @internal - */ - public const SUPPORTED_COLLECTION_OPERATION_METHODS = [ - 'GET' => true, - 'POST' => true, - ]; - - /** - * @internal - */ - public const SUPPORTED_ITEM_OPERATION_METHODS = [ - 'GET' => true, - 'PUT' => true, - // PATCH is automatically supported if at least one patch format has been configured - 'DELETE' => true, - ]; - - private $decorated; - private $patchFormats; - - public function __construct(ResourceMetadataFactoryInterface $decorated, array $patchFormats = []) - { - $this->decorated = $decorated; - $this->patchFormats = $patchFormats; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - $isAbstract = (new \ReflectionClass($resourceClass))->isAbstract(); - - $collectionOperations = $resourceMetadata->getCollectionOperations(); - if (null === $collectionOperations) { - $resourceMetadata = $resourceMetadata->withCollectionOperations($this->createOperations($isAbstract ? ['GET'] : ['GET', 'POST'], $resourceMetadata)); - } else { - $resourceMetadata = $this->normalize(true, $resourceClass, $resourceMetadata, $collectionOperations); - } - - $itemOperations = $resourceMetadata->getItemOperations(); - if (null === $itemOperations) { - $methods = ['GET', 'DELETE']; - - if (!$isAbstract) { - $methods[] = 'PUT'; - - if ($this->patchFormats) { - $methods[] = 'PATCH'; - } - } - - $resourceMetadata = $resourceMetadata->withItemOperations($this->createOperations($methods, $resourceMetadata)); - } else { - $resourceMetadata = $this->normalize(false, $resourceClass, $resourceMetadata, $itemOperations); - } - - $graphql = $resourceMetadata->getGraphql(); - if (null === $graphql) { - $resourceMetadata = $resourceMetadata->withGraphql(['item_query' => [], 'collection_query' => [], 'delete' => [], 'update' => [], 'create' => []]); - } else { - $resourceMetadata = $this->normalizeGraphQl($resourceMetadata, $graphql); - } - - return $resourceMetadata; - } - - private function createOperations(array $methods, ResourceMetadata $resourceMetadata): array - { - $operations = []; - foreach ($methods as $method) { - $operations[strtolower($method)] = ['method' => $method, 'stateless' => $resourceMetadata->getAttribute('stateless')]; - } - - return $operations; - } - - private function normalize(bool $collection, string $resourceClass, ResourceMetadata $resourceMetadata, array $operations): ResourceMetadata - { - $newOperations = []; - foreach ($operations as $operationName => $operation) { - // e.g.: @ApiResource(itemOperations={"get"}) - if (\is_int($operationName) && \is_string($operation)) { - $operationName = $operation; - $operation = []; - } - - $upperOperationName = strtoupper((string) $operationName); - if ($collection) { - $supported = isset(self::SUPPORTED_COLLECTION_OPERATION_METHODS[$upperOperationName]); - } else { - $supported = isset(self::SUPPORTED_ITEM_OPERATION_METHODS[$upperOperationName]) || ($this->patchFormats && 'PATCH' === $upperOperationName); - } - - if (!isset($operation['method']) && !isset($operation['route_name'])) { - if ($supported) { - $operation['method'] = $upperOperationName; - } else { - @trigger_error(sprintf('The "route_name" attribute will not be set automatically again in API Platform 3.0, set it for the %s operation "%s" of the class "%s".', $collection ? 'collection' : 'item', $operationName, $resourceClass), \E_USER_DEPRECATED); - $operation['route_name'] = $operationName; - } - } - - if (isset($operation['method'])) { - $operation['method'] = strtoupper($operation['method']); - } - - $operation['stateless'] = $operation['stateless'] ?? $resourceMetadata->getAttribute('stateless'); - - $newOperations[$operationName] = $operation; - } - - return $collection ? $resourceMetadata->withCollectionOperations($newOperations) : $resourceMetadata->withItemOperations($newOperations); - } - - private function normalizeGraphQl(ResourceMetadata $resourceMetadata, array $operations): ResourceMetadata - { - foreach ($operations as $operationName => $operation) { - if (\is_int($operationName) && \is_string($operation)) { - unset($operations[$operationName]); - $operations[$operation] = []; - } - } - - return $resourceMetadata->withGraphql($operations); - } -} diff --git a/src/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php deleted file mode 100644 index f2257d24efd..00000000000 --- a/src/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php +++ /dev/null @@ -1,61 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use phpDocumentor\Reflection\DocBlockFactory; -use phpDocumentor\Reflection\DocBlockFactoryInterface; -use phpDocumentor\Reflection\Types\ContextFactory; - -/** - * Extracts descriptions from PHPDoc. - * - * @author Kévin Dunglas - */ -final class PhpDocResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - private $docBlockFactory; - private $contextFactory; - - public function __construct(ResourceMetadataFactoryInterface $decorated, DocBlockFactoryInterface $docBlockFactory = null) - { - $this->decorated = $decorated; - $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance(); - $this->contextFactory = new ContextFactory(); - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - - if (null !== $resourceMetadata->getDescription()) { - return $resourceMetadata; - } - - $reflectionClass = new \ReflectionClass($resourceClass); - - try { - $docBlock = $this->docBlockFactory->create($reflectionClass, $this->contextFactory->createFromReflector($reflectionClass)); - $resourceMetadata = $resourceMetadata->withDescription($docBlock->getSummary()); - } catch (\InvalidArgumentException $e) { - // Ignore empty DocBlocks - } - - return $resourceMetadata; - } -} diff --git a/src/Core/Metadata/Resource/Factory/ResourceMetadataFactoryInterface.php b/src/Core/Metadata/Resource/Factory/ResourceMetadataFactoryInterface.php deleted file mode 100644 index 8032e73377e..00000000000 --- a/src/Core/Metadata/Resource/Factory/ResourceMetadataFactoryInterface.php +++ /dev/null @@ -1,32 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; - -/** - * Creates a resource metadata value object. - * - * @author Kévin Dunglas - */ -interface ResourceMetadataFactoryInterface -{ - /** - * Creates a resource metadata. - * - * @throws ResourceClassNotFoundException - */ - public function create(string $resourceClass): ResourceMetadata; -} diff --git a/src/Core/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php deleted file mode 100644 index c7f9e898f63..00000000000 --- a/src/Core/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php +++ /dev/null @@ -1,49 +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); - -namespace ApiPlatform\Core\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Guesses the short name from the class name if not already set. - * - * @author Kévin Dunglas - */ -final class ShortNameResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - - public function __construct(ResourceMetadataFactoryInterface $decorated) - { - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - - if (null !== $resourceMetadata->getShortName()) { - return $resourceMetadata; - } - - if (false !== $pos = strrpos($resourceClass, '\\')) { - return $resourceMetadata->withShortName(substr($resourceClass, $pos + 1)); - } - - return $resourceMetadata->withShortName($resourceClass); - } -} diff --git a/src/Core/Metadata/Resource/ResourceMetadata.php b/src/Core/Metadata/Resource/ResourceMetadata.php deleted file mode 100644 index cc226f6c201..00000000000 --- a/src/Core/Metadata/Resource/ResourceMetadata.php +++ /dev/null @@ -1,311 +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); - -namespace ApiPlatform\Core\Metadata\Resource; - -use ApiPlatform\Core\Api\OperationType; - -/** - * Resource metadata. - * - * @author Kévin Dunglas - */ -final class ResourceMetadata -{ - private $shortName; - private $description; - private $iri; - private $itemOperations; - private $collectionOperations; - private $subresourceOperations; - private $graphql; - private $attributes; - - public function __construct(string $shortName = null, string $description = null, string $iri = null, array $itemOperations = null, array $collectionOperations = null, array $attributes = null, array $subresourceOperations = null, array $graphql = null) - { - $this->shortName = $shortName; - $this->description = $description; - $this->iri = $iri; - $this->itemOperations = $itemOperations; - $this->collectionOperations = $collectionOperations; - $this->subresourceOperations = $subresourceOperations; - $this->graphql = $graphql; - $this->attributes = $attributes; - } - - /** - * Gets the short name. - */ - public function getShortName(): ?string - { - return $this->shortName; - } - - /** - * Returns a new instance with the given short name. - */ - public function withShortName(string $shortName): self - { - $metadata = clone $this; - $metadata->shortName = $shortName; - - return $metadata; - } - - /** - * Gets the description. - */ - public function getDescription(): ?string - { - return $this->description; - } - - /** - * Returns a new instance with the given description. - */ - public function withDescription(string $description): self - { - $metadata = clone $this; - $metadata->description = $description; - - return $metadata; - } - - /** - * Gets the associated IRI. - */ - public function getIri(): ?string - { - return $this->iri; - } - - /** - * Returns a new instance with the given IRI. - */ - public function withIri(string $iri): self - { - $metadata = clone $this; - $metadata->iri = $iri; - - return $metadata; - } - - /** - * Gets item operations. - */ - public function getItemOperations(): ?array - { - return $this->itemOperations; - } - - /** - * Returns a new instance with the given item operations. - */ - public function withItemOperations(array $itemOperations): self - { - $metadata = clone $this; - $metadata->itemOperations = $itemOperations; - - return $metadata; - } - - /** - * Gets collection operations. - */ - public function getCollectionOperations(): ?array - { - return $this->collectionOperations; - } - - /** - * Returns a new instance with the given collection operations. - */ - public function withCollectionOperations(array $collectionOperations): self - { - $metadata = clone $this; - $metadata->collectionOperations = $collectionOperations; - - return $metadata; - } - - /** - * Gets subresource operations. - */ - public function getSubresourceOperations(): ?array - { - return $this->subresourceOperations; - } - - /** - * Returns a new instance with the given subresource operations. - */ - public function withSubresourceOperations(array $subresourceOperations): self - { - $metadata = clone $this; - $metadata->subresourceOperations = $subresourceOperations; - - return $metadata; - } - - /** - * Gets a collection operation attribute, optionally fallback to a resource attribute. - * - * @param mixed|null $defaultValue - */ - public function getCollectionOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - return $this->findOperationAttribute($this->collectionOperations, $operationName, $key, $defaultValue, $resourceFallback); - } - - /** - * Gets an item operation attribute, optionally fallback to a resource attribute. - * - * @param mixed|null $defaultValue - */ - public function getItemOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - return $this->findOperationAttribute($this->itemOperations, $operationName, $key, $defaultValue, $resourceFallback); - } - - /** - * Gets a subresource operation attribute, optionally fallback to a resource attribute. - * - * @param mixed|null $defaultValue - */ - public function getSubresourceOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - return $this->findOperationAttribute($this->subresourceOperations, $operationName, $key, $defaultValue, $resourceFallback); - } - - public function getGraphqlAttribute(string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - if (isset($this->graphql[$operationName][$key])) { - return $this->graphql[$operationName][$key]; - } - - if ($resourceFallback && isset($this->attributes[$key])) { - return $this->attributes[$key]; - } - - return $defaultValue; - } - - /** - * Gets the first available operation attribute according to the following order: collection, item, subresource, optionally fallback to a default value. - * - * @param mixed|null $defaultValue - */ - public function getOperationAttribute(array $attributes, string $key, $defaultValue = null, bool $resourceFallback = false) - { - if (isset($attributes['collection_operation_name'])) { - return $this->getCollectionOperationAttribute($attributes['collection_operation_name'], $key, $defaultValue, $resourceFallback); - } - - if (isset($attributes['item_operation_name'])) { - return $this->getItemOperationAttribute($attributes['item_operation_name'], $key, $defaultValue, $resourceFallback); - } - - if (isset($attributes['subresource_operation_name'])) { - return $this->getSubresourceOperationAttribute($attributes['subresource_operation_name'], $key, $defaultValue, $resourceFallback); - } - - if ($resourceFallback && isset($this->attributes[$key])) { - return $this->attributes[$key]; - } - - return $defaultValue; - } - - /** - * Gets an attribute for a given operation type and operation name. - * - * @param mixed|null $defaultValue - */ - public function getTypedOperationAttribute(string $operationType, string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - switch ($operationType) { - case OperationType::COLLECTION: - return $this->getCollectionOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); - case OperationType::ITEM: - return $this->getItemOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); - default: - return $this->getSubresourceOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); - } - } - - /** - * Gets attributes. - */ - public function getAttributes(): ?array - { - return $this->attributes; - } - - /** - * Gets an attribute. - * - * @param mixed|null $defaultValue - */ - public function getAttribute(string $key, $defaultValue = null) - { - return $this->attributes[$key] ?? $defaultValue; - } - - /** - * Returns a new instance with the given attribute. - */ - public function withAttributes(array $attributes): self - { - $metadata = clone $this; - $metadata->attributes = $attributes; - - return $metadata; - } - - /** - * Gets options of for the GraphQL query. - */ - public function getGraphql(): ?array - { - return $this->graphql; - } - - /** - * Returns a new instance with the given GraphQL options. - */ - public function withGraphql(array $graphql): self - { - $metadata = clone $this; - $metadata->graphql = $graphql; - - return $metadata; - } - - /** - * Gets an operation attribute, optionally fallback to a resource attribute. - * - * @param mixed|null $defaultValue - */ - private function findOperationAttribute(?array $operations, ?string $operationName, string $key, $defaultValue, bool $resourceFallback) - { - if (null !== $operationName && isset($operations[$operationName][$key])) { - return $operations[$operationName][$key]; - } - - if ($resourceFallback && isset($this->attributes[$key])) { - return $this->attributes[$key]; - } - - return $defaultValue; - } -} diff --git a/src/Core/Metadata/Resource/ToggleableOperationAttributeTrait.php b/src/Core/Metadata/Resource/ToggleableOperationAttributeTrait.php deleted file mode 100644 index b1aa81da947..00000000000 --- a/src/Core/Metadata/Resource/ToggleableOperationAttributeTrait.php +++ /dev/null @@ -1,44 +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); - -namespace ApiPlatform\Core\Metadata\Resource; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; - -/** - * @internal - * TODO: 3.0 remove the trait - */ -trait ToggleableOperationAttributeTrait -{ - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface|null - */ - private $resourceMetadataFactory; - - private function isOperationAttributeDisabled(array $attributes, string $attribute, bool $default = false, bool $resourceFallback = true): bool - { - if (null === $this->resourceMetadataFactory) { - return !($attributes[$attribute] ?? !$default); - } - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - return !$default; - } - - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - - return !((bool) $resourceMetadata->getOperationAttribute($attributes, $attribute, !$default, $resourceFallback)); - } -} diff --git a/src/Core/Metadata/schema/metadata.xsd b/src/Core/Metadata/schema/metadata.xsd deleted file mode 100644 index 2515d2440fc..00000000000 --- a/src/Core/Metadata/schema/metadata.xsd +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Core/OpenApi/Factory/OpenApiFactory.php b/src/Core/OpenApi/Factory/OpenApiFactory.php deleted file mode 100644 index 6ebdacb6111..00000000000 --- a/src/Core/OpenApi/Factory/OpenApiFactory.php +++ /dev/null @@ -1,538 +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); - -namespace ApiPlatform\Core\OpenApi\Factory; - -use ApiPlatform\Core\Api\FilterLocatorTrait; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\JsonSchema\Schema; -use ApiPlatform\JsonSchema\SchemaFactoryInterface; -use ApiPlatform\JsonSchema\TypeFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; -use ApiPlatform\OpenApi\Model; -use ApiPlatform\OpenApi\Model\ExternalDocumentation; -use ApiPlatform\OpenApi\Model\PathItem; -use ApiPlatform\OpenApi\OpenApi; -use ApiPlatform\OpenApi\Options; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use ApiPlatform\State\Pagination\PaginationOptions; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; - -/** - * Generates an Open API v3 specification. - */ -final class OpenApiFactory implements OpenApiFactoryInterface -{ - use FilterLocatorTrait; - - public const BASE_URL = 'base_url'; - public const OPENAPI_DEFINITION_NAME = 'openapi_definition_name'; - - private $resourceNameCollectionFactory; - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $operationPathResolver; - private $subresourceOperationFactory; - private $formats; - private $jsonSchemaFactory; - private $jsonSchemaTypeFactory; - private $openApiOptions; - private $paginationOptions; - private $identifiersExtractor; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, SchemaFactoryInterface $jsonSchemaFactory, TypeFactoryInterface $jsonSchemaTypeFactory, OperationPathResolverInterface $operationPathResolver, ContainerInterface $filterLocator, SubresourceOperationFactoryInterface $subresourceOperationFactory, IdentifiersExtractorInterface $identifiersExtractor = null, array $formats = [], Options $openApiOptions = null, PaginationOptions $paginationOptions = null) - { - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->jsonSchemaFactory = $jsonSchemaFactory; - $this->jsonSchemaTypeFactory = $jsonSchemaTypeFactory; - $this->formats = $formats; - $this->setFilterLocator($filterLocator, true); - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->operationPathResolver = $operationPathResolver; - $this->subresourceOperationFactory = $subresourceOperationFactory; - $this->identifiersExtractor = $identifiersExtractor; - $this->openApiOptions = $openApiOptions ?: new Options('API Platform'); - $this->paginationOptions = $paginationOptions ?: new PaginationOptions(); - } - - /** - * {@inheritdoc} - */ - public function __invoke(array $context = []): OpenApi - { - $baseUrl = $context[self::BASE_URL] ?? '/'; - $contact = null === $this->openApiOptions->getContactUrl() || null === $this->openApiOptions->getContactEmail() ? null : new Model\Contact($this->openApiOptions->getContactName(), $this->openApiOptions->getContactUrl(), $this->openApiOptions->getContactEmail()); - $license = null === $this->openApiOptions->getLicenseName() ? null : new Model\License($this->openApiOptions->getLicenseName(), $this->openApiOptions->getLicenseUrl()); - $info = new Model\Info($this->openApiOptions->getTitle(), $this->openApiOptions->getVersion(), trim($this->openApiOptions->getDescription()), $this->openApiOptions->getTermsOfService(), $contact, $license); - $servers = '/' === $baseUrl || '' === $baseUrl ? [new Model\Server('/')] : [new Model\Server($baseUrl)]; - $paths = new Model\Paths(); - $links = []; - $schemas = new \ArrayObject(); - - foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - // Items needs to be parsed first to be able to reference the lines from the collection operation - $this->collectPaths($resourceMetadata, $resourceClass, OperationType::ITEM, $context, $paths, $links, $schemas); - $this->collectPaths($resourceMetadata, $resourceClass, OperationType::COLLECTION, $context, $paths, $links, $schemas); - - $this->collectPaths($resourceMetadata, $resourceClass, OperationType::SUBRESOURCE, $context, $paths, $links, $schemas); - } - - $securitySchemes = $this->getSecuritySchemes(); - $securityRequirements = []; - - foreach (array_keys($securitySchemes) as $key) { - $securityRequirements[] = [$key => []]; - } - - return new OpenApi( - $info, - $servers, - $paths, - new Model\Components( - $schemas, - new \ArrayObject(), - new \ArrayObject(), - new \ArrayObject(), - new \ArrayObject(), - new \ArrayObject(), - new \ArrayObject($securitySchemes) - ), - $securityRequirements - ); - } - - private function collectPaths(ResourceMetadata $resourceMetadata, string $resourceClass, string $operationType, array $context, Model\Paths $paths, array &$links, \ArrayObject $schemas): void - { - $resourceShortName = $resourceMetadata->getShortName(); - $operations = OperationType::COLLECTION === $operationType ? $resourceMetadata->getCollectionOperations() : (OperationType::ITEM === $operationType ? $resourceMetadata->getItemOperations() : $this->subresourceOperationFactory->create($resourceClass)); - if (!$operations) { - return; - } - - $rootResourceClass = $resourceClass; - foreach ($operations as $operationName => $operation) { - if (OperationType::COLLECTION === $operationType && !$resourceMetadata->getItemOperations()) { - $identifiers = []; - } else { - $identifiers = (array) ($operation['identifiers'] ?? $resourceMetadata->getAttribute('identifiers', null === $this->identifiersExtractor ? ['id'] : $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass))); - } - if (\count($identifiers) > 1 ? $resourceMetadata->getAttribute('composite_identifier', true) : false) { - $identifiers = ['id']; - } - - $resourceClass = $operation['resource_class'] ?? $rootResourceClass; - $path = $this->getPath($resourceShortName, $operationName, $operation, $operationType); - $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); - - if (!\in_array($method, PathItem::$methods, true)) { - continue; - } - - [$requestMimeTypes, $responseMimeTypes] = $this->getMimeTypes($resourceClass, $operationName, $operationType, $resourceMetadata); - $operationId = $operation['openapi_context']['operationId'] ?? lcfirst($operationName).ucfirst($resourceShortName).ucfirst($operationType); - $linkedOperationId = 'get'.ucfirst($resourceShortName).ucfirst(OperationType::ITEM); - $pathItem = $paths->getPath($path) ?: new Model\PathItem(); - $forceSchemaCollection = OperationType::SUBRESOURCE === $operationType ? ($operation['collection'] ?? false) : false; - - $schema = new Schema('openapi'); - $schema->setDefinitions($schemas); - - $operationOutputSchemas = []; - foreach ($responseMimeTypes as $operationFormat) { - $operationOutputSchema = $this->jsonSchemaFactory->buildSchema($resourceClass, $operationFormat, Schema::TYPE_OUTPUT, $operationType, $operationName, $schema, null, $forceSchemaCollection); - $operationOutputSchemas[$operationFormat] = $operationOutputSchema; - $this->appendSchemaDefinitions($schemas, $operationOutputSchema->getDefinitions()); - } - - $parameters = []; - $responses = []; - - if ($operation['openapi_context']['parameters'] ?? false) { - foreach ($operation['openapi_context']['parameters'] as $parameter) { - $parameters[] = new Model\Parameter($parameter['name'], $parameter['in'], $parameter['description'] ?? '', $parameter['required'] ?? false, $parameter['deprecated'] ?? false, $parameter['allowEmptyValue'] ?? false, $parameter['schema'] ?? [], $parameter['style'] ?? null, $parameter['explode'] ?? false, $parameter['allowReserved '] ?? false, $parameter['example'] ?? null, isset($parameter['examples']) ? new \ArrayObject($parameter['examples']) : null, isset($parameter['content']) ? new \ArrayObject($parameter['content']) : null); - } - } - - // Set up parameters - if (OperationType::ITEM === $operationType) { - foreach ($identifiers as $parameterName => $identifier) { - $parameterName = \is_string($parameterName) ? $parameterName : $identifier; - $parameter = new Model\Parameter($parameterName, 'path', 'Resource identifier', true, false, false, ['type' => 'string']); - if ($this->hasParameter($parameter, $parameters)) { - continue; - } - - $parameters[] = $parameter; - } - $links[$operationId] = $this->getLink($resourceClass, $operationId, $path); - } elseif (OperationType::COLLECTION === $operationType && 'GET' === $method) { - foreach (array_merge($this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($resourceMetadata, $operationName, $resourceClass)) as $parameter) { - if ($this->hasParameter($parameter, $parameters)) { - continue; - } - - $parameters[] = $parameter; - } - } elseif (OperationType::SUBRESOURCE === $operationType) { - foreach ($operation['identifiers'] as $parameterName => [$class, $property]) { - $parameter = new Model\Parameter($parameterName, 'path', $this->resourceMetadataFactory->create($class)->getShortName().' identifier', true, false, false, ['type' => 'string']); - if ($this->hasParameter($parameter, $parameters)) { - continue; - } - - $parameters[] = $parameter; - } - - if ($operation['collection']) { - $subresourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - foreach (array_merge($this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($subresourceMetadata, $operationName, $resourceClass)) as $parameter) { - if ($this->hasParameter($parameter, $parameters)) { - continue; - } - - $parameters[] = $parameter; - } - } - } - - // Create responses - switch ($method) { - case 'GET': - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); - $responseContent = $this->buildContent($responseMimeTypes, $operationOutputSchemas); - $responses[$successStatus] = new Model\Response(sprintf('%s %s', $resourceShortName, OperationType::COLLECTION === $operationType ? 'collection' : 'resource'), $responseContent); - break; - case 'POST': - $responseLinks = new \ArrayObject(isset($links[$linkedOperationId]) ? [ucfirst($linkedOperationId) => $links[$linkedOperationId]] : []); - $responseContent = $this->buildContent($responseMimeTypes, $operationOutputSchemas); - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '201'); - $responses[$successStatus] = new Model\Response(sprintf('%s resource created', $resourceShortName), $responseContent, null, $responseLinks); - $responses['400'] = new Model\Response('Invalid input'); - $responses['422'] = new Model\Response('Unprocessable entity'); - break; - case 'PATCH': - case 'PUT': - $responseLinks = new \ArrayObject(isset($links[$linkedOperationId]) ? [ucfirst($linkedOperationId) => $links[$linkedOperationId]] : []); - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); - $responseContent = $this->buildContent($responseMimeTypes, $operationOutputSchemas); - $responses[$successStatus] = new Model\Response(sprintf('%s resource updated', $resourceShortName), $responseContent, null, $responseLinks); - $responses['400'] = new Model\Response('Invalid input'); - $responses['422'] = new Model\Response('Unprocessable entity'); - break; - case 'DELETE': - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '204'); - $responses[$successStatus] = new Model\Response(sprintf('%s resource deleted', $resourceShortName)); - break; - } - - if (OperationType::ITEM === $operationType) { - $responses['404'] = new Model\Response('Resource not found'); - } - - if (!$responses) { - $responses['default'] = new Model\Response('Unexpected error'); - } - - if ($contextResponses = $operation['openapi_context']['responses'] ?? false) { - foreach ($contextResponses as $statusCode => $contextResponse) { - $responses[$statusCode] = new Model\Response($contextResponse['description'] ?? '', isset($contextResponse['content']) ? new \ArrayObject($contextResponse['content']) : null, isset($contextResponse['headers']) ? new \ArrayObject($contextResponse['headers']) : null, isset($contextResponse['links']) ? new \ArrayObject($contextResponse['links']) : null); - } - } - - $requestBody = null; - if ($contextRequestBody = $operation['openapi_context']['requestBody'] ?? false) { - $requestBody = new Model\RequestBody($contextRequestBody['description'] ?? '', new \ArrayObject($contextRequestBody['content']), $contextRequestBody['required'] ?? false); - } elseif ('PUT' === $method || 'POST' === $method || 'PATCH' === $method) { - $operationInputSchemas = []; - foreach ($requestMimeTypes as $operationFormat) { - $operationInputSchema = $this->jsonSchemaFactory->buildSchema($resourceClass, $operationFormat, Schema::TYPE_INPUT, $operationType, $operationName, $schema, null, $forceSchemaCollection); - $operationInputSchemas[$operationFormat] = $operationInputSchema; - $this->appendSchemaDefinitions($schemas, $operationInputSchema->getDefinitions()); - } - - $requestBody = new Model\RequestBody(sprintf('The %s %s resource', 'POST' === $method ? 'new' : 'updated', $resourceShortName), $this->buildContent($requestMimeTypes, $operationInputSchemas), true); - } - - $pathItem = $pathItem->{'with'.ucfirst($method)}(new Model\Operation( - $operationId, - $operation['openapi_context']['tags'] ?? (OperationType::SUBRESOURCE === $operationType ? $operation['shortNames'] : [$resourceShortName]), - $responses, - $operation['openapi_context']['summary'] ?? $this->getPathDescription($resourceShortName, $method, $operationType), - $operation['openapi_context']['description'] ?? $this->getPathDescription($resourceShortName, $method, $operationType), - isset($operation['openapi_context']['externalDocs']) ? new ExternalDocumentation($operation['openapi_context']['externalDocs']['description'] ?? null, $operation['openapi_context']['externalDocs']['url']) : null, - $parameters, - $requestBody, - isset($operation['openapi_context']['callbacks']) ? new \ArrayObject($operation['openapi_context']['callbacks']) : null, - $operation['openapi_context']['deprecated'] ?? (bool) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', false, true), - $operation['openapi_context']['security'] ?? null, - $operation['openapi_context']['servers'] ?? null, - array_filter($operation['openapi_context'] ?? [], static function ($item) { - return preg_match('/^x-.*$/i', $item); - }, \ARRAY_FILTER_USE_KEY) - )); - - $paths->addPath($path, $pathItem); - } - } - - private function buildContent(array $responseMimeTypes, array $operationSchemas): \ArrayObject - { - $content = new \ArrayObject(); - - foreach ($responseMimeTypes as $mimeType => $format) { - $content[$mimeType] = new Model\MediaType(new \ArrayObject($operationSchemas[$format]->getArrayCopy(false))); - } - - return $content; - } - - private function getMimeTypes(string $resourceClass, string $operationName, string $operationType, ResourceMetadata $resourceMetadata = null): array - { - $requestFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'input_formats', $this->formats, true); - $responseFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output_formats', $this->formats, true); - - $requestMimeTypes = $this->flattenMimeTypes($requestFormats); - $responseMimeTypes = $this->flattenMimeTypes($responseFormats); - - return [$requestMimeTypes, $responseMimeTypes]; - } - - private function flattenMimeTypes(array $responseFormats): array - { - $responseMimeTypes = []; - foreach ($responseFormats as $responseFormat => $mimeTypes) { - foreach ($mimeTypes as $mimeType) { - $responseMimeTypes[$mimeType] = $responseFormat; - } - } - - return $responseMimeTypes; - } - - /** - * Gets the path for an operation. - * - * If the path ends with the optional _format parameter, it is removed - * as optional path parameters are not yet supported. - * - * @see https://github.com/OAI/OpenAPI-Specification/issues/93 - */ - private function getPath(string $resourceShortName, string $operationName, array $operation, string $operationType): string - { - $path = $this->operationPathResolver->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - if ('.{_format}' === substr($path, -10)) { - $path = substr($path, 0, -10); - } - - return 0 === strpos($path, '/') ? $path : '/'.$path; - } - - private function getPathDescription(string $resourceShortName, string $method, string $operationType): string - { - switch ($method) { - case 'GET': - $pathSummary = OperationType::COLLECTION === $operationType ? 'Retrieves the collection of %s resources.' : 'Retrieves a %s resource.'; - break; - case 'POST': - $pathSummary = 'Creates a %s resource.'; - break; - case 'PATCH': - $pathSummary = 'Updates the %s resource.'; - break; - case 'PUT': - $pathSummary = 'Replaces the %s resource.'; - break; - case 'DELETE': - $pathSummary = 'Removes the %s resource.'; - break; - default: - return $resourceShortName; - } - - return sprintf($pathSummary, $resourceShortName); - } - - /** - * @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#linkObject. - */ - private function getLink(string $resourceClass, string $operationId, string $path): Model\Link - { - $parameters = []; - - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - if (!$propertyMetadata->isIdentifier()) { - continue; - } - - $parameters[$propertyName] = sprintf('$response.body#/%s', $propertyName); - } - - return new Model\Link( - $operationId, - new \ArrayObject($parameters), - null, - 1 === \count($parameters) ? sprintf('The `%1$s` value returned in the response can be used as the `%1$s` parameter in `GET %2$s`.', key($parameters), $path) : sprintf('The values returned in the response can be used in `GET %s`.', $path) - ); - } - - /** - * Gets parameters corresponding to enabled filters. - */ - private function getFiltersParameters(ResourceMetadata $resourceMetadata, string $operationName, string $resourceClass): array - { - $parameters = []; - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); - foreach ($resourceFilters as $filterId) { - if (!$filter = $this->getFilter($filterId)) { - continue; - } - - foreach ($filter->getDescription($resourceClass) as $name => $data) { - $schema = $data['schema'] ?? (\in_array($data['type'], Type::$builtinTypes, true) ? $this->jsonSchemaTypeFactory->getType(new Type($data['type'], false, null, $data['is_collection'] ?? false)) : ['type' => 'string']); - - $parameters[] = new Model\Parameter( - $name, - 'query', - $data['description'] ?? '', - $data['required'] ?? false, - $data['openapi']['deprecated'] ?? false, - $data['openapi']['allowEmptyValue'] ?? true, - $schema, - 'array' === $schema['type'] && \in_array($data['type'], - [Type::BUILTIN_TYPE_ARRAY, Type::BUILTIN_TYPE_OBJECT], true) ? 'deepObject' : 'form', - $data['openapi']['explode'] ?? ('array' === $schema['type']), - $data['openapi']['allowReserved'] ?? false, - $data['openapi']['example'] ?? null, - isset($data['openapi']['examples'] - ) ? new \ArrayObject($data['openapi']['examples']) : null); - } - } - - return $parameters; - } - - private function getPaginationParameters(ResourceMetadata $resourceMetadata, string $operationName): array - { - if (!$this->paginationOptions->isPaginationEnabled()) { - return []; - } - - $parameters = []; - - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_enabled', true, true)) { - $parameters[] = new Model\Parameter($this->paginationOptions->getPaginationPageParameterName(), 'query', 'The collection page number', false, false, true, ['type' => 'integer', 'default' => 1]); - - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $this->paginationOptions->getClientItemsPerPage(), true)) { - $schema = [ - 'type' => 'integer', - 'default' => $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', 30, true), - 'minimum' => 0, - ]; - - if (null !== $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_maximum_items_per_page', null, true)) { - $schema['maximum'] = $maxItemsPerPage; - } - - $parameters[] = new Model\Parameter($this->paginationOptions->getItemsPerPageParameterName(), 'query', 'The number of items per page', false, false, true, $schema); - } - } - - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_enabled', $this->paginationOptions->getPaginationClientEnabled(), true)) { - $parameters[] = new Model\Parameter($this->paginationOptions->getPaginationClientEnabledParameterName(), 'query', 'Enable or disable pagination', false, false, true, ['type' => 'boolean']); - } - - return $parameters; - } - - private function getOauthSecurityScheme(): Model\SecurityScheme - { - $oauthFlow = new Model\OAuthFlow($this->openApiOptions->getOAuthAuthorizationUrl(), $this->openApiOptions->getOAuthTokenUrl(), $this->openApiOptions->getOAuthRefreshUrl(), new \ArrayObject($this->openApiOptions->getOAuthScopes())); - $description = sprintf( - 'OAuth 2.0 %s Grant', - strtolower(preg_replace('/[A-Z]/', ' \\0', lcfirst($this->openApiOptions->getOAuthFlow()))) - ); - $implicit = $password = $clientCredentials = $authorizationCode = null; - - switch ($this->openApiOptions->getOAuthFlow()) { - case 'implicit': - $implicit = $oauthFlow; - break; - case 'password': - $password = $oauthFlow; - break; - case 'application': - case 'clientCredentials': - $clientCredentials = $oauthFlow; - break; - case 'accessCode': - case 'authorizationCode': - $authorizationCode = $oauthFlow; - break; - default: - throw new \LogicException('OAuth flow must be one of: implicit, password, clientCredentials, authorizationCode'); - } - - return new Model\SecurityScheme($this->openApiOptions->getOAuthType(), $description, null, null, null, null, new Model\OAuthFlows($implicit, $password, $clientCredentials, $authorizationCode), null); - } - - private function getSecuritySchemes(): array - { - $securitySchemes = []; - - if ($this->openApiOptions->getOAuthEnabled()) { - $securitySchemes['oauth'] = $this->getOauthSecurityScheme(); - } - - foreach ($this->openApiOptions->getApiKeys() as $key => $apiKey) { - $description = sprintf('Value for the %s %s parameter.', $apiKey['name'], $apiKey['type']); - $securitySchemes[$key] = new Model\SecurityScheme('apiKey', $description, $apiKey['name'], $apiKey['type']); - } - - return $securitySchemes; - } - - private function appendSchemaDefinitions(\ArrayObject $schemas, \ArrayObject $definitions): void - { - foreach ($definitions as $key => $value) { - $schemas[$key] = $value; - } - } - - /** - * @param Model\Parameter[] $parameters - */ - private function hasParameter(Model\Parameter $parameter, array $parameters): bool - { - foreach ($parameters as $existingParameter) { - if ($existingParameter->getName() === $parameter->getName() && $existingParameter->getIn() === $parameter->getIn()) { - return true; - } - } - - return false; - } -} diff --git a/src/Core/OpenApi/Model/Components.php b/src/Core/OpenApi/Model/Components.php deleted file mode 100644 index 0d67b0427f7..00000000000 --- a/src/Core/OpenApi/Model/Components.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Components::class); - -if (false) { - final class Components extends \ApiPlatform\OpenApi\Model\Components - { - } -} diff --git a/src/Core/OpenApi/Model/Contact.php b/src/Core/OpenApi/Model/Contact.php deleted file mode 100644 index 9d581ea108f..00000000000 --- a/src/Core/OpenApi/Model/Contact.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Contact::class); - -if (false) { - final class Contact extends \ApiPlatform\OpenApi\Model\Contact - { - } -} diff --git a/src/Core/OpenApi/Model/Encoding.php b/src/Core/OpenApi/Model/Encoding.php deleted file mode 100644 index bd8e3bcd106..00000000000 --- a/src/Core/OpenApi/Model/Encoding.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Encoding::class); - -if (false) { - final class Encoding extends \ApiPlatform\OpenApi\Model\Encoding - { - } -} diff --git a/src/Core/OpenApi/Model/ExtensionTrait.php b/src/Core/OpenApi/Model/ExtensionTrait.php deleted file mode 100644 index 1c14b40fc2e..00000000000 --- a/src/Core/OpenApi/Model/ExtensionTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\ExtensionTrait::class); - -if (false) { - trait ExtensionTrait - { - use \ApiPlatform\OpenApi\Model\ExtensionTrait; - } -} diff --git a/src/Core/OpenApi/Model/ExternalDocumentation.php b/src/Core/OpenApi/Model/ExternalDocumentation.php deleted file mode 100644 index e5b093f74e1..00000000000 --- a/src/Core/OpenApi/Model/ExternalDocumentation.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\ExternalDocumentation::class); - -if (false) { - final class ExternalDocumentation extends \ApiPlatform\OpenApi\Model\ExternalDocumentation - { - } -} diff --git a/src/Core/OpenApi/Model/Info.php b/src/Core/OpenApi/Model/Info.php deleted file mode 100644 index 5a1bcad4f44..00000000000 --- a/src/Core/OpenApi/Model/Info.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Info::class); - -if (false) { - final class Info extends \ApiPlatform\OpenApi\Model\Info - { - } -} diff --git a/src/Core/OpenApi/Model/License.php b/src/Core/OpenApi/Model/License.php deleted file mode 100644 index 294f1e3ba1e..00000000000 --- a/src/Core/OpenApi/Model/License.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\License::class); - -if (false) { - final class License extends \ApiPlatform\OpenApi\Model\License - { - } -} diff --git a/src/Core/OpenApi/Model/Link.php b/src/Core/OpenApi/Model/Link.php deleted file mode 100644 index 74eeb0cd700..00000000000 --- a/src/Core/OpenApi/Model/Link.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Link::class); - -if (false) { - final class Link extends \ApiPlatform\OpenApi\Model\Link - { - } -} diff --git a/src/Core/OpenApi/Model/MediaType.php b/src/Core/OpenApi/Model/MediaType.php deleted file mode 100644 index 0e097e418f3..00000000000 --- a/src/Core/OpenApi/Model/MediaType.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\MediaType::class); - -if (false) { - final class MediaType extends \ApiPlatform\OpenApi\Model\MediaType - { - } -} diff --git a/src/Core/OpenApi/Model/OAuthFlow.php b/src/Core/OpenApi/Model/OAuthFlow.php deleted file mode 100644 index e87a3070be6..00000000000 --- a/src/Core/OpenApi/Model/OAuthFlow.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\OAuthFlow::class); - -if (false) { - final class OAuthFlow extends \ApiPlatform\OpenApi\Model\OAuthFlow - { - } -} diff --git a/src/Core/OpenApi/Model/OAuthFlows.php b/src/Core/OpenApi/Model/OAuthFlows.php deleted file mode 100644 index 6ad827f3b47..00000000000 --- a/src/Core/OpenApi/Model/OAuthFlows.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\OAuthFlows::class); - -if (false) { - final class OAuthFlows extends \ApiPlatform\OpenApi\Model\OAuthFlows - { - } -} diff --git a/src/Core/OpenApi/Model/Operation.php b/src/Core/OpenApi/Model/Operation.php deleted file mode 100644 index 438d1babbcf..00000000000 --- a/src/Core/OpenApi/Model/Operation.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Operation::class); - -if (false) { - final class Operation extends \ApiPlatform\OpenApi\Model\Operation - { - } -} diff --git a/src/Core/OpenApi/Model/Parameter.php b/src/Core/OpenApi/Model/Parameter.php deleted file mode 100644 index 15cf20105ea..00000000000 --- a/src/Core/OpenApi/Model/Parameter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Parameter::class); - -if (false) { - final class Parameter extends \ApiPlatform\OpenApi\Model\Parameter - { - } -} diff --git a/src/Core/OpenApi/Model/PathItem.php b/src/Core/OpenApi/Model/PathItem.php deleted file mode 100644 index 620b550d86e..00000000000 --- a/src/Core/OpenApi/Model/PathItem.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\PathItem::class); - -if (false) { - final class PathItem extends \ApiPlatform\OpenApi\Model\PathItem - { - } -} diff --git a/src/Core/OpenApi/Model/Paths.php b/src/Core/OpenApi/Model/Paths.php deleted file mode 100644 index 71b34eb4cd5..00000000000 --- a/src/Core/OpenApi/Model/Paths.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Paths::class); - -if (false) { - final class Paths extends \ApiPlatform\OpenApi\Model\Paths - { - } -} diff --git a/src/Core/OpenApi/Model/RequestBody.php b/src/Core/OpenApi/Model/RequestBody.php deleted file mode 100644 index bddb2198353..00000000000 --- a/src/Core/OpenApi/Model/RequestBody.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\RequestBody::class); - -if (false) { - final class RequestBody extends \ApiPlatform\OpenApi\Model\RequestBody - { - } -} diff --git a/src/Core/OpenApi/Model/Response.php b/src/Core/OpenApi/Model/Response.php deleted file mode 100644 index eea31238412..00000000000 --- a/src/Core/OpenApi/Model/Response.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Response::class); - -if (false) { - final class Response extends \ApiPlatform\OpenApi\Model\Response - { - } -} diff --git a/src/Core/OpenApi/Model/Schema.php b/src/Core/OpenApi/Model/Schema.php deleted file mode 100644 index 73a32a49a0c..00000000000 --- a/src/Core/OpenApi/Model/Schema.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Schema::class); - -if (false) { - final class Schema extends \ApiPlatform\OpenApi\Model\Schema - { - } -} diff --git a/src/Core/OpenApi/Model/SecurityScheme.php b/src/Core/OpenApi/Model/SecurityScheme.php deleted file mode 100644 index 8faffa45d28..00000000000 --- a/src/Core/OpenApi/Model/SecurityScheme.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\SecurityScheme::class); - -if (false) { - final class SecurityScheme extends \ApiPlatform\OpenApi\Model\SecurityScheme - { - } -} diff --git a/src/Core/OpenApi/Model/Server.php b/src/Core/OpenApi/Model/Server.php deleted file mode 100644 index a63c045560e..00000000000 --- a/src/Core/OpenApi/Model/Server.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Server::class); - -if (false) { - final class Server extends \ApiPlatform\OpenApi\Model\Server - { - } -} diff --git a/src/Core/OpenApi/OpenApi.php b/src/Core/OpenApi/OpenApi.php deleted file mode 100644 index 0bd7f40b086..00000000000 --- a/src/Core/OpenApi/OpenApi.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi; - -class_exists(\ApiPlatform\OpenApi\OpenApi::class); - -if (false) { - final class OpenApi extends \ApiPlatform\OpenApi\OpenApi - { - } -} diff --git a/src/Core/OpenApi/Options.php b/src/Core/OpenApi/Options.php deleted file mode 100644 index c82e2176249..00000000000 --- a/src/Core/OpenApi/Options.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi; - -class_exists(\ApiPlatform\OpenApi\Options::class); - -if (false) { - final class Options extends \ApiPlatform\OpenApi\Options - { - } -} diff --git a/src/Core/OpenApi/Serializer/OpenApiNormalizer.php b/src/Core/OpenApi/Serializer/OpenApiNormalizer.php deleted file mode 100644 index 22f696d0643..00000000000 --- a/src/Core/OpenApi/Serializer/OpenApiNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\OpenApi\Serializer; - -class_exists(\ApiPlatform\OpenApi\Serializer\OpenApiNormalizer::class); - -if (false) { - final class OpenApiNormalizer extends \ApiPlatform\OpenApi\Serializer\OpenApiNormalizer - { - } -} diff --git a/src/Core/Operation/DashPathSegmentNameGenerator.php b/src/Core/Operation/DashPathSegmentNameGenerator.php deleted file mode 100644 index f7bfa15455d..00000000000 --- a/src/Core/Operation/DashPathSegmentNameGenerator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Operation; - -class_exists(\ApiPlatform\Operation\DashPathSegmentNameGenerator::class); - -if (false) { - final class DashPathSegmentNameGenerator extends \ApiPlatform\Operation\DashPathSegmentNameGenerator - { - } -} diff --git a/src/Core/Operation/Factory/CachedSubresourceOperationFactory.php b/src/Core/Operation/Factory/CachedSubresourceOperationFactory.php deleted file mode 100644 index fa5ced37a34..00000000000 --- a/src/Core/Operation/Factory/CachedSubresourceOperationFactory.php +++ /dev/null @@ -1,47 +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); - -namespace ApiPlatform\Core\Operation\Factory; - -use ApiPlatform\Util\CachedTrait; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @internal - */ -final class CachedSubresourceOperationFactory implements SubresourceOperationFactoryInterface -{ - use CachedTrait; - - public const CACHE_KEY_PREFIX = 'subresource_operations_'; - - private $decorated; - - public function __construct(CacheItemPoolInterface $cacheItemPool, SubresourceOperationFactoryInterface $decorated) - { - $this->cacheItemPool = $cacheItemPool; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): array - { - $cacheKey = self::CACHE_KEY_PREFIX.md5($resourceClass); - - return $this->getCached($cacheKey, function () use ($resourceClass) { - return $this->decorated->create($resourceClass); - }); - } -} diff --git a/src/Core/Operation/Factory/SubresourceOperationFactory.php b/src/Core/Operation/Factory/SubresourceOperationFactory.php deleted file mode 100644 index 2b442ff4806..00000000000 --- a/src/Core/Operation/Factory/SubresourceOperationFactory.php +++ /dev/null @@ -1,214 +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); - -namespace ApiPlatform\Core\Operation\Factory; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Operation\PathSegmentNameGeneratorInterface; - -/** - * @internal - */ -final class SubresourceOperationFactory implements SubresourceOperationFactoryInterface -{ - public const SUBRESOURCE_SUFFIX = '_subresource'; - public const FORMAT_SUFFIX = '.{_format}'; - public const ROUTE_OPTIONS = ['defaults' => [], 'requirements' => [], 'options' => [], 'host' => '', 'schemes' => [], 'condition' => '', 'controller' => null, 'stateless' => null]; - - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $pathSegmentNameGenerator; - private $identifiersExtractor; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, PathSegmentNameGeneratorInterface $pathSegmentNameGenerator, IdentifiersExtractorInterface $identifiersExtractor = null) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->pathSegmentNameGenerator = $pathSegmentNameGenerator; - $this->identifiersExtractor = $identifiersExtractor; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): array - { - $tree = []; - - try { - $this->computeSubresourceOperations($resourceClass, $tree); - } catch (ResourceClassNotFoundException $e) { - return []; - } - - return $tree; - } - - /** - * Handles subresource operations recursively and declare their corresponding routes. - * - * @param string $rootResourceClass null on the first iteration, it then keeps track of the origin resource class - * @param array $parentOperation the previous call operation - * @param int $depth the number of visited - * @param int $maxDepth - */ - private function computeSubresourceOperations(string $resourceClass, array &$tree, string $rootResourceClass = null, array $parentOperation = null, array $visited = [], int $depth = 0, int $maxDepth = null): void - { - if (null === $rootResourceClass) { - $rootResourceClass = $resourceClass; - } - - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $property) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $property, ['deprecate' => false]); - - if (!$subresource = $propertyMetadata->getSubresource()) { - continue; - } - - trigger_deprecation('api-platform/core', '2.7', sprintf('A subresource is declared on "%s::%s". Subresources are deprecated, use another #[ApiResource] instead.', $resourceClass, $property)); - $subresourceClass = $subresource->getResourceClass(); - $subresourceMetadata = $this->resourceMetadataFactory->create($subresourceClass); - $subresourceMetadata = $subresourceMetadata->withAttributes(($subresourceMetadata->getAttributes() ?: []) + ['identifiers' => !$this->identifiersExtractor ? [$property] : $this->identifiersExtractor->getIdentifiersFromResourceClass($subresourceClass)]); - $isLastItem = ($parentOperation['resource_class'] ?? null) === $resourceClass && $propertyMetadata->isIdentifier(); - - // A subresource that is also an identifier can't be a start point - if ($isLastItem && (null === $parentOperation || false === $parentOperation['collection'])) { - continue; - } - - $visiting = "$resourceClass $property $subresourceClass"; - - // Handle maxDepth - if (null !== $maxDepth && $depth >= $maxDepth) { - break; - } - if (isset($visited[$visiting])) { - continue; - } - - $rootResourceMetadata = $this->resourceMetadataFactory->create($rootResourceClass); - $rootResourceMetadata = $rootResourceMetadata->withAttributes(($rootResourceMetadata->getAttributes() ?: []) + ['identifiers' => !$this->identifiersExtractor ? ['id'] : $this->identifiersExtractor->getIdentifiersFromResourceClass($rootResourceClass)]); - $operationName = 'get'; - $operation = [ - 'property' => $property, - 'collection' => $subresource->isCollection(), - 'resource_class' => $subresourceClass, - 'shortNames' => [$subresourceMetadata->getShortName()], - 'legacy_filters' => $subresourceMetadata->getAttribute('filters', []), - 'legacy_normalization_context' => $subresourceMetadata->getAttribute('normalization_context', []), - 'legacy_type' => $subresourceMetadata->getIri(), - ]; - - if (null === $parentOperation) { - $identifiers = (array) $rootResourceMetadata->getAttribute('identifiers'); - $rootShortname = $rootResourceMetadata->getShortName(); - $identifier = \is_string($key = array_key_first($identifiers)) ? $key : $identifiers[0]; - $operation['identifiers'][$identifier] = [$rootResourceClass, $identifiers[$identifier][1] ?? $identifier, true]; - $operation['operation_name'] = sprintf( - '%s_%s%s', - RouteNameGenerator::inflector($operation['property'], $operation['collection']), - $operationName, - self::SUBRESOURCE_SUFFIX - ); - - $subresourceOperation = $rootResourceMetadata->getSubresourceOperations()[$operation['operation_name']] ?? []; - - $operation['route_name'] = sprintf( - '%s%s_%s', - RouteNameGenerator::ROUTE_NAME_PREFIX, - RouteNameGenerator::inflector($rootShortname), - $operation['operation_name'] - ); - - $prefix = trim(trim($rootResourceMetadata->getAttribute('route_prefix', '')), '/'); - if ('' !== $prefix) { - $prefix .= '/'; - } - - $operation['path'] = $subresourceOperation['path'] ?? sprintf( - '/%s%s/{%s}/%s%s', - $prefix, - $this->pathSegmentNameGenerator->getSegmentName($rootShortname), - $identifier, - $this->pathSegmentNameGenerator->getSegmentName($operation['property'], $operation['collection']), - self::FORMAT_SUFFIX - ); - - if (!\in_array($rootShortname, $operation['shortNames'], true)) { - $operation['shortNames'][] = $rootShortname; - } - } else { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $identifiers = (array) $resourceMetadata->getAttribute('identifiers', null === $this->identifiersExtractor ? ['id'] : $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)); - $identifier = \is_string($key = array_key_first($identifiers)) ? $key : $identifiers[0]; - $operation['identifiers'] = $parentOperation['identifiers']; - - if (!isset($operation['identifiers'][$parentOperation['property']])) { - $operation['identifiers'][$parentOperation['property']] = [$resourceClass, $identifiers[$identifier][1] ?? $identifier, $isLastItem ? true : $parentOperation['collection']]; - } - - $operation['operation_name'] = str_replace( - 'get'.self::SUBRESOURCE_SUFFIX, - RouteNameGenerator::inflector($isLastItem ? 'item' : $property, $operation['collection']).'_get'.self::SUBRESOURCE_SUFFIX, - $parentOperation['operation_name'] - ); - $operation['route_name'] = str_replace($parentOperation['operation_name'], $operation['operation_name'], $parentOperation['route_name']); - - if (!\in_array($resourceMetadata->getShortName(), $operation['shortNames'], true)) { - $operation['shortNames'][] = $resourceMetadata->getShortName(); - } - - $subresourceOperation = $rootResourceMetadata->getSubresourceOperations()[$operation['operation_name']] ?? []; - - if (isset($subresourceOperation['path'])) { - $operation['path'] = $subresourceOperation['path']; - } else { - $operation['path'] = str_replace(self::FORMAT_SUFFIX, '', (string) $parentOperation['path']); - - if ($parentOperation['collection']) { - $operation['path'] .= sprintf('/{%s}', array_key_last($operation['identifiers'])); - } - - if ($isLastItem) { - $operation['path'] .= self::FORMAT_SUFFIX; - } else { - $operation['path'] .= sprintf('/%s%s', $this->pathSegmentNameGenerator->getSegmentName($property, $operation['collection']), self::FORMAT_SUFFIX); - } - } - } - - if (isset($subresourceOperation['openapi_context'])) { - $operation['openapi_context'] = $subresourceOperation['openapi_context']; - } - - foreach (self::ROUTE_OPTIONS as $routeOption => $defaultValue) { - $operation[$routeOption] = $subresourceOperation[$routeOption] ?? $defaultValue; - } - - $tree[$operation['route_name']] = $operation; - - // Get the minimum maxDepth between the rootMaxDepth and the maxDepth of the to be visited Subresource - $currentMaxDepth = array_filter([$maxDepth, $subresource->getMaxDepth()], 'is_int'); - $currentMaxDepth = empty($currentMaxDepth) ? null : min($currentMaxDepth); - - $this->computeSubresourceOperations($subresourceClass, $tree, $rootResourceClass, $operation, $visited + [$visiting => true], $depth + 1, $currentMaxDepth); - } - } -} diff --git a/src/Core/Operation/Factory/SubresourceOperationFactoryInterface.php b/src/Core/Operation/Factory/SubresourceOperationFactoryInterface.php deleted file mode 100644 index 030c81a07a7..00000000000 --- a/src/Core/Operation/Factory/SubresourceOperationFactoryInterface.php +++ /dev/null @@ -1,27 +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); - -namespace ApiPlatform\Core\Operation\Factory; - -/** - * Computes subresource operation for a given resource. - * - * @author Antoine Bluchet - */ -interface SubresourceOperationFactoryInterface -{ - /** - * Creates subresource operations. - */ - public function create(string $resourceClass): array; -} diff --git a/src/Core/Operation/UnderscorePathSegmentNameGenerator.php b/src/Core/Operation/UnderscorePathSegmentNameGenerator.php deleted file mode 100644 index 854d0b08074..00000000000 --- a/src/Core/Operation/UnderscorePathSegmentNameGenerator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Operation; - -class_exists(\ApiPlatform\Operation\UnderscorePathSegmentNameGenerator::class); - -if (false) { - final class UnderscorePathSegmentNameGenerator extends \ApiPlatform\Operation\UnderscorePathSegmentNameGenerator - { - } -} diff --git a/src/Core/PathResolver/CustomOperationPathResolver.php b/src/Core/PathResolver/CustomOperationPathResolver.php deleted file mode 100644 index 6aa963d40fe..00000000000 --- a/src/Core/PathResolver/CustomOperationPathResolver.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\PathResolver; - -class_exists(\ApiPlatform\PathResolver\CustomOperationPathResolver::class); - -if (false) { - final class CustomOperationPathResolver extends \ApiPlatform\PathResolver\CustomOperationPathResolver - { - } -} diff --git a/src/Core/PathResolver/DashOperationPathResolver.php b/src/Core/PathResolver/DashOperationPathResolver.php deleted file mode 100644 index 25810ebea45..00000000000 --- a/src/Core/PathResolver/DashOperationPathResolver.php +++ /dev/null @@ -1,46 +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); - -namespace ApiPlatform\Core\PathResolver; - -use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator; -use ApiPlatform\PathResolver\OperationPathResolverInterface; - -/** - * Generates a path with words separated by underscores. - * - * @author Paul Le Corre - * - * @deprecated since version 2.1, to be removed in 3.0. Use {@see \ApiPlatform\Core\Operation\DashPathSegmentNameGenerator} instead. - */ -final class DashOperationPathResolver implements OperationPathResolverInterface -{ - public function __construct() - { - @trigger_error(sprintf('The use of %s is deprecated since 2.1. Please use %s instead.', __CLASS__, DashPathSegmentNameGenerator::class), \E_USER_DEPRECATED); - } - - /** - * {@inheritdoc} - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() >= 4) { - $operationName = func_get_arg(3); - } else { - $operationName = null; - } - - return (new OperationPathResolver(new DashPathSegmentNameGenerator()))->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - } -} diff --git a/src/Core/PathResolver/OperationPathResolver.php b/src/Core/PathResolver/OperationPathResolver.php deleted file mode 100644 index 7ff7f7c7da7..00000000000 --- a/src/Core/PathResolver/OperationPathResolver.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\PathResolver; - -class_exists(\ApiPlatform\PathResolver\OperationPathResolver::class); - -if (false) { - final class OperationPathResolver extends \ApiPlatform\PathResolver\OperationPathResolver - { - } -} diff --git a/src/Core/PathResolver/UnderscoreOperationPathResolver.php b/src/Core/PathResolver/UnderscoreOperationPathResolver.php deleted file mode 100644 index 99615c74adc..00000000000 --- a/src/Core/PathResolver/UnderscoreOperationPathResolver.php +++ /dev/null @@ -1,46 +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); - -namespace ApiPlatform\Core\PathResolver; - -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\PathResolver\OperationPathResolverInterface; - -/** - * Generates a path with words separated by underscores. - * - * @author Paul Le Corre - * - * @deprecated since version 2.1, to be removed in 3.0. Use {@see \ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator} instead. - */ -final class UnderscoreOperationPathResolver implements OperationPathResolverInterface -{ - public function __construct() - { - @trigger_error(sprintf('The use of %s is deprecated since 2.1. Please use %s instead.', __CLASS__, UnderscorePathSegmentNameGenerator::class), \E_USER_DEPRECATED); - } - - /** - * {@inheritdoc} - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() >= 4) { - $operationName = func_get_arg(3); - } else { - $operationName = null; - } - - return (new OperationPathResolver(new UnderscorePathSegmentNameGenerator()))->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - } -} diff --git a/src/Core/Problem/Serializer/ConstraintViolationListNormalizer.php b/src/Core/Problem/Serializer/ConstraintViolationListNormalizer.php deleted file mode 100644 index 9b8ff0b88c5..00000000000 --- a/src/Core/Problem/Serializer/ConstraintViolationListNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Problem\Serializer; - -class_exists(\ApiPlatform\Problem\Serializer\ConstraintViolationListNormalizer::class); - -if (false) { - final class ConstraintViolationListNormalizer extends \ApiPlatform\Problem\Serializer\ConstraintViolationListNormalizer - { - } -} diff --git a/src/Core/Problem/Serializer/ErrorNormalizer.php b/src/Core/Problem/Serializer/ErrorNormalizer.php deleted file mode 100644 index fcd78ee5356..00000000000 --- a/src/Core/Problem/Serializer/ErrorNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Problem\Serializer; - -class_exists(\ApiPlatform\Problem\Serializer\ErrorNormalizer::class); - -if (false) { - final class ErrorNormalizer extends \ApiPlatform\Problem\Serializer\ErrorNormalizer - { - } -} diff --git a/src/Core/Problem/Serializer/ErrorNormalizerTrait.php b/src/Core/Problem/Serializer/ErrorNormalizerTrait.php deleted file mode 100644 index 767688c159f..00000000000 --- a/src/Core/Problem/Serializer/ErrorNormalizerTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Problem\Serializer; - -class_exists(\ApiPlatform\Problem\Serializer\ErrorNormalizerTrait::class); - -if (false) { - trait ErrorNormalizerTrait - { - use \ApiPlatform\Problem\Serializer\ErrorNormalizerTrait; - } -} diff --git a/src/Core/Security/Core/Authorization/ExpressionLanguageProvider.php b/src/Core/Security/Core/Authorization/ExpressionLanguageProvider.php deleted file mode 100644 index 51e66c90598..00000000000 --- a/src/Core/Security/Core/Authorization/ExpressionLanguageProvider.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Security\Core\Authorization; - -class_exists(\ApiPlatform\Symfony\Security\Core\Authorization\ExpressionLanguageProvider::class); - -if (false) { - final class ExpressionLanguageProvider extends \ApiPlatform\Symfony\Security\Core\Authorization\ExpressionLanguageProvider - { - } -} diff --git a/src/Core/Security/EventListener/DenyAccessListener.php b/src/Core/Security/EventListener/DenyAccessListener.php deleted file mode 100644 index db2a9e059bf..00000000000 --- a/src/Core/Security/EventListener/DenyAccessListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Security\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\DenyAccessListener::class); - -if (false) { - final class DenyAccessListener extends \ApiPlatform\Symfony\EventListener\DenyAccessListener - { - } -} diff --git a/src/Core/Security/ExpressionLanguage.php b/src/Core/Security/ExpressionLanguage.php deleted file mode 100644 index 2fb29d73851..00000000000 --- a/src/Core/Security/ExpressionLanguage.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Security; - -class_exists(\ApiPlatform\Symfony\Security\ExpressionLanguage::class); - -if (false) { - class ExpressionLanguage extends \ApiPlatform\Symfony\Security\ExpressionLanguage - { - } -} diff --git a/src/Core/Security/ResourceAccessChecker.php b/src/Core/Security/ResourceAccessChecker.php deleted file mode 100644 index c9990d2ae6e..00000000000 --- a/src/Core/Security/ResourceAccessChecker.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Security; - -class_exists(\ApiPlatform\Symfony\Security\ResourceAccessChecker::class); - -if (false) { - final class ResourceAccessChecker extends \ApiPlatform\Symfony\Security\ResourceAccessChecker - { - } -} diff --git a/src/Core/Serializer/AbstractCollectionNormalizer.php b/src/Core/Serializer/AbstractCollectionNormalizer.php deleted file mode 100644 index a4c82b907a9..00000000000 --- a/src/Core/Serializer/AbstractCollectionNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\AbstractCollectionNormalizer::class); - -if (false) { - class AbstractCollectionNormalizer extends \ApiPlatform\Serializer\AbstractCollectionNormalizer - { - } -} diff --git a/src/Core/Serializer/AbstractConstraintViolationListNormalizer.php b/src/Core/Serializer/AbstractConstraintViolationListNormalizer.php deleted file mode 100644 index 106dc418511..00000000000 --- a/src/Core/Serializer/AbstractConstraintViolationListNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\AbstractConstraintViolationListNormalizer::class); - -if (false) { - class AbstractConstraintViolationListNormalizer extends \ApiPlatform\Serializer\AbstractConstraintViolationListNormalizer - { - } -} diff --git a/src/Core/Serializer/AbstractItemNormalizer.php b/src/Core/Serializer/AbstractItemNormalizer.php deleted file mode 100644 index fcec2177f32..00000000000 --- a/src/Core/Serializer/AbstractItemNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\AbstractItemNormalizer::class); - -if (false) { - class AbstractItemNormalizer extends \ApiPlatform\Serializer\AbstractItemNormalizer - { - } -} diff --git a/src/Core/Serializer/CacheKeyTrait.php b/src/Core/Serializer/CacheKeyTrait.php deleted file mode 100644 index e047229da1d..00000000000 --- a/src/Core/Serializer/CacheKeyTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\CacheKeyTrait::class); - -if (false) { - trait CacheKeyTrait - { - use \ApiPlatform\Serializer\CacheKeyTrait; - } -} diff --git a/src/Core/Serializer/ContextTrait.php b/src/Core/Serializer/ContextTrait.php deleted file mode 100644 index e173d5ae011..00000000000 --- a/src/Core/Serializer/ContextTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\ContextTrait::class); - -if (false) { - trait ContextTrait - { - use \ApiPlatform\Serializer\ContextTrait; - } -} diff --git a/src/Core/Serializer/Filter/GroupFilter.php b/src/Core/Serializer/Filter/GroupFilter.php deleted file mode 100644 index 25abf1d0fd9..00000000000 --- a/src/Core/Serializer/Filter/GroupFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer\Filter; - -class_exists(\ApiPlatform\Serializer\Filter\GroupFilter::class); - -if (false) { - final class GroupFilter extends \ApiPlatform\Serializer\Filter\GroupFilter - { - } -} diff --git a/src/Core/Serializer/Filter/PropertyFilter.php b/src/Core/Serializer/Filter/PropertyFilter.php deleted file mode 100644 index 7e0cc0c46e2..00000000000 --- a/src/Core/Serializer/Filter/PropertyFilter.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer\Filter; - -class_exists(\ApiPlatform\Serializer\Filter\PropertyFilter::class); - -if (false) { - final class PropertyFilter extends \ApiPlatform\Serializer\Filter\PropertyFilter - { - } -} diff --git a/src/Core/Serializer/InputOutputMetadataTrait.php b/src/Core/Serializer/InputOutputMetadataTrait.php deleted file mode 100644 index 0073cc00912..00000000000 --- a/src/Core/Serializer/InputOutputMetadataTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\InputOutputMetadataTrait::class); - -if (false) { - trait InputOutputMetadataTrait - { - use \ApiPlatform\Serializer\InputOutputMetadataTrait; - } -} diff --git a/src/Core/Serializer/ItemNormalizer.php b/src/Core/Serializer/ItemNormalizer.php deleted file mode 100644 index b9ff47a2f9e..00000000000 --- a/src/Core/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\ItemNormalizer::class); - -if (false) { - class ItemNormalizer extends \ApiPlatform\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/Serializer/JsonEncoder.php b/src/Core/Serializer/JsonEncoder.php deleted file mode 100644 index 3bc790a7429..00000000000 --- a/src/Core/Serializer/JsonEncoder.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\JsonEncoder::class); - -if (false) { - final class JsonEncoder extends \ApiPlatform\Serializer\JsonEncoder - { - } -} diff --git a/src/Core/Serializer/Mapping/Factory/ClassMetadataFactory.php b/src/Core/Serializer/Mapping/Factory/ClassMetadataFactory.php deleted file mode 100644 index 88245f55bfd..00000000000 --- a/src/Core/Serializer/Mapping/Factory/ClassMetadataFactory.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer\Mapping\Factory; - -class_exists(\ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory::class); - -if (false) { - final class ClassMetadataFactory extends \ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory - { - } -} diff --git a/src/Core/Serializer/ResourceList.php b/src/Core/Serializer/ResourceList.php deleted file mode 100644 index 3c992b93f7c..00000000000 --- a/src/Core/Serializer/ResourceList.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\ResourceList::class); - -if (false) { - class ResourceList extends \ApiPlatform\Serializer\ResourceList - { - } -} diff --git a/src/Core/Serializer/SerializerContextBuilder.php b/src/Core/Serializer/SerializerContextBuilder.php deleted file mode 100644 index aaf4f86cc48..00000000000 --- a/src/Core/Serializer/SerializerContextBuilder.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\SerializerContextBuilder::class); - -if (false) { - final class SerializerContextBuilder extends \ApiPlatform\Serializer\SerializerContextBuilder - { - } -} diff --git a/src/Core/Serializer/SerializerFilterContextBuilder.php b/src/Core/Serializer/SerializerFilterContextBuilder.php deleted file mode 100644 index 538503c8baf..00000000000 --- a/src/Core/Serializer/SerializerFilterContextBuilder.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Serializer; - -class_exists(\ApiPlatform\Serializer\SerializerFilterContextBuilder::class); - -if (false) { - final class SerializerFilterContextBuilder extends \ApiPlatform\Serializer\SerializerFilterContextBuilder - { - } -} diff --git a/src/Core/Swagger/Serializer/ApiGatewayNormalizer.php b/src/Core/Swagger/Serializer/ApiGatewayNormalizer.php deleted file mode 100644 index 9d359d15391..00000000000 --- a/src/Core/Swagger/Serializer/ApiGatewayNormalizer.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Swagger\Serializer; - -class_exists(\ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer::class); - -if (false) { - final class ApiGatewayNormalizer extends \ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer - { - } -} diff --git a/src/Core/Swagger/Serializer/DocumentationNormalizer.php b/src/Core/Swagger/Serializer/DocumentationNormalizer.php deleted file mode 100644 index 5f9bf9b9455..00000000000 --- a/src/Core/Swagger/Serializer/DocumentationNormalizer.php +++ /dev/null @@ -1,941 +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); - -namespace ApiPlatform\Core\Swagger\Serializer; - -use ApiPlatform\Api\FilterLocatorTrait; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ApiResourceToLegacyResourceMetadataTrait; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\JsonSchema\Schema; -use ApiPlatform\JsonSchema\SchemaFactory; -use ApiPlatform\JsonSchema\SchemaFactoryInterface; -use ApiPlatform\JsonSchema\TypeFactory; -use ApiPlatform\JsonSchema\TypeFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\OpenApi\OpenApi; -use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Generates an OpenAPI specification (formerly known as Swagger). OpenAPI v2 and v3 are supported. - * - * @author Amrouche Hamza - * @author Teoh Han Hui - * @author Kévin Dunglas - * @author Anthony GRASSIOT - */ -final class DocumentationNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface -{ - use ApiResourceToLegacyResourceMetadataTrait; - use FilterLocatorTrait; - - public const FORMAT = 'json'; - public const BASE_URL = 'base_url'; - public const SPEC_VERSION = 'spec_version'; - public const OPENAPI_VERSION = '3.0.2'; - public const SWAGGER_DEFINITION_NAME = 'swagger_definition_name'; - public const SWAGGER_VERSION = '2.0'; - - /** - * @deprecated - */ - public const ATTRIBUTE_NAME = 'swagger_context'; - - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $operationMethodResolver; - private $operationPathResolver; - private $oauthEnabled; - private $oauthType; - private $oauthFlow; - private $oauthTokenUrl; - private $oauthAuthorizationUrl; - private $oauthScopes; - private $apiKeys; - private $subresourceOperationFactory; - private $paginationEnabled; - private $paginationPageParameterName; - private $clientItemsPerPage; - private $itemsPerPageParameterName; - private $paginationClientEnabled; - private $paginationClientEnabledParameterName; - private $formats; - private $formatsProvider; - - /** - * @var SchemaFactoryInterface - */ - private $jsonSchemaFactory; - /** - * @var TypeFactoryInterface - */ - private $jsonSchemaTypeFactory; - private $defaultContext = [ - self::BASE_URL => '/', - ApiGatewayNormalizer::API_GATEWAY => false, - ]; - - private $identifiersExtractor; - - private $openApiNormalizer; - private $legacyMode; - - /** - * @param SchemaFactoryInterface|ResourceClassResolverInterface|null $jsonSchemaFactory - * @param ContainerInterface|FilterCollection|null $filterLocator - * @param array|OperationAwareFormatsProviderInterface $formats - * @param mixed|null $jsonSchemaTypeFactory - * @param int[] $swaggerVersions - * @param mixed $resourceMetadataFactory - */ - public function __construct($resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, $jsonSchemaFactory = null, $jsonSchemaTypeFactory = null, OperationPathResolverInterface $operationPathResolver = null, UrlGeneratorInterface $urlGenerator = null, $filterLocator = null, NameConverterInterface $nameConverter = null, bool $oauthEnabled = false, string $oauthType = '', string $oauthFlow = '', string $oauthTokenUrl = '', string $oauthAuthorizationUrl = '', array $oauthScopes = [], array $apiKeys = [], SubresourceOperationFactoryInterface $subresourceOperationFactory = null, bool $paginationEnabled = true, string $paginationPageParameterName = 'page', bool $clientItemsPerPage = false, string $itemsPerPageParameterName = 'itemsPerPage', $formats = [], bool $paginationClientEnabled = false, string $paginationClientEnabledParameterName = 'pagination', array $defaultContext = [], array $swaggerVersions = [2, 3], IdentifiersExtractorInterface $identifiersExtractor = null, NormalizerInterface $openApiNormalizer = null, bool $legacyMode = false) - { - if ($jsonSchemaTypeFactory instanceof OperationMethodResolverInterface) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0.', OperationMethodResolverInterface::class, __METHOD__), \E_USER_DEPRECATED); - - $this->operationMethodResolver = $jsonSchemaTypeFactory; - $this->jsonSchemaTypeFactory = new TypeFactory(); - } else { - $this->jsonSchemaTypeFactory = $jsonSchemaTypeFactory ?? new TypeFactory(); - } - - if ($jsonSchemaFactory instanceof ResourceClassResolverInterface) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0.', ResourceClassResolverInterface::class, __METHOD__), \E_USER_DEPRECATED); - } - - if (null === $jsonSchemaFactory || $jsonSchemaFactory instanceof ResourceClassResolverInterface) { - $jsonSchemaFactory = new SchemaFactory($this->jsonSchemaTypeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $nameConverter); - $this->jsonSchemaTypeFactory->setSchemaFactory($jsonSchemaFactory); - } - $this->jsonSchemaFactory = $jsonSchemaFactory; - - if ($nameConverter) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0.', NameConverterInterface::class, __METHOD__), \E_USER_DEPRECATED); - } - - if ($urlGenerator) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.1 and will be removed in 3.0.', UrlGeneratorInterface::class, __METHOD__), \E_USER_DEPRECATED); - } - - if ($formats instanceof FormatsProviderInterface) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0, pass an array instead.', FormatsProviderInterface::class, __METHOD__), \E_USER_DEPRECATED); - - $this->formatsProvider = $formats; - } else { - $this->formats = $formats; - } - - $this->setFilterLocator($filterLocator, true); - - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->operationPathResolver = $operationPathResolver; - $this->oauthEnabled = $oauthEnabled; - $this->oauthType = $oauthType; - $this->oauthFlow = $oauthFlow; - $this->oauthTokenUrl = $oauthTokenUrl; - $this->oauthAuthorizationUrl = $oauthAuthorizationUrl; - $this->oauthScopes = $oauthScopes; - $this->subresourceOperationFactory = $subresourceOperationFactory; - $this->paginationEnabled = $paginationEnabled; - $this->paginationPageParameterName = $paginationPageParameterName; - $this->apiKeys = $apiKeys; - $this->clientItemsPerPage = $clientItemsPerPage; - $this->itemsPerPageParameterName = $itemsPerPageParameterName; - $this->paginationClientEnabled = $paginationClientEnabled; - $this->paginationClientEnabledParameterName = $paginationClientEnabledParameterName; - $this->defaultContext[self::SPEC_VERSION] = $swaggerVersions[0] ?? 2; - $this->defaultContext = array_merge($this->defaultContext, $defaultContext); - $this->identifiersExtractor = $identifiersExtractor; - $this->openApiNormalizer = $openApiNormalizer; - $this->legacyMode = $legacyMode; - } - - /** - * {@inheritdoc} - * - * @return array|string|int|float|bool|\ArrayObject|null - */ - public function normalize($object, $format = null, array $context = []) - { - if ($object instanceof OpenApi) { - @trigger_error('Using the swagger DocumentationNormalizer is deprecated in favor of decorating the OpenApiFactory, use the "openapi.backward_compatibility_layer" configuration to change this behavior.', \E_USER_DEPRECATED); - - return $this->openApiNormalizer->normalize($object, $format, $context); - } - - $v3 = 3 === ($context['spec_version'] ?? $this->defaultContext['spec_version']) && !($context['api_gateway'] ?? $this->defaultContext['api_gateway']); - - $definitions = new \ArrayObject(); - $paths = new \ArrayObject(); - $links = new \ArrayObject(); - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - foreach ($object->getResourceNameCollection() as $resourceClass) { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); - foreach ($resourceMetadataCollection as $i => $resourceMetadata) { - $resourceMetadata = $this->transformResourceToResourceMetadata($resourceMetadata); - // Items needs to be parsed first to be able to reference the lines from the collection operation - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceMetadata->getShortName(), $resourceMetadata, OperationType::ITEM, $links); - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceMetadata->getShortName(), $resourceMetadata, OperationType::COLLECTION, $links); - } - } - - $definitions->ksort(); - $paths->ksort(); - - return $this->computeDoc($v3, $object, $definitions, $paths, $context); - } - - foreach ($object->getResourceNameCollection() as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($this->identifiersExtractor) { - $identifiers = []; - if ($resourceMetadata->getItemOperations()) { - $identifiers = $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass); - } - - $resourceMetadata = $resourceMetadata->withAttributes(($resourceMetadata->getAttributes() ?: []) + ['identifiers' => $identifiers]); - } - $resourceShortName = $resourceMetadata->getShortName(); - - // Items needs to be parsed first to be able to reference the lines from the collection operation - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceShortName, $resourceMetadata, OperationType::ITEM, $links); - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceShortName, $resourceMetadata, OperationType::COLLECTION, $links); - - if (null === $this->subresourceOperationFactory) { - continue; - } - - foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $subresourceOperation) { - $method = $resourceMetadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, $subresourceOperation['operation_name'], 'method', 'GET'); - $paths[$this->getPath($subresourceOperation['shortNames'][0], $subresourceOperation['route_name'], $subresourceOperation, OperationType::SUBRESOURCE)][strtolower($method)] = $this->addSubresourceOperation($v3, $subresourceOperation, $definitions, $operationId, $resourceMetadata); - } - } - - $definitions->ksort(); - $paths->ksort(); - - return $this->computeDoc($v3, $object, $definitions, $paths, $context); - } - - /** - * Updates the list of entries in the paths collection. - */ - private function addPaths(bool $v3, \ArrayObject $paths, \ArrayObject $definitions, string $resourceClass, string $resourceShortName, ResourceMetadata $resourceMetadata, string $operationType, \ArrayObject $links) - { - if (null === $operations = OperationType::COLLECTION === $operationType ? $resourceMetadata->getCollectionOperations() : $resourceMetadata->getItemOperations()) { - return; - } - - foreach ($operations as $operationName => $operation) { - if (isset($operation['uri_template'])) { - $path = str_replace('.{_format}', '', $operation['uri_template']); - if (0 !== strpos($path, '/')) { - $path = '/'.$path; - } - } else { - $path = $this->getPath($resourceShortName, $operationName, $operation, $operationType); - } - - if ($this->operationMethodResolver) { - $method = OperationType::ITEM === $operationType ? $this->operationMethodResolver->getItemOperationMethod($resourceClass, $operationName) : $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName); - } else { - $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); - } - - $paths[$path][strtolower($method)] = $this->getPathOperation($v3, $operationName, $operation, $method, $operationType, $resourceClass, $resourceMetadata, $definitions, $links); - } - } - - /** - * Gets the path for an operation. - * - * If the path ends with the optional _format parameter, it is removed - * as optional path parameters are not yet supported. - * - * @see https://github.com/OAI/OpenAPI-Specification/issues/93 - */ - private function getPath(string $resourceShortName, string $operationName, array $operation, string $operationType): string - { - $path = $this->operationPathResolver->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - - if ('.{_format}' === substr($path, -10)) { - $path = substr($path, 0, -10); - } - - return $path; - } - - /** - * Gets a path Operation Object. - * - * @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#operation-object - */ - private function getPathOperation(bool $v3, string $operationName, array $operation, string $method, string $operationType, string $resourceClass, ResourceMetadata $resourceMetadata, \ArrayObject $definitions, \ArrayObject $links): \ArrayObject - { - $pathOperation = new \ArrayObject($operation[$v3 ? 'openapi_context' : 'swagger_context'] ?? []); - $resourceShortName = $resourceMetadata->getShortName(); - $pathOperation['tags'] ?? $pathOperation['tags'] = [$resourceShortName]; - $pathOperation['operationId'] ?? $pathOperation['operationId'] = lcfirst($operationName).ucfirst($resourceShortName).ucfirst($operationType); - if ($v3 && 'GET' === $method && OperationType::ITEM === $operationType && $link = $this->getLinkObject($resourceClass, $pathOperation['operationId'], $this->getPath($resourceShortName, $operationName, $operation, $operationType))) { - $links[$pathOperation['operationId']] = $link; - } - if ($resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', null, true)) { - $pathOperation['deprecated'] = true; - } - - if (null === $this->formatsProvider) { - $requestFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'input_formats', [], true); - $responseFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output_formats', [], true); - } else { - $requestFormats = $responseFormats = $this->formatsProvider->getFormatsFromOperation($resourceClass, $operationName, $operationType); - } - - $requestMimeTypes = $this->flattenMimeTypes($requestFormats); - $responseMimeTypes = $this->flattenMimeTypes($responseFormats); - switch ($method) { - case 'GET': - return $this->updateGetOperation($v3, $pathOperation, $responseMimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); - case 'POST': - return $this->updatePostOperation($v3, $pathOperation, $requestMimeTypes, $responseMimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions, $links); - case 'PATCH': - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Updates the %s resource.', $resourceShortName); - // no break - case 'PUT': - return $this->updatePutOperation($v3, $pathOperation, $requestMimeTypes, $responseMimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); - case 'DELETE': - return $this->updateDeleteOperation($v3, $pathOperation, $resourceShortName, $operationType, $operationName, $resourceMetadata, $resourceClass); - } - - return $pathOperation; - } - - /** - * @return array the update message as first value, and if the schema is defined as second - */ - private function addSchemas(bool $v3, array $message, \ArrayObject $definitions, string $resourceClass, string $operationType, string $operationName, array $mimeTypes, string $type = Schema::TYPE_OUTPUT, bool $forceCollection = false): array - { - if (!$v3) { - $jsonSchema = $this->getJsonSchema($v3, $definitions, $resourceClass, $type, $operationType, $operationName, 'json', null, $forceCollection); - if (!$jsonSchema->isDefined()) { - return [$message, false]; - } - - $message['schema'] = $jsonSchema->getArrayCopy(false); - - return [$message, true]; - } - - foreach ($mimeTypes as $mimeType => $format) { - $jsonSchema = $this->getJsonSchema($v3, $definitions, $resourceClass, $type, $operationType, $operationName, $format, null, $forceCollection); - if (!$jsonSchema->isDefined()) { - return [$message, false]; - } - - $message['content'][$mimeType] = ['schema' => $jsonSchema->getArrayCopy(false)]; - } - - return [$message, true]; - } - - private function updateGetOperation(bool $v3, \ArrayObject $pathOperation, array $mimeTypes, string $operationType, ResourceMetadata $resourceMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions): \ArrayObject - { - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); - - if (!$v3) { - $pathOperation['produces'] ?? $pathOperation['produces'] = array_keys($mimeTypes); - } - - if (OperationType::COLLECTION === $operationType) { - $outputResourseShortName = $resourceMetadata->getCollectionOperations()[$operationName]['output']['name'] ?? $resourceShortName; - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Retrieves the collection of %s resources.', $outputResourseShortName); - - $successResponse = ['description' => sprintf('%s collection response', $outputResourseShortName)]; - [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $mimeTypes); - - $pathOperation['responses'] ?? $pathOperation['responses'] = [$successStatus => $successResponse]; - - if ( - ($resourceMetadata->getAttributes()['extra_properties']['is_legacy_subresource'] ?? false) || - ($resourceMetadata->getAttributes()['extra_properties']['is_alternate_resource_metadata'] ?? false)) { - // Avoid duplicates parameters when there is a filter on a subresource identifier - $parametersMemory = []; - $pathOperation['parameters'] = []; - - foreach ($resourceMetadata->getAttributes()['identifiers'] as $parameterName => [$class, $identifier]) { - $parameter = ['name' => $parameterName, 'in' => 'path', 'required' => true]; - $v3 ? $parameter['schema'] = ['type' => 'string'] : $parameter['type'] = 'string'; - $pathOperation['parameters'][] = $parameter; - $parametersMemory[] = $parameterName; - } - - if ($parameters = $this->getFiltersParameters($v3, $resourceClass, $operationName, $resourceMetadata)) { - foreach ($parameters as $parameter) { - if (!\in_array($parameter['name'], $parametersMemory, true)) { - $pathOperation['parameters'][] = $parameter; - } - } - } - } else { - $pathOperation['parameters'] ?? $pathOperation['parameters'] = $this->getFiltersParameters($v3, $resourceClass, $operationName, $resourceMetadata); - } - - $this->addPaginationParameters($v3, $resourceMetadata, OperationType::COLLECTION, $operationName, $pathOperation); - - return $pathOperation; - } - - $outputResourseShortName = $resourceMetadata->getItemOperations()[$operationName]['output']['name'] ?? $resourceShortName; - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Retrieves a %s resource.', $outputResourseShortName); - - $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata, $resourceClass); - - $successResponse = ['description' => sprintf('%s resource response', $outputResourseShortName)]; - [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $mimeTypes); - - $pathOperation['responses'] ?? $pathOperation['responses'] = [ - $successStatus => $successResponse, - '404' => ['description' => 'Resource not found'], - ]; - - return $pathOperation; - } - - private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMetadata, string $operationType, string $operationName, \ArrayObject $pathOperation) - { - if ($this->paginationEnabled && $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_enabled', true, true)) { - $paginationParameter = [ - 'name' => $this->paginationPageParameterName, - 'in' => 'query', - 'required' => false, - 'description' => 'The collection page number', - ]; - $v3 ? $paginationParameter['schema'] = [ - 'type' => 'integer', - 'default' => 1, - ] : $paginationParameter['type'] = 'integer'; - $pathOperation['parameters'][] = $paginationParameter; - - if ($resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_client_items_per_page', $this->clientItemsPerPage, true)) { - $itemPerPageParameter = [ - 'name' => $this->itemsPerPageParameterName, - 'in' => 'query', - 'required' => false, - 'description' => 'The number of items per page', - ]; - if ($v3) { - $itemPerPageParameter['schema'] = [ - 'type' => 'integer', - 'default' => $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_items_per_page', 30, true), - 'minimum' => 0, - ]; - - $maxItemsPerPage = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'maximum_items_per_page', null, true); - if (null !== $maxItemsPerPage) { - @trigger_error('The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3.', \E_USER_DEPRECATED); - } - $maxItemsPerPage = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_maximum_items_per_page', $maxItemsPerPage, true); - - if (null !== $maxItemsPerPage) { - $itemPerPageParameter['schema']['maximum'] = $maxItemsPerPage; - } - } else { - $itemPerPageParameter['type'] = 'integer'; - } - - $pathOperation['parameters'][] = $itemPerPageParameter; - } - } - - if ($this->paginationEnabled && $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_client_enabled', $this->paginationClientEnabled, true)) { - $paginationEnabledParameter = [ - 'name' => $this->paginationClientEnabledParameterName, - 'in' => 'query', - 'required' => false, - 'description' => 'Enable or disable pagination', - ]; - $v3 ? $paginationEnabledParameter['schema'] = ['type' => 'boolean'] : $paginationEnabledParameter['type'] = 'boolean'; - $pathOperation['parameters'][] = $paginationEnabledParameter; - } - } - - /** - * @throws ResourceClassNotFoundException - */ - private function addSubresourceOperation(bool $v3, array $subresourceOperation, \ArrayObject $definitions, string $operationId, ResourceMetadata $resourceMetadata): \ArrayObject - { - $operationName = 'get'; // TODO: we might want to extract that at some point to also support other subresource operations - $collection = $subresourceOperation['collection'] ?? false; - - $subResourceMetadata = $this->resourceMetadataFactory->create($subresourceOperation['resource_class']); - - $pathOperation = new \ArrayObject([]); - $pathOperation['tags'] = $subresourceOperation['shortNames']; - $pathOperation['operationId'] = $operationId; - $pathOperation['summary'] = sprintf('Retrieves %s%s resource%s.', $subresourceOperation['collection'] ? 'the collection of ' : 'a ', $subresourceOperation['shortNames'][0], $subresourceOperation['collection'] ? 's' : ''); - - if (null === $this->formatsProvider) { - // TODO: Subresource operation metadata aren't available by default, for now we have to fallback on default formats. - // TODO: A better approach would be to always populate the subresource operation array. - $subResourceMetadata = $this - ->resourceMetadataFactory - ->create($subresourceOperation['resource_class']); - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $subResourceMetadata = $this->transformResourceToResourceMetadata($subResourceMetadata[0]); - } - - $responseFormats = $subResourceMetadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, $operationName, 'output_formats', $this->formats, true); - } else { - $responseFormats = $this->formatsProvider->getFormatsFromOperation($subresourceOperation['resource_class'], $operationName, OperationType::SUBRESOURCE); - } - - $mimeTypes = $this->flattenMimeTypes($responseFormats); - - if (!$v3) { - $pathOperation['produces'] = array_keys($mimeTypes); - } - - $successResponse = [ - 'description' => sprintf('%s %s response', $subresourceOperation['shortNames'][0], $collection ? 'collection' : 'resource'), - ]; - [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $subresourceOperation['resource_class'], OperationType::SUBRESOURCE, $operationName, $mimeTypes, Schema::TYPE_OUTPUT, $collection); - - $pathOperation['responses'] = ['200' => $successResponse, '404' => ['description' => 'Resource not found']]; - - // Avoid duplicates parameters when there is a filter on a subresource identifier - $parametersMemory = []; - $pathOperation['parameters'] = []; - foreach ($subresourceOperation['identifiers'] as $parameterName => [$class, $identifier, $hasIdentifier]) { - if (false === strpos($subresourceOperation['path'], sprintf('{%s}', $parameterName))) { - continue; - } - - $parameter = ['name' => $parameterName, 'in' => 'path', 'required' => true]; - $v3 ? $parameter['schema'] = ['type' => 'string'] : $parameter['type'] = 'string'; - $pathOperation['parameters'][] = $parameter; - $parametersMemory[] = $parameterName; - } - - if ($parameters = $this->getFiltersParameters($v3, $subresourceOperation['resource_class'], $operationName, $subResourceMetadata)) { - foreach ($parameters as $parameter) { - if (!\in_array($parameter['name'], $parametersMemory, true)) { - $pathOperation['parameters'][] = $parameter; - } - } - } - - if ($subresourceOperation['collection']) { - $this->addPaginationParameters($v3, $subResourceMetadata, OperationType::SUBRESOURCE, $subresourceOperation['operation_name'], $pathOperation); - } - - return $pathOperation; - } - - private function updatePostOperation(bool $v3, \ArrayObject $pathOperation, array $requestMimeTypes, array $responseMimeTypes, string $operationType, ResourceMetadata $resourceMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions, \ArrayObject $links): \ArrayObject - { - if (!$v3) { - $pathOperation['consumes'] ?? $pathOperation['consumes'] = array_keys($requestMimeTypes); - $pathOperation['produces'] ?? $pathOperation['produces'] = array_keys($responseMimeTypes); - } - - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Creates a %s resource.', $resourceShortName); - - $identifiers = (array) $resourceMetadata - ->getTypedOperationAttribute($operationType, $operationName, 'identifiers', [], false); - - $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata, $resourceClass, OperationType::ITEM === $operationType ? false : true); - - $successResponse = ['description' => sprintf('%s resource created', $resourceShortName)]; - [$successResponse, $defined] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $responseMimeTypes); - - if ($defined && $v3 && ($links[$key = 'get'.ucfirst($resourceShortName).ucfirst(OperationType::ITEM)] ?? null)) { - $successResponse['links'] = [ucfirst($key) => $links[$key]]; - } - - $pathOperation['responses'] ?? $pathOperation['responses'] = [ - (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '201') => $successResponse, - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ]; - - return $this->addRequestBody($v3, $pathOperation, $definitions, $resourceClass, $resourceShortName, $operationType, $operationName, $requestMimeTypes); - } - - private function updatePutOperation(bool $v3, \ArrayObject $pathOperation, array $requestMimeTypes, array $responseMimeTypes, string $operationType, ResourceMetadata $resourceMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions): \ArrayObject - { - if (!$v3) { - $pathOperation['consumes'] ?? $pathOperation['consumes'] = array_keys($requestMimeTypes); - $pathOperation['produces'] ?? $pathOperation['produces'] = array_keys($responseMimeTypes); - } - - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Replaces the %s resource.', $resourceShortName); - - $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata, $resourceClass); - - $successResponse = ['description' => sprintf('%s resource updated', $resourceShortName)]; - [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $responseMimeTypes); - - $pathOperation['responses'] ?? $pathOperation['responses'] = [ - (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200') => $successResponse, - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ]; - - return $this->addRequestBody($v3, $pathOperation, $definitions, $resourceClass, $resourceShortName, $operationType, $operationName, $requestMimeTypes, true); - } - - private function addRequestBody(bool $v3, \ArrayObject $pathOperation, \ArrayObject $definitions, string $resourceClass, string $resourceShortName, string $operationType, string $operationName, array $requestMimeTypes, bool $put = false) - { - if (isset($pathOperation['requestBody'])) { - return $pathOperation; - } - - [$message, $defined] = $this->addSchemas($v3, [], $definitions, $resourceClass, $operationType, $operationName, $requestMimeTypes, Schema::TYPE_INPUT); - if (!$defined) { - return $pathOperation; - } - - $description = sprintf('The %s %s resource', $put ? 'updated' : 'new', $resourceShortName); - if ($v3) { - $pathOperation['requestBody'] = $message + ['description' => $description]; - - return $pathOperation; - } - - if (!$this->hasBodyParameter($pathOperation['parameters'] ?? [])) { - $pathOperation['parameters'][] = [ - 'name' => lcfirst($resourceShortName), - 'in' => 'body', - 'description' => $description, - ] + $message; - } - - return $pathOperation; - } - - private function hasBodyParameter(array $parameters): bool - { - foreach ($parameters as $parameter) { - if (\array_key_exists('in', $parameter) && 'body' === $parameter['in']) { - return true; - } - } - - return false; - } - - private function updateDeleteOperation(bool $v3, \ArrayObject $pathOperation, string $resourceShortName, string $operationType, string $operationName, ResourceMetadata $resourceMetadata, string $resourceClass): \ArrayObject - { - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Removes the %s resource.', $resourceShortName); - $pathOperation['responses'] ?? $pathOperation['responses'] = [ - (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '204') => ['description' => sprintf('%s resource deleted', $resourceShortName)], - '404' => ['description' => 'Resource not found'], - ]; - - return $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata, $resourceClass); - } - - private function addItemOperationParameters(bool $v3, \ArrayObject $pathOperation, string $operationType, string $operationName, ResourceMetadata $resourceMetadata, string $resourceClass, bool $isPost = false): \ArrayObject - { - $identifiers = (array) $resourceMetadata - ->getTypedOperationAttribute($operationType, $operationName, 'identifiers', [], false); - - // Auto-generated routes in API Platform < 2.7 are considered as collection, hotfix this as the OpenApi Factory supports new operations anyways. - // this also fixes a bug where we could not create POST item operations in API P 2.6 - if (OperationType::ITEM === $operationType && $isPost) { - $operationType = OperationType::COLLECTION; - } - - if (!$identifiers && OperationType::COLLECTION !== $operationType) { - try { - $identifiers = $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass); - } catch (RuntimeException $e) { - // Ignore exception here - } catch (ResourceClassNotFoundException $e) { - if (false === $this->legacyMode) { - // Skipping these, swagger is not compatible with post 2.7 resource metadata - return $pathOperation; - } - throw $e; - } - } - - if (\count($identifiers) > 1 ? $resourceMetadata->getItemOperationAttribute($operationName, 'composite_identifier', true, true) : false) { - $identifiers = ['id']; - } - - if (!$identifiers && OperationType::COLLECTION === $operationType) { - return $pathOperation; - } - - if (!isset($pathOperation['parameters'])) { - $pathOperation['parameters'] = []; - } - - foreach ($identifiers as $parameterName => $identifier) { - $parameter = [ - 'name' => \is_string($parameterName) ? $parameterName : $identifier, - 'in' => 'path', - 'required' => true, - ]; - $v3 ? $parameter['schema'] = ['type' => 'string'] : $parameter['type'] = 'string'; - $pathOperation['parameters'][] = $parameter; - } - - return $pathOperation; - } - - private function getJsonSchema(bool $v3, \ArrayObject $definitions, string $resourceClass, string $type, ?string $operationType, ?string $operationName, string $format = 'json', ?array $serializerContext = null, bool $forceCollection = false): Schema - { - $schema = new Schema($v3 ? Schema::VERSION_OPENAPI : Schema::VERSION_SWAGGER); - $schema->setDefinitions($definitions); - - return $this->jsonSchemaFactory->buildSchema($resourceClass, $format, $type, $operationType, $operationName, $schema, $serializerContext, $forceCollection); - } - - private function computeDoc(bool $v3, Documentation $documentation, \ArrayObject $definitions, \ArrayObject $paths, array $context): array - { - $baseUrl = $context[self::BASE_URL] ?? $this->defaultContext[self::BASE_URL]; - - if ($v3) { - $docs = ['openapi' => self::OPENAPI_VERSION]; - if ('/' !== $baseUrl && '' !== $baseUrl) { - $docs['servers'] = [['url' => $baseUrl]]; - } - } else { - $docs = [ - 'swagger' => self::SWAGGER_VERSION, - 'basePath' => $baseUrl, - ]; - } - - $docs += [ - 'info' => [ - 'title' => $documentation->getTitle(), - 'version' => $documentation->getVersion(), - ], - 'paths' => $paths, - ]; - - if ('' !== $description = $documentation->getDescription()) { - $docs['info']['description'] = $description; - } - - $securityDefinitions = []; - $security = []; - - if ($this->oauthEnabled) { - $oauthAttributes = [ - 'authorizationUrl' => $this->oauthAuthorizationUrl, - 'scopes' => new \ArrayObject($this->oauthScopes), - ]; - - if ($this->oauthTokenUrl) { - $oauthAttributes['tokenUrl'] = $this->oauthTokenUrl; - } - - $securityDefinitions['oauth'] = [ - 'type' => $this->oauthType, - 'description' => sprintf( - 'OAuth 2.0 %s Grant', - strtolower(preg_replace('/[A-Z]/', ' \\0', lcfirst($this->oauthFlow))) - ), - ]; - - if ($v3) { - $securityDefinitions['oauth']['flows'] = [ - $this->oauthFlow => $oauthAttributes, - ]; - } else { - $securityDefinitions['oauth']['flow'] = $this->oauthFlow; - $securityDefinitions['oauth'] = array_merge($securityDefinitions['oauth'], $oauthAttributes); - } - - $security[] = ['oauth' => []]; - } - - foreach ($this->apiKeys as $key => $apiKey) { - $name = $apiKey['name']; - $type = $apiKey['type']; - - $securityDefinitions[$key] = [ - 'type' => 'apiKey', - 'in' => $type, - 'description' => sprintf('Value for the %s %s', $name, 'query' === $type ? sprintf('%s parameter', $type) : $type), - 'name' => $name, - ]; - - $security[] = [$key => []]; - } - - if ($securityDefinitions && $security) { // @phpstan-ignore-line false positive - $docs['security'] = $security; - if (!$v3) { - $docs['securityDefinitions'] = $securityDefinitions; - } - } - - if ($v3) { - if (\count($definitions) + \count($securityDefinitions)) { - $docs['components'] = []; - if (\count($definitions)) { - $docs['components']['schemas'] = $definitions; - } - if (\count($securityDefinitions)) { - $docs['components']['securitySchemes'] = $securityDefinitions; - } - } - } elseif (\count($definitions) > 0) { - $docs['definitions'] = $definitions; - } - - return $docs; - } - - /** - * Gets parameters corresponding to enabled filters. - */ - private function getFiltersParameters(bool $v3, string $resourceClass, string $operationName, ResourceMetadata $resourceMetadata): array - { - if (null === $this->filterLocator) { - return []; - } - - $parameters = []; - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); - foreach ($resourceFilters as $filterId) { - if (!$filter = $this->getFilter($filterId)) { - continue; - } - - foreach ($filter->getDescription($resourceClass) as $name => $data) { - $parameter = [ - 'name' => $name, - 'in' => 'query', - 'required' => $data['required'], - ]; - - $type = \in_array($data['type'], Type::$builtinTypes, true) ? $this->jsonSchemaTypeFactory->getType(new Type($data['type'], false, null, $data['is_collection'] ?? false)) : ['type' => 'string']; - $v3 ? $parameter['schema'] = $type : $parameter += $type; - - if ($v3 && isset($data['schema'])) { - $parameter['schema'] = $data['schema']; - } - - if ('array' === ($type['type'] ?? '')) { - $deepObject = \in_array($data['type'], [Type::BUILTIN_TYPE_ARRAY, Type::BUILTIN_TYPE_OBJECT], true); - - if ($v3) { - $parameter['style'] = $deepObject ? 'deepObject' : 'form'; - $parameter['explode'] = true; - } else { - $parameter['collectionFormat'] = $deepObject ? 'csv' : 'multi'; - } - } - - $key = $v3 ? 'openapi' : 'swagger'; - if (isset($data[$key])) { - $parameter = $data[$key] + $parameter; - } - - $parameters[] = $parameter; - } - } - - return $parameters; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return self::FORMAT === $format && ($data instanceof Documentation || $this->openApiNormalizer && $data instanceof OpenApi); - } - - /** - * {@inheritdoc} - */ - public function hasCacheableSupportsMethod(): bool - { - return true; - } - - private function flattenMimeTypes(array $responseFormats): array - { - $responseMimeTypes = []; - foreach ($responseFormats as $responseFormat => $mimeTypes) { - foreach ($mimeTypes as $mimeType) { - $responseMimeTypes[$mimeType] = $responseFormat; - } - } - - return $responseMimeTypes; - } - - /** - * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#linkObject. - */ - private function getLinkObject(string $resourceClass, string $operationId, string $path): array - { - $linkObject = $identifiers = []; - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - if (!$propertyMetadata->isIdentifier()) { - continue; - } - - $linkObject['parameters'][$propertyName] = sprintf('$response.body#/%s', $propertyName); - $identifiers[] = $propertyName; - } - - if (!$linkObject) { - return []; - } - $linkObject['operationId'] = $operationId; - $linkObject['description'] = 1 === \count($identifiers) ? sprintf('The `%1$s` value returned in the response can be used as the `%1$s` parameter in `GET %2$s`.', $identifiers[0], $path) : sprintf('The values returned in the response can be used in `GET %s`.', $path); - - return $linkObject; - } -} diff --git a/src/Core/Test/DoctrineMongoDbOdmFilterTestCase.php b/src/Core/Test/DoctrineMongoDbOdmFilterTestCase.php deleted file mode 100644 index 2a58a772cf8..00000000000 --- a/src/Core/Test/DoctrineMongoDbOdmFilterTestCase.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Test; - -class_exists(\ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase::class); - -if (false) { - class DoctrineMongoDbOdmFilterTestCase extends \ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase - { - } -} diff --git a/src/Core/Test/DoctrineMongoDbOdmSetup.php b/src/Core/Test/DoctrineMongoDbOdmSetup.php deleted file mode 100644 index 87b4cdfd54d..00000000000 --- a/src/Core/Test/DoctrineMongoDbOdmSetup.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Test; - -class_exists(\ApiPlatform\Test\DoctrineMongoDbOdmSetup::class); - -if (false) { - class DoctrineMongoDbOdmSetup extends \ApiPlatform\Test\DoctrineMongoDbOdmSetup - { - } -} diff --git a/src/Core/Test/DoctrineMongoDbOdmTestCase.php b/src/Core/Test/DoctrineMongoDbOdmTestCase.php deleted file mode 100644 index 79cbe9fc64c..00000000000 --- a/src/Core/Test/DoctrineMongoDbOdmTestCase.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Test; - -class_exists(\ApiPlatform\Test\DoctrineMongoDbOdmTestCase::class); - -if (false) { - class DoctrineMongoDbOdmTestCase extends \ApiPlatform\Test\DoctrineMongoDbOdmTestCase - { - } -} diff --git a/src/Core/Test/DoctrineOrmFilterTestCase.php b/src/Core/Test/DoctrineOrmFilterTestCase.php deleted file mode 100644 index 487505038a8..00000000000 --- a/src/Core/Test/DoctrineOrmFilterTestCase.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Test; - -class_exists(\ApiPlatform\Test\DoctrineOrmFilterTestCase::class); - -if (false) { - class DoctrineOrmFilterTestCase extends \ApiPlatform\Test\DoctrineOrmFilterTestCase - { - } -} diff --git a/src/Core/Upgrade/ColorConsoleDiffFormatter.php b/src/Core/Upgrade/ColorConsoleDiffFormatter.php deleted file mode 100644 index c423afaf390..00000000000 --- a/src/Core/Upgrade/ColorConsoleDiffFormatter.php +++ /dev/null @@ -1,119 +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); - -namespace ApiPlatform\Core\Upgrade; - -use Symfony\Component\Console\Formatter\OutputFormatter; - -/** - * Inspired by @see https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/src/Differ/DiffConsoleFormatter.php to be - * used as standalone class, without need to require whole package by Dariusz Rumiński - * Forked by @soyuka from Symplify\PackageBuilder\Console\Formatter to remove Nette\Utils\Strings dependency to be even more standalone. - * - * @see \Symplify\PackageBuilder\Tests\Console\Formatter\ColorConsoleDiffFormatterTest - * - * @internal - */ -final class ColorConsoleDiffFormatter -{ - /** - * @var string - * - * @see https://regex101.com/r/ovLMDF/1 - */ - private const PLUS_START_REGEX = '#^(\+.*)#'; - - /** - * @var string - * - * @see https://regex101.com/r/xwywpa/1 - */ - private const MINUT_START_REGEX = '#^(\-.*)#'; - - /** - * @var string - * - * @see https://regex101.com/r/CMlwa8/1 - */ - private const AT_START_REGEX = '#^(@.*)#'; - - /** - * @var string - * - * @see https://regex101.com/r/qduj2O/1 - */ - private const NEWLINES_REGEX = "#\n\r|\n#"; - - private string $template; - - public function __construct() - { - $this->template = sprintf( - ' ---------- begin diff ----------%s%%s%s ----------- end diff -----------'.\PHP_EOL, - \PHP_EOL, - \PHP_EOL - ); - } - - public function format(string $diff): string - { - return $this->formatWithTemplate($diff, $this->template); - } - - private function formatWithTemplate(string $diff, string $template): string - { - $escapedDiff = OutputFormatter::escape(rtrim($diff)); - - $escapedDiffLines = preg_split(self::NEWLINES_REGEX, $escapedDiff); - - // remove description of added + remove; obvious on diffs - foreach ($escapedDiffLines as $key => $escapedDiffLine) { - if ('--- Original' === $escapedDiffLine) { - unset($escapedDiffLines[$key]); - } - - if ('+++ New' === $escapedDiffLine) { - unset($escapedDiffLines[$key]); - } - } - - $coloredLines = array_map(function (string $string): string { - $string = $this->makePlusLinesGreen($string); - $string = $this->makeMinusLinesRed($string); - $string = $this->makeAtNoteCyan($string); - - if (' ' === $string) { - return ''; - } - - return $string; - }, $escapedDiffLines); - - return sprintf($template, implode(\PHP_EOL, $coloredLines)); - } - - private function makePlusLinesGreen(string $string): string - { - return preg_replace(self::PLUS_START_REGEX, '$1', $string); - } - - private function makeMinusLinesRed(string $string): string - { - return preg_replace(self::MINUT_START_REGEX, '$1', $string); - } - - private function makeAtNoteCyan(string $string): string - { - return preg_replace(self::AT_START_REGEX, '$1', $string); - } -} diff --git a/src/Core/Upgrade/RemoveAnnotationTrait.php b/src/Core/Upgrade/RemoveAnnotationTrait.php deleted file mode 100644 index be49d3ce0ec..00000000000 --- a/src/Core/Upgrade/RemoveAnnotationTrait.php +++ /dev/null @@ -1,34 +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); - -namespace ApiPlatform\Core\Upgrade; - -use phpDocumentor\Reflection\DocBlock\Serializer; -use phpDocumentor\Reflection\DocBlockFactory; -use PhpParser\Comment\Doc; - -trait RemoveAnnotationTrait -{ - private function removeAnnotationByTag(Doc $comment, string $tagName): Doc - { - $factory = DocBlockFactory::createInstance(); - $docBlock = $factory->create($comment->getText()); - foreach ($docBlock->getTagsByName($tagName) as $tag) { - $docBlock->removeTag($tag); - } - - $serializer = new Serializer(0, '', true, null, null, \PHP_EOL); - - return new Doc($serializer->getDocComment($docBlock)); - } -} diff --git a/src/Core/Upgrade/SubresourceTransformer.php b/src/Core/Upgrade/SubresourceTransformer.php deleted file mode 100644 index e14dd94d9e9..00000000000 --- a/src/Core/Upgrade/SubresourceTransformer.php +++ /dev/null @@ -1,112 +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); - -namespace ApiPlatform\Core\Upgrade; - -use ApiPlatform\Util\Inflector; -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as ODMClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver as ODMAnnotationDriver; -use Doctrine\ODM\MongoDB\Mapping\MappingException as ODMMappingException; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Mapping\Driver\AnnotationDriver; -use Doctrine\ORM\Mapping\MappingException; -use Doctrine\Persistence\Mapping\RuntimeReflectionService; - -final class SubresourceTransformer -{ - private $ormMetadataFactory; - private $odmMetadataFactory; - - public function __construct() - { - $this->ormMetadataFactory = class_exists(AnnotationDriver::class) ? new AnnotationDriver(new AnnotationReader()) : null; - $this->odmMetadataFactory = class_exists(ODMAnnotationDriver::class) ? new ODMAnnotationDriver(new AnnotationReader()) : null; - } - - public function toUriVariables(array $subresourceMetadata): array - { - $uriVariables = []; - $toClass = $subresourceMetadata['resource_class']; - $fromProperty = $subresourceMetadata['property']; - - foreach (array_reverse($subresourceMetadata['identifiers']) as $identifier => $identifiedBy) { - [$fromClass, $fromIdentifier, $fromPathVariable] = $identifiedBy; - $fromClassMetadata = $this->getDoctrineMetadata($fromClass); - $fromClassMetadataAssociationMappings = $fromClassMetadata->associationMappings; - - $uriVariables[$identifier] = [ - 'from_class' => $fromClass, - 'from_property' => null, - 'to_property' => null, - 'identifiers' => $fromPathVariable ? [$fromIdentifier] : [], - 'composite_identifier' => false, - 'expanded_value' => $fromPathVariable ? null : Inflector::tableize($identifier), - ]; - - if ($toClass === $fromClass) { - $fromProperty = $identifier; - continue; - } - - $toClass = $fromClass; - - if (isset($fromProperty, $fromClassMetadataAssociationMappings[$fromProperty])) { - $type = $fromClassMetadataAssociationMappings[$fromProperty]['type']; - if (((class_exists(ODMClassMetadata::class) && ODMClassMetadata::MANY === $type) || (\is_int($type) && $type & ClassMetadataInfo::TO_MANY)) && isset($fromClassMetadataAssociationMappings[$fromProperty]['mappedBy'])) { - $uriVariables[$identifier]['to_property'] = $fromClassMetadataAssociationMappings[$fromProperty]['mappedBy']; - $fromProperty = $identifier; - continue; - } - $uriVariables[$identifier]['from_property'] = $fromProperty; - $fromProperty = $identifier; - } - } - - return array_reverse($uriVariables); - } - - /** - * @return ODMClassMetadata|ClassMetadata - */ - private function getDoctrineMetadata(string $class) - { - if ($this->odmMetadataFactory && class_exists(ODMClassMetadata::class)) { - $isDocument = true; - $metadata = new ODMClassMetadata($class); - - try { - $this->odmMetadataFactory->loadMetadataForClass($class, $metadata); - } catch (ODMMappingException $e) { - $isDocument = false; - } - - if ($isDocument) { - return $metadata; - } - } - - $metadata = new ClassMetadata($class); - $metadata->initializeReflection(new RuntimeReflectionService()); - - try { - if ($this->ormMetadataFactory) { - $this->ormMetadataFactory->loadMetadataForClass($class, $metadata); - } - } catch (MappingException $e) { - } - - return $metadata; - } -} diff --git a/src/Core/Upgrade/UpgradeApiResourceVisitor.php b/src/Core/Upgrade/UpgradeApiResourceVisitor.php deleted file mode 100644 index f88590c74b5..00000000000 --- a/src/Core/Upgrade/UpgradeApiResourceVisitor.php +++ /dev/null @@ -1,444 +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); - -namespace ApiPlatform\Core\Upgrade; - -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource as LegacyApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Delete; -use ApiPlatform\Metadata\Get; -use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\GraphQl\Mutation; -use ApiPlatform\Metadata\GraphQl\Query; -use ApiPlatform\Metadata\GraphQl\QueryCollection; -use ApiPlatform\Metadata\Link; -use ApiPlatform\Metadata\Patch; -use ApiPlatform\Metadata\Post; -use ApiPlatform\Metadata\Put; -use ApiPlatform\Metadata\Resource\DeprecationMetadataTrait; -use PhpParser\Node; -use PhpParser\NodeVisitorAbstract; - -final class UpgradeApiResourceVisitor extends NodeVisitorAbstract -{ - use DeprecationMetadataTrait; - use RemoveAnnotationTrait; - - private LegacyApiResource $resourceAnnotation; - private IdentifiersExtractorInterface $identifiersExtractor; - private bool $isAnnotation = false; - private string $resourceClass; - - public function __construct(LegacyApiResource $resourceAnnotation, bool $isAnnotation, IdentifiersExtractorInterface $identifiersExtractor, string $resourceClass) - { - $this->resourceAnnotation = $resourceAnnotation; - $this->isAnnotation = $isAnnotation; - $this->identifiersExtractor = $identifiersExtractor; - $this->resourceClass = $resourceClass; - } - - /** - * In API Platform 3.x there's no difference between items and collections other then a flag within the Operation - * Therefore we need to fix the behavior with an empty array. - */ - private function getLegacyOperations(bool $isCollection = false): array - { - $key = $isCollection ? 'collectionOperations' : 'itemOperations'; - if ([] === $this->resourceAnnotation->{$key}) { - return []; - } - - $default = $isCollection ? ['post', 'get'] : ['get', 'put', 'patch', 'delete']; - - return $this->resourceAnnotation->{$key} ?? $default; - } - - /** - * @return int|Node|null - */ - public function enterNode(Node $node) - { - // We don't go through every resources to remove ApiSubresource annotations, do this here as well if there are some - // @see UpgradeApiSubresourceVisitor - $comment = $node->getDocComment(); - if ($comment && preg_match('/@ApiSubresource/', $comment->getText())) { - $node->setDocComment($this->removeAnnotationByTag($comment, 'ApiSubresource')); - } - - if ($node instanceof Node\Stmt\Namespace_) { - $namespaces = array_unique(array_merge( - [ApiResource::class], - $this->getOperationsNamespaces($this->getLegacyOperations()), - $this->getOperationsNamespaces($this->getLegacyOperations(true), true), - $this->getGraphQlOperationsNamespaces($this->resourceAnnotation->graphql ?? []) - )); - - if (true === !($this->resourceAnnotation->attributes['composite_identifier'] ?? true)) { - $namespaces[] = Link::class; - } - - foreach ($node->stmts as $k => $stmt) { - if (!$stmt instanceof Node\Stmt\Use_) { - break; - } - - $useStatement = implode('\\', $stmt->uses[0]->name->parts); - - if (LegacyApiResource::class === $useStatement) { - unset($node->stmts[$k]); - continue; - } - - // There might be a use left as the UpgradeApiSubresourceVisitor doesn't go through all the resources - if (ApiSubresource::class === $useStatement) { - unset($node->stmts[$k]); - continue; - } - - if (false !== ($key = array_search($useStatement, $namespaces, true))) { - unset($namespaces[$key]); - } - } - - foreach ($namespaces as $namespace) { - array_unshift($node->stmts, new Node\Stmt\Use_([ - new Node\Stmt\UseUse( - new Node\Name( - $namespace - ) - ), - ])); - } - } - - if ($node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Interface_) { - if ($this->isAnnotation) { - $this->removeAnnotation($node); - } else { - $this->removeAttribute($node); - } - - $arguments = []; - $operations = null === $this->resourceAnnotation->itemOperations && null === $this->resourceAnnotation->collectionOperations ? null : array_merge( - $this->legacyOperationsToOperations($this->getLegacyOperations()), - $this->legacyOperationsToOperations($this->getLegacyOperations(true), true) - ); - - if (null !== $operations) { - $arguments['operations'] = new Node\Expr\Array_( - array_map(function ($value) { - return new Node\Expr\ArrayItem($value); - }, $operations), - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ); - } - - $graphQlOperations = null === $this->resourceAnnotation->graphql ? null : []; - foreach ($this->resourceAnnotation->graphql ?? [] as $operationName => $graphQlOperation) { - if (\is_int($operationName)) { - $ns = $this->getGraphQlOperationNamespace($graphQlOperation); - $graphQlOperations[] = new Node\Expr\New_(new Node\Name($this->getShortName($ns)), $this->arrayToArguments(['name' => $this->valueToNode($graphQlOperation)])); - continue; - } - - $ns = $this->getGraphQlOperationNamespace($operationName, $graphQlOperation); - $args = ['name' => $this->valueToNode($operationName)]; - foreach ($graphQlOperation as $key => $value) { - [$key, $value] = $this->getKeyValue($key, $value); - $args[$key] = $this->valueToNode($value); - } - - $graphQlOperations[] = new Node\Expr\New_(new Node\Name($this->getShortName($ns)), $this->arrayToArguments($args)); - } - - if (null !== $graphQlOperations) { - $arguments['graphQlOperations'] = new Node\Expr\Array_( - array_map(function ($value) { - return new Node\Expr\ArrayItem($value); - }, $graphQlOperations), - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ); - } - - foreach (['shortName', 'description', 'iri'] as $key) { - if (!($value = $this->resourceAnnotation->{$key})) { - continue; - } - - if ('iri' === $key) { - $arguments['types'] = new Node\Expr\Array_([new Node\Expr\ArrayItem( - new Node\Scalar\String_($value) - )], ['kind' => Node\Expr\Array_::KIND_SHORT]); - continue; - } - - $arguments[$key] = new Node\Scalar\String_($value); - } - - foreach ($this->resourceAnnotation->attributes ?? [] as $key => $value) { - if (null === $value) { - continue; - } - - [$key, $value] = $this->getKeyValue($key, $value); - - if ('urlGenerationStrategy' === $key) { - $urlGeneratorInterface = new \ReflectionClass(UrlGeneratorInterface::class); - $urlGeneratorConstants = array_flip($urlGeneratorInterface->getConstants()); - $currentUrlGeneratorConstant = $urlGeneratorConstants[$value]; - - $arguments[$key] = - new Node\Expr\ClassConstFetch( - new Node\Name('UrlGeneratorInterface'), - $currentUrlGeneratorConstant - ); - continue; - } - - if ('compositeIdentifier' === $key) { - if (false !== $value) { - continue; - } - - $identifiers = $this->identifiersExtractor->getIdentifiersFromResourceClass($this->resourceClass); - $identifierNodeItems = []; - foreach ($identifiers as $identifier) { - $identifierNodes = [ - 'compositeIdentifier' => new Node\Expr\ConstFetch(new Node\Name('false')), - 'fromClass' => new Node\Expr\ClassConstFetch( - new Node\Name( - 'self' - ), - 'class' - ), - 'identifiers' => new Node\Expr\Array_( - [ - new Node\Expr\ArrayItem(new Node\Scalar\String_($identifier)), - ], - ['kind' => Node\Expr\Array_::KIND_SHORT] - ), - ]; - - $identifierNodeItems[] = new Node\Expr\ArrayItem( - new Node\Expr\New_(new Node\Name('Link'), $this->arrayToArguments($identifierNodes)), - new Node\Scalar\String_($identifier) - ); - } - - $arguments['uriVariables'] = new Node\Expr\Array_($identifierNodeItems, ['kind' => Node\Expr\Array_::KIND_SHORT]); - continue; - } - - $arguments[$key] = $this->valueToNode($value); - } - - $apiResourceAttribute = - new Node\AttributeGroup([ - new Node\Attribute( - new Node\Name('ApiResource'), - $this->arrayToArguments($arguments) - ), - ]); - - array_unshift($node->attrGroups, $apiResourceAttribute); - } - } - - private function getGraphQlOperationNamespace(string $operationName, array $operation = []): string - { - switch ($operationName) { - case 'item_query': - return Query::class; - case 'collection_query': - return QueryCollection::class; - case 'update': - return Mutation::class; - case 'delete': - return Mutation::class; - case 'create': - return Mutation::class; - default: - if (isset($operation['item_query'])) { - return Query::class; - } - - if (isset($operation['collection_query'])) { - return QueryCollection::class; - } - - if (isset($operation['mutation'])) { - return Mutation::class; - } - - throw new \LogicException(sprintf('The graphql operation %s is not following API Platform naming convention.', $operationName)); - } - } - - private function getOperationNamespace(string $method, bool $isCollection = false): string - { - switch ($method) { - case 'POST': - return Post::class; - case 'PUT': - return Put::class; - case 'PATCH': - return Patch::class; - case 'DELETE': - return Delete::class; - default: - return $isCollection ? GetCollection::class : Get::class; - } - } - - private function getGraphQlOperationsNamespaces(array $operations): array - { - $namespaces = []; - foreach ($operations as $operationName => $operation) { - if (\is_string($operationName)) { - $namespaces[] = $this->getGraphQlOperationNamespace($operationName, $operation); - continue; - } - - $namespaces[] = $this->getGraphQlOperationNamespace($operation); - } - - return $namespaces; - } - - private function getOperationsNamespaces(array $operations, bool $isCollection = false): array - { - $namespaces = []; - foreach ($operations as $operationName => $operation) { - if (\is_string($operationName)) { - $namespaces[] = $this->getOperationNamespace($operation['method'] ?? strtoupper($operationName), $isCollection); - continue; - } - - $method = \is_string($operation) ? strtoupper($operation) : $operation['method']; - $namespaces[] = $this->getOperationNamespace($method, $isCollection); - } - - return $namespaces; - } - - /** - * @return Node\Arg[] - */ - private function arrayToArguments(array $arguments) - { - $args = []; - foreach ($arguments as $key => $value) { - $args[] = new Node\Arg($value, false, false, [], new Node\Identifier($key)); - } - - return $args; - } - - private function removeAttribute(Node\Stmt\Class_|Node\Stmt\Interface_ $node) - { - foreach ($node->attrGroups as $k => $attrGroupNode) { - foreach ($attrGroupNode->attrs as $i => $attribute) { - if (str_ends_with(implode('\\', $attribute->name->parts), 'ApiResource')) { - unset($node->attrGroups[$k]); - break; - } - } - } - } - - private function removeAnnotation(Node\Stmt\Class_|Node\Stmt\Interface_ $node) - { - $comment = $node->getDocComment(); - - if (preg_match('/@ApiResource/', $comment->getText())) { - $node->setDocComment($this->removeAnnotationByTag($comment, 'ApiResource')); - } - } - - private function valueToNode(mixed $value) - { - if (\is_string($value)) { - if (class_exists($value)) { - return new Node\Expr\ClassConstFetch(new Node\Name($this->getShortName($value)), 'class'); - } - - return new Node\Scalar\String_($value); - } - - if (\is_bool($value)) { - return new Node\Expr\ConstFetch(new Node\Name($value ? 'true' : 'false')); - } - - if (is_numeric($value)) { - return \is_int($value) ? new Node\Scalar\LNumber($value) : new Node\Scalar\DNumber($value); - } - - if (\is_array($value)) { - return new Node\Expr\Array_( - array_map(function ($key, $value) { - return new Node\Expr\ArrayItem( - $this->valueToNode($value), - \is_string($key) ? $this->valueToNode($key) : null, - ); - }, array_keys($value), array_values($value)), - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ); - } - } - - private function getShortName(string $class): string - { - if (false !== $pos = strrpos($class, '\\')) { - return substr($class, $pos + 1); - } - - return $class; - } - - private function createOperation(string $namespace, array $arguments = []) - { - $args = []; - foreach ($arguments as $key => $value) { - [$key, $value] = $this->getKeyValue($key, $value); - $args[$key] = $this->valueToNode($value); - } - - return new Node\Expr\New_(new Node\Name($this->getShortName($namespace)), $this->arrayToArguments($args)); - } - - private function legacyOperationsToOperations($legacyOperations, bool $isCollection = false) - { - $operations = []; - foreach ($legacyOperations as $operationName => $operation) { - if (\is_int($operationName)) { - $operations[] = $this->createOperation($this->getOperationNamespace(strtoupper($operation), $isCollection)); - continue; - } - - $method = $operation['method'] ?? strtoupper($operationName); - unset($operation['method']); - $operations[] = $this->createOperation($this->getOperationNamespace($method, $isCollection), $operation); - } - - return $operations; - } -} diff --git a/src/Core/Upgrade/UpgradeApiSubresourceVisitor.php b/src/Core/Upgrade/UpgradeApiSubresourceVisitor.php deleted file mode 100644 index 05ab16089fe..00000000000 --- a/src/Core/Upgrade/UpgradeApiSubresourceVisitor.php +++ /dev/null @@ -1,289 +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); - -namespace ApiPlatform\Core\Upgrade; - -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiSubresource; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Get; -use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Link; -use PhpParser\Node; -use PhpParser\NodeVisitorAbstract; -use ReflectionClass; - -final class UpgradeApiSubresourceVisitor extends NodeVisitorAbstract -{ - use RemoveAnnotationTrait; - private $subresourceMetadata; - private $referenceType; - - public function __construct($subresourceMetadata, $referenceType) - { - $this->subresourceMetadata = $subresourceMetadata; - $this->referenceType = $referenceType; - } - - /** - * @return int|Node|null - */ - public function enterNode(Node $node) - { - $operationToCreate = $this->subresourceMetadata['collection'] ? GetCollection::class : Get::class; - $operationUseStatementNeeded = true; - $apiResourceUseStatementNeeded = true; - - $comment = $node->getDocComment(); - if ($comment && preg_match('/@ApiSubresource/', $comment->getText())) { - $node->setDocComment($this->removeAnnotationByTag($comment, 'ApiSubresource')); - } - - if ($node instanceof Node\Stmt\Namespace_) { - foreach ($node->stmts as $i => $stmt) { - if (!$stmt instanceof Node\Stmt\Use_) { - break; - } - - $useStatement = implode('\\', $stmt->uses[0]->name->parts); - if (ApiSubresource::class === $useStatement) { - unset($node->stmts[$i]); - } - - if (ApiResource::class === $useStatement) { - $apiResourceUseStatementNeeded = false; - continue; - } - - if ($useStatement === $operationToCreate) { - $operationUseStatementNeeded = false; - continue; - } - } - - if ($operationUseStatementNeeded) { - array_unshift( - $node->stmts, - new Node\Stmt\Use_([ - new Node\Stmt\UseUse( - new Node\Name( - $this->subresourceMetadata['collection'] ? GetCollection::class : Get::class - ) - ), - ]) - ); - } - - if ($apiResourceUseStatementNeeded) { - array_unshift( - $node->stmts, - new Node\Stmt\Use_([ - new Node\Stmt\UseUse( - new Node\Name( - ApiResource::class - ) - ), - ]), - new Node\Stmt\Use_([ - new Node\Stmt\UseUse( - new Node\Name( - Link::class - ) - ), - ]) - ); - } - } - - if ($node instanceof Node\Stmt\Class_) { - $identifiersNodeItems = []; - - foreach ($this->subresourceMetadata['uri_variables'] as $identifier => $resource) { - $identifierNodes = [ - 'fromClass' => new Node\Expr\ClassConstFetch( - new Node\Name( - ($resource['from_class'] === $this->subresourceMetadata['resource_class']) ? 'self' : '\\'.$resource['from_class'] - ), - 'class' - ), - 'identifiers' => new Node\Expr\Array_( - isset($resource['identifiers'][0]) ? [ - new Node\Expr\ArrayItem(new Node\Scalar\String_($resource['identifiers'][0])), - ] : [], - ['kind' => Node\Expr\Array_::KIND_SHORT] - ), - ]; - - if (isset($resource['expanded_value'])) { - $identifierNodes['expandedValue'] = new Node\Scalar\String_($resource['expanded_value']); - } - - if (isset($resource['from_property']) || isset($resource['to_property'])) { - $identifierNodes[isset($resource['to_property']) ? 'toProperty' : 'fromProperty'] = new Node\Scalar\String_($resource['to_property'] ?? $resource['from_property']); - } - - $identifierNodeItems[] = new Node\Expr\ArrayItem( - new Node\Expr\New_(new Node\Name('Link'), $this->arrayToArguments($identifierNodes)), - new Node\Scalar\String_($identifier) - ); - } - - $arguments = [ - new Node\Arg( - new Node\Scalar\String_($this->subresourceMetadata['path']), - false, - false, - [], - new Node\Identifier('uriTemplate') - ), - new Node\Arg( - new Node\Expr\Array_($identifierNodeItems, ['kind' => Node\Expr\Array_::KIND_SHORT]), - false, - false, - [], - new Node\Identifier('uriVariables') - ), - new Node\Arg( - new Node\Scalar\LNumber(200), - false, - false, - [], - new Node\Identifier('status') - ), - ]; - - if (null !== $this->referenceType) { - $urlGeneratorInterface = new ReflectionClass(UrlGeneratorInterface::class); - $urlGeneratorConstants = array_flip($urlGeneratorInterface->getConstants()); - $currentUrlGeneratorConstant = $urlGeneratorConstants[$this->referenceType]; - - $arguments[] = new Node\Arg( - new Node\Expr\ClassConstFetch( - new Node\Name('UrlGeneratorInterface'), - $currentUrlGeneratorConstant - ), - false, - false, - [], - new Node\Identifier('urlGenerationStrategy') - ); - } - - if ($this->subresourceMetadata['legacy_type'] ?? false) { - $arguments[] = new Node\Arg( - new Node\Expr\ArrayItem( - new Node\Expr\Array_( - [ - new Node\Expr\ArrayItem( - new Node\Scalar\String_($this->subresourceMetadata['legacy_type']) - ), - ], - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ) - ), - false, - false, - [], - new Node\Identifier('types') - ); - } - - if ($this->subresourceMetadata['legacy_filters'] ?? false) { - $arguments[] = new Node\Arg( - new Node\Expr\ArrayItem( - new Node\Expr\Array_( - array_map(function ($filter) { - return new Node\Expr\ArrayItem( - new Node\Scalar\String_($filter) - ); - }, $this->subresourceMetadata['legacy_filters']), - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ) - ), - false, - false, - [], - new Node\Identifier('filters') - ); - } - - if ($this->subresourceMetadata['legacy_normalization_context']['groups'] ?? false) { - $arguments[] = new Node\Arg( - new Node\Expr\ArrayItem( - new Node\Expr\Array_([ - new Node\Expr\ArrayItem( - new Node\Expr\Array_( - array_map(function ($group) { - return new Node\Expr\ArrayItem(new Node\Scalar\String_($group)); - }, $this->subresourceMetadata['legacy_normalization_context']['groups']), - ['kind' => Node\Expr\Array_::KIND_SHORT] - ), - new Node\Scalar\String_('groups') - ), - ], ['kind' => Node\Expr\Array_::KIND_SHORT]) - ), - false, - false, - [], - new Node\Identifier('normalizationContext') - ); - } - - $arguments[] = new Node\Arg( - new Node\Expr\Array_( - [ - new Node\Expr\ArrayItem( - new Node\Expr\New_( - new Node\Name($this->subresourceMetadata['collection'] ? 'GetCollection' : 'Get') - ), - ), - ], - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ), - false, - false, - [], - new Node\Identifier('operations') - ); - - $apiResourceAttribute = - new Node\AttributeGroup([ - new Node\Attribute( - new Node\Name('ApiResource'), - $arguments - ), - ]); - - $node->attrGroups[] = $apiResourceAttribute; - } - } - - /** - * @return Node\Arg[] - */ - private function arrayToArguments(array $arguments) - { - $args = []; - foreach ($arguments as $key => $value) { - $args[] = new Node\Arg($value, false, false, [], new Node\Identifier($key)); - } - - return $args; - } -} diff --git a/src/Core/Util/AnnotationFilterExtractorTrait.php b/src/Core/Util/AnnotationFilterExtractorTrait.php deleted file mode 100644 index 62498a53fb1..00000000000 --- a/src/Core/Util/AnnotationFilterExtractorTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\AnnotationFilterExtractorTrait::class); - -if (false) { - trait AnnotationFilterExtractorTrait - { - use \ApiPlatform\Util\AnnotationFilterExtractorTrait; - } -} diff --git a/src/Core/Util/ArrayTrait.php b/src/Core/Util/ArrayTrait.php deleted file mode 100644 index 2fc3bc81c37..00000000000 --- a/src/Core/Util/ArrayTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\ArrayTrait::class); - -if (false) { - trait ArrayTrait - { - use \ApiPlatform\Util\ArrayTrait; - } -} diff --git a/src/Core/Util/AttributesExtractor.php b/src/Core/Util/AttributesExtractor.php deleted file mode 100644 index 1ef911cca26..00000000000 --- a/src/Core/Util/AttributesExtractor.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\AttributesExtractor::class); - -if (false) { - final class AttributesExtractor extends \ApiPlatform\Util\AttributesExtractor - { - } -} diff --git a/src/Core/Util/ClassInfoTrait.php b/src/Core/Util/ClassInfoTrait.php deleted file mode 100644 index 9fc3fb7751b..00000000000 --- a/src/Core/Util/ClassInfoTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\ClassInfoTrait::class); - -if (false) { - trait ClassInfoTrait - { - use \ApiPlatform\Util\ClassInfoTrait; - } -} diff --git a/src/Core/Util/ClientTrait.php b/src/Core/Util/ClientTrait.php deleted file mode 100644 index 376776f80f7..00000000000 --- a/src/Core/Util/ClientTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\ClientTrait::class); - -if (false) { - trait ClientTrait - { - use \ApiPlatform\Util\ClientTrait; - } -} diff --git a/src/Core/Util/CloneTrait.php b/src/Core/Util/CloneTrait.php deleted file mode 100644 index a2a221b85b3..00000000000 --- a/src/Core/Util/CloneTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\CloneTrait::class); - -if (false) { - trait CloneTrait - { - use \ApiPlatform\Util\CloneTrait; - } -} diff --git a/src/Core/Util/CorsTrait.php b/src/Core/Util/CorsTrait.php deleted file mode 100644 index 7b66cb2697b..00000000000 --- a/src/Core/Util/CorsTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\CorsTrait::class); - -if (false) { - trait CorsTrait - { - use \ApiPlatform\Util\CorsTrait; - } -} diff --git a/src/Core/Util/ErrorFormatGuesser.php b/src/Core/Util/ErrorFormatGuesser.php deleted file mode 100644 index 5bc6fb11b0e..00000000000 --- a/src/Core/Util/ErrorFormatGuesser.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\ErrorFormatGuesser::class); - -if (false) { - final class ErrorFormatGuesser extends \ApiPlatform\Util\ErrorFormatGuesser - { - } -} diff --git a/src/Core/Util/Inflector.php b/src/Core/Util/Inflector.php deleted file mode 100644 index ab2ec6ca1f4..00000000000 --- a/src/Core/Util/Inflector.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\Inflector::class); - -if (false) { - final class Inflector extends \ApiPlatform\Util\Inflector - { - } -} diff --git a/src/Core/Util/IriHelper.php b/src/Core/Util/IriHelper.php deleted file mode 100644 index aca7d8dfd23..00000000000 --- a/src/Core/Util/IriHelper.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\IriHelper::class); - -if (false) { - final class IriHelper extends \ApiPlatform\Util\IriHelper - { - } -} diff --git a/src/Core/Util/Reflection.php b/src/Core/Util/Reflection.php deleted file mode 100644 index 2e4910c4321..00000000000 --- a/src/Core/Util/Reflection.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\Reflection::class); - -if (false) { - final class Reflection extends \ApiPlatform\Util\Reflection - { - } -} diff --git a/src/Core/Util/ReflectionClassRecursiveIterator.php b/src/Core/Util/ReflectionClassRecursiveIterator.php deleted file mode 100644 index 56504a2c544..00000000000 --- a/src/Core/Util/ReflectionClassRecursiveIterator.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\ReflectionClassRecursiveIterator::class); - -if (false) { - final class ReflectionClassRecursiveIterator extends \ApiPlatform\Util\ReflectionClassRecursiveIterator - { - } -} diff --git a/src/Core/Util/RequestAttributesExtractor.php b/src/Core/Util/RequestAttributesExtractor.php deleted file mode 100644 index cb834b5d9f6..00000000000 --- a/src/Core/Util/RequestAttributesExtractor.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\RequestAttributesExtractor::class); - -if (false) { - final class RequestAttributesExtractor extends \ApiPlatform\Util\RequestAttributesExtractor - { - } -} diff --git a/src/Core/Util/RequestParser.php b/src/Core/Util/RequestParser.php deleted file mode 100644 index db51ba35427..00000000000 --- a/src/Core/Util/RequestParser.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\RequestParser::class); - -if (false) { - final class RequestParser extends \ApiPlatform\Util\RequestParser - { - } -} diff --git a/src/Core/Util/ResourceClassInfoTrait.php b/src/Core/Util/ResourceClassInfoTrait.php deleted file mode 100644 index ab7bbc12c28..00000000000 --- a/src/Core/Util/ResourceClassInfoTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\ResourceClassInfoTrait::class); - -if (false) { - trait ResourceClassInfoTrait - { - use \ApiPlatform\Util\ResourceClassInfoTrait; - } -} diff --git a/src/Core/Util/ResponseTrait.php b/src/Core/Util/ResponseTrait.php deleted file mode 100644 index 8df237ceb58..00000000000 --- a/src/Core/Util/ResponseTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\ResponseTrait::class); - -if (false) { - trait ResponseTrait - { - use \ApiPlatform\Util\ResponseTrait; - } -} diff --git a/src/Core/Util/SortTrait.php b/src/Core/Util/SortTrait.php deleted file mode 100644 index 0367e29b6fb..00000000000 --- a/src/Core/Util/SortTrait.php +++ /dev/null @@ -1,23 +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); - -namespace ApiPlatform\Core\Util; - -class_exists(\ApiPlatform\Util\SortTrait::class); - -if (false) { - trait SortTrait - { - use \ApiPlatform\Util\SortTrait; - } -} diff --git a/src/Core/Validator/EventListener/ValidateListener.php b/src/Core/Validator/EventListener/ValidateListener.php deleted file mode 100644 index b5b9ae12341..00000000000 --- a/src/Core/Validator/EventListener/ValidateListener.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Validator\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\ValidateListener::class); - -if (false) { - final class ValidateListener extends \ApiPlatform\Symfony\EventListener\ValidateListener - { - } -} diff --git a/src/Core/Validator/Exception/ValidationException.php b/src/Core/Validator/Exception/ValidationException.php deleted file mode 100644 index a18f4def1f6..00000000000 --- a/src/Core/Validator/Exception/ValidationException.php +++ /dev/null @@ -1,22 +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); - -namespace ApiPlatform\Core\Validator\Exception; - -class_exists(\ApiPlatform\Validator\Exception\ValidationException::class); - -if (false) { - class ValidationException extends \ApiPlatform\Validator\Exception\ValidationException - { - } -} diff --git a/src/Doctrine/Common/Filter/BooleanFilterTrait.php b/src/Doctrine/Common/Filter/BooleanFilterTrait.php index 41173d4fe46..199dc54763d 100644 --- a/src/Doctrine/Common/Filter/BooleanFilterTrait.php +++ b/src/Doctrine/Common/Filter/BooleanFilterTrait.php @@ -97,5 +97,3 @@ private function normalizeValue($value, string $property): ?bool return null; } } - -class_alias(BooleanFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\BooleanFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/DateFilterTrait.php b/src/Doctrine/Common/Filter/DateFilterTrait.php index 11f9c5aa10d..958af548aca 100644 --- a/src/Doctrine/Common/Filter/DateFilterTrait.php +++ b/src/Doctrine/Common/Filter/DateFilterTrait.php @@ -94,5 +94,3 @@ private function normalizeValue($value, string $operator): ?string return $value; } } - -class_alias(DateFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\DateFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/ExistsFilterTrait.php b/src/Doctrine/Common/Filter/ExistsFilterTrait.php index 25895f4f158..41cfe4a36a0 100644 --- a/src/Doctrine/Common/Filter/ExistsFilterTrait.php +++ b/src/Doctrine/Common/Filter/ExistsFilterTrait.php @@ -100,5 +100,3 @@ private function normalizeValue($value, string $property): ?bool return null; } } - -class_alias(ExistsFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\ExistsFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/NumericFilterTrait.php b/src/Doctrine/Common/Filter/NumericFilterTrait.php index 0a946372c8a..5d4850d6644 100644 --- a/src/Doctrine/Common/Filter/NumericFilterTrait.php +++ b/src/Doctrine/Common/Filter/NumericFilterTrait.php @@ -122,5 +122,3 @@ protected function isNumericArray(array $values): bool return true; } } - -class_alias(NumericFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\NumericFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/OrderFilterTrait.php b/src/Doctrine/Common/Filter/OrderFilterTrait.php index faf92372523..8d7ad9d302f 100644 --- a/src/Doctrine/Common/Filter/OrderFilterTrait.php +++ b/src/Doctrine/Common/Filter/OrderFilterTrait.php @@ -84,5 +84,3 @@ private function normalizeValue($value, string $property): ?string return $value; } } - -class_alias(OrderFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\OrderFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Doctrine/Common/Filter/RangeFilterTrait.php index 007d59f0db6..6051ac48efd 100644 --- a/src/Doctrine/Common/Filter/RangeFilterTrait.php +++ b/src/Doctrine/Common/Filter/RangeFilterTrait.php @@ -139,5 +139,3 @@ private function normalizeValue(string $value, string $operator) return $value + 0; // coerce $value to the right type. } } - -class_alias(RangeFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\RangeFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/SearchFilterTrait.php b/src/Doctrine/Common/Filter/SearchFilterTrait.php index f74a0a4b90a..1aa89b8ab8b 100644 --- a/src/Doctrine/Common/Filter/SearchFilterTrait.php +++ b/src/Doctrine/Common/Filter/SearchFilterTrait.php @@ -176,5 +176,3 @@ protected function hasValidValues(array $values, $type = null): bool return true; } } - -class_alias(SearchFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterTrait::class); diff --git a/src/Doctrine/Common/PropertyHelperTrait.php b/src/Doctrine/Common/PropertyHelperTrait.php index 573e30baac5..21ec57b8be2 100644 --- a/src/Doctrine/Common/PropertyHelperTrait.php +++ b/src/Doctrine/Common/PropertyHelperTrait.php @@ -169,5 +169,3 @@ protected function getClassMetadata(string $resourceClass): ClassMetadata ->getClassMetadata($resourceClass); } } - -class_alias(PropertyHelperTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\PropertyHelperTrait::class); diff --git a/src/Doctrine/EventListener/PurgeHttpCacheListener.php b/src/Doctrine/EventListener/PurgeHttpCacheListener.php index 7fa2b10eb8a..59534ee8985 100644 --- a/src/Doctrine/EventListener/PurgeHttpCacheListener.php +++ b/src/Doctrine/EventListener/PurgeHttpCacheListener.php @@ -171,5 +171,3 @@ private function addTagForItem($value): void } } } - -class_alias(PurgeHttpCacheListener::class, \ApiPlatform\Core\Bridge\Doctrine\EventListener\PurgeHttpCacheListener::class); diff --git a/src/Doctrine/EventListener/WriteListener.php b/src/Doctrine/EventListener/WriteListener.php index 5938b6223ba..808d298f34f 100644 --- a/src/Doctrine/EventListener/WriteListener.php +++ b/src/Doctrine/EventListener/WriteListener.php @@ -84,5 +84,3 @@ private function getManager(string $resourceClass, $data): ?ObjectManager return $objectManager; } } - -class_alias(WriteListener::class, \ApiPlatform\Core\Bridge\Doctrine\EventListener\WriteListener::class); diff --git a/src/Doctrine/Odm/Extension/FilterExtension.php b/src/Doctrine/Odm/Extension/FilterExtension.php index b5442791c67..b5df5addbc1 100644 --- a/src/Doctrine/Odm/Extension/FilterExtension.php +++ b/src/Doctrine/Odm/Extension/FilterExtension.php @@ -77,5 +77,3 @@ public function applyToCollection(Builder $aggregationBuilder, string $resourceC } } } - -class_alias(FilterExtension::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\FilterExtension::class); diff --git a/src/Doctrine/Odm/Filter/AbstractFilter.php b/src/Doctrine/Odm/Filter/AbstractFilter.php index b568ebfb3b8..567d9a8a1fb 100644 --- a/src/Doctrine/Odm/Filter/AbstractFilter.php +++ b/src/Doctrine/Odm/Filter/AbstractFilter.php @@ -111,5 +111,3 @@ protected function normalizePropertyName($property) return implode('.', array_map([$this->nameConverter, 'normalize'], explode('.', (string) $property))); } } - -class_alias(AbstractFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\AbstractFilter::class); diff --git a/src/Doctrine/Odm/Filter/BooleanFilter.php b/src/Doctrine/Odm/Filter/BooleanFilter.php index 1e295ab76da..111760aa251 100644 --- a/src/Doctrine/Odm/Filter/BooleanFilter.php +++ b/src/Doctrine/Odm/Filter/BooleanFilter.php @@ -68,5 +68,3 @@ protected function filterProperty(string $property, $value, Builder $aggregation $aggregationBuilder->match()->field($matchField)->equals($value); } } - -class_alias(BooleanFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\BooleanFilter::class); diff --git a/src/Doctrine/Odm/Filter/DateFilter.php b/src/Doctrine/Odm/Filter/DateFilter.php index 92a48f7674f..9b64b4b4a56 100644 --- a/src/Doctrine/Odm/Filter/DateFilter.php +++ b/src/Doctrine/Odm/Filter/DateFilter.php @@ -151,5 +151,3 @@ private function addMatch(Builder $aggregationBuilder, string $field, string $op $aggregationBuilder->match()->addAnd($aggregationBuilder->matchExpr()->field($field)->operator($operatorValue[$operator], $value)); } } - -class_alias(DateFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\DateFilter::class); diff --git a/src/Doctrine/Odm/Filter/ExistsFilter.php b/src/Doctrine/Odm/Filter/ExistsFilter.php index 0e723437604..829d60315d5 100644 --- a/src/Doctrine/Odm/Filter/ExistsFilter.php +++ b/src/Doctrine/Odm/Filter/ExistsFilter.php @@ -105,5 +105,3 @@ protected function isNullableField(string $property, string $resourceClass): boo return $metadata instanceof ClassMetadata && $metadata->hasField($field) ? $metadata->isNullable($field) : false; } } - -class_alias(ExistsFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\ExistsFilter::class); diff --git a/src/Doctrine/Odm/Filter/NumericFilter.php b/src/Doctrine/Odm/Filter/NumericFilter.php index 84f1517b7ee..e6766af8a98 100644 --- a/src/Doctrine/Odm/Filter/NumericFilter.php +++ b/src/Doctrine/Odm/Filter/NumericFilter.php @@ -91,5 +91,3 @@ protected function getType(string $doctrineType = null): string return 'int'; } } - -class_alias(NumericFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\NumericFilter::class); diff --git a/src/Doctrine/Odm/Filter/OrderFilter.php b/src/Doctrine/Odm/Filter/OrderFilter.php index 02d31b9c011..60c6df2f7cd 100644 --- a/src/Doctrine/Odm/Filter/OrderFilter.php +++ b/src/Doctrine/Odm/Filter/OrderFilter.php @@ -105,5 +105,3 @@ protected function filterProperty(string $property, $direction, Builder $aggrega ); } } - -class_alias(OrderFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\OrderFilter::class); diff --git a/src/Doctrine/Odm/Filter/RangeFilter.php b/src/Doctrine/Odm/Filter/RangeFilter.php index 9dbcf22318d..b6c1c7d9d48 100644 --- a/src/Doctrine/Odm/Filter/RangeFilter.php +++ b/src/Doctrine/Odm/Filter/RangeFilter.php @@ -126,5 +126,3 @@ protected function addMatch(Builder $aggregationBuilder, string $field, string $ } } } - -class_alias(RangeFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\RangeFilter::class); diff --git a/src/Doctrine/Odm/Paginator.php b/src/Doctrine/Odm/Paginator.php index 11ff2ae9411..69efc1baf86 100644 --- a/src/Doctrine/Odm/Paginator.php +++ b/src/Doctrine/Odm/Paginator.php @@ -184,5 +184,3 @@ private function hasLimitZeroStage(array $resultsFacetInfo): bool return false; } } - -class_alias(Paginator::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator::class); diff --git a/src/Doctrine/Odm/PropertyHelperTrait.php b/src/Doctrine/Odm/PropertyHelperTrait.php index ca8f20715b5..436293cf694 100644 --- a/src/Doctrine/Odm/PropertyHelperTrait.php +++ b/src/Doctrine/Odm/PropertyHelperTrait.php @@ -105,5 +105,3 @@ protected function addLookupsForNestedProperty(string $property, Builder $aggreg return [$property, $propertyParts['field'], $propertyParts['associations']]; } } - -class_alias(PropertyHelperTrait::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\PropertyHelperTrait::class); diff --git a/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php b/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php index d6c22d3f185..511d5adb10d 100644 --- a/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php +++ b/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php @@ -183,5 +183,3 @@ private function getPhpType(string $doctrineType): ?string return null; } } - -class_alias(DoctrineExtractor::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\PropertyInfo\DoctrineExtractor::class); diff --git a/src/Doctrine/Orm/AbstractPaginator.php b/src/Doctrine/Orm/AbstractPaginator.php index 258ab792de9..f024925012b 100644 --- a/src/Doctrine/Orm/AbstractPaginator.php +++ b/src/Doctrine/Orm/AbstractPaginator.php @@ -77,5 +77,3 @@ public function count(): int return iterator_count($this->getIterator()); } } - -class_alias(AbstractPaginator::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\AbstractPaginator::class); diff --git a/src/Doctrine/Orm/Extension/EagerLoadingExtension.php b/src/Doctrine/Orm/Extension/EagerLoadingExtension.php index bac34438d46..a3f224bfd3e 100644 --- a/src/Doctrine/Orm/Extension/EagerLoadingExtension.php +++ b/src/Doctrine/Orm/Extension/EagerLoadingExtension.php @@ -13,10 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Extension; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; @@ -27,14 +23,14 @@ use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyMetadata; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\Query\Expr\Select; use Doctrine\ORM\QueryBuilder; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; @@ -55,38 +51,16 @@ final class EagerLoadingExtension implements ContextAwareQueryCollectionExtensio private $propertyMetadataFactory; private $classMetadataFactory; private $maxJoins; - private $serializerContextBuilder; - private $requestStack; - /** - * @TODO move $fetchPartial after $forceEager (@soyuka) in 3.0 - * - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - * @param PropertyMetadataFactoryInterface|LegacyPropertyMetadataFactory $propertyMetadataFactory - */ - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory, int $maxJoins = 30, bool $forceEager = true, RequestStack $requestStack = null, SerializerContextBuilderInterface $serializerContextBuilder = null, bool $fetchPartial = false, ClassMetadataFactoryInterface $classMetadataFactory = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, int $maxJoins = 30, bool $forceEager = true, bool $fetchPartial = false, ClassMetadataFactoryInterface $classMetadataFactory = null) { - if (null !== $this->requestStack) { - @trigger_error(sprintf('Passing an instance of "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the data provider\'s context instead.', RequestStack::class), \E_USER_DEPRECATED); - } - if (null !== $this->serializerContextBuilder) { - @trigger_error(sprintf('Passing an instance of "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the data provider\'s context instead.', SerializerContextBuilderInterface::class), \E_USER_DEPRECATED); - } - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->classMetadataFactory = $classMetadataFactory; $this->maxJoins = $maxJoins; $this->forceEager = $forceEager; $this->fetchPartial = $fetchPartial; - $this->serializerContextBuilder = $serializerContextBuilder; - $this->requestStack = $requestStack; } /** @@ -122,29 +96,19 @@ private function apply(bool $collection, QueryBuilder $queryBuilder, QueryNameGe $operation = null; $forceEager = $this->forceEager; $fetchPartial = $this->fetchPartial; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $resourceMetadataCollection->getOperation($operationName); - $forceEager = $operation->getForceEager() ?? $this->forceEager; - $fetchPartial = $operation->getFetchPartial() ?? $this->fetchPartial; - } catch (OperationNotFoundException $e) { - // In some cases the operation may not exist - } - } else { - $forceEager = $this->shouldOperationForceEager($resourceClass, $options); - $fetchPartial = $this->shouldOperationFetchPartial($resourceClass, $options); + $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); + try { + $operation = $resourceMetadataCollection->getOperation($operationName); + $forceEager = $operation->getForceEager() ?? $this->forceEager; + $fetchPartial = $operation->getFetchPartial() ?? $this->fetchPartial; + } catch (OperationNotFoundException $e) { + // In some cases the operation may not exist } if (!isset($context['groups']) && !isset($context['attributes'])) { $contextType = isset($context['api_denormalize']) ? 'denormalization_context' : 'normalization_context'; - if (null !== $this->requestStack && null !== $this->serializerContextBuilder && null !== $request = $this->requestStack->getCurrentRequest()) { - $context += $this->serializerContextBuilder->createFromRequest($request, 'normalization_context' === $contextType); - } elseif ($operation) { + if ($operation) { $context += 'denormalization_context' === $contextType ? ($operation->getDenormalizationContext() ?? []) : ($operation->getNormalizationContext() ?? []); - } elseif (!$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - // TODO: remove in 3.0 - $context += $this->getNormalizationContext($context['resource_class'] ?? $resourceClass, $contextType, $options); } } @@ -156,9 +120,12 @@ private function apply(bool $collection, QueryBuilder $queryBuilder, QueryNameGe $options['serializer_groups'] = (array) $context[AbstractNormalizer::GROUPS]; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $options['normalization_groups'] = $operation ? ($operation->getNormalizationContext()['groups'] ?? null) : null; - $options['denormalization_groups'] = $operation ? ($operation->getDenormalizationContext()['groups'] ?? null) : null; + if ($operation && $normalizationGroups = $operation->getNormalizationContext()['groups'] ?? null) { + $options['normalization_groups'] = $normalizationGroups; + } + + if ($operation && $denormalizationGroups = $operation->getDenormalizationContext()['groups'] ?? null) { + $options['denormalization_groups'] = $denormalizationGroups; } $this->joinRelations($queryBuilder, $queryNameGenerator, $resourceClass, $forceEager, $fetchPartial, $queryBuilder->getRootAliases()[0], $options, $context); @@ -191,7 +158,6 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt } try { - /** @var ApiProperty|PropertyMetadata */ $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $association, $options); } catch (PropertyNotFoundException $propertyNotFoundException) { // skip properties not found @@ -221,16 +187,7 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt $inAttributes = null; } - $fetchEager = null; - if ($propertyMetadata instanceof ApiProperty) { - $fetchEager = $propertyMetadata->getFetchEager(); - } elseif ( - $propertyMetadata instanceof PropertyMetadata && - (null === $fetchEager = $propertyMetadata->getAttribute('fetch_eager')) && - (null !== $fetchEager = $propertyMetadata->getAttribute('fetchEager')) - ) { - @trigger_error('The "fetchEager" attribute is deprecated since 2.3. Please use "fetch_eager" instead.', \E_USER_DEPRECATED); - } + $fetchEager = $propertyMetadata->getFetchEager(); if (false === $fetchEager) { continue; @@ -320,7 +277,7 @@ private function addSelect(QueryBuilder $queryBuilder, string $entity, string $a // If it's an embedded property see below if (!\array_key_exists($property, $targetClassMetadata->embeddedClasses)) { - $isFetchable = $propertyMetadata instanceof ApiProperty ? $propertyMetadata->isFetchable() : $propertyMetadata->getAttribute('fetchable'); + $isFetchable = $propertyMetadata->isFetchable(); // the field test allows to add methods to a Resource which do not reflect real database fields if ($targetClassMetadata->hasField($property) && (true === $isFetchable || $propertyMetadata->isReadable())) { $select[] = $property; @@ -331,7 +288,7 @@ private function addSelect(QueryBuilder $queryBuilder, string $entity, string $a // It's an embedded property, select relevant subfields foreach ($this->propertyNameCollectionFactory->create($targetClassMetadata->embeddedClasses[$property]['class']) as $embeddedProperty) { - $isFetchable = $propertyMetadata instanceof ApiProperty ? $propertyMetadata->isFetchable() : $propertyMetadata->getAttribute('fetchable'); + $isFetchable = $propertyMetadata->isFetchable(); $propertyMetadata = $this->propertyMetadataFactory->create($entity, $property, $propertyMetadataOptions); $propertyName = "$property.$embeddedProperty"; if ($targetClassMetadata->hasField($propertyName) && (true === $isFetchable || $propertyMetadata->isReadable())) { @@ -362,10 +319,6 @@ private function addSelectOnce(QueryBuilder $queryBuilder, string $alias) */ private function getNormalizationContext(string $resourceClass, string $contextType, array $options): array { - if (null !== $this->requestStack && null !== $this->serializerContextBuilder && null !== $request = $this->requestStack->getCurrentRequest()) { - return $this->serializerContextBuilder->createFromRequest($request, 'normalization_context' === $contextType); - } - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); if (isset($options['collection_operation_name'])) { $context = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], $contextType, null, true); @@ -378,5 +331,3 @@ private function getNormalizationContext(string $resourceClass, string $contextT return $context ?? []; } } - -class_alias(EagerLoadingExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\EagerLoadingExtension::class); diff --git a/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php b/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php index 6c867abd2c6..453f1146c73 100644 --- a/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php +++ b/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php @@ -202,5 +202,3 @@ private function buildReplacePatterns(array $aliases): array }, $aliases); } } - -class_alias(FilterEagerLoadingExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterEagerLoadingExtension::class); diff --git a/src/Doctrine/Orm/Extension/FilterExtension.php b/src/Doctrine/Orm/Extension/FilterExtension.php index 4a02d630dcd..ceb898ad47f 100644 --- a/src/Doctrine/Orm/Extension/FilterExtension.php +++ b/src/Doctrine/Orm/Extension/FilterExtension.php @@ -106,5 +106,3 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator } } } - -class_alias(FilterExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterExtension::class); diff --git a/src/Doctrine/Orm/Extension/OrderExtension.php b/src/Doctrine/Orm/Extension/OrderExtension.php index 894ccfb2884..b8a29f4e0d5 100644 --- a/src/Doctrine/Orm/Extension/OrderExtension.php +++ b/src/Doctrine/Orm/Extension/OrderExtension.php @@ -115,6 +115,3 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator } } } - -class_alias(OrderExtension::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\OrderExtension::class); -class_alias(OrderExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\OrderExtension::class); diff --git a/src/Doctrine/Orm/Extension/PaginationExtension.php b/src/Doctrine/Orm/Extension/PaginationExtension.php index 8eebdc8707d..10259f41b27 100644 --- a/src/Doctrine/Orm/Extension/PaginationExtension.php +++ b/src/Doctrine/Orm/Extension/PaginationExtension.php @@ -488,6 +488,3 @@ private function shouldDoctrinePaginatorUseOutputWalkers(QueryBuilder $queryBuil return false; } } - -class_alias(PaginationExtension::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\PaginationExtension::class); -class_alias(PaginationExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension::class); diff --git a/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php b/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php index 70ab6c0af51..4385d8f5a95 100644 --- a/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php +++ b/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php @@ -34,5 +34,3 @@ public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $q } } } - -class_alias(AbstractContextAwareFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractContextAwareFilter::class); diff --git a/src/Doctrine/Orm/Filter/AbstractFilter.php b/src/Doctrine/Orm/Filter/AbstractFilter.php index 3781664f73e..68d8cc61c30 100644 --- a/src/Doctrine/Orm/Filter/AbstractFilter.php +++ b/src/Doctrine/Orm/Filter/AbstractFilter.php @@ -162,5 +162,3 @@ protected function normalizePropertyName($property) return implode('.', array_map([$this->nameConverter, 'normalize'], explode('.', (string) $property))); } } - -class_alias(AbstractFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter::class); diff --git a/src/Doctrine/Orm/Filter/BooleanFilter.php b/src/Doctrine/Orm/Filter/BooleanFilter.php index 162bcc064c9..4f2bacc3257 100644 --- a/src/Doctrine/Orm/Filter/BooleanFilter.php +++ b/src/Doctrine/Orm/Filter/BooleanFilter.php @@ -72,5 +72,3 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB ->setParameter($valueParameter, $value); } } - -class_alias(BooleanFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\BooleanFilter::class); diff --git a/src/Doctrine/Orm/Filter/DateFilter.php b/src/Doctrine/Orm/Filter/DateFilter.php index 0031cad1af2..5d63a1a94e0 100644 --- a/src/Doctrine/Orm/Filter/DateFilter.php +++ b/src/Doctrine/Orm/Filter/DateFilter.php @@ -182,5 +182,3 @@ protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterf $queryBuilder->setParameter($valueParameter, $value, $type); } } - -class_alias(DateFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\DateFilter::class); diff --git a/src/Doctrine/Orm/Filter/ExistsFilter.php b/src/Doctrine/Orm/Filter/ExistsFilter.php index 3a17f44f7bb..854461d7b6d 100644 --- a/src/Doctrine/Orm/Filter/ExistsFilter.php +++ b/src/Doctrine/Orm/Filter/ExistsFilter.php @@ -211,5 +211,3 @@ protected function extractProperties(Request $request/* , string $resourceClass return \is_array($properties) ? $properties : []; } } - -class_alias(ExistsFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\ExistsFilter::class); diff --git a/src/Doctrine/Orm/Filter/NumericFilter.php b/src/Doctrine/Orm/Filter/NumericFilter.php index f0b487fe961..f32e16f0771 100644 --- a/src/Doctrine/Orm/Filter/NumericFilter.php +++ b/src/Doctrine/Orm/Filter/NumericFilter.php @@ -102,5 +102,3 @@ protected function getType(string $doctrineType = null): string return 'int'; } } - -class_alias(NumericFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\NumericFilter::class); diff --git a/src/Doctrine/Orm/Filter/OrderFilter.php b/src/Doctrine/Orm/Filter/OrderFilter.php index 9f17e2e5433..8241b52e1b3 100644 --- a/src/Doctrine/Orm/Filter/OrderFilter.php +++ b/src/Doctrine/Orm/Filter/OrderFilter.php @@ -131,5 +131,3 @@ protected function extractProperties(Request $request/* , string $resourceClass return \is_array($properties) ? $properties : []; } } - -class_alias(OrderFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter::class); diff --git a/src/Doctrine/Orm/Filter/RangeFilter.php b/src/Doctrine/Orm/Filter/RangeFilter.php index edd5b95afb0..e8738bb00bd 100644 --- a/src/Doctrine/Orm/Filter/RangeFilter.php +++ b/src/Doctrine/Orm/Filter/RangeFilter.php @@ -148,5 +148,3 @@ protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterf } } } - -class_alias(RangeFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\RangeFilter::class); diff --git a/src/Doctrine/Orm/Paginator.php b/src/Doctrine/Orm/Paginator.php index 21a3d18d22b..92f8265b66e 100644 --- a/src/Doctrine/Orm/Paginator.php +++ b/src/Doctrine/Orm/Paginator.php @@ -56,5 +56,3 @@ public function getQuery(): Query return $this->paginator->getQuery(); } } - -class_alias(Paginator::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator::class); diff --git a/src/Doctrine/Orm/PropertyHelperTrait.php b/src/Doctrine/Orm/PropertyHelperTrait.php index 88da7b02059..d29f586bcab 100644 --- a/src/Doctrine/Orm/PropertyHelperTrait.php +++ b/src/Doctrine/Orm/PropertyHelperTrait.php @@ -82,5 +82,3 @@ protected function addJoinsForNestedProperty(string $property, string $rootAlias return [$alias, $propertyParts['field'], $propertyParts['associations']]; } } - -class_alias(PropertyHelperTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\PropertyHelperTrait::class); diff --git a/src/Doctrine/Orm/Util/EagerLoadingTrait.php b/src/Doctrine/Orm/Util/EagerLoadingTrait.php index 6853288a642..12d125fd3f4 100644 --- a/src/Doctrine/Orm/Util/EagerLoadingTrait.php +++ b/src/Doctrine/Orm/Util/EagerLoadingTrait.php @@ -106,5 +106,3 @@ private function hasFetchEagerAssociation(EntityManagerInterface $em, ClassMetad return false; } } - -class_alias(EagerLoadingTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\EagerLoadingTrait::class); diff --git a/src/Doctrine/Orm/Util/QueryBuilderHelper.php b/src/Doctrine/Orm/Util/QueryBuilderHelper.php index 2d6790da33c..b22d5e5d87a 100644 --- a/src/Doctrine/Orm/Util/QueryBuilderHelper.php +++ b/src/Doctrine/Orm/Util/QueryBuilderHelper.php @@ -218,5 +218,3 @@ private static function mapJoinAliases(iterable $joins): array return $aliasMap; } } - -class_alias(QueryBuilderHelper::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryBuilderHelper::class); diff --git a/src/Doctrine/Orm/Util/QueryChecker.php b/src/Doctrine/Orm/Util/QueryChecker.php index d5b449168ec..ce8dd718a5c 100644 --- a/src/Doctrine/Orm/Util/QueryChecker.php +++ b/src/Doctrine/Orm/Util/QueryChecker.php @@ -205,5 +205,3 @@ public static function hasJoinedToManyAssociation(QueryBuilder $queryBuilder, Ma return false; } } - -class_alias(QueryChecker::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryChecker::class); diff --git a/src/Doctrine/Orm/Util/QueryJoinParser.php b/src/Doctrine/Orm/Util/QueryJoinParser.php index 861efc00e52..abe9bf2fd01 100644 --- a/src/Doctrine/Orm/Util/QueryJoinParser.php +++ b/src/Doctrine/Orm/Util/QueryJoinParser.php @@ -89,5 +89,3 @@ public static function getOrderByParts(OrderBy $orderBy): array return $orderBy->getParts(); } } - -class_alias(QueryJoinParser::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryJoinParser::class); diff --git a/src/Doctrine/Orm/Util/QueryNameGenerator.php b/src/Doctrine/Orm/Util/QueryNameGenerator.php index bf049615c7d..9bf85b1581d 100644 --- a/src/Doctrine/Orm/Util/QueryNameGenerator.php +++ b/src/Doctrine/Orm/Util/QueryNameGenerator.php @@ -41,5 +41,3 @@ public function generateParameterName(string $name): string return sprintf('%s_p%d', str_replace('.', '_', $name), $this->incrementedName++); } } - -class_alias(QueryNameGenerator::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator::class); diff --git a/src/Documentation/Action/DocumentationAction.php b/src/Documentation/Action/DocumentationAction.php index b470f185cd8..34177f31cbe 100644 --- a/src/Documentation/Action/DocumentationAction.php +++ b/src/Documentation/Action/DocumentationAction.php @@ -43,7 +43,7 @@ final class DocumentationAction * @param mixed|array|FormatsProviderInterface $formatsProvider * @param LegacyOpenApiFactoryInterface|OpenApiFactoryInterface $openApiFactory */ - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, string $title = '', string $description = '', string $version = '', $formatsProvider = null, array $swaggerVersions = [2, 3], $openApiFactory = null) + public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, string $title = '', string $description = '', string $version = '', array $swaggerVersions = [2, 3], OpenApiFactoryInterface $openApiFactory = null) { $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; $this->title = $title; @@ -51,23 +51,6 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName $this->version = $version; $this->swaggerVersions = $swaggerVersions; $this->openApiFactory = $openApiFactory; - - if (null === $openApiFactory) { - @trigger_error(sprintf('Not passing an instance of "%s" as 7th parameter of the constructor of "%s" is deprecated since API Platform 2.6', OpenApiFactoryInterface::class, __CLASS__), \E_USER_DEPRECATED); - } - - if (null === $formatsProvider) { - return; - } - - @trigger_error(sprintf('Passing an array or an instance of "%s" as 5th parameter of the constructor of "%s" is deprecated since API Platform 2.5', FormatsProviderInterface::class, __CLASS__), \E_USER_DEPRECATED); - if (\is_array($formatsProvider)) { - $this->formats = $formatsProvider; - - return; - } - - $this->formatsProvider = $formatsProvider; } public function __invoke(Request $request = null): DocumentationInterface @@ -82,11 +65,6 @@ public function __invoke(Request $request = null): DocumentationInterface $attributes = RequestAttributesExtractor::extractAttributes($request); } - // BC check to be removed in 3.0 - if (null !== $this->formatsProvider) { - $this->formats = $this->formatsProvider->getFormatsFromAttributes($attributes ?? []); - } - if ('json' === $request->getRequestFormat() && null !== $this->openApiFactory && 3 === ($context['spec_version'] ?? null)) { return $this->openApiFactory->__invoke($context ?? []); } @@ -94,5 +72,3 @@ public function __invoke(Request $request = null): DocumentationInterface return new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version, $this->formats); } } - -class_alias(DocumentationAction::class, \ApiPlatform\Core\Documentation\Action\DocumentationAction::class); diff --git a/src/Documentation/Documentation.php b/src/Documentation/Documentation.php index fdc2cd3b8b0..8f674167489 100644 --- a/src/Documentation/Documentation.php +++ b/src/Documentation/Documentation.php @@ -75,5 +75,3 @@ public function getResourceNameCollection(): ResourceNameCollection return $this->resourceNameCollection; } } - -class_alias(Documentation::class, \ApiPlatform\Core\Documentation\Documentation::class); diff --git a/src/Elasticsearch/Exception/IndexNotFoundException.php b/src/Elasticsearch/Exception/IndexNotFoundException.php index 13ccd4846b2..c12ca5d6b9e 100644 --- a/src/Elasticsearch/Exception/IndexNotFoundException.php +++ b/src/Elasticsearch/Exception/IndexNotFoundException.php @@ -25,5 +25,3 @@ final class IndexNotFoundException extends \Exception implements ExceptionInterface { } - -class_alias(IndexNotFoundException::class, \ApiPlatform\Core\Bridge\Elasticsearch\Exception\IndexNotFoundException::class); diff --git a/src/Elasticsearch/Exception/NonUniqueIdentifierException.php b/src/Elasticsearch/Exception/NonUniqueIdentifierException.php index 6851f208cee..e2d007b1f70 100644 --- a/src/Elasticsearch/Exception/NonUniqueIdentifierException.php +++ b/src/Elasticsearch/Exception/NonUniqueIdentifierException.php @@ -25,5 +25,3 @@ final class NonUniqueIdentifierException extends \Exception implements ExceptionInterface { } - -class_alias(NonUniqueIdentifierException::class, \ApiPlatform\Core\Bridge\Elasticsearch\Exception\NonUniqueIdentifierException::class); diff --git a/src/Elasticsearch/Extension/AbstractFilterExtension.php b/src/Elasticsearch/Extension/AbstractFilterExtension.php index 45d334a1c98..da139632bc8 100644 --- a/src/Elasticsearch/Extension/AbstractFilterExtension.php +++ b/src/Elasticsearch/Extension/AbstractFilterExtension.php @@ -72,5 +72,3 @@ abstract protected function getFilterInterface(): string; */ abstract protected function alterRequestBody(array $requestBody, array $clauseBody): array; } - -class_alias(AbstractFilterExtension::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\AbstractFilterExtension::class); diff --git a/src/Elasticsearch/Extension/ConstantScoreFilterExtension.php b/src/Elasticsearch/Extension/ConstantScoreFilterExtension.php index 69e85cbb37f..bb5a5819151 100644 --- a/src/Elasticsearch/Extension/ConstantScoreFilterExtension.php +++ b/src/Elasticsearch/Extension/ConstantScoreFilterExtension.php @@ -49,5 +49,3 @@ protected function alterRequestBody(array $requestBody, array $clauseBody): arra return $requestBody; } } - -class_alias(ConstantScoreFilterExtension::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\ConstantScoreFilterExtension::class); diff --git a/src/Elasticsearch/Extension/SortExtension.php b/src/Elasticsearch/Extension/SortExtension.php index 8d98e8bc7ba..627663e8018 100644 --- a/src/Elasticsearch/Extension/SortExtension.php +++ b/src/Elasticsearch/Extension/SortExtension.php @@ -97,5 +97,3 @@ private function getOrder(string $resourceClass, string $property, string $direc return [$property => $order]; } } - -class_alias(SortExtension::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\SortExtension::class); diff --git a/src/Elasticsearch/Extension/SortFilterExtension.php b/src/Elasticsearch/Extension/SortFilterExtension.php index e9d50486f11..84aec9efe6c 100644 --- a/src/Elasticsearch/Extension/SortFilterExtension.php +++ b/src/Elasticsearch/Extension/SortFilterExtension.php @@ -44,5 +44,3 @@ protected function alterRequestBody(array $requestBody, array $clauseBody): arra return $requestBody; } } - -class_alias(SortFilterExtension::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\SortFilterExtension::class); diff --git a/src/Elasticsearch/Metadata/Document/DocumentMetadata.php b/src/Elasticsearch/Metadata/Document/DocumentMetadata.php index c035862c97a..c6197da4ffb 100644 --- a/src/Elasticsearch/Metadata/Document/DocumentMetadata.php +++ b/src/Elasticsearch/Metadata/Document/DocumentMetadata.php @@ -73,5 +73,3 @@ public function getType(): string return $this->type; } } - -class_alias(DocumentMetadata::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\DocumentMetadata::class); diff --git a/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php index 0bd6c20fa44..3b4f9647af5 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php @@ -88,5 +88,3 @@ public function create(string $resourceClass): DocumentMetadata throw new IndexNotFoundException(sprintf('No index associated with the "%s" resource class.', $resourceClass)); } } - -class_alias(AttributeDocumentMetadataFactory::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory::class); diff --git a/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php index 6f28aa420e3..08316964138 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php @@ -78,5 +78,3 @@ private function handleNotFound(DocumentMetadata $documentMetadata, string $reso return $documentMetadata; } } - -class_alias(CachedDocumentMetadataFactory::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory::class); diff --git a/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php index 6f89047ff93..2a7a8f60f3a 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php @@ -104,5 +104,3 @@ private function handleNotFound(?DocumentMetadata $documentMetadata, string $res throw new IndexNotFoundException(sprintf('No index associated with the "%s" resource class.', $resourceClass)); } } - -class_alias(CatDocumentMetadataFactory::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory::class); diff --git a/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php index d194d46576e..fb1d1da7098 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php @@ -69,5 +69,3 @@ public function create(string $resourceClass): DocumentMetadata return $documentMetadata; } } - -class_alias(ConfiguredDocumentMetadataFactory::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory::class); diff --git a/src/Elasticsearch/Paginator.php b/src/Elasticsearch/Paginator.php index 87837e5eb64..f04504f7e8f 100644 --- a/src/Elasticsearch/Paginator.php +++ b/src/Elasticsearch/Paginator.php @@ -128,5 +128,3 @@ public function getIterator(): \Traversable } } } - -class_alias(Paginator::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Paginator::class); diff --git a/src/Elasticsearch/Serializer/DocumentNormalizer.php b/src/Elasticsearch/Serializer/DocumentNormalizer.php index e4040990b81..7400c5e27f3 100644 --- a/src/Elasticsearch/Serializer/DocumentNormalizer.php +++ b/src/Elasticsearch/Serializer/DocumentNormalizer.php @@ -100,5 +100,3 @@ private function populateIdentifier(array $data, string $class): array return $data; } } - -class_alias(DocumentNormalizer::class, \ApiPlatform\Core\Bridge\Elasticsearch\Serializer\DocumentNormalizer::class); diff --git a/src/Elasticsearch/Serializer/ItemNormalizer.php b/src/Elasticsearch/Serializer/ItemNormalizer.php index f88d1637d66..86cf5f3090d 100644 --- a/src/Elasticsearch/Serializer/ItemNormalizer.php +++ b/src/Elasticsearch/Serializer/ItemNormalizer.php @@ -111,5 +111,3 @@ public function setSerializer(SerializerInterface $serializer) $this->decorated->setSerializer($serializer); } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\Bridge\Elasticsearch\Serializer\ItemNormalizer::class); diff --git a/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php b/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php index 8c469cfd87e..a408a1181ad 100644 --- a/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php +++ b/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php @@ -60,5 +60,3 @@ private function convertInnerFields(string $propertyName, bool $normalization, s return implode('.', $convertedProperties); } } - -class_alias(InnerFieldsNameConverter::class, \ApiPlatform\Core\Bridge\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter::class); diff --git a/src/Elasticsearch/Util/FieldDatatypeTrait.php b/src/Elasticsearch/Util/FieldDatatypeTrait.php index a944623d706..e5fec39bb45 100644 --- a/src/Elasticsearch/Util/FieldDatatypeTrait.php +++ b/src/Elasticsearch/Util/FieldDatatypeTrait.php @@ -104,5 +104,3 @@ private function getNestedFieldPath(string $resourceClass, string $property): ?s return null; } } - -class_alias(FieldDatatypeTrait::class, \ApiPlatform\Core\Bridge\Elasticsearch\Util\FieldDatatypeTrait::class); diff --git a/src/Exception/DeserializationException.php b/src/Exception/DeserializationException.php index 21e719cf410..37dfcb55772 100644 --- a/src/Exception/DeserializationException.php +++ b/src/Exception/DeserializationException.php @@ -24,5 +24,3 @@ class DeserializationException extends \Exception implements ExceptionInterface, SerializerExceptionInterface { } - -class_alias(DeserializationException::class, \ApiPlatform\Core\Exception\DeserializationException::class); diff --git a/src/Exception/FilterValidationException.php b/src/Exception/FilterValidationException.php index b350f14c9d9..4fe0cbb1c7f 100644 --- a/src/Exception/FilterValidationException.php +++ b/src/Exception/FilterValidationException.php @@ -34,5 +34,3 @@ public function __toString(): string return implode("\n", $this->constraintViolationList); } } - -class_alias(FilterValidationException::class, \ApiPlatform\Core\Exception\FilterValidationException::class); diff --git a/src/Exception/InvalidArgumentException.php b/src/Exception/InvalidArgumentException.php index f691a1e94c8..bddf0a57112 100644 --- a/src/Exception/InvalidArgumentException.php +++ b/src/Exception/InvalidArgumentException.php @@ -21,5 +21,3 @@ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } - -class_alias(InvalidArgumentException::class, \ApiPlatform\Core\Exception\InvalidArgumentException::class); diff --git a/src/Exception/InvalidIdentifierException.php b/src/Exception/InvalidIdentifierException.php index f7ae0c6d851..961aad89db1 100644 --- a/src/Exception/InvalidIdentifierException.php +++ b/src/Exception/InvalidIdentifierException.php @@ -21,5 +21,3 @@ final class InvalidIdentifierException extends \Exception implements ExceptionInterface { } - -class_alias(InvalidIdentifierException::class, \ApiPlatform\Core\Exception\InvalidIdentifierException::class); diff --git a/src/Exception/InvalidResourceException.php b/src/Exception/InvalidResourceException.php index 580ad5ac473..a69543355d7 100644 --- a/src/Exception/InvalidResourceException.php +++ b/src/Exception/InvalidResourceException.php @@ -21,5 +21,3 @@ class InvalidResourceException extends \Exception implements ExceptionInterface { } - -class_alias(InvalidResourceException::class, \ApiPlatform\Core\Exception\InvalidResourceException::class); diff --git a/src/Exception/InvalidValueException.php b/src/Exception/InvalidValueException.php index 74e93c00417..96b023fdbae 100644 --- a/src/Exception/InvalidValueException.php +++ b/src/Exception/InvalidValueException.php @@ -16,5 +16,3 @@ class InvalidValueException extends InvalidArgumentException { } - -class_alias(InvalidValueException::class, \ApiPlatform\Core\Exception\InvalidValueException::class); diff --git a/src/Exception/ItemNotFoundException.php b/src/Exception/ItemNotFoundException.php index 43c017fd364..a66f39965d8 100644 --- a/src/Exception/ItemNotFoundException.php +++ b/src/Exception/ItemNotFoundException.php @@ -21,5 +21,3 @@ class ItemNotFoundException extends InvalidArgumentException { } - -class_alias(ItemNotFoundException::class, \ApiPlatform\Core\Exception\ItemNotFoundException::class); diff --git a/src/Exception/PropertyNotFoundException.php b/src/Exception/PropertyNotFoundException.php index 80146c5ffce..44df7ee03ec 100644 --- a/src/Exception/PropertyNotFoundException.php +++ b/src/Exception/PropertyNotFoundException.php @@ -21,5 +21,3 @@ class PropertyNotFoundException extends \Exception implements ExceptionInterface { } - -class_alias(PropertyNotFoundException::class, \ApiPlatform\Core\Exception\PropertyNotFoundException::class); diff --git a/src/Exception/ResourceClassNotFoundException.php b/src/Exception/ResourceClassNotFoundException.php index a1ee01887ce..0a0f0eaa9c4 100644 --- a/src/Exception/ResourceClassNotFoundException.php +++ b/src/Exception/ResourceClassNotFoundException.php @@ -21,5 +21,3 @@ class ResourceClassNotFoundException extends \Exception implements ExceptionInterface { } - -class_alias(ResourceClassNotFoundException::class, \ApiPlatform\Core\Exception\ResourceClassNotFoundException::class); diff --git a/src/Exception/ResourceClassNotSupportedException.php b/src/Exception/ResourceClassNotSupportedException.php index b45fea4183f..9d291d1ae09 100644 --- a/src/Exception/ResourceClassNotSupportedException.php +++ b/src/Exception/ResourceClassNotSupportedException.php @@ -21,5 +21,3 @@ class ResourceClassNotSupportedException extends \Exception implements ExceptionInterface { } - -class_alias(ResourceClassNotSupportedException::class, \ApiPlatform\Core\Exception\ResourceClassNotSupportedException::class); diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php index ae09346244f..7eba6481b10 100644 --- a/src/Exception/RuntimeException.php +++ b/src/Exception/RuntimeException.php @@ -21,5 +21,3 @@ class RuntimeException extends \RuntimeException implements ExceptionInterface { } - -class_alias(RuntimeException::class, \ApiPlatform\Core\Exception\RuntimeException::class); diff --git a/src/GraphQl/Action/EntrypointAction.php b/src/GraphQl/Action/EntrypointAction.php index 6eb558a9883..ca03ed6a43f 100644 --- a/src/GraphQl/Action/EntrypointAction.php +++ b/src/GraphQl/Action/EntrypointAction.php @@ -221,5 +221,3 @@ private function decodeVariables(string $variables): array return $decoded; } } - -class_alias(EntrypointAction::class, \ApiPlatform\Core\GraphQl\Action\EntrypointAction::class); diff --git a/src/GraphQl/Action/GraphQlPlaygroundAction.php b/src/GraphQl/Action/GraphQlPlaygroundAction.php index 1c4650c9b13..7216ef7bb01 100644 --- a/src/GraphQl/Action/GraphQlPlaygroundAction.php +++ b/src/GraphQl/Action/GraphQlPlaygroundAction.php @@ -54,5 +54,3 @@ public function __invoke(Request $request): Response throw new BadRequestHttpException('GraphQL Playground is not enabled.'); } } - -class_alias(GraphQlPlaygroundAction::class, \ApiPlatform\Core\GraphQl\Action\GraphQlPlaygroundAction::class); diff --git a/src/GraphQl/Action/GraphiQlAction.php b/src/GraphQl/Action/GraphiQlAction.php index 0b548b99331..985edc615a8 100644 --- a/src/GraphQl/Action/GraphiQlAction.php +++ b/src/GraphQl/Action/GraphiQlAction.php @@ -54,5 +54,3 @@ public function __invoke(Request $request): Response throw new BadRequestHttpException('GraphiQL is not enabled.'); } } - -class_alias(GraphiQlAction::class, \ApiPlatform\Core\GraphQl\Action\GraphiQlAction::class); diff --git a/src/GraphQl/Error/ErrorHandler.php b/src/GraphQl/Error/ErrorHandler.php index dc04eb50954..9979ea118d5 100644 --- a/src/GraphQl/Error/ErrorHandler.php +++ b/src/GraphQl/Error/ErrorHandler.php @@ -28,5 +28,3 @@ public function __invoke(array $errors, callable $formatter): array return array_map($formatter, $errors); } } - -class_alias(ErrorHandler::class, \ApiPlatform\Core\GraphQl\Error\ErrorHandler::class); diff --git a/src/GraphQl/Executor.php b/src/GraphQl/Executor.php index f423d85edf5..d1b5f7736da 100644 --- a/src/GraphQl/Executor.php +++ b/src/GraphQl/Executor.php @@ -32,5 +32,3 @@ public function executeQuery(Schema $schema, $source, $rootValue = null, $contex return GraphQL::executeQuery($schema, $source, $rootValue, $context, $variableValues, $operationName, $fieldResolver, $validationRules); } } - -class_alias(Executor::class, \ApiPlatform\Core\GraphQl\Executor::class); diff --git a/src/GraphQl/Resolver/Util/IdentifierTrait.php b/src/GraphQl/Resolver/Util/IdentifierTrait.php index deb00fc0d67..8ec7c0c6d8d 100644 --- a/src/GraphQl/Resolver/Util/IdentifierTrait.php +++ b/src/GraphQl/Resolver/Util/IdentifierTrait.php @@ -33,5 +33,3 @@ private function getIdentifierFromContext(array $context): ?string return $args['id'] ?? null; } } - -class_alias(IdentifierTrait::class, \ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait::class); diff --git a/src/GraphQl/Serializer/ItemNormalizer.php b/src/GraphQl/Serializer/ItemNormalizer.php index 529d57b02eb..af94b85127c 100644 --- a/src/GraphQl/Serializer/ItemNormalizer.php +++ b/src/GraphQl/Serializer/ItemNormalizer.php @@ -15,9 +15,8 @@ use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface as LegacyIdentifiersExtractorInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\ItemNormalizer as BaseItemNormalizer; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; @@ -43,13 +42,13 @@ final class ItemNormalizer extends BaseItemNormalizer public const ITEM_IDENTIFIERS_KEY = '#itemIdentifiers'; /** - * @var IdentifiersExtractorInterface|LegacyIdentifiersExtractorInterface + * @var IdentifiersExtractorInterface */ private $identifiersExtractor; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $identifiersExtractor, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, ItemDataProviderInterface $itemDataProvider = null, bool $allowPlainIdentifiers = false, LoggerInterface $logger = null, iterable $dataTransformers = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, $identifiersExtractor, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, LoggerInterface $logger = null, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $itemDataProvider, $allowPlainIdentifiers, $logger ?: new NullLogger(), $dataTransformers, $resourceMetadataCollectionFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $logger ?: new NullLogger(), $resourceMetadataCollectionFactory, $resourceAccessChecker); $this->identifiersExtractor = $identifiersExtractor; } diff --git a/src/GraphQl/Type/Definition/IterableType.php b/src/GraphQl/Type/Definition/IterableType.php index 300b872978c..717af8b066f 100644 --- a/src/GraphQl/Type/Definition/IterableType.php +++ b/src/GraphQl/Type/Definition/IterableType.php @@ -148,5 +148,3 @@ private function parseIterableLiteral($valueNode) } } } - -class_alias(IterableType::class, \ApiPlatform\Core\GraphQl\Type\Definition\IterableType::class); diff --git a/src/GraphQl/Type/Definition/UploadType.php b/src/GraphQl/Type/Definition/UploadType.php index bfe3bac45cf..d0f90c351e2 100644 --- a/src/GraphQl/Type/Definition/UploadType.php +++ b/src/GraphQl/Type/Definition/UploadType.php @@ -89,5 +89,3 @@ public function parseValue($value): UploadedFile return $value; } } - -class_alias(UploadType::class, \ApiPlatform\Core\GraphQl\Type\Definition\UploadType::class); diff --git a/src/GraphQl/Type/TypeNotFoundException.php b/src/GraphQl/Type/TypeNotFoundException.php index 404c6d54cff..96cb3c26eab 100644 --- a/src/GraphQl/Type/TypeNotFoundException.php +++ b/src/GraphQl/Type/TypeNotFoundException.php @@ -39,5 +39,3 @@ public function getTypeId(): string return $this->typeId; } } - -class_alias(TypeNotFoundException::class, \ApiPlatform\Core\GraphQl\Type\TypeNotFoundException::class); diff --git a/src/GraphQl/Type/TypesContainer.php b/src/GraphQl/Type/TypesContainer.php index 9e53f295f8b..d389bd7cb76 100644 --- a/src/GraphQl/Type/TypesContainer.php +++ b/src/GraphQl/Type/TypesContainer.php @@ -60,5 +60,3 @@ public function has($id): bool return \array_key_exists($id, $this->graphqlTypes); } } - -class_alias(TypesContainer::class, \ApiPlatform\Core\GraphQl\Type\TypesContainer::class); diff --git a/src/GraphQl/Type/TypesFactory.php b/src/GraphQl/Type/TypesFactory.php index 57a6e1b30b8..64fd466e470 100644 --- a/src/GraphQl/Type/TypesFactory.php +++ b/src/GraphQl/Type/TypesFactory.php @@ -48,5 +48,3 @@ public function getTypes(): array return $types; } } - -class_alias(TypesFactory::class, \ApiPlatform\Core\GraphQl\Type\TypesFactory::class); diff --git a/src/Hal/JsonSchema/SchemaFactory.php b/src/Hal/JsonSchema/SchemaFactory.php index b49a9ba1bcd..2d6dddf1473 100644 --- a/src/Hal/JsonSchema/SchemaFactory.php +++ b/src/Hal/JsonSchema/SchemaFactory.php @@ -135,5 +135,3 @@ public function addDistinctFormat(string $format): void } } } - -class_alias(SchemaFactory::class, \ApiPlatform\Core\Hal\JsonSchema\SchemaFactory::class); diff --git a/src/Hal/Serializer/CollectionNormalizer.php b/src/Hal/Serializer/CollectionNormalizer.php index 7b420645ab4..b1688595dc6 100644 --- a/src/Hal/Serializer/CollectionNormalizer.php +++ b/src/Hal/Serializer/CollectionNormalizer.php @@ -105,5 +105,3 @@ protected function getItemsData($object, string $format = null, array $context = return $data; } } - -class_alias(CollectionNormalizer::class, \ApiPlatform\Core\Hal\Serializer\CollectionNormalizer::class); diff --git a/src/Hal/Serializer/EntrypointNormalizer.php b/src/Hal/Serializer/EntrypointNormalizer.php index ffa09cce83b..391516df21a 100644 --- a/src/Hal/Serializer/EntrypointNormalizer.php +++ b/src/Hal/Serializer/EntrypointNormalizer.php @@ -118,5 +118,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(EntrypointNormalizer::class, \ApiPlatform\Core\Hal\Serializer\EntrypointNormalizer::class); diff --git a/src/Hal/Serializer/ItemNormalizer.php b/src/Hal/Serializer/ItemNormalizer.php index bce69d7092b..444dbe26e54 100644 --- a/src/Hal/Serializer/ItemNormalizer.php +++ b/src/Hal/Serializer/ItemNormalizer.php @@ -13,9 +13,6 @@ namespace ApiPlatform\Hal\Serializer; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Serializer\AbstractItemNormalizer; use ApiPlatform\Serializer\CacheKeyTrait; use ApiPlatform\Serializer\ContextTrait; @@ -66,7 +63,7 @@ public function normalize($object, $format = null, array $context = []) $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); $context = $this->initContext($resourceClass, $context); - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($object) : $this->iriConverter->getIriFromResource($object); + $iri = $this->iriConverter->getIriFromResource($object); $context['iri'] = $iri; $context['api_normalize'] = true; @@ -141,11 +138,10 @@ private function getComponents($object, ?string $format, array $context): array ]; foreach ($attributes as $attribute) { - /** @var ApiProperty|PropertyMetadata */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $options); // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : ($propertyMetadata->getBuiltinTypes()[0] ?? null); + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; $isOne = $isMany = false; if (null !== $type) { @@ -278,5 +274,3 @@ private function isMaxDepthReached(array $attributesMetadata, string $class, str return false; } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\Hal\Serializer\ItemNormalizer::class); diff --git a/src/Hal/Serializer/ObjectNormalizer.php b/src/Hal/Serializer/ObjectNormalizer.php index 4130716aba3..a05c3561169 100644 --- a/src/Hal/Serializer/ObjectNormalizer.php +++ b/src/Hal/Serializer/ObjectNormalizer.php @@ -110,5 +110,3 @@ public function denormalize($data, $class, $format = null, array $context = []) throw new LogicException(sprintf('%s is a read-only format.', self::FORMAT)); } } - -class_alias(ObjectNormalizer::class, \ApiPlatform\Core\Hal\Serializer\ObjectNormalizer::class); diff --git a/src/HttpCache/EventListener/AddHeadersListener.php b/src/HttpCache/EventListener/AddHeadersListener.php index 34a0a64a121..fa130d7caed 100644 --- a/src/HttpCache/EventListener/AddHeadersListener.php +++ b/src/HttpCache/EventListener/AddHeadersListener.php @@ -13,7 +13,6 @@ namespace ApiPlatform\HttpCache\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Util\RequestAttributesExtractor; use Symfony\Component\HttpKernel\Event\ResponseEvent; @@ -31,18 +30,16 @@ final class AddHeadersListener private $sharedMaxAge; private $vary; private $public; - private $resourceMetadataFactory; private $staleWhileRevalidate; private $staleIfError; - public function __construct(bool $etag = false, int $maxAge = null, int $sharedMaxAge = null, array $vary = null, bool $public = null, ResourceMetadataFactoryInterface $resourceMetadataFactory = null, int $staleWhileRevalidate = null, int $staleIfError = null) + public function __construct(bool $etag = false, int $maxAge = null, int $sharedMaxAge = null, array $vary = null, bool $public = null, int $staleWhileRevalidate = null, int $staleIfError = null) { $this->etag = $etag; $this->maxAge = $maxAge; $this->sharedMaxAge = $sharedMaxAge; $this->vary = $vary; $this->public = $public; - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->staleWhileRevalidate = $staleWhileRevalidate; $this->staleIfError = $staleIfError; } @@ -65,14 +62,7 @@ public function onKernelResponse(ResponseEvent $event): void return; } - $resourceCacheHeaders = []; - - if ($this->resourceMetadataFactory) { - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - $resourceCacheHeaders = $resourceMetadata->getOperationAttribute($attributes, 'cache_headers', [], true); - } else { - $resourceCacheHeaders = $attributes['cache_headers'] ?? []; - } + $resourceCacheHeaders = $attributes['cache_headers'] ?? []; if ($this->etag && !$response->getEtag()) { $response->setEtag(md5((string) $response->getContent())); @@ -107,5 +97,3 @@ public function onKernelResponse(ResponseEvent $event): void } } } - -class_alias(AddHeadersListener::class, \ApiPlatform\Core\HttpCache\EventListener\AddHeadersListener::class); diff --git a/src/HttpCache/EventListener/AddTagsListener.php b/src/HttpCache/EventListener/AddTagsListener.php index f52f691c1ac..4879596c2fe 100644 --- a/src/HttpCache/EventListener/AddTagsListener.php +++ b/src/HttpCache/EventListener/AddTagsListener.php @@ -47,12 +47,7 @@ final class AddTagsListener private $iriConverter; private $purger; - /** - * @param LegacyPurgerInterface|PurgerInterface|null $purger - * @param LegacyIriConverterInterface|IriConverterInterface $iriConverter - * @param mixed|null $purger - */ - public function __construct($iriConverter, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, $purger = null) + public function __construct(IriConverterInterface $iriConverter, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ?PurgerInterface $purger = null) { $this->iriConverter = $iriConverter; $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; @@ -80,12 +75,7 @@ public function onKernelResponse(ResponseEvent $event): void if (isset($attributes['collection_operation_name']) || ($attributes['subresource_context']['collection'] ?? false) || ($operation && $operation instanceof CollectionOperationInterface)) { // Allows to purge collections $uriVariables = $this->getOperationUriVariables($operation, $request->attributes->all(), $attributes['resource_class']); - - if ($this->iriConverter instanceof LegacyIriConverterInterface) { - $iri = $this->iriConverter->getIriFromResourceClass($attributes['resource_class'], UrlGeneratorInterface::ABS_PATH); - } else { - $iri = $this->iriConverter->getIriFromResource($attributes['resource_class'], UrlGeneratorInterface::ABS_PATH, $operation, ['uri_variables' => $uriVariables]); - } + $iri = $this->iriConverter->getIriFromResource($attributes['resource_class'], UrlGeneratorInterface::ABS_PATH, $operation, ['uri_variables' => $uriVariables]); $resources[$iri] = $iri; } @@ -94,13 +84,6 @@ public function onKernelResponse(ResponseEvent $event): void return; } - if ($this->purger instanceof LegacyPurgerInterface || !$this->purger) { - $response->headers->set('Cache-Tags', implode(',', $resources)); - trigger_deprecation('api-platform/core', '2.7', sprintf('The interface "%s" is deprecated, use "%s" instead.', LegacyPurgerInterface::class, PurgerInterface::class)); - - return; - } - $headers = $this->purger->getResponseHeaders($resources); foreach ($headers as $key => $value) { @@ -108,5 +91,3 @@ public function onKernelResponse(ResponseEvent $event): void } } } - -class_alias(AddTagsListener::class, \ApiPlatform\Core\HttpCache\EventListener\AddTagsListener::class); diff --git a/src/HttpCache/VarnishPurger.php b/src/HttpCache/VarnishPurger.php index 23fb74d99e7..f35abec27e0 100644 --- a/src/HttpCache/VarnishPurger.php +++ b/src/HttpCache/VarnishPurger.php @@ -139,5 +139,3 @@ private function chunkRegexParts(array $parts): iterable yield from $this->chunkRegexParts($nextParts); } } - -class_alias(VarnishPurger::class, \ApiPlatform\Core\HttpCache\VarnishPurger::class); diff --git a/src/HttpCache/VarnishXKeyPurger.php b/src/HttpCache/VarnishXKeyPurger.php index 1b6e0ca1249..32f7523af0f 100644 --- a/src/HttpCache/VarnishXKeyPurger.php +++ b/src/HttpCache/VarnishXKeyPurger.php @@ -112,5 +112,3 @@ private function chunkKeys(array $keys): iterable } } } - -class_alias(VarnishXKeyPurger::class, \ApiPlatform\Core\HttpCache\VarnishXKeyPurger::class); diff --git a/src/Hydra/EventListener/AddLinkHeaderListener.php b/src/Hydra/EventListener/AddLinkHeaderListener.php index 18b100a3873..ecf15d120c2 100644 --- a/src/Hydra/EventListener/AddLinkHeaderListener.php +++ b/src/Hydra/EventListener/AddLinkHeaderListener.php @@ -58,5 +58,3 @@ public function onKernelResponse(ResponseEvent $event): void $request->attributes->set('_links', $linkProvider->withLink($link)); } } - -class_alias(AddLinkHeaderListener::class, \ApiPlatform\Core\Hydra\EventListener\AddLinkHeaderListener::class); diff --git a/src/Hydra/JsonSchema/SchemaFactory.php b/src/Hydra/JsonSchema/SchemaFactory.php index d0e0aa6b269..15188ff6102 100644 --- a/src/Hydra/JsonSchema/SchemaFactory.php +++ b/src/Hydra/JsonSchema/SchemaFactory.php @@ -187,5 +187,3 @@ public function addDistinctFormat(string $format): void } } } - -class_alias(SchemaFactory::class, \ApiPlatform\Core\Hydra\JsonSchema\SchemaFactory::class); diff --git a/src/Hydra/Serializer/CollectionFiltersNormalizer.php b/src/Hydra/Serializer/CollectionFiltersNormalizer.php index 9c5c7135909..43c3453e8e5 100644 --- a/src/Hydra/Serializer/CollectionFiltersNormalizer.php +++ b/src/Hydra/Serializer/CollectionFiltersNormalizer.php @@ -147,5 +147,3 @@ private function getSearch(string $resourceClass, array $parts, array $filters): return ['@type' => 'hydra:IriTemplate', 'hydra:template' => sprintf('%s{?%s}', $parts['path'], implode(',', $variables)), 'hydra:variableRepresentation' => 'BasicRepresentation', 'hydra:mapping' => $mapping]; } } - -class_alias(CollectionFiltersNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\CollectionFiltersNormalizer::class); diff --git a/src/Hydra/Serializer/CollectionNormalizer.php b/src/Hydra/Serializer/CollectionNormalizer.php index f2f49304b56..36b335cb821 100644 --- a/src/Hydra/Serializer/CollectionNormalizer.php +++ b/src/Hydra/Serializer/CollectionNormalizer.php @@ -136,5 +136,3 @@ private function normalizeRawCollection(iterable $object, ?string $format, array return $data; } } - -class_alias(CollectionNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\CollectionNormalizer::class); diff --git a/src/Hydra/Serializer/ConstraintViolationListNormalizer.php b/src/Hydra/Serializer/ConstraintViolationListNormalizer.php index c988f0fd734..6fd05d74ba7 100644 --- a/src/Hydra/Serializer/ConstraintViolationListNormalizer.php +++ b/src/Hydra/Serializer/ConstraintViolationListNormalizer.php @@ -53,5 +53,3 @@ public function normalize($object, $format = null, array $context = []) ]; } } - -class_alias(ConstraintViolationListNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\ConstraintViolationListNormalizer::class); diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index f662b7d9c9a..3f3b94199c9 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -720,5 +720,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(DocumentationNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\DocumentationNormalizer::class); diff --git a/src/Hydra/Serializer/EntrypointNormalizer.php b/src/Hydra/Serializer/EntrypointNormalizer.php index cc8aafacbee..12b738b21d5 100644 --- a/src/Hydra/Serializer/EntrypointNormalizer.php +++ b/src/Hydra/Serializer/EntrypointNormalizer.php @@ -123,5 +123,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(EntrypointNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\EntrypointNormalizer::class); diff --git a/src/Hydra/Serializer/ErrorNormalizer.php b/src/Hydra/Serializer/ErrorNormalizer.php index b7beef065ae..d63b7f2b550 100644 --- a/src/Hydra/Serializer/ErrorNormalizer.php +++ b/src/Hydra/Serializer/ErrorNormalizer.php @@ -81,5 +81,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(ErrorNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\ErrorNormalizer::class); diff --git a/src/Hydra/Serializer/PartialCollectionViewNormalizer.php b/src/Hydra/Serializer/PartialCollectionViewNormalizer.php index 7cbe5d45ca5..f5c902e843b 100644 --- a/src/Hydra/Serializer/PartialCollectionViewNormalizer.php +++ b/src/Hydra/Serializer/PartialCollectionViewNormalizer.php @@ -195,5 +195,3 @@ private function populateDataWithPagination(array $data, array $parsed, ?float $ return $data; } } - -class_alias(PartialCollectionViewNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\PartialCollectionViewNormalizer::class); diff --git a/src/JsonApi/Serializer/CollectionNormalizer.php b/src/JsonApi/Serializer/CollectionNormalizer.php index 38dd3044f68..34a727befd2 100644 --- a/src/JsonApi/Serializer/CollectionNormalizer.php +++ b/src/JsonApi/Serializer/CollectionNormalizer.php @@ -117,5 +117,3 @@ protected function getItemsData($object, string $format = null, array $context = return $data; } } - -class_alias(CollectionNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\CollectionNormalizer::class); diff --git a/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php b/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php index 899bc471e3b..d93514f146b 100644 --- a/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php +++ b/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php @@ -111,5 +111,3 @@ private function getSourcePointerFromViolation(ConstraintViolationInterface $vio return "data/attributes/$fieldName"; } } - -class_alias(ConstraintViolationListNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\ConstraintViolationListNormalizer::class); diff --git a/src/JsonApi/Serializer/EntrypointNormalizer.php b/src/JsonApi/Serializer/EntrypointNormalizer.php index a385107ef40..f0e2cd76ae6 100644 --- a/src/JsonApi/Serializer/EntrypointNormalizer.php +++ b/src/JsonApi/Serializer/EntrypointNormalizer.php @@ -121,5 +121,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(EntrypointNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\EntrypointNormalizer::class); diff --git a/src/JsonApi/Serializer/ErrorNormalizer.php b/src/JsonApi/Serializer/ErrorNormalizer.php index e856f660081..316a6b62620 100644 --- a/src/JsonApi/Serializer/ErrorNormalizer.php +++ b/src/JsonApi/Serializer/ErrorNormalizer.php @@ -82,5 +82,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(ErrorNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\ErrorNormalizer::class); diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index 48cad34d2b9..c32c49131ee 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -14,13 +14,9 @@ namespace ApiPlatform\JsonApi\Serializer; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Serializer\AbstractItemNormalizer; use ApiPlatform\Serializer\CacheKeyTrait; use ApiPlatform\Serializer\ContextTrait; @@ -52,9 +48,9 @@ final class ItemNormalizer extends AbstractItemNormalizer private $componentsCache = []; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ?PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter, $resourceMetadataFactory, array $defaultContext = [], iterable $dataTransformers = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ?PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter, $resourceMetadataFactory, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, null, null, false, $defaultContext, $dataTransformers, $resourceMetadataFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, null, $defaultContext, $resourceMetadataFactory, $resourceAccessChecker); } /** @@ -82,7 +78,7 @@ public function normalize($object, $format = null, array $context = []) $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); $context = $this->initContext($resourceClass, $context); - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($object) : $this->iriConverter->getIriFromResource($object); + $iri = $this->iriConverter->getIriFromResource($object); $context['iri'] = $iri; $context['api_normalize'] = true; @@ -146,10 +142,7 @@ public function denormalize($data, $class, $format = null, array $context = []) throw new NotNormalizableValueException('Update is not allowed for this operation.'); } - $context[self::OBJECT_TO_POPULATE] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri( - $data['data']['id'], - $context + ['fetch_data' => false] - ) : $this->iriConverter->getResourceFromIri( + $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri( $data['data']['id'], $context + ['fetch_data' => false] ); @@ -202,7 +195,7 @@ protected function denormalizeRelation(string $attributeName, $propertyMetadata, } try { - return $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($value['id'], $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($value['id'], $context + ['fetch_data' => true]); + return $this->iriConverter->getResourceFromIri($value['id'], $context + ['fetch_data' => true]); } catch (ItemNotFoundException $e) { throw new RuntimeException($e->getMessage(), $e->getCode(), $e); } @@ -218,7 +211,7 @@ protected function denormalizeRelation(string $attributeName, $propertyMetadata, protected function normalizeRelation($propertyMetadata, $relatedObject, string $resourceClass, ?string $format, array $context) { if (null !== $relatedObject) { - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($relatedObject) : $this->iriConverter->getIriFromResource($relatedObject); + $iri = $this->iriConverter->getIriFromResource($relatedObject); $context['iri'] = $iri; if (isset($context['resources'])) { @@ -281,13 +274,12 @@ private function getComponents($object, ?string $format, array $context): array ]; foreach ($attributes as $attribute) { - /** @var ApiProperty|PropertyMetadata */ $propertyMetadata = $this ->propertyMetadataFactory ->create($context['resource_class'], $attribute, $options); // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : ($propertyMetadata->getBuiltinTypes()[0] ?? null); + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; $isOne = $isMany = false; if (null !== $type) { @@ -463,18 +455,10 @@ private function getIncludedNestedResources(string $relationshipName, array $con }, $filtered); } - // TODO: 3.0 remove private function getResourceShortName(string $resourceClass): string { - /** @var ResourceMetadata|ResourceMetadataCollection */ $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if ($resourceMetadata instanceof ResourceMetadata) { - return $resourceMetadata->getShortName(); - } - return $resourceMetadata->getOperation()->getShortName(); } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\ItemNormalizer::class); diff --git a/src/JsonApi/Serializer/ObjectNormalizer.php b/src/JsonApi/Serializer/ObjectNormalizer.php index 5b017e5d7fc..6c7e0cf5331 100644 --- a/src/JsonApi/Serializer/ObjectNormalizer.php +++ b/src/JsonApi/Serializer/ObjectNormalizer.php @@ -127,5 +127,3 @@ private function getResourceShortName(string $resourceClass): string return $resourceMetadata->getOperation()->getShortName(); } } - -class_alias(ObjectNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\ObjectNormalizer::class); diff --git a/src/JsonApi/Serializer/ReservedAttributeNameConverter.php b/src/JsonApi/Serializer/ReservedAttributeNameConverter.php index 402b4402dad..750d6a76635 100644 --- a/src/JsonApi/Serializer/ReservedAttributeNameConverter.php +++ b/src/JsonApi/Serializer/ReservedAttributeNameConverter.php @@ -70,5 +70,3 @@ public function denormalize($propertyName, string $class = null, string $format return $propertyName; } } - -class_alias(ReservedAttributeNameConverter::class, \ApiPlatform\Core\JsonApi\Serializer\ReservedAttributeNameConverter::class); diff --git a/src/JsonLd/Action/ContextAction.php b/src/JsonLd/Action/ContextAction.php index 593b87e8270..bbb21fa781a 100644 --- a/src/JsonLd/Action/ContextAction.php +++ b/src/JsonLd/Action/ContextAction.php @@ -87,5 +87,3 @@ public function __invoke(string $shortName): array throw new NotFoundHttpException(); } } - -class_alias(ContextAction::class, \ApiPlatform\Core\JsonLd\Action\ContextAction::class); diff --git a/src/JsonLd/ContextBuilder.php b/src/JsonLd/ContextBuilder.php index ab6442c5b29..5b0776c2615 100644 --- a/src/JsonLd/ContextBuilder.php +++ b/src/JsonLd/ContextBuilder.php @@ -256,5 +256,3 @@ private function getResourceContextWithShortname(string $resourceClass, int $ref return $context; } } - -class_alias(ContextBuilder::class, \ApiPlatform\Core\JsonLd\ContextBuilder::class); diff --git a/src/JsonLd/Serializer/ItemNormalizer.php b/src/JsonLd/Serializer/ItemNormalizer.php index cc487ac271c..7fd4828fcc4 100644 --- a/src/JsonLd/Serializer/ItemNormalizer.php +++ b/src/JsonLd/Serializer/ItemNormalizer.php @@ -16,11 +16,11 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\HttpOperation; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\AbstractItemNormalizer; use ApiPlatform\Serializer\ContextTrait; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; @@ -46,14 +46,10 @@ final class ItemNormalizer extends AbstractItemNormalizer private $contextBuilder; - public function __construct($resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ContextBuilderInterface $contextBuilder, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], iterable $dataTransformers = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ContextBuilderInterface $contextBuilder, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) { parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, null, false, $defaultContext, $dataTransformers, $resourceMetadataFactory, $resourceAccessChecker); - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } - $this->contextBuilder = $contextBuilder; } @@ -90,12 +86,7 @@ public function normalize($object, $format = null, array $context = []) unset($context['operation'], $context['operation_name']); } - if ($this->iriConverter instanceof LegacyIriConverterInterface) { - $iri = $this->iriConverter->getIriFromItem($object); - } else { - $iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context); - } - + $iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context); $context['iri'] = $iri; $metadata['@id'] = $iri; $context['api_normalize'] = true; @@ -105,18 +96,12 @@ public function normalize($object, $format = null, array $context = []) return $data; } - // TODO: remove in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $metadata['@type'] = $resourceMetadata->getIri() ?: $resourceMetadata->getShortName(); - } elseif ($this->resourceMetadataFactory) { - $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation(); - $types = $operation instanceof HttpOperation ? $operation->getTypes() : null; - if (null === $types) { - $types = [$operation->getShortName()]; - } - $metadata['@type'] = 1 === \count($types) ? $types[0] : $types; + $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation(); + $types = $operation instanceof HttpOperation ? $operation->getTypes() : null; + if (null === $types) { + $types = [$operation->getShortName()]; } + $metadata['@type'] = 1 === \count($types) ? $types[0] : $types; return $metadata + $data; } @@ -144,11 +129,9 @@ public function denormalize($data, $class, $format = null, array $context = []) throw new NotNormalizableValueException('Update is not allowed for this operation.'); } - $context[self::OBJECT_TO_POPULATE] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($data['@id'], $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($data['@id'], $context + ['fetch_data' => true]); + $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri($data['@id'], $context + ['fetch_data' => true]); } return parent::denormalize($data, $class, $format, $context); } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\JsonLd\Serializer\ItemNormalizer::class); diff --git a/src/JsonLd/Serializer/JsonLdContextTrait.php b/src/JsonLd/Serializer/JsonLdContextTrait.php index 296c6476143..fcbe98206c2 100644 --- a/src/JsonLd/Serializer/JsonLdContextTrait.php +++ b/src/JsonLd/Serializer/JsonLdContextTrait.php @@ -59,5 +59,3 @@ private function createJsonLdContext(AnonymousContextBuilderInterface $contextBu return $contextBuilder->getAnonymousResourceContext($object, ($context['output'] ?? []) + ['api_resource' => $context['api_resource'] ?? null]); } } - -class_alias(JsonLdContextTrait::class, \ApiPlatform\Core\JsonLd\Serializer\JsonLdContextTrait::class); diff --git a/src/JsonLd/Serializer/ObjectNormalizer.php b/src/JsonLd/Serializer/ObjectNormalizer.php index 3bfe72d97f6..93b064ed261 100644 --- a/src/JsonLd/Serializer/ObjectNormalizer.php +++ b/src/JsonLd/Serializer/ObjectNormalizer.php @@ -104,5 +104,3 @@ public function normalize($object, $format = null, array $context = []) return $metadata + $data; } } - -class_alias(ObjectNormalizer::class, \ApiPlatform\Core\JsonLd\Serializer\ObjectNormalizer::class); diff --git a/src/JsonSchema/Command/JsonSchemaGenerateCommand.php b/src/JsonSchema/Command/JsonSchemaGenerateCommand.php index 10aaedf29c6..ed369a3c728 100644 --- a/src/JsonSchema/Command/JsonSchemaGenerateCommand.php +++ b/src/JsonSchema/Command/JsonSchemaGenerateCommand.php @@ -115,5 +115,3 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } } - -class_alias(JsonSchemaGenerateCommand::class, \ApiPlatform\Core\JsonSchema\Command\JsonSchemaGenerateCommand::class); diff --git a/src/JsonSchema/Schema.php b/src/JsonSchema/Schema.php index 1a8f48bf795..4a840bd0d38 100644 --- a/src/JsonSchema/Schema.php +++ b/src/JsonSchema/Schema.php @@ -133,5 +133,3 @@ private function removeDefinitionKeyPrefix(string $definitionKey): string return substr($definitionKey, $prefix); } } - -class_alias(Schema::class, \ApiPlatform\Core\JsonSchema\Schema::class); diff --git a/src/JsonSchema/SchemaFactory.php b/src/JsonSchema/SchemaFactory.php index 535fada3564..1c67bac0a70 100644 --- a/src/JsonSchema/SchemaFactory.php +++ b/src/JsonSchema/SchemaFactory.php @@ -438,5 +438,3 @@ private function getFactoryOptions(array $serializerContext, array $validationGr return $options; } } - -class_alias(SchemaFactory::class, \ApiPlatform\Core\JsonSchema\SchemaFactory::class); diff --git a/src/JsonSchema/TypeFactory.php b/src/JsonSchema/TypeFactory.php index b732726ad62..3bf200ae72b 100644 --- a/src/JsonSchema/TypeFactory.php +++ b/src/JsonSchema/TypeFactory.php @@ -195,5 +195,3 @@ private function addNullabilityToTypeDefinition(array $jsonSchema, Type $type, ? return array_merge($jsonSchema, ['nullable' => true]); } } - -class_alias(TypeFactory::class, \ApiPlatform\Core\JsonSchema\TypeFactory::class); diff --git a/src/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php b/src/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php index 02aabedee40..58884ea4821 100644 --- a/src/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php +++ b/src/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php @@ -48,5 +48,3 @@ public function create(string $resourceClass, array $options = []): PropertyName }); } } - -class_alias(CachedPropertyNameCollectionFactory::class, \ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class); diff --git a/src/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php b/src/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php index 6e9708421d4..27df8c93881 100644 --- a/src/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php +++ b/src/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php @@ -75,5 +75,3 @@ public function create(string $resourceClass, array $options = []): PropertyName return new PropertyNameCollection(array_values($propertyNames)); } } - -class_alias(ExtractorPropertyNameCollectionFactory::class, \ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class); diff --git a/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php b/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php index bad805cc564..02c16235a7e 100644 --- a/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php +++ b/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php @@ -42,5 +42,3 @@ public function create(string $resourceClass, array $options = []): PropertyName return new PropertyNameCollection($properties ?? []); } } - -class_alias(PropertyInfoPropertyNameCollectionFactory::class, \ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory::class); diff --git a/src/Metadata/Property/PropertyNameCollection.php b/src/Metadata/Property/PropertyNameCollection.php index de52f141b7a..c72dec5d879 100644 --- a/src/Metadata/Property/PropertyNameCollection.php +++ b/src/Metadata/Property/PropertyNameCollection.php @@ -51,5 +51,3 @@ public function count(): int return \count($this->properties); } } - -class_alias(PropertyNameCollection::class, \ApiPlatform\Core\Metadata\Property\PropertyNameCollection::class); diff --git a/src/Metadata/Resource/ResourceMetadataCollection.php b/src/Metadata/Resource/ResourceMetadataCollection.php index 383c12a47d2..aead554dc68 100644 --- a/src/Metadata/Resource/ResourceMetadataCollection.php +++ b/src/Metadata/Resource/ResourceMetadataCollection.php @@ -77,6 +77,11 @@ public function getOperation(?string $operationName = null, bool $forceCollectio $it->next(); } + // Idea: + // if ($metadata) { + // return (new class extends HttpOperation {})->withResource($metadata); + // } + $this->handleNotFound($operationName, $metadata); } diff --git a/src/OpenApi/Factory/OpenApiFactory.php b/src/OpenApi/Factory/OpenApiFactory.php index 6e3fb82bcbe..0e5cf048abd 100644 --- a/src/OpenApi/Factory/OpenApiFactory.php +++ b/src/OpenApi/Factory/OpenApiFactory.php @@ -14,8 +14,6 @@ namespace ApiPlatform\OpenApi\Factory; use ApiPlatform\Api\FilterLocatorTrait; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\JsonSchema\TypeFactoryInterface; @@ -33,7 +31,6 @@ use ApiPlatform\OpenApi\Model\ExternalDocumentation; use ApiPlatform\OpenApi\OpenApi; use ApiPlatform\OpenApi\Options; -use ApiPlatform\PathResolver\OperationPathResolverInterface; use ApiPlatform\State\Pagination\PaginationOptions; use Psr\Container\ContainerInterface; use Symfony\Component\PropertyInfo\Type; @@ -51,15 +48,8 @@ final class OpenApiFactory implements OpenApiFactoryInterface private $resourceNameCollectionFactory; private $resourceMetadataFactory; - /** - * @var LegacyPropertyNameCollectionFactoryInterface|PropertyNameCollectionFactoryInterface - */ private $propertyNameCollectionFactory; - /** - * @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface - */ private $propertyMetadataFactory; - private $operationPathResolver; private $formats; private $jsonSchemaFactory; private $jsonSchemaTypeFactory; @@ -68,7 +58,7 @@ final class OpenApiFactory implements OpenApiFactoryInterface private $router; private $routeCollection; - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, SchemaFactoryInterface $jsonSchemaFactory, TypeFactoryInterface $jsonSchemaTypeFactory, OperationPathResolverInterface $operationPathResolver, ContainerInterface $filterLocator, array $formats = [], Options $openApiOptions = null, PaginationOptions $paginationOptions = null, RouterInterface $router = null) + public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, SchemaFactoryInterface $jsonSchemaFactory, TypeFactoryInterface $jsonSchemaTypeFactory, ContainerInterface $filterLocator, array $formats = [], Options $openApiOptions = null, PaginationOptions $paginationOptions = null, RouterInterface $router = null) { $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; $this->jsonSchemaFactory = $jsonSchemaFactory; @@ -78,7 +68,6 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName $this->resourceMetadataFactory = $resourceMetadataFactory; $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->operationPathResolver = $operationPathResolver; $this->openApiOptions = $openApiOptions ?: new Options('API Platform'); $this->paginationOptions = $paginationOptions ?: new PaginationOptions(); $this->router = $router; diff --git a/src/OpenApi/Model/Components.php b/src/OpenApi/Model/Components.php index 698ad5f752e..681996bccb0 100644 --- a/src/OpenApi/Model/Components.php +++ b/src/OpenApi/Model/Components.php @@ -176,5 +176,3 @@ public function withPathItems(\ArrayObject $pathItems): self return $clone; } } - -class_alias(Components::class, \ApiPlatform\Core\OpenApi\Model\Components::class); diff --git a/src/OpenApi/Model/Contact.php b/src/OpenApi/Model/Contact.php index 3f008a75e14..81437ef0081 100644 --- a/src/OpenApi/Model/Contact.php +++ b/src/OpenApi/Model/Contact.php @@ -67,5 +67,3 @@ public function withEmail(?string $email): self return $clone; } } - -class_alias(Contact::class, \ApiPlatform\Core\OpenApi\Model\Contact::class); diff --git a/src/OpenApi/Model/Encoding.php b/src/OpenApi/Model/Encoding.php index 8ab44514058..8b83f4c71ba 100644 --- a/src/OpenApi/Model/Encoding.php +++ b/src/OpenApi/Model/Encoding.php @@ -107,5 +107,3 @@ public function withAllowReserved(bool $allowReserved): self return $clone; } } - -class_alias(Encoding::class, \ApiPlatform\Core\OpenApi\Model\Encoding::class); diff --git a/src/OpenApi/Model/ExtensionTrait.php b/src/OpenApi/Model/ExtensionTrait.php index 97724a0ae83..0033241e373 100644 --- a/src/OpenApi/Model/ExtensionTrait.php +++ b/src/OpenApi/Model/ExtensionTrait.php @@ -34,5 +34,3 @@ public function getExtensionProperties(): array return $this->extensionProperties; } } - -class_alias(ExtensionTrait::class, \ApiPlatform\Core\OpenApi\Model\ExtensionTrait::class); diff --git a/src/OpenApi/Model/ExternalDocumentation.php b/src/OpenApi/Model/ExternalDocumentation.php index 83153e42918..5c0c5b97d12 100644 --- a/src/OpenApi/Model/ExternalDocumentation.php +++ b/src/OpenApi/Model/ExternalDocumentation.php @@ -52,5 +52,3 @@ public function withUrl(string $url): self return $clone; } } - -class_alias(ExternalDocumentation::class, \ApiPlatform\Core\OpenApi\Model\ExternalDocumentation::class); diff --git a/src/OpenApi/Model/Info.php b/src/OpenApi/Model/Info.php index 947e3e39cef..aab2a0e4d65 100644 --- a/src/OpenApi/Model/Info.php +++ b/src/OpenApi/Model/Info.php @@ -127,5 +127,3 @@ public function withSummary(string $summary): self return $clone; } } - -class_alias(Info::class, \ApiPlatform\Core\OpenApi\Model\Info::class); diff --git a/src/OpenApi/Model/License.php b/src/OpenApi/Model/License.php index f856d603bb9..b103fc7fa11 100644 --- a/src/OpenApi/Model/License.php +++ b/src/OpenApi/Model/License.php @@ -67,5 +67,3 @@ public function withIdentifier(?string $identifier): self return $clone; } } - -class_alias(License::class, \ApiPlatform\Core\OpenApi\Model\License::class); diff --git a/src/OpenApi/Model/Link.php b/src/OpenApi/Model/Link.php index 9021e3e10c2..edd7180d221 100644 --- a/src/OpenApi/Model/Link.php +++ b/src/OpenApi/Model/Link.php @@ -97,5 +97,3 @@ public function withServer(Server $server): self return $clone; } } - -class_alias(Link::class, \ApiPlatform\Core\OpenApi\Model\Link::class); diff --git a/src/OpenApi/Model/MediaType.php b/src/OpenApi/Model/MediaType.php index b982360ef13..ae97fec3583 100644 --- a/src/OpenApi/Model/MediaType.php +++ b/src/OpenApi/Model/MediaType.php @@ -82,5 +82,3 @@ public function withEncoding(Encoding $encoding): self return $clone; } } - -class_alias(MediaType::class, \ApiPlatform\Core\OpenApi\Model\MediaType::class); diff --git a/src/OpenApi/Model/OAuthFlow.php b/src/OpenApi/Model/OAuthFlow.php index 884bbfe96f8..e8e6b35c1f6 100644 --- a/src/OpenApi/Model/OAuthFlow.php +++ b/src/OpenApi/Model/OAuthFlow.php @@ -82,5 +82,3 @@ public function withScopes(\ArrayObject $scopes): self return $clone; } } - -class_alias(OAuthFlow::class, \ApiPlatform\Core\OpenApi\Model\OAuthFlow::class); diff --git a/src/OpenApi/Model/OAuthFlows.php b/src/OpenApi/Model/OAuthFlows.php index f68e678ceea..0e0cc02db5c 100644 --- a/src/OpenApi/Model/OAuthFlows.php +++ b/src/OpenApi/Model/OAuthFlows.php @@ -82,5 +82,3 @@ public function withAuthorizationCode(OAuthFlow $authorizationCode): self return $clone; } } - -class_alias(OAuthFlows::class, \ApiPlatform\Core\OpenApi\Model\OAuthFlows::class); diff --git a/src/OpenApi/Model/Operation.php b/src/OpenApi/Model/Operation.php index e16bdf3d99b..d829f1d7a01 100644 --- a/src/OpenApi/Model/Operation.php +++ b/src/OpenApi/Model/Operation.php @@ -210,5 +210,3 @@ public function withServers(?array $servers = null): self return $clone; } } - -class_alias(Operation::class, \ApiPlatform\Core\OpenApi\Model\Operation::class); diff --git a/src/OpenApi/Model/Parameter.php b/src/OpenApi/Model/Parameter.php index eddf887f1f8..9965704db78 100644 --- a/src/OpenApi/Model/Parameter.php +++ b/src/OpenApi/Model/Parameter.php @@ -242,5 +242,3 @@ public function withContent(\ArrayObject $content): self return $clone; } } - -class_alias(Parameter::class, \ApiPlatform\Core\OpenApi\Model\Parameter::class); diff --git a/src/OpenApi/Model/PathItem.php b/src/OpenApi/Model/PathItem.php index de173a8518f..5f08abde98a 100644 --- a/src/OpenApi/Model/PathItem.php +++ b/src/OpenApi/Model/PathItem.php @@ -218,5 +218,3 @@ public function withParameters(array $parameters): self return $clone; } } - -class_alias(PathItem::class, \ApiPlatform\Core\OpenApi\Model\PathItem::class); diff --git a/src/OpenApi/Model/Paths.php b/src/OpenApi/Model/Paths.php index 7d0cae6c3ae..babfdb82cb0 100644 --- a/src/OpenApi/Model/Paths.php +++ b/src/OpenApi/Model/Paths.php @@ -34,5 +34,3 @@ public function getPaths(): array return $this->paths ?? []; } } - -class_alias(Paths::class, \ApiPlatform\Core\OpenApi\Model\Paths::class); diff --git a/src/OpenApi/Model/RequestBody.php b/src/OpenApi/Model/RequestBody.php index 3703ecd8b5b..350136faf70 100644 --- a/src/OpenApi/Model/RequestBody.php +++ b/src/OpenApi/Model/RequestBody.php @@ -67,5 +67,3 @@ public function withRequired(bool $required): self return $clone; } } - -class_alias(RequestBody::class, \ApiPlatform\Core\OpenApi\Model\RequestBody::class); diff --git a/src/OpenApi/Model/Response.php b/src/OpenApi/Model/Response.php index 29ed33ac79f..54c7326a2fc 100644 --- a/src/OpenApi/Model/Response.php +++ b/src/OpenApi/Model/Response.php @@ -82,5 +82,3 @@ public function withLinks(\ArrayObject $links): self return $clone; } } - -class_alias(Response::class, \ApiPlatform\Core\OpenApi\Model\Response::class); diff --git a/src/OpenApi/Model/Schema.php b/src/OpenApi/Model/Schema.php index 487049a4e4d..68a31abf779 100644 --- a/src/OpenApi/Model/Schema.php +++ b/src/OpenApi/Model/Schema.php @@ -172,5 +172,3 @@ public function withDeprecated(bool $deprecated): self return $clone; } } - -class_alias(Schema::class, \ApiPlatform\Core\OpenApi\Model\Schema::class); diff --git a/src/OpenApi/Model/SecurityScheme.php b/src/OpenApi/Model/SecurityScheme.php index bf255ccdb43..600770f257f 100644 --- a/src/OpenApi/Model/SecurityScheme.php +++ b/src/OpenApi/Model/SecurityScheme.php @@ -142,5 +142,3 @@ public function withOpenIdConnectUrl(string $openIdConnectUrl): self return $clone; } } - -class_alias(SecurityScheme::class, \ApiPlatform\Core\OpenApi\Model\SecurityScheme::class); diff --git a/src/OpenApi/Model/Server.php b/src/OpenApi/Model/Server.php index 1baa0c8aea2..35eaafe6b28 100644 --- a/src/OpenApi/Model/Server.php +++ b/src/OpenApi/Model/Server.php @@ -67,5 +67,3 @@ public function withVariables(\ArrayObject $variables): self return $clone; } } - -class_alias(Server::class, \ApiPlatform\Core\OpenApi\Model\Server::class); diff --git a/src/OpenApi/OpenApi.php b/src/OpenApi/OpenApi.php index 09e9d1a2b55..2efede9b088 100644 --- a/src/OpenApi/OpenApi.php +++ b/src/OpenApi/OpenApi.php @@ -174,5 +174,3 @@ public function withJsonSchemaDialect(?string $jsonSchemaDialect): self return $clone; } } - -class_alias(OpenApi::class, \ApiPlatform\Core\OpenApi\OpenApi::class); diff --git a/src/OpenApi/Options.php b/src/OpenApi/Options.php index a7ba9e871a3..65a66293e1d 100644 --- a/src/OpenApi/Options.php +++ b/src/OpenApi/Options.php @@ -139,5 +139,3 @@ public function getLicenseUrl(): ?string return $this->licenseUrl; } } - -class_alias(Options::class, \ApiPlatform\Core\OpenApi\Options::class); diff --git a/src/OpenApi/Serializer/ApiGatewayNormalizer.php b/src/OpenApi/Serializer/ApiGatewayNormalizer.php index 78b3d099f9a..c904208a51f 100644 --- a/src/OpenApi/Serializer/ApiGatewayNormalizer.php +++ b/src/OpenApi/Serializer/ApiGatewayNormalizer.php @@ -149,5 +149,3 @@ private function normalizeRef(string $ref): string return implode('/', $refParts); } } - -class_alias(ApiGatewayNormalizer::class, \ApiPlatform\Core\Swagger\Serializer\ApiGatewayNormalizer::class); diff --git a/src/OpenApi/Serializer/OpenApiNormalizer.php b/src/OpenApi/Serializer/OpenApiNormalizer.php index 489d3c9123a..86991992af2 100644 --- a/src/OpenApi/Serializer/OpenApiNormalizer.php +++ b/src/OpenApi/Serializer/OpenApiNormalizer.php @@ -87,5 +87,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(OpenApiNormalizer::class, \ApiPlatform\Core\OpenApi\Serializer\OpenApiNormalizer::class); diff --git a/src/Operation/DashPathSegmentNameGenerator.php b/src/Operation/DashPathSegmentNameGenerator.php index 8d320e12528..3cac090173f 100644 --- a/src/Operation/DashPathSegmentNameGenerator.php +++ b/src/Operation/DashPathSegmentNameGenerator.php @@ -35,5 +35,3 @@ private function dashize(string $string): string return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '-$1', $string)); } } - -class_alias(DashPathSegmentNameGenerator::class, \ApiPlatform\Core\Operation\DashPathSegmentNameGenerator::class); diff --git a/src/Operation/UnderscorePathSegmentNameGenerator.php b/src/Operation/UnderscorePathSegmentNameGenerator.php index 09d75ec1fdf..c045cad6991 100644 --- a/src/Operation/UnderscorePathSegmentNameGenerator.php +++ b/src/Operation/UnderscorePathSegmentNameGenerator.php @@ -32,5 +32,3 @@ public function getSegmentName(string $name, bool $collection = true): string return $collection ? Inflector::pluralize($name) : $name; } } - -class_alias(UnderscorePathSegmentNameGenerator::class, \ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator::class); diff --git a/src/PathResolver/CustomOperationPathResolver.php b/src/PathResolver/CustomOperationPathResolver.php deleted file mode 100644 index 11b8f2f52c1..00000000000 --- a/src/PathResolver/CustomOperationPathResolver.php +++ /dev/null @@ -1,49 +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); - -namespace ApiPlatform\PathResolver; - -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; - -/** - * Resolves the custom operations path. - * - * @author Guilhem N. - */ -final class CustomOperationPathResolver implements OperationPathResolverInterface -{ - private $deferred; - - public function __construct(OperationPathResolverInterface $deferred) - { - $this->deferred = $deferred; - } - - /** - * {@inheritdoc} - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() >= 4) { - $operationName = func_get_arg(3); - } else { - @trigger_error(sprintf('Method %s() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1.', __METHOD__), \E_USER_DEPRECATED); - - $operationName = null; - } - - return $operation['path'] ?? $this->deferred->resolveOperationPath($resourceShortName, $operation, OperationTypeDeprecationHelper::getOperationType($operationType), $operationName); - } -} - -class_alias(CustomOperationPathResolver::class, \ApiPlatform\Core\PathResolver\CustomOperationPathResolver::class); diff --git a/src/PathResolver/OperationPathResolver.php b/src/PathResolver/OperationPathResolver.php deleted file mode 100644 index a08957bb31d..00000000000 --- a/src/PathResolver/OperationPathResolver.php +++ /dev/null @@ -1,68 +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); - -namespace ApiPlatform\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Operation\PathSegmentNameGeneratorInterface; - -/** - * Generates an operation path. - * - * @author Antoine Bluchet - */ -final class OperationPathResolver implements OperationPathResolverInterface -{ - private $pathSegmentNameGenerator; - - public function __construct(PathSegmentNameGeneratorInterface $pathSegmentNameGenerator) - { - $this->pathSegmentNameGenerator = $pathSegmentNameGenerator; - } - - /** - * {@inheritdoc} - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() < 4) { - @trigger_error(sprintf('Method %s() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1.', __METHOD__), \E_USER_DEPRECATED); - } - - $operationType = OperationTypeDeprecationHelper::getOperationType($operationType); - - if (OperationType::SUBRESOURCE === $operationType) { - throw new InvalidArgumentException('Subresource operations are not supported by the OperationPathResolver.'); - } - - $path = '/'.$this->pathSegmentNameGenerator->getSegmentName($resourceShortName); - - if (OperationType::ITEM === $operationType) { - if (isset($operation['identifiers']) && (\count($operation['identifiers']) <= 1 || false === ($operation['has_composite_identifier'] ?? true))) { - foreach ($operation['identifiers'] as $parameterName => $identifier) { - $path .= sprintf('/{%s}', \is_string($parameterName) ? $parameterName : $identifier); - } - } else { - $path .= '/{id}'; - } - } - - $path .= '.{_format}'; - - return $path; - } -} - -class_alias(OperationPathResolver::class, \ApiPlatform\Core\PathResolver\OperationPathResolver::class); diff --git a/src/PathResolver/OperationPathResolverInterface.php b/src/PathResolver/OperationPathResolverInterface.php deleted file mode 100644 index a447dff270e..00000000000 --- a/src/PathResolver/OperationPathResolverInterface.php +++ /dev/null @@ -1,32 +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); - -namespace ApiPlatform\PathResolver; - -/** - * Resolves the path of a resource operation. - * - * @author Paul Le Corre - */ -interface OperationPathResolverInterface -{ - /** - * Resolves the operation path. - * - * @param string $resourceShortName When the operation type is a subresource and the operation has more than one identifier, this value is the previous operation path - * @param array $operation The operation metadata - * @param string|bool $operationType One of the constants defined in ApiPlatform\Core\Api\OperationType - * If the property is a boolean, true represents OperationType::COLLECTION, false is for OperationType::ITEM - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string; -} diff --git a/src/Problem/Serializer/ConstraintViolationListNormalizer.php b/src/Problem/Serializer/ConstraintViolationListNormalizer.php index e4935bb828d..70325c06227 100644 --- a/src/Problem/Serializer/ConstraintViolationListNormalizer.php +++ b/src/Problem/Serializer/ConstraintViolationListNormalizer.php @@ -56,5 +56,3 @@ public function normalize($object, $format = null, array $context = []): array ]; } } - -class_alias(ConstraintViolationListNormalizer::class, \ApiPlatform\Core\Problem\Serializer\ConstraintViolationListNormalizer::class); diff --git a/src/Problem/Serializer/ErrorNormalizer.php b/src/Problem/Serializer/ErrorNormalizer.php index b819a1282a9..2d424d58ea2 100644 --- a/src/Problem/Serializer/ErrorNormalizer.php +++ b/src/Problem/Serializer/ErrorNormalizer.php @@ -78,5 +78,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(ErrorNormalizer::class, \ApiPlatform\Core\Problem\Serializer\ErrorNormalizer::class); diff --git a/src/Problem/Serializer/ErrorNormalizerTrait.php b/src/Problem/Serializer/ErrorNormalizerTrait.php index 18c373db33e..773fade6bcf 100644 --- a/src/Problem/Serializer/ErrorNormalizerTrait.php +++ b/src/Problem/Serializer/ErrorNormalizerTrait.php @@ -53,5 +53,3 @@ private function getErrorCode($object): ?string return null; } } - -class_alias(ErrorNormalizerTrait::class, \ApiPlatform\Core\Problem\Serializer\ErrorNormalizerTrait::class); diff --git a/src/RamseyUuid/Serializer/UuidDenormalizer.php b/src/RamseyUuid/Serializer/UuidDenormalizer.php index 5d691261504..9df2f011c66 100644 --- a/src/RamseyUuid/Serializer/UuidDenormalizer.php +++ b/src/RamseyUuid/Serializer/UuidDenormalizer.php @@ -42,5 +42,3 @@ public function supportsDenormalization($data, $type, $format = null): bool return \is_string($data) && is_a($type, UuidInterface::class, true); } } - -class_alias(UuidDenormalizer::class, \ApiPlatform\Core\Bridge\RamseyUuid\Serializer\UuidDenormalizer::class); diff --git a/src/Serializer/AbstractCollectionNormalizer.php b/src/Serializer/AbstractCollectionNormalizer.php index 41c09dd820b..d4aa8f41042 100644 --- a/src/Serializer/AbstractCollectionNormalizer.php +++ b/src/Serializer/AbstractCollectionNormalizer.php @@ -155,5 +155,3 @@ abstract protected function getPaginationData($object, array $context = []): arr */ abstract protected function getItemsData($object, string $format = null, array $context = []): array; } - -class_alias(AbstractCollectionNormalizer::class, \ApiPlatform\Core\Serializer\AbstractCollectionNormalizer::class); diff --git a/src/Serializer/AbstractConstraintViolationListNormalizer.php b/src/Serializer/AbstractConstraintViolationListNormalizer.php index ba898d12fc9..fcc9f4f1430 100644 --- a/src/Serializer/AbstractConstraintViolationListNormalizer.php +++ b/src/Serializer/AbstractConstraintViolationListNormalizer.php @@ -85,5 +85,3 @@ protected function getMessagesAndViolations(ConstraintViolationListInterface $co return [$messages, $violations]; } } - -class_alias(AbstractConstraintViolationListNormalizer::class, \ApiPlatform\Core\Serializer\AbstractConstraintViolationListNormalizer::class); diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 35a25e2be6a..f3c867d83f5 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -15,14 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Bridge\Symfony\Messenger\DataTransformer as MessengerDataTransformer; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\InvalidValueException; use ApiPlatform\Exception\ItemNotFoundException; @@ -78,16 +70,15 @@ abstract class AbstractItemNormalizer extends AbstractObjectNormalizer protected $resourceClassResolver; protected $resourceAccessChecker; protected $propertyAccessor; - protected $itemDataProvider; protected $allowPlainIdentifiers; protected $dataTransformers = []; protected $localCache = []; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, ItemDataProviderInterface $itemDataProvider = null, bool $allowPlainIdentifiers = false, array $defaultContext = [], iterable $dataTransformers = [], $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { if (!isset($defaultContext['circular_reference_handler'])) { $defaultContext['circular_reference_handler'] = function ($object) { - return $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($object) : $this->iriConverter->getIriFromResource($object); + return $this->iriConverter->getIriFromResource($object); }; } if (!interface_exists(AdvancedNameConverterInterface::class) && method_exists($this, 'setCircularReferenceHandler')) { @@ -98,36 +89,9 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; - - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } - $this->iriConverter = $iriConverter; $this->resourceClassResolver = $resourceClassResolver; $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - $this->itemDataProvider = $itemDataProvider; - - if (true === $allowPlainIdentifiers) { - @trigger_error(sprintf('Allowing plain identifiers as argument of "%s" is deprecated since API Platform 2.7 and will not be possible anymore in API Platform 3.', self::class), \E_USER_DEPRECATED); - } - $this->allowPlainIdentifiers = $allowPlainIdentifiers; - - $this->dataTransformers = $dataTransformers; - - // Just skip our data transformer to trigger a proper deprecation - $customDataTransformers = array_filter(\is_array($dataTransformers) ? $dataTransformers : iterator_to_array($dataTransformers), function ($dataTransformer) { - return !$dataTransformer instanceof MessengerDataTransformer; - }); - - if (\count($customDataTransformers)) { - trigger_deprecation('api-platform/core', '2.7', 'The DataTransformer pattern is deprecated, use a Provider or a Processor and either use your input or return a new output there.'); - } - - if ($resourceMetadataFactory && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->resourceAccessChecker = $resourceAccessChecker; } @@ -188,7 +152,7 @@ public function normalize($object, $format = null, array $context = []) if (isset($context['iri'])) { $iri = $context['iri']; } else { - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($object) : $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_URL, $context['operation'] ?? null, $context); + $iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_URL, $context['operation'] ?? null, $context); } $context['iri'] = $iri; @@ -245,71 +209,25 @@ public function denormalize($data, $class, $format = null, array $context = []) $context['api_denormalize'] = true; $context['resource_class'] = $resourceClass; - if (null !== $inputClass = $this->getInputClass($resourceClass, $context)) { - if (null !== $dataTransformer = $this->getDataTransformer($data, $resourceClass, $context)) { - $dataTransformerContext = $context; - - unset($context['input']); - unset($context['resource_class']); - - if (!$this->serializer instanceof DenormalizerInterface) { - throw new LogicException('Cannot denormalize the input because the injected serializer is not a denormalizer'); - } - - if ($dataTransformer instanceof DataTransformerInitializerInterface) { - $context[AbstractObjectNormalizer::OBJECT_TO_POPULATE] = $dataTransformer->initialize($inputClass, $context); - $context[AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE] = true; - } - - try { - $denormalizedInput = $this->serializer->denormalize($data, $inputClass, $format, $context); - } catch (NotNormalizableValueException $e) { - throw new UnexpectedValueException('The input data is misformatted.', $e->getCode(), $e); - } - - if (!\is_object($denormalizedInput)) { - throw new UnexpectedValueException('Expected denormalized input to be an object.'); - } - - return $dataTransformer->transform($denormalizedInput, $resourceClass, $dataTransformerContext); - } - - // Are we in a Request context? - if ($context['operation'] ?? $context['operation_type'] ?? false) { - $resourceClass = $inputClass; - $context['resource_class'] = $inputClass; - } + if ( + $inputClass = $this->getInputClass($resourceClass, $context) + && + ($context['operation'] ?? $context['operation_type'] ?? false) // Are we in a Request context? + ) { + $resourceClass = $inputClass; + $context['resource_class'] = $inputClass; } - $supportsPlainIdentifiers = $this->supportsPlainIdentifiers(); - if (\is_string($data)) { try { - return $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($data, $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($data, $context + ['fetch_data' => true]); + return $this->iriConverter->getResourceFromIri($data, $context + ['fetch_data' => true]); } catch (ItemNotFoundException $e) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); - } + throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); } catch (InvalidArgumentException $e) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException(sprintf('Invalid IRI "%s".', $data), $e->getCode(), $e); - } + throw new UnexpectedValueException(sprintf('Invalid IRI "%s".', $data), $e->getCode(), $e); } } - if (!\is_array($data)) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException(sprintf('Expected IRI or document for resource "%s", "%s" given.', $resourceClass, \gettype($data))); - } - - $item = $this->itemDataProvider->getItem($resourceClass, $data, null, $context + ['fetch_data' => true]); - if (null === $item) { - throw new ItemNotFoundException(sprintf('Item not found for resource "%s" with id "%s".', $resourceClass, $data)); - } - - return $item; - } - $previousObject = null !== $objectToPopulate ? clone $objectToPopulate : null; $object = parent::denormalize($data, $resourceClass, $format, $context); @@ -598,19 +516,13 @@ protected function denormalizeCollection(string $attribute, $propertyMetadata, T */ protected function denormalizeRelation(string $attributeName, $propertyMetadata, string $className, $value, ?string $format, array $context) { - $supportsPlainIdentifiers = $this->supportsPlainIdentifiers(); - if (\is_string($value)) { try { - return $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($value, $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($value, $context + ['fetch_data' => true]); + return $this->iriConverter->getResourceFromIri($value, $context + ['fetch_data' => true]); } catch (ItemNotFoundException $e) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); - } + throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); } catch (InvalidArgumentException $e) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException(sprintf('Invalid IRI "%s".', $value), $e->getCode(), $e); - } + throw new UnexpectedValueException(sprintf('Invalid IRI "%s".', $value), $e->getCode(), $e); } } @@ -629,23 +541,12 @@ protected function denormalizeRelation(string $attributeName, $propertyMetadata, return $item; } catch (InvalidValueException $e) { - if (!$supportsPlainIdentifiers) { - throw $e; - } + throw $e; } } if (!\is_array($value)) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException(sprintf('Expected IRI or nested document for attribute "%s", "%s" given.', $attributeName, \gettype($value))); - } - - $item = $this->itemDataProvider->getItem($className, $value, null, $context + ['fetch_data' => true]); - if (null === $item) { - throw new ItemNotFoundException(sprintf('Item not found for resource "%s" with id "%s".', $className, $value)); - } - - return $item; + throw new UnexpectedValueException(sprintf('Expected IRI or nested document for attribute "%s", "%s" given.', $attributeName, \gettype($value))); } throw new UnexpectedValueException(sprintf('Nested documents for attribute "%s" are not allowed. Use IRIs instead.', $attributeName)); @@ -855,50 +756,14 @@ protected function normalizeRelation($propertyMetadata, $relatedObject, string $ return $iri; } - /** - * Finds the first supported data transformer if any. - * - * @param object|array $data object on normalize / array on denormalize - */ - protected function getDataTransformer($data, string $to, array $context = []): ?DataTransformerInterface - { - foreach ($this->dataTransformers as $dataTransformer) { - if ($dataTransformer->supportsTransformation($data, $to, $context)) { - return $dataTransformer; - } - } - - return null; - } - - /** - * For a given resource, it returns an output representation if any - * If not, the resource is returned. - * - * @param mixed $object - */ - protected function transformOutput($object, array $context = [], string $outputClass = null) - { - if (null === $outputClass) { - $outputClass = $this->getOutputClass($this->getObjectClass($object), $context); - } - - if (null !== $outputClass && null !== $dataTransformer = $this->getDataTransformer($object, $outputClass, $context)) { - return $dataTransformer->transform($object, $outputClass, $context); - } - - return $object; - } - private function createAttributeValue($attribute, $value, $format = null, array $context = []) { if (!$this->resourceClassResolver->isResourceClass($context['resource_class'])) { return $value; } - /** @var ApiProperty|PropertyMetadata */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $this->getFactoryOptions($context)); - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : ($propertyMetadata->getBuiltinTypes()[0] ?? null); + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; if (null === $type) { // No type provided, blindly return the value @@ -1036,16 +901,4 @@ private function setValue($object, string $attributeName, $value) // Properties not found are ignored } } - - /** - * TODO: to remove in 3.0. - * - * @deprecated since 2.7 - */ - private function supportsPlainIdentifiers(): bool - { - return $this->allowPlainIdentifiers && null !== $this->itemDataProvider; - } } - -class_alias(AbstractItemNormalizer::class, \ApiPlatform\Core\Serializer\AbstractItemNormalizer::class); diff --git a/src/Serializer/CacheKeyTrait.php b/src/Serializer/CacheKeyTrait.php index 56c9823c660..51cb44952d9 100644 --- a/src/Serializer/CacheKeyTrait.php +++ b/src/Serializer/CacheKeyTrait.php @@ -34,5 +34,3 @@ private function getCacheKey(?string $format, array $context) } } } - -class_alias(CacheKeyTrait::class, \ApiPlatform\Core\Serializer\CacheKeyTrait::class); diff --git a/src/Serializer/ContextTrait.php b/src/Serializer/ContextTrait.php index 90fe49392a4..daf67498f62 100644 --- a/src/Serializer/ContextTrait.php +++ b/src/Serializer/ContextTrait.php @@ -31,5 +31,3 @@ private function initContext(string $resourceClass, array $context): array ]); } } - -class_alias(ContextTrait::class, \ApiPlatform\Core\Serializer\ContextTrait::class); diff --git a/src/Serializer/Filter/GroupFilter.php b/src/Serializer/Filter/GroupFilter.php index e297ac4cfba..24999cab313 100644 --- a/src/Serializer/Filter/GroupFilter.php +++ b/src/Serializer/Filter/GroupFilter.php @@ -75,5 +75,3 @@ public function getDescription(string $resourceClass): array ]; } } - -class_alias(GroupFilter::class, \ApiPlatform\Core\Serializer\Filter\GroupFilter::class); diff --git a/src/Serializer/Filter/PropertyFilter.php b/src/Serializer/Filter/PropertyFilter.php index a5f34449af0..41e1e86ecff 100644 --- a/src/Serializer/Filter/PropertyFilter.php +++ b/src/Serializer/Filter/PropertyFilter.php @@ -168,5 +168,3 @@ private function denormalizePropertyName($property) return null !== $this->nameConverter ? $this->nameConverter->denormalize($property) : $property; } } - -class_alias(PropertyFilter::class, \ApiPlatform\Core\Serializer\Filter\PropertyFilter::class); diff --git a/src/Serializer/InputOutputMetadataTrait.php b/src/Serializer/InputOutputMetadataTrait.php index 66bbb61b71e..8c7758053cf 100644 --- a/src/Serializer/InputOutputMetadataTrait.php +++ b/src/Serializer/InputOutputMetadataTrait.php @@ -85,5 +85,3 @@ private function getInputOutputMetadata(string $class, string $inputOrOutput, ar return $metadata->getAttribute($inputOrOutput)['class'] ?? null; } } - -class_alias(InputOutputMetadataTrait::class, \ApiPlatform\Core\Serializer\InputOutputMetadataTrait::class); diff --git a/src/Serializer/ItemNormalizer.php b/src/Serializer/ItemNormalizer.php index e97c6daedbf..80390d98afd 100644 --- a/src/Serializer/ItemNormalizer.php +++ b/src/Serializer/ItemNormalizer.php @@ -14,11 +14,12 @@ namespace ApiPlatform\Serializer; use ApiPlatform\Api\IriConverterInterface; +use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; @@ -36,15 +37,9 @@ class ItemNormalizer extends AbstractItemNormalizer { private $logger; - /** - * @param mixed $propertyMetadataFactory - * @param LegacyIriConverterInterface|IriConverterInterface $iriConverter - * @param mixed $resourceClassResolver - * @param mixed|null $resourceMetadataFactory - */ - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, ItemDataProviderInterface $itemDataProvider = null, bool $allowPlainIdentifiers = false, LoggerInterface $logger = null, iterable $dataTransformers = [], $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, LoggerInterface $logger = null, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $itemDataProvider, $allowPlainIdentifiers, [], $dataTransformers, $resourceMetadataFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, [], $resourceMetadataFactory, $resourceAccessChecker); $this->logger = $logger ?: new NullLogger(); } @@ -80,33 +75,13 @@ public function denormalize($data, $class, $format = null, array $context = []) private function updateObjectToPopulate(array $data, array &$context): void { try { - $context[self::OBJECT_TO_POPULATE] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri((string) $data['id'], $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri((string) $data['id'], $context + ['fetch_data' => true]); + $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri((string) $data['id'], $context + ['fetch_data' => true]); } catch (InvalidArgumentException $e) { - if ($this->iriConverter instanceof LegacyIriConverterInterface) { - // remove in 3.0 - $identifier = null; - $options = $this->getFactoryOptions($context); + $operation = $this->resourceMetadataFactory->create($context['resource_class'])->getOperation(); + // todo: we could guess uri variables with the operation and the data instead of hardcoding id + $iri = $this->iriConverter->getIriFromResource($context['resource_class'], UrlGeneratorInterface::ABS_PATH, $operation, ['uri_variables' => ['id' => $data['id']]]); - foreach ($this->propertyNameCollectionFactory->create($context['resource_class'], $options) as $propertyName) { - if (true === $this->propertyMetadataFactory->create($context['resource_class'], $propertyName)->isIdentifier()) { - $identifier = $propertyName; - break; - } - } - - if (null === $identifier) { - throw $e; - } - $iri = sprintf('%s/%s', $this->iriConverter->getIriFromResourceClass($context['resource_class']), $data[$identifier]); - } else { - $operation = $this->resourceMetadataFactory->create($context['resource_class'])->getOperation(); - // todo: we could guess uri variables with the operation and the data instead of hardcoding id - $iri = $this->iriConverter->getIriFromResource($context['resource_class'], UrlGeneratorInterface::ABS_PATH, $operation, ['uri_variables' => ['id' => $data['id']]]); - } - - $context[self::OBJECT_TO_POPULATE] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($iri, ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($iri, ['fetch_data' => true]); + $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri($iri, ['fetch_data' => true]); } } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\Serializer\ItemNormalizer::class); diff --git a/src/Serializer/JsonEncoder.php b/src/Serializer/JsonEncoder.php index 2a95e510bb0..a336ae787a9 100644 --- a/src/Serializer/JsonEncoder.php +++ b/src/Serializer/JsonEncoder.php @@ -86,5 +86,3 @@ public function decode($data, $format, array $context = []) return $this->jsonEncoder->decode($data, $format, $context); } } - -class_alias(JsonEncoder::class, \ApiPlatform\Core\Serializer\JsonEncoder::class); diff --git a/src/Serializer/Mapping/Factory/ClassMetadataFactory.php b/src/Serializer/Mapping/Factory/ClassMetadataFactory.php index fb2b29ee391..954c8bdb8dc 100644 --- a/src/Serializer/Mapping/Factory/ClassMetadataFactory.php +++ b/src/Serializer/Mapping/Factory/ClassMetadataFactory.php @@ -44,5 +44,3 @@ public function hasMetadataFor($value): bool return $this->decorated->hasMetadataFor(\is_object($value) ? $this->getObjectClass($value) : $this->getRealClassName($value)); } } - -class_alias(ClassMetadataFactory::class, \ApiPlatform\Core\Serializer\Mapping\Factory\ClassMetadataFactory::class); diff --git a/src/Serializer/ResourceList.php b/src/Serializer/ResourceList.php index caba8d0d6c0..3817529da26 100644 --- a/src/Serializer/ResourceList.php +++ b/src/Serializer/ResourceList.php @@ -19,5 +19,3 @@ class ResourceList extends \ArrayObject { } - -class_alias(ResourceList::class, \ApiPlatform\Core\Serializer\ResourceList::class); diff --git a/src/Serializer/SerializerContextBuilder.php b/src/Serializer/SerializerContextBuilder.php index e5d97ec8d7c..6f5ae3a4b96 100644 --- a/src/Serializer/SerializerContextBuilder.php +++ b/src/Serializer/SerializerContextBuilder.php @@ -13,12 +13,7 @@ namespace ApiPlatform\Serializer; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\RequestAttributesExtractor; use Symfony\Component\HttpFoundation\Request; @@ -33,13 +28,9 @@ final class SerializerContextBuilder implements SerializerContextBuilderInterfac { private $resourceMetadataFactory; - public function __construct($resourceMetadataFactory) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -51,70 +42,30 @@ public function createFromRequest(Request $request, bool $normalization, array $ throw new RuntimeException('Request attributes are not valid.'); } - // TODO: 3.0 change the condition to remove the ResourceMetadataFactorym only used to skip null values - if ( - $this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface - && (isset($attributes['operation_name']) || isset($attributes['operation'])) - ) { - $operation = $attributes['operation'] ?? $this->resourceMetadataFactory->create($attributes['resource_class'])->getOperation($attributes['operation_name']); - $context = $normalization ? ($operation->getNormalizationContext() ?? []) : ($operation->getDenormalizationContext() ?? []); - $context['operation_name'] = $operation->getName(); - $context['operation'] = $operation; - $context['resource_class'] = $attributes['resource_class']; - // TODO: 3.0 becomes true by default - $context['skip_null_values'] = $context['skip_null_values'] ?? $this->shouldSkipNullValues($attributes['resource_class'], $context['operation_name']); - // TODO: remove in 3.0, operation type will not exist anymore - $context['operation_type'] = $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM; - $context['iri_only'] = $context['iri_only'] ?? false; - $context['request_uri'] = $request->getRequestUri(); - $context['uri'] = $request->getUri(); - $context['input'] = $operation->getInput(); - $context['output'] = $operation->getOutput(); + $operation = $attributes['operation'] ?? $this->resourceMetadataFactory->create($attributes['resource_class'])->getOperation($attributes['operation_name']); + $context = $normalization ? ($operation->getNormalizationContext() ?? []) : ($operation->getDenormalizationContext() ?? []); + $context['operation_name'] = $operation->getName(); + $context['operation'] = $operation; + $context['resource_class'] = $attributes['resource_class']; + $context['skip_null_values'] = $context['skip_null_values'] ?? true; + $context['iri_only'] = $context['iri_only'] ?? false; + $context['request_uri'] = $request->getRequestUri(); + $context['uri'] = $request->getUri(); + $context['input'] = $operation->getInput(); + $context['output'] = $operation->getOutput(); + + if ($operation->getTypes()) { $context['types'] = $operation->getTypes(); + } + + if ($operation->getUriVariables()) { $context['uri_variables'] = []; foreach (array_keys($operation->getUriVariables() ?? []) as $parameterName) { $context['uri_variables'][$parameterName] = $request->attributes->get($parameterName); } - - if (!$normalization) { - if (!isset($context['api_allow_update'])) { - $context['api_allow_update'] = \in_array($method = $request->getMethod(), ['PUT', 'PATCH'], true); - - if ($context['api_allow_update'] && 'PATCH' === $method) { - $context['deep_object_to_populate'] = $context['deep_object_to_populate'] ?? true; - } - } - - if ('csv' === $request->getContentType()) { - $context[CsvEncoder::AS_COLLECTION_KEY] = false; - } - } - - return $context; - } - - /** @var ResourceMetadata $resourceMetadata */ - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - $key = $normalization ? 'normalization_context' : 'denormalization_context'; - if (isset($attributes['collection_operation_name'])) { - $operationKey = 'collection_operation_name'; - $operationType = OperationType::COLLECTION; - } elseif (isset($attributes['item_operation_name'])) { - $operationKey = 'item_operation_name'; - $operationType = OperationType::ITEM; - } else { - $operationKey = 'subresource_operation_name'; - $operationType = OperationType::SUBRESOURCE; } - $context = $resourceMetadata->getTypedOperationAttribute($operationType, $attributes[$operationKey], $key, [], true); - $context['operation_type'] = $operationType; - $context[$operationKey] = $attributes[$operationKey]; - $context['iri_only'] = $resourceMetadata->getAttribute('normalization_context')['iri_only'] ?? false; - $context['input'] = $resourceMetadata->getTypedOperationAttribute($operationType, $attributes[$operationKey], 'input', null, true); - $context['output'] = $resourceMetadata->getTypedOperationAttribute($operationType, $attributes[$operationKey], 'output', null, true); - if (!$normalization) { if (!isset($context['api_allow_update'])) { $context['api_allow_update'] = \in_array($method = $request->getMethod(), ['PUT', 'PATCH'], true); @@ -129,69 +80,6 @@ public function createFromRequest(Request $request, bool $normalization, array $ } } - $context['resource_class'] = $attributes['resource_class']; - $context['request_uri'] = $request->getRequestUri(); - $context['uri'] = $request->getUri(); - - if (isset($attributes['subresource_context'])) { - $context['subresource_identifiers'] = []; - - foreach ($attributes['subresource_context']['identifiers'] as $parameterName => [$resourceClass]) { - if (!isset($context['subresource_resources'][$resourceClass])) { - $context['subresource_resources'][$resourceClass] = []; - } - - $context['subresource_identifiers'][$parameterName] = $context['subresource_resources'][$resourceClass][$parameterName] = $request->attributes->get($parameterName); - } - } - - if (isset($attributes['subresource_property'])) { - $context['subresource_property'] = $attributes['subresource_property']; - $context['subresource_resource_class'] = $attributes['subresource_resource_class'] ?? null; - } - - unset($context[DocumentationNormalizer::SWAGGER_DEFINITION_NAME]); - - if (isset($context['skip_null_values'])) { - return $context; - } - - // TODO: We should always use `skip_null_values` but changing this would be a BC break, for now use it only when `merge-patch+json` is activated on a Resource - if (!$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - foreach ($resourceMetadata->getItemOperations() as $operation) { - if ('PATCH' === ($operation['method'] ?? '') && \in_array('application/merge-patch+json', $operation['input_formats']['json'] ?? [], true)) { - $context['skip_null_values'] = true; - - break; - } - } - } else { - $context['skip_null_values'] = $this->shouldSkipNullValues($attributes['resource_class'], $attributes['operation_name']); - } - return $context; } - - /** - * TODO: remove in 3.0, this will have no impact and skip_null_values will be default, no more resourceMetadataFactory call in this class. - */ - private function shouldSkipNullValues(string $class, string $operationName): bool - { - if (!$this->resourceMetadataFactory) { - return false; - } - - $collection = $this->resourceMetadataFactory->create($class); - foreach ($collection as $metadata) { - foreach ($metadata->getOperations() as $operation) { - if ('PATCH' === ($operation->getMethod() ?? '') && \in_array('application/merge-patch+json', $operation->getInputFormats()['json'] ?? [], true)) { - return true; - } - } - } - - return false; - } } - -class_alias(SerializerContextBuilder::class, \ApiPlatform\Core\Serializer\SerializerContextBuilder::class); diff --git a/src/Serializer/SerializerFilterContextBuilder.php b/src/Serializer/SerializerFilterContextBuilder.php index 234bdc841a8..3132861b8af 100644 --- a/src/Serializer/SerializerFilterContextBuilder.php +++ b/src/Serializer/SerializerFilterContextBuilder.php @@ -75,5 +75,3 @@ public function createFromRequest(Request $request, bool $normalization, array $ return $context; } } - -class_alias(SerializerFilterContextBuilder::class, \ApiPlatform\Core\Serializer\SerializerFilterContextBuilder::class); diff --git a/src/State/Pagination/ArrayPaginator.php b/src/State/Pagination/ArrayPaginator.php index d20f2ede837..94adbcea280 100644 --- a/src/State/Pagination/ArrayPaginator.php +++ b/src/State/Pagination/ArrayPaginator.php @@ -93,5 +93,3 @@ public function getIterator(): \Traversable return $this->iterator; } } - -class_alias(ArrayPaginator::class, \ApiPlatform\Core\DataProvider\ArrayPaginator::class); diff --git a/src/State/Pagination/PaginationOptions.php b/src/State/Pagination/PaginationOptions.php index 72fa7988a8a..2e62cc58926 100644 --- a/src/State/Pagination/PaginationOptions.php +++ b/src/State/Pagination/PaginationOptions.php @@ -102,5 +102,3 @@ public function getPartialPaginationParameterName(): string return $this->partialPaginationParameterName; } } - -class_alias(PaginationOptions::class, \ApiPlatform\Core\DataProvider\PaginationOptions::class); diff --git a/src/State/Pagination/TraversablePaginator.php b/src/State/Pagination/TraversablePaginator.php index bb5713de8f7..9b40f517804 100644 --- a/src/State/Pagination/TraversablePaginator.php +++ b/src/State/Pagination/TraversablePaginator.php @@ -88,5 +88,3 @@ public function getIterator(): \Traversable return $this->traversable; } } - -class_alias(TraversablePaginator::class, \ApiPlatform\Core\DataProvider\TraversablePaginator::class); diff --git a/src/Symfony/Bundle/ApiPlatformBundle.php b/src/Symfony/Bundle/ApiPlatformBundle.php index 9fe0c17db3e..6c7462f6c13 100644 --- a/src/Symfony/Bundle/ApiPlatformBundle.php +++ b/src/Symfony/Bundle/ApiPlatformBundle.php @@ -56,5 +56,3 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new AuthenticatorManagerPass()); } } - -class_alias(ApiPlatformBundle::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class); diff --git a/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php b/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php index 83f0aa495c6..2681a94748a 100644 --- a/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php +++ b/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php @@ -76,5 +76,3 @@ private function getExpectedInputClass(Request $request): ?string return $context['input'] ?? $context['resource_class']; } } - -class_alias(PayloadArgumentResolver::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver::class); diff --git a/src/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php b/src/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php index f6974680a9d..d9ead7ef527 100644 --- a/src/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php +++ b/src/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php @@ -59,5 +59,3 @@ public function isOptional(): bool return false; } } - -class_alias(CachePoolClearerCacheWarmer::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer::class); diff --git a/src/Symfony/Bundle/Command/GraphQlExportCommand.php b/src/Symfony/Bundle/Command/GraphQlExportCommand.php index 84db8778593..a0ce0797c78 100644 --- a/src/Symfony/Bundle/Command/GraphQlExportCommand.php +++ b/src/Symfony/Bundle/Command/GraphQlExportCommand.php @@ -80,5 +80,3 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } } - -class_alias(GraphQlExportCommand::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Command\GraphQlExportCommand::class); diff --git a/src/Symfony/Bundle/Command/OpenApiCommand.php b/src/Symfony/Bundle/Command/OpenApiCommand.php index de02f179acc..e27f083d63c 100644 --- a/src/Symfony/Bundle/Command/OpenApiCommand.php +++ b/src/Symfony/Bundle/Command/OpenApiCommand.php @@ -96,5 +96,3 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } } - -class_alias(OpenApiCommand::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Command\OpenApiCommand::class); diff --git a/src/Symfony/Bundle/DataCollector/RequestDataCollector.php b/src/Symfony/Bundle/DataCollector/RequestDataCollector.php index eaef3f46595..cf2901766ac 100644 --- a/src/Symfony/Bundle/DataCollector/RequestDataCollector.php +++ b/src/Symfony/Bundle/DataCollector/RequestDataCollector.php @@ -13,18 +13,7 @@ namespace ApiPlatform\Symfony\Bundle\DataCollector; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister\TraceableChainDataPersister; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainCollectionDataProvider; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainItemDataProvider; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainSubresourceDataProvider; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\ApiResourceToLegacyResourceMetadataTrait; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\RequestAttributesExtractor; use PackageVersions\Versions; use Psr\Container\ContainerInterface; @@ -38,36 +27,15 @@ */ final class RequestDataCollector extends DataCollector { - use ApiResourceToLegacyResourceMetadataTrait; - - /** - * @var ResourceMetadataCollectionFactoryInterface - */ private $metadataFactory; private $filterLocator; - private $collectionDataProvider; - private $itemDataProvider; - private $subresourceDataProvider; - private $dataPersister; public function __construct( $metadataFactory, ContainerInterface $filterLocator, - CollectionDataProviderInterface $collectionDataProvider = null, - ItemDataProviderInterface $itemDataProvider = null, - SubresourceDataProviderInterface $subresourceDataProvider = null, - DataPersisterInterface $dataPersister = null ) { $this->metadataFactory = $metadataFactory; $this->filterLocator = $filterLocator; - $this->collectionDataProvider = $collectionDataProvider; - $this->itemDataProvider = $itemDataProvider; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->dataPersister = $dataPersister; - - if (!$metadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -102,35 +70,8 @@ public function collect(Request $request, Response $response, \Throwable $except 'acceptable_content_types' => $request->getAcceptableContentTypes(), 'filters' => $filters, 'counters' => $counters, - 'dataProviders' => [], - 'dataPersisters' => ['responses' => []], 'request_attributes' => $requestAttributes, ]; - - if ($this->collectionDataProvider instanceof TraceableChainCollectionDataProvider) { - $this->data['dataProviders']['collection'] = [ - 'context' => $this->cloneVar($this->collectionDataProvider->getContext()), - 'responses' => $this->collectionDataProvider->getProvidersResponse(), - ]; - } - - if ($this->itemDataProvider instanceof TraceableChainItemDataProvider) { - $this->data['dataProviders']['item'] = [ - 'context' => $this->cloneVar($this->itemDataProvider->getContext()), - 'responses' => $this->itemDataProvider->getProvidersResponse(), - ]; - } - - if ($this->subresourceDataProvider instanceof TraceableChainSubresourceDataProvider) { - $this->data['dataProviders']['subresource'] = [ - 'context' => $this->cloneVar($this->subresourceDataProvider->getContext()), - 'responses' => $this->subresourceDataProvider->getProvidersResponse(), - ]; - } - - if ($this->dataPersister instanceof TraceableChainDataPersister) { - $this->data['dataPersisters']['responses'] = $this->dataPersister->getPersistersResponse(); - } } private function setFilters(ApiResource $resourceMetadata, int $index, array &$filters, array &$counters): void @@ -176,26 +117,6 @@ public function getCounters(): array return $this->data['counters'] ?? []; } - public function getCollectionDataProviders(): array - { - return $this->data['dataProviders']['collection'] ?? ['context' => [], 'responses' => []]; - } - - public function getItemDataProviders(): array - { - return $this->data['dataProviders']['item'] ?? ['context' => [], 'responses' => []]; - } - - public function getSubresourceDataProviders(): array - { - return $this->data['dataProviders']['subresource'] ?? ['context' => [], 'responses' => []]; - } - - public function getDataPersisters(): array - { - return $this->data['dataPersisters'] ?? ['responses' => []]; - } - public function getVersion(): ?string { if (!class_exists(Versions::class)) { diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 52feb0e118d..f645ed56343 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -15,13 +15,6 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; use ApiPlatform\Doctrine\Odm\Filter\AbstractFilter as DoctrineMongoDbOdmAbstractFilter; @@ -36,14 +29,13 @@ use ApiPlatform\GraphQl\Resolver\QueryCollectionResolverInterface; use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface; use ApiPlatform\GraphQl\Type\Definition\TypeInterface as GraphQlTypeInterface; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\State\ProcessorInterface; use ApiPlatform\State\ProviderInterface; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface; -use Doctrine\Common\Annotations\Annotation; use phpDocumentor\Reflection\DocBlockFactoryInterface; use Ramsey\Uuid\Uuid; -use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -117,7 +109,6 @@ public function load(array $configs, ContainerBuilder $container): void $this->registerJsonHalConfiguration($formats, $loader); $this->registerJsonProblemConfiguration($errorFormats, $loader); $this->registerGraphQlConfiguration($container, $config, $loader); - $this->registerLegacyBundlesConfiguration($container, $config, $loader); $this->registerCacheConfiguration($container); $this->registerDoctrineOrmConfiguration($container, $config, $loader); $this->registerDoctrineMongoDbOdmConfiguration($container, $config, $loader); @@ -131,18 +122,6 @@ public function load(array $configs, ContainerBuilder $container): void $this->registerSecurityConfiguration($container, $loader, $config); $this->registerMakerConfiguration($container, $config, $loader); $this->registerArgumentResolverConfiguration($container, $loader, $config); - $this->registerLegacyServices($container, $config, $loader); - $this->registerUpgradeCommandConfiguration($container, $loader, $config); - - // TODO: remove in 3.x - $container->registerForAutoconfiguration(DataPersisterInterface::class) - ->addTag('api_platform.data_persister'); - $container->registerForAutoconfiguration(ItemDataProviderInterface::class) - ->addTag('api_platform.item_data_provider'); - $container->registerForAutoconfiguration(CollectionDataProviderInterface::class) - ->addTag('api_platform.collection_data_provider'); - $container->registerForAutoconfiguration(SubresourceDataProviderInterface::class) - ->addTag('api_platform.subresource_data_provider'); $container->registerForAutoconfiguration(FilterInterface::class) ->addTag('api_platform.filter'); @@ -154,57 +133,19 @@ public function load(array $configs, ContainerBuilder $container): void private function registerCommonConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader, array $formats, array $patchFormats, array $errorFormats): void { + $loader->load('symfony/events.xml'); $loader->load('api.xml'); - - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/api.xml'); - $loader->load('legacy/data_provider.xml'); - $loader->load('legacy/backward_compatibility.xml'); - } else { - $loader->load('v3/api.xml'); - $loader->load('legacy/data_provider.xml'); - $loader->load('v3/state.xml'); - $loader->load('v3/backward_compatibility.xml'); - } - - $loader->load('data_persister.xml'); - $loader->load('data_provider.xml'); + $loader->load('state.xml'); $loader->load('filter.xml'); - if ($container->hasDefinition('api_platform.operation_method_resolver')) { - $container->getDefinition('api_platform.operation_method_resolver') - ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'The "%service_id%" service is deprecated since API Platform 2.5.')); - } - - if ($container->hasDefinition('api_platform.formats_provider')) { - $container->getDefinition('api_platform.formats_provider') - ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'The "%service_id%" service is deprecated since API Platform 2.5.')); - $container->getAlias('ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface') - ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'The "%alias_id%" alias is deprecated since API Platform 2.5.')); - } - - if ($container->hasDefinition('api_platform.operation_path_resolver.underscore')) { - $container->getDefinition('api_platform.operation_path_resolver.underscore') - ->setDeprecated(...$this->buildDeprecationArgs('2.1', 'The "%service_id%" service is deprecated since API Platform 2.1 and will be removed in 3.0. Use "api_platform.path_segment_name_generator.underscore" instead.')); - } - - if ($container->hasDefinition('api_platform.operation_path_resolver.underscore')) { - $container->getDefinition('api_platform.operation_path_resolver.dash') - ->setDeprecated(...$this->buildDeprecationArgs('2.1', 'The "%service_id%" service is deprecated since API Platform 2.1 and will be removed in 3.0. Use "api_platform.path_segment_name_generator.dash" instead.')); - } - - $container->getDefinition('api_platform.filters') - ->setDeprecated(...$this->buildDeprecationArgs('2.1', 'The "%service_id%" service is deprecated since 2.1 and will be removed in 3.0. Use the "api_platform.filter_locator" service instead.')); - if (class_exists(Uuid::class)) { $loader->load('ramsey_uuid.xml'); } if (class_exists(AbstractUid::class)) { - $loader->load('symfony_uid.xml'); + $loader->load('symfony/uid.xml'); } - $container->setParameter('api_platform.metadata_backward_compatibility_layer', $config['metadata_backward_compatibility_layer']); $container->setParameter('api_platform.enable_entrypoint', $config['enable_entrypoint']); $container->setParameter('api_platform.enable_docs', $config['enable_docs']); $container->setParameter('api_platform.title', $config['title']); @@ -279,7 +220,11 @@ private function normalizeDefaults(array $defaults): array $normalizedDefaults = ['attributes' => $defaults['attributes'] ?? []]; unset($defaults['attributes']); - [$publicProperties,] = ApiResource::getConfigMetadata(); + $rc = new \ReflectionClass(ApiResource::class); + $publicProperties = []; + foreach ($rc->getConstructor()->getParameters() as $param) { + $publicProperties[$param->getName()] = true; + } $nameConverter = new CamelCaseToSnakeCaseNameConverter(); foreach ($defaults as $option => $value) { @@ -308,39 +253,11 @@ private function registerMetadataConfiguration(ContainerBuilder $container, arra )); } - $loader->load('legacy/metadata.xml'); - $container->getDefinition('api_platform.metadata.extractor.xml.legacy')->replaceArgument(0, $xmlResources); - - if (class_exists(Annotation::class)) { - $loader->load('legacy/metadata_annotation.xml'); - } - - if (interface_exists(DocBlockFactoryInterface::class)) { - $loader->load('legacy/metadata_php_doc.xml'); - } - - if (class_exists(Yaml::class)) { - $loader->load('legacy/metadata_yaml.xml'); - $container->getDefinition('api_platform.metadata.extractor.yaml.legacy')->replaceArgument(0, $yamlResources); - - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/metadata_yaml_backward_compatibility.xml'); - } - } - - // Load the legacy metadata as well - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/metadata_backward_compatibility.xml'); - - return; - } - // V3 metadata $loader->load('metadata/xml.xml'); $loader->load('metadata/links.xml'); $loader->load('metadata/property.xml'); $loader->load('metadata/resource.xml'); - $loader->load('v3/metadata.xml'); $container->getDefinition('api_platform.metadata.resource_extractor.xml')->replaceArgument(0, $xmlResources); $container->getDefinition('api_platform.metadata.property_extractor.xml')->replaceArgument(0, $xmlResources); @@ -483,22 +400,9 @@ private function registerSwaggerConfiguration(ContainerBuilder $container, array } $container->setParameter('api_platform.swagger_ui.extra_configuration', $config['openapi']['swagger_ui_extra_configuration'] ?: $config['swagger']['swagger_ui_extra_configuration']); - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/swagger.xml'); - $loader->load('legacy/openapi.xml'); - $loader->load('legacy/swagger_ui.xml'); - - if (true === $config['openapi']['backward_compatibility_layer']) { - $container->getDefinition('api_platform.swagger.normalizer.documentation')->addArgument($container->getDefinition('api_platform.openapi.normalizer')); - } - - return; - } - // for swagger 2 support - $loader->load('legacy/swagger.xml'); - $loader->load('v3/openapi.xml'); - $loader->load('v3/swagger_ui.xml'); + $loader->load('openapi.xml'); + $loader->load('swagger_ui.xml'); } private function registerJsonApiConfiguration(array $formats, XmlFileLoader $loader): void @@ -564,12 +468,6 @@ private function registerGraphQlConfiguration(ContainerBuilder $container, array $loader->load('graphql.xml'); - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/graphql.xml'); - } else { - $loader->load('v3/graphql.xml'); - } - $container->registerForAutoconfiguration(QueryItemResolverInterface::class) ->addTag('api_platform.graphql.query_resolver'); $container->registerForAutoconfiguration(QueryCollectionResolverInterface::class) @@ -582,48 +480,11 @@ private function registerGraphQlConfiguration(ContainerBuilder $container, array ->addTag('api_platform.graphql.error_handler'); } - private function registerLegacyBundlesConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void - { - /** @var string[] $bundles */ - $bundles = $container->getParameter('kernel.bundles'); - - if (isset($bundles['FOSUserBundle']) && $config['enable_fos_user']) { - $loader->load('fos_user.xml'); - } - - if (isset($bundles['NelmioApiDocBundle']) && $config['enable_nelmio_api_doc']) { - $loader->load('nelmio_api_doc.xml'); - - $container->getDefinition('api_platform.nelmio_api_doc.annotations_provider') - ->setDeprecated(...$this->buildDeprecationArgs('2.2', 'The "%service_id%" service is deprecated since API Platform 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.')); - $container->getDefinition('api_platform.nelmio_api_doc.parser') - ->setDeprecated(...$this->buildDeprecationArgs('2.2', 'The "%service_id%" service is deprecated since API Platform 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.')); - } - } - private function registerCacheConfiguration(ContainerBuilder $container): void { if (!$container->hasParameter('kernel.debug') || !$container->getParameter('kernel.debug')) { $container->removeDefinition('api_platform.cache_warmer.cache_pool_clearer'); } - - if (!$container->hasParameter('api_platform.metadata_cache')) { - return; - } - - @trigger_error('The "api_platform.metadata_cache" parameter is deprecated since version 2.4 and will have no effect in 3.0.', \E_USER_DEPRECATED); - - // BC - if (!$container->getParameter('api_platform.metadata_cache')) { - $container->removeDefinition('api_platform.cache_warmer.cache_pool_clearer'); - - $container->register('api_platform.cache.metadata.property', ArrayAdapter::class); - $container->register('api_platform.cache.metadata.resource', ArrayAdapter::class); - $container->register('api_platform.cache.route_name_resolver', ArrayAdapter::class); - $container->register('api_platform.cache.identifiers_extractor', ArrayAdapter::class); - $container->register('api_platform.cache.subresource_operation_factory', ArrayAdapter::class); - $container->register('api_platform.elasticsearch.cache.metadata.document', ArrayAdapter::class); - } } private function registerDoctrineOrmConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void @@ -640,11 +501,6 @@ private function registerDoctrineOrmConfiguration(ContainerBuilder $container, a ->setBindings(['$requestStack' => null]); $loader->load('doctrine_orm.xml'); - $loader->load('legacy/doctrine_orm.xml'); - - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('v3/doctrine_orm.xml'); - } if ($this->isConfigEnabled($container, $config['eager_loading'])) { return; @@ -670,11 +526,6 @@ private function registerDoctrineMongoDbOdmConfiguration(ContainerBuilder $conta ->setBindings(['$managerRegistry' => new Reference('doctrine_mongodb')]); $loader->load('doctrine_mongodb_odm.xml'); - $loader->load('legacy/doctrine_odm.xml'); - - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('v3/doctrine_odm.xml'); - } } private function registerHttpCacheConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void @@ -728,12 +579,8 @@ private function getFormats(array $configFormats): array private function registerValidatorConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void { if (interface_exists(ValidatorInterface::class)) { - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/validator.xml'); - } else { - $loader->load('metadata/validator.xml'); - $loader->load('symfony/validator.xml'); - } + $loader->load('metadata/validator.xml'); + $loader->load('symfony/validator.xml'); $container->registerForAutoconfiguration(ValidationGroupsGeneratorInterface::class) ->addTag('api_platform.validation_groups_generator') @@ -761,20 +608,10 @@ private function registerDataCollectorConfiguration(ContainerBuilder $container, return; } - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/data_collector.xml'); - } else { - $loader->load('v3/data_collector.xml'); - } + $loader->load('data_collector.xml'); if ($container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug')) { $loader->load('debug.xml'); - - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/debug.xml'); - } else { - $loader->load('v3/debug.xml'); - } } } @@ -790,43 +627,27 @@ private function registerMercureConfiguration(ContainerBuilder $container, array } if ($this->isConfigEnabled($container, $config['doctrine'])) { - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/doctrine_orm_mercure_publisher.xml'); - } else { - $loader->load('v3/doctrine_orm_mercure_publisher.xml'); - } + $loader->load('doctrine_orm_mercure_publisher.xml'); if (class_exists(HubRegistry::class)) { $container->getDefinition('api_platform.doctrine.orm.listener.mercure.publish')->setArgument(6, new Reference(HubRegistry::class)); } } if ($this->isConfigEnabled($container, $config['doctrine_mongodb_odm'])) { - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/doctrine_odm_mercure_publisher.xml'); - } else { - $loader->load('v3/doctrine_odm_mercure_publisher.xml'); - } + $loader->load('doctrine_odm_mercure_publisher.xml'); if (class_exists(HubRegistry::class)) { $container->getDefinition('api_platform.doctrine_mongodb.odm.listener.mercure.publish')->setArgument(6, new Reference(HubRegistry::class)); } } if ($this->isConfigEnabled($container, $config['graphql'])) { - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/graphql_mercure.xml'); - } else { - $loader->load('v3/graphql_mercure.xml'); - } + $loader->load('graphql_mercure.xml'); if (class_exists(HubRegistry::class)) { $container->getDefinition('api_platform.graphql.subscription.mercure_iri_generator')->addArgument(new Reference(HubRegistry::class)); } else { $container->getDefinition('api_platform.graphql.subscription.mercure_iri_generator')->addArgument($config['mercure']['hub_url'] ?? '%mercure.default_hub%'); } } - - if ($config['metadata_backward_compatibility_layer']) { - $container->getDefinition('api_platform.mercure.listener.response.add_link_header')->setArgument(0, new Reference('api_platform.metadata.resource.metadata_factory')); - } } private function registerMessengerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void @@ -836,10 +657,6 @@ private function registerMessengerConfiguration(ContainerBuilder $container, arr } $loader->load('messenger.xml'); - - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('v3/messenger.xml'); - } } private function registerElasticsearchConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void @@ -854,10 +671,6 @@ private function registerElasticsearchConfiguration(ContainerBuilder $container, $loader->load('elasticsearch.xml'); - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('v3/elasticsearch.xml'); - } - $container->registerForAutoconfiguration(RequestBodySearchCollectionExtensionInterface::class) ->addTag('api_platform.elasticsearch.request_body_search_extension.collection'); @@ -884,10 +697,6 @@ private function registerSecurityConfiguration(ContainerBuilder $container, XmlF } $loader->load('security.xml'); - - if ($config['metadata_backward_compatibility_layer']) { - $container->getDefinition('api_platform.security.listener.request.deny_access')->setArgument(0, new Reference('api_platform.metadata.resource.metadata_factory')); - } } private function registerOpenApiConfiguration(ContainerBuilder $container, array $config): void @@ -911,39 +720,6 @@ private function registerMakerConfiguration(ContainerBuilder $container, array $ private function registerArgumentResolverConfiguration(ContainerBuilder $container, XmlFileLoader $loader, array $config): void { - if ($config['metadata_backward_compatibility_layer']) { - return; - } - $loader->load('argument_resolver.xml'); } - - private function registerLegacyServices(ContainerBuilder $container, array $config, XmlFileLoader $loader): void - { - $container->setParameter('api_platform.metadata_backward_compatibility_layer', $config['metadata_backward_compatibility_layer']); - - $loader->load('legacy/identifiers.xml'); - - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('symfony.xml'); - - return; - } - - $loader->load('legacy/api.xml'); - } - - private function registerUpgradeCommandConfiguration(ContainerBuilder $container, XmlFileLoader $loader, array $config): void - { - $loader->load('legacy/upgrade.xml'); - } - - private function buildDeprecationArgs(string $version, string $message): array - { - return method_exists(Definition::class, 'getDeprecation') - ? ['api-platform/core', $version, $message] - : [true, $message]; - } } - -class_alias(ApiPlatformExtension::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\ApiPlatformExtension::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php index 16e0669fa14..8f072fb4f21 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php @@ -100,5 +100,3 @@ private function createFilterDefinitions(\ReflectionClass $resourceReflectionCla } } } - -class_alias(AnnotationFilterPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php index bf18c829ecf..772d370c794 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php @@ -35,5 +35,3 @@ public function process(ContainerBuilder $container): void } } } - -class_alias(AuthenticatorManagerPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php index 05e93aa07a5..f1be702b296 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderInterface; use ApiPlatform\State\SerializerAwareProviderInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -35,10 +33,6 @@ final class DataProviderPass implements CompilerPassInterface */ public function process(ContainerBuilder $container) { - foreach (OperationType::TYPES as $type) { - $this->addSerializerLocator($container, $type); - } - $services = $container->findTaggedServiceIds('api_platform.state_provider', true); foreach ($services as $id => $tags) { @@ -48,18 +42,4 @@ public function process(ContainerBuilder $container) } } } - - private function addSerializerLocator(ContainerBuilder $container, string $type): void - { - $services = $container->findTaggedServiceIds("api_platform.{$type}_data_provider", true); - - foreach ($services as $id => $tags) { - $definition = $container->getDefinition((string) $id); - if (is_a($definition->getClass(), SerializerAwareDataProviderInterface::class, true)) { - $definition->addMethodCall('setSerializerLocator', [new Reference('api_platform.serializer_locator')]); - } - } - } } - -class_alias(DataProviderPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php index b2e426b2f23..afa28c12a42 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php @@ -39,5 +39,3 @@ private function buildDeprecationArgs(string $version, string $message): array : [$message]; } } - -class_alias(DeprecateMercurePublisherPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php index 22cb662bf4e..0d99dd7468c 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php @@ -55,5 +55,3 @@ public function process(ContainerBuilder $container) } } } - -class_alias(ElasticsearchClientPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php index b77616418e0..2897b0c4e30 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php @@ -49,5 +49,3 @@ public function process(ContainerBuilder $container) $container->getDefinition('api_platform.filter_collection_factory')->addArgument(array_keys($filters)); } } - -class_alias(FilterPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\FilterPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php index 2cbcbba15bf..cb032239ece 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php @@ -45,5 +45,3 @@ public function process(ContainerBuilder $container) $container->getDefinition('api_platform.graphql.mutation_resolver_locator')->addArgument($mutations); } } - -class_alias(GraphQlMutationResolverPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php index bc00d4aaabf..882a3510317 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php @@ -45,5 +45,3 @@ public function process(ContainerBuilder $container) $container->getDefinition('api_platform.graphql.query_resolver_locator')->addArgument($resolvers); } } - -class_alias(GraphQlQueryResolverPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php index ada87331f64..3c412b33123 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php @@ -46,5 +46,3 @@ public function process(ContainerBuilder $container) $container->getDefinition('api_platform.graphql.types_factory')->addArgument(array_keys($types)); } } - -class_alias(GraphQlTypePass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php index 42454ff26dd..aee2cbf109d 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php @@ -53,5 +53,3 @@ public function process(ContainerBuilder $container) $container->setAlias('api_platform.name_converter', 'serializer.name_converter.metadata_aware'); } } - -class_alias(MetadataAwareNameConverterPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php index da6d9593436..c2812085e03 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php @@ -41,5 +41,3 @@ public function process(ContainerBuilder $container) ); } } - -class_alias(TestClientPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/DependencyInjection/Configuration.php index 3fc8affcc47..7289ef89b86 100644 --- a/src/Symfony/Bundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/DependencyInjection/Configuration.php @@ -678,4 +678,3 @@ private function buildDeprecationArgs(string $version, string $message): array } } -class_alias(Configuration::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Configuration::class); diff --git a/src/Symfony/Bundle/EventListener/SwaggerUiListener.php b/src/Symfony/Bundle/EventListener/SwaggerUiListener.php index 09020c02486..65d58468fb9 100644 --- a/src/Symfony/Bundle/EventListener/SwaggerUiListener.php +++ b/src/Symfony/Bundle/EventListener/SwaggerUiListener.php @@ -33,5 +33,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_controller', 'api_platform.swagger.action.ui'); } } - -class_alias(SwaggerUiListener::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener\SwaggerUiListener::class); diff --git a/src/Symfony/Bundle/Resources/config/api.xml b/src/Symfony/Bundle/Resources/config/api.xml index 77ceaa9df87..def9586dbe3 100644 --- a/src/Symfony/Bundle/Resources/config/api.xml +++ b/src/Symfony/Bundle/Resources/config/api.xml @@ -80,16 +80,6 @@ - - - - - - - - - - @@ -131,5 +121,60 @@ + + + + + + + %api_platform.formats% + %api_platform.resource_class_directories% + %api_platform.graphql.enabled% + %api_platform.enable_entrypoint% + %api_platform.enable_docs% + %api_platform.graphql.graphiql.enabled% + %api_platform.graphql.graphql_playground.enabled% + null + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + null + + diff --git a/src/Symfony/Bundle/Resources/config/data_collector.xml b/src/Symfony/Bundle/Resources/config/data_collector.xml index 08956bab01c..689561d3f41 100644 --- a/src/Symfony/Bundle/Resources/config/data_collector.xml +++ b/src/Symfony/Bundle/Resources/config/data_collector.xml @@ -8,11 +8,6 @@ - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/debug.xml b/src/Symfony/Bundle/Resources/config/debug.xml index d8becbdbb92..df1ad13979e 100644 --- a/src/Symfony/Bundle/Resources/config/debug.xml +++ b/src/Symfony/Bundle/Resources/config/debug.xml @@ -8,5 +8,12 @@ + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml b/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml index e06c5094b55..6ce17d97ba9 100644 --- a/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml +++ b/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml @@ -108,6 +108,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_odm_mercure_publisher.xml b/src/Symfony/Bundle/Resources/config/doctrine_odm_mercure_publisher.xml similarity index 100% rename from src/Symfony/Bundle/Resources/config/v3/doctrine_odm_mercure_publisher.xml rename to src/Symfony/Bundle/Resources/config/doctrine_odm_mercure_publisher.xml diff --git a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml index 3b783508aa8..ed332e74fa1 100644 --- a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml +++ b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml @@ -128,6 +128,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + null + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_orm_mercure_publisher.xml b/src/Symfony/Bundle/Resources/config/doctrine_orm_mercure_publisher.xml similarity index 100% rename from src/Symfony/Bundle/Resources/config/v3/doctrine_orm_mercure_publisher.xml rename to src/Symfony/Bundle/Resources/config/doctrine_orm_mercure_publisher.xml diff --git a/src/Symfony/Bundle/Resources/config/elasticsearch.xml b/src/Symfony/Bundle/Resources/config/elasticsearch.xml index 910d80ea5ff..c74b5231aed 100644 --- a/src/Symfony/Bundle/Resources/config/elasticsearch.xml +++ b/src/Symfony/Bundle/Resources/config/elasticsearch.xml @@ -134,6 +134,30 @@ %api_platform.collection.order_parameter_name% + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/fos_user.xml b/src/Symfony/Bundle/Resources/config/fos_user.xml deleted file mode 100644 index 30c0141e64a..00000000000 --- a/src/Symfony/Bundle/Resources/config/fos_user.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/graphql.xml b/src/Symfony/Bundle/Resources/config/graphql.xml index e4781353ebf..05e0f868368 100644 --- a/src/Symfony/Bundle/Resources/config/graphql.xml +++ b/src/Symfony/Bundle/Resources/config/graphql.xml @@ -91,6 +91,195 @@ + + + + + + + + + + %api_platform.graphql.nesting_separator% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %api_platform.graphql.nesting_separator% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %api_platform.allow_plain_identifiers% + null + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %api_platform.exception_to_status% + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/http_cache.xml b/src/Symfony/Bundle/Resources/config/http_cache.xml index 9c7ddd21bf1..c2bea69a9cd 100644 --- a/src/Symfony/Bundle/Resources/config/http_cache.xml +++ b/src/Symfony/Bundle/Resources/config/http_cache.xml @@ -11,7 +11,6 @@ %api_platform.http_cache.shared_max_age% %api_platform.http_cache.vary% %api_platform.http_cache.public% - null diff --git a/src/Symfony/Bundle/Resources/config/legacy/README b/src/Symfony/Bundle/Resources/config/legacy/README deleted file mode 100644 index b90488053fa..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/README +++ /dev/null @@ -1 +0,0 @@ -The `legacy` directory declares API Platform 2.x services. This directory will be removed in 3.0 but kept in 2.7. diff --git a/src/Symfony/Bundle/Resources/config/legacy/api.xml b/src/Symfony/Bundle/Resources/config/legacy/api.xml deleted file mode 100644 index cceb903baa5..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/api.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - - - - %api_platform.formats% - %api_platform.resource_class_directories% - - %api_platform.graphql.enabled% - %api_platform.enable_entrypoint% - %api_platform.enable_docs% - %api_platform.graphql.graphiql.enabled% - %api_platform.graphql.graphql_playground.enabled% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - - - - - - - - - - - - - - - - null - - - - - - %api_platform.error_formats% - %api_platform.exception_to_status% - - - - - - api_platform.action.exception - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/backward_compatibility.xml b/src/Symfony/Bundle/Resources/config/legacy/backward_compatibility.xml deleted file mode 100644 index 00562814160..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/backward_compatibility.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/data_collector.xml b/src/Symfony/Bundle/Resources/config/legacy/data_collector.xml deleted file mode 100644 index 3e484801f45..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/data_collector.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/data_provider.xml b/src/Symfony/Bundle/Resources/config/legacy/data_provider.xml deleted file mode 100644 index 78458553729..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/data_provider.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - %api_platform.collection.pagination% - %api_platform.graphql.collection.pagination% - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/debug.xml b/src/Symfony/Bundle/Resources/config/legacy/debug.xml deleted file mode 100644 index 65045e79405..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/debug.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm.xml b/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm.xml deleted file mode 100644 index 430f5d7974f..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm_mercure_publisher.xml b/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm_mercure_publisher.xml deleted file mode 100644 index 8d7c9672b12..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm_mercure_publisher.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm.xml deleted file mode 100644 index 0b135d72ad3..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - null - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm_mercure_publisher.xml b/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm_mercure_publisher.xml deleted file mode 100644 index fbd3d138618..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm_mercure_publisher.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/graphql.xml b/src/Symfony/Bundle/Resources/config/legacy/graphql.xml deleted file mode 100644 index 4403fc2f7d8..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/graphql.xml +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.graphql.nesting_separator% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.graphql.nesting_separator% - - - - - - - - - - - - - - - - - - - - - - - - - - - %kernel.debug% - %api_platform.graphql.graphiql.enabled% - %api_platform.graphql.graphql_playground.enabled% - %api_platform.graphql.default_ide% - - - - - - %api_platform.graphql.graphiql.enabled% - %api_platform.title% - %api_platform.asset_package% - - - - - - %api_platform.graphql.graphql_playground.enabled% - %api_platform.title% - %api_platform.asset_package% - - - - - - - - - - - - - - - %api_platform.allow_plain_identifiers% - null - - - - - - - - - - - - - - - - - - - - - - %api_platform.exception_to_status% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/graphql_mercure.xml b/src/Symfony/Bundle/Resources/config/legacy/graphql_mercure.xml deleted file mode 100644 index cc7249aed7a..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/graphql_mercure.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/identifiers.xml b/src/Symfony/Bundle/Resources/config/legacy/identifiers.xml deleted file mode 100644 index 80eed2426af..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/identifiers.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - %api_platform.metadata_backward_compatibility_layer% - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata.xml deleted file mode 100644 index 94f4449f4d0..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - %api_platform.patch_formats% - - - - - %api_platform.formats% - %api_platform.patch_formats% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_annotation.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_annotation.xml deleted file mode 100644 index 880407eaf77..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_annotation.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - %api_platform.resource_class_directories% - - - - - - - %api_platform.defaults% - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_backward_compatibility.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_backward_compatibility.xml deleted file mode 100644 index 36c90c2c795..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_backward_compatibility.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_php_doc.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_php_doc.xml deleted file mode 100644 index 5865e92dd93..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_php_doc.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml.xml deleted file mode 100644 index cfb76ecbe08..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - %api_platform.defaults% - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml_backward_compatibility.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml_backward_compatibility.xml deleted file mode 100644 index 0dd363e5cfe..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml_backward_compatibility.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/openapi.xml b/src/Symfony/Bundle/Resources/config/legacy/openapi.xml deleted file mode 100644 index 68b0df9f725..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/openapi.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - %api_platform.formats% - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/swagger.xml b/src/Symfony/Bundle/Resources/config/legacy/swagger.xml deleted file mode 100644 index 3bd9b39e36d..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/swagger.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - null - - null - %api_platform.oauth.enabled% - %api_platform.oauth.type% - %api_platform.oauth.flow% - %api_platform.oauth.tokenUrl% - %api_platform.oauth.authorizationUrl% - %api_platform.oauth.scopes% - %api_platform.swagger.api_keys% - - %api_platform.collection.pagination.enabled% - %api_platform.collection.pagination.page_parameter_name% - %api_platform.collection.pagination.client_items_per_page% - %api_platform.collection.pagination.items_per_page_parameter_name% - %api_platform.formats% - %api_platform.collection.pagination.client_enabled% - %api_platform.collection.pagination.enabled_parameter_name% - - %api_platform.swagger.versions% - - null - %api_platform.metadata_backward_compatibility_layer% - - - - - - - - - - - - %api_platform.title% - %api_platform.description% - %api_platform.version% - null - %api_platform.swagger.versions% - %api_platform.metadata_backward_compatibility_layer% - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/swagger_ui.xml b/src/Symfony/Bundle/Resources/config/legacy/swagger_ui.xml deleted file mode 100644 index c9739cc0f4c..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/swagger_ui.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - %api_platform.formats% - %api_platform.oauth.clientId% - %api_platform.oauth.clientSecret% - %api_platform.oauth.pkce% - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/upgrade.xml b/src/Symfony/Bundle/Resources/config/legacy/upgrade.xml deleted file mode 100644 index 33f0b6094fb..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/upgrade.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/validator.xml b/src/Symfony/Bundle/Resources/config/legacy/validator.xml deleted file mode 100644 index 9cf8d42f5e2..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/validator.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.validator.query_parameter_validation% - - - - - diff --git a/src/Symfony/Bundle/Resources/config/maker.xml b/src/Symfony/Bundle/Resources/config/maker.xml index f829cf3af09..5b6be1706b0 100644 --- a/src/Symfony/Bundle/Resources/config/maker.xml +++ b/src/Symfony/Bundle/Resources/config/maker.xml @@ -5,15 +5,15 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - - - - - - - - + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/messenger.xml b/src/Symfony/Bundle/Resources/config/messenger.xml index 69eacad40db..8e80e617450 100644 --- a/src/Symfony/Bundle/Resources/config/messenger.xml +++ b/src/Symfony/Bundle/Resources/config/messenger.xml @@ -7,11 +7,8 @@ - - - - - + + @@ -20,11 +17,6 @@ - - - - - diff --git a/src/Symfony/Bundle/Resources/config/metadata/property.xml b/src/Symfony/Bundle/Resources/config/metadata/property.xml index 82fe8b3c984..05498db2f5f 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/property.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/property.xml @@ -5,6 +5,8 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + @@ -52,11 +54,6 @@ - - - - - diff --git a/src/Symfony/Bundle/Resources/config/metadata/resource_name.xml b/src/Symfony/Bundle/Resources/config/metadata/resource_name.xml index 2613336d50d..df4e7f3a425 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/resource_name.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/resource_name.xml @@ -23,5 +23,9 @@ + + %api_platform.resource_class_directories% + + diff --git a/src/Symfony/Bundle/Resources/config/nelmio_api_doc.xml b/src/Symfony/Bundle/Resources/config/nelmio_api_doc.xml deleted file mode 100644 index 9bfd8a8f6d6..00000000000 --- a/src/Symfony/Bundle/Resources/config/nelmio_api_doc.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/openapi.xml b/src/Symfony/Bundle/Resources/config/openapi.xml index b35d80da872..c54481d2095 100644 --- a/src/Symfony/Bundle/Resources/config/openapi.xml +++ b/src/Symfony/Bundle/Resources/config/openapi.xml @@ -61,6 +61,22 @@ + + + + + + + + + + %api_platform.formats% + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/data_provider.xml b/src/Symfony/Bundle/Resources/config/state.xml similarity index 61% rename from src/Symfony/Bundle/Resources/config/data_provider.xml rename to src/Symfony/Bundle/Resources/config/state.xml index edbe31d3d2e..b18400712f7 100644 --- a/src/Symfony/Bundle/Resources/config/data_provider.xml +++ b/src/Symfony/Bundle/Resources/config/state.xml @@ -3,15 +3,31 @@ - + + + + + + + + %api_platform.collection.pagination% + %api_platform.graphql.collection.pagination% + + + + + + + + + - %api_platform.collection.pagination.enabled% %api_platform.collection.pagination.page_parameter_name% @@ -27,5 +43,4 @@ - diff --git a/src/Symfony/Bundle/Resources/config/swagger_ui.xml b/src/Symfony/Bundle/Resources/config/swagger_ui.xml index dd7c83de602..e60682f7fef 100644 --- a/src/Symfony/Bundle/Resources/config/swagger_ui.xml +++ b/src/Symfony/Bundle/Resources/config/swagger_ui.xml @@ -19,34 +19,17 @@ %api_platform.swagger_ui.extra_configuration% - - - - + + - %api_platform.title% - %api_platform.description% - %api_platform.version% + + + + %api_platform.formats% - %api_platform.oauth.enabled% %api_platform.oauth.clientId% %api_platform.oauth.clientSecret% - %api_platform.oauth.type% - %api_platform.oauth.flow% - %api_platform.oauth.tokenUrl% - %api_platform.oauth.authorizationUrl% - %api_platform.oauth.scopes% - %api_platform.show_webby% - %api_platform.enable_swagger_ui% - %api_platform.enable_re_doc% - %api_platform.graphql.enabled% - %api_platform.graphql.graphiql.enabled% - %api_platform.graphql.graphql_playground.enabled% - %api_platform.swagger.versions% - - %api_platform.asset_package% - %api_platform.swagger_ui.extra_configuration% %api_platform.oauth.pkce% diff --git a/src/Symfony/Bundle/Resources/config/symfony.xml b/src/Symfony/Bundle/Resources/config/symfony/events.xml similarity index 100% rename from src/Symfony/Bundle/Resources/config/symfony.xml rename to src/Symfony/Bundle/Resources/config/symfony/events.xml diff --git a/src/Symfony/Bundle/Resources/config/symfony_uid.xml b/src/Symfony/Bundle/Resources/config/symfony/uid.xml similarity index 100% rename from src/Symfony/Bundle/Resources/config/symfony_uid.xml rename to src/Symfony/Bundle/Resources/config/symfony/uid.xml diff --git a/src/Symfony/Bundle/Resources/config/v3/api.xml b/src/Symfony/Bundle/Resources/config/v3/api.xml deleted file mode 100644 index 630eb93e364..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/api.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - %api_platform.formats% - %api_platform.resource_class_directories% - null - %api_platform.graphql.enabled% - %api_platform.enable_entrypoint% - %api_platform.enable_docs% - %api_platform.graphql.graphiql.enabled% - %api_platform.graphql.graphql_playground.enabled% - null - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - null - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/backward_compatibility.xml b/src/Symfony/Bundle/Resources/config/v3/backward_compatibility.xml deleted file mode 100644 index c242414a4aa..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/backward_compatibility.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - %api_platform.defaults% - - - - - - - - - - - - - - - - - - - - %api_platform.metadata_backward_compatibility_layer% - - - - - - - - - - - - null - %api_platform.metadata_backward_compatibility_layer% - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/data_collector.xml b/src/Symfony/Bundle/Resources/config/v3/data_collector.xml deleted file mode 100644 index 382895236d1..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/data_collector.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/debug.xml b/src/Symfony/Bundle/Resources/config/v3/debug.xml deleted file mode 100644 index 412f179d7d8..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/debug.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml b/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml deleted file mode 100644 index 7870a67a3da..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml deleted file mode 100644 index e3d8c6da9a3..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - null - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/elasticsearch.xml b/src/Symfony/Bundle/Resources/config/v3/elasticsearch.xml deleted file mode 100644 index c04b5eaa882..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/elasticsearch.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/graphql.xml b/src/Symfony/Bundle/Resources/config/v3/graphql.xml deleted file mode 100644 index 180cba84b0e..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/graphql.xml +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - %api_platform.graphql.nesting_separator% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.graphql.nesting_separator% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.allow_plain_identifiers% - null - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.exception_to_status% - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/graphql_mercure.xml b/src/Symfony/Bundle/Resources/config/v3/graphql_mercure.xml deleted file mode 100644 index f682291900e..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/graphql_mercure.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/messenger.xml b/src/Symfony/Bundle/Resources/config/v3/messenger.xml deleted file mode 100644 index de581cca87e..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/messenger.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/metadata.xml b/src/Symfony/Bundle/Resources/config/v3/metadata.xml deleted file mode 100644 index 76885ef83ea..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/metadata.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - %api_platform.resource_class_directories% - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/openapi.xml b/src/Symfony/Bundle/Resources/config/v3/openapi.xml deleted file mode 100644 index 819742bf4d8..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/openapi.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/state.xml b/src/Symfony/Bundle/Resources/config/v3/state.xml deleted file mode 100644 index 9004bdd9d5d..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/state.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - %api_platform.collection.pagination% - %api_platform.graphql.collection.pagination% - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/swagger_ui.xml b/src/Symfony/Bundle/Resources/config/v3/swagger_ui.xml deleted file mode 100644 index f53c4f0f05c..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/swagger_ui.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - %api_platform.formats% - %api_platform.oauth.clientId% - %api_platform.oauth.clientSecret% - %api_platform.oauth.pkce% - - - diff --git a/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php b/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php index ca84d92ee1a..0a87bb126fa 100644 --- a/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php +++ b/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php @@ -135,5 +135,3 @@ private function getPathAndMethod(array $swaggerData): array throw new RuntimeException(sprintf('The operation "%s" cannot be found in the Swagger specification.', $swaggerData['operationId'])); } } - -class_alias(SwaggerUiAction::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi\SwaggerUiAction::class); diff --git a/src/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php b/src/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php index 5b113ed8b22..f8e4cd347af 100644 --- a/src/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php +++ b/src/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php @@ -76,5 +76,3 @@ public function getExtraConfiguration(): array return $this->extraConfiguration; } } - -class_alias(SwaggerUiContext::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi\SwaggerUiContext::class); diff --git a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php b/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php index 1af59ecdfb1..f2c687e2a3a 100644 --- a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php +++ b/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php @@ -162,5 +162,3 @@ private static function getSchemaFactory(): SchemaFactoryInterface return $schemaFactory; } } - -class_alias(ApiTestAssertionsTrait::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestAssertionsTrait::class); diff --git a/src/Symfony/Bundle/Test/ApiTestCase.php b/src/Symfony/Bundle/Test/ApiTestCase.php index 94b121f285e..ae251ecdc13 100644 --- a/src/Symfony/Bundle/Test/ApiTestCase.php +++ b/src/Symfony/Bundle/Test/ApiTestCase.php @@ -105,5 +105,3 @@ protected function findIriBy(string $resourceClass, array $criteria): ?string return $iriConverter instanceof LegacyIriConverterInterface ? $iriConverter->getIriFromItem($item) : $iriConverter->getIriFromResource($item); } } - -class_alias(ApiTestCase::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase::class); diff --git a/src/Symfony/Bundle/Test/Client.php b/src/Symfony/Bundle/Test/Client.php index f7b45308104..aaae8e5c3f3 100644 --- a/src/Symfony/Bundle/Test/Client.php +++ b/src/Symfony/Bundle/Test/Client.php @@ -256,5 +256,3 @@ public function loginUser(UserInterface $user, string $firewallContext = 'main') return $this; } } - -class_alias(Client::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client::class); diff --git a/src/Symfony/Bundle/Test/Constraint/ArraySubset.php b/src/Symfony/Bundle/Test/Constraint/ArraySubset.php index 1eae632d5d6..758e4063b58 100644 --- a/src/Symfony/Bundle/Test/Constraint/ArraySubset.php +++ b/src/Symfony/Bundle/Test/Constraint/ArraySubset.php @@ -18,12 +18,8 @@ use SebastianBergmann\Comparator\ComparisonFailure as LegacyComparisonFailure; if (!class_exists(ComparisonFailure::class) && class_exists(LegacyComparisonFailure::class)) { - class_alias(LegacyComparisonFailure::class, 'PHPUnit\SebastianBergmann\Comparator\ComparisonFailure'); } // Aliases as string to avoid loading the class if (\PHP_VERSION_ID >= 80000 || (float) Version::series() >= 9) { - class_alias('ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubsetV9', 'ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubset'); -} else { - class_alias('ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubsetLegacy', 'ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubset'); } diff --git a/src/Symfony/Bundle/Test/Response.php b/src/Symfony/Bundle/Test/Response.php index e96ee96c100..4f06632ce64 100644 --- a/src/Symfony/Bundle/Test/Response.php +++ b/src/Symfony/Bundle/Test/Response.php @@ -180,5 +180,3 @@ public function cancel(): void $this->info['error'] = 'Response has been canceled.'; } } - -class_alias(Response::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Response::class); diff --git a/src/Symfony/EventListener/AddFormatListener.php b/src/Symfony/EventListener/AddFormatListener.php index b85c1f1cf29..f4896f59b03 100644 --- a/src/Symfony/EventListener/AddFormatListener.php +++ b/src/Symfony/EventListener/AddFormatListener.php @@ -188,5 +188,3 @@ private function getNotAcceptableHttpException(string $accept, array $mimeTypes) )); } } - -class_alias(AddFormatListener::class, \ApiPlatform\Core\EventListener\AddFormatListener::class); diff --git a/src/Symfony/EventListener/AddLinkHeaderListener.php b/src/Symfony/EventListener/AddLinkHeaderListener.php index 88f16c383ed..18b8ce1ed8c 100644 --- a/src/Symfony/EventListener/AddLinkHeaderListener.php +++ b/src/Symfony/EventListener/AddLinkHeaderListener.php @@ -104,5 +104,3 @@ public function onKernelResponse(ResponseEvent $event): void $this->discovery->addLink($request, $hub); } } - -class_alias(AddLinkHeaderListener::class, \ApiPlatform\Core\Mercure\EventListener\AddLinkHeaderListener::class); diff --git a/src/Symfony/EventListener/DenyAccessListener.php b/src/Symfony/EventListener/DenyAccessListener.php index 9852c172947..e40ca7cd4dc 100644 --- a/src/Symfony/EventListener/DenyAccessListener.php +++ b/src/Symfony/EventListener/DenyAccessListener.php @@ -155,5 +155,3 @@ private function checkSecurity(Request $request, string $attribute, bool $backwa } } } - -class_alias(DenyAccessListener::class, \ApiPlatform\Core\Security\EventListener\DenyAccessListener::class); diff --git a/src/Symfony/EventListener/DeserializeListener.php b/src/Symfony/EventListener/DeserializeListener.php index ab29409842e..44049bf7c3e 100644 --- a/src/Symfony/EventListener/DeserializeListener.php +++ b/src/Symfony/EventListener/DeserializeListener.php @@ -14,9 +14,6 @@ namespace ApiPlatform\Symfony\EventListener; use ApiPlatform\Api\FormatMatcher; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; @@ -35,44 +32,17 @@ final class DeserializeListener { use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; public const OPERATION_ATTRIBUTE_KEY = 'deserialize'; private $serializer; private $serializerContextBuilder; - private $formats; - private $formatsProvider; - /** - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface|FormatsProviderInterface|array $resourceMetadataFactory - */ - public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, $resourceMetadataFactory) + public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { $this->serializer = $serializer; $this->serializerContextBuilder = $serializerContextBuilder; - - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if ($resourceMetadataFactory) { - if (!$resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - @trigger_error(sprintf('Passing an array or an instance of "%s" as 3rd parameter of the constructor of "%s" is deprecated since API Platform 2.5, pass an instance of "%s" instead', FormatsProviderInterface::class, __CLASS__, ResourceMetadataFactoryInterface::class), \E_USER_DEPRECATED); - } - - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - if ($resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } - } - - if (\is_array($resourceMetadataFactory)) { - $this->formats = $resourceMetadataFactory; - } elseif ($resourceMetadataFactory instanceof FormatsProviderInterface) { - $this->formatsProvider = $resourceMetadataFactory; - } + $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; } /** @@ -101,32 +71,9 @@ public function onKernelRequest(RequestEvent $event): void return; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && ( - !$attributes['receive'] - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) - )) { - return; - } - $context = $this->serializerContextBuilder->createFromRequest($request, false, $attributes); - $formats = $operation ? $operation->getInputFormats() ?? null : null; - - if (!$formats) { - // BC check to be removed in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - @trigger_error('When using a "route_name", be sure to define the "_api_operation" route defaults as we will not rely on metadata in API Platform 3.0.', \E_USER_DEPRECATED); - $formats = $this->resourceMetadataFactory - ->create($attributes['resource_class']) - ->getOperationAttribute($attributes, 'input_formats', [], true); - } elseif ($this->formatsProvider instanceof FormatsProviderInterface) { - $formats = $this->formatsProvider->getFormatsFromAttributes($attributes); - } else { - $formats = $this->formats; - } - } - - $format = $this->getFormat($request, $formats); + $format = $this->getFormat($request, $operation->getInputFormats() ?? []); $data = $request->attributes->get('data'); if (null !== $data) { $context[AbstractNormalizer::OBJECT_TO_POPULATE] = $data; @@ -169,5 +116,3 @@ private function getFormat(Request $request, array $formats): string return $format; } } - -class_alias(DeserializeListener::class, \ApiPlatform\Core\EventListener\DeserializeListener::class); diff --git a/src/Symfony/EventListener/EventPriorities.php b/src/Symfony/EventListener/EventPriorities.php index 3ec8faa4c65..bfa958a26e7 100644 --- a/src/Symfony/EventListener/EventPriorities.php +++ b/src/Symfony/EventListener/EventPriorities.php @@ -36,5 +36,3 @@ final class EventPriorities // kernel.response public const POST_RESPOND = 0; } - -class_alias(EventPriorities::class, \ApiPlatform\Core\EventListener\EventPriorities::class); diff --git a/src/Symfony/EventListener/ExceptionListener.php b/src/Symfony/EventListener/ExceptionListener.php index 8afdb5b4cea..58e1efb367f 100644 --- a/src/Symfony/EventListener/ExceptionListener.php +++ b/src/Symfony/EventListener/ExceptionListener.php @@ -51,5 +51,3 @@ public function onKernelException(ExceptionEvent $event): void $this->exceptionListener->onKernelException($event); } } - -class_alias(ExceptionListener::class, \ApiPlatform\Core\EventListener\ExceptionListener::class); diff --git a/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php index 58b9e5eeb82..6716d8a49fd 100644 --- a/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php @@ -88,5 +88,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_api_filter_property', $properties); } } - -class_alias(TransformFieldsetsParametersListener::class, \ApiPlatform\Core\JsonApi\EventListener\TransformFieldsetsParametersListener::class); diff --git a/src/Symfony/EventListener/JsonApi/TransformFilteringParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformFilteringParametersListener.php index a683dabde86..18efa74852d 100644 --- a/src/Symfony/EventListener/JsonApi/TransformFilteringParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformFilteringParametersListener.php @@ -41,5 +41,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_api_filters', array_merge($filterParameter, $filters)); } } - -class_alias(TransformFilteringParametersListener::class, \ApiPlatform\Core\JsonApi\EventListener\TransformFilteringParametersListener::class); diff --git a/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php index 0c33f88edbf..ec5cd2fd49f 100644 --- a/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php @@ -43,5 +43,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_api_pagination', $pageParameter); } } - -class_alias(TransformPaginationParametersListener::class, \ApiPlatform\Core\JsonApi\EventListener\TransformPaginationParametersListener::class); diff --git a/src/Symfony/EventListener/JsonApi/TransformSortingParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformSortingParametersListener.php index 70e87d9b0ec..fc732b80107 100644 --- a/src/Symfony/EventListener/JsonApi/TransformSortingParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformSortingParametersListener.php @@ -63,5 +63,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_api_filters', $filters); } } - -class_alias(TransformSortingParametersListener::class, \ApiPlatform\Core\JsonApi\EventListener\TransformSortingParametersListener::class); diff --git a/src/Symfony/EventListener/QueryParameterValidateListener.php b/src/Symfony/EventListener/QueryParameterValidateListener.php index 17c1ec5a4c7..ed6445416fe 100644 --- a/src/Symfony/EventListener/QueryParameterValidateListener.php +++ b/src/Symfony/EventListener/QueryParameterValidateListener.php @@ -14,9 +14,6 @@ namespace ApiPlatform\Symfony\EventListener; use ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator; -use ApiPlatform\Core\Filter\QueryParameterValidator as LegacyQueryParameterValidator; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; @@ -32,7 +29,6 @@ final class QueryParameterValidateListener { use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; public const OPERATION_ATTRIBUTE_KEY = 'query_parameter_validate'; @@ -42,19 +38,9 @@ final class QueryParameterValidateListener private $enabled; - /** - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - * @param QueryParameterValidator|LegacyQueryParameterValidator $queryParameterValidator - */ - public function __construct($resourceMetadataFactory, $queryParameterValidator, bool $enabled = true) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, QueryParameterValidator $queryParameterValidator, bool $enabled = true) { - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } else { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; + $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; $this->queryParameterValidator = $queryParameterValidator; $this->enabled = $enabled; } @@ -72,33 +58,12 @@ public function onKernelRequest(RequestEvent $event) return; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && - (!$operation || !($operation->getQueryParameterValidationEnabled() ?? true) || !$operation instanceof CollectionOperationInterface) - ) { - return; - } - - // TODO: remove in 3.0 - $operationName = $attributes['collection_operation_name'] ?? null; - if (!$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && - ( - null === $operationName - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY, !$this->enabled) - ) - ) { + if (!$operation || !($operation->getQueryParameterValidationEnabled() ?? true) || !$operation instanceof CollectionOperationInterface) { return; } $queryString = RequestParser::getQueryString($request); $queryParameters = $queryString ? RequestParser::parseRequestParams($queryString) : []; - $resourceFilters = []; - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceFilters = $this->resourceMetadataFactory->create($attributes['resource_class'])->getCollectionOperationAttribute($operationName, 'filters', [], true); - } elseif ($operation) { - $resourceFilters = $operation->getFilters() ?? []; - } - $this->queryParameterValidator->validateFilters($attributes['resource_class'], $resourceFilters, $queryParameters); + $this->queryParameterValidator->validateFilters($attributes['resource_class'], $operation->getFilters() ?? [], $queryParameters); } } - -class_alias(QueryParameterValidateListener::class, \ApiPlatform\Core\EventListener\QueryParameterValidateListener::class); diff --git a/src/Symfony/EventListener/RespondListener.php b/src/Symfony/EventListener/RespondListener.php index 1dbd7ed09f7..6e8645808d2 100644 --- a/src/Symfony/EventListener/RespondListener.php +++ b/src/Symfony/EventListener/RespondListener.php @@ -156,5 +156,3 @@ private function addAcceptPatchHeader(array $headers, array $attributes, Resourc return $headers; } } - -class_alias(RespondListener::class, \ApiPlatform\Core\EventListener\RespondListener::class); diff --git a/src/Symfony/EventListener/SerializeListener.php b/src/Symfony/EventListener/SerializeListener.php index d9789078711..07fcb569e2f 100644 --- a/src/Symfony/EventListener/SerializeListener.php +++ b/src/Symfony/EventListener/SerializeListener.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\ResourceList; @@ -38,26 +36,17 @@ final class SerializeListener { use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; public const OPERATION_ATTRIBUTE_KEY = 'serialize'; private $serializer; private $serializerContextBuilder; - public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, $resourceMetadataFactory = null) + public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { $this->serializer = $serializer; $this->serializerContextBuilder = $serializerContextBuilder; - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if ($resourceMetadataFactory && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - if ($resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } + $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; } /** @@ -75,21 +64,11 @@ public function onKernelView(ViewEvent $event): void $attributes = RequestAttributesExtractor::extractAttributes($request); - // TODO: 3.0 remove condition - if ( - (!$this->resourceMetadataFactory || $this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) - && - ( - !($attributes['respond'] ?? $request->attributes->getBoolean('_api_respond', false)) - || ($attributes && $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY)) - ) - ) { + if (!($attributes['respond'] ?? $request->attributes->getBoolean('_api_respond', false))) { return; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && - ($operation && !($operation->canSerialize() ?? true)) - ) { + if (!$operation || !($operation->canSerialize() ?? true)) { return; } @@ -154,5 +133,3 @@ private function serializeRawData(ViewEvent $event, Request $request, $controlle $event->setControllerResult($this->serializer->encode($controllerResult, $request->getRequestFormat())); } } - -class_alias(SerializeListener::class, \ApiPlatform\Core\EventListener\SerializeListener::class); diff --git a/src/Symfony/EventListener/ValidateListener.php b/src/Symfony/EventListener/ValidateListener.php index e610814a048..61bfe23f86f 100644 --- a/src/Symfony/EventListener/ValidateListener.php +++ b/src/Symfony/EventListener/ValidateListener.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; use ApiPlatform\Util\RequestAttributesExtractor; @@ -31,23 +29,16 @@ final class ValidateListener { use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; public const OPERATION_ATTRIBUTE_KEY = 'validate'; private $validator; private $resourceMetadataFactory; - public function __construct(ValidatorInterface $validator, $resourceMetadataFactory) + public function __construct(ValidatorInterface $validator, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { $this->validator = $validator; - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } else { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } + $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; } /** @@ -70,32 +61,10 @@ public function onKernelView(ViewEvent $event): void return; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && - (!$operation || !($operation->canValidate() ?? true)) - ) { - return; - } - - // TODO: 3.0 remove condition - if ( - $this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && ( - !$attributes['receive'] - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) - ) - ) { + if (!$operation || !($operation->canValidate() ?? true)) { return; } - $validationContext = $operation ? ($operation->getValidationContext() ?? []) : []; - - if (!$validationContext && $this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - $validationGroups = $resourceMetadata->getOperationAttribute($attributes, 'validation_groups', null, true); - $validationContext = ['groups' => $validationGroups]; - } - - $this->validator->validate($controllerResult, $validationContext); + $this->validator->validate($controllerResult, $operation->getValidationContext() ?? []); } } - -class_alias(ValidateListener::class, \ApiPlatform\Core\Validator\EventListener\ValidateListener::class); diff --git a/src/Symfony/Messenger/ContextStamp.php b/src/Symfony/Messenger/ContextStamp.php index c49268ea9a7..11be14f7ab8 100644 --- a/src/Symfony/Messenger/ContextStamp.php +++ b/src/Symfony/Messenger/ContextStamp.php @@ -39,5 +39,3 @@ public function getContext(): array return $this->context; } } - -class_alias(ContextStamp::class, \ApiPlatform\Core\Bridge\Symfony\Messenger\ContextStamp::class); diff --git a/src/Symfony/Messenger/DispatchTrait.php b/src/Symfony/Messenger/DispatchTrait.php index f60329b8b0e..0502be7a40f 100644 --- a/src/Symfony/Messenger/DispatchTrait.php +++ b/src/Symfony/Messenger/DispatchTrait.php @@ -53,5 +53,3 @@ private function dispatch($message) } } } - -class_alias(DispatchTrait::class, \ApiPlatform\Core\Bridge\Symfony\Messenger\DispatchTrait::class); diff --git a/src/Symfony/Messenger/RemoveStamp.php b/src/Symfony/Messenger/RemoveStamp.php index 4e7f690c428..dc12d1b2166 100644 --- a/src/Symfony/Messenger/RemoveStamp.php +++ b/src/Symfony/Messenger/RemoveStamp.php @@ -25,5 +25,3 @@ final class RemoveStamp implements StampInterface { } - -class_alias(RemoveStamp::class, \ApiPlatform\Core\Bridge\Symfony\Messenger\RemoveStamp::class); diff --git a/src/Symfony/Routing/ApiLoader.php b/src/Symfony/Routing/ApiLoader.php index 5a7459efdd6..ed6fb74d821 100644 --- a/src/Symfony/Routing/ApiLoader.php +++ b/src/Symfony/Routing/ApiLoader.php @@ -13,19 +13,10 @@ namespace ApiPlatform\Symfony\Routing; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Exception\InvalidResourceException; -use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\PathResolver\OperationPathResolverInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\Config\Resource\DirectoryResource; @@ -51,11 +42,9 @@ final class ApiLoader extends Loader private $fileLoader; private $resourceNameCollectionFactory; private $resourceMetadataFactory; - private $operationPathResolver; private $container; private $formats; private $resourceClassDirectories; - private $subresourceOperationFactory; private $graphqlEnabled; private $graphiQlEnabled; private $graphQlPlaygroundEnabled; @@ -63,28 +52,21 @@ final class ApiLoader extends Loader private $docsEnabled; private $identifiersExtractor; - public function __construct(KernelInterface $kernel, ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, $resourceMetadataFactory, OperationPathResolverInterface $operationPathResolver, ContainerInterface $container, array $formats, array $resourceClassDirectories = [], SubresourceOperationFactoryInterface $subresourceOperationFactory = null, bool $graphqlEnabled = false, bool $entrypointEnabled = true, bool $docsEnabled = true, bool $graphiQlEnabled = false, bool $graphQlPlaygroundEnabled = false, IdentifiersExtractorInterface $identifiersExtractor = null) + public function __construct(KernelInterface $kernel, ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ContainerInterface $container, array $formats, array $resourceClassDirectories = [], bool $graphqlEnabled = false, bool $entrypointEnabled = true, bool $docsEnabled = true, bool $graphiQlEnabled = false, bool $graphQlPlaygroundEnabled = false) { /** @var string[]|string $paths */ $paths = $kernel->locateResource('@ApiPlatformBundle/Resources/config/routing'); $this->fileLoader = new XmlFileLoader(new FileLocator($paths)); $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->operationPathResolver = $operationPathResolver; $this->container = $container; $this->formats = $formats; $this->resourceClassDirectories = $resourceClassDirectories; - $this->subresourceOperationFactory = $subresourceOperationFactory; $this->graphqlEnabled = $graphqlEnabled; $this->graphiQlEnabled = $graphiQlEnabled; $this->graphQlPlaygroundEnabled = $graphQlPlaygroundEnabled; $this->entrypointEnabled = $entrypointEnabled; $this->docsEnabled = $docsEnabled; - $this->identifiersExtractor = $identifiersExtractor; } /** @@ -99,42 +81,36 @@ public function load($data, $type = null): RouteCollection $this->loadExternalFiles($routeCollection); foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $this->loadLegacyMetadata($routeCollection, $resourceClass); - $this->loadLegacySubresources($routeCollection, $resourceClass); - continue; - } - foreach ($this->resourceMetadataFactory->create($resourceClass) as $resourceMetadata) { foreach ($resourceMetadata->getOperations() as $operationName => $operation) { if ($operation->getRouteName()) { continue; } - $legacyDefaults = []; - - if ($operation->getExtraProperties()['is_legacy_subresource'] ?? false) { - $legacyDefaults['_api_subresource_operation_name'] = $operationName; - $legacyDefaults['_api_subresource_context'] = [ - 'property' => $operation->getExtraProperties()['legacy_subresource_property'], - 'identifiers' => $operation->getExtraProperties()['legacy_subresource_identifiers'], - 'collection' => $operation instanceof CollectionOperationInterface, - 'operationId' => $operation->getExtraProperties()['legacy_subresource_operation_name'] ?? null, - ]; - $legacyDefaults['_api_identifiers'] = $operation->getExtraProperties()['legacy_subresource_identifiers']; - } elseif ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) { - $legacyDefaults[sprintf('_api_%s_operation_name', $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM)] = $operationName; - $legacyDefaults['_api_identifiers'] = []; - // Legacy identifiers - $hasCompositeIdentifier = false; - foreach ($operation->getUriVariables() ?? [] as $parameterName => $identifiedBy) { - $hasCompositeIdentifier = $identifiedBy->getCompositeIdentifier(); - foreach ($identifiedBy->getIdentifiers() ?? [] as $identifier) { - $legacyDefaults['_api_identifiers'][] = $identifier; - } - } - $legacyDefaults['_api_has_composite_identifier'] = $hasCompositeIdentifier; - } + // $legacyDefaults = []; + + // if ($operation->getExtraProperties()['is_legacy_subresource'] ?? false) { + // $legacyDefaults['_api_subresource_operation_name'] = $operationName; + // $legacyDefaults['_api_subresource_context'] = [ + // 'property' => $operation->getExtraProperties()['legacy_subresource_property'], + // 'identifiers' => $operation->getExtraProperties()['legacy_subresource_identifiers'], + // 'collection' => $operation instanceof CollectionOperationInterface, + // 'operationId' => $operation->getExtraProperties()['legacy_subresource_operation_name'] ?? null, + // ]; + // $legacyDefaults['_api_identifiers'] = $operation->getExtraProperties()['legacy_subresource_identifiers']; + // } elseif ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) { + // $legacyDefaults[sprintf('_api_%s_operation_name', $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM)] = $operationName; + // $legacyDefaults['_api_identifiers'] = []; + // // Legacy identifiers + // $hasCompositeIdentifier = false; + // foreach ($operation->getUriVariables() ?? [] as $parameterName => $identifiedBy) { + // $hasCompositeIdentifier = $identifiedBy->getCompositeIdentifier(); + // foreach ($identifiedBy->getIdentifiers() ?? [] as $identifier) { + // $legacyDefaults['_api_identifiers'][] = $identifier; + // } + // } + // $legacyDefaults['_api_has_composite_identifier'] = $hasCompositeIdentifier; + // } $path = ($operation->getRoutePrefix() ?? '').$operation->getUriTemplate(); foreach ($operation->getUriVariables() ?? [] as $parameterName => $link) { @@ -147,7 +123,7 @@ public function load($data, $type = null): RouteCollection $route = new Route( $path, - $legacyDefaults + [ + [ '_controller' => $operation->getController() ?? 'api_platform.action.placeholder', '_format' => null, '_stateless' => $operation->getStateless(), @@ -213,136 +189,4 @@ private function loadExternalFiles(RouteCollection $routeCollection): void $routeCollection->addCollection($this->fileLoader->load('jsonld.xml')); } } - - /** - * TODO: remove in 3.0. - */ - private function loadLegacyMetadata(RouteCollection $routeCollection, string $resourceClass) - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $resourceShortName = $resourceMetadata->getShortName(); - - if (null === $resourceShortName) { - throw new InvalidResourceException(sprintf('Resource %s has no short name defined.', $resourceClass)); - } - - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - foreach ($collectionOperations as $operationName => $operation) { - $this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $resourceMetadata, OperationType::COLLECTION); - } - } - - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - foreach ($itemOperations as $operationName => $operation) { - $this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $resourceMetadata, OperationType::ITEM); - } - } - } - - /** - * TODO: remove in 3.0. - */ - private function loadLegacySubresources(RouteCollection $routeCollection, string $resourceClass) - { - if (null === $this->subresourceOperationFactory) { - return; - } - - foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $operation) { - if (null === $controller = $operation['controller'] ?? null) { - $controller = self::DEFAULT_ACTION_PATTERN.'get_subresource'; - - if (!$this->container->has($controller)) { - throw new RuntimeException(sprintf('There is no builtin action for the %s %s operation. You need to define the controller yourself.', OperationType::SUBRESOURCE, 'GET')); - } - } - - $routeCollection->add($operation['route_name'], new Route( - $operation['path'], - [ - '_controller' => $controller, - '_format' => $operation['defaults']['_format'] ?? null, - '_stateless' => $operation['stateless'] ?? null, - '_api_resource_class' => $operation['resource_class'], - '_api_identifiers' => $operation['identifiers'], - '_api_has_composite_identifier' => false, - '_api_subresource_operation_name' => $operation['route_name'], - '_api_subresource_context' => [ - 'property' => $operation['property'], - 'identifiers' => $operation['identifiers'], - 'collection' => $operation['collection'], - 'operationId' => $operationId, - ], - ] + ($operation['defaults'] ?? []), - $operation['requirements'] ?? [], - $operation['options'] ?? [], - $operation['host'] ?? '', - $operation['schemes'] ?? [], - ['GET'], - $operation['condition'] ?? '' - )); - } - } - - /** - * Creates and adds a route for the given operation to the route collection. - * - * @throws RuntimeException - */ - private function addRoute(RouteCollection $routeCollection, string $resourceClass, string $operationName, array $operation, ResourceMetadata $resourceMetadata, string $operationType): void - { - $resourceShortName = $resourceMetadata->getShortName(); - - if (isset($operation['route_name'])) { - if (!isset($operation['method'])) { - @trigger_error(sprintf('Not setting the "method" attribute is deprecated and will not be supported anymore in API Platform 3.0, set it for the %s operation "%s" of the class "%s".', OperationType::COLLECTION === $operationType ? 'collection' : 'item', $operationName, $resourceClass), \E_USER_DEPRECATED); - } - - return; - } - - if (!isset($operation['method'])) { - throw new RuntimeException(sprintf('Either a "route_name" or a "method" operation attribute must exist for the operation "%s" of the resource "%s".', $operationName, $resourceClass)); - } - - if (null === $controller = $operation['controller'] ?? null) { - $controller = sprintf('%s%s_%s', self::DEFAULT_ACTION_PATTERN, strtolower($operation['method']), $operationType); - - if (!$this->container->has($controller)) { - throw new RuntimeException(sprintf('There is no builtin action for the %s %s operation. You need to define the controller yourself.', $operationType, $operation['method'])); - } - } - - if ($resourceMetadata->getItemOperations()) { - $operation['identifiers'] = (array) ($operation['identifiers'] ?? $resourceMetadata->getAttribute('identifiers', $this->identifiersExtractor ? $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass) : ['id'])); - } - - $operation['has_composite_identifier'] = isset($operation['identifiers']) && \count($operation['identifiers']) > 1 ? $resourceMetadata->getAttribute('composite_identifier', true) : false; - $path = trim(trim($resourceMetadata->getAttribute('route_prefix', '')), '/'); - $path .= $this->operationPathResolver->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - - $route = new Route( - $path, - [ - '_controller' => $controller, - '_format' => $operation['defaults']['_format'] ?? null, - '_stateless' => $operation['stateless'] ?? null, - '_api_resource_class' => $resourceClass, - '_api_identifiers' => $operation['identifiers'] ?? [], - '_api_has_composite_identifier' => $operation['has_composite_identifier'] ?? true, - '_api_operation_name' => RouteNameGenerator::generate($operationName, $resourceShortName, $operationType), - sprintf('_api_%s_operation_name', $operationType) => $operationName, - ] + ($operation['defaults'] ?? []), - $operation['requirements'] ?? [], - $operation['options'] ?? [], - $operation['host'] ?? '', - $operation['schemes'] ?? [], - [$operation['method']], - $operation['condition'] ?? '' - ); - - $routeCollection->add(RouteNameGenerator::generate($operationName, $resourceShortName, $operationType), $route); - } } - -class_alias(ApiLoader::class, \ApiPlatform\Core\Bridge\Symfony\Routing\ApiLoader::class); diff --git a/src/Symfony/Routing/Router.php b/src/Symfony/Routing/Router.php index 14f70c5d81a..c2f73563d28 100644 --- a/src/Symfony/Routing/Router.php +++ b/src/Symfony/Routing/Router.php @@ -107,5 +107,3 @@ public function generate($name, $parameters = [], $referenceType = null): string return $this->router->generate($name, $parameters, self::CONST_MAP[$referenceType ?? $this->urlGenerationStrategy]); } } - -class_alias(Router::class, \ApiPlatform\Core\Bridge\Symfony\Routing\Router::class); diff --git a/src/Symfony/Security/Core/Authorization/ExpressionLanguageProvider.php b/src/Symfony/Security/Core/Authorization/ExpressionLanguageProvider.php index 2d7e46a3c92..5ff56fb9d2a 100644 --- a/src/Symfony/Security/Core/Authorization/ExpressionLanguageProvider.php +++ b/src/Symfony/Security/Core/Authorization/ExpressionLanguageProvider.php @@ -34,5 +34,3 @@ public function getFunctions(): array ]; } } - -class_alias(ExpressionLanguageProvider::class, \ApiPlatform\Core\Security\Core\Authorization\ExpressionLanguageProvider::class); diff --git a/src/Symfony/Security/ExpressionLanguage.php b/src/Symfony/Security/ExpressionLanguage.php index 97db8549416..172f8d9c6fe 100644 --- a/src/Symfony/Security/ExpressionLanguage.php +++ b/src/Symfony/Security/ExpressionLanguage.php @@ -47,5 +47,3 @@ protected function registerFunctions() }); } } - -class_alias(ExpressionLanguage::class, \ApiPlatform\Core\Security\ExpressionLanguage::class); diff --git a/src/Symfony/Security/ResourceAccessChecker.php b/src/Symfony/Security/ResourceAccessChecker.php index 15ac6db8d3e..c6a3c5f350a 100644 --- a/src/Symfony/Security/ResourceAccessChecker.php +++ b/src/Symfony/Security/ResourceAccessChecker.php @@ -108,5 +108,3 @@ private function getEffectiveRoles(TokenInterface $token): array }, $this->roleHierarchy->getReachableRoles($token->getRoles())); // @phpstan-ignore-line } } - -class_alias(ResourceAccessChecker::class, \ApiPlatform\Core\Security\ResourceAccessChecker::class); diff --git a/src/Symfony/Validator/EventListener/ValidationExceptionListener.php b/src/Symfony/Validator/EventListener/ValidationExceptionListener.php index d66df684cb2..a34d0b4186e 100644 --- a/src/Symfony/Validator/EventListener/ValidationExceptionListener.php +++ b/src/Symfony/Validator/EventListener/ValidationExceptionListener.php @@ -71,5 +71,3 @@ public function onKernelException(ExceptionEvent $event): void )); } } - -class_alias(ValidationExceptionListener::class, \ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidationExceptionListener::class); diff --git a/src/Symfony/Validator/Exception/ValidationException.php b/src/Symfony/Validator/Exception/ValidationException.php index 3b2417271f8..269d6503396 100644 --- a/src/Symfony/Validator/Exception/ValidationException.php +++ b/src/Symfony/Validator/Exception/ValidationException.php @@ -54,5 +54,3 @@ public function __toString(): string return $message; } } - -class_alias(ValidationException::class, \ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException::class); diff --git a/src/Symfony/Validator/Validator.php b/src/Symfony/Validator/Validator.php index 7b96123a258..5631872a282 100644 --- a/src/Symfony/Validator/Validator.php +++ b/src/Symfony/Validator/Validator.php @@ -70,5 +70,3 @@ public function validate($data, array $context = []) } } } - -class_alias(Validator::class, \ApiPlatform\Core\Bridge\Symfony\Validator\Validator::class); diff --git a/src/Test/DoctrineMongoDbOdmFilterTestCase.php b/src/Test/DoctrineMongoDbOdmFilterTestCase.php index 54f0173a611..705d82d3cb5 100644 --- a/src/Test/DoctrineMongoDbOdmFilterTestCase.php +++ b/src/Test/DoctrineMongoDbOdmFilterTestCase.php @@ -103,5 +103,3 @@ protected function buildFilter(?array $properties = null) abstract public function provideApplyTestData(): array; } - -class_alias(DoctrineMongoDbOdmFilterTestCase::class, \ApiPlatform\Core\Test\DoctrineMongoDbOdmFilterTestCase::class); diff --git a/src/Test/DoctrineMongoDbOdmSetup.php b/src/Test/DoctrineMongoDbOdmSetup.php index ed23666aef4..6806f33f955 100644 --- a/src/Test/DoctrineMongoDbOdmSetup.php +++ b/src/Test/DoctrineMongoDbOdmSetup.php @@ -119,5 +119,3 @@ private static function createCacheInstance(bool $isDevMode, ?Cache $cache) return class_exists(ArrayCache::class) ? new ArrayCache() : new ArrayAdapter(); } } - -class_alias(DoctrineMongoDbOdmSetup::class, \ApiPlatform\Core\Test\DoctrineMongoDbOdmSetup::class); diff --git a/src/Test/DoctrineMongoDbOdmTestCase.php b/src/Test/DoctrineMongoDbOdmTestCase.php index e426d4ff0c1..455afd00545 100644 --- a/src/Test/DoctrineMongoDbOdmTestCase.php +++ b/src/Test/DoctrineMongoDbOdmTestCase.php @@ -51,5 +51,3 @@ public static function createTestDocumentManager($paths = []) return DocumentManager::create(null, $config); } } - -class_alias(DoctrineMongoDbOdmTestCase::class, \ApiPlatform\Core\Test\DoctrineMongoDbOdmTestCase::class); diff --git a/src/Test/DoctrineOrmFilterTestCase.php b/src/Test/DoctrineOrmFilterTestCase.php index 3bc1d6e07db..242b094ca21 100644 --- a/src/Test/DoctrineOrmFilterTestCase.php +++ b/src/Test/DoctrineOrmFilterTestCase.php @@ -126,5 +126,3 @@ protected function buildFilter(?array $properties = null) abstract public function provideApplyTestData(): array; } - -class_alias(DoctrineOrmFilterTestCase::class, \ApiPlatform\Core\Test\DoctrineOrmFilterTestCase::class); diff --git a/src/Util/AnnotationFilterExtractorTrait.php b/src/Util/AnnotationFilterExtractorTrait.php index f4f9d3bb31d..2ff621d2570 100644 --- a/src/Util/AnnotationFilterExtractorTrait.php +++ b/src/Util/AnnotationFilterExtractorTrait.php @@ -155,5 +155,3 @@ private function generateFilterId(\ReflectionClass $reflectionClass, string $fil return 'annotated_'.Inflector::tableize(str_replace('\\', '', $reflectionClass->getName().(new \ReflectionClass($filterClass))->getName().$suffix)); } } - -class_alias(AnnotationFilterExtractorTrait::class, \ApiPlatform\Core\Util\AnnotationFilterExtractorTrait::class); diff --git a/src/Util/ArrayTrait.php b/src/Util/ArrayTrait.php index 2f0cebd6b5b..f17486cd9f8 100644 --- a/src/Util/ArrayTrait.php +++ b/src/Util/ArrayTrait.php @@ -40,5 +40,3 @@ public function arrayContainsOnly(array $array, string $type): bool }); } } - -class_alias(ArrayTrait::class, \ApiPlatform\Core\Util\ArrayTrait::class); diff --git a/src/Util/AttributesExtractor.php b/src/Util/AttributesExtractor.php index e4c63b6dff2..d65cec31c49 100644 --- a/src/Util/AttributesExtractor.php +++ b/src/Util/AttributesExtractor.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Util; -use ApiPlatform\Core\Api\OperationType; - /** * Extracts data used by the library form given attributes. * @@ -39,19 +37,6 @@ public static function extractAttributes(array $attributes): array $result['subresource_context'] = $subresourceContext; } - // Normalizing identifiers tuples - // TODO: 3.0 remove - $identifiers = []; - foreach (($attributes['_api_identifiers'] ?? ['id']) as $parameterName => $identifiedBy) { - if (\is_string($identifiedBy)) { - $identifiers[$identifiedBy] = [$result['resource_class'], $identifiedBy]; - } else { - $identifiers[$parameterName] = $identifiedBy; - } - } - - $result['identifiers'] = $identifiers; - if (null === $result['resource_class']) { return []; } @@ -65,18 +50,6 @@ public static function extractAttributes(array $attributes): array $result['operation'] = $attributes['_api_operation']; } - // TODO: remove in 3.0 - if (!isset($result['operation']) || ($result['operation']->getExtraProperties()['is_legacy_resource_metadata'] ?? false) || ($result['operation']->getExtraProperties()['is_legacy_subresource'] ?? false)) { - foreach (OperationType::TYPES as $operationType) { - $attribute = "_api_{$operationType}_operation_name"; - if (isset($attributes[$attribute])) { - $result["{$operationType}_operation_name"] = $attributes[$attribute]; - $hasRequestAttributeKey = true; - break; - } - } - } - if ($previousObject = $attributes['previous_data'] ?? null) { $result['previous_data'] = $previousObject; } @@ -94,5 +67,3 @@ public static function extractAttributes(array $attributes): array return $result; } } - -class_alias(AttributesExtractor::class, \ApiPlatform\Core\Util\AttributesExtractor::class); diff --git a/src/Util/CachedTrait.php b/src/Util/CachedTrait.php index 831a4c6a041..abe06aca934 100644 --- a/src/Util/CachedTrait.php +++ b/src/Util/CachedTrait.php @@ -49,5 +49,3 @@ private function getCached(string $cacheKey, callable $getValue) return $this->localCache[$cacheKey] = $value; } } - -class_alias(CachedTrait::class, \ApiPlatform\Core\Cache\CachedTrait::class); diff --git a/src/Util/ClassInfoTrait.php b/src/Util/ClassInfoTrait.php index a481f901ab7..9bb039ec863 100644 --- a/src/Util/ClassInfoTrait.php +++ b/src/Util/ClassInfoTrait.php @@ -59,5 +59,3 @@ private function getRealClassName(string $className): string ); } } - -class_alias(ClassInfoTrait::class, \ApiPlatform\Core\Util\ClassInfoTrait::class); diff --git a/src/Util/ClientTrait.php b/src/Util/ClientTrait.php index ab88472f0cb..01fc07bc253 100644 --- a/src/Util/ClientTrait.php +++ b/src/Util/ClientTrait.php @@ -24,5 +24,3 @@ trait ClientTrait use ClientTrait72; } } - -class_alias(ClientTrait::class, \ApiPlatform\Core\Util\ClientTrait::class); diff --git a/src/Util/CloneTrait.php b/src/Util/CloneTrait.php index 24760cc763f..51623aecb41 100644 --- a/src/Util/CloneTrait.php +++ b/src/Util/CloneTrait.php @@ -35,5 +35,3 @@ public function clone($data) } } } - -class_alias(CloneTrait::class, \ApiPlatform\Core\Util\CloneTrait::class); diff --git a/src/Util/CorsTrait.php b/src/Util/CorsTrait.php index 1595a1fab77..c55ce2584c0 100644 --- a/src/Util/CorsTrait.php +++ b/src/Util/CorsTrait.php @@ -31,5 +31,3 @@ public function isPreflightRequest(Request $request): bool return $request->isMethod('OPTIONS') && $request->headers->has('Access-Control-Request-Method'); } } - -class_alias(CorsTrait::class, \ApiPlatform\Core\Util\CorsTrait::class); diff --git a/src/Util/ErrorFormatGuesser.php b/src/Util/ErrorFormatGuesser.php index a8163333308..a42e1fb5b34 100644 --- a/src/Util/ErrorFormatGuesser.php +++ b/src/Util/ErrorFormatGuesser.php @@ -53,5 +53,3 @@ public static function guessErrorFormat(Request $request, array $errorFormats): return $defaultFormat; } } - -class_alias(ErrorFormatGuesser::class, \ApiPlatform\Core\Util\ErrorFormatGuesser::class); diff --git a/src/Util/Inflector.php b/src/Util/Inflector.php index 412547054b2..85fdf60f0e2 100644 --- a/src/Util/Inflector.php +++ b/src/Util/Inflector.php @@ -53,5 +53,3 @@ public static function pluralize(string $word): string return class_exists(InflectorFactory::class) ? self::getInstance()->pluralize($word) : LegacyInflector::pluralize($word); // @phpstan-ignore-line } } - -class_alias(Inflector::class, \ApiPlatform\Core\Util\Inflector::class); diff --git a/src/Util/IriHelper.php b/src/Util/IriHelper.php index db6970b4388..8c6a6a24591 100644 --- a/src/Util/IriHelper.php +++ b/src/Util/IriHelper.php @@ -113,5 +113,3 @@ public static function createIri(array $parts, array $parameters, string $pagePa return $url; } } - -class_alias(IriHelper::class, \ApiPlatform\Core\Util\IriHelper::class); diff --git a/src/Util/Reflection.php b/src/Util/Reflection.php index 5029011cb2a..97a6880b41a 100644 --- a/src/Util/Reflection.php +++ b/src/Util/Reflection.php @@ -39,5 +39,3 @@ public function getProperty(string $methodName): ?string return null; } } - -class_alias(Reflection::class, \ApiPlatform\Core\Util\Reflection::class); diff --git a/src/Util/ReflectionClassRecursiveIterator.php b/src/Util/ReflectionClassRecursiveIterator.php index 10957a432ad..8215c532c11 100644 --- a/src/Util/ReflectionClassRecursiveIterator.php +++ b/src/Util/ReflectionClassRecursiveIterator.php @@ -66,5 +66,3 @@ public static function getReflectionClassesFromDirectories(array $directories): } } } - -class_alias(ReflectionClassRecursiveIterator::class, \ApiPlatform\Core\Util\ReflectionClassRecursiveIterator::class); diff --git a/src/Util/RequestAttributesExtractor.php b/src/Util/RequestAttributesExtractor.php index 47b041c8e91..8565e922e92 100644 --- a/src/Util/RequestAttributesExtractor.php +++ b/src/Util/RequestAttributesExtractor.php @@ -35,5 +35,3 @@ public static function extractAttributes(Request $request): array return AttributesExtractor::extractAttributes($request->attributes->all()); } } - -class_alias(RequestAttributesExtractor::class, \ApiPlatform\Core\Util\RequestAttributesExtractor::class); diff --git a/src/Util/RequestParser.php b/src/Util/RequestParser.php index bbaf41477d5..5d76abca243 100644 --- a/src/Util/RequestParser.php +++ b/src/Util/RequestParser.php @@ -103,5 +103,3 @@ public static function getQueryString(Request $request): ?string return implode('&', $parts); } } - -class_alias(RequestParser::class, \ApiPlatform\Core\Util\RequestParser::class); diff --git a/src/Util/ResourceClassInfoTrait.php b/src/Util/ResourceClassInfoTrait.php index cf43b091641..fa5bec30697 100644 --- a/src/Util/ResourceClassInfoTrait.php +++ b/src/Util/ResourceClassInfoTrait.php @@ -83,5 +83,3 @@ private function isResourceClass(string $class): bool return true; } } - -class_alias(ResourceClassInfoTrait::class, \ApiPlatform\Core\Util\ResourceClassInfoTrait::class); diff --git a/src/Util/ResponseTrait.php b/src/Util/ResponseTrait.php index fbd0957f18d..5932b944e23 100644 --- a/src/Util/ResponseTrait.php +++ b/src/Util/ResponseTrait.php @@ -24,5 +24,3 @@ trait ResponseTrait use ResponseTrait80; } } - -class_alias(ResponseTrait::class, \ApiPlatform\Core\Util\ResponseTrait::class); diff --git a/src/Util/SortTrait.php b/src/Util/SortTrait.php index 97e20eb7d94..04a8a31917c 100644 --- a/src/Util/SortTrait.php +++ b/src/Util/SortTrait.php @@ -33,5 +33,3 @@ private function arrayRecursiveSort(array &$array, callable $sortFunction): void $sortFunction($array); } } - -class_alias(SortTrait::class, \ApiPlatform\Core\Util\SortTrait::class); diff --git a/src/Validator/Exception/ValidationException.php b/src/Validator/Exception/ValidationException.php index d7838312a3c..361eb200485 100644 --- a/src/Validator/Exception/ValidationException.php +++ b/src/Validator/Exception/ValidationException.php @@ -23,5 +23,3 @@ class ValidationException extends RuntimeException { } - -class_alias(ValidationException::class, \ApiPlatform\Core\Validator\Exception\ValidationException::class); diff --git a/src/deprecated_interfaces.php b/src/deprecated_interfaces.php deleted file mode 100644 index 8f1c66a5dfc..00000000000 --- a/src/deprecated_interfaces.php +++ /dev/null @@ -1,121 +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); - -return [ - ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface::class => ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface::class, - ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface::class => ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface::class, - ApiPlatform\Core\Metadata\Extractor\ExtractorInterface::class => ApiPlatform\Metadata\Extractor\ResourceExtractorInterface::class, - - // Bridge\Doctrine => Doctrine - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\DateFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\DateFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\ExistsFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\ExistsFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\OrderFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\OrderFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\RangeFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\RangeFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface::class, - - // Bridge\Doctrine\MongoDbOdm => Doctrine\Odm - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationCollectionExtensionInterface::class => ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationItemExtensionInterface::class => ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationResultCollectionExtensionInterface::class => ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationResultItemExtensionInterface::class => ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\FilterInterface::class => ApiPlatform\Doctrine\Odm\Filter\FilterInterface::class, - - // Bridge\Doctrine\Orm => Doctrine\Orm - ApiPlatform\Core\Bridge\Doctrine\Orm\QueryAwareInterface::class => ApiPlatform\Doctrine\Orm\QueryAwareInterface::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\ContextAwareQueryCollectionExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\ContextAwareQueryResultCollectionExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryResultCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\ContextAwareQueryResultItemExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryResultItemExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\ContextAwareFilterInterface::class => ApiPlatform\Doctrine\Orm\Filter\ContextAwareFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\FilterInterface::class => ApiPlatform\Doctrine\Orm\Filter\FilterInterface::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface::class => ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface::class, - - // Bridge\Elasticsearch => Elasticsearch - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\RequestBodySearchCollectionExtensionInterface::class => ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface::class, - - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\ConstantScoreFilterInterface::class => ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\FilterInterface::class => ApiPlatform\Elasticsearch\Filter\FilterInterface::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\SortFilterInterface::class => ApiPlatform\Elasticsearch\Filter\SortFilterInterface::class, - - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface::class, - - // Bridge\Symfony\Validator - ApiPlatform\Core\Bridge\Symfony\Validator\ValidationGroupsGeneratorInterface::class => ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface::class, - ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface::class => ApiPlatform\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface::class, - ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface::class => ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface::class, - - // DataProvider => State/Pagination - ApiPlatform\Core\DataProvider\PaginatorInterface::class => ApiPlatform\State\Pagination\PaginatorInterface::class, - ApiPlatform\Core\DataProvider\PartialPaginatorInterface::class => ApiPlatform\State\Pagination\PartialPaginatorInterface::class, - - // Documentation - ApiPlatform\Core\Documentation\DocumentationInterface::class => ApiPlatform\Documentation\DocumentationInterface::class, - - // JsonLd - ApiPlatform\Core\JsonLd\AnonymousContextBuilderInterface::class => ApiPlatform\JsonLd\AnonymousContextBuilderInterface::class, - ApiPlatform\Core\JsonLd\ContextBuilderInterface::class => ApiPlatform\JsonLd\ContextBuilderInterface::class, - - // JsonSchema - ApiPlatform\Core\JsonSchema\SchemaFactoryInterface::class => ApiPlatform\JsonSchema\SchemaFactoryInterface::class, - ApiPlatform\Core\JsonSchema\TypeFactoryInterface::class => ApiPlatform\JsonSchema\TypeFactoryInterface::class, - - // OpenApi - ApiPlatform\Core\OpenApi\Factory\OpenApiFactoryInterface::class => ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface::class, - - // PathResolver - ApiPlatform\Core\PathResolver\OperationPathResolverInterface::class => ApiPlatform\PathResolver\OperationPathResolverInterface::class, - - // Security => Symfony/Security - ApiPlatform\Core\Security\ResourceAccessCheckerInterface::class => ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface::class, - - // Serializer - ApiPlatform\Core\Serializer\Filter\FilterInterface::class => ApiPlatform\Serializer\Filter\FilterInterface::class, - ApiPlatform\Core\Serializer\SerializerContextBuilderInterface::class => ApiPlatform\Serializer\SerializerContextBuilderInterface::class, - - ApiPlatform\Core\Validator\ValidatorInterface::class => ApiPlatform\Validator\ValidatorInterface::class, - - // API: - ApiPlatform\Core\Api\ResourceClassResolverInterface::class => ApiPlatform\Api\ResourceClassResolverInterface::class, - ApiPlatform\Core\Api\UrlGeneratorInterface::class => ApiPlatform\Api\UrlGeneratorInterface::class, - - // GraphQl - ApiPlatform\Core\GraphQl\ExecutorInterface::class => ApiPlatform\GraphQl\ExecutorInterface::class, - ApiPlatform\Core\GraphQl\Error\ErrorHandlerInterface::class => ApiPlatform\GraphQl\Error\ErrorHandlerInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\ValidateStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\ValidateStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\SecurityStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\WriteStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\WriteStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\DeserializeStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\DeserializeStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\QueryItemResolverInterface::class => ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface::class, - ApiPlatform\Core\GraphQl\Resolver\QueryCollectionResolverInterface::class => ApiPlatform\GraphQl\Resolver\QueryCollectionResolverInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\ResolverFactoryInterface::class => ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface::class, - ApiPlatform\Core\GraphQl\Resolver\MutationResolverInterface::class => ApiPlatform\GraphQl\Resolver\MutationResolverInterface::class, - ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface::class => ApiPlatform\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface::class, - ApiPlatform\Core\GraphQl\Subscription\SubscriptionIdentifierGeneratorInterface::class => ApiPlatform\GraphQl\Subscription\SubscriptionIdentifierGeneratorInterface::class, - ApiPlatform\Core\GraphQl\Subscription\SubscriptionManagerInterface::class => ApiPlatform\GraphQl\Subscription\SubscriptionManagerInterface::class, - ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface::class => ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface::class, - ApiPlatform\Core\GraphQl\Type\TypesFactoryInterface::class => ApiPlatform\GraphQl\Type\TypesFactoryInterface::class, - ApiPlatform\Core\GraphQl\Type\Definition\TypeInterface::class => ApiPlatform\GraphQl\Type\Definition\TypeInterface::class, - ApiPlatform\Core\GraphQl\Type\TypesContainerInterface::class => ApiPlatform\GraphQl\Type\TypesContainerInterface::class, - - ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface::class => ApiPlatform\Operation\PathSegmentNameGeneratorInterface::class, -]; diff --git a/src/deprecation.php b/src/deprecation.php deleted file mode 100644 index 1355c779556..00000000000 --- a/src/deprecation.php +++ /dev/null @@ -1,479 +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); - -// Must be declared first! -class_alias(ApiPlatform\Api\FilterInterface::class, ApiPlatform\Core\Api\FilterInterface::class); -class_alias(ApiPlatform\Api\ResourceClassResolverInterface::class, ApiPlatform\Core\Api\ResourceClassResolverInterface::class); - -$deprecatedInterfaces = include 'deprecated_interfaces.php'; -foreach ($deprecatedInterfaces as $oldInterfaceName => $interfaceName) { - // Do not replace existing interface - if (interface_exists($oldInterfaceName)) { - continue; - } - - if (!interface_exists($interfaceName)) { - dump("interface $interfaceName does not exist, replacement $oldInterfaceName neither"); - continue; - } - - class_alias($interfaceName, $oldInterfaceName); -} - -$deprecatedClassesWithAliases = [ - ApiPlatform\Core\Api\Entrypoint::class => ApiPlatform\Api\Entrypoint::class, - ApiPlatform\Core\Api\FilterLocatorTrait::class => ApiPlatform\Api\FilterLocatorTrait::class, - ApiPlatform\Core\Api\FormatMatcher::class => ApiPlatform\Api\FormatMatcher::class, - ApiPlatform\Core\Api\ResourceClassResolver::class => ApiPlatform\Api\ResourceClassResolver::class, - - ApiPlatform\Core\Metadata\Property\PropertyNameCollection::class => ApiPlatform\Metadata\Property\PropertyNameCollection::class, - ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class, - ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class, - - // Test cases - ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase::class => ApiPlatform\Symfony\Bundle\Test\ApiTestCase::class, - ApiPlatform\Core\Test\DoctrineMongoDbOdmFilterTestCase::class => ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase::class, - ApiPlatform\Core\Test\DoctrineMongoDbOdmTestCase::class => ApiPlatform\Test\DoctrineMongoDbOdmTestCase::class, - ApiPlatform\Core\Test\DoctrineOrmFilterTestCase::class => ApiPlatform\Test\DoctrineOrmFilterTestCase::class, - - // Exceptions - ApiPlatform\Core\Exception\DeserializationException::class => ApiPlatform\Exception\DeserializationException::class, - ApiPlatform\Core\Exception\FilterValidationException::class => ApiPlatform\Exception\FilterValidationException::class, - ApiPlatform\Core\Exception\InvalidArgumentException::class => ApiPlatform\Exception\InvalidArgumentException::class, - ApiPlatform\Core\Exception\InvalidIdentifierException::class => ApiPlatform\Exception\InvalidIdentifierException::class, - ApiPlatform\Core\Exception\InvalidResourceException::class => ApiPlatform\Exception\InvalidResourceException::class, - ApiPlatform\Core\Exception\InvalidValueException::class => ApiPlatform\Exception\InvalidValueException::class, - ApiPlatform\Core\Exception\PropertyNotFoundException::class => ApiPlatform\Exception\PropertyNotFoundException::class, - ApiPlatform\Core\Exception\RuntimeException::class => ApiPlatform\Exception\RuntimeException::class, - ApiPlatform\Core\Exception\ResourceClassNotFoundException::class => ApiPlatform\Exception\ResourceClassNotFoundException::class, - ApiPlatform\Core\Exception\ResourceClassNotSupportedException::class => ApiPlatform\Exception\ResourceClassNotSupportedException::class, - ApiPlatform\Core\Exception\ItemNotFoundException::class => ApiPlatform\Exception\ItemNotFoundException::class, - - // Action - ApiPlatform\Core\Action\EntrypointAction::class => ApiPlatform\Action\EntrypointAction::class, - ApiPlatform\Core\Action\ExceptionAction::class => ApiPlatform\Action\ExceptionAction::class, - ApiPlatform\Core\Action\NotFoundAction::class => ApiPlatform\Action\NotFoundAction::class, - ApiPlatform\Core\Action\PlaceholderAction::class => ApiPlatform\Action\PlaceholderAction::class, - - // Bridge\Doctrine - ApiPlatform\Core\Bridge\Doctrine\Common\PropertyHelperTrait::class => ApiPlatform\Doctrine\Common\PropertyHelperTrait::class, - - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\BooleanFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\BooleanFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\DateFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\DateFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\ExistsFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\ExistsFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\NumericFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\NumericFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\OrderFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\OrderFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\RangeFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\RangeFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait::class, - - // Bridge\Doctrine\EventListener - ApiPlatform\Core\Bridge\Doctrine\EventListener\PurgeHttpCacheListener::class => ApiPlatform\Doctrine\EventListener\PurgeHttpCacheListener::class, - ApiPlatform\Core\Bridge\Doctrine\EventListener\WriteListener::class => ApiPlatform\Doctrine\EventListener\WriteListener::class, - - // Bridge\Doctrine\MongoDbOdm - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\FilterExtension::class => ApiPlatform\Doctrine\Odm\Extension\FilterExtension::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\OrderExtension::class => ApiPlatform\Doctrine\Orm\Extension\OrderExtension::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\PaginationExtension::class => ApiPlatform\Doctrine\Orm\Extension\PaginationExtension::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\AbstractFilter::class => ApiPlatform\Doctrine\Odm\Filter\AbstractFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\BooleanFilter::class => ApiPlatform\Doctrine\Odm\Filter\BooleanFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\DateFilter::class => ApiPlatform\Doctrine\Odm\Filter\DateFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\ExistsFilter::class => ApiPlatform\Doctrine\Odm\Filter\ExistsFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\NumericFilter::class => ApiPlatform\Doctrine\Odm\Filter\NumericFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\OrderFilter::class => ApiPlatform\Doctrine\Odm\Filter\OrderFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\RangeFilter::class => ApiPlatform\Doctrine\Odm\Filter\RangeFilter::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\PropertyInfo\DoctrineExtractor::class => ApiPlatform\Doctrine\Odm\PropertyInfo\DoctrineExtractor::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator::class => ApiPlatform\Doctrine\Odm\Paginator::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\PropertyHelperTrait::class => ApiPlatform\Doctrine\Odm\PropertyHelperTrait::class, - - // Bridge\Doctrine\Orm - ApiPlatform\Core\Bridge\Doctrine\Orm\AbstractPaginator::class => ApiPlatform\Doctrine\Orm\AbstractPaginator::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator::class => ApiPlatform\Doctrine\Orm\Paginator::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\PropertyHelperTrait::class => ApiPlatform\Doctrine\Orm\PropertyHelperTrait::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\EagerLoadingExtension::class => ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterEagerLoadingExtension::class => ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterExtension::class => ApiPlatform\Doctrine\Orm\Extension\FilterExtension::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\OrderExtension::class => ApiPlatform\Doctrine\Orm\Extension\OrderExtension::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension::class => ApiPlatform\Doctrine\Orm\Extension\PaginationExtension::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractContextAwareFilter::class => ApiPlatform\Doctrine\Orm\Filter\AbstractContextAwareFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter::class => ApiPlatform\Doctrine\Orm\Filter\AbstractFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\BooleanFilter::class => ApiPlatform\Doctrine\Orm\Filter\BooleanFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\DateFilter::class => ApiPlatform\Doctrine\Orm\Filter\DateFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\ExistsFilter::class => ApiPlatform\Doctrine\Orm\Filter\ExistsFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\NumericFilter::class => ApiPlatform\Doctrine\Orm\Filter\NumericFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter::class => ApiPlatform\Doctrine\Orm\Filter\OrderFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\RangeFilter::class => ApiPlatform\Doctrine\Orm\Filter\RangeFilter::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\EagerLoadingTrait::class => ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryBuilderHelper::class => ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryChecker::class => ApiPlatform\Doctrine\Orm\Util\QueryChecker::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryJoinParser::class => ApiPlatform\Doctrine\Orm\Util\QueryJoinParser::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator::class => ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator::class, - - // Bridge\Elasticsearch - ApiPlatform\Core\Bridge\Elasticsearch\Exception\IndexNotFoundException::class => ApiPlatform\Elasticsearch\Exception\IndexNotFoundException::class, - ApiPlatform\Core\Bridge\Elasticsearch\Exception\NonUniqueIdentifierException::class => ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException::class, - - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\AbstractFilterExtension::class => ApiPlatform\Elasticsearch\Extension\AbstractFilterExtension::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\ConstantScoreFilterExtension::class => ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\SortExtension::class => ApiPlatform\Elasticsearch\Extension\SortExtension::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\SortFilterExtension::class => ApiPlatform\Elasticsearch\Extension\SortFilterExtension::class, - - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory::class, - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory::class, - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory::class, - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory::class, - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\DocumentMetadata::class => ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata::class, - - ApiPlatform\Core\Bridge\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter::class => ApiPlatform\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter::class, - ApiPlatform\Core\Bridge\Elasticsearch\Serializer\DocumentNormalizer::class => ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer::class, - ApiPlatform\Core\Bridge\Elasticsearch\Serializer\ItemNormalizer::class => ApiPlatform\Elasticsearch\Serializer\ItemNormalizer::class, - ApiPlatform\Core\Bridge\Elasticsearch\Util\FieldDatatypeTrait::class => ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait::class, - - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Paginator::class => ApiPlatform\Elasticsearch\Paginator::class, - - // Bridge\RamseyUuid - ApiPlatform\Core\Bridge\RamseyUuid\Serializer\UuidDenormalizer::class => ApiPlatform\RamseyUuid\Serializer\UuidDenormalizer::class, - - // Bridge\Symfony\Bundle - ApiPlatform\Core\Bridge\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver::class => ApiPlatform\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer::class => ApiPlatform\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\Command\GraphQlExportCommand::class => ApiPlatform\Symfony\Bundle\Command\GraphQlExportCommand::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\Command\OpenApiCommand::class => ApiPlatform\Symfony\Bundle\Command\OpenApiCommand::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\FilterPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\ApiPlatformExtension::class => ApiPlatform\Symfony\Bundle\DependencyInjection\ApiPlatformExtension::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Configuration::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Configuration::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener\SwaggerUiListener::class => ApiPlatform\Symfony\Bundle\EventListener\SwaggerUiListener::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi\SwaggerUiAction::class => ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi\SwaggerUiContext::class => ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiContext::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestAssertionsTrait::class => ApiPlatform\Symfony\Bundle\Test\ApiTestAssertionsTrait::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client::class => ApiPlatform\Symfony\Bundle\Test\Client::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Response::class => ApiPlatform\Symfony\Bundle\Test\Response::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class, - - // Bridge\Symfony\Messenger - ApiPlatform\Core\Bridge\Symfony\Messenger\ContextStamp::class => ApiPlatform\Symfony\Messenger\ContextStamp::class, - ApiPlatform\Core\Bridge\Symfony\Messenger\DispatchTrait::class => ApiPlatform\Symfony\Messenger\DispatchTrait::class, - ApiPlatform\Core\Bridge\Symfony\Messenger\RemoveStamp::class => ApiPlatform\Symfony\Messenger\RemoveStamp::class, - - // Bridge\Symfony\PropertyInfo\Metadata\Property => Metadata\Property - ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory::class, - - // Bridge\Symfony\Routing - ApiPlatform\Core\Bridge\Symfony\Routing\ApiLoader::class => ApiPlatform\Symfony\Routing\ApiLoader::class, - ApiPlatform\Core\Bridge\Symfony\Routing\Router::class => ApiPlatform\Symfony\Routing\Router::class, - - // Bridge\Symfony\Validator - ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidationExceptionListener::class => ApiPlatform\Symfony\Validator\EventListener\ValidationExceptionListener::class, - ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException::class => ApiPlatform\Symfony\Validator\Exception\ValidationException::class, - ApiPlatform\Core\Bridge\Symfony\Validator\Validator::class => ApiPlatform\Symfony\Validator\Validator::class, - - // Cache - ApiPlatform\Core\Cache\CachedTrait::class => ApiPlatform\Util\CachedTrait::class, - - // DataProvider => State/Pagination - ApiPlatform\Core\DataProvider\ArrayPaginator::class => ApiPlatform\State\Pagination\ArrayPaginator::class, - ApiPlatform\Core\DataProvider\PaginationOptions::class => ApiPlatform\State\Pagination\PaginationOptions::class, - ApiPlatform\Core\DataProvider\TraversablePaginator::class => ApiPlatform\State\Pagination\TraversablePaginator::class, - - // Documentation - ApiPlatform\Core\Documentation\Action\DocumentationAction::class => ApiPlatform\Documentation\Action\DocumentationAction::class, - ApiPlatform\Core\Documentation\Documentation::class => ApiPlatform\Documentation\Documentation::class, - - // EventListener => Symfony/EventListener - ApiPlatform\Core\EventListener\AddFormatListener::class => ApiPlatform\Symfony\EventListener\AddFormatListener::class, - ApiPlatform\Core\EventListener\DeserializeListener::class => ApiPlatform\Symfony\EventListener\DeserializeListener::class, - ApiPlatform\Core\EventListener\EventPriorities::class => ApiPlatform\Symfony\EventListener\EventPriorities::class, - ApiPlatform\Core\EventListener\ExceptionListener::class => ApiPlatform\Symfony\EventListener\ExceptionListener::class, - ApiPlatform\Core\EventListener\QueryParameterValidateListener::class => ApiPlatform\Symfony\EventListener\QueryParameterValidateListener::class, - ApiPlatform\Core\EventListener\RespondListener::class => ApiPlatform\Symfony\EventListener\RespondListener::class, - ApiPlatform\Core\EventListener\SerializeListener::class => ApiPlatform\Symfony\EventListener\SerializeListener::class, - - // Hal - ApiPlatform\Core\Hal\JsonSchema\SchemaFactory::class => ApiPlatform\Hal\JsonSchema\SchemaFactory::class, - ApiPlatform\Core\Hal\Serializer\CollectionNormalizer::class => ApiPlatform\Hal\Serializer\CollectionNormalizer::class, - ApiPlatform\Core\Hal\Serializer\EntrypointNormalizer::class => ApiPlatform\Hal\Serializer\EntrypointNormalizer::class, - ApiPlatform\Core\Hal\Serializer\ItemNormalizer::class => ApiPlatform\Hal\Serializer\ItemNormalizer::class, - ApiPlatform\Core\Hal\Serializer\ObjectNormalizer::class => ApiPlatform\Hal\Serializer\ObjectNormalizer::class, - - // HttpCache - ApiPlatform\Core\HttpCache\EventListener\AddHeadersListener::class => ApiPlatform\HttpCache\EventListener\AddHeadersListener::class, - ApiPlatform\Core\HttpCache\EventListener\AddTagsListener::class => ApiPlatform\HttpCache\EventListener\AddTagsListener::class, - ApiPlatform\Core\HttpCache\VarnishPurger::class => ApiPlatform\HttpCache\VarnishPurger::class, - ApiPlatform\Core\HttpCache\VarnishXKeyPurger::class => ApiPlatform\HttpCache\VarnishXKeyPurger::class, - - // Hydra - ApiPlatform\Core\Hydra\EventListener\AddLinkHeaderListener::class => ApiPlatform\Hydra\EventListener\AddLinkHeaderListener::class, - ApiPlatform\Core\Hydra\JsonSchema\SchemaFactory::class => ApiPlatform\Hydra\JsonSchema\SchemaFactory::class, - ApiPlatform\Core\Hydra\Serializer\CollectionFiltersNormalizer::class => ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\CollectionNormalizer::class => ApiPlatform\Hydra\Serializer\CollectionNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\ConstraintViolationListNormalizer::class => ApiPlatform\Hydra\Serializer\ConstraintViolationListNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\DocumentationNormalizer::class => ApiPlatform\Hydra\Serializer\DocumentationNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\EntrypointNormalizer::class => ApiPlatform\Hydra\Serializer\EntrypointNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\ErrorNormalizer::class => ApiPlatform\Hydra\Serializer\ErrorNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\PartialCollectionViewNormalizer::class => ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer::class, - - // JsonApi/EventListener => Symfony/EventListener - ApiPlatform\Core\JsonApi\EventListener\TransformFieldsetsParametersListener::class => ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener::class, - ApiPlatform\Core\JsonApi\EventListener\TransformFilteringParametersListener::class => ApiPlatform\Symfony\EventListener\JsonApi\TransformFilteringParametersListener::class, - ApiPlatform\Core\JsonApi\EventListener\TransformPaginationParametersListener::class => ApiPlatform\Symfony\EventListener\JsonApi\TransformPaginationParametersListener::class, - ApiPlatform\Core\JsonApi\EventListener\TransformSortingParametersListener::class => ApiPlatform\Symfony\EventListener\JsonApi\TransformSortingParametersListener::class, - - // JsonApi/Serializer - ApiPlatform\Core\JsonApi\Serializer\CollectionNormalizer::class => ApiPlatform\JsonApi\Serializer\CollectionNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ConstraintViolationListNormalizer::class => ApiPlatform\JsonApi\Serializer\ConstraintViolationListNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\EntrypointNormalizer::class => ApiPlatform\JsonApi\Serializer\EntrypointNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ErrorNormalizer::class => ApiPlatform\JsonApi\Serializer\ErrorNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ItemNormalizer::class => ApiPlatform\JsonApi\Serializer\ItemNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ObjectNormalizer::class => ApiPlatform\JsonApi\Serializer\ObjectNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ReservedAttributeNameConverter::class => ApiPlatform\JsonApi\Serializer\ReservedAttributeNameConverter::class, - - // JsonLd - ApiPlatform\Core\JsonLd\Action\ContextAction::class => ApiPlatform\JsonLd\Action\ContextAction::class, - ApiPlatform\Core\JsonLd\Serializer\ItemNormalizer::class => ApiPlatform\JsonLd\Serializer\ItemNormalizer::class, - ApiPlatform\Core\JsonLd\Serializer\JsonLdContextTrait::class => ApiPlatform\JsonLd\Serializer\JsonLdContextTrait::class, - ApiPlatform\Core\JsonLd\Serializer\ObjectNormalizer::class => ApiPlatform\JsonLd\Serializer\ObjectNormalizer::class, - ApiPlatform\Core\JsonLd\ContextBuilder::class => ApiPlatform\JsonLd\ContextBuilder::class, - - // JsonSchema - ApiPlatform\Core\JsonSchema\Command\JsonSchemaGenerateCommand::class => ApiPlatform\JsonSchema\Command\JsonSchemaGenerateCommand::class, - ApiPlatform\Core\JsonSchema\Schema::class => ApiPlatform\JsonSchema\Schema::class, - ApiPlatform\Core\JsonSchema\SchemaFactory::class => ApiPlatform\JsonSchema\SchemaFactory::class, - ApiPlatform\Core\JsonSchema\TypeFactory::class => ApiPlatform\JsonSchema\TypeFactory::class, - - // Mercure/EventListener => Symfony/EventListener - ApiPlatform\Core\Mercure\EventListener\AddLinkHeaderListener::class => ApiPlatform\Symfony\EventListener\AddLinkHeaderListener::class, - - // OpenApi - ApiPlatform\Core\OpenApi\Model\Components::class => ApiPlatform\OpenApi\Model\Components::class, - ApiPlatform\Core\OpenApi\Model\Contact::class => ApiPlatform\OpenApi\Model\Contact::class, - ApiPlatform\Core\OpenApi\Model\Encoding::class => ApiPlatform\OpenApi\Model\Encoding::class, - ApiPlatform\Core\OpenApi\Model\ExtensionTrait::class => ApiPlatform\OpenApi\Model\ExtensionTrait::class, - ApiPlatform\Core\OpenApi\Model\ExternalDocumentation::class => ApiPlatform\OpenApi\Model\ExternalDocumentation::class, - ApiPlatform\Core\OpenApi\Model\Info::class => ApiPlatform\OpenApi\Model\Info::class, - ApiPlatform\Core\OpenApi\Model\License::class => ApiPlatform\OpenApi\Model\License::class, - ApiPlatform\Core\OpenApi\Model\Link::class => ApiPlatform\OpenApi\Model\Link::class, - ApiPlatform\Core\OpenApi\Model\MediaType::class => ApiPlatform\OpenApi\Model\MediaType::class, - ApiPlatform\Core\OpenApi\Model\OAuthFlow::class => ApiPlatform\OpenApi\Model\OAuthFlow::class, - ApiPlatform\Core\OpenApi\Model\OAuthFlows::class => ApiPlatform\OpenApi\Model\OAuthFlows::class, - ApiPlatform\Core\OpenApi\Model\Parameter::class => ApiPlatform\OpenApi\Model\Parameter::class, - ApiPlatform\Core\OpenApi\Model\Paths::class => ApiPlatform\OpenApi\Model\Paths::class, - ApiPlatform\Core\OpenApi\Model\PathItem::class => ApiPlatform\OpenApi\Model\PathItem::class, - ApiPlatform\Core\OpenApi\Model\Operation::class => ApiPlatform\OpenApi\Model\Operation::class, - ApiPlatform\Core\OpenApi\Model\RequestBody::class => ApiPlatform\OpenApi\Model\RequestBody::class, - ApiPlatform\Core\OpenApi\Model\Response::class => ApiPlatform\OpenApi\Model\Response::class, - ApiPlatform\Core\OpenApi\Model\Schema::class => ApiPlatform\OpenApi\Model\Schema::class, - ApiPlatform\Core\OpenApi\Model\SecurityScheme::class => ApiPlatform\OpenApi\Model\SecurityScheme::class, - ApiPlatform\Core\OpenApi\Model\Server::class => ApiPlatform\OpenApi\Model\Server::class, - ApiPlatform\Core\OpenApi\Serializer\OpenApiNormalizer::class => ApiPlatform\OpenApi\Serializer\OpenApiNormalizer::class, - ApiPlatform\Core\OpenApi\OpenApi::class => ApiPlatform\OpenApi\OpenApi::class, - ApiPlatform\Core\OpenApi\Options::class => ApiPlatform\OpenApi\Options::class, - - // PathResolver - ApiPlatform\Core\PathResolver\CustomOperationPathResolver::class => ApiPlatform\PathResolver\CustomOperationPathResolver::class, - ApiPlatform\Core\PathResolver\OperationPathResolver::class => ApiPlatform\PathResolver\OperationPathResolver::class, - - // Problem - ApiPlatform\Core\Problem\Serializer\ConstraintViolationListNormalizer::class => ApiPlatform\Problem\Serializer\ConstraintViolationListNormalizer::class, - ApiPlatform\Core\Problem\Serializer\ErrorNormalizer::class => ApiPlatform\Problem\Serializer\ErrorNormalizer::class, - ApiPlatform\Core\Problem\Serializer\ErrorNormalizerTrait::class => ApiPlatform\Problem\Serializer\ErrorNormalizerTrait::class, - - // Security => Symfony/Security - ApiPlatform\Core\Security\Core\Authorization\ExpressionLanguageProvider::class => ApiPlatform\Symfony\Security\Core\Authorization\ExpressionLanguageProvider::class, - ApiPlatform\Core\Security\ExpressionLanguage::class => ApiPlatform\Symfony\Security\ExpressionLanguage::class, - ApiPlatform\Core\Security\ResourceAccessChecker::class => ApiPlatform\Symfony\Security\ResourceAccessChecker::class, - - // Security/EventListener => Symfony/EventListener - ApiPlatform\Core\Security\EventListener\DenyAccessListener::class => ApiPlatform\Symfony\EventListener\DenyAccessListener::class, - - // Serializer - ApiPlatform\Core\Serializer\Filter\GroupFilter::class => ApiPlatform\Serializer\Filter\GroupFilter::class, - ApiPlatform\Core\Serializer\Filter\PropertyFilter::class => ApiPlatform\Serializer\Filter\PropertyFilter::class, - ApiPlatform\Core\Serializer\Mapping\Factory\ClassMetadataFactory::class => ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory::class, - ApiPlatform\Core\Serializer\AbstractCollectionNormalizer::class => ApiPlatform\Serializer\AbstractCollectionNormalizer::class, - ApiPlatform\Core\Serializer\AbstractConstraintViolationListNormalizer::class => ApiPlatform\Serializer\AbstractConstraintViolationListNormalizer::class, - ApiPlatform\Core\Serializer\AbstractItemNormalizer::class => ApiPlatform\Serializer\AbstractItemNormalizer::class, - ApiPlatform\Core\Serializer\CacheKeyTrait::class => ApiPlatform\Serializer\CacheKeyTrait::class, - ApiPlatform\Core\Serializer\ContextTrait::class => ApiPlatform\Serializer\ContextTrait::class, - ApiPlatform\Core\Serializer\InputOutputMetadataTrait::class => ApiPlatform\Serializer\InputOutputMetadataTrait::class, - ApiPlatform\Core\Serializer\ItemNormalizer::class => ApiPlatform\Serializer\ItemNormalizer::class, - ApiPlatform\Core\Serializer\JsonEncoder::class => ApiPlatform\Serializer\JsonEncoder::class, - ApiPlatform\Core\Serializer\ResourceList::class => ApiPlatform\Serializer\ResourceList::class, - ApiPlatform\Core\Serializer\SerializerContextBuilder::class => ApiPlatform\Serializer\SerializerContextBuilder::class, - ApiPlatform\Core\Serializer\SerializerFilterContextBuilder::class => ApiPlatform\Serializer\SerializerFilterContextBuilder::class, - - // Swagger/Serializer => OpenApi/Serializer - ApiPlatform\Core\Swagger\Serializer\ApiGatewayNormalizer::class => ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer::class, - - // Test - ApiPlatform\Core\Test\DoctrineMongoDbOdmSetup::class => ApiPlatform\Test\DoctrineMongoDbOdmSetup::class, - - // Util - ApiPlatform\Core\Util\AnnotationFilterExtractorTrait::class => ApiPlatform\Util\AnnotationFilterExtractorTrait::class, - ApiPlatform\Core\Util\ArrayTrait::class => ApiPlatform\Util\ArrayTrait::class, - ApiPlatform\Core\Util\AttributesExtractor::class => ApiPlatform\Util\AttributesExtractor::class, - ApiPlatform\Core\Util\ClassInfoTrait::class => ApiPlatform\Util\ClassInfoTrait::class, - ApiPlatform\Core\Util\ClientTrait::class => ApiPlatform\Util\ClientTrait::class, - ApiPlatform\Core\Util\CloneTrait::class => ApiPlatform\Util\CloneTrait::class, - ApiPlatform\Core\Util\CorsTrait::class => ApiPlatform\Util\CorsTrait::class, - ApiPlatform\Core\Util\ErrorFormatGuesser::class => ApiPlatform\Util\ErrorFormatGuesser::class, - ApiPlatform\Core\Util\Inflector::class => ApiPlatform\Util\Inflector::class, - ApiPlatform\Core\Util\IriHelper::class => ApiPlatform\Util\IriHelper::class, - ApiPlatform\Core\Util\Reflection::class => ApiPlatform\Util\Reflection::class, - ApiPlatform\Core\Util\ReflectionClassRecursiveIterator::class => ApiPlatform\Util\ReflectionClassRecursiveIterator::class, - ApiPlatform\Core\Util\RequestAttributesExtractor::class => ApiPlatform\Util\RequestAttributesExtractor::class, - ApiPlatform\Core\Util\RequestParser::class => ApiPlatform\Util\RequestParser::class, - ApiPlatform\Core\Util\ResourceClassInfoTrait::class => ApiPlatform\Util\ResourceClassInfoTrait::class, - ApiPlatform\Core\Util\ResponseTrait::class => ApiPlatform\Util\ResponseTrait::class, - ApiPlatform\Core\Util\SortTrait::class => ApiPlatform\Util\SortTrait::class, - - // Validator - ApiPlatform\Core\Validator\EventListener\ValidateListener::class => ApiPlatform\Symfony\EventListener\ValidateListener::class, - ApiPlatform\Core\Validator\Exception\ValidationException::class => ApiPlatform\Validator\Exception\ValidationException::class, - - ApiPlatform\Core\Filter\QueryParameterValidator::class => ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator::class, - ApiPlatform\Core\Filter\Validator\ArrayItems::class => ApiPlatform\Api\QueryParameterValidator\Validator\ArrayItems::class, - ApiPlatform\Core\Filter\Validator\Bounds::class => ApiPlatform\Api\QueryParameterValidator\Validator\Bounds::class, - ApiPlatform\Core\Filter\Validator\Enum::class => ApiPlatform\Api\QueryParameterValidator\Validator\Enum::class, - ApiPlatform\Core\Filter\Validator\Length::class => ApiPlatform\Api\QueryParameterValidator\Validator\Length::class, - ApiPlatform\Core\Filter\Validator\MultipleOf::class => ApiPlatform\Api\QueryParameterValidator\Validator\MultipleOf::class, - ApiPlatform\Core\Filter\Validator\Pattern::class => ApiPlatform\Api\QueryParameterValidator\Validator\Pattern::class, - ApiPlatform\Core\Filter\Validator\Required::class => ApiPlatform\Api\QueryParameterValidator\Validator\Required::class, - ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator::class => ApiPlatform\Operation\UnderscorePathSegmentNameGenerator::class, - ApiPlatform\Core\Operation\DashPathSegmentNameGenerator::class => ApiPlatform\Operation\DashPathSegmentNameGenerator::class, - - // GraphQl - ApiPlatform\Core\GraphQl\Executor::class => ApiPlatform\GraphQl\Executor::class, - ApiPlatform\Core\GraphQl\Error\ErrorHandler::class => ApiPlatform\GraphQl\Error\ErrorHandler::class, - ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait::class => ApiPlatform\GraphQl\Resolver\Util\IdentifierTrait::class, - ApiPlatform\Core\GraphQl\Action\EntrypointAction::class => ApiPlatform\GraphQl\Action\EntrypointAction::class, - ApiPlatform\Core\GraphQl\Action\GraphiQlAction::class => ApiPlatform\GraphQl\Action\GraphiQlAction::class, - ApiPlatform\Core\GraphQl\Action\GraphQlPlaygroundAction::class => ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction::class, - ApiPlatform\Core\GraphQl\Type\TypeNotFoundException::class => ApiPlatform\GraphQl\Type\TypeNotFoundException::class, - ApiPlatform\Core\GraphQl\Type\TypesFactory::class => ApiPlatform\GraphQl\Type\TypesFactory::class, - ApiPlatform\Core\GraphQl\Type\Definition\UploadType::class => ApiPlatform\GraphQl\Type\Definition\UploadType::class, - ApiPlatform\Core\GraphQl\Type\Definition\IterableType::class => ApiPlatform\GraphQl\Type\Definition\IterableType::class, - ApiPlatform\Core\GraphQl\Type\TypesContainer::class => ApiPlatform\GraphQl\Type\TypesContainer::class, -]; - -// These classes are deprecated but we don't want aliases as the interfaces changed -$deprecatedClassesWithoutAliases = [ - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\AbstractFilter::class => ApiPlatform\Elasticsearch\Filter\AbstractFilter::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\AbstractSearchFilter::class => ApiPlatform\Elasticsearch\Filter\AbstractSearchFilter::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\MatchFilter::class => ApiPlatform\Elasticsearch\Filter\MatchFilter::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\OrderFilter::class => ApiPlatform\Elasticsearch\Filter\OrderFilter::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\TermFilter::class => ApiPlatform\Elasticsearch\Filter\TermFilter::class, - - ApiPlatform\Core\DataProvider\Pagination::class => ApiPlatform\State\Pagination\Pagination::class, - - ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory::class, - ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\CachedPropertyMetadataFactory::class, - ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\ExtractorPropertyMetadataFactory::class, - ApiPlatform\Core\Metadata\Property\Factory\DefaultPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\DefaultPropertyMetadataFactory::class, - - ApiPlatform\Core\Metadata\Extractor\XmlExtractor::class => ApiPlatform\Metadata\Extractor\XmlResourceExtractor::class, - ApiPlatform\Core\Metadata\Extractor\YamlExtractor::class => ApiPlatform\Metadata\Extractor\YamlResourceExtractor::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Metadata\Property\DoctrineMongoDbOdmPropertyMetadataFactory::class => ApiPlatform\Doctrine\Odm\Metadata\Property\DoctrineMongoDbOdmPropertyMetadataFactory::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory::class => ApiPlatform\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory::class, - ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyMetadataFactory::class, - ApiPlatform\Core\Metadata\Property\PropertyMetadata::class => ApiPlatform\Metadata\ApiProperty::class, - - ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStage::class => ApiPlatform\GraphQl\Resolver\Stage\ReadStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\WriteStage::class => ApiPlatform\GraphQl\Resolver\Stage\WriteStage::class, - ApiPlatform\Core\GraphQl\Type\TypeConverter::class => ApiPlatform\GraphQl\Type\TypeConverter::class, - ApiPlatform\Core\GraphQl\Type\TypeBuilder::class => ApiPlatform\GraphQl\Type\TypeBuilder::class, - ApiPlatform\Core\GraphQl\Type\FieldsBuilder::class => ApiPlatform\GraphQl\Type\FieldsBuilder::class, - ApiPlatform\Core\GraphQl\Type\SchemaBuilder::class => ApiPlatform\GraphQl\Type\SchemaBuilder::class, - ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilder::class => ApiPlatform\GraphQl\Serializer\SerializerContextBuilder::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\ItemResolverFactory::class => ApiPlatform\GraphQl\Resolver\Factory\ItemResolverFactory::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\CollectionResolverFactory::class => ApiPlatform\GraphQl\Resolver\Factory\CollectionResolverFactory::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\ItemMutationResolverFactory::class => ApiPlatform\GraphQl\Resolver\Factory\ItemMutationResolverFactory::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\ItemSubscriptionResolverFactory::class => ApiPlatform\GraphQl\Resolver\Factory\ItemSubscriptionResolverFactory::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStage::class => ApiPlatform\GraphQl\Resolver\Stage\SecurityStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStage::class => ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStage::class => ApiPlatform\GraphQl\Resolver\Stage\SerializeStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\DeserializeStage::class => ApiPlatform\GraphQl\Resolver\Stage\DeserializeStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\ValidateStage::class => ApiPlatform\GraphQl\Resolver\Stage\ValidateStage::class, - ApiPlatform\Core\GraphQl\Resolver\ResourceFieldResolver::class => ApiPlatform\GraphQl\Resolver\ResourceFieldResolver::class, - ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer::class => ApiPlatform\GraphQl\Serializer\ItemNormalizer::class, - ApiPlatform\Core\GraphQl\Serializer\ObjectNormalizer::class => ApiPlatform\GraphQl\Serializer\ObjectNormalizer::class, - ApiPlatform\Core\GraphQl\Subscription\SubscriptionManager::class => ApiPlatform\GraphQl\Subscription\SubscriptionManager::class, - ApiPlatform\Core\GraphQl\Serializer\Exception\ErrorNormalizer::class => ApiPlatform\GraphQl\Serializer\Exception\ErrorNormalizer::class, - ApiPlatform\Core\GraphQl\Serializer\Exception\ValidationExceptionNormalizer::class => ApiPlatform\GraphQl\Serializer\Exception\ValidationExceptionNormalizer::class, - ApiPlatform\Core\GraphQl\Serializer\Exception\HttpExceptionNormalizer::class => ApiPlatform\GraphQl\Serializer\Exception\HttpExceptionNormalizer::class, - ApiPlatform\Core\GraphQl\Serializer\Exception\RuntimeExceptionNormalizer::class => ApiPlatform\GraphQl\Serializer\Exception\RuntimeExceptionNormalizer::class, - ApiPlatform\Core\GraphQl\Subscription\SubscriptionIdentifierGenerator::class => ApiPlatform\GraphQl\Subscription\SubscriptionIdentifierGenerator::class, - ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGenerator::class => ApiPlatform\GraphQl\Subscription\MercureSubscriptionIriGenerator::class, - - ApiPlatform\Core\Bridge\Doctrine\EventListener\PublishMercureUpdatesListener::class => ApiPlatform\Doctrine\EventListener\PublishMercureUpdatesListener::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\SearchFilter::class => ApiPlatform\Doctrine\Odm\Filter\SearchFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter::class => ApiPlatform\Doctrine\Orm\Filter\SearchFilter::class, - ApiPlatform\Core\HttpCache\PurgerInterface::class => ApiPlatform\HttpCache\PurgerInterface::class, -]; - -spl_autoload_register(function ($className) use ($deprecatedInterfaces, $deprecatedClassesWithoutAliases, $deprecatedClassesWithAliases) { - // We can not class alias when working with doctrine annotations - static $deprecatedAnnotations = [ - 'ApiResource' => [ApiPlatform\Core\Annotation\ApiResource::class, ApiPlatform\Metadata\ApiResource::class], - 'ApiProperty' => [ApiPlatform\Core\Annotation\ApiProperty::class, ApiPlatform\Metadata\ApiProperty::class], - 'ApiFilter' => [ApiPlatform\Core\Annotation\ApiFilter::class, ApiPlatform\Metadata\ApiFilter::class], - ]; - - if (isset($deprecatedClassesWithoutAliases[$className])) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The class %s is deprecated, use %s instead.', $className, $deprecatedClassesWithoutAliases[$className])); - - return; - } - - if (isset($deprecatedClassesWithAliases[$className])) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The class %s is deprecated, use %s instead.', $className, $deprecatedClassesWithAliases[$className])); - - class_alias($deprecatedClassesWithAliases[$className], $className); - - return; - } - - if (isset($deprecatedAnnotations[$className])) { - [$annotationClassName, $attributeClassName] = $deprecatedAnnotations[$className]; - trigger_deprecation('api-platform/core', '2.7', sprintf('The Doctrine annotation %s is deprecated, use the PHP attribute %s instead.', $annotationClassName, $attributeClassName)); - - return; - } - - if (isset($deprecatedInterfaces[$className])) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The interface %s is deprecated, use %s instead.', $className, $deprecatedInterfaces[$className])); - } -}); diff --git a/tests/Action/EntrypointActionTest.php b/tests/Action/EntrypointActionTest.php index 1ee49540df1..048aa110d5c 100644 --- a/tests/Action/EntrypointActionTest.php +++ b/tests/Action/EntrypointActionTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Action\EntrypointAction; use ApiPlatform\Api\Entrypoint; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Action/ExceptionActionTest.php b/tests/Action/ExceptionActionTest.php index a33229d637d..f3d28abedaf 100644 --- a/tests/Action/ExceptionActionTest.php +++ b/tests/Action/ExceptionActionTest.php @@ -14,9 +14,6 @@ namespace ApiPlatform\Tests\Action; use ApiPlatform\Action\ExceptionAction; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; @@ -24,6 +21,7 @@ use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Tests\ProphecyTrait; use DomainException; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; @@ -38,7 +36,6 @@ * @author Amrouche Hamza * @author Baptiste Meyer * - * @group legacy * @group time-sensitive */ class ExceptionActionTest extends TestCase @@ -69,62 +66,6 @@ public function testActionWithCatchableException() $this->assertTrue($response->headers->contains('X-Frame-Options', 'deny')); } - /** - * @dataProvider provideOperationExceptionToStatusCases - * @group legacy - */ - public function testLegacyActionWithOperationExceptionToStatus( - array $globalExceptionToStatus, - ?array $resourceExceptionToStatus, - ?array $operationExceptionToStatus, - int $expectedStatusCode - ) { - $this->expectDeprecation('Since api-platform/core 2.7: Use "ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface" instead of "ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface".'); - - $exception = new DomainException(); - $flattenException = FlattenException::create($exception); - - $serializer = $this->prophesize(SerializerInterface::class); - $serializer->serialize($flattenException, 'jsonproblem', ['statusCode' => $expectedStatusCode])->willReturn(''); - - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create('Foo')->willReturn(new ResourceMetadata( - 'Foo', - null, - null, - [ - 'operation' => null !== $operationExceptionToStatus ? ['exception_to_status' => $operationExceptionToStatus] : [], - ], - null, - null !== $resourceExceptionToStatus ? ['exception_to_status' => $resourceExceptionToStatus] : [] - )); - - $exceptionAction = new ExceptionAction( - $serializer->reveal(), - [ - 'jsonproblem' => ['application/problem+json'], - 'jsonld' => ['application/ld+json'], - ], - $globalExceptionToStatus, - $resourceMetadataFactory->reveal() - ); - - $request = new Request(); - $request->setFormat('jsonproblem', 'application/problem+json'); - $request->attributes->replace([ - '_api_resource_class' => 'Foo', - '_api_item_operation_name' => 'operation', - ]); - - $response = $exceptionAction($flattenException, $request); - - $this->assertSame('', $response->getContent()); - $this->assertSame($expectedStatusCode, $response->getStatusCode()); - $this->assertTrue($response->headers->contains('Content-Type', 'application/problem+json; charset=utf-8')); - $this->assertTrue($response->headers->contains('X-Content-Type-Options', 'nosniff')); - $this->assertTrue($response->headers->contains('X-Frame-Options', 'deny')); - } - /** * @dataProvider provideOperationExceptionToStatusCases */ diff --git a/tests/Api/IdentifiersExtractorTest.php b/tests/Api/IdentifiersExtractorTest.php index 762d699d32b..0c4f194e0f9 100644 --- a/tests/Api/IdentifiersExtractorTest.php +++ b/tests/Api/IdentifiersExtractorTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IdentifiersExtractor; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Link; @@ -23,6 +22,7 @@ use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php b/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php index c076153b81a..fa33da2bf0c 100644 --- a/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php +++ b/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Core/Behat/CommandContext.php b/tests/Behat/CommandContext.php similarity index 98% rename from tests/Core/Behat/CommandContext.php rename to tests/Behat/CommandContext.php index c1417b51443..5afe54b009e 100644 --- a/tests/Core/Behat/CommandContext.php +++ b/tests/Behat/CommandContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Gherkin\Node\PyStringNode; diff --git a/tests/Core/Behat/CoverageContext.php b/tests/Behat/CoverageContext.php similarity index 97% rename from tests/Core/Behat/CoverageContext.php rename to tests/Behat/CoverageContext.php index 2143d4e6bf1..ed16a536527 100644 --- a/tests/Core/Behat/CoverageContext.php +++ b/tests/Behat/CoverageContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; diff --git a/tests/Core/Behat/DoctrineContext.php b/tests/Behat/DoctrineContext.php similarity index 99% rename from tests/Core/Behat/DoctrineContext.php rename to tests/Behat/DoctrineContext.php index 7707d44e478..cea400d57ba 100644 --- a/tests/Core/Behat/DoctrineContext.php +++ b/tests/Behat/DoctrineContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Orm\EntityManager; use ApiPlatform\Tests\Fixtures\TestBundle\Document\AbsoluteUrlDummy as AbsoluteUrlDummyDocument; diff --git a/tests/Core/Behat/ElasticsearchContext.php b/tests/Behat/ElasticsearchContext.php similarity index 98% rename from tests/Core/Behat/ElasticsearchContext.php rename to tests/Behat/ElasticsearchContext.php index 94a185f86e0..a11435d0889 100644 --- a/tests/Core/Behat/ElasticsearchContext.php +++ b/tests/Behat/ElasticsearchContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use Behat\Behat\Context\Context; diff --git a/tests/Core/Behat/GraphqlContext.php b/tests/Behat/GraphqlContext.php similarity index 99% rename from tests/Core/Behat/GraphqlContext.php rename to tests/Behat/GraphqlContext.php index a0621f3996c..73e90212104 100644 --- a/tests/Core/Behat/GraphqlContext.php +++ b/tests/Behat/GraphqlContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; diff --git a/tests/Core/Behat/HttpCacheContext.php b/tests/Behat/HttpCacheContext.php similarity index 96% rename from tests/Core/Behat/HttpCacheContext.php rename to tests/Behat/HttpCacheContext.php index 26e49e83e20..5eb40c5f4eb 100644 --- a/tests/Core/Behat/HttpCacheContext.php +++ b/tests/Behat/HttpCacheContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use PHPUnit\Framework\ExpectationFailedException; diff --git a/tests/Core/Behat/HydraContext.php b/tests/Behat/HydraContext.php similarity index 99% rename from tests/Core/Behat/HydraContext.php rename to tests/Behat/HydraContext.php index 9ac151d6148..27fe569cb0c 100644 --- a/tests/Core/Behat/HydraContext.php +++ b/tests/Behat/HydraContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; diff --git a/tests/Core/Behat/JsonApiContext.php b/tests/Behat/JsonApiContext.php similarity index 99% rename from tests/Core/Behat/JsonApiContext.php rename to tests/Behat/JsonApiContext.php index 87855f328bb..e4c17635e87 100644 --- a/tests/Core/Behat/JsonApiContext.php +++ b/tests/Behat/JsonApiContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use ApiPlatform\Tests\Fixtures\TestBundle\Document\CircularReference as CircularReferenceDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyFriend as DummyFriendDocument; diff --git a/tests/Core/Behat/JsonContext.php b/tests/Behat/JsonContext.php similarity index 98% rename from tests/Core/Behat/JsonContext.php rename to tests/Behat/JsonContext.php index 944dcec738d..059df954d78 100644 --- a/tests/Core/Behat/JsonContext.php +++ b/tests/Behat/JsonContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; use Behat\Gherkin\Node\PyStringNode; diff --git a/tests/Core/Behat/JsonHalContext.php b/tests/Behat/JsonHalContext.php similarity index 98% rename from tests/Core/Behat/JsonHalContext.php rename to tests/Behat/JsonHalContext.php index fdab6e63737..f1f3c890fdf 100644 --- a/tests/Core/Behat/JsonHalContext.php +++ b/tests/Behat/JsonHalContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; diff --git a/tests/Core/Behat/MercureContext.php b/tests/Behat/MercureContext.php similarity index 97% rename from tests/Core/Behat/MercureContext.php rename to tests/Behat/MercureContext.php index 2ee18723932..35b2e213bbc 100644 --- a/tests/Core/Behat/MercureContext.php +++ b/tests/Behat/MercureContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Gherkin\Node\PyStringNode; diff --git a/tests/Core/Behat/OpenApiContext.php b/tests/Behat/OpenApiContext.php similarity index 99% rename from tests/Core/Behat/OpenApiContext.php rename to tests/Behat/OpenApiContext.php index 2ddc5ed1875..d53c529fc4b 100644 --- a/tests/Core/Behat/OpenApiContext.php +++ b/tests/Behat/OpenApiContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; diff --git a/tests/Core/Behat/XmlContext.php b/tests/Behat/XmlContext.php similarity index 96% rename from tests/Core/Behat/XmlContext.php rename to tests/Behat/XmlContext.php index 8e18ffd9408..af05fed1fce 100644 --- a/tests/Core/Behat/XmlContext.php +++ b/tests/Behat/XmlContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Gherkin\Node\PyStringNode; use Behatch\Context\XmlContext as BaseXmlContext; diff --git a/tests/Core/Annotation/ApiFilterTest.php b/tests/Core/Annotation/ApiFilterTest.php deleted file mode 100644 index 45b175ecaa8..00000000000 --- a/tests/Core/Annotation/ApiFilterTest.php +++ /dev/null @@ -1,75 +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); - -namespace ApiPlatform\Core\Tests\Annotation; - -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Tests\Fixtures\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * @author Antoine Bluchet - */ -class ApiFilterTest extends TestCase -{ - public function testInvalidConstructor() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('This annotation needs a value representing the filter class.'); - - new ApiFilter(null); // @phpstan-ignore-line - } - - public function testInvalidFilter() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The filter class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy" does not implement "ApiPlatform\\Api\\FilterInterface". Did you forget a use statement?'); - - new ApiFilter(['value' => Dummy::class]); // @phpstan-ignore-line - } - - public function testInvalidProperty() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Property "foo" does not exist on the ApiFilter annotation.'); - - new ApiFilter(['value' => DummyFilter::class, 'foo' => 'bar']); // @phpstan-ignore-line - } - - public function testAssignation() - { - $resource = new ApiFilter(['value' => DummyFilter::class, 'strategy' => 'test', 'properties' => ['one', 'two'], 'arguments' => ['args']]); // @phpstan-ignore-line - - $this->assertEquals($resource->filterClass, DummyFilter::class); - $this->assertEquals($resource->strategy, 'test'); - $this->assertEquals($resource->properties, ['one', 'two']); - $this->assertEquals($resource->arguments, ['args']); - } - - /** - * @requires PHP 8.0 - */ - public function testAssignationAttribute() - { - $filter = eval(<<<'PHP' -return new \ApiPlatform\Core\Annotation\ApiFilter(\ApiPlatform\Tests\Fixtures\DummyFilter::class, strategy: 'test', properties: ['one', 'two'], arguments: ['args']); -PHP -); - - $this->assertEquals($filter->filterClass, DummyFilter::class); - $this->assertEquals($filter->strategy, 'test'); - $this->assertEquals($filter->properties, ['one', 'two']); - $this->assertEquals($filter->arguments, ['args']); - } -} diff --git a/tests/Core/Annotation/ApiPropertyTest.php b/tests/Core/Annotation/ApiPropertyTest.php deleted file mode 100644 index e777127395b..00000000000 --- a/tests/Core/Annotation/ApiPropertyTest.php +++ /dev/null @@ -1,107 +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); - -namespace ApiPlatform\Core\Tests\Annotation; - -use ApiPlatform\Core\Annotation\ApiProperty; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class ApiPropertyTest extends TestCase -{ - public function testAssignation() - { - $property = new ApiProperty(); - $property->description = 'description'; - $property->readable = true; - $property->writable = true; - $property->readableLink = true; - $property->writableLink = true; - $property->required = true; - $property->iri = 'http://example.com/prop'; - $property->identifier = true; - $property->attributes = ['foo' => 'bar']; - - $this->assertEquals('description', $property->description); - $this->assertTrue($property->readable); - $this->assertTrue($property->writable); - $this->assertTrue($property->readableLink); - $this->assertTrue($property->writableLink); - $this->assertTrue($property->required); - $this->assertEquals('http://example.com/prop', $property->iri); - $this->assertTrue($property->identifier); - $this->assertEquals(['foo' => 'bar'], $property->attributes); - } - - public function testConstruct() - { - $property = new ApiProperty([ - 'deprecationReason' => 'this field is deprecated', - 'fetchable' => true, - 'fetchEager' => false, - 'jsonldContext' => ['foo' => 'bar'], - 'security' => 'is_granted(\'ROLE_ADMIN\')', - 'swaggerContext' => ['foo' => 'baz'], - 'openapiContext' => ['foo' => 'baz'], - 'push' => true, - 'attributes' => ['unknown' => 'unknown', 'fetchable' => false], - ]); - $this->assertEquals([ - 'deprecation_reason' => 'this field is deprecated', - 'fetchable' => false, - 'fetch_eager' => false, - 'jsonld_context' => ['foo' => 'bar'], - 'security' => 'is_granted(\'ROLE_ADMIN\')', - 'swagger_context' => ['foo' => 'baz'], - 'openapi_context' => ['foo' => 'baz'], - 'push' => true, - 'unknown' => 'unknown', - ], $property->attributes); - } - - /** - * @requires PHP 8.0 - */ - public function testConstructAttribute() - { - $property = eval(<<<'PHP' -return new \ApiPlatform\Core\Annotation\ApiProperty( - deprecationReason: 'this field is deprecated', - fetchable: true, - fetchEager: false, - jsonldContext: ['foo' => 'bar'], - security: 'is_granted(\'ROLE_ADMIN\')', - swaggerContext: ['foo' => 'baz'], - openapiContext: ['foo' => 'baz'], - push: true, - attributes: ['unknown' => 'unknown', 'fetchable' => false] -); -PHP - ); - - $this->assertEquals([ - 'deprecation_reason' => 'this field is deprecated', - 'fetchable' => false, - 'fetch_eager' => false, - 'jsonld_context' => ['foo' => 'bar'], - 'security' => 'is_granted(\'ROLE_ADMIN\')', - 'swagger_context' => ['foo' => 'baz'], - 'openapi_context' => ['foo' => 'baz'], - 'push' => true, - 'unknown' => 'unknown', - 'security_post_denormalize' => null, - ], $property->attributes); - } -} diff --git a/tests/Core/Annotation/ApiResourceTest.php b/tests/Core/Annotation/ApiResourceTest.php deleted file mode 100644 index 1e1a3b6e550..00000000000 --- a/tests/Core/Annotation/ApiResourceTest.php +++ /dev/null @@ -1,297 +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); - -namespace ApiPlatform\Core\Tests\Annotation; - -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Tests\Fixtures\AnnotatedClass; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8; -use Doctrine\Common\Annotations\AnnotationReader; -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Kévin Dunglas - */ -class ApiResourceTest extends TestCase -{ - use ExpectDeprecationTrait; - - /** - * @group legacy - */ - public function testConstruct() - { - $resource = new ApiResource([ - 'security' => 'is_granted("ROLE_FOO")', - 'securityMessage' => 'You are not foo.', - 'securityPostDenormalize' => 'is_granted("ROLE_BAR")', - 'securityPostDenormalizeMessage' => 'You are not bar.', - 'securityPostValidation' => 'is_granted("ROLE_FOO")', - 'securityPostValidationMessage' => 'You are not foo.', - 'attributes' => ['foo' => 'bar', 'validation_groups' => ['baz', 'qux'], 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']]], - 'collectionOperations' => ['bar' => ['foo']], - 'denormalizationContext' => ['groups' => ['foo']], - 'description' => 'description', - 'fetchPartial' => true, - 'forceEager' => false, - 'formats' => ['foo', 'bar' => ['application/bar']], - 'filters' => ['foo', 'bar'], - 'graphql' => ['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], - 'input' => 'Foo', - 'iri' => 'http://example.com/res', - 'itemOperations' => ['foo' => ['bar']], - 'mercure' => ['private' => true], - 'messenger' => true, - 'normalizationContext' => ['groups' => ['bar']], - 'order' => ['foo', 'bar' => 'ASC'], - 'openapiContext' => ['description' => 'foo'], - 'output' => 'Bar', - 'paginationClientEnabled' => true, - 'paginationClientItemsPerPage' => true, - 'paginationClientPartial' => true, - 'paginationEnabled' => true, - 'paginationFetchJoinCollection' => true, - 'paginationItemsPerPage' => 42, - 'paginationMaximumItemsPerPage' => 50, - 'paginationPartial' => true, - 'routePrefix' => '/foo', - 'shortName' => 'shortName', - 'subresourceOperations' => [], - 'swaggerContext' => ['description' => 'bar'], - 'validationGroups' => ['foo', 'bar'], - 'sunset' => 'Thu, 11 Oct 2018 00:00:00 +0200', - 'urlGenerationStrategy' => UrlGeneratorInterface::ABS_PATH, - 'queryParameterValidationEnabled' => false, - ]); - - $this->assertSame('shortName', $resource->shortName); - $this->assertSame('description', $resource->description); - $this->assertSame('http://example.com/res', $resource->iri); - $this->assertSame(['foo' => ['bar']], $resource->itemOperations); - $this->assertSame(['bar' => ['foo']], $resource->collectionOperations); - $this->assertSame([], $resource->subresourceOperations); - $this->assertSame(['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], $resource->graphql); - $this->assertEquals([ - 'security' => 'is_granted("ROLE_FOO")', - 'security_message' => 'You are not foo.', - 'security_post_denormalize' => 'is_granted("ROLE_BAR")', - 'security_post_denormalize_message' => 'You are not bar.', - 'security_post_validation' => 'is_granted("ROLE_FOO")', - 'security_post_validation_message' => 'You are not foo.', - 'denormalization_context' => ['groups' => ['foo']], - 'fetch_partial' => true, - 'foo' => 'bar', - 'force_eager' => false, - 'formats' => ['foo', 'bar' => ['application/bar']], - 'filters' => ['foo', 'bar'], - 'input' => 'Foo', - 'mercure' => ['private' => true], - 'messenger' => true, - 'normalization_context' => ['groups' => ['bar']], - 'order' => ['foo', 'bar' => 'ASC'], - 'openapi_context' => ['description' => 'foo'], - 'output' => 'Bar', - 'pagination_client_enabled' => true, - 'pagination_client_items_per_page' => true, - 'pagination_client_partial' => true, - 'pagination_enabled' => true, - 'pagination_fetch_join_collection' => true, - 'pagination_items_per_page' => 42, - 'pagination_maximum_items_per_page' => 50, - 'pagination_partial' => true, - 'route_prefix' => '/foo', - 'swagger_context' => ['description' => 'bar'], - 'validation_groups' => ['baz', 'qux'], - 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']], - 'sunset' => 'Thu, 11 Oct 2018 00:00:00 +0200', - 'url_generation_strategy' => 1, - 'query_parameter_validation_enabled' => false, - ], $resource->attributes); - } - - /** - * @requires PHP 8.0 - */ - public function testConstructAttribute() - { - $resource = eval(<<<'PHP' -return new \ApiPlatform\Core\Annotation\ApiResource( - security: 'is_granted("ROLE_FOO")', - securityMessage: 'You are not foo.', - securityPostDenormalize: 'is_granted("ROLE_BAR")', - securityPostDenormalizeMessage: 'You are not bar.', - securityPostValidation: 'is_granted("ROLE_FOO")', - securityPostValidationMessage: 'You are not foo.', - attributes: ['foo' => 'bar', 'validation_groups' => ['baz', 'qux'], 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']]], - collectionOperations: ['bar' => ['foo']], - denormalizationContext: ['groups' => ['foo']], - description: 'description', - fetchPartial: true, - forceEager: false, - formats: ['foo', 'bar' => ['application/bar']], - filters: ['foo', 'bar'], - graphql: ['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], - input: 'Foo', - iri: 'http://example.com/res', - itemOperations: ['foo' => ['bar']], - mercure: ['private' => true], - messenger: true, - normalizationContext: ['groups' => ['bar']], - order: ['foo', 'bar' => 'ASC'], - openapiContext: ['description' => 'foo'], - output: 'Bar', - paginationClientEnabled: true, - paginationClientItemsPerPage: true, - paginationClientPartial: true, - paginationEnabled: true, - paginationFetchJoinCollection: true, - paginationItemsPerPage: 42, - paginationMaximumItemsPerPage: 50, - paginationPartial: true, - routePrefix: '/foo', - shortName: 'shortName', - subresourceOperations: [], - swaggerContext: ['description' => 'bar'], - validationGroups: ['foo', 'bar'], - sunset: 'Thu, 11 Oct 2018 00:00:00 +0200', - urlGenerationStrategy: \ApiPlatform\Api\UrlGeneratorInterface::ABS_PATH, - deprecationReason: 'reason', - elasticsearch: true, - hydraContext: ['hydra' => 'foo'], - paginationViaCursor: ['foo'], - stateless: true, - exceptionToStatus: [ - \DomainException::class => 400, - ], - queryParameterValidationEnabled: false, -); -PHP - ); - - $this->assertSame('shortName', $resource->shortName); - $this->assertSame('description', $resource->description); - $this->assertSame('http://example.com/res', $resource->iri); - $this->assertSame(['foo' => ['bar']], $resource->itemOperations); - $this->assertSame(['bar' => ['foo']], $resource->collectionOperations); - $this->assertSame([], $resource->subresourceOperations); - $this->assertSame(['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], $resource->graphql); - $this->assertEquals([ - 'security' => 'is_granted("ROLE_FOO")', - 'security_message' => 'You are not foo.', - 'security_post_denormalize' => 'is_granted("ROLE_BAR")', - 'security_post_denormalize_message' => 'You are not bar.', - 'security_post_validation' => 'is_granted("ROLE_FOO")', - 'security_post_validation_message' => 'You are not foo.', - 'denormalization_context' => ['groups' => ['foo']], - 'fetch_partial' => true, - 'foo' => 'bar', - 'force_eager' => false, - 'formats' => ['foo', 'bar' => ['application/bar']], - 'filters' => ['foo', 'bar'], - 'input' => 'Foo', - 'mercure' => ['private' => true], - 'messenger' => true, - 'normalization_context' => ['groups' => ['bar']], - 'order' => ['foo', 'bar' => 'ASC'], - 'openapi_context' => ['description' => 'foo'], - 'output' => 'Bar', - 'pagination_client_enabled' => true, - 'pagination_client_items_per_page' => true, - 'pagination_client_partial' => true, - 'pagination_enabled' => true, - 'pagination_fetch_join_collection' => true, - 'pagination_items_per_page' => 42, - 'pagination_maximum_items_per_page' => 50, - 'pagination_partial' => true, - 'route_prefix' => '/foo', - 'swagger_context' => ['description' => 'bar'], - 'validation_groups' => ['baz', 'qux'], - 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']], - 'sunset' => 'Thu, 11 Oct 2018 00:00:00 +0200', - 'url_generation_strategy' => 1, - 'deprecation_reason' => 'reason', - 'elasticsearch' => true, - 'hydra_context' => ['hydra' => 'foo'], - 'pagination_via_cursor' => ['foo'], - 'stateless' => true, - 'composite_identifier' => null, - 'exception_to_status' => [ - \DomainException::class => 400, - ], - 'query_parameter_validation_enabled' => false, - ], $resource->attributes); - } - - /** - * @requires PHP 8.0 - */ - public function testUseAttribute() - { - $this->assertSame('Hey PHP 8', (new \ReflectionClass(DummyPhp8::class))->getAttributes(ApiResource::class)[0]->getArguments()['description']); - } - - /** - * @group legacy - */ - public function testApiResourceAnnotation() - { - $reader = new AnnotationReader(); - /** - * @var ApiResource - */ - $resource = $reader->getClassAnnotation(new \ReflectionClass(AnnotatedClass::class), ApiResource::class); - - $this->assertSame('shortName', $resource->shortName); - $this->assertSame('description', $resource->description); - $this->assertSame('http://example.com/res', $resource->iri); - $this->assertSame(['bar' => ['foo']], $resource->collectionOperations); - $this->assertSame(['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], $resource->graphql); - $this->assertEquals([ - 'foo' => 'bar', - 'route_prefix' => '/whatever', - 'security' => "is_granted('ROLE_FOO')", - 'security_message' => 'You are not foo.', - 'security_post_denormalize' => "is_granted('ROLE_BAR')", - 'security_post_denormalize_message' => 'You are not bar.', - 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']], - ], $resource->attributes); - } - - public function testConstructWithInvalidAttribute() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Unknown property "invalidAttribute" on annotation "ApiPlatform\\Core\\Annotation\\ApiResource".'); - - new ApiResource([ - 'shortName' => 'shortName', - 'routePrefix' => '/foo', - 'invalidAttribute' => 'exception', - ]); - } - - /** - * @group legacy - * @expectedDeprecation Attribute "accessControl" is deprecated in annotation since API Platform 2.5, prefer using "security" attribute instead - * @expectedDeprecation Attribute "accessControlMessage" is deprecated in annotation since API Platform 2.5, prefer using "securityMessage" attribute instead - */ - public function testWithDeprecatedAttributes() - { - new ApiResource([ - 'accessControl' => "is_granted('ROLE_USER')", - 'accessControlMessage' => 'Nope!', - ]); - } -} diff --git a/tests/Core/Annotation/ApiSubresourceTest.php b/tests/Core/Annotation/ApiSubresourceTest.php deleted file mode 100644 index fc1ed117299..00000000000 --- a/tests/Core/Annotation/ApiSubresourceTest.php +++ /dev/null @@ -1,53 +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); - -namespace ApiPlatform\Core\Tests\Annotation; - -use ApiPlatform\Core\Annotation\ApiSubresource; -use PHPUnit\Framework\TestCase; - -/** - * @author Cody Banman - */ -class ApiSubresourceTest extends TestCase -{ - public function testAssignation() - { - $property = new ApiSubresource(); - $property->maxDepth = 1; - - $this->assertEquals(1, $property->maxDepth); - } - - public function testConstruct() - { - $property = new ApiSubresource([ // @phpstan-ignore-line - 'maxDepth' => 1, - ]); - $this->assertEquals(1, $property->maxDepth); - } - - /** - * @requires PHP 8.0 - */ - public function testConstructAttribute() - { - $property = eval(<<<'PHP' -return new \ApiPlatform\Core\Annotation\ApiSubresource( - maxDepth: 1 -); -PHP - ); - $this->assertEquals(1, $property->maxDepth); - } -} diff --git a/tests/Core/Api/CachedIdentifiersExtractorTest.php b/tests/Core/Api/CachedIdentifiersExtractorTest.php deleted file mode 100644 index 96666aac644..00000000000 --- a/tests/Core/Api/CachedIdentifiersExtractorTest.php +++ /dev/null @@ -1,244 +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); - -namespace ApiPlatform\Core\Tests\Api; - -use ApiPlatform\Core\Api\CachedIdentifiersExtractor; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class CachedIdentifiersExtractorTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function itemProvider() - { - $dummy = new Dummy(); - $dummy->setId($id = 1); - yield [$dummy, ['id' => $id]]; - - $dummy = new Dummy(); - $dummy->setId($id = new Uuid()); - yield [$dummy, ['id' => $id]]; - } - - /** - * @dataProvider itemProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testFirstPass($item, $expected) - { - $cacheItemKey = 'iri_identifiers'.md5(Dummy::class); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(false); - $cacheItemProphecy->set(['id'])->shouldBeCalled()->willReturn($cacheItemProphecy->reveal()); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem($cacheItemKey)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldBeCalled(); - - $decoratedProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $decoratedProphecy->getIdentifiersFromItem($item)->willReturn($expected); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new CachedIdentifiersExtractor($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item), 'Trigger the local cache'); - - $expected = ['id']; - - $decoratedProphecy->getIdentifiersFromResourceClass(Dummy::class)->willReturn($expected); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class), 'Trigger the local cache'); - } - - /** - * @dataProvider itemProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testSecondPass($item, $expected) - { - $cacheItemKey = 'iri_identifiers'.md5(Dummy::class); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(true); - $cacheItemProphecy->get()->willReturn(['id']); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem($cacheItemKey)->willReturn($cacheItemProphecy); - - $decoratedProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $decoratedProphecy->getIdentifiersFromItem($item)->shouldNotBeCalled(); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new CachedIdentifiersExtractor($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item), 'Trigger the local cache'); - - $expected = ['id']; - - $decoratedProphecy->getIdentifiersFromResourceClass(Dummy::class)->willReturn($expected); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class), 'Trigger the local cache'); - } - - public function identifiersRelatedProvider() - { - $related = new RelatedDummy(); - $related->setId($relatedId = 2); - - $dummy = new Dummy(); - $dummy->setId($id = 1); - $dummy->setRelatedDummy($related); - - yield [$dummy, ['id' => $id, 'relatedDummy' => $relatedId]]; - - $related = new RelatedDummy(); - $related->setId($relatedId = 1); - - $dummy = new Dummy(); - $dummy->setId($id = new Uuid()); - $dummy->setRelatedDummy($related); - - yield [$dummy, ['id' => $id, 'relatedDummy' => $relatedId]]; - - $related = new RelatedDummy(); - $related->setId($relatedId = new Uuid()); - - $dummy = new Dummy(); - $dummy->setId($id = new Uuid()); - $dummy->setRelatedDummy($related); - - yield [$dummy, ['id' => $id, 'relatedDummy' => $relatedId]]; - } - - /** - * @dataProvider identifiersRelatedProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testFirstPassWithRelated($item, $expected) - { - $cacheItemKey = 'iri_identifiers'.md5(Dummy::class); - $relatedCacheItemKey = 'iri_identifiers'.md5(RelatedDummy::class); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(true); - $cacheItemProphecy->get()->willReturn(['id', 'relatedDummy']); - - $relatedCacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $relatedCacheItemProphecy->isHit()->willReturn(false); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem($cacheItemKey)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->getItem($relatedCacheItemKey)->willReturn($relatedCacheItemProphecy); - - $decoratedProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $decoratedProphecy->getIdentifiersFromItem($item)->willReturn($expected); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(Argument::type(RelatedDummy::class))->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new CachedIdentifiersExtractor($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item), 'Trigger the local cache'); - } - - /** - * @dataProvider identifiersRelatedProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testSecondPassWithRelated($item, $expected) - { - $cacheItemKey = 'iri_identifiers'.md5(Dummy::class); - $relatedCacheItemKey = 'iri_identifiers'.md5(RelatedDummy::class); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(true); - $cacheItemProphecy->get()->willReturn(['id', 'relatedDummy']); - - $relatedCacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $relatedCacheItemProphecy->isHit()->willReturn(true); - $relatedCacheItemProphecy->get()->willReturn(['id']); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem($cacheItemKey)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->getItem($relatedCacheItemKey)->willReturn($relatedCacheItemProphecy); - - $decoratedProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $decoratedProphecy->getIdentifiersFromItem($item)->shouldNotBeCalled(); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(Argument::type(RelatedDummy::class))->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new CachedIdentifiersExtractor($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item), 'Trigger the local cache'); - } - - /** - * @group legacy - */ - public function testDeprecationResourceClassResolver() - { - $this->expectDeprecation('Not injecting ApiPlatform\Core\Api\ResourceClassResolverInterface in the CachedIdentifiersExtractor might introduce cache issues with object identifiers.'); - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $decoration = $this->prophesize(IdentifiersExtractorInterface::class); - - new CachedIdentifiersExtractor($cacheItemPool->reveal(), $decoration->reveal(), null); - } -} diff --git a/tests/Core/Api/EntrypointTest.php b/tests/Core/Api/EntrypointTest.php deleted file mode 100644 index 85b0a3d7756..00000000000 --- a/tests/Core/Api/EntrypointTest.php +++ /dev/null @@ -1,32 +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); - -namespace ApiPlatform\Core\Tests\Api; - -use ApiPlatform\Api\Entrypoint; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * @author Amrouche Hamza - */ -class EntrypointTest extends TestCase -{ - public function testGetResourceNameCollection() - { - $resourceNameCollection = new ResourceNameCollection([Dummy::class]); - $entrypoint = new Entrypoint($resourceNameCollection); - $this->assertEquals($entrypoint->getResourceNameCollection(), $resourceNameCollection); - } -} diff --git a/tests/Core/Api/FilterCollectionFactoryTest.php b/tests/Core/Api/FilterCollectionFactoryTest.php deleted file mode 100644 index ef94c8edad4..00000000000 --- a/tests/Core/Api/FilterCollectionFactoryTest.php +++ /dev/null @@ -1,50 +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); - -namespace ApiPlatform\Core\Tests\Api; - -use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\FilterCollectionFactory; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; - -/** - * @author Baptiste Meyer - */ -class FilterCollectionFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testCreateFilterCollectionFromLocator() - { - $filter = $this->prophesize(FilterInterface::class)->reveal(); - - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filterLocatorProphecy->has('foo')->willReturn(true)->shouldBeCalled(); - $filterLocatorProphecy->get('foo')->willReturn($filter)->shouldBeCalled(); - $filterLocatorProphecy->has('bar')->willReturn(false)->shouldBeCalled(); - - $filterCollection = (new FilterCollectionFactory(['foo', 'bar']))->createFilterCollectionFromLocator($filterLocatorProphecy->reveal()); - - $this->assertArrayNotHasKey('bar', $filterCollection); - $this->assertTrue(isset($filterCollection['foo'])); - $this->assertInstanceOf(FilterInterface::class, $filterCollection['foo']); - $this->assertEquals(new FilterCollection(['foo' => $filter]), $filterCollection); - } -} diff --git a/tests/Core/Api/FilterCollectionTest.php b/tests/Core/Api/FilterCollectionTest.php deleted file mode 100644 index 65461d060ad..00000000000 --- a/tests/Core/Api/FilterCollectionTest.php +++ /dev/null @@ -1,33 +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); - -namespace ApiPlatform\Core\Tests\Api; - -use ApiPlatform\Core\Api\FilterCollection; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class FilterCollectionTest extends TestCase -{ - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testIsArrayObject() - { - $filterCollection = new FilterCollection(); - $this->assertInstanceOf(\ArrayObject::class, $filterCollection); - } -} diff --git a/tests/Core/Api/FilterLocatorTraitTest.php b/tests/Core/Api/FilterLocatorTraitTest.php deleted file mode 100644 index 4501a427dc5..00000000000 --- a/tests/Core/Api/FilterLocatorTraitTest.php +++ /dev/null @@ -1,161 +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); - -namespace ApiPlatform\Core\Tests\Api; - -use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Api\FilterLocatorTrait; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; - -/** - * @author Baptiste Meyer - */ -class FilterLocatorTraitTest extends TestCase -{ - use ProphecyTrait; - - public function testSetFilterLocator() - { - $filterLocator = $this->prophesize(ContainerInterface::class)->reveal(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator($filterLocator); - - $this->assertEquals($filterLocator, $filterLocatorTraitImpl->getFilterLocator()); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testSetFilterLocatorWithDeprecatedFilterCollection() - { - $filterCollection = new FilterCollection(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator($filterCollection); - - $this->assertEquals($filterCollection, $filterLocatorTraitImpl->getFilterLocator()); - } - - public function testSetFilterLocatorWithNullAndNullAllowed() - { - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(null, true); - - $this->assertNull($filterLocatorTraitImpl->getFilterLocator()); - } - - /** - * @group legacy - */ - public function testSetFilterLocatorWithNullAndNullNotAllowed() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface.'); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(null); - } - - /** - * @group legacy - */ - public function testSetFilterLocatorWithInvalidFilterLocator() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface or null.'); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(new \ArrayObject(), true); - } - - public function testGetFilter() - { - $filter = $this->prophesize(FilterInterface::class)->reveal(); - - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filterLocatorProphecy->has('foo')->willReturn(true)->shouldBeCalled(); - $filterLocatorProphecy->get('foo')->willReturn($filter)->shouldBeCalled(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator($filterLocatorProphecy->reveal()); - - $returnedFilter = $filterLocatorTraitImpl->getFilter('foo'); - - $this->assertInstanceOf(FilterInterface::class, $returnedFilter); - $this->assertEquals($filter, $returnedFilter); - } - - public function testGetFilterWithNonexistentFilterId() - { - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filterLocatorProphecy->has('foo')->willReturn(false)->shouldBeCalled(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator($filterLocatorProphecy->reveal()); - - $filter = $filterLocatorTraitImpl->getFilter('foo'); - - $this->assertNull($filter); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testGetFilterWithDeprecatedFilterCollection() - { - $filter = $this->prophesize(FilterInterface::class)->reveal(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(new FilterCollection(['foo' => $filter])); - - $returnedFilter = $filterLocatorTraitImpl->getFilter('foo'); - - $this->assertInstanceOf(FilterInterface::class, $returnedFilter); - $this->assertEquals($filter, $returnedFilter); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testGetFilterWithNonexistentFilterIdAndDeprecatedFilterCollection() - { - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(new FilterCollection()); - - $filter = $filterLocatorTraitImpl->getFilter('foo'); - - $this->assertNull($filter); - } - - private function getFilterLocatorTraitImpl() - { - return new class() { - use FilterLocatorTrait { - FilterLocatorTrait::setFilterLocator as public; - FilterLocatorTrait::getFilter as public; - } - - public function getFilterLocator() - { - return $this->filterLocator; - } - }; - } -} diff --git a/tests/Core/Api/FormatsProviderTest.php b/tests/Core/Api/FormatsProviderTest.php deleted file mode 100644 index e29e5430226..00000000000 --- a/tests/Core/Api/FormatsProviderTest.php +++ /dev/null @@ -1,189 +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); - -namespace ApiPlatform\Core\Tests\Api; - -use ApiPlatform\Core\Api\FormatsProvider; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - * - * @group legacy - */ -class FormatsProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testNoResourceClass() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create()->shouldNotBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => 'application/ld+json']); - - $this->assertSame(['jsonld' => 'application/ld+json'], $formatProvider->getFormatsFromAttributes([])); - } - - public function testResourceClassWithoutFormatsAttributes() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata())->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testResourceClassWithFormatsAttributes() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testResourceClassWithFormatsAttributesOverRiddingMimeTypes() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => 'application/fuz']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => ['application/fuz']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testBadFormatsShortDeclaration() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('You either need to add the format \'foo\' to your project configuration or declare a mime type for it in your annotation.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['foo']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); - - $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get']); - } - - public function testInvalidFormatsShortDeclaration() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes value must be a string when trying to include an already configured format, array given.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => [['badFormat']]]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testInvalidFormatsDeclaration() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes must be an array, string given for resource class \'Foo\'.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => 'badFormat']); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testResourceClassWithoutFormatsAttributesFromOperation() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata())->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } - - public function testResourceClassWithFormatsAttributesFromOperation() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } - - public function testResourceClassWithFormatsAttributesOverRiddingMimeTypesFromOperation() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => 'application/fuz']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => ['application/fuz']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } - - public function testBadFormatsShortDeclarationFromOperation() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('You either need to add the format \'foo\' to your project configuration or declare a mime type for it in your annotation.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['foo']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); - - $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION); - } - - public function testInvalidFormatsShortDeclarationFromOperation() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes value must be a string when trying to include an already configured format, array given.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => [['badFormat']]]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } - - public function testInvalidFormatsDeclarationFromOperation() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes must be an array, string given for resource class \'Foo\'.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => 'badFormat']); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } -} diff --git a/tests/Core/Api/IdentifiersExtractorTest.php b/tests/Core/Api/IdentifiersExtractorTest.php deleted file mode 100644 index 60e2bf924e7..00000000000 --- a/tests/Core/Api/IdentifiersExtractorTest.php +++ /dev/null @@ -1,276 +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); - -namespace ApiPlatform\Core\Tests\Api; - -use ApiPlatform\Core\Api\IdentifiersExtractor; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Exception\RuntimeException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceInterfaceImplementation; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Antoine Bluchet - */ -class IdentifiersExtractorTest extends TestCase -{ - use ProphecyTrait; - - public function testGetIdentifiersFromResourceClass() - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id']); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame(['id'], $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - } - - public function testGetCompositeIdentifiersFromResourceClass() - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id', 'name']); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame(['id', 'name'], $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - } - - public function itemProvider() - { - $dummy = new Dummy(); - $dummy->setId(1); - yield [$dummy, ['id' => 1]]; - - $uuid = new Uuid(); - $dummy = new Dummy(); - $dummy->setId($uuid); - yield [$dummy, ['id' => $uuid]]; - } - - /** - * @dataProvider itemProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testGetIdentifiersFromItem($item, $expected) - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id']); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - } - - public function itemProviderComposite() - { - $dummy = new Dummy(); - $dummy->setId(1); - $dummy->setName('foo'); - yield [$dummy, ['id' => 1, 'name' => 'foo']]; - - $dummy = new Dummy(); - $dummy->setId($uuid = new Uuid()); - $dummy->setName('foo'); - yield [$dummy, ['id' => $uuid, 'name' => 'foo']]; - } - - /** - * @dataProvider itemProviderComposite - * - * @param mixed $item - * @param mixed $expected - */ - public function testGetCompositeIdentifiersFromItem($item, $expected) - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id', 'name']); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - } - - public function itemProviderRelated() - { - $related = new RelatedDummy(); - $related->setId(2); - - $dummy = new Dummy(); - $dummy->setId(1); - $dummy->setRelatedDummy($related); - yield [$dummy, ['id' => 1, 'relatedDummy' => 2]]; - - $uuid2 = new Uuid(); - $related = new RelatedDummy(); - $related->setId($uuid2); - - $uuid = new Uuid(); - $dummy = new Dummy(); - $dummy->setId($uuid); - $dummy->setRelatedDummy($related); - yield [$dummy, ['id' => $uuid, 'relatedDummy' => $uuid2]]; - } - - /** - * @dataProvider itemProviderRelated - * - * @param mixed $item - * @param mixed $expected - */ - public function testGetRelatedIdentifiersFromItem($item, $expected) - { - $prophecies = $this->getMetadataFactoryProphecies(Dummy::class, ['id', 'relatedDummy']); - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(RelatedDummy::class, ['id'], $prophecies); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(Argument::type(RelatedDummy::class))->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - } - - public function testThrowNoIdentifierFromItem() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('No identifier found in "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\RelatedDummy" through relation "relatedDummy" of "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy" used as identifier'); - - $related = new RelatedDummy(); - $related->setId(2); - - $dummy = new Dummy(); - $dummy->setId(1); - $dummy->setRelatedDummy($related); - - $prophecies = $this->getMetadataFactoryProphecies(Dummy::class, ['id', 'relatedDummy']); - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(RelatedDummy::class, [], $prophecies); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($dummy)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(Argument::type(RelatedDummy::class))->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $identifiersExtractor->getIdentifiersFromItem($dummy); - } - - public function testGetsIdentifiersFromCorrectResourceClass(): void - { - $item = new ResourceInterfaceImplementation(); - $item->setFoo('woot'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(ResourceInterface::class)->willReturn(new PropertyNameCollection(['foo', 'fooz'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(ResourceInterface::class, 'foo')->willReturn((new PropertyMetadata())->withIdentifier(true)); - $propertyMetadataFactoryProphecy->create(ResourceInterface::class, 'fooz')->willReturn(new PropertyMetadata()); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(ResourceInterface::class); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $identifiersExtractor->getIdentifiersFromItem($item); - - $this->assertSame(['foo' => 'woot'], $identifiersExtractor->getIdentifiersFromItem($item)); - } - - public function testNoIdentifiers(): void - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('No identifier defined in "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy". You should add #[\ApiPlatform\Core\Annotation\ApiProperty(identifier: true)]" on the property identifying the resource.'); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['foo'])); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'foo')->willReturn(new PropertyMetadata()); - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class); - } - - /** - * @group legacy - * @expectedDeprecation Not injecting ApiPlatform\Core\Api\ResourceClassResolverInterface in the IdentifiersExtractor might introduce cache issues with object identifiers. - */ - public function testLegacyGetIdentifiersFromItem() - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id']); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()); - - $dummy = new Dummy(); - $dummy->setId(1); - - $this->assertSame(['id' => 1], $identifiersExtractor->getIdentifiersFromItem($dummy)); - } - - private function getMetadataFactoryProphecies($class, $identifiers, array $prophecies = null) - { - // adds a random property that is not an identifier - $properties = array_merge(['foo'], $identifiers); - - if (!$prophecies) { - $prophecies = [$this->prophesize(PropertyNameCollectionFactoryInterface::class), $this->prophesize(PropertyMetadataFactoryInterface::class)]; - } - - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $prophecies; - - $propertyNameCollectionFactoryProphecy->create($class)->willReturn(new PropertyNameCollection($properties)); - - foreach ($properties as $prop) { - $metadata = new PropertyMetadata(); - $propertyMetadataFactoryProphecy->create($class, $prop)->willReturn($metadata->withIdentifier(\in_array($prop, $identifiers, true))); - } - - return [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy]; - } - - public function testDefaultIdentifierId(): void - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['id'])); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->willReturn(new PropertyMetadata()); - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame(['id'], $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - } -} diff --git a/tests/Core/Api/ResourceClassResolverTest.php b/tests/Core/Api/ResourceClassResolverTest.php deleted file mode 100644 index c775778da41..00000000000 --- a/tests/Core/Api/ResourceClassResolverTest.php +++ /dev/null @@ -1,209 +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); - -namespace ApiPlatform\Tests\Api; - -use ApiPlatform\Api\ResourceClassResolver; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\State\Pagination\PaginatorInterface; -use ApiPlatform\Tests\Fixtures\DummyResourceImplementation; -use ApiPlatform\Tests\Fixtures\DummyResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; -use PHPUnit\Framework\TestCase; - -/** - * @author Amrouche Hamza - */ -class ResourceClassResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testGetResourceClassWithIntendedClassName() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $dummy = new Dummy(); - $dummy->setName('Smail'); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass($dummy, Dummy::class)); - } - - public function testGetResourceClassWithNonResourceClassName() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Specified class "ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar" is not a resource class.'); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $dummy = new Dummy(); - $dummy->setName('Smail'); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $resourceClassResolver->getResourceClass($dummy, DummyCar::class, true); - } - - public function testGetResourceClassWithNoClassName() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $dummy = new Dummy(); - $dummy->setName('Smail'); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass($dummy)); - } - - public function testGetResourceClassWithTraversableAsValue() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $dummy = new Dummy(); - $dummy->setName('JLM'); - - $dummies = new \ArrayIterator([$dummy]); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass($dummies, Dummy::class)); - } - - public function testGetResourceClassWithTraversable() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([\ArrayObject::class])); - - $dummy = new \ArrayObject(); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(\ArrayObject::class, $resourceClassResolver->getResourceClass($dummy)); - } - - public function testGetResourceClassWithPaginatorInterfaceAsValue() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $paginatorProphecy = $this->prophesize(PaginatorInterface::class); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass($paginatorProphecy->reveal(), Dummy::class)); - } - - public function testGetResourceClassWithWrongClassName() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No resource class found for object of type "stdClass".'); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $resourceClassResolver->getResourceClass(new \stdClass()); - } - - public function testGetResourceClassWithNoResourceClassName() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Resource type could not be determined. Resource class must be specified.'); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([])); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $resourceClassResolver->getResourceClass(new \ArrayIterator([])); - } - - public function testIsResourceClassWithIntendedClassName() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertTrue($resourceClassResolver->isResourceClass(Dummy::class)); - } - - public function testIsResourceClassWithWrongClassName() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([\ArrayIterator::class])); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertFalse($resourceClassResolver->isResourceClass('')); - } - - public function testGetResourceClassWithNoResourceClassNameAndNoObject() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Resource type could not be determined. Resource class must be specified.'); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $resourceClassResolver->getResourceClass(false); - } - - public function testGetResourceClassWithResourceClassNameAndNoObject() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass(false, Dummy::class)); - } - - public function testGetResourceClassWithChildResource() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([DummyTableInheritance::class, DummyTableInheritanceChild::class])); - - $dummy = new DummyTableInheritanceChild(); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(DummyTableInheritanceChild::class, $resourceClassResolver->getResourceClass($dummy, DummyTableInheritance::class)); - } - - public function testGetResourceClassWithInterfaceResource() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([DummyResourceInterface::class])); - - $dummy = new DummyResourceImplementation(); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(DummyResourceInterface::class, $resourceClassResolver->getResourceClass($dummy, DummyResourceInterface::class, true)); - } -} diff --git a/tests/Core/Bridge/Doctrine/Common/DataPersisterTest.php b/tests/Core/Bridge/Doctrine/Common/DataPersisterTest.php deleted file mode 100644 index 804339a9c9e..00000000000 --- a/tests/Core/Bridge/Doctrine/Common/DataPersisterTest.php +++ /dev/null @@ -1,162 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Common; - -use ApiPlatform\Core\Bridge\Doctrine\Common\DataPersister; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use PHPUnit\Framework\TestCase; -use Prophecy\Prediction\CallPrediction; -use Prophecy\Prediction\NoCallsPrediction; - -/** - * @author Baptiste Meyer - */ -class DataPersisterTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $this->assertInstanceOf(DataPersisterInterface::class, new DataPersister($this->prophesize(ManagerRegistry::class)->reveal())); - } - - public function testSupports() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($this->prophesize(ObjectManager::class)->reveal())->shouldBeCalled(); - - $this->assertTrue((new DataPersister($managerRegistryProphecy->reveal()))->supports(new Dummy())); - } - - public function testDoesNotSupport() - { - $this->assertFalse((new DataPersister($this->prophesize(ManagerRegistry::class)->reveal()))->supports('dummy')); - } - - public function testPersist() - { - $dummy = new Dummy(); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->contains($dummy)->willReturn(false); - $objectManagerProphecy->persist($dummy)->shouldBeCalled(); - $objectManagerProphecy->flush()->shouldBeCalled(); - $objectManagerProphecy->refresh($dummy)->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($objectManagerProphecy->reveal())->shouldBeCalled(); - - $result = (new DataPersister($managerRegistryProphecy->reveal()))->persist($dummy); - $this->assertSame($dummy, $result); - } - - public function testPersistIfEntityAlreadyManaged() - { - $dummy = new Dummy(); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->contains($dummy)->willReturn(true); - $objectManagerProphecy->persist($dummy)->shouldNotBeCalled(); - $objectManagerProphecy->flush()->shouldBeCalled(); - $objectManagerProphecy->refresh($dummy)->shouldBeCalled(); - $objectManagerProphecy->getClassMetadata(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($objectManagerProphecy->reveal())->shouldBeCalled(); - - $result = (new DataPersister($managerRegistryProphecy->reveal()))->persist($dummy); - $this->assertSame($dummy, $result); - } - - public function testPersistWithNullManager() - { - $dummy = new Dummy(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $result = (new DataPersister($managerRegistryProphecy->reveal()))->persist($dummy); - $this->assertSame($dummy, $result); - } - - public function testRemove() - { - $dummy = new Dummy(); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->remove($dummy)->shouldBeCalled(); - $objectManagerProphecy->flush()->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($objectManagerProphecy->reveal())->shouldBeCalled(); - - (new DataPersister($managerRegistryProphecy->reveal()))->remove($dummy); - } - - public function testRemoveWithNullManager() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - (new DataPersister($managerRegistryProphecy->reveal()))->remove(new Dummy()); - } - - public function getTrackingPolicyParameters() - { - return [ - 'deferred explicit ORM' => [ClassMetadataInfo::class, true, true], - 'deferred implicit ORM' => [ClassMetadataInfo::class, false, false], - 'deferred explicit ODM' => [ClassMetadata::class, true, true], - 'deferred implicit ODM' => [ClassMetadata::class, false, false], - ]; - } - - /** - * @dataProvider getTrackingPolicyParameters - * - * @param mixed $metadataClass - * @param mixed $deferredExplicit - * @param mixed $persisted - */ - public function testTrackingPolicy($metadataClass, $deferredExplicit, $persisted) - { - $dummy = new Dummy(); - - $classMetadataInfo = $this->prophesize($metadataClass); - if (method_exists($metadataClass, 'isChangeTrackingDeferredExplicit')) { - $classMetadataInfo->isChangeTrackingDeferredExplicit()->willReturn($deferredExplicit)->shouldBeCalled(); - } else { - $persisted = false; - } - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->getClassMetadata(Dummy::class)->willReturn($classMetadataInfo)->shouldBeCalled(); - $objectManagerProphecy->contains($dummy)->willReturn(true); - $objectManagerProphecy->persist($dummy)->should($persisted ? new CallPrediction() : new NoCallsPrediction()); - $objectManagerProphecy->flush()->shouldBeCalled(); - $objectManagerProphecy->refresh($dummy)->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($objectManagerProphecy)->shouldBeCalled(); - - $result = (new DataPersister($managerRegistryProphecy->reveal()))->persist($dummy); - $this->assertSame($dummy, $result); - } -} diff --git a/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php b/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php deleted file mode 100644 index 5c1f3a07a6b..00000000000 --- a/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php +++ /dev/null @@ -1,245 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Common\Util; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\PropertyNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy as DummyDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use Doctrine\DBAL\Types\Type as DBALType; -use Doctrine\DBAL\Types\Types; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MongoDbOdmClassMetadata; -use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\Mapping\ClassMetadata; -use Doctrine\Persistence\ObjectManager; -use PHPUnit\Framework\TestCase; -use Ramsey\Uuid\Doctrine\UuidType; - -/** - * @group legacy - */ -class IdentifierManagerTraitTest extends TestCase -{ - use ProphecyTrait; - - private function getIdentifierManagerTraitImpl(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - return new class($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory) { - use IdentifierManagerTrait { - IdentifierManagerTrait::normalizeIdentifiers as public; - } - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - }; - } - - /** - * @group legacy - */ - public function testSingleIdentifier() - { - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $objectManager = $this->getEntityManager(Dummy::class, [ - 'id' => [ - 'type' => Types::INTEGER, - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $this->assertEquals($identifierManager->normalizeIdentifiers(1, $objectManager, Dummy::class), ['id' => 1]); - } - - /** - * @group legacy - * @group mongodb - */ - public function testSingleDocumentIdentifier() - { - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(DummyDocument::class, [ - 'id', - ]); - $objectManager = $this->getDocumentManager(DummyDocument::class, [ - 'id' => [ - 'type' => MongoDbType::INTEGER, - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $this->assertEquals($identifierManager->normalizeIdentifiers(1, $objectManager, DummyDocument::class), ['id' => 1]); - } - - /** - * @group legacy - */ - public function testCompositeIdentifier() - { - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $objectManager = $this->getEntityManager(Dummy::class, [ - 'ida' => [ - 'type' => Types::INTEGER, - ], - 'idb' => [ - 'type' => Types::INTEGER, - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $this->assertEquals($identifierManager->normalizeIdentifiers('ida=1;idb=2', $objectManager, Dummy::class), ['ida' => 1, 'idb' => 2]); - } - - /** - * @group legacy - */ - public function testInvalidIdentifier() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Invalid identifier "idbad=1;idb=2", "ida" was not found for resource "dummy".'); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $objectManager = $this->getEntityManager(Dummy::class, [ - 'ida' => [ - 'type' => Types::INTEGER, - ], - 'idb' => [ - 'type' => Types::INTEGER, - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $identifierManager->normalizeIdentifiers('idbad=1;idb=2', $objectManager, Dummy::class); - } - - /** - * Gets mocked metadata factories. - */ - private function getMetadataFactories(string $resourceClass, array $identifiers): array - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - $resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('dummy')); - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()]; - } - - /** - * Gets a mocked entity manager. - */ - private function getEntityManager(string $resourceClass, array $identifierFields): ObjectManager - { - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(array_keys($identifierFields)); - - foreach ($identifierFields as $name => $field) { - $classMetadataProphecy->getTypeOfField($name)->willReturn($field['type']); - } - - $platformProphecy = $this->prophesize(AbstractPlatform::class); - - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy->getDatabasePlatform()->willReturn($platformProphecy); - - $managerProphecy = $this->prophesize(EntityManagerInterface::class); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - $managerProphecy->getConnection()->willReturn($connectionProphecy); - - return $managerProphecy->reveal(); - } - - /** - * Gets a mocked document manager. - */ - private function getDocumentManager(string $resourceClass, array $identifierFields): ObjectManager - { - $classMetadataProphecy = $this->prophesize(MongoDbOdmClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(array_keys($identifierFields)); - - foreach ($identifierFields as $name => $field) { - $classMetadataProphecy->getTypeOfField($name)->willReturn($field['type']); - } - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - - return $managerProphecy->reveal(); - } - - /** - * @group legacy - */ - public function testInvalidIdentifierConversion() - { - DBALType::addType('ramsey-uuid', UuidType::class); - - $this->expectException(InvalidIdentifierException::class); - $this->expectExceptionMessage('Invalid value "ida" provided for an identifier for resource "dummy".'); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - ]); - $objectManager = $this->getEntityManager(Dummy::class, [ - 'ida' => [ - 'type' => 'ramsey-uuid', - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $identifierManager->normalizeIdentifiers('notanuuid', $objectManager, Dummy::class); - } -} diff --git a/tests/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php b/tests/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php deleted file mode 100644 index f85de944385..00000000000 --- a/tests/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php +++ /dev/null @@ -1,166 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\CollectionDataProvider; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Operations; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Iterator\Iterator; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; - -/** - * @author Alan Poulain - * - * @group mongodb - */ -class CollectionDataProviderTest extends TestCase -{ - use ProphecyTrait; - - private $managerRegistryProphecy; - private $resourceMetadataFactoryProphecy; - - /** - * {@inheritdoc} - */ - protected function setUp(): void - { - parent::setUp(); - - $this->managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - } - - public function testGetCollection() - { - // No solution for this see https://github.com/doctrine/mongodb-odm/pull/2395 - if (method_exists(Builder::class, 'getAggregation')) { - $this->markTestSkipped('Can not mock Aggregation.'); - } - - $iterator = $this->prophesize(Iterator::class)->reveal(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute([])->willReturn($iterator)->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['foo' => new GetCollection()]))])); - - $extensionProphecy = $this->prophesize(AggregationCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, Dummy::class, 'foo', [])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals($iterator, $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testGetCollectionWithExecuteOptions() - { - if (method_exists(Builder::class, 'getAggregation')) { - $this->markTestSkipped('Can not mock Aggregation.'); - } - - $iterator = $this->prophesize(Iterator::class)->reveal(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute(['allowDiskUse' => true])->willReturn($iterator)->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['foo' => (new GetCollection())->withExtraProperties(['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]])]))])); - - $extensionProphecy = $this->prophesize(AggregationCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, Dummy::class, 'foo', [])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals($iterator, $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testAggregationResultExtension() - { - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(AggregationResultCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, Dummy::class, 'foo', [])->shouldBeCalled(); - $extensionProphecy->supportsResult(Dummy::class, 'foo', [])->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($aggregationBuilder, Dummy::class, 'foo', [])->willReturn([])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testCannotCreateAggregationBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository for "ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy" must be an instance of "Doctrine\ODM\MongoDB\Repository\DocumentRepository".'); - - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal()); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testUnsupportedClass() - { - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(AggregationResultCollectionExtensionInterface::class); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertFalse($dataProvider->supports(Dummy::class, 'foo')); - } -} diff --git a/tests/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php b/tests/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php deleted file mode 100644 index 37c883f255f..00000000000 --- a/tests/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php +++ /dev/null @@ -1,307 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationItemExtensionInterface; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationResultItemExtensionInterface; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\ItemDataProvider; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Exception\RuntimeException; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\Aggregation\Stage\MatchStage as AggregationMatch; -use Doctrine\ODM\MongoDB\Iterator\Iterator; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; - -/** - * @group mongodb - * - * @author Alan Poulain - */ -class ItemDataProviderTest extends TestCase -{ - use ProphecyTrait; - - private $resourceMetadataFactoryProphecy; - - /** - * {@inheritdoc} - */ - protected function setUp(): void - { - parent::setUp(); - - $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - } - - public function testGetItemSingleIdentifier() - { - $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $matchProphecy = $this->prophesize(AggregationMatch::class); - $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->equals(1)->shouldBeCalled(); - - $iterator = $this->prophesize(Iterator::class); - $result = new \stdClass(); - $iterator->current()->willReturn($result)->shouldBeCalled(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled(); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute([])->willReturn($iterator->reveal())->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testGetItemWithExecuteOptions() - { - $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $matchProphecy = $this->prophesize(AggregationMatch::class); - $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->equals(1)->shouldBeCalled(); - - $iterator = $this->prophesize(Iterator::class); - $result = new \stdClass(); - $iterator->current()->willReturn($result)->shouldBeCalled(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled(); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute(['allowDiskUse' => true])->willReturn($iterator->reveal())->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata( - 'Dummy', - null, - null, - ['foo' => ['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]]] - )); - - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testGetItemDoubleIdentifier() - { - $matchProphecy = $this->prophesize(AggregationMatch::class); - $matchProphecy->field('ida')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->field('idb')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->equals(1)->shouldBeCalled(); - $matchProphecy->equals(2)->shouldBeCalled(); - - $iterator = $this->prophesize(Iterator::class); - $result = new \stdClass(); - $iterator->current()->willReturn($result)->shouldBeCalled(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled(); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute([])->willReturn($iterator->reveal())->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)); - } - - /** - * @group legacy - */ - public function testGetItemWrongCompositeIdentifier() - { - $this->expectException(PropertyNotFoundException::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $this->prophesize(Builder::class)->reveal(), [ - 'ida' => [ - 'type' => MongoDbType::INTEGER, - ], - 'idb' => [ - 'type' => MongoDbType::INTEGER, - ], - ]); - - $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getItem(Dummy::class, 'ida=1;', 'foo'); - } - - public function testAggregationResultExtension() - { - $matchProphecy = $this->prophesize(AggregationMatch::class); - $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->equals(1)->shouldBeCalled(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(AggregationResultItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $extensionProphecy->supportsResult(Dummy::class, 'foo', $context)->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($aggregationBuilder, Dummy::class, 'foo', $context)->willReturn([])->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $this->assertEquals([], $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testUnsupportedClass() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - $this->assertFalse($dataProvider->supports(Dummy::class, 'foo')); - } - - public function testCannotCreateAggregationBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository for "ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy" must be an instance of "Doctrine\ODM\MongoDB\Repository\DocumentRepository".'); - - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal()); - - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - - (new ItemDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]))->getItem(Dummy::class, 'foo', null, [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]); - } - - /** - * Gets mocked metadata factories. - */ - private function getMetadataFactories(string $resourceClass, array $identifiers): array - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()]; - } - - /** - * Gets a mocked manager registry. - */ - private function getManagerRegistry(string $resourceClass, Builder $aggregationBuilder, array $identifierFields = []): ManagerRegistry - { - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(array_keys($identifierFields)); - - foreach ($identifierFields as $name => $field) { - $classMetadataProphecy->getTypeOfField($name)->willReturn($field['type']); - } - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository($resourceClass)->willReturn($repositoryProphecy->reveal()); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal()); - - return $managerRegistryProphecy->reveal(); - } -} diff --git a/tests/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php b/tests/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php deleted file mode 100644 index 54def94b3d0..00000000000 --- a/tests/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php +++ /dev/null @@ -1,541 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationResultCollectionExtensionInterface; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\SubresourceDataProvider; -use ApiPlatform\Core\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Core\Exception\RuntimeException; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\Aggregation\Stage\Lookup; -use Doctrine\ODM\MongoDB\Aggregation\Stage\MatchStage as AggregationMatch; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Iterator\Iterator; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @group mongodb - * - * @author Alan Poulain - */ -class SubresourceDataProviderTest extends TestCase -{ - use ProphecyTrait; - - private $resourceMetadataFactoryProphecy; - - /** - * {@inheritdoc} - */ - protected function setUp(): void - { - parent::setUp(); - - $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - } - - private function getMetadataProphecies(array $resourceClassesIdentifiers) - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - foreach ($resourceClassesIdentifiers as $resourceClass => $identifiers) { - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - } - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()]; - } - - private function getManagerRegistryProphecy(Builder $aggregationBuilder, array $identifiers, string $resourceClass) - { - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository($resourceClass)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass($resourceClass)->willReturn($managerProphecy->reveal()); - - return $managerRegistryProphecy->reveal(); - } - - public function testNotASubresource() - { - $this->expectException(ResourceClassNotSupportedException::class); - $this->expectExceptionMessage('The given resource class is not a subresource.'); - - $identifiers = ['id']; - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - $aggregationBuilder = $this->prophesize(Builder::class)->reveal(); - $managerRegistry = $this->getManagerRegistryProphecy($aggregationBuilder, $identifiers, Dummy::class); - - $dataProvider = new SubresourceDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, []); - - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testGetSubresource() - { - $aggregationBuilder = $this->prophesize(Builder::class); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $dummyAggregationBuilder = $this->prophesize(Builder::class); - $dummyLookup = $this->prophesize(Lookup::class); - $dummyLookup->alias('relatedDummies')->shouldBeCalled(); - $dummyAggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($dummyLookup->reveal()); - - $dummyMatch = $this->prophesize(AggregationMatch::class); - $dummyMatch->equals(1)->shouldBeCalled(); - $dummyMatch->field('id')->shouldBeCalled()->willReturn($dummyMatch); - $dummyAggregationBuilder->match()->shouldBeCalled()->willReturn($dummyMatch->reveal()); - - $dummyIterator = $this->prophesize(Iterator::class); - $dummyIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'relatedDummies' => [['_id' => 2]]]]); - $dummyAggregationBuilder->execute([])->shouldBeCalled()->willReturn($dummyIterator->reveal()); - - $managerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($dummyAggregationBuilder->reveal()); - - $match = $this->prophesize(AggregationMatch::class); - $match->in([2])->shouldBeCalled(); - $match->field('_id')->shouldBeCalled()->willReturn($match); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match); - - $iterator = $this->prophesize(Iterator::class); - $iterator->toArray()->shouldBeCalled()->willReturn([]); - $aggregationBuilder->execute([])->shouldBeCalled()->willReturn($iterator->reveal()); - $aggregationBuilder->hydrate(RelatedDummy::class)->shouldBeCalled()->willReturn($aggregationBuilder); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => ['id']]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testGetSubSubresourceItem() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - - // First manager (Dummy) - $dummyAggregationBuilder = $this->prophesize(Builder::class); - $dummyLookup = $this->prophesize(Lookup::class); - $dummyLookup->alias('relatedDummies')->shouldBeCalled(); - $dummyAggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($dummyLookup->reveal()); - - $dummyMatch = $this->prophesize(AggregationMatch::class); - $dummyMatch->equals(1)->shouldBeCalled(); - $dummyMatch->field('id')->shouldBeCalled()->willReturn($dummyMatch); - $dummyAggregationBuilder->match()->shouldBeCalled()->willReturn($dummyMatch->reveal()); - - $dummyIterator = $this->prophesize(Iterator::class); - $dummyIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'relatedDummies' => [['_id' => 2]]]]); - $dummyAggregationBuilder->execute([])->shouldBeCalled()->willReturn($dummyIterator->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - - $dummyManagerProphecy = $this->prophesize(DocumentManager::class); - $dummyManagerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($dummyAggregationBuilder->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $rAggregationBuilder = $this->prophesize(Builder::class); - $rLookup = $this->prophesize(Lookup::class); - $rLookup->alias('thirdLevel')->shouldBeCalled(); - $rAggregationBuilder->lookup('thirdLevel')->shouldBeCalled()->willReturn($rLookup->reveal()); - - $rMatch = $this->prophesize(AggregationMatch::class); - $rMatch->equals(1)->shouldBeCalled(); - $rMatch->field('id')->shouldBeCalled()->willReturn($rMatch); - $previousRMatch = $this->prophesize(AggregationMatch::class); - $previousRMatch->in([2])->shouldBeCalled(); - $previousRMatch->field('_id')->shouldBeCalled()->willReturn($previousRMatch); - $rAggregationBuilder->match()->shouldBeCalled()->willReturn($rMatch->reveal(), $previousRMatch->reveal()); - - $rIterator = $this->prophesize(Iterator::class); - $rIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'thirdLevel' => [['_id' => 3]]]]); - $rAggregationBuilder->execute([])->shouldBeCalled()->willReturn($rIterator->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('thirdLevel')->shouldBeCalled()->willReturn(true); - - $rDummyManagerProphecy = $this->prophesize(DocumentManager::class); - $rDummyManagerProphecy->createAggregationBuilder(RelatedDummy::class)->shouldBeCalled()->willReturn($rAggregationBuilder->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - // Origin manager (ThirdLevel) - $aggregationBuilder = $this->prophesize(Builder::class); - - $match = $this->prophesize(AggregationMatch::class); - $match->in([3])->shouldBeCalled(); - $match->field('_id')->shouldBeCalled()->willReturn($match); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match); - - $iterator = $this->prophesize(Iterator::class); - $iterator->current()->shouldBeCalled()->willReturn($result); - $aggregationBuilder->execute([])->shouldBeCalled()->willReturn($iterator->reveal()); - $aggregationBuilder->hydrate(ThirdLevel::class)->shouldBeCalled()->willReturn($aggregationBuilder); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(ThirdLevel::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(ThirdLevel::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(ThirdLevel::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'thirdLevel', 'identifiers' => ['id' => [Dummy::class, 'id'], 'relatedDummies' => [RelatedDummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 1]], $context)); - } - - public function testGetSubSubresourceItemWithExecuteOptions() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - - // First manager (Dummy) - $dummyAggregationBuilder = $this->prophesize(Builder::class); - $dummyLookup = $this->prophesize(Lookup::class); - $dummyLookup->alias('relatedDummies')->shouldBeCalled(); - $dummyAggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($dummyLookup->reveal()); - - $dummyMatch = $this->prophesize(AggregationMatch::class); - $dummyMatch->equals(1)->shouldBeCalled(); - $dummyMatch->field('id')->shouldBeCalled()->willReturn($dummyMatch); - $dummyAggregationBuilder->match()->shouldBeCalled()->willReturn($dummyMatch->reveal()); - - $dummyIterator = $this->prophesize(Iterator::class); - $dummyIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'relatedDummies' => [['_id' => 2]]]]); - $dummyAggregationBuilder->execute(['allowDiskUse' => true])->shouldBeCalled()->willReturn($dummyIterator->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - - $dummyManagerProphecy = $this->prophesize(DocumentManager::class); - $dummyManagerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($dummyAggregationBuilder->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $rAggregationBuilder = $this->prophesize(Builder::class); - $rLookup = $this->prophesize(Lookup::class); - $rLookup->alias('thirdLevel')->shouldBeCalled(); - $rAggregationBuilder->lookup('thirdLevel')->shouldBeCalled()->willReturn($rLookup->reveal()); - - $rMatch = $this->prophesize(AggregationMatch::class); - $rMatch->equals(1)->shouldBeCalled(); - $rMatch->field('id')->shouldBeCalled()->willReturn($rMatch); - $previousRMatch = $this->prophesize(AggregationMatch::class); - $previousRMatch->in([2])->shouldBeCalled(); - $previousRMatch->field('_id')->shouldBeCalled()->willReturn($previousRMatch); - $rAggregationBuilder->match()->shouldBeCalled()->willReturn($rMatch->reveal(), $previousRMatch->reveal()); - - $rIterator = $this->prophesize(Iterator::class); - $rIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'thirdLevel' => [['_id' => 3]]]]); - $rAggregationBuilder->execute(['allowDiskUse' => true])->shouldBeCalled()->willReturn($rIterator->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('thirdLevel')->shouldBeCalled()->willReturn(true); - - $rDummyManagerProphecy = $this->prophesize(DocumentManager::class); - $rDummyManagerProphecy->createAggregationBuilder(RelatedDummy::class)->shouldBeCalled()->willReturn($rAggregationBuilder->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - // Origin manager (ThirdLevel) - $aggregationBuilder = $this->prophesize(Builder::class); - - $match = $this->prophesize(AggregationMatch::class); - $match->in([3])->shouldBeCalled(); - $match->field('_id')->shouldBeCalled()->willReturn($match); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match); - - $iterator = $this->prophesize(Iterator::class); - $iterator->current()->shouldBeCalled()->willReturn($result); - $aggregationBuilder->execute(['allowDiskUse' => true])->shouldBeCalled()->willReturn($iterator->reveal()); - $aggregationBuilder->hydrate(ThirdLevel::class)->shouldBeCalled()->willReturn($aggregationBuilder); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(ThirdLevel::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(ThirdLevel::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(ThirdLevel::class)->willReturn(new ResourceMetadata( - 'ThirdLevel', - null, - null, - null, - null, - null, - ['third_level_operation_name' => ['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]]] - )); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'thirdLevel', 'identifiers' => ['id' => [Dummy::class, 'id'], 'relatedDummies' => [RelatedDummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 1]], $context, 'third_level_operation_name')); - } - - public function testGetSubresourceOneToOneOwningRelation() - { - // RelatedOwningDummy OneToOne Dummy - $identifiers = ['id']; - $aggregationBuilder = $this->prophesize(Builder::class); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('ownedDummy')->willReturn(true)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $lookup = $this->prophesize(Lookup::class); - $lookup->alias('ownedDummy')->shouldBeCalled(); - $aggregationBuilder->lookup('ownedDummy')->shouldBeCalled()->willReturn($lookup->reveal()); - $managerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $match = $this->prophesize(AggregationMatch::class); - $match->equals(1)->shouldBeCalled(); - $match->field('id')->shouldBeCalled()->willReturn($match); - $previousMatch = $this->prophesize(AggregationMatch::class); - $previousMatch->in([3])->shouldBeCalled(); - $previousMatch->field('_id')->shouldBeCalled()->willReturn($previousMatch); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match->reveal(), $previousMatch->reveal()); - - $iterator = $this->prophesize(Iterator::class); - $iterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'ownedDummy' => [['_id' => 3]]]]); - $result = new \stdClass(); - $iterator->current()->shouldBeCalled()->willReturn($result); - $aggregationBuilder->execute([])->shouldBeCalled()->willReturn($iterator->reveal()); - $aggregationBuilder->hydrate(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($aggregationBuilder); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(RelatedOwningDummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'ownedDummy', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(RelatedOwningDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testAggregationResultExtension() - { - $identifiers = ['id']; - $aggregationBuilder = $this->prophesize(Builder::class); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $lookup = $this->prophesize(Lookup::class); - $lookup->alias('relatedDummies')->shouldBeCalled(); - $aggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($lookup->reveal()); - $managerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $match = $this->prophesize(AggregationMatch::class); - $match->equals(1)->shouldBeCalled(); - $match->field('id')->shouldBeCalled()->willReturn($match); - $previousMatch = $this->prophesize(AggregationMatch::class); - $previousMatch->in([3])->shouldBeCalled(); - $previousMatch->field('_id')->shouldBeCalled()->willReturn($previousMatch); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match->reveal(), $previousMatch->reveal()); - - $iterator = $this->prophesize(Iterator::class); - $iterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'relatedDummies' => [['_id' => 3]]]]); - $aggregationBuilder->execute([])->shouldBeCalled()->willReturn($iterator->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $extensionProphecy = $this->prophesize(AggregationResultCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, RelatedDummy::class, null, Argument::type('array'))->shouldBeCalled(); - $extensionProphecy->supportsResult(RelatedDummy::class, null, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($aggregationBuilder, RelatedDummy::class, null, Argument::type('array'))->willReturn([])->shouldBeCalled(); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testCannotCreateQueryBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository for "ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy" must be an instance of "Doctrine\ODM\MongoDB\Repository\DocumentRepository".'); - - $identifiers = ['id']; - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testThrowResourceClassNotSupportedException() - { - $this->expectException(ResourceClassNotSupportedException::class); - - $identifiers = ['id']; - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testGetSubresourceCollectionItem() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - - $rAggregationBuilder = $this->prophesize(Builder::class); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('id')->shouldBeCalled()->willReturn(false); - $rClassMetadataProphecy->isIdentifier('id')->shouldBeCalled()->willReturn(true); - - $rDummyManagerProphecy = $this->prophesize(DocumentManager::class); - $rDummyManagerProphecy->createAggregationBuilder(RelatedDummy::class)->shouldBeCalled()->willReturn($rAggregationBuilder->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - - $rIterator = $this->prophesize(Iterator::class); - $rIterator->current()->shouldBeCalled()->willReturn($result); - $rAggregationBuilder->execute([])->shouldBeCalled()->willReturn($rIterator->reveal()); - $rAggregationBuilder->hydrate(RelatedDummy::class)->shouldBeCalled()->willReturn($rAggregationBuilder); - - $aggregationBuilder = $this->prophesize(Builder::class); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $rDummyManagerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'id', 'identifiers' => ['id' => [Dummy::class, 'id', true], [RelatedDummy::class, 'relatedDummies', true]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 2]], $context)); - } -} diff --git a/tests/Core/Bridge/Doctrine/Orm/CollectionDataProviderTest.php b/tests/Core/Bridge/Doctrine/Orm/CollectionDataProviderTest.php deleted file mode 100644 index a814cb70520..00000000000 --- a/tests/Core/Bridge/Doctrine/Orm/CollectionDataProviderTest.php +++ /dev/null @@ -1,114 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Orm\CollectionDataProvider; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\ORM\AbstractQuery; -use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Kévin Dunglas - */ -class CollectionDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetCollection() - { - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getResult()->willReturn([])->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilderProphecy->getQuery()->willReturn($queryProphecy->reveal())->shouldBeCalled(); - $queryBuilder = $queryBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(QueryCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, 'foo', [])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testQueryResultExtension() - { - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilder = $queryBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(QueryResultCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, 'foo', [])->shouldBeCalled(); - $extensionProphecy->supportsResult(Dummy::class, 'foo', [])->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($queryBuilder, Dummy::class, 'foo', [])->willReturn([])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testCannotCreateQueryBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository class must have a "createQueryBuilder" method.'); - - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($managerRegistryProphecy->reveal()); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testUnsupportedClass() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(QueryResultCollectionExtensionInterface::class); - - $dataProvider = new CollectionDataProvider($managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertFalse($dataProvider->supports(Dummy::class, 'foo')); - } -} diff --git a/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php b/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php deleted file mode 100644 index f3a47a8feea..00000000000 --- a/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php +++ /dev/null @@ -1,305 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Orm\ItemDataProvider; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Exception\PropertyNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use Doctrine\DBAL\Types\Types; -use Doctrine\ORM\AbstractQuery; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query\Expr; -use Doctrine\ORM\Query\Expr\Comparison; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class ItemDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetItemSingleIdentifier() - { - $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->willReturn([])->shouldBeCalled(); - - $comparisonProphecy = $this->prophesize(Comparison::class); - $comparison = $comparisonProphecy->reveal(); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->eq('o.id', ':id_p1')->willReturn($comparisonProphecy)->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilderProphecy->getQuery()->willReturn($queryProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->expr()->willReturn($exprProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->andWhere($comparison)->shouldBeCalled(); - $queryBuilderProphecy->getRootAliases()->shouldBeCalled()->willReturn(['o']); - $queryBuilderProphecy->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled(); - - $queryBuilder = $queryBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, [ - 'id' => [ - 'type' => Types::INTEGER, - ], - ], $queryBuilder); - - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - - $this->assertEquals([], $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testGetItemDoubleIdentifier() - { - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->willReturn([])->shouldBeCalled(); - - $comparisonProphecy = $this->prophesize(Comparison::class); - $comparison = $comparisonProphecy->reveal(); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->eq('o.ida', ':ida_p1')->willReturn($comparisonProphecy)->shouldBeCalled(); - $exprProphecy->eq('o.idb', ':idb_p2')->willReturn($comparisonProphecy)->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilderProphecy->getQuery()->willReturn($queryProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->expr()->willReturn($exprProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->andWhere($comparison)->shouldBeCalled(); - $queryBuilderProphecy->getRootAliases()->shouldBeCalled()->willReturn(['o']); - - $queryBuilderProphecy->setParameter('ida_p1', 1, Types::INTEGER)->shouldBeCalled(); - $queryBuilderProphecy->setParameter('idb_p2', 2, Types::INTEGER)->shouldBeCalled(); - - $queryBuilder = $queryBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, [ - 'ida' => [ - 'type' => Types::INTEGER, - ], - 'idb' => [ - 'type' => Types::INTEGER, - ], - ], $queryBuilder); - - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - - $this->assertEquals([], $dataProvider->getItem(Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)); - } - - /** - * @group legacy - */ - public function testGetItemWrongCompositeIdentifier() - { - $this->expectException(PropertyNotFoundException::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, [ - 'ida' => [ - 'type' => Types::INTEGER, - ], - 'idb' => [ - 'type' => Types::INTEGER, - ], - ], $this->prophesize(QueryBuilder::class)->reveal()); - - $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [], $resourceMetadataFactory); - $dataProvider->getItem(Dummy::class, 'ida=1;', 'foo'); - } - - public function testQueryResultExtension() - { - $comparisonProphecy = $this->prophesize(Comparison::class); - $comparison = $comparisonProphecy->reveal(); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->eq('o.id', ':id_p1')->willReturn($comparisonProphecy)->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilderProphecy->expr()->willReturn($exprProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->andWhere($comparison)->shouldBeCalled(); - $queryBuilderProphecy->getRootAliases()->shouldBeCalled()->willReturn(['o']); - $queryBuilderProphecy->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled(); - - $queryBuilder = $queryBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, [ - 'id' => [ - 'type' => Types::INTEGER, - ], - ], $queryBuilder); - - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(QueryResultItemExtensionInterface::class); - $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $extensionProphecy->supportsResult(Dummy::class, 'foo', $context)->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($queryBuilder, Dummy::class, 'foo', $context)->willReturn([])->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - - $this->assertEquals([], $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testUnsupportedClass() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - $this->assertFalse($dataProvider->supports(Dummy::class, 'foo')); - } - - public function testCannotCreateQueryBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository class must have a "createQueryBuilder" method.'); - - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn([ - 'id', - ]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER); - - $platformProphecy = $this->prophesize(AbstractPlatform::class); - - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy->getDatabasePlatform()->willReturn($platformProphecy); - - $managerProphecy = $this->prophesize(EntityManagerInterface::class); - $managerProphecy->getClassMetadata(Dummy::class)->willReturn($classMetadataProphecy->reveal()); - $managerProphecy->getConnection()->willReturn($connectionProphecy); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal()); - - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - - $itemDataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - $itemDataProvider->getItem(Dummy::class, ['id' => 1234], null, [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]); - } - - /** - * Gets mocked metadata factories. - */ - private function getMetadataFactories(string $resourceClass, array $identifiers): array - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - $resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('dummy')); - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()]; - } - - /** - * Gets a mocked manager registry. - */ - private function getManagerRegistry(string $resourceClass, array $identifierFields, QueryBuilder $queryBuilder): ManagerRegistry - { - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(array_keys($identifierFields)); - - foreach ($identifierFields as $name => $field) { - $classMetadataProphecy->getTypeOfField($name)->willReturn($field['type']); - } - - $platformProphecy = $this->prophesize(AbstractPlatform::class); - - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy->getDatabasePlatform()->willReturn($platformProphecy); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder); - - $managerProphecy = $this->prophesize(EntityManagerInterface::class); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - $managerProphecy->getConnection()->willReturn($connectionProphecy); - $managerProphecy->getRepository($resourceClass)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal()); - - return $managerRegistryProphecy->reveal(); - } -} diff --git a/tests/Core/Bridge/Doctrine/Orm/SubresourceDataProviderTest.php b/tests/Core/Bridge/Doctrine/Orm/SubresourceDataProviderTest.php deleted file mode 100644 index 32b412ee011..00000000000 --- a/tests/Core/Bridge/Doctrine/Orm/SubresourceDataProviderTest.php +++ /dev/null @@ -1,615 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Orm\SubresourceDataProvider; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use Doctrine\DBAL\Types\Types; -use Doctrine\ORM\AbstractQuery; -use Doctrine\ORM\EntityManager; -use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query\Expr; -use Doctrine\ORM\Query\Expr\Func; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Kévin Dunglas - */ -class SubresourceDataProviderTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - private function assertIdentifierManagerMethodCalls($managerProphecy) - { - $platformProphecy = $this->prophesize(AbstractPlatform::class); - - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy->getDatabasePlatform()->willReturn($platformProphecy); - - $managerProphecy->getConnection()->willReturn($connectionProphecy); - } - - private function getMetadataProphecies(array $resourceClassesIdentifiers) - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - foreach ($resourceClassesIdentifiers as $resourceClass => $identifiers) { - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - } - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()]; - } - - private function getManagerRegistryProphecy(QueryBuilder $queryBuilder, array $identifiers, string $resourceClass) - { - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn($identifiers); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - $managerProphecy->getRepository($resourceClass)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass($resourceClass)->willReturn($managerProphecy->reveal()); - - return $managerRegistryProphecy->reveal(); - } - - public function testNotASubresource() - { - $this->expectException(ResourceClassNotSupportedException::class); - $this->expectExceptionMessage('The given resource class is not a subresource.'); - - $identifiers = ['id']; - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - $queryBuilder = $this->prophesize(QueryBuilder::class)->reveal(); - $managerRegistry = $this->getManagerRegistryProphecy($queryBuilder, $identifiers, Dummy::class); - - $dataProvider = new SubresourceDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, []); - - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testGetSubresource() - { - $dql = 'SELECT relatedDummies_a2 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a1 INNER JOIN id_a1.relatedDummies relatedDummies_a2 WHERE id_a1.id = :id_p1'; - - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getResult()->shouldBeCalled()->willReturn([]); - - $identifiers = ['id']; - $queryBuilder = $this->prophesize(QueryBuilder::class); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(EntityManager::class); - $managerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a2')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a1')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a1.relatedDummies', 'relatedDummies_a2')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a1.id = :id_p1')->shouldBeCalled()->willReturn($qb); - $qb->getDQL()->shouldBeCalled()->willReturn($dql); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->in('o', $dql)->willReturn($func)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($exprProphecy->reveal()); - - $managerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testGetSubSubresourceItem() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - // First manager (Dummy) - $dummyDQL = 'SELECT relatedDummies_a3 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a2 INNER JOIN id_a2.relatedDummies relatedDummies_a3 WHERE id_a2.id = :id_p2'; - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a2')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a2.relatedDummies', 'relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a2.id = :id_p2')->shouldBeCalled()->willReturn($qb); - - $dummyFunc = new Func('in', ['any']); - - $dummyExpProphecy = $this->prophesize(Expr::class); - $dummyExpProphecy->in('relatedDummies_a1', $dummyDQL)->willReturn($dummyFunc)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($dummyExpProphecy->reveal()); - - $qb->getDQL()->shouldBeCalled()->willReturn($dummyDQL); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $dummyManagerProphecy = $this->prophesize(EntityManager::class); - $dummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($dummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $relatedDQL = 'SELECT IDENTITY(relatedDummies_a1.thirdLevel) FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy relatedDummies_a1 WHERE relatedDummies_a1.id = :id_p1 AND relatedDummies_a1 IN(SELECT relatedDummies_a3 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a2 INNER JOIN id_a2.relatedDummies relatedDummies_a3 WHERE id_a2.id = :id_p2)'; - - $rqb = $this->prophesize(QueryBuilder::class); - $rqb->select('IDENTITY(relatedDummies_a1.thirdLevel)')->shouldBeCalled()->willReturn($rqb); - $rqb->from(RelatedDummy::class, 'relatedDummies_a1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere('relatedDummies_a1.id = :id_p1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere($dummyFunc)->shouldBeCalled()->willReturn($rqb); - $rqb->getDQL()->shouldBeCalled()->willReturn($relatedDQL); - - $relatedExpProphecy = $this->prophesize(Expr::class); - $relatedExpProphecy->in('o', $relatedDQL)->willReturn($func)->shouldBeCalled(); - - $rqb->expr()->shouldBeCalled()->willReturn($relatedExpProphecy->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('thirdLevel')->shouldBeCalled()->willReturn(true); - $rClassMetadataProphecy->getAssociationMapping('thirdLevel')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_ONE]); - $rClassMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $rDummyManagerProphecy = $this->prophesize(EntityManager::class); - $rDummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($rqb->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($rDummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - // Origin manager (ThirdLevel) - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->shouldBeCalled()->willReturn($result); - - $queryBuilder = $this->prophesize(QueryBuilder::class); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $queryBuilder->setParameter('id_p2', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(ThirdLevel::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(ThirdLevel::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'thirdLevel', 'identifiers' => ['id' => [Dummy::class, 'id'], 'relatedDummies' => [RelatedDummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 1]], $context)); - } - - public function testGetSubresourceOneToOneOwningRelation() - { - // RelatedOwningDummy OneToOne Dummy - $dql = 'SELECT ownedDummy_a2 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a1 INNER JOIN id_a1.ownedDummy ownedDummy_a2 WHERE id_a1.id = :id_p1'; - - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->shouldBeCalled()->willReturn([]); - - $identifiers = ['id']; - $queryBuilder = $this->prophesize(QueryBuilder::class); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(EntityManager::class); - $managerProphecy->getRepository(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('ownedDummy')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('ownedDummy')->shouldBeCalled()->willReturn(['type' => ClassMetadata::ONE_TO_ONE]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('IDENTITY(id_a1.ownedDummy)')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a1')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a1.id = :id_p1')->shouldBeCalled()->willReturn($qb); - $qb->getDQL()->shouldBeCalled()->willReturn($dql); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->in('o', $dql)->willReturn($func)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($exprProphecy->reveal()); - - $managerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'ownedDummy', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedOwningDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testQueryResultExtension() - { - $dql = 'SELECT relatedDummies_a2 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a1 INNER JOIN id_a1.relatedDummies relatedDummies_a2 WHERE id_a1.id = :id_p1'; - - $identifiers = ['id']; - $queryBuilder = $this->prophesize(QueryBuilder::class); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(EntityManager::class); - $managerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a2')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a1')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a1.relatedDummies', 'relatedDummies_a2')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a1.id = :id_p1')->shouldBeCalled()->willReturn($qb); - $qb->getDQL()->shouldBeCalled()->willReturn($dql); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->in('o', $dql)->willReturn($func)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($exprProphecy->reveal()); - - $managerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $extensionProphecy = $this->prophesize(QueryResultCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), RelatedDummy::class, null, Argument::type('array'))->shouldBeCalled(); - $extensionProphecy->supportsResult(RelatedDummy::class, null, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($queryBuilder, RelatedDummy::class, null, Argument::type('array'))->willReturn([])->shouldBeCalled(); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testCannotCreateQueryBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository class must have a "createQueryBuilder" method.'); - - $identifiers = ['id']; - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testThrowResourceClassNotSupportedException() - { - $this->expectException(ResourceClassNotSupportedException::class); - - $identifiers = ['id']; - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - /** - * @group legacy - */ - public function testGetSubSubresourceItemLegacy() - { - $this->expectDeprecation('Identifiers should match the convention introduced in ADR 0001-resource-identifiers, this behavior will be removed in 3.0.'); - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - // First manager (Dummy) - $dummyDQL = 'SELECT relatedDummies_a3 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a2 INNER JOIN id_a2.relatedDummies relatedDummies_a3 WHERE id_a2.id = :id_p2'; - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a2')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a2.relatedDummies', 'relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a2.id = :id_p2')->shouldBeCalled()->willReturn($qb); - - $dummyFunc = new Func('in', ['any']); - - $dummyExpProphecy = $this->prophesize(Expr::class); - $dummyExpProphecy->in('relatedDummies_a1', $dummyDQL)->willReturn($dummyFunc)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($dummyExpProphecy->reveal()); - - $qb->getDQL()->shouldBeCalled()->willReturn($dummyDQL); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn($identifiers); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->shouldBeCalled()->willReturn(Types::INTEGER); - - $dummyManagerProphecy = $this->prophesize(EntityManager::class); - $dummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($dummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $relatedDQL = 'SELECT IDENTITY(relatedDummies_a1.thirdLevel) FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy relatedDummies_a1 WHERE relatedDummies_a1.id = :id_p1 AND relatedDummies_a1 IN(SELECT relatedDummies_a3 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a2 INNER JOIN id_a2.relatedDummies relatedDummies_a3 WHERE id_a2.id = :id_p2)'; - - $rqb = $this->prophesize(QueryBuilder::class); - $rqb->select('IDENTITY(relatedDummies_a1.thirdLevel)')->shouldBeCalled()->willReturn($rqb); - $rqb->from(RelatedDummy::class, 'relatedDummies_a1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere('relatedDummies_a1.id = :id_p1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere($dummyFunc)->shouldBeCalled()->willReturn($rqb); - $rqb->getDQL()->shouldBeCalled()->willReturn($relatedDQL); - - $relatedExpProphecy = $this->prophesize(Expr::class); - $relatedExpProphecy->in('o', $relatedDQL)->willReturn($func)->shouldBeCalled(); - - $rqb->expr()->shouldBeCalled()->willReturn($relatedExpProphecy->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn($identifiers); - $rClassMetadataProphecy->getTypeOfField('id')->shouldBeCalled()->willReturn(Types::INTEGER); - $rClassMetadataProphecy->hasAssociation('thirdLevel')->shouldBeCalled()->willReturn(true); - $rClassMetadataProphecy->getAssociationMapping('thirdLevel')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_ONE]); - - $rDummyManagerProphecy = $this->prophesize(EntityManager::class); - $rDummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($rqb->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($rDummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - // Origin manager (ThirdLevel) - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->shouldBeCalled()->willReturn($result); - - $queryBuilder = $this->prophesize(QueryBuilder::class); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $queryBuilder->setParameter('id_p2', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(ThirdLevel::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(ThirdLevel::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'thirdLevel', 'identifiers' => [['id', Dummy::class], ['relatedDummies', RelatedDummy::class]], 'collection' => false]; - - $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => 1, 'relatedDummies' => 1], $context)); - } - - public function testGetSubresourceCollectionItem() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - // First manager (Dummy) - $dummyDQL = 'dql'; - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a2')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a2.relatedDummies', 'relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a2.id = :id_p2')->shouldBeCalled()->willReturn($qb); - - $dummyFunc = new Func('in', ['any']); - - $dummyExpProphecy = $this->prophesize(Expr::class); - $dummyExpProphecy->in('relatedDummies_a1', $dummyDQL)->willReturn($dummyFunc)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($dummyExpProphecy->reveal()); - - $qb->getDQL()->shouldBeCalled()->willReturn($dummyDQL); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->shouldBeCalled()->willReturn(Types::INTEGER); - - $dummyManagerProphecy = $this->prophesize(EntityManager::class); - $dummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($dummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $relatedDQL = 'relateddql'; - - $rqb = $this->prophesize(QueryBuilder::class); - $rqb->select('relatedDummies_a1')->shouldBeCalled()->willReturn($rqb); - $rqb->from(RelatedDummy::class, 'relatedDummies_a1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere('relatedDummies_a1.id = :id_p1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere($dummyFunc)->shouldBeCalled()->willReturn($rqb); - $rqb->getDQL()->shouldBeCalled()->willReturn($relatedDQL); - - $relatedExpProphecy = $this->prophesize(Expr::class); - $relatedExpProphecy->in('o', $relatedDQL)->willReturn($func)->shouldBeCalled(); - - $rqb->expr()->shouldBeCalled()->willReturn($relatedExpProphecy->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('id')->shouldBeCalled()->willReturn(false); - $rClassMetadataProphecy->isIdentifier('id')->shouldBeCalled()->willReturn(true); - $rClassMetadataProphecy->getTypeOfField('id')->shouldBeCalled()->willReturn(Types::INTEGER); - - $rDummyManagerProphecy = $this->prophesize(EntityManager::class); - $rDummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($rqb->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($rDummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->shouldBeCalled()->willReturn($result); - - $queryBuilder = $this->prophesize(QueryBuilder::class); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - $queryBuilder->setParameter('id_p1', 2, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $queryBuilder->setParameter('id_p2', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $rDummyManagerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'id', 'identifiers' => ['id' => [Dummy::class, 'id', true], 'relatedDummies' => [RelatedDummy::class, 'id', true]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 2]], $context)); - } -} diff --git a/tests/Core/Bridge/Elasticsearch/Api/IdentifierExtractorTest.php b/tests/Core/Bridge/Elasticsearch/Api/IdentifierExtractorTest.php deleted file mode 100644 index a83edb0c647..00000000000 --- a/tests/Core/Bridge/Elasticsearch/Api/IdentifierExtractorTest.php +++ /dev/null @@ -1,70 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Elasticsearch\Api; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractor; -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeRelation; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -class IdentifierExtractorTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - self::assertInstanceOf( - IdentifierExtractorInterface::class, - new IdentifierExtractor($this->prophesize(IdentifiersExtractorInterface::class)->reveal()) - ); - } - - public function testGetIdentifierFromResourceClass() - { - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Dummy::class)->willReturn(['id'])->shouldBeCalled(); - - $identifierExtractor = new IdentifierExtractor($identifiersExtractorProphecy->reveal()); - - self::assertSame('id', $identifierExtractor->getIdentifierFromResourceClass(Dummy::class)); - } - - public function testGetIdentifierFromResourceClassWithCompositeIdentifiers() - { - $this->expectException(NonUniqueIdentifierException::class); - $this->expectExceptionMessage('Composite identifiers not supported.'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(CompositeRelation::class)->willReturn(['compositeItem', 'compositeLabel'])->shouldBeCalled(); - - $identifierExtractor = new IdentifierExtractor($identifiersExtractorProphecy->reveal()); - $identifierExtractor->getIdentifierFromResourceClass(CompositeRelation::class); - } - - public function testGetIdentifierFromResourceClassWithNoIdentifier() - { - $this->expectException(NonUniqueIdentifierException::class); - $this->expectExceptionMessage('Resource "ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy" has no identifiers.'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Dummy::class)->willReturn([])->shouldBeCalled(); - - $identifierExtractor = new IdentifierExtractor($identifiersExtractorProphecy->reveal()); - $identifierExtractor->getIdentifierFromResourceClass(Dummy::class); - } -} diff --git a/tests/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php b/tests/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php deleted file mode 100644 index f2fc0809db7..00000000000 --- a/tests/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php +++ /dev/null @@ -1,186 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Elasticsearch\DataProvider; - -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\CollectionDataProvider; -use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Paginator; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; -use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; -use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\State\Pagination\Pagination; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeRelation; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarColor; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; -use Elasticsearch\Client; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * @group legacy - * @requires PHP >= 7.4 - */ -class CollectionDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - self::assertInstanceOf( - CollectionDataProviderInterface::class, - new CollectionDataProvider( - $this->prophesize(Client::class)->reveal(), - $this->prophesize(DocumentMetadataFactoryInterface::class)->reveal(), - $this->prophesize(IdentifierExtractorInterface::class)->reveal(), - $this->prophesize(DenormalizerInterface::class)->reveal(), - new Pagination($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal() - ) - ); - } - - public function testSupports() - { - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - $documentMetadataFactoryProphecy->create(Dummy::class)->willThrow(new IndexNotFoundException())->shouldBeCalled(); - $documentMetadataFactoryProphecy->create(CompositeRelation::class)->willReturn(new DocumentMetadata('composite_relation'))->shouldBeCalled(); - - $identifierExtractorProphecy = $this->prophesize(IdentifierExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $identifierExtractorProphecy->getIdentifierFromResourceClass(CompositeRelation::class)->willThrow(new NonUniqueIdentifierException())->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata())->withAttributes(['elasticsearch' => false])); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyCarColor::class)->shouldBeCalled()->willThrow(new ResourceClassNotFoundException()); - - $collectionDataProvider = new CollectionDataProvider( - $this->prophesize(Client::class)->reveal(), - $documentMetadataFactoryProphecy->reveal(), - $identifierExtractorProphecy->reveal(), - $this->prophesize(DenormalizerInterface::class)->reveal(), - new Pagination($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()), - $resourceMetadataFactoryProphecy->reveal() - ); - - self::assertTrue($collectionDataProvider->supports(Foo::class)); - self::assertFalse($collectionDataProvider->supports(Dummy::class)); - self::assertFalse($collectionDataProvider->supports(CompositeRelation::class)); - self::assertFalse($collectionDataProvider->supports(DummyCar::class)); - self::assertFalse($collectionDataProvider->supports(DummyCarColor::class)); - } - - public function testGetCollection() - { - $context = [ - 'groups' => ['custom'], - ]; - - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata()); - - $documents = [ - 'took' => 15, - 'time_out' => false, - '_shards' => [ - 'total' => 5, - 'successful' => 5, - 'skipped' => 0, - 'failed' => 0, - ], - 'hits' => [ - 'total' => 4, - 'max_score' => 1, - 'hits' => [ - [ - '_index' => 'foo', - '_type' => '_doc', - '_id' => '1', - '_score' => 1, - '_source' => [ - 'id' => 1, - 'name' => 'Kilian', - 'bar' => 'Jornet', - ], - ], - [ - '_index' => 'foo', - '_type' => '_doc', - '_id' => '2', - '_score' => 1, - '_source' => [ - 'id' => 2, - 'name' => 'François', - 'bar' => 'D\'Haene', - ], - ], - ], - ], - ]; - - $clientProphecy = $this->prophesize(Client::class); - $clientProphecy - ->search( - Argument::allOf( - Argument::withEntry('index', 'foo'), - Argument::withEntry('body', Argument::allOf( - Argument::withEntry('size', 2), - Argument::withEntry('from', 0), - Argument::withEntry('query', Argument::allOf( - Argument::withEntry('match_all', Argument::type(\stdClass::class)), - Argument::size(1) - )), - Argument::size(3) - )), - Argument::size(2) - ) - ) - ->willReturn($documents) - ->shouldBeCalled(); - - $requestBodySearchCollectionExtensionProphecy = $this->prophesize(RequestBodySearchCollectionExtensionInterface::class); - $requestBodySearchCollectionExtensionProphecy->applyToCollection([], Foo::class, 'get', $context)->willReturn([])->shouldBeCalled(); - - $collectionDataProvider = new CollectionDataProvider( - $clientProphecy->reveal(), - $documentMetadataFactoryProphecy->reveal(), - $this->prophesize(IdentifierExtractorInterface::class)->reveal(), - $denormalizer = $this->prophesize(DenormalizerInterface::class)->reveal(), - new Pagination($resourceMetadataFactoryProphecy->reveal(), ['items_per_page' => 2]), - $resourceMetadataFactoryProphecy->reveal(), - [$requestBodySearchCollectionExtensionProphecy->reveal()] - ); - - self::assertEquals( - new Paginator($denormalizer, $documents, Foo::class, 2, 0, $context), - $collectionDataProvider->getCollection(Foo::class, 'get', $context) - ); - } -} diff --git a/tests/Core/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php b/tests/Core/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php deleted file mode 100644 index adfe2f6c3a2..00000000000 --- a/tests/Core/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php +++ /dev/null @@ -1,149 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Elasticsearch\DataProvider; - -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\ItemDataProvider; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; -use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeRelation; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarColor; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; -use Elasticsearch\Client; -use Elasticsearch\Common\Exceptions\Missing404Exception; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * @group legacy - * @requires PHP >= 7.4 - */ -class ItemDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - self::assertInstanceOf( - ItemDataProviderInterface::class, - new ItemDataProvider( - $this->prophesize(Client::class)->reveal(), - $this->prophesize(DocumentMetadataFactoryInterface::class)->reveal(), - $this->prophesize(IdentifierExtractorInterface::class)->reveal(), - $this->prophesize(DenormalizerInterface::class)->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal() - ) - ); - } - - public function testSupports() - { - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - $documentMetadataFactoryProphecy->create(Dummy::class)->willThrow(new IndexNotFoundException())->shouldBeCalled(); - $documentMetadataFactoryProphecy->create(CompositeRelation::class)->willReturn(new DocumentMetadata('composite_relation'))->shouldBeCalled(); - - $identifierExtractorProphecy = $this->prophesize(IdentifierExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $identifierExtractorProphecy->getIdentifierFromResourceClass(CompositeRelation::class)->willThrow(new NonUniqueIdentifierException())->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata())->withAttributes(['elasticsearch' => false])); - $resourceMetadataFactoryProphecy->create(DummyCarColor::class)->shouldBeCalled()->willThrow(new ResourceClassNotFoundException()); - - $itemDataProvider = new ItemDataProvider( - $this->prophesize(Client::class)->reveal(), - $documentMetadataFactoryProphecy->reveal(), - $identifierExtractorProphecy->reveal(), - $this->prophesize(DenormalizerInterface::class)->reveal(), - $resourceMetadataFactoryProphecy->reveal() - ); - - self::assertTrue($itemDataProvider->supports(Foo::class)); - self::assertFalse($itemDataProvider->supports(Dummy::class)); - self::assertFalse($itemDataProvider->supports(CompositeRelation::class)); - self::assertFalse($itemDataProvider->supports(DummyCar::class)); - self::assertFalse($itemDataProvider->supports(DummyCarColor::class)); - } - - public function testGetItem() - { - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - - $identifierExtractorProphecy = $this->prophesize(IdentifierExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - - $document = [ - '_index' => 'foo', - '_type' => '_doc', - '_id' => '1', - '_version' => 1, - 'found' => true, - '_source' => [ - 'id' => 1, - 'name' => 'Rossinière', - 'bar' => 'erèinissor', - ], - ]; - - $foo = new Foo(); - $foo->setName('Rossinière'); - $foo->setBar('erèinissor'); - - $clientProphecy = $this->prophesize(Client::class); - $clientProphecy->get(['index' => 'foo', 'id' => '1'])->willReturn($document)->shouldBeCalled(); - - $denormalizerProphecy = $this->prophesize(DenormalizerInterface::class); - $denormalizerProphecy->denormalize($document, Foo::class, DocumentNormalizer::FORMAT, [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => true])->willReturn($foo)->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $itemDataProvider = new ItemDataProvider($clientProphecy->reveal(), $documentMetadataFactoryProphecy->reveal(), $identifierExtractorProphecy->reveal(), $denormalizerProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - - self::assertSame($foo, $itemDataProvider->getItem(Foo::class, ['id' => 1])); - } - - public function testGetItemWithMissing404Exception() - { - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - - $identifierExtractorProphecy = $this->prophesize(IdentifierExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - - $clientProphecy = $this->prophesize(Client::class); - $clientProphecy->get(['index' => 'foo', 'id' => '404'])->willThrow(new Missing404Exception())->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $itemDataProvider = new ItemDataProvider($clientProphecy->reveal(), $documentMetadataFactoryProphecy->reveal(), $identifierExtractorProphecy->reveal(), $this->prophesize(DenormalizerInterface::class)->reveal(), $resourceMetadataFactoryProphecy->reveal()); - - self::assertNull($itemDataProvider->getItem(Foo::class, ['id' => 404])); - } -} diff --git a/tests/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php b/tests/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php deleted file mode 100644 index 7ade6ced88f..00000000000 --- a/tests/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php +++ /dev/null @@ -1,64 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Elasticsearch\Metadata\Resource\Factory; - -use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Resource\Factory\ElasticsearchOperationResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class ElasticsearchOperationResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - self::assertInstanceOf( - ResourceMetadataFactoryInterface::class, - new ElasticsearchOperationResourceMetadataFactory($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()) - ); - } - - public function testCreate() - { - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(Foo::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - - $resourceMetadata = (new ElasticsearchOperationResourceMetadataFactory($decoratedProphecy->reveal()))->create(Foo::class); - - self::assertSame(['get' => ['method' => 'GET']], $resourceMetadata->getCollectionOperations()); - self::assertSame(['get' => ['method' => 'GET']], $resourceMetadata->getItemOperations()); - } - - public function testCreateWithExistingOperations() - { - $originalResourceMetadata = new ResourceMetadata(); - $originalResourceMetadata = $originalResourceMetadata->withItemOperations(['foo' => ['method' => 'GET']]); - $originalResourceMetadata = $originalResourceMetadata->withCollectionOperations(['bar' => ['method' => 'GET']]); - - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(Foo::class)->willReturn($originalResourceMetadata)->shouldBeCalled(); - - $resourceMetadata = (new ElasticsearchOperationResourceMetadataFactory($decoratedProphecy->reveal()))->create(Foo::class); - - self::assertSame($originalResourceMetadata, $resourceMetadata); - self::assertSame(['foo' => ['method' => 'GET']], $resourceMetadata->getItemOperations()); - self::assertSame(['bar' => ['method' => 'GET']], $resourceMetadata->getCollectionOperations()); - } -} diff --git a/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php b/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php deleted file mode 100644 index b3e1f2afee9..00000000000 --- a/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php +++ /dev/null @@ -1,569 +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); - -namespace ApiPlatform\Core\Tests\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider; - -use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider; -use ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser; -use ApiPlatform\Core\Bridge\Symfony\Routing\OperationMethodResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use Nelmio\ApiDocBundle\Annotation\ApiDoc; -use Nelmio\ApiDocBundle\Extractor\AnnotationsProviderInterface; -use Nelmio\ApiDocBundle\NelmioApiDocBundle; -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * @author Teoh Han Hui - * - * @group legacy - */ -class ApiPlatformProviderTest extends TestCase -{ - use ProphecyTrait; - - protected function setUp(): void - { - if (!class_exists(NelmioApiDocBundle::class)) { - $this->markTestSkipped('NelmioApiDocBundle is not installed.'); - } - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testConstruct() - { - $apiPlatformProvider = new ApiPlatformProvider( - $this->prophesize(ResourceNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(NormalizerInterface::class)->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - - $this->assertInstanceOf(AnnotationsProviderInterface::class, $apiPlatformProvider); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testGetAnnotations() - { - $dummySearchFilterProphecy = $this->prophesize(FilterInterface::class); - $dummySearchFilterProphecy->getDescription(Dummy::class)->willReturn([ - 'name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => 'false', - 'strategy' => 'partial', - ], - ])->shouldBeCalled(); - - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filterLocatorProphecy->has('my_dummy.search')->willReturn(true)->shouldBeCalled(); - $filterLocatorProphecy->get('my_dummy.search')->willReturn($dummySearchFilterProphecy->reveal())->shouldBeCalled(); - - $this->extractAnnotations($filterLocatorProphecy->reveal()); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testGetAnnotationsWithDeprecatedFilterCollection() - { - $dummySearchFilterProphecy = $this->prophesize(FilterInterface::class); - $dummySearchFilterProphecy->getDescription(Dummy::class)->willReturn([ - 'name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => 'false', - 'strategy' => 'partial', - ], - ])->shouldBeCalled(); - - $this->extractAnnotations(new FilterCollection(['my_dummy.search' => $dummySearchFilterProphecy->reveal()])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testConstructWithInvalidFilterLocator() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface.'); - - new ApiPlatformProvider( - $this->prophesize(ResourceNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(NormalizerInterface::class)->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - new \ArrayObject(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - } - - private function extractAnnotations($filterLocator) - { - $resourceNameCollection = new ResourceNameCollection([Dummy::class, RelatedDummy::class]); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn($resourceNameCollection)->shouldBeCalled(); - - $apiDocumentationBuilderProphecy = $this->prophesize(NormalizerInterface::class); - $apiDocumentationBuilderProphecy->normalize(new Documentation($resourceNameCollection))->willReturn($this->getHydraDoc())->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withItemOperations([ - 'get' => [ - 'method' => 'GET', - ], - 'put' => [ - 'method' => 'PUT', - ], - 'delete' => [ - 'method' => 'DELETE', - ], - ]) - ->withCollectionOperations([ - 'get' => [ - 'filters' => [ - 'my_dummy.search', - ], - 'method' => 'GET', - ], - 'post' => [ - 'method' => 'POST', - ], - ]); - - $relatedDummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('RelatedDummy'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedDummyResourceMetadata)->shouldBeCalled(); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'post')->willReturn('POST')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'put')->willReturn('PUT')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'delete')->willReturn('DELETE')->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationRoute(Dummy::class, 'get')->willReturn((new Route('/dummies'))->setMethods(['GET']))->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationRoute(Dummy::class, 'post')->willReturn((new Route('/dummies'))->setMethods(['POST']))->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'get')->willReturn((new Route('/dummies/{id}'))->setMethods(['GET']))->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'put')->willReturn((new Route('/dummies/{id}'))->setMethods(['PUT']))->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'delete')->willReturn((new Route('/dummies/{id}'))->setMethods(['DELETE']))->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $apiDocumentationBuilderProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $filterLocator, - $operationMethodResolverProphecy->reveal() - ); - - $annotations = $apiPlatformProvider->getAnnotations(); - - $this->assertCount(5, $annotations); - - $expectedResults = [ - [ - 'resource' => '/dummies', - 'description' => 'Retrieves the collection of Dummy resources.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => null, - 'output' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - 'filters' => [ - 'name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => 'false', - 'strategy' => 'partial', - ], - ], - 'path' => '/dummies', - 'methods' => ['GET'], - ], - [ - 'resource' => '/dummies', - 'description' => 'Creates a Dummy resource.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => sprintf('%s:%s:%s', ApiPlatformParser::IN_PREFIX, Dummy::class, 'post'), - 'output' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'post'), - 'filters' => [], - 'path' => '/dummies', - 'methods' => ['POST'], - ], - [ - 'resource' => '/dummies/{id}', - 'description' => 'Retrieves Dummy resource.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => null, - 'output' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - 'filters' => [], - 'path' => '/dummies/{id}', - 'methods' => ['GET'], - ], - [ - 'resource' => '/dummies/{id}', - 'description' => 'Replaces the Dummy resource.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => sprintf('%s:%s:%s', ApiPlatformParser::IN_PREFIX, Dummy::class, 'put'), - 'output' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'put'), - 'filters' => [], - 'path' => '/dummies/{id}', - 'methods' => ['PUT'], - ], - [ - 'resource' => '/dummies/{id}', - 'description' => 'Deletes the Dummy resource.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => null, - 'output' => null, - 'filters' => [], - 'path' => '/dummies/{id}', - 'methods' => ['DELETE'], - ], - ]; - - foreach ($expectedResults as $i => $expected) { - /** @var ApiDoc $apiDoc */ - $apiDoc = $annotations[$i]; - - $this->assertInstanceOf(ApiDoc::class, $apiDoc); - $this->assertEquals($expected['resource'], $apiDoc->getResource()); - $this->assertEquals($expected['description'], $apiDoc->getDescription()); - $this->assertEquals($expected['resource_description'], $apiDoc->getResourceDescription()); - $this->assertEquals($expected['section'], $apiDoc->getSection()); - $this->assertEquals($expected['input'], $apiDoc->getInput()); - $this->assertEquals($expected['output'], $apiDoc->getOutput()); - $this->assertEquals($expected['filters'], $apiDoc->getFilters()); - $this->assertInstanceOf(Route::class, $apiDoc->getRoute()); - $this->assertEquals($expected['path'], $apiDoc->getRoute()->getPath()); - $this->assertEquals($expected['methods'], $apiDoc->getRoute()->getMethods()); - } - } - - private function getHydraDoc() - { - $hydraDocJson = <<<'JSON' - { - "hydra:supportedClass": [ - { - "@id": "#Dummy", - "hydra:title": "Dummy", - "hydra:supportedOperation": [ - { - "hydra:method": "GET", - "hydra:title": "Retrieves Dummy resource.", - "returns": "#Dummy" - }, - { - "expects": "#Dummy", - "hydra:method": "PUT", - "hydra:title": "Replaces the Dummy resource.", - "returns": "#Dummy" - }, - { - "hydra:method": "DELETE", - "hydra:title": "Deletes the Dummy resource.", - "returns": "owl:Nothing" - } - ] - }, - { - "@id": "#Entrypoint", - "hydra:supportedProperty": [ - { - "hydra:property": { - "@id": "#Entrypoint\/dummy", - "hydra:supportedOperation": [ - { - "hydra:method": "GET", - "hydra:title": "Retrieves the collection of Dummy resources.", - "returns": "hydra:PagedCollection" - }, - { - "expects": "#Dummy", - "hydra:method": "POST", - "hydra:title": "Creates a Dummy resource.", - "returns": "#Dummy" - } - ] - } - } - ] - } - ] - } -JSON; - - return json_decode($hydraDocJson, true); - } - - public function testGetAnnotationsWithEmptyHydraDoc() - { - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn([])->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - - $this->assertEquals([], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithInvalidHydraSupportedClass() - { - $hydraDoc = ['hydra:supportedClass' => 'not an array']; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - - $this->assertEquals([], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithEmptyHydraSupportedClass() - { - $hydraDoc = ['hydra:supportedClass' => []]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - - $this->assertEquals([], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithInvalidHydraSupportedOperation() - { - $hydraDoc = ['hydra:supportedClass' => [ - ['@id' => '#Entrypoint'], - ['@id' => '#Dummy', 'hydra:supportedOperation' => 'not an array'], - ]]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withItemOperations([ - 'get' => [ - 'method' => 'GET', - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - - $route = (new Route('/dummies/{id}'))->setMethods(['GET']); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'get')->willReturn($route)->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $operationMethodResolverProphecy->reveal() - ); - - $apiDoc = new ApiDoc(['resource' => $route->getPath(), 'description' => '', 'resourceDescription' => '', 'section' => '']); - $apiDoc->setRoute($route); - - $this->assertEquals([$apiDoc], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithEmptyHydraSupportedOperation() - { - $hydraDoc = ['hydra:supportedClass' => [ - ['@id' => '#Entrypoint'], - ['@id' => '#Dummy', 'hydra:supportedOperation' => []], - ]]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withItemOperations([ - 'get' => [ - 'method' => 'GET', - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - - $route = (new Route('/dummies/{id}'))->setMethods(['GET']); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'get')->willReturn($route)->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $operationMethodResolverProphecy->reveal() - ); - - $apiDoc = new ApiDoc(['resource' => $route->getPath(), 'description' => '', 'resourceDescription' => '', 'section' => '']); - $apiDoc->setRoute($route); - - $this->assertEquals([$apiDoc], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithInvalidHydraSupportedProperty() - { - $hydraDoc = ['hydra:supportedClass' => [ - ['@id' => '#Entrypoint', 'hydra:supportedProperty' => 'not an array'], - ['@id' => '#Dummy'], - ]]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withCollectionOperations([ - 'get' => [ - 'method' => 'GET', - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - - $route = (new Route('/dummies'))->setMethods(['GET']); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationRoute(Dummy::class, 'get')->willReturn($route)->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $operationMethodResolverProphecy->reveal() - ); - - $apiDoc = new ApiDoc(['resource' => $route->getPath(), 'description' => '', 'resourceDescription' => '', 'section' => '', 'filters' => []]); - $apiDoc->setRoute($route); - - $this->assertEquals([$apiDoc], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithEmptyHydraSupportedProperty() - { - $hydraDoc = ['hydra:supportedClass' => [ - ['@id' => '#Entrypoint', 'hydra:supportedProperty' => []], - ['@id' => '#Dummy'], - ]]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withCollectionOperations([ - 'get' => [ - 'method' => 'GET', - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - - $route = (new Route('/dummies'))->setMethods(['GET']); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationRoute(Dummy::class, 'get')->willReturn($route)->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $operationMethodResolverProphecy->reveal() - ); - - $apiDoc = new ApiDoc(['resource' => $route->getPath(), 'description' => '', 'resourceDescription' => '', 'section' => '', 'filters' => []]); - $apiDoc->setRoute($route); - - $this->assertEquals([$apiDoc], $apiPlatformProvider->getAnnotations()); - } -} diff --git a/tests/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php b/tests/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php deleted file mode 100644 index 0b35c0c68f6..00000000000 --- a/tests/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php +++ /dev/null @@ -1,540 +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); - -namespace ApiPlatform\Core\Tests\Bridge\NelmioApiDoc\Parser; - -use ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser; -use ApiPlatform\Core\Exception\ResourceClassNotFoundException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UnknownDummy; -use ApiPlatform\Core\Tests\ProphecyTrait; -use Doctrine\Common\Collections\Collection; -use Nelmio\ApiDocBundle\DataTypes; -use Nelmio\ApiDocBundle\Parser\ParserInterface; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -/** - * @author Teoh Han Hui - * - * @group legacy - */ -class ApiPlatformParserTest extends TestCase -{ - use ProphecyTrait; - - protected function setUp(): void - { - if (!class_exists(NelmioApiDocBundle::class)) { - $this->markTestSkipped('NelmioApiDocBundle is not installed.'); - } - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testConstruct() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertInstanceOf(ParserInterface::class, $apiPlatformParser); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testSupports() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertTrue($apiPlatformParser->supports([ - 'class' => sprintf('%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class), - ])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testNoOnDataFirstArray() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertFalse($apiPlatformParser->supports([ - 'class' => sprintf('%s', ApiPlatformParser::OUT_PREFIX), - ])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testSupportsAttributeNormalization() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Acme\CustomAttributeDummy')->willReturn(new ResourceMetadata('dummy', 'dummy', null, [ - 'get' => ['method' => 'GET', 'normalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_get']]], - 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_put']]], - 'delete' => ['method' => 'DELETE'], - ], []))->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create('Acme\CustomAttributeDummy', Argument::cetera())->willReturn(new PropertyNameCollection([ - 'id', - 'name', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $idPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_INT, false)) - ->withDescription('The id.') - ->withReadable(true) - ->withWritable(false) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create('Acme\CustomAttributeDummy', 'id')->willReturn($idPropertyMetadata)->shouldBeCalled(); - $namePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, false)) - ->withDescription('The dummy name.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create('Acme\CustomAttributeDummy', 'name')->willReturn($namePropertyMetadata)->shouldBeCalled(); - - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, 'Acme\CustomAttributeDummy', 'get'), - ]); - - $this->assertEquals([ - 'id' => [ - 'dataType' => DataTypes::INTEGER, - 'required' => false, - 'description' => 'The id.', - 'readonly' => true, - ], - 'name' => [ - 'dataType' => DataTypes::STRING, - 'required' => true, - 'description' => 'The dummy name.', - 'readonly' => false, - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testSupportsUnknownResource() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(UnknownDummy::class)->willThrow(ResourceClassNotFoundException::class)->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertFalse($apiPlatformParser->supports([ - 'class' => sprintf('%s:%s', ApiPlatformParser::OUT_PREFIX, UnknownDummy::class), - ])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testSupportsUnsupportedClassFormat() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Argument::any())->shouldNotBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertFalse($apiPlatformParser->supports([ - 'class' => Dummy::class, - ])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParse() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [ - 'get' => ['method' => 'GET', 'normalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_get']]], - 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_put']]], - 'gerard' => ['method' => 'get', 'path' => '/gerard', 'denormalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_put']]], - 'delete' => ['method' => 'DELETE'], - ], []))->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'id', - 'name', - 'dummyPrice', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $idPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_INT, false)) - ->withDescription('The id.') - ->withReadable(true) - ->withWritable(false) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->willReturn($idPropertyMetadata)->shouldBeCalled(); - $namePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, false)) - ->withDescription('The dummy name.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name')->willReturn($namePropertyMetadata)->shouldBeCalled(); - $dummyPricePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_FLOAT, true)) - ->withDescription('A dummy price.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyPrice')->willReturn($dummyPricePropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'gerard'), - ]); - - $this->assertEquals([ - 'id' => [ - 'dataType' => DataTypes::INTEGER, - 'required' => false, - 'description' => 'The id.', - 'readonly' => true, - ], - 'name' => [ - 'dataType' => DataTypes::STRING, - 'required' => true, - 'description' => 'The dummy name.', - 'readonly' => false, - ], - 'dummyPrice' => [ - 'dataType' => DataTypes::FLOAT, - 'required' => false, - 'description' => 'A dummy price.', - 'readonly' => false, - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParseDateTime() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'dummyDate', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $dummyDatePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class)) - ->withDescription('A dummy date.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate')->willReturn($dummyDatePropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - ]); - - $this->assertEquals([ - 'dummyDate' => [ - 'dataType' => DataTypes::DATETIME, - 'required' => false, - 'description' => 'A dummy date.', - 'readonly' => false, - 'format' => sprintf('{DateTime %s}', \DateTime::RFC3339), - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParseRelation() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'relatedDummy', - 'relatedDummies', - ]))->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'id', - 'name', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relatedDummyPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class)) - ->withDescription('A related dummy.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy')->willReturn($relatedDummyPropertyMetadata)->shouldBeCalled(); - $relatedDummiesPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, Collection::class, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class))) - ->withDescription('Several dummies.') - ->withReadable(true) - ->withWritable(true) - ->withReadableLink(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies')->willReturn($relatedDummiesPropertyMetadata)->shouldBeCalled(); - $idPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_INT, false)) - ->withReadable(true) - ->withWritable(false) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'id')->willReturn($idPropertyMetadata)->shouldBeCalled(); - $namePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, false)) - ->withDescription('A name.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name')->willReturn($namePropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - ]); - - $this->assertEquals([ - 'relatedDummy' => [ - 'dataType' => 'IRI', - 'required' => false, - 'description' => 'A related dummy.', - 'readonly' => false, - 'actualType' => DataTypes::STRING, - ], - 'relatedDummies' => [ - 'dataType' => null, - 'required' => false, - 'description' => 'Several dummies.', - 'readonly' => false, - 'actualType' => DataTypes::COLLECTION, - 'subType' => RelatedDummy::class, - 'children' => [ - 'id' => [ - 'dataType' => DataTypes::INTEGER, - 'required' => false, - 'description' => null, - 'readonly' => true, - ], - 'name' => [ - 'dataType' => DataTypes::STRING, - 'required' => false, - 'description' => 'A name.', - 'readonly' => false, - ], - ], - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParseWithNameConverter() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'nameConverted', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $nameConvertedPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, true)) - ->withDescription('A converted name') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'nameConverted')->willReturn($nameConvertedPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $nameConverterProphecy = $this->prophesize(NameConverterInterface::class); - $nameConverterProphecy->normalize('nameConverted', Dummy::class)->willReturn('name_converted')->shouldBeCalled(); - $nameConverter = $nameConverterProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $nameConverter); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - ]); - - $this->assertEquals([ - 'name_converted' => [ - 'dataType' => DataTypes::STRING, - 'required' => false, - 'description' => 'A converted name', - 'readonly' => false, - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParseRecursive() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'relatedDummy', - ]))->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'dummy', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relatedDummyMetadatata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class)) - ->withDescription('A related Dummy.') - ->withReadable(true) - ->withReadableLink(true) - ->withWritableLink(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy')->willReturn($relatedDummyMetadatata)->shouldBeCalled(); - $dummyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class)) - ->withDescription('A Dummy.') - ->withReadable(true) - ->withWritable(true) - ->withReadableLink(true) - ->withWritableLink(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'dummy')->willReturn($dummyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - ]); - - $this->assertEquals([ - 'relatedDummy' => [ - 'dataType' => null, - 'required' => false, - 'description' => 'A related Dummy.', - 'readonly' => false, - 'actualType' => 'model', - 'subType' => RelatedDummy::class, - 'children' => [ - 'dummy' => [ - 'dataType' => null, - 'required' => false, - 'description' => 'A Dummy.', - 'readonly' => false, - 'actualType' => 'model', - 'subType' => Dummy::class, - 'children' => [], - ], - ], - ], - ], $actual); - } -} diff --git a/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php b/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php deleted file mode 100644 index 3cd3cf99136..00000000000 --- a/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php +++ /dev/null @@ -1,54 +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); - -namespace ApiPlatform\Core\Tests\Bridge\RamseyUuid\Identifier\Normalizer; - -use ApiPlatform\Core\Bridge\RamseyUuid\Identifier\Normalizer\UuidNormalizer; -use ApiPlatform\Exception\InvalidIdentifierException; -use PHPUnit\Framework\TestCase; -use Ramsey\Uuid\Uuid; - -class UuidNormalizerTest extends TestCase -{ - public function testDenormalizeUuid() - { - $uuid = Uuid::uuid4(); - $normalizer = new UuidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($uuid->toString(), Uuid::class)); - $this->assertEquals($uuid, $normalizer->denormalize($uuid->toString(), Uuid::class)); - } - - public function testNoSupportDenormalizeUuid() - { - $uuid = 'notanuuid'; - $normalizer = new UuidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($uuid, '')); - } - - public function testFailDenormalizeUuid() - { - $this->expectException(InvalidIdentifierException::class); - - $uuid = 'notanuuid'; - $normalizer = new UuidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($uuid, Uuid::class)); - $normalizer->denormalize($uuid, Uuid::class); - } - - public function testDoNotSupportNotString() - { - $uuid = Uuid::uuid4(); - $normalizer = new UuidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($uuid, Uuid::class)); - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandTest.php b/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandTest.php deleted file mode 100644 index aef9ec5a63f..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandTest.php +++ /dev/null @@ -1,137 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\Command; - -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Component\Console\Exception\InvalidOptionException; -use Symfony\Component\Console\Tester\ApplicationTester; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Yaml; - -/** - * @author Amrouche Hamza - * @group legacy - */ -class SwaggerCommandTest extends KernelTestCase -{ - /** - * @var ApplicationTester - */ - private $tester; - - protected function setUp(): void - { - self::bootKernel(); - - $application = new Application(static::$kernel); - $application->setCatchExceptions(false); - $application->setAutoExit(false); - - $this->tester = new ApplicationTester($application); - - if (false === static::$kernel->getContainer()->getParameter('api_platform.metadata_backward_compatibility_layer')) { - $this->markTestSkipped( - 'Swagger is not compatible with the new metadata.' - ); - } - } - - /** - * @group legacy - * @expectedDeprecation The command "api:swagger:export" is deprecated for the spec version 3 use "api:openapi:export". - */ - public function testExecuteWithAliasVersion3() - { - $this->tester->run(['command' => 'api:swagger:export', '--spec-version' => 3]); - - $this->assertJson($this->tester->getDisplay()); - } - - /** - * @group legacy - * @expectedDeprecation The command "api:swagger:export" is deprecated for the spec version 3 use "api:openapi:export". - */ - public function testExecuteWithYamlVersion3() - { - $this->tester->run(['command' => 'api:swagger:export', '--yaml' => true, '--spec-version' => 3]); - - $result = $this->tester->getDisplay(); - $this->assertYaml($result); - - $expected = <<assertStringContainsString(str_replace(\PHP_EOL, "\n", $expected), $result, 'nested object should be present.'); - - $expected = <<assertStringContainsString(str_replace(\PHP_EOL, "\n", $expected), $result, 'arrays should be correctly formatted.'); - $this->assertStringContainsString('openapi: 3.0.2', $result); - - $expected = <<assertStringContainsString(str_replace(\PHP_EOL, "\n", $expected), $result, 'multiline formatting must be preserved (using literal style).'); - - $expected = <<assertStringContainsString(str_replace(\PHP_EOL, "\n", $expected), $result); - } - - public function testExecuteWithBadArguments() - { - $this->expectException(InvalidOptionException::class); - $this->expectExceptionMessage('This tool only supports versions 2, 3 of the OpenAPI specification ("foo" given).'); - $this->tester->run(['command' => 'api:swagger:export', '--spec-version' => 'foo', '--yaml' => true]); - } - - public function testWriteToFile() - { - /** @var string $tmpFile */ - $tmpFile = tempnam(sys_get_temp_dir(), 'test_write_to_file'); - - $this->tester->run(['command' => 'api:swagger:export', '--output' => $tmpFile]); - - $this->assertJson((string) @file_get_contents($tmpFile)); - @unlink($tmpFile); - } - - /** - * @param string $data - */ - private function assertYaml($data) - { - try { - Yaml::parse($data); - } catch (ParseException $exception) { - $this->fail('Is not valid YAML: '.$exception->getMessage()); - } - $this->addToAssertionCount(1); - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php b/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php deleted file mode 100644 index 2a677c2a085..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php +++ /dev/null @@ -1,69 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\Command; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\Command\SwaggerCommand; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use PHPUnit\Framework\MockObject\MockObject; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\BufferedOutput; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -class SwaggerCommandUnitTest extends KernelTestCase -{ - /** @var MockObject&NormalizerInterface */ - private $normalizer; - - /** @var ResourceNameCollectionFactoryInterface&MockObject */ - private $resources; - - /** @var SwaggerCommand */ - private $command; - - protected function setUp(): void - { - $this->normalizer = $this->createMock(NormalizerInterface::class); - $this->resources = $this->createMock(ResourceNameCollectionFactoryInterface::class); - $this->command = new SwaggerCommand( - $this->normalizer, - $this->resources, - 'My API', - 'I told you already: it is my API', - 'one-zero-zero' - ); - - $this->resources->method('create') - ->willReturn(new ResourceNameCollection()); - } - - public function testDocumentationJsonDoesNotUseEscapedSlashes(): void - { - $this->normalizer->method('normalize') - ->with(self::isInstanceOf(Documentation::class)) - ->willReturn(['a-jsonable-documentation' => 'containing/some/slashes']); - - $output = new BufferedOutput(); - - $this->command->run(new ArrayInput([]), $output); - - $jsonOutput = $output->fetch(); - - self::assertJson($jsonOutput); - self::assertStringNotContainsString('containing\/some\/slashes', $jsonOutput); - self::assertStringContainsString('containing/some/slashes', $jsonOutput); - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommandTest.php b/tests/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommandTest.php deleted file mode 100644 index a67f0904c4b..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommandTest.php +++ /dev/null @@ -1,106 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\Command; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Bridge\Symfony\Bundle\Command\UpgradeApiResourceCommand; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Core\Upgrade\SubresourceTransformer; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use Doctrine\Common\Annotations\AnnotationReader; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Tester\CommandTester; - -class UpgradeApiResourceCommandTest extends TestCase -{ - use ProphecyTrait; - - private function getCommandTester(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, SubresourceOperationFactoryInterface $subresourceOperationFactory): CommandTester - { - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - - $application = new Application(); - $application->setCatchExceptions(false); - $application->setAutoExit(false); - - $application->add(new UpgradeApiResourceCommand($resourceNameCollectionFactory, $resourceMetadataFactory, $subresourceOperationFactory, new SubresourceTransformer(), $identifiersExtractor->reveal(), new AnnotationReader())); - - $command = $application->find('api:upgrade-resource'); - - return new CommandTester($command); - } - - /** - * @requires PHP 8.1 - */ - public function testDebugResource() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([RelatedDummy::class])); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); - $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); - $subresourceOperationFactoryProphecy->create(RelatedDummy::class)->willReturn([[ - 'property' => 'id', - 'collection' => false, - 'resource_class' => RelatedDummy::class, - 'shortNames' => [ - 'RelatedDummy', - ], - 'legacy_filters' => [ - 'related_dummy.friends', - 'related_dummy.complex_sub_query', - ], - 'legacy_normalization_context' => [ - 'groups' => [ - 'friends', - ], - ], - 'legacy_type' => 'https://schema.org/Product', - 'identifiers' => [ - 'id' => [ - RelatedDummy::class, - 'id', - true, - ], - ], - 'operation_name' => 'id_get_subresource', - 'route_name' => 'api_related_dummies_id_get_subresource', - 'path' => '/related_dummies/{id}/id.{_format}', - ]]); - - $commandTester = $this->getCommandTester($resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), $subresourceOperationFactoryProphecy->reveal()); - $commandTester->execute([]); - - $expectedStrings = [ - '-use ApiPlatform\\Core\\Annotation\\ApiSubresource', - '-use ApiPlatform\\Core\\Annotation\\ApiResource', - '+use ApiPlatform\\Metadata\\ApiResource', - '+use ApiPlatform\\Metadata\\Get', - "+#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']])], types: ['https://schema.org/Product'], normalizationContext: ['groups' => ['friends']], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'])]", - "#[ApiResource(uriTemplate: '/related_dummies/{id}/id.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])]", - ]; - - $display = $commandTester->getDisplay(); - foreach ($expectedStrings as $expectedString) { - $this->assertStringContainsString($expectedString, $display); - } - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php b/tests/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php deleted file mode 100644 index 79e28babcd4..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php +++ /dev/null @@ -1,185 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\DataPersister; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister\TraceableChainDataPersister; -use ApiPlatform\Core\DataPersister\ChainDataPersister; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataPersister\ResumableDataPersisterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - */ -class TraceableChainDataPersisterTest extends TestCase -{ - use ProphecyTrait; - - /** @dataProvider dataPersisterProvider */ - public function testPersist($persister, $expected) - { - $dataPersister = new TraceableChainDataPersister($persister); - $dataPersister->persist(''); - - $result = $dataPersister->getPersistersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, DataPersisterInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - } - - /** @dataProvider dataPersisterProvider */ - public function testRemove($persister, $expected) - { - $dataPersister = new TraceableChainDataPersister($persister); - $dataPersister->remove(''); - - $result = $dataPersister->getPersistersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, DataPersisterInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - } - - public function testSupports() - { - $context = ['ok' => true]; - $persister = $this->prophesize(DataPersisterInterface::class); - $persister->supports('', $context)->willReturn(true)->shouldBeCalled(); - $chain = new ChainDataPersister([$persister->reveal()]); - $persister->persist('', $context)->shouldBeCalled(); - $dataPersister = new TraceableChainDataPersister($chain); - $dataPersister->persist('', $context); - } - - public function dataPersisterProvider(): iterable - { - yield [ - new ChainDataPersister([]), - [], - ]; - - yield [ - new ChainDataPersister([ - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return false; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return true; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return true; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - ]), - [false, true, false], - ]; - - yield [ - new ChainDataPersister([ - new class() implements DataPersisterInterface, ResumableDataPersisterInterface { - public function supports($data): bool - { - return true; - } - - public function resumable(array $context = []): bool - { - return true; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return false; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return true; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - ]), - [true, false, true], - ]; - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php b/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php deleted file mode 100644 index 82c4282773c..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php +++ /dev/null @@ -1,149 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\DataProvider; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainCollectionDataProvider; -use ApiPlatform\Core\DataProvider\ChainCollectionDataProvider; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - */ -class TraceableChainCollectionDataCollectorTest extends TestCase -{ - /** @dataProvider dataProviderProvider */ - public function testGetCollection($provider, $context, $expected) - { - $dataProvider = new TraceableChainCollectionDataProvider($provider); - $dataProvider->getCollection('', null, $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, CollectionDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - /** - * @dataProvider deprecatedDataProviderProvider - * @group legacy - * - * @param mixed $provider - * @param mixed $context - * @param mixed $expected - */ - public function testDeprecatedGetCollection($provider, $context, $expected) - { - $dataProvider = new TraceableChainCollectionDataProvider($provider); - $dataProvider->getCollection('', null, $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, CollectionDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - public function dataProviderProvider(): iterable - { - yield 'Not a ChainCollectionDataProvider' => [ - new class() implements CollectionDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - }, - ['some_context'], - [], - ]; - - yield 'Empty ChainCollectionDataProvider' => [ - new ChainCollectionDataProvider([]), - ['some_context'], - [], - ]; - - yield 'ChainCollectionDataProvider' => [ - new ChainCollectionDataProvider([ - new class() implements CollectionDataProviderInterface, RestrictedDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return false; - } - }, - new class() implements CollectionDataProviderInterface, RestrictedDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return true; - } - }, - new class() implements CollectionDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - }, - ]), - ['some_context'], - [false, true, null], - ]; - } - - public function deprecatedDataProviderProvider(): iterable - { - yield 'ChainCollectionDataProvider' => [ - new ChainCollectionDataProvider([ - new class() implements CollectionDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - throw new ResourceClassNotSupportedException('nope'); - } - }, - new class() implements CollectionDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - }, - ]), - ['some_context'], - [false, true], - ]; - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php b/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php deleted file mode 100644 index d8cfb0c387a..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php +++ /dev/null @@ -1,150 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\DataProvider; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainItemDataProvider; -use ApiPlatform\Core\DataProvider\ChainItemDataProvider; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - */ -class TraceableChainItemDataCollectorTest extends TestCase -{ - /** @dataProvider dataProviderProvider */ - public function testGetItem($provider, $context, $expected) - { - $dataProvider = new TraceableChainItemDataProvider($provider); - $dataProvider->getItem('', '', null, $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, ItemDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - /** - * @dataProvider deprecatedDataProviderProvider - * @group legacy - * - * @param mixed $provider - * @param mixed $context - * @param mixed $expected - */ - public function testDeprecatedGetItem($provider, $context, $expected) - { - $dataProvider = new TraceableChainItemDataProvider($provider); - $dataProvider->getItem('', '', null, $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, ItemDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - public function dataProviderProvider(): iterable - { - yield 'Not a ChainItemDataProvider' => [ - new class() implements ItemDataProviderInterface { - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return null; - } - }, - ['some_context'], - [], - ]; - - yield 'Empty ChainItemDataProvider' => [ - new ChainItemDataProvider([]), - ['some_context'], - [], - ]; - - yield 'ChainItemDataProvider' => [ - new ChainItemDataProvider([ - new class() implements ItemDataProviderInterface, RestrictedDataProviderInterface { - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return false; - } - - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return null; - } - }, - new class() implements ItemDataProviderInterface, RestrictedDataProviderInterface, DenormalizedIdentifiersAwareItemDataProviderInterface { - public function getItem(string $resourceClass, /* array */ $id, string $operationName = null, array $context = []) - { - return null; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return true; - } - }, - new class() implements ItemDataProviderInterface { - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return null; - } - }, - ]), - ['some_context'], - [false, true, null], - ]; - } - - public function deprecatedDataProviderProvider(): iterable - { - yield 'deprecated ChainItemDataProvider - ResourceClassNotSupportedException' => [ - new ChainItemDataProvider([ - new class() implements ItemDataProviderInterface { - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - throw new ResourceClassNotSupportedException('nope'); - } - }, - new class() implements ItemDataProviderInterface { - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return null; - } - }, - ]), - ['some_context'], - [false, true], - ]; - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php b/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php deleted file mode 100644 index 41bc0d2f2e0..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php +++ /dev/null @@ -1,149 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\DataProvider; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainSubresourceDataProvider; -use ApiPlatform\Core\DataProvider\ChainSubresourceDataProvider; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - */ -class TraceableChainSubresourceDataCollectorTest extends TestCase -{ - /** @dataProvider dataProviderProvider */ - public function testGetSubresource($provider, $context, $expected) - { - $dataProvider = new TraceableChainSubresourceDataProvider($provider); - $dataProvider->getSubresource('', [], $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, SubresourceDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - /** - * @dataProvider deprecatedDataProviderProvider - * @group legacy - * - * @param mixed $provider - * @param mixed $context - * @param mixed $expected - */ - public function testDeprecatedGetSubResource($provider, $context, $expected) - { - $dataProvider = new TraceableChainSubresourceDataProvider($provider); - $dataProvider->getSubresource('', [], $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, SubresourceDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - public function dataProviderProvider(): iterable - { - yield 'Not a ChainSubresourceDataProvider' => [ - new class() implements SubresourceDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - }, - ['some_context'], - [], - ]; - - yield 'Empty ChainSubresourceDataProvider' => [ - new ChainSubresourceDataProvider([]), - ['some_context'], - [], - ]; - - yield 'ChainSubresourceDataProvider' => [ - new ChainSubresourceDataProvider([ - new class() implements SubresourceDataProviderInterface, RestrictedDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return false; - } - }, - new class() implements SubresourceDataProviderInterface, RestrictedDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return true; - } - }, - new class() implements SubresourceDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - }, - ]), - ['some_context'], - [false, true, null], - ]; - } - - public function deprecatedDataProviderProvider(): iterable - { - yield 'deprecated ChainSubresourceDataProvider - ResourceClassNotSupportedException' => [ - new ChainSubresourceDataProvider([ - new class() implements SubresourceDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - throw new ResourceClassNotSupportedException('nope'); - } - }, - new class() implements SubresourceDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - }, - ]), - ['some_context'], - [false, true], - ]; - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php b/tests/Core/Bridge/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php deleted file mode 100644 index d4b84ac03fa..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php +++ /dev/null @@ -1,299 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\Twig; - -use ApiPlatform\Core\Bridge\Doctrine\Common\DataPersister; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\CollectionDataProvider as OdmCollectionDataProvider; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\ItemDataProvider as OdmItemDataProvider; -use ApiPlatform\Core\Bridge\Doctrine\Orm\CollectionDataProvider; -use ApiPlatform\Core\Bridge\Doctrine\Orm\ItemDataProvider; -use ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\ContainNonResourceItemDataProvider; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy as DocumentDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Tools\SchemaTool; -use Doctrine\Persistence\ManagerRegistry; -use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; - -/** - * @author Anthony GRASSIOT - */ -class ApiPlatformProfilerPanelTest extends WebTestCase -{ - /** - * @var EntityManagerInterface - */ - private $manager; - private $schemaTool; - private $env; - private $legacy; - - protected function setUp(): void - { - parent::setUp(); - $kernel = self::bootKernel(); - $this->env = $kernel->getEnvironment(); - $this->legacy = $kernel->getContainer()->getParameter('api_platform.metadata_backward_compatibility_layer'); - - /** @var ManagerRegistry $doctrine */ - $doctrine = $kernel->getContainer()->get('doctrine'); - /** @var EntityManagerInterface $manager */ - $manager = $doctrine->getManager(); - $this->manager = $manager; - $this->schemaTool = new SchemaTool($this->manager); - /** @var \Doctrine\ORM\Mapping\ClassMetadata[] $classes */ - $classes = $this->manager->getMetadataFactory()->getAllMetadata(); - $this->schemaTool->dropSchema($classes); - $this->manager->clear(); - $this->schemaTool->createSchema($classes); - - $this->ensureKernelShutdown(); - } - - protected function tearDown(): void - { - $this->schemaTool->dropSchema($this->manager->getMetadataFactory()->getAllMetadata()); - $this->manager->clear(); - parent::tearDown(); - } - - public function testDebugBarContentNotResourceClass() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - // Using html to get default Swagger UI - $client->request('GET', '/'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - /** @var string $token */ - $token = $client->getResponse()->headers->get('X-Debug-Token'); - $crawler = $client->request('GET', "/_wdt/$token"); - - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $block = $crawler->filter('div[class*=sf-toolbar-block-api_platform]'); - - // Check extra info content - $this->assertStringContainsString('sf-toolbar-status-default', $block->attr('class'), 'The toolbar block should have the default color.'); - $this->assertSame('Not an API Platform resource', $block->filterXPath('//div[@class="sf-toolbar-info-piece"][./b[contains(., "Resource Class")]]/span')->html()); - } - - public function testDebugBarContent() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('GET', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json']); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - /** @var string $token */ - $token = $client->getResponse()->headers->get('X-Debug-Token'); - - $crawler = $client->request('GET', "/_wdt/$token"); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $block = $crawler->filter('div[class*=sf-toolbar-block-api_platform]'); - - // Check extra info content - $this->assertStringContainsString('sf-toolbar-status-default', $block->attr('class'), 'The toolbar block should have the default color.'); - $this->assertSame('mongodb' === $this->env ? DocumentDummy::class : Dummy::class, $block->filterXPath('//div[@class="sf-toolbar-info-piece"][./b[contains(., "Resource Class")]]/span')->html()); - } - - public function testProfilerGeneralLayoutNotResourceClass() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - // Using html to get default Swagger UI - $client->request('GET', '/'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $crawler = $client->request('GET', '/_profiler/latest?panel=api_platform.data_collector.request', [], [], []); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Check that the Api-Platform sidebar link is active - $this->assertNotEmpty($menuLink = $crawler->filter('a[href$="panel=api_platform.data_collector.request"]')); - $this->assertNotEmpty($menuLink->filter('.disabled'), 'The sidebar menu should be disabled.'); - - $metrics = $crawler->filter('.metrics'); - $this->assertCount(1, $metrics->filter('.metric'), 'The should be one metric displayed (resource class).'); - $this->assertSame('Not an API Platform resource', $metrics->filter('span.value')->html()); - - $this->assertEmpty($crawler->filter('.sf-tabs .tab'), 'Tabs must not be presents on the panel.'); - } - - public function testProfilerGeneralLayout() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('GET', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json']); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $crawler = $client->request('GET', '/_profiler/latest?panel=api_platform.data_collector.request', [], [], []); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Check that the Api-Platform sidebar link is active - $this->assertNotEmpty($menuLink = $crawler->filter('a[href$="panel=api_platform.data_collector.request"]')); - $this->assertEmpty($menuLink->filter('.disabled'), 'The sidebar menu should not be disabled.'); - - $metrics = $crawler->filter('.metrics'); - $this->assertCount(1, $metrics->filter('.metric'), 'The should be one metric displayed (resource class).'); - $this->assertSame('mongodb' === $this->env ? DocumentDummy::class : Dummy::class, $metrics->filter('span.value')->html()); - - $this->assertCount(3, $crawler->filter('.sf-tabs .tab'), 'Tabs must be presents on the panel.'); - - // Metadata tab - $this->assertSame('Resource Metadata', $crawler->filter('.tab:nth-of-type(1) .tab-title')->html()); - $tabContent = $crawler->filter('.tab:nth-of-type(1) .tab-content'); - $this->assertStringEndsWith('"Dummy"', $tabContent->filter('h3')->html(), 'the resource shortname should be displayed.'); - - $this->assertCount(4, $tabContent->filter('table')); - $this->assertSame('Item operations', $tabContent->filter('table:first-of-type thead th:first-of-type')->html()); - $this->assertSame('Collection operations', $tabContent->filter('table:nth-of-type(2) thead th:first-of-type')->html()); - $this->assertSame('Filters', $tabContent->filter('table:nth-of-type(3) thead th:first-of-type')->html()); - $this->assertSame('Attributes', $tabContent->filter('table:last-of-type thead th:first-of-type')->html()); - - // Data providers tab - $this->assertSame('Data Providers', $crawler->filter('.tab:nth-of-type(2) .tab-title')->html()); - $this->assertNotEmpty($crawler->filter('.tab:nth-of-type(2) .tab-content')); - - // Data persisters tab - $this->assertSame('Data Persisters', $crawler->filter('.tab:last-child .tab-title')->html()); - $this->assertNotEmpty($crawler->filter('.tab:nth-of-type(3) .tab-content')); - } - - public function testGetCollectionProfiler() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('GET', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json']); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $crawler = $client->request('GET', '/_profiler/latest?panel=api_platform.data_collector.request'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Metadata tab - $tabContent = $crawler->filter('.tab:nth-of-type(1) .tab-content'); - $this->assertSame('get', $tabContent->filter('table:nth-of-type(2) th.status-success')->html(), 'The actual operation should be highlighted.'); - $this->assertEmpty($tabContent->filter('table:not(:nth-of-type(2)) .status-success'), 'Only the actual operation should be highlighted.'); - - // Data provider tab - $tabContent = $crawler->filter('.tab:nth-of-type(2) .tab-content'); - $this->assertSame('TRUE', $tabContent->filter('table tbody .status-success')->html()); - $this->assertStringContainsString('mongodb' === $this->env ? OdmCollectionDataProvider::class : CollectionDataProvider::class, $tabContent->filter('table tbody')->html()); - - $this->assertStringContainsString('No calls to item data provider have been recorded.', $tabContent->html()); - $this->assertStringContainsString('No calls to subresource data provider have been recorded.', $tabContent->html()); - - // Data persiters tab - $this->assertStringContainsString('No calls to data persister have been recorded.', $crawler->filter('.tab:nth-of-type(3) .tab-content .empty')->html()); - } - - public function testPostCollectionProfiler() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('POST', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json', 'CONTENT_TYPE' => 'application/ld+json'], '{"name": "foo"}'); - $this->assertEquals(201, $client->getResponse()->getStatusCode()); - $crawler = $client->request('get', '/_profiler/latest?panel=api_platform.data_collector.request'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Metadata tab - $tabContent = $crawler->filter('.tab:nth-of-type(1) .tab-content'); - $this->assertSame('post', $tabContent->filter('table:nth-of-type(2) th.status-success')->html(), 'The actual operation should be highlighted.'); - $this->assertEmpty($tabContent->filter('table:not(:nth-of-type(2)) .status-success'), 'Only the actual operation should be highlighted.'); - - // Data provider tab - $tabContent = $crawler->filter('.tab:nth-of-type(2) .tab-content'); - $this->assertStringContainsString('No calls to collection data provider have been recorded.', $tabContent->html()); - $this->assertStringContainsString('No calls to item data provider have been recorded.', $tabContent->html()); - $this->assertStringContainsString('No calls to subresource data provider have been recorded.', $tabContent->html()); - - // Data persiters tab - $tabContent = $crawler->filter('.tab:nth-of-type(3) .tab-content'); - $this->assertSame('TRUE', $tabContent->filter('table tbody .status-success')->html()); - $this->assertStringContainsString(DataPersister::class, $tabContent->filter('table tbody')->html()); - } - - /** - * @group legacy - * Group legacy is due ApiPlatform\Core\Exception\ResourceClassNotSupportedException, the annotation could be removed in 3.0 but the test should stay - */ - public function testGetItemProfiler() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $dummy = new Dummy(); - $dummy->setName('bar'); - $this->manager->persist($dummy); - $this->manager->flush(); - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('GET', '/dummies/1', [], [], ['HTTP_ACCEPT' => 'application/ld+json', 'CONTENT_TYPE' => 'application/ld+json'], '{"name": "foo"}'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $crawler = $client->request('get', '/_profiler/latest?panel=api_platform.data_collector.request'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Metadata tab - $tabContent = $crawler->filter('.tab:nth-of-type(1) .tab-content'); - $this->assertSame('get', $tabContent->filter('table:nth-of-type(1) th.status-success')->html(), 'The actual operation should be highlighted.'); - $this->assertEmpty($tabContent->filter('table:not(:nth-of-type(1)) .status-success'), 'Only the actual operation should be highlighted.'); - - // Data provider tab - $tabContent = $crawler->filter('.tab:nth-of-type(2) .tab-content'); - $this->assertSame('FALSE', $tabContent->filter('table tbody tr:first-of-type .status-error')->html()); - $this->assertSame(ContainNonResourceItemDataProvider::class, $tabContent->filter('table tbody tr:first-of-type td:nth-of-type(3)')->html()); - - $this->assertSame('TRUE', $tabContent->filter('table tbody .status-success')->html()); - $this->assertStringContainsString('mongodb' === $this->env ? OdmItemDataProvider::class : ItemDataProvider::class, $tabContent->filter('table tbody')->html()); - - $this->assertStringContainsString('No calls to collection data provider have been recorded.', $tabContent->html()); - $this->assertStringContainsString('No calls to subresource data provider have been recorded.', $tabContent->html()); - - // Data persiters tab - $this->assertStringContainsString('No calls to data persister have been recorded.', $crawler->filter('.tab:nth-of-type(3) .tab-content .empty')->html()); - } -} diff --git a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php b/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php deleted file mode 100644 index 170fab26d65..00000000000 --- a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php +++ /dev/null @@ -1,62 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Identifier\Normalizer; - -use ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UlidNormalizer; -use ApiPlatform\Exception\InvalidIdentifierException; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Uid\AbstractUid; -use Symfony\Component\Uid\Ulid; - -final class UlidNormalizerTest extends TestCase -{ - protected function setUp(): void - { - if (!class_exists(AbstractUid::class)) { - $this->markTestSkipped(); - } - } - - public function testDenormalizeUlid() - { - $ulid = new Ulid(); - $normalizer = new UlidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($ulid->__toString(), Ulid::class)); - $this->assertEquals($ulid, $normalizer->denormalize($ulid->__toString(), Ulid::class)); - } - - public function testNoSupportDenormalizeUlid() - { - $ulid = 'notanulid'; - $normalizer = new UlidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($ulid, '')); - } - - public function testFailDenormalizeUlid() - { - $this->expectException(InvalidIdentifierException::class); - - $ulid = 'notanulid'; - $normalizer = new UlidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($ulid, Ulid::class)); - $normalizer->denormalize($ulid, Ulid::class); - } - - public function testDoNotSupportNotString() - { - $ulid = new Ulid(); - $normalizer = new UlidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($ulid, Ulid::class)); - } -} diff --git a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php b/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php deleted file mode 100644 index 32c124a72ad..00000000000 --- a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php +++ /dev/null @@ -1,62 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Identifier\Normalizer; - -use ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UuidNormalizer; -use ApiPlatform\Exception\InvalidIdentifierException; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Uid\AbstractUid; -use Symfony\Component\Uid\Uuid; - -final class UuidNormalizerTest extends TestCase -{ - protected function setUp(): void - { - if (!class_exists(AbstractUid::class)) { - $this->markTestSkipped(); - } - } - - public function testDenormalizeUuid() - { - $uuid = Uuid::v4(); - $normalizer = new UuidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($uuid->__toString(), Uuid::class)); - $this->assertEquals($uuid, $normalizer->denormalize($uuid->__toString(), Uuid::class)); - } - - public function testNoSupportDenormalizeUuid() - { - $uuid = 'notanuuid'; - $normalizer = new UuidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($uuid, '')); - } - - public function testFailDenormalizeUuid() - { - $this->expectException(InvalidIdentifierException::class); - - $uuid = 'notanuuid'; - $normalizer = new UuidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($uuid, Uuid::class)); - $normalizer->denormalize($uuid, Uuid::class); - } - - public function testDoNotSupportNotString() - { - $uuid = Uuid::v4(); - $normalizer = new UuidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($uuid, Uuid::class)); - } -} diff --git a/tests/Core/Bridge/Symfony/Maker/MakeDataPersisterTest.php b/tests/Core/Bridge/Symfony/Maker/MakeDataPersisterTest.php deleted file mode 100644 index 12cc2aa2785..00000000000 --- a/tests/Core/Bridge/Symfony/Maker/MakeDataPersisterTest.php +++ /dev/null @@ -1,187 +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); - -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Filesystem\Filesystem; - -class MakeDataPersisterTest extends KernelTestCase -{ - protected function tearDown(): void - { - (new Filesystem())->remove(self::tempDir()); - parent::tearDown(); - } - - /** @dataProvider dataPersisterProvider */ - public function testMakeDataPersister(array $commandInputs, array $userInputs, string $expected) - { - $this->assertFileDoesNotExist(self::tempFile('src/DataPersister/CustomDataPersister.php')); - - $tester = new CommandTester((new Application(self::bootKernel()))->find('make:data-persister')); - $tester->setInputs($userInputs); - $tester->execute($commandInputs); - - $this->assertFileExists(self::tempFile('src/DataPersister/CustomDataPersister.php')); - - // Unify line endings - $expected = preg_replace('~\R~u', "\r\n", $expected); - $result = preg_replace('~\R~u', "\r\n", file_get_contents(self::tempFile('src/DataPersister/CustomDataPersister.php'))); - $this->assertSame($expected, $result); - - $display = $tester->getDisplay(); - $this->assertStringContainsString('Success!', $display); - - if (!isset($commandInputs['name'])) { - $this->assertStringContainsString('Choose a class name for your data persister (e.g. AwesomeDataPersister):', $display); - } else { - $this->assertStringNotContainsString('Choose a class name for your data persister (e.g. AwesomeDataPersister):', $display); - } - if (!isset($commandInputs['resource-class'])) { - $this->assertStringContainsString('Choose a Resource class:', $display); - } else { - $this->assertStringNotContainsString('Choose a Resource class:', $display); - } - $this->assertStringContainsString(<< [ - [], - ['CustomDataPersister', ''], - \PHP_VERSION_ID >= 70200 ? $expected : str_replace(': object', '', $expected), - ]; - - $expected = <<<'EOF' - [ - [], - ['CustomDataPersister', Question::class], - $expected, - ]; - - yield 'Generate data persister with resource class not interactively' => [ - ['name' => 'CustomDataPersister', 'resource-class' => Question::class], - [], - $expected, - ]; - } - - private static function tempDir(): string - { - return __DIR__.'/../../../../Fixtures/app/var/tmp'; - } - - private static function tempFile(string $path): string - { - return sprintf('%s/%s', self::tempDir(), $path); - } -} diff --git a/tests/Core/Bridge/Symfony/Maker/MakeDataProviderTest.php b/tests/Core/Bridge/Symfony/Maker/MakeDataProviderTest.php deleted file mode 100644 index 5dfc87c52d0..00000000000 --- a/tests/Core/Bridge/Symfony/Maker/MakeDataProviderTest.php +++ /dev/null @@ -1,332 +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); - -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException; -use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Filesystem\Filesystem; - -class MakeDataProviderTest extends KernelTestCase -{ - protected function tearDown(): void - { - (new Filesystem())->remove(self::tempDir()); - parent::tearDown(); - } - - /** @dataProvider dataProviderProvider */ - public function testMakeDataProvider(array $commandInputs, array $userInputs, string $expected) - { - $this->assertFileDoesNotExist(self::tempFile('src/DataProvider/CustomDataProvider.php')); - - $tester = new CommandTester((new Application(self::bootKernel()))->find('make:data-provider')); - $tester->setInputs($userInputs); - $tester->execute($commandInputs); - - $this->assertFileExists(self::tempFile('src/DataProvider/CustomDataProvider.php')); - - // Unify line endings - $expected = preg_replace('~\R~u', "\r\n", $expected); - $result = preg_replace('~\R~u', "\r\n", file_get_contents(self::tempFile('src/DataProvider/CustomDataProvider.php'))); - $this->assertSame($expected, $result); - - $display = $tester->getDisplay(); - $this->assertStringContainsString('Success!', $display); - - if (!isset($commandInputs['name'])) { - $this->assertStringContainsString('Choose a class name for your data provider (e.g. AwesomeDataProvider):', $display); - } else { - $this->assertStringNotContainsString('Choose a class name for your data provider (e.g. AwesomeDataProvider):', $display); - } - if (!isset($commandInputs['resource-class'])) { - $this->assertStringContainsString(' Choose a Resource class:', $display); - } else { - $this->assertStringNotContainsString('Choose a Resource class:', $display); - } - - $this->assertStringContainsString(<< [ - [], - ['CustomDataProvider', ''], - \PHP_VERSION_ID >= 70200 ? $expected : str_replace(': ?object', '', $expected), - ]; - - $expected = <<<'EOF' - [ - [], - ['CustomDataProvider', Question::class], - $expected, - ]; - - yield 'Generate all with resource class not interactively' => [ - ['name' => 'CustomDataProvider', 'resource-class' => Question::class], - [], - $expected, - ]; - - $expected = <<<'EOF' - [ - ['--item-only' => true], - ['CustomDataProvider', ''], - \PHP_VERSION_ID >= 70200 ? $expected : str_replace(': ?object', '', $expected), - ]; - - $expected = <<<'EOF' - [ - ['--item-only' => true], - ['CustomDataProvider', Question::class], - $expected, - ]; - - yield 'Generate an item data provider with a resource class not interactively' => [ - ['name' => 'CustomDataProvider', 'resource-class' => Question::class, '--item-only' => true], - [], - $expected, - ]; - - $expected = <<<'EOF' - [ - ['--collection-only' => true], - ['CustomDataProvider', ''], - $expected, - ]; - - $expected = <<<'EOF' - [ - ['--collection-only' => true], - ['CustomDataProvider', Question::class], - $expected, - ]; - - yield 'Generate a collection data provider with a resource class not interactively' => [ - ['name' => 'CustomDataProvider', 'resource-class' => Question::class, '--collection-only' => true], - [], - $expected, - ]; - } - - public function testMakeDataProviderThrows() - { - $tester = new CommandTester((new Application(self::bootKernel()))->find('make:data-provider')); - $this->expectException(RuntimeCommandException::class); - $this->expectExceptionMessage('You should at least generate an item or a collection data provider'); - - $tester->execute(['name' => 'CustomDataProvider', 'resource-class' => Question::class, '--collection-only' => true, '--item-only' => true]); - } - - private static function tempDir(): string - { - return __DIR__.'/../../../../Fixtures/app/var/tmp'; - } - - private static function tempFile(string $path): string - { - return sprintf('%s/%s', self::tempDir(), $path); - } -} diff --git a/tests/Core/Bridge/Symfony/Messenger/DataPersisterTest.php b/tests/Core/Bridge/Symfony/Messenger/DataPersisterTest.php deleted file mode 100644 index 983fa78db75..00000000000 --- a/tests/Core/Bridge/Symfony/Messenger/DataPersisterTest.php +++ /dev/null @@ -1,107 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Messenger; - -use ApiPlatform\Core\Bridge\Symfony\Messenger\DataPersister; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Symfony\Messenger\ContextStamp; -use ApiPlatform\Symfony\Messenger\RemoveStamp; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Messenger\Stamp\HandledStamp; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class DataPersisterTest extends TestCase -{ - use ProphecyTrait; - - public function testSupport() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); - - $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal()); - $this->assertTrue($dataPersister->supports(new Dummy())); - } - - public function testSupportWithContext() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); - $metadataFactoryProphecy->create(DummyCar::class)->willThrow(new ResourceClassNotFoundException()); - - $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal()); - $this->assertTrue($dataPersister->supports(new DummyCar(), ['resource_class' => Dummy::class])); - $this->assertFalse($dataPersister->supports(new DummyCar())); - } - - public function testPersist() - { - $dummy = new Dummy(); - - $messageBus = $this->prophesize(MessageBusInterface::class); - $messageBus->dispatch(Argument::that(function (Envelope $envelope) use ($dummy) { - return $dummy === $envelope->getMessage() && null !== $envelope->last(ContextStamp::class); - }))->willReturn(new Envelope($dummy))->shouldBeCalled(); - - $dataPersister = new DataPersister($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), $messageBus->reveal()); - $this->assertSame($dummy, $dataPersister->persist($dummy)); - } - - public function testRemove() - { - $dummy = new Dummy(); - - $messageBus = $this->prophesize(MessageBusInterface::class); - - $messageBus->dispatch(Argument::that(function (Envelope $envelope) use ($dummy) { - return $dummy === $envelope->getMessage() && null !== $envelope->last(RemoveStamp::class); - }))->willReturn(new Envelope($dummy))->shouldBeCalled(); - - $dataPersister = new DataPersister($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), $messageBus->reveal()); - $dataPersister->remove($dummy); - } - - public function testHandle() - { - $dummy = new Dummy(); - - $messageBus = $this->prophesize(MessageBusInterface::class); - $messageBus->dispatch(Argument::that(function (Envelope $envelope) use ($dummy) { - return $dummy === $envelope->getMessage() && null !== $envelope->last(ContextStamp::class); - }))->willReturn((new Envelope($dummy))->with(new HandledStamp($dummy, 'DummyHandler::__invoke')))->shouldBeCalled(); - - $dataPersister = new DataPersister($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), $messageBus->reveal()); - $this->assertSame($dummy, $dataPersister->persist($dummy)); - } - - public function testSupportWithGraphqlContext() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata(null, null, null, null, null, []))->withGraphQl(['create' => ['messenger' => 'input']])); - - $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal()); - $this->assertTrue($dataPersister->supports(new DummyCar(), ['resource_class' => Dummy::class, 'graphql_operation_name' => 'create'])); - } -} diff --git a/tests/Core/Bridge/Symfony/Messenger/DataTransformerTest.php b/tests/Core/Bridge/Symfony/Messenger/DataTransformerTest.php deleted file mode 100644 index d7b7ab5e78d..00000000000 --- a/tests/Core/Bridge/Symfony/Messenger/DataTransformerTest.php +++ /dev/null @@ -1,101 +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); - -namespace ApiPlatform\Tests\Symfony\Messenger; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Messenger\DataTransformer; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class DataTransformerTest extends TestCase -{ - use ProphecyTrait; - - public function testSupport() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertTrue($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth']])); - } - - public function testSupportWithinRequest() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['foo' => ['messenger' => 'input']], null, [])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertTrue($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth'], 'operation_type' => OperationType::ITEM, 'item_operation_name' => 'foo'])); - } - - public function testNoSupport() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertFalse($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth']])); - } - - public function testNoSupportWithinRequest() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['foo' => ['messenger' => true]], null, [])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertFalse($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth'], 'operation_type' => OperationType::ITEM, 'item_operation_name' => 'foo'])); - } - - public function testNoSupportWithoutInput() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertFalse($dataTransformer->supportsTransformation([], Dummy::class, [])); - } - - public function testNoSupportWithObject() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertFalse($dataTransformer->supportsTransformation(new Dummy(), Dummy::class, [])); - } - - public function testTransform() - { - $dummy = new Dummy(); - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertSame($dummy, $dataTransformer->transform($dummy, Dummy::class)); - } - - public function testSupportWithGraphqlContext() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata(null, null, null, null, null, []))->withGraphQl(['create' => ['messenger' => 'input']])); - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertTrue($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth'], 'graphql_operation_name' => 'create'])); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php b/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php deleted file mode 100644 index a38b5033507..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php +++ /dev/null @@ -1,361 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidResourceException; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; -use ApiPlatform\Symfony\Routing\ApiLoader; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use ApiPlatform\Tests\Fixtures\RelatedDummyEntity; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Routing\Route; - -/** - * @author Antoine Bluchet - * @author Amrouche Hamza - * - * @group legacy - */ -class ApiLoaderTest extends TestCase -{ - use ProphecyTrait; - - public function testLegacyApiLoader() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - $resourceMetadata = $resourceMetadata->withAttributes(['identifiers' => 'id']); - // default operation based on OperationResourceMetadataFactory - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => ['method' => 'GET', 'requirements' => ['id' => '\d+'], 'defaults' => ['my_default' => 'default_value', '_controller' => 'should_not_be_overriden'], 'stateless' => null], - 'put' => ['method' => 'PUT', 'stateless' => null], - 'delete' => ['method' => 'DELETE', 'stateless' => null], - ]); - // custom operations - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'my_op' => ['method' => 'GET', 'controller' => 'some.service.name', 'requirements' => ['_format' => 'a valid format'], 'defaults' => ['my_default' => 'default_value', '_format' => 'a valid format'], 'condition' => "request.headers.get('User-Agent') matches '/firefox/i'", 'stateless' => null], // with controller - 'my_second_op' => ['method' => 'POST', 'options' => ['option' => 'option_value'], 'host' => '{subdomain}.api-platform.com', 'schemes' => ['https'], 'stateless' => null], // without controller, takes the default one - 'my_path_op' => ['method' => 'GET', 'path' => 'some/custom/path', 'stateless' => null], // custom path - 'my_stateless_op' => ['method' => 'GET', 'stateless' => true], - ]); - $resourceMetadata = $resourceMetadata->withSubresourceOperations([ - 'subresources_get_subresource' => ['stateless' => true], - ]); - - $routeCollection = $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); - - $this->assertEquals( - $this->getRoute('/dummies/{id}.{_format}', 'api_platform.action.get_item', DummyEntity::class, 'api_dummies_get_item', ['GET'], false, ['id' => '\d+'], ['my_default' => 'default_value', '_stateless' => null]), - $routeCollection->get('api_dummies_get_item') - ); - - $this->assertEquals( - $this->getRoute('/dummies/{id}.{_format}', 'api_platform.action.delete_item', DummyEntity::class, 'api_dummies_delete_item', ['DELETE']), - $routeCollection->get('api_dummies_delete_item') - ); - - $this->assertEquals( - $this->getRoute('/dummies/{id}.{_format}', 'api_platform.action.put_item', DummyEntity::class, 'api_dummies_put_item', ['PUT']), - $routeCollection->get('api_dummies_put_item') - ); - - $this->assertEquals( - $this->getRoute('/dummies.{_format}', 'some.service.name', DummyEntity::class, 'api_dummies_my_op_collection', ['GET'], true, ['_format' => 'a valid format'], ['my_default' => 'default_value', '_format' => 'a valid format', '_stateless' => null], [], '', [], "request.headers.get('User-Agent') matches '/firefox/i'"), - $routeCollection->get('api_dummies_my_op_collection') - ); - - $this->assertEquals( - $this->getRoute('/dummies.{_format}', 'api_platform.action.post_collection', DummyEntity::class, 'api_dummies_my_second_op_collection', ['POST'], true, [], ['_stateless' => null], ['option' => 'option_value'], '{subdomain}.api-platform.com', ['https']), - $routeCollection->get('api_dummies_my_second_op_collection') - ); - - $this->assertEquals( - $this->getRoute('/some/custom/path', 'api_platform.action.get_collection', DummyEntity::class, 'api_dummies_my_path_op_collection', ['GET'], true), - $routeCollection->get('api_dummies_my_path_op_collection') - ); - - $this->assertEquals( - $this->getRoute('/dummies.{_format}', 'api_platform.action.get_collection', DummyEntity::class, 'api_dummies_my_stateless_op_collection', ['GET'], true, [], ['_stateless' => true]), - $routeCollection->get('api_dummies_my_stateless_op_collection') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/dummies/{id}/subresources.{_format}', 'api_platform.action.get_subresource', RelatedDummyEntity::class, 'api_dummies_subresources_get_subresource', ['property' => 'subresource', 'identifiers' => ['id' => [DummyEntity::class, 'id', true]], 'collection' => true, 'operationId' => 'api_dummies_subresources_get_subresource'], [], ['_stateless' => true]), - $routeCollection->get('api_dummies_subresources_get_subresource') - ); - } - - public function testApiLoaderWithPrefix() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => ['method' => 'GET', 'requirements' => ['id' => '\d+'], 'defaults' => ['my_default' => 'default_value', '_controller' => 'should_not_be_overriden'], 'stateless' => null], - 'put' => ['method' => 'PUT', 'stateless' => null], - 'delete' => ['method' => 'DELETE', 'stateless' => null], - ]); - $resourceMetadata = $resourceMetadata->withAttributes(['route_prefix' => '/foobar-prefix', 'identifiers' => 'id']); - - $routeCollection = $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); - - $this->assertEquals( - $this->getRoute('/foobar-prefix/dummies/{id}.{_format}', 'api_platform.action.get_item', DummyEntity::class, 'api_dummies_get_item', ['GET'], false, ['id' => '\d+'], ['my_default' => 'default_value', '_stateless' => null]), - $routeCollection->get('api_dummies_get_item') - ); - - $this->assertEquals( - $this->getRoute('/foobar-prefix/dummies/{id}.{_format}', 'api_platform.action.delete_item', DummyEntity::class, 'api_dummies_delete_item', ['DELETE']), - $routeCollection->get('api_dummies_delete_item') - ); - - $this->assertEquals( - $this->getRoute('/foobar-prefix/dummies/{id}.{_format}', 'api_platform.action.put_item', DummyEntity::class, 'api_dummies_put_item', ['PUT']), - $routeCollection->get('api_dummies_put_item') - ); - } - - public function testNoMethodApiLoader() - { - $this->expectException(\RuntimeException::class); - - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => [], - ]); - - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'get' => ['method' => 'GET', 'stateless' => null], - ]); - - $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); - } - - public function testWrongMethodApiLoader() - { - $this->expectException(\RuntimeException::class); - - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'post' => ['method' => 'POST', 'stateless' => null], - ]); - - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'get' => ['method' => 'GET', 'stateless' => null], - ]); - - $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); - } - - public function testNoShortNameApiLoader() - { - $this->expectException(InvalidResourceException::class); - - $this->getApiLoaderWithResourceMetadata(new ResourceMetadata())->load(null); - } - - public function testRecursiveSubresource() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => ['method' => 'GET', 'stateless' => null], - 'put' => ['method' => 'PUT', 'stateless' => null], - 'delete' => ['method' => 'DELETE', 'stateless' => null], - ]); - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'my_op' => ['method' => 'GET', 'controller' => 'some.service.name', 'stateless' => null], // with controller - 'my_second_op' => ['method' => 'POST', 'stateless' => null], // without controller, takes the default one - 'my_path_op' => ['method' => 'GET', 'path' => 'some/custom/path', 'stateless' => null], // custom path - ]); - - $routeCollection = $this->getApiLoaderWithResourceMetadata($resourceMetadata, true)->load(null); - - $this->assertEquals( - $this->getSubresourceRoute('/dummies/{id}/subresources.{_format}', 'api_platform.action.get_subresource', RelatedDummyEntity::class, 'api_dummies_subresources_get_subresource', ['property' => 'subresource', 'identifiers' => ['id' => [DummyEntity::class, 'id', true]], 'collection' => true, 'operationId' => 'api_dummies_subresources_get_subresource']), - $routeCollection->get('api_dummies_subresources_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/related_dummies/{id}/recursivesubresource/subresources.{_format}', 'api_platform.action.get_subresource', RelatedDummyEntity::class, 'api_related_dummies_recursivesubresource_subresources_get_subresource', ['property' => 'subresource', 'identifiers' => ['id' => [RelatedDummyEntity::class, 'id', true], 'recursivesubresource' => [DummyEntity::class, 'id', false]], 'collection' => true, 'operationId' => 'api_related_dummies_recursivesubresource_subresources_get_subresource']), - $routeCollection->get('api_related_dummies_recursivesubresource_subresources_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/related_dummies/{id}/recursivesubresource.{_format}', 'dummy_controller', DummyEntity::class, 'api_related_dummies_recursivesubresource_get_subresource', ['property' => 'recursivesubresource', 'identifiers' => ['id' => [RelatedDummyEntity::class, 'id', true]], 'collection' => false, 'operationId' => 'api_related_dummies_recursivesubresource_get_subresource']), - $routeCollection->get('api_related_dummies_recursivesubresource_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/dummies/{id}/subresources/{subresource}/recursivesubresource.{_format}', 'api_platform.action.get_subresource', DummyEntity::class, 'api_dummies_subresources_recursivesubresource_get_subresource', ['property' => 'recursivesubresource', 'identifiers' => ['id' => [DummyEntity::class, 'id', true], 'subresource' => [RelatedDummyEntity::class, 'id', true]], 'collection' => false, 'operationId' => 'api_dummies_subresources_recursivesubresource_get_subresource']), - $routeCollection->get('api_dummies_subresources_recursivesubresource_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/related_dummies/{id}/secondrecursivesubresource/subresources.{_format}', 'api_platform.action.get_subresource', RelatedDummyEntity::class, 'api_related_dummies_secondrecursivesubresource_subresources_get_subresource', ['property' => 'subresource', 'identifiers' => ['id' => [RelatedDummyEntity::class, 'id', true], 'secondrecursivesubresource' => [DummyEntity::class, 'id', false]], 'collection' => true, 'operationId' => 'api_related_dummies_secondrecursivesubresource_subresources_get_subresource']), - $routeCollection->get('api_related_dummies_secondrecursivesubresource_subresources_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/related_dummies/{id}/secondrecursivesubresource.{_format}', 'api_platform.action.get_subresource', DummyEntity::class, 'api_related_dummies_secondrecursivesubresource_get_subresource', ['property' => 'secondrecursivesubresource', 'identifiers' => ['id' => [RelatedDummyEntity::class, 'id', true]], 'collection' => false, 'operationId' => 'api_related_dummies_secondrecursivesubresource_get_subresource']), - $routeCollection->get('api_related_dummies_secondrecursivesubresource_get_subresource') - ); - } - - private function getApiLoaderWithResourceMetadata(ResourceMetadata $resourceMetadata, $recursiveSubresource = false): ApiLoader - { - $routingConfig = __DIR__.'/../../../../../src/Symfony/Bundle/Resources/config/routing'; - - $kernelProphecy = $this->prophesize(KernelInterface::class); - $kernelProphecy->locateResource(Argument::any())->willReturn($routingConfig); - $possibleArguments = [ - 'api_platform.action.get_collection', - 'api_platform.action.post_collection', - 'api_platform.action.get_item', - 'api_platform.action.put_item', - 'api_platform.action.delete_item', - 'api_platform.action.get_subresource', - ]; - $containerProphecy = $this->prophesize(ContainerInterface::class); - - foreach ($possibleArguments as $possibleArgument) { - $containerProphecy->has($possibleArgument)->willReturn(true); - } - - $containerProphecy->has(Argument::type('string'))->willReturn(false); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata); - - $relatedDummyEntityMetadata = (new ResourceMetadata())->withShortName('related_dummies')->withSubresourceOperations([ - 'recursivesubresource_get_subresource' => [ - 'controller' => 'dummy_controller', - ], - ]); - - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->willReturn($relatedDummyEntityMetadata); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([DummyEntity::class, RelatedDummyEntity::class])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->willReturn(new PropertyNameCollection(['id', 'subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->willReturn(new PropertyNameCollection(['id', 'recursivesubresource', 'secondrecursivesubresource'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata()); - - $relatedType = new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummyEntity::class); - - $subResourcePropertyMetadata = (new PropertyMetadata()) - ->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, true)) - ->withType(new Type(Type::BUILTIN_TYPE_ARRAY, false, \ArrayObject::class, true, null, $relatedType)); - - if (false === $recursiveSubresource) { - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'recursivesubresource', Argument::type('array'))->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'secondrecursivesubresource', Argument::type('array'))->willReturn(new PropertyMetadata()); - } else { - $dummyType = new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyEntity::class); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'recursivesubresource', Argument::type('array')) - ->willReturn((new PropertyMetadata()) - ->withSubresource(new SubresourceMetadata(DummyEntity::class, false)) - ->withType($dummyType)); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'secondrecursivesubresource', Argument::type('array')) - ->willReturn((new PropertyMetadata()) - ->withSubresource(new SubresourceMetadata(DummyEntity::class, false)) - ->withType($dummyType)); - } - - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->willReturn($subResourcePropertyMetadata); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - $identifiersExtractor = $identifiersExtractorProphecy->reveal(); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactory, $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), new UnderscorePathSegmentNameGenerator(), $identifiersExtractor); - - return new ApiLoader($kernelProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactory, $operationPathResolver, $containerProphecy->reveal(), ['jsonld' => ['application/ld+json']], [], $subresourceOperationFactory, false, true, true, false, false, $identifiersExtractor); - } - - private function getRoute(string $path, string $controller, string $resourceClass, string $operationName, array $methods, bool $collection = false, array $requirements = [], array $extraDefaults = ['_stateless' => null], array $options = [], string $host = '', array $schemes = [], string $condition = ''): Route - { - $legacyOperationName = str_replace('api_dummies_', '', str_replace($collection ? '_collection' : '_item', '', $operationName)); - - return new Route( - $path, - [ - '_controller' => $controller, - '_format' => $extraDefaults['_format'] ?? null, - '_api_resource_class' => $resourceClass, - '_api_identifiers' => ['id'], - '_api_has_composite_identifier' => false, - sprintf('_api_%s_operation_name', $collection ? 'collection' : 'item') => $legacyOperationName, - '_api_operation_name' => $operationName, - ] + $extraDefaults, - $requirements, - $options, - $host, - $schemes, - $methods, - $condition - ); - } - - private function getSubresourceRoute(string $path, string $controller, string $resourceClass, string $operationName, array $context, array $requirements = [], array $extraDefaults = ['_stateless' => null]): Route - { - return new Route( - $path, - [ - '_controller' => $controller, - '_format' => $extraDefaults['_format'] ?? null, - '_api_resource_class' => $resourceClass, - '_api_subresource_operation_name' => $operationName, - '_api_subresource_context' => $context, - '_api_identifiers' => $context['identifiers'], - '_api_has_composite_identifier' => false, - ] + $extraDefaults, - $requirements, - [], - '', - [], - ['GET'] - ); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/CachedRouteNameResolverTest.php b/tests/Core/Bridge/Symfony/Routing/CachedRouteNameResolverTest.php deleted file mode 100644 index 1c4b0f59252..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/CachedRouteNameResolverTest.php +++ /dev/null @@ -1,178 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\CachedRouteNameResolver; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @author Teoh Han Hui - */ -class CachedRouteNameResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertInstanceOf(RouteNameResolverInterface::class, $cachedRouteNameResolver); - } - - public function testGetRouteNameForItemRouteWithNoMatchingRoute() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No item route associated with the type "AppBundle\\Entity\\User".'); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(false)->shouldBeCalled(); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldNotBeCalled(); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', OperationType::ITEM, []) - ->willThrow(new InvalidArgumentException('No item route associated with the type "AppBundle\Entity\User".')) - ->shouldBeCalled(); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM); - } - - public function testGetRouteNameForItemRouteOnCacheMiss() - { - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(false)->shouldBeCalledTimes(1); - $cacheItemProphecy->set('some_item_route')->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy->reveal()); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldBeCalledTimes(1)->willReturn(true); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', false, [])->willReturn('some_item_route')->shouldBeCalledTimes(1); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', false)); - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', false), 'Trigger the local cache'); - } - - public function testGetRouteNameForItemRouteOnCacheHit() - { - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->shouldBeCalledTimes(1)->willReturn(true); - $cacheItemProphecy->get()->shouldBeCalledTimes(1)->willReturn('some_item_route'); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldNotBeCalled(); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName(Argument::cetera())->shouldNotBeCalled(); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM)); - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM), 'Trigger the local cache'); - } - - public function testGetRouteNameForCollectionRouteWithNoMatchingRoute() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No collection route associated with the type "AppBundle\\Entity\\User".'); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(false)->shouldBeCalled(); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldNotBeCalled(); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION, []) - ->willThrow(new InvalidArgumentException('No collection route associated with the type "AppBundle\Entity\User".')) - ->shouldBeCalled(); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION); - } - - public function testGetRouteNameForCollectionRouteOnCacheMiss() - { - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->shouldBeCalledTimes(1)->willReturn(false); - $cacheItemProphecy->set('some_collection_route')->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy->reveal()); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldBeCalledTimes(1)->willReturn(true); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', true, [])->willReturn('some_collection_route')->shouldBeCalledTimes(1); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_collection_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', true)); - $this->assertSame('some_collection_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', true), 'Trigger the local cache'); - } - - public function testGetRouteNameForCollectionRouteOnCacheHit() - { - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(true)->shouldBeCalledTimes(1); - $cacheItemProphecy->get()->willReturn('some_collection_route')->shouldBeCalledTimes(1); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldNotBeCalled(); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName(Argument::cetera())->shouldNotBeCalled(); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_collection_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION)); - $this->assertSame('some_collection_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION), 'Trigger the local cache'); - } - - public function testGetRouteNameWithCacheItemThrowsCacheException() - { - $cacheException = new class() extends \Exception implements CacheException {}; - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willThrow($cacheException); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', OperationType::ITEM, [])->willReturn('some_item_route')->shouldBeCalledTimes(1); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPool->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM)); - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM), 'Trigger the local cache'); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/IriConverterTest.php b/tests/Core/Bridge/Symfony/Routing/IriConverterTest.php deleted file mode 100644 index f215880d50a..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/IriConverterTest.php +++ /dev/null @@ -1,453 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Routing; - -use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IdentifiersExtractor; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\IriConverter; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameResolverInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\ItemNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RouterInterface; - -/** - * @author Vincent Chalamon - * @group legacy - */ -class IriConverterTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function testGetItemFromIriNoRouteException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No route matches "/users/3".'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willThrow(new RouteNotFoundException())->shouldBeCalledTimes(1); - $converter = $this->getIriConverter($routerProphecy); - $converter->getItemFromIri('/users/3'); - } - - public function testGetItemFromIriNoResourceException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No resource associated to "/users/3".'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy); - $converter->getItemFromIri('/users/3'); - } - - public function testGetItemFromIriCollectionRouteException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The iri "/users" references a collection not an item.'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_collection_operation_name' => 'get', - '_api_identifiers' => ['id'], - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy); - $converter->getItemFromIri('/users'); - } - - public function testGetItemFromIriItemNotFoundException() - { - $this->expectException(ItemNotFoundException::class); - $this->expectExceptionMessage('Item not found for "/users/3".'); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy - ->getItem(Dummy::class, ['id' => 3], 'get', [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]) - ->shouldBeCalled()->willReturn(null); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_item_operation_name' => 'get', - '_api_identifiers' => ['id'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy); - $converter->getItemFromIri('/users/3'); - } - - public function testGetItemFromIri() - { - $item = new \stdClass(); - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(Dummy::class, ['id' => 3], 'get', ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->shouldBeCalled()->willReturn($item); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_item_operation_name' => 'get', - '_api_identifiers' => ['id'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item); - } - - public function testGetItemFromIriWithOperationName() - { - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem('AppBundle\Entity\User', ['id' => 3], 'operation_name', ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]) - ->willReturn('foo') - ->shouldBeCalledTimes(1); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'operation_name', - '_api_identifiers' => ['id'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), 'foo'); - } - - public function testGetIriFromResourceClass() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::COLLECTION)->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', [], UrlGeneratorInterface::ABS_PATH)->willReturn('/dummies'); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - $this->assertEquals($converter->getIriFromResourceClass(Dummy::class), '/dummies'); - } - - public function testGetIriFromResourceClassAbsoluteUrl() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::COLLECTION)->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', [], UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('', '', '', [], [], ['url_generation_strategy' => UrlGeneratorInterface::ABS_URL])); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); - $this->assertEquals($converter->getIriFromResourceClass(Dummy::class), 'http://example.com/dummies'); - } - - public function testNotAbleToGenerateGetIriFromResourceClass() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Unable to generate an IRI for "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy"'); - - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::COLLECTION)->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', [], UrlGeneratorInterface::ABS_PATH)->willThrow(new RouteNotFoundException()); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - $converter->getIriFromResourceClass(Dummy::class); - } - - /** - * @group legacy - */ - public function testGetSubresourceIriFromResourceClass() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::SUBRESOURCE, Argument::type('array'))->willReturn('api_dummies_related_dummies_get_subresource'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('api_dummies_related_dummies_get_subresource', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willReturn('/dummies/1/related_dummies'); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - $this->assertEquals($converter->getSubresourceIriFromResourceClass(Dummy::class, ['subresource_identifiers' => ['id' => 1], 'subresource_resources' => [RelatedDummy::class => 1]]), '/dummies/1/related_dummies'); - } - - /** - * @group legacy - */ - public function testNotAbleToGenerateGetSubresourceIriFromResourceClass() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Unable to generate an IRI for "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy"'); - - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::SUBRESOURCE, Argument::type('array'))->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willThrow(new RouteNotFoundException()); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - $converter->getSubresourceIriFromResourceClass(Dummy::class, ['subresource_identifiers' => ['id' => 1], 'subresource_resources' => [RelatedDummy::class => 1]]); - } - - /** - * @group legacy - */ - public function testGetItemIriFromResourceClass() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::ITEM)->willReturn('api_dummies_get_item'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('api_dummies_get_item', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willReturn('/dummies/1'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['composite_identifier' => true])); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); - $this->assertEquals($converter->getItemIriFromResourceClass(Dummy::class, ['id' => 1]), '/dummies/1'); - } - - /** - * @group legacy - */ - public function testGetItemIriFromResourceClassAbsoluteUrl() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::ITEM)->willReturn('api_dummies_get_item'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('api_dummies_get_item', ['id' => 1], UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies/1'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('', '', '', [], [], ['url_generation_strategy' => UrlGeneratorInterface::ABS_URL])); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); - $this->assertEquals($converter->getItemIriFromResourceClass(Dummy::class, ['id' => 1]), 'http://example.com/dummies/1'); - } - - /** - * @group legacy - */ - public function testNotAbleToGenerateGetItemIriFromResourceClass() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Unable to generate an IRI for "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy"'); - - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::ITEM)->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willThrow(new RouteNotFoundException()); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['composite_identifier' => true])); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); - $converter->getItemIriFromResourceClass(Dummy::class, ['id' => 1]); - } - - public function testGetItemFromIriWithIdentifierConverter() - { - $item = new \stdClass(); - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(Dummy::class, ['id' => 3], 'get', ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->shouldBeCalled()->willReturn($item); - $identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverterProphecy->convert(['id' => '3'], Dummy::class)->shouldBeCalled()->willReturn(['id' => 3]); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_item_operation_name' => 'get', - '_api_identifiers' => ['id' => [Dummy::class, 'id']], - 'id' => 3, - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy, null, $identifierConverterProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item); - } - - public function testGetItemFromIriWithSubresourceDataProvider() - { - $item = new \stdClass(); - $subresourceContext = ['identifiers' => ['id' => [Dummy::class, 'id', true]]]; - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3/adresses')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_subresource_context' => $subresourceContext, - '_api_subresource_operation_name' => 'get_subresource', - '_api_identifiers' => $subresourceContext['identifiers'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - $subresourceDataProviderProphecy = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProviderProphecy->getSubresource(Dummy::class, ['id' => ['id' => 3]], $subresourceContext + ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true], 'get_subresource')->shouldBeCalled()->willReturn($item); - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $subresourceDataProviderProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3/adresses', ['fetch_data' => true]), $item); - } - - public function testGetItemFromIriWithSubresourceDataProviderNotFound() - { - $this->expectException(ItemNotFoundException::class); - $this->expectExceptionMessage('Item not found for "/users/3/adresses".'); - - $subresourceContext = ['identifiers' => ['id' => [Dummy::class, 'id', true]]]; - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3/adresses')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_subresource_context' => $subresourceContext, - '_api_subresource_operation_name' => 'get_subresource', - '_api_identifiers' => $subresourceContext['identifiers'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - $identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverterProphecy->convert(['id' => '3'], Dummy::class)->shouldBeCalled()->willReturn(['id' => 3]); - $subresourceDataProviderProphecy = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProviderProphecy->getSubresource(Dummy::class, ['id' => ['id' => 3]], $subresourceContext + ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true], 'get_subresource')->shouldBeCalled()->willReturn(null); - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $subresourceDataProviderProphecy, $identifierConverterProphecy); - $converter->getItemFromIri('/users/3/adresses', ['fetch_data' => true]); - } - - public function testGetItemFromIriBadIdentifierException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Item not found for "/users/3".'); - - $item = new \stdClass(); - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_item_operation_name' => 'get_subresource', - '_api_identifiers' => ['id'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - $identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverterProphecy->convert(['id' => '3'], Dummy::class)->shouldBeCalled()->willThrow(new InvalidIdentifierException('Item not found for "/users/3".')); - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, $identifierConverterProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item); - } - - public function testNoIdentifiersException() - { - $this->markTestSkipped('The method "generateIdentifiersUrl" has been removed.'); - /* @phpstan-ignore-next-line */ - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No identifiers defined for resource of type "\App\Entity\Sample"'); - - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - - $method = new \ReflectionMethod(IriConverter::class, 'generateIdentifiersUrl'); - $method->setAccessible(true); - $method->invoke($converter, [], '\App\Entity\Sample'); - } - - /** - * @group legacy - */ - public function testLegacyConstructor() - { - $this->expectDeprecation('Not injecting ApiPlatform\Core\Api\ResourceClassResolverInterface in the IdentifiersExtractor might introduce cache issues with object identifiers.'); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - - new IriConverter( - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $itemDataProviderProphecy->reveal(), - $routeNameResolverProphecy->reveal(), - $routerProphecy->reveal(), - null - ); - } - - private function getResourceClassResolver() - { - $resourceClassResolver = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolver->isResourceClass(Argument::type('string'))->will(function ($args) { - return true; - }); - - $resourceClassResolver->getResourceClass(Argument::cetera())->will(function ($args) { - return \get_class($args[0]); - }); - - return $resourceClassResolver->reveal(); - } - - private function getIriConverter($routerProphecy = null, $routeNameResolverProphecy = null, $itemDataProviderProphecy = null, $subresourceDataProviderProphecy = null, $identifierConverterProphecy = null, $resourceMetadataFactory = null) - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - if (!$routerProphecy) { - $routerProphecy = $this->prophesize(RouterInterface::class); - } - - if (!$routeNameResolverProphecy) { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - } - - $itemDataProvider = $itemDataProviderProphecy ?: $this->prophesize(ItemDataProviderInterface::class); - - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - if (null === $identifierConverterProphecy) { - $identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverterProphecy->convert(Argument::type('array'), Argument::type('string'))->will(function ($args) { - return $args[0]; - }); - } - - return new IriConverter( - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $itemDataProvider->reveal(), - $routeNameResolverProphecy->reveal(), - $routerProphecy->reveal(), - null, - new IdentifiersExtractor($propertyNameCollectionFactory, $propertyMetadataFactory, null, $this->getResourceClassResolver()), - $subresourceDataProviderProphecy ? $subresourceDataProviderProphecy->reveal() : null, - $identifierConverterProphecy->reveal(), - null, - $resourceMetadataFactory - ); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/RouteNameGeneratorTest.php b/tests/Core/Bridge/Symfony/Routing/RouteNameGeneratorTest.php deleted file mode 100644 index 0d3663e7669..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/RouteNameGeneratorTest.php +++ /dev/null @@ -1,48 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; - -/** - * @author Baptiste Meyer - */ -class RouteNameGeneratorTest extends TestCase -{ - public function testGenerate() - { - $this->assertEquals('api_foos_get_collection', RouteNameGenerator::generate('get', 'Foo', OperationType::COLLECTION)); - $this->assertEquals('api_bars_custom_operation_item', RouteNameGenerator::generate('custom_operation', 'Bar', OperationType::ITEM)); - } - - /** - * @group legacy - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testLegacyGenerate() - { - $this->assertEquals('api_foos_get_collection', RouteNameGenerator::generate('get', 'Foo', true)); - } - - public function testGenerateWithSubresource() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Subresource operations are not supported by the RouteNameGenerator.'); - - $this->assertEquals('api_foos_bar_get_subresource', RouteNameGenerator::generate('get', 'Foo', OperationType::SUBRESOURCE)); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/RouteNameResolverTest.php b/tests/Core/Bridge/Symfony/Routing/RouteNameResolverTest.php deleted file mode 100644 index 7f7ba96d33b..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/RouteNameResolverTest.php +++ /dev/null @@ -1,195 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameResolver; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; - -/** - * @author Teoh Han Hui - */ -class RouteNameResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $routerProphecy = $this->prophesize(RouterInterface::class); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - - $this->assertInstanceOf(RouteNameResolverInterface::class, $routeNameResolver); - } - - public function testGetRouteNameForItemRouteWithNoMatchingRoute() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('No item route associated with the type "AppBundle\\Entity\\User".'); - - $routeCollection = new RouteCollection(); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM); - } - - /** - * @group legacy - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testGetRouteNameForItemRouteLegacy() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', false); - - $this->assertSame('some_item_route', $actual); - } - - public function testGetRouteNameForItemRoute() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM); - - $this->assertSame('some_item_route', $actual); - } - - public function testGetRouteNameForCollectionRouteWithNoMatchingRoute() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('No collection route associated with the type "AppBundle\\Entity\\User".'); - - $routeCollection = new RouteCollection(); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION); - } - - /** - * @group legacy - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testGetRouteNameForCollectionRouteLegacy() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', true); - - $this->assertSame('some_collection_route', $actual); - } - - public function testGetRouteNameForCollectionRoute() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION); - - $this->assertSame('some_collection_route', $actual); - } - - public function testGetRouteNameForSubresourceRoute() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('a_some_subresource_route', new Route('/a/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_subresource_operation_name' => 'some_other_item_op', - '_api_subresource_context' => ['identifiers' => ['id' => ['Bar', 'id']]], - ])); - $routeCollection->add('b_some_subresource_route', new Route('/b/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_subresource_operation_name' => 'some_item_op', - '_api_subresource_context' => ['identifiers' => ['id' => ['Foo', 'id']]], - ])); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::SUBRESOURCE, ['subresource_resources' => ['Foo' => 1]]); - - $this->assertSame('b_some_subresource_route', $actual); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/RouterOperationPathResolverTest.php b/tests/Core/Bridge/Symfony/Routing/RouterOperationPathResolverTest.php deleted file mode 100644 index c8c72e99afc..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/RouterOperationPathResolverTest.php +++ /dev/null @@ -1,98 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; - -/** - * @author Baptiste Meyer - */ -class RouterOperationPathResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testResolveOperationPath() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('foos', new Route('/foos')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection)->shouldBeCalled(); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), $this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $this->assertEquals('/foos', $operationPathResolver->resolveOperationPath('Foo', ['route_name' => 'foos'], OperationType::COLLECTION, 'get')); - } - - public function testResolveOperationPathWithSubresource() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Subresource operations are not supported by the RouterOperationPathResolver without a route name.'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), $this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $operationPathResolver->resolveOperationPath('Foo', ['property' => 'bar', 'collection' => true, 'resource_class' => 'Foo'], OperationType::SUBRESOURCE, 'get'); - } - - public function testResolveOperationPathWithRouteNameGeneration() - { - $routeCollection = new RouteCollection(); - $routeCollection->add(RouteNameGenerator::generate('get', 'Foo', OperationType::COLLECTION), new Route('/foos')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection)->shouldBeCalled(); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), $this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $this->assertEquals('/foos', $operationPathResolver->resolveOperationPath('Foo', [], OperationType::COLLECTION, 'get')); - } - - public function testResolveOperationPathWithRouteNotFound() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The route "api_foos_get_collection" of the resource "Foo" was not found.'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn(new RouteCollection())->shouldBeCalled(); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), $this->prophesize(OperationPathResolverInterface::class)->reveal()); - $operationPathResolver->resolveOperationPath('Foo', [], OperationType::COLLECTION, 'get'); - } - - /** - * @group legacy - * @expectedDeprecation Method ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver::resolveOperationPath() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1. - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testLegacyResolveOperationPath() - { - $operationPathResolverProphecy = $this->prophesize(OperationPathResolverInterface::class); - $operationPathResolverProphecy->resolveOperationPath('Foo', [], OperationType::ITEM, null)->willReturn('/foos/{id}.{_format}')->shouldBeCalled(); - - $operationPathResolver = new RouterOperationPathResolver($this->prophesize(RouterInterface::class)->reveal(), $operationPathResolverProphecy->reveal()); - - $this->assertEquals('/foos/{id}.{_format}', $operationPathResolver->resolveOperationPath('Foo', [], false)); - } -} diff --git a/tests/Core/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php b/tests/Core/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php deleted file mode 100644 index 6fd2b4f3073..00000000000 --- a/tests/Core/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php +++ /dev/null @@ -1,212 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Validator\EventListener; - -use ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidateListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use ApiPlatform\Validator\Exception\ValidationException; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\Validator\ConstraintViolationListInterface; -use Symfony\Component\Validator\Validator\ValidatorInterface; - -/** - * @author Samuel ROZE - * - * @group legacy - */ -class ValidateListenerTest extends TestCase -{ - use ProphecyTrait; - - public function testNotAnApiPlatformRequest() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - $validator = $validatorProphecy->reveal(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $request = new Request(); - $request->setMethod('POST'); - - $listener = new ValidateListener($validator, $resourceMetadataFactory); - - $event = new ViewEvent($this->prophesize(HttpKernelInterface::class)->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, []); - $listener->onKernelView($event); - } - - public function testValidatorIsCalled() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $constraintViolationList = $this->prophesize(ConstraintViolationListInterface::class); - $constraintViolationList->count()->willReturn(0); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->willReturn($constraintViolationList)->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - $containerProphecy = $this->prophesize(ContainerInterface::class); - $containerProphecy->has(Argument::any())->shouldNotBeCalled(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory, $containerProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testGetGroupsFromCallable() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $constraintViolationList = $this->prophesize(ConstraintViolationListInterface::class); - $constraintViolationList->count()->willReturn(0); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->willReturn($constraintViolationList)->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - $closure = function ($data) use ($expectedValidationGroups): array { - return $data instanceof DummyEntity ? $expectedValidationGroups : []; - }; - - [$resourceMetadataFactory, $event] = $this->createEventObject($closure, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - public function testGetGroupsFromService() - { - $data = new DummyEntity(); - - $constraintViolationList = $this->prophesize(ConstraintViolationListInterface::class); - $constraintViolationList->count()->willReturn(0); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, ['a', 'b', 'c'])->willReturn($constraintViolationList)->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject('groups_builder', $data); - - $containerProphecy = $this->prophesize(ContainerInterface::class); - $containerProphecy->has('groups_builder')->willReturn(true)->shouldBeCalled(); - $containerProphecy->get('groups_builder')->willReturn(new class() { - public function __invoke($data): array - { - return $data instanceof DummyEntity ? ['a', 'b', 'c'] : []; - } - } - )->shouldBeCalled(); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory, $containerProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testValidatorWithScalarGroup() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['foo']; - - $constraintViolationList = $this->prophesize(ConstraintViolationListInterface::class); - $constraintViolationList->count()->willReturn(0); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->willreturn($constraintViolationList)->shouldBeCalled(); - - $containerProphecy = $this->prophesize(ContainerInterface::class); - $containerProphecy->has('foo')->willReturn(false)->shouldBeCalled(); - - [$resourceMetadataFactory, $event] = $this->createEventObject('foo', $data); - - $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactory, $containerProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testDoNotCallWhenReceiveFlagIsFalse() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->shouldNotBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data, false); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - public function testThrowsValidationExceptionWithViolationsFound() - { - $this->expectException(ValidationException::class); - - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $violationsProphecy = $this->prophesize(ConstraintViolationListInterface::class); - $violationsProphecy->rewind()->shouldBeCalled(); - $violationsProphecy->valid()->shouldBeCalled(); - $violationsProphecy->count()->willReturn(1)->shouldBeCalled(); - $violations = $violationsProphecy->reveal(); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->willReturn($violations)->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - private function createEventObject($expectedValidationGroups, $data, bool $receive = true): array - { - $resourceMetadata = new ResourceMetadata(null, null, null, [ - 'create' => ['validation_groups' => $expectedValidationGroups], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - if ($receive) { - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata)->shouldBeCalled(); - } - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $kernel = $this->prophesize(HttpKernelInterface::class)->reveal(); - $request = new Request([], [], [ - '_api_resource_class' => DummyEntity::class, - '_api_item_operation_name' => 'create', - '_api_format' => 'json', - '_api_mime_type' => 'application/json', - '_api_receive' => $receive, - ]); - - $request->setMethod('POST'); - $event = new ViewEvent($kernel, $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $data); - - return [$resourceMetadataFactory, $event]; - } -} diff --git a/tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php b/tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php deleted file mode 100644 index b261e167ff3..00000000000 --- a/tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,398 +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); - -namespace ApiPlatform\Core\Tests\Bridge\Symfony\Validator\Metadata\Property; - -use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaFormat; -use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLengthRestriction; -use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaOneOfRestriction; -use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction; -use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\ValidatorPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\DummyAtLeastOneOfValidatedEntity; -use ApiPlatform\Tests\Fixtures\DummyIriWithValidationEntity; -use ApiPlatform\Tests\Fixtures\DummySequentiallyValidatedEntity; -use ApiPlatform\Tests\Fixtures\DummyValidatedEntity; -use Doctrine\Common\Annotations\AnnotationReader; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Intl\Countries; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Validator\Constraints\AtLeastOneOf; -use Symfony\Component\Validator\Constraints\Sequentially; -use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; -use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; - -/** - * @author Baptiste Meyer - */ -class ValidatorPropertyMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - private $validatorClassMetadata; - - protected function setUp(): void - { - $this->validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($this->validatorClassMetadata); - } - - public function testCreateWithPropertyWithRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(true); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy', [])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy'); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithNotRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy date', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(false); - $expectedPropertyMetadata = $expectedPropertyMetadata->withIri('http://schema.org/Date'); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate', [])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate'); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithoutConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy id', true, true, null, null, null, true); - $expectedPropertyMetadata = $propertyMetadata->withRequired(false); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyId', [])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyId'); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithRightValidationGroupsAndRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(true); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['dummy']])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['dummy']]); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithBadValidationGroupsAndRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(false); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['ymmud']])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['ymmud']]); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithNonStringValidationGroupsAndRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(false); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [1312]])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [1312]]); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithRequiredByDecorated() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy date', true, true, null, null, true, false, 'foo:bar'); - $expectedPropertyMetadata = clone $propertyMetadata; - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate', [])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate'); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithValidationConstraints() - { - if (!class_exists(Countries::class)) { - $this->markTestSkipped('symfony/intl not installed'); - } - - $validatorClassMetadata = new ClassMetadata(DummyIriWithValidationEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $types = [ - 'dummyUrl' => 'http://schema.org/url', - 'dummyEmail' => 'http://schema.org/email', - 'dummyUuid' => 'http://schema.org/identifier', - 'dummyCardScheme' => 'http://schema.org/identifier', - 'dummyBic' => 'http://schema.org/identifier', - 'dummyIban' => 'http://schema.org/identifier', - 'dummyDate' => 'http://schema.org/Date', - 'dummyDateTime' => 'http://schema.org/DateTime', - 'dummyTime' => 'http://schema.org/Time', - 'dummyImage' => 'http://schema.org/image', - 'dummyFile' => 'http://schema.org/MediaObject', - 'dummyCurrency' => 'http://schema.org/priceCurrency', - 'dummyIsbn' => 'http://schema.org/isbn', - 'dummyIssn' => 'http://schema.org/issn', - ]; - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - foreach ($types as $property => $iri) { - $decoratedPropertyMetadataFactory->create(DummyIriWithValidationEntity::class, $property, [])->willReturn(new PropertyMetadata())->shouldBeCalled(); - } - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyIriWithValidationEntity::class)->willReturn($validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - - foreach ($types as $property => $iri) { - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyIriWithValidationEntity::class, $property); - $this->assertSame($iri, $resultedPropertyMetadata->getIri()); - } - } - - public function testCreateWithPropertyLengthRestriction(): void - { - $validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $property = 'dummy'; - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, $property, [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING)) - )->shouldBeCalled(); - - $lengthRestrictions = new PropertySchemaLengthRestriction(); - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(), [$lengthRestrictions] - ); - - $schema = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, $property)->getSchema(); - $this->assertNotNull($schema); - $this->assertArrayHasKey('minLength', $schema); - $this->assertArrayHasKey('maxLength', $schema); - } - - public function testCreateWithPropertyRegexRestriction(): void - { - $validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy', [])->willReturn( - new PropertyMetadata() - )->shouldBeCalled(); - - $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(), - [new PropertySchemaRegexRestriction()] - ); - - $schema = $validationPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy')->getSchema(); - $this->assertNotNull($schema); - $this->assertArrayHasKey('pattern', $schema); - $this->assertEquals('^(dummy)$', $schema['pattern']); - } - - public function testCreateWithPropertyFormatRestriction(): void - { - $validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - $formats = [ - 'dummyEmail' => 'email', - 'dummyUuid' => 'uuid', - 'dummyIpv4' => 'ipv4', - 'dummyIpv6' => 'ipv6', - ]; - - foreach ($formats as $property => $format) { - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, $property, [])->willReturn( - new PropertyMetadata() - )->shouldBeCalled(); - $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [new PropertySchemaFormat()] - ); - $schema = $validationPropertyMetadataFactory->create(DummyValidatedEntity::class, $property)->getSchema(); - $this->assertNotNull($schema); - $this->assertArrayHasKey('format', $schema); - $this->assertEquals($format, $schema['format']); - } - } - - public function testCreateWithSequentiallyConstraint(): void - { - if (!class_exists(Sequentially::class)) { - $this->markTestSkipped(); - } - - $validatorClassMetadata = new ClassMetadata(DummySequentiallyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummySequentiallyValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummySequentiallyValidatedEntity::class, 'dummy', [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING)) - )->shouldBeCalled(); - $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [new PropertySchemaLengthRestriction(), new PropertySchemaRegexRestriction()] - ); - $schema = $validationPropertyMetadataFactory->create(DummySequentiallyValidatedEntity::class, 'dummy')->getSchema(); - - $this->assertNotNull($schema); - $this->assertArrayHasKey('minLength', $schema); - $this->assertArrayHasKey('maxLength', $schema); - $this->assertArrayHasKey('pattern', $schema); - } - - public function testCreateWithAtLeastOneOfConstraint(): void - { - if (!class_exists(AtLeastOneOf::class)) { - $this->markTestSkipped(); - } - - $validatorClassMetadata = new ClassMetadata(DummyAtLeastOneOfValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyAtLeastOneOfValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyAtLeastOneOfValidatedEntity::class, 'dummy', [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING)) - )->shouldBeCalled(); - $restrictionsMetadata = [new PropertySchemaLengthRestriction(), new PropertySchemaRegexRestriction()]; - $restrictionsMetadata = [new PropertySchemaOneOfRestriction($restrictionsMetadata), new PropertySchemaLengthRestriction(), new PropertySchemaRegexRestriction()]; - $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - $restrictionsMetadata - ); - $schema = $validationPropertyMetadataFactory->create(DummyAtLeastOneOfValidatedEntity::class, 'dummy')->getSchema(); - - $this->assertNotNull($schema); - $this->assertArrayHasKey('oneOf', $schema); - $this->assertSame([ - ['pattern' => '^(.*#.*)$'], - ['minLength' => 10], - ], $schema['oneOf']); - } -} diff --git a/tests/Core/DataPersister/ChainDataPersisterTest.php b/tests/Core/DataPersister/ChainDataPersisterTest.php deleted file mode 100644 index 4248a3f6feb..00000000000 --- a/tests/Core/DataPersister/ChainDataPersisterTest.php +++ /dev/null @@ -1,122 +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); - -namespace ApiPlatform\Core\Tests\DataPersister; - -use ApiPlatform\Core\DataPersister\ChainDataPersister; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataPersister\ResumableDataPersisterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Baptiste Meyer - */ -class ChainDataPersisterTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $this->assertInstanceOf(DataPersisterInterface::class, new ChainDataPersister([$this->prophesize(DataPersisterInterface::class)->reveal()])); - } - - public function testSupports() - { - $dummy = new Dummy(); - - $persisterProphecy = $this->prophesize(DataPersisterInterface::class); - $persisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - - $this->assertTrue((new ChainDataPersister([$persisterProphecy->reveal()]))->supports($dummy)); - } - - public function testDoesNotSupport() - { - $dummy = new Dummy(); - - $persisterProphecy = $this->prophesize(DataPersisterInterface::class); - $persisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - - $this->assertFalse((new ChainDataPersister([$persisterProphecy->reveal()]))->supports($dummy)); - } - - public function testPersist() - { - $dummy = new Dummy(); - - $fooPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $fooPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - $fooPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $barPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $barPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $barPersisterProphecy->persist($dummy, Argument::type('array'))->shouldBeCalled(); - - $foobarPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $foobarPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled(); - $foobarPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - - (new ChainDataPersister([$fooPersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->persist($dummy); - } - - public function testRemove() - { - $dummy = new Dummy(); - - $fooPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $fooPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - $fooPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $barPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $barPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $barPersisterProphecy->remove($dummy, Argument::type('array'))->shouldBeCalled(); - - $foobarPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $foobarPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled(); - $foobarPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - (new ChainDataPersister([$fooPersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->remove($dummy); - } - - public function testResumable() - { - $dummy = new Dummy(); - $fooPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $fooPersisterProphecy->willImplement(ResumableDataPersisterInterface::class); - $fooPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $fooPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - $fooPersisterProphecy->remove($dummy, Argument::type('array'))->shouldBeCalled(); - $fooPersisterProphecy->resumable(Argument::type('array'))->willReturn(true)->shouldBeCalled(); - - $foo2PersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $foo2PersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - $foo2PersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $foo2PersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $barPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $barPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $barPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - $barPersisterProphecy->remove($dummy, Argument::type('array'))->shouldBeCalled(); - - $foobarPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $foobarPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldNotBeCalled(); - $foobarPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $foobarPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - (new ChainDataPersister([$fooPersisterProphecy->reveal(), $foo2PersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->persist($dummy); - (new ChainDataPersister([$fooPersisterProphecy->reveal(), $foo2PersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->remove($dummy); - } -} diff --git a/tests/Core/DataProvider/ChainCollectionDataProviderTest.php b/tests/Core/DataProvider/ChainCollectionDataProviderTest.php deleted file mode 100644 index 4788181528a..00000000000 --- a/tests/Core/DataProvider/ChainCollectionDataProviderTest.php +++ /dev/null @@ -1,126 +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); - -namespace ApiPlatform\Core\Tests\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainCollectionDataProvider; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * Retrieves items from a persistence layer. - * - * @author Kévin Dunglas - */ -class ChainCollectionDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetCollection() - { - $dummy = new Dummy(); - $dummy->setName('Rosa'); - $dummy2 = new Dummy(); - $dummy2->setName('Parks'); - - $firstDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, null, [])->willReturn(false); - - $secondDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $secondDataProvider->willImplement(RestrictedDataProviderInterface::class); - $secondDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $secondDataProvider->getCollection(Dummy::class, null, []) - ->willReturn([$dummy, $dummy2]); - - $thirdDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $thirdDataProvider->willImplement(RestrictedDataProviderInterface::class); - $thirdDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $thirdDataProvider->getCollection(Dummy::class, null, [])->willReturn([$dummy]); - - $chainItemDataProvider = new ChainCollectionDataProvider([ - $firstDataProvider->reveal(), - $secondDataProvider->reveal(), - $thirdDataProvider->reveal(), - ]); - - $this->assertEquals( - [$dummy, $dummy2], - $chainItemDataProvider->getCollection(Dummy::class) - ); - } - - public function testGetCollectionNotSupported() - { - $firstDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports('notfound', 'op', [])->willReturn(false); - - $collection = (new ChainCollectionDataProvider([$firstDataProvider->reveal()]))->getCollection('notfound', 'op'); - - $this->assertTrue(is_iterable($collection)); - $this->assertEmpty($collection); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetCollection() - { - $dummy = new Dummy(); - $dummy->setName('Rosa'); - $dummy2 = new Dummy(); - $dummy2->setName('Parks'); - - $firstDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $firstDataProvider->getCollection(Dummy::class, null, [])->willThrow(ResourceClassNotSupportedException::class); - - $secondDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $secondDataProvider->getCollection(Dummy::class, null, [])->willReturn([$dummy, $dummy2]); - - $thirdDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $thirdDataProvider->getCollection(Dummy::class, null, [])->willReturn([$dummy]); - - $chainItemDataProvider = new ChainCollectionDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]); - - $this->assertEquals([$dummy, $dummy2], $chainItemDataProvider->getCollection(Dummy::class)); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetCollectionExceptions() - { - $firstDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $firstDataProvider->getCollection('notfound', 'op', [])->willThrow(ResourceClassNotSupportedException::class); - - $collection = (new ChainCollectionDataProvider([$firstDataProvider->reveal()]))->getCollection('notfound', 'op'); - - $this->assertTrue(is_iterable($collection)); - $this->assertEmpty($collection); - } - - public function testGetCollectionWithEmptyDataProviders() - { - $collection = (new ChainCollectionDataProvider([]))->getCollection(Dummy::class); - - $this->assertTrue(is_iterable($collection)); - $this->assertEmpty($collection); - } -} diff --git a/tests/Core/DataProvider/ChainItemDataProviderTest.php b/tests/Core/DataProvider/ChainItemDataProviderTest.php deleted file mode 100644 index a28aad91635..00000000000 --- a/tests/Core/DataProvider/ChainItemDataProviderTest.php +++ /dev/null @@ -1,158 +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); - -namespace ApiPlatform\Core\Tests\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainItemDataProvider; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositePrimitiveItem; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * Retrieves items from a persistence layer. - * - * @author Kévin Dunglas - */ -class ChainItemDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetItem() - { - $dummy = new Dummy(); - $dummy->setName('Lucie'); - - $firstDataProvider = $this->prophesize(DenormalizedIdentifiersAwareItemDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, null, [])->willReturn(false); - - $secondDataProvider = $this->prophesize(DenormalizedIdentifiersAwareItemDataProviderInterface::class); - $secondDataProvider->willImplement(RestrictedDataProviderInterface::class); - $secondDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $secondDataProvider->getItem(Dummy::class, ['id' => 1], null, [])->willReturn($dummy); - - $thirdDataProvider = $this->prophesize(DenormalizedIdentifiersAwareItemDataProviderInterface::class); - $thirdDataProvider->willImplement(RestrictedDataProviderInterface::class); - $thirdDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $thirdDataProvider->getItem(Dummy::class, ['id' => 1], null, [])->willReturn(new \stdClass()); - - $chainItemDataProvider = new ChainItemDataProvider([ - $firstDataProvider->reveal(), - $secondDataProvider->reveal(), - $thirdDataProvider->reveal(), - ]); - - $this->assertEquals($dummy, $chainItemDataProvider->getItem(Dummy::class, ['id' => 1])); - } - - public function testGetItemWithoutDenormalizedIdentifiers() - { - $dummy = new Dummy(); - $dummy->setName('Lucie'); - - $firstDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, null, [])->willReturn(false); - - $secondDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $secondDataProvider->willImplement(RestrictedDataProviderInterface::class); - $secondDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $secondDataProvider->getItem(Dummy::class, '1', null, [])->willReturn($dummy); - - $thirdDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $thirdDataProvider->willImplement(RestrictedDataProviderInterface::class); - $thirdDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $thirdDataProvider->getItem(Dummy::class, 1, null, [])->willReturn(new \stdClass()); - - $chainItemDataProvider = new ChainItemDataProvider([ - $firstDataProvider->reveal(), - $secondDataProvider->reveal(), - $thirdDataProvider->reveal(), - ]); - - $this->assertEquals($dummy, $chainItemDataProvider->getItem(Dummy::class, ['id' => 1])); - } - - public function testGetItemExceptions() - { - $firstDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports('notfound', null, [])->willReturn(false); - - $chainItemDataProvider = new ChainItemDataProvider([$firstDataProvider->reveal()]); - - $this->assertEquals('', $chainItemDataProvider->getItem('notfound', 1)); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetItem() - { - $dummy = new Dummy(); - $dummy->setName('Lucie'); - - $firstDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $firstDataProvider->getItem(Dummy::class, 1, null, [])->willThrow(ResourceClassNotSupportedException::class); - - $secondDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $secondDataProvider->getItem(Dummy::class, 1, null, [])->willReturn($dummy); - - $thirdDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $thirdDataProvider->getItem(Dummy::class, 1, null, [])->willReturn(new \stdClass()); - - $chainItemDataProvider = new ChainItemDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]); - - $chainItemDataProvider->getItem(Dummy::class, 1); - } - - /** - * @group legacy - * @expectedDeprecation Receiving "$id" as non-array in an item data provider is deprecated in 2.3 in favor of implementing "ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface". - */ - public function testLegacyGetItemWithoutDenormalizedIdentifiersAndCompositeIdentifier() - { - $dummy = new CompositePrimitiveItem('Lucie', 1984); - - $dataProvider = $this->prophesize(ItemDataProviderInterface::class); - $dataProvider->willImplement(RestrictedDataProviderInterface::class); - $dataProvider->supports(CompositePrimitiveItem::class, null, [])->willReturn(true); - $dataProvider->getItem(CompositePrimitiveItem::class, 'name=Lucie;year=1984', null, [])->willReturn($dummy); - - $chainItemDataProvider = new ChainItemDataProvider([ - $dataProvider->reveal(), - ]); - - $this->assertEquals($dummy, $chainItemDataProvider->getItem(CompositePrimitiveItem::class, ['name' => 'Lucie', 'year' => 1984])); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetItemExceptions() - { - $firstDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $firstDataProvider->getItem('notfound', 1, null, [])->willThrow(ResourceClassNotSupportedException::class); - - $chainItemDataProvider = new ChainItemDataProvider([$firstDataProvider->reveal()]); - - $this->assertEquals('', $chainItemDataProvider->getItem('notfound', 1)); - } -} diff --git a/tests/Core/DataProvider/ChainSubresourcedataProviderTest.php b/tests/Core/DataProvider/ChainSubresourcedataProviderTest.php deleted file mode 100644 index c451d62194a..00000000000 --- a/tests/Core/DataProvider/ChainSubresourcedataProviderTest.php +++ /dev/null @@ -1,122 +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); - -namespace ApiPlatform\Core\Tests\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainSubresourceDataProvider; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * Retrieves items from a persistence layer. - */ -class ChainSubresourcedataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetSubresource() - { - $dummy = new Dummy(); - $dummy->setName('Rosa'); - $dummy2 = new Dummy(); - $dummy2->setName('Parks'); - - $context = ['identifiers' => ['id' => Dummy::class], 'property' => 'relatedDummies']; - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, 'get', $context)->willReturn(false); - $firstDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2])->willThrow(ResourceClassNotSupportedException::class); - - $secondDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $secondDataProvider->willImplement(RestrictedDataProviderInterface::class); - $secondDataProvider->supports(Dummy::class, 'get', $context)->willReturn(true); - $secondDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2]); - - $thirdDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $thirdDataProvider->willImplement(RestrictedDataProviderInterface::class); - $thirdDataProvider->supports(Dummy::class, 'get', $context)->willReturn(true); - $thirdDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy]); - - $chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]); - - $this->assertEquals([$dummy, $dummy2], $chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')); - } - - public function testGetSubresourceExceptionsItem() - { - $context = ['collection' => false]; - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, 'get', $context)->willReturn(false); - - $chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal()]); - - $this->assertNull($chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')); - } - - public function testGetSubresourceExceptionsCollection() - { - $context = ['collection' => true]; - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, 'get', $context)->willReturn(false); - - $chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal()]); - - $this->assertEquals([], $chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetSubresource() - { - $dummy = new Dummy(); - $dummy->setName('Rosa'); - $dummy2 = new Dummy(); - $dummy2->setName('Parks'); - - $context = ['identifiers' => ['id' => Dummy::class], 'property' => 'relatedDummies']; - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2])->willThrow(ResourceClassNotSupportedException::class); - - $secondDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $secondDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2]); - - $thirdDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $thirdDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy]); - - $chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]); - - $this->assertEquals([$dummy, $dummy2], $chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetCollectionExceptions() - { - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->getSubresource('notfound', ['id' => 1], [], 'get')->willThrow(ResourceClassNotSupportedException::class); - - $chainItemDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal()]); - - $this->assertEquals('', $chainItemDataProvider->getSubresource('notfound', ['id' => 1], [], 'get')); - } -} diff --git a/tests/Core/EventListener/ReadListenerTest.php b/tests/Core/EventListener/ReadListenerTest.php deleted file mode 100644 index 08b9596545f..00000000000 --- a/tests/Core/EventListener/ReadListenerTest.php +++ /dev/null @@ -1,409 +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); - -namespace ApiPlatform\Core\Tests\EventListener; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\EventListener\ReadListener; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class ReadListenerTest extends TestCase -{ - use ProphecyTrait; - - public function testNotAnApiPlatformRequest() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn(new Request())->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - /** - * @group legacy - */ - public function testLegacyConstructor() - { - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn(new Request())->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testDoNotReadWhenReceiveFlagIsFalse() - { - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection(Argument::cetera())->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem(Argument::cetera())->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource(Argument::cetera())->shouldNotBeCalled(); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $request = new Request([], [], ['id' => 1, 'data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'put', '_api_receive' => false]); - $request->setMethod('PUT'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testDoNotReadWhenDisabledInOperationAttribute() - { - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection(Argument::cetera())->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem(Argument::cetera())->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource(Argument::cetera())->shouldNotBeCalled(); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [ - 'put' => [ - 'read' => false, - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); - - $request = new Request([], [], ['id' => 1, 'data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'put']); - $request->setMethod('PUT'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveCollectionPost() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post', '_api_format' => 'json', '_api_mime_type' => 'application/json'], [], [], [], '{}'); - $request->setMethod('POST'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $this->assertFalse($request->attributes->has('data')); - $this->assertFalse($request->attributes->has('previous_data')); - } - - public function testRetrieveCollectionGet() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection('Foo', 'get', ['filters' => ['foo' => 'bar']])->willReturn([])->shouldBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json'], [], [], ['QUERY_STRING' => 'foo=bar']); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $this->assertSame([], $request->attributes->get('data')); - $this->assertFalse($request->attributes->has('previous_data')); - } - - public function testRetrieveItem() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willReturn(['id' => '1']); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $data = new \stdClass(); - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem('Foo', ['id' => '1'], 'get', [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->willReturn($data)->shouldBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $this->assertSame($data, $request->attributes->get('data')); - $this->assertEquals($data, $request->attributes->get('previous_data')); - } - - public function testRetrieveItemNoIdentifier() - { - $this->expectException(NotFoundHttpException::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal()); - $listener->onKernelRequest($event->reveal()); - - $request->attributes->get('data'); - } - - public function testRetrieveSubresource() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willReturn(['id' => '1']); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $data = [new \stdClass()]; - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource('Foo', ['id' => ['id' => '1']], ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar', IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true], 'get')->willReturn($data)->shouldBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar']]); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $this->assertSame($data, $request->attributes->get('data')); - $this->assertSame($data, $request->attributes->get('previous_data')); - } - - public function testRetrieveSubresourceNoDataProvider() - { - $this->expectException(RuntimeException::class); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willReturn(['id' => '1']); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar']]); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), null, null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $request->attributes->get('data'); - } - - public function testRetrieveSubresourceNotFound() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->willThrow(new InvalidIdentifierException())->shouldBeCalled(); - $this->expectException(NotFoundHttpException::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar']]); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $this->prophesize(SubresourceDataProviderInterface::class)->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveItemNotFound() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '22'], 'Foo')->shouldBeCalled()->willReturn(['id' => 22]); - $this->expectException(NotFoundHttpException::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem('Foo', ['id' => 22], 'get', [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->willReturn(null)->shouldBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - - $request = new Request([], [], ['id' => '22', '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveBadItemNormalizedIdentifiers() - { - $this->expectException(NotFoundHttpException::class); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willThrow(new InvalidIdentifierException()); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $request->setMethod(Request::METHOD_GET); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveBadSubresourceNormalizedIdentifiers() - { - $this->expectException(NotFoundHttpException::class); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(Argument::type('array'), Argument::type('string'))->shouldBeCalled()->willThrow(new InvalidIdentifierException()); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar']]); - $request->setMethod(Request::METHOD_GET); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveItemWithCompositeIdentifiersCallsIdentifierConverter() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['foo' => '22', 'bar' => 'test'], 'DummyWithCompositeIdentifier')->shouldBeCalled()->willReturn(['foo' => 22, 'bar' => 'test']); - $this->expectException(NotFoundHttpException::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem('DummyWithCompositeIdentifier', ['foo' => 22, 'bar' => 'test'], 'get', [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->willReturn(null)->shouldBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - - $request = new Request([], [], ['id' => 'foo=22;bar=test', '_api_resource_class' => 'DummyWithCompositeIdentifier', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_identifiers' => ['foo', 'bar'], '_api_has_composite_identifier' => true]); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } -} diff --git a/tests/Core/EventListener/WriteListenerTest.php b/tests/Core/EventListener/WriteListenerTest.php deleted file mode 100644 index 94743b941a8..00000000000 --- a/tests/Core/EventListener/WriteListenerTest.php +++ /dev/null @@ -1,400 +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); - -namespace ApiPlatform\Core\Tests\EventListener; - -use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\EventListener\WriteListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ConcreteDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * @author Baptiste Meyer - * @group legacy - */ -class WriteListenerTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function testOnKernelViewWithControllerResultAndPersist() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummy/1')->shouldBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class]); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - foreach (['PATCH', 'PUT', 'POST'] as $httpMethod) { - $request->setMethod($httpMethod); - $request->attributes->set(sprintf('_api_%s_operation_name', 'POST' === $httpMethod ? 'collection' : 'item'), strtolower($httpMethod)); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - $this->assertSame($dummy, $event->getControllerResult()); - $this->assertEquals('/dummy/1', $request->attributes->get('_api_write_item_iri')); - } - } - - /** - * @group legacy - * @expectedDeprecation Not returning an object from ApiPlatform\Core\DataPersister\DataPersisterInterface::persist() is deprecated since API Platform 2.3 and will not be supported in API Platform 3. - */ - public function testOnKernelViewWithControllerResultAndPersistReturningVoid() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummy/1'); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class]); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - foreach (['PATCH', 'PUT', 'POST'] as $httpMethod) { - $request->setMethod($httpMethod); - $request->attributes->set(sprintf('_api_%s_operation_name', 'POST' === $httpMethod ? 'collection' : 'item'), strtolower($httpMethod)); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - $this->assertSame($dummy, $event->getControllerResult()); - } - } - - /** - * @see https://github.com/api-platform/core/issues/1799 - * @see https://github.com/api-platform/core/issues/2692 - */ - public function testOnKernelViewWithControllerResultAndPersistWithImmutableResource() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dummy2 = new Dummy(); - $dummy2->setId(2); - $dummy2->setName('Dummyferoce'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy2); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy2)->willReturn('/dummy/2'); - - $writeListener = new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class]); - - foreach (['PATCH', 'PUT', 'POST'] as $httpMethod) { - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $request->setMethod($httpMethod); - $request->attributes->set(sprintf('_api_%s_operation_name', 'POST' === $httpMethod ? 'collection' : 'item'), strtolower($httpMethod)); - - $writeListener->onKernelView($event); - - $this->assertSame($dummy2, $event->getControllerResult()); - $this->assertEquals('/dummy/2', $request->attributes->get('_api_write_item_iri')); - } - } - - public function testOnKernelViewDoNotCallIriConverterWhenOutputClassDisabled() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['output' => ['class' => null]])); - - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post']); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()))->onKernelView($event); - } - - public function testOnKernelViewWithControllerResultAndRemove() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $dataPersisterProphecy->remove($dummy, Argument::type('array'))->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'delete']); - $request->setMethod('DELETE'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - } - - public function testOnKernelViewWithSafeMethod() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'head']); - $request->setMethod('HEAD'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal()))->onKernelView($event); - } - - public function testDoNotWriteWhenControllerResultIsResponse() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->persist(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->remove(Argument::cetera())->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $request = new Request(); - - $response = new Response(); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $response - ); - - $listener = new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()); - $listener->onKernelView($event); - } - - public function testDoNotWriteWhenPersistFlagIsFalse() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->persist(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->remove(Argument::cetera())->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $request = new Request([], [], ['data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post', '_api_persist' => false]); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $listener = new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()); - $listener->onKernelView($event); - } - - public function testDoNotWriteWhenDisabledInOperationAttribute() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->persist(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->remove(Argument::cetera())->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [], [ - 'post' => [ - 'write' => false, - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); - - $request = new Request([], [], ['data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post']); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $listener = new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $listener->onKernelView($event); - } - - public function testOnKernelViewWithNoResourceClass() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $request = new Request(); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - } - - public function testOnKernelViewWithParentResourceClass() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new ConcreteDummy(); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummy/1')->shouldBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => ConcreteDummy::class, '_api_item_operation_name' => 'put', '_api_persist' => true]); - $request->setMethod('PUT'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - } - - public function testOnKernelViewWithNoDataPersisterSupport() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => 'Dummy', '_api_collection_operation_name' => 'post']); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - } -} diff --git a/tests/Core/Identifier/CompositeIdentifierParserTest.php b/tests/Core/Identifier/CompositeIdentifierParserTest.php deleted file mode 100644 index 79e87b99e0d..00000000000 --- a/tests/Core/Identifier/CompositeIdentifierParserTest.php +++ /dev/null @@ -1,67 +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); - -namespace ApiPlatform\Core\Tests\Identifier; - -use ApiPlatform\Core\Identifier\CompositeIdentifierParser; -use PHPUnit\Framework\TestCase; - -class CompositeIdentifierParserTest extends TestCase -{ - /** - * @dataProvider variousIdentifiers - */ - public function testNormalizeCompositeCorrectly(array $identifiers) - { - foreach ($identifiers as $string => $expected) { - $this->assertEquals(CompositeIdentifierParser::parse($string), $expected); - } - } - - public function variousIdentifiers(): array - { - return [[[ - 'a=bd;dc=d' => ['a' => 'bd', 'dc' => 'd'], - 'a=b;c=d foo;d23i=e' => ['a' => 'b', 'c' => 'd foo', 'd23i' => 'e'], - 'a=1;c=2;d=10-30-24' => ['a' => '1', 'c' => '2', 'd' => '10-30-24'], - 'a=test;b=bar;foo;c=123' => ['a' => 'test', 'b' => 'bar;foo', 'c' => '123'], - 'a=test;b=bar ;foo;c=123;459;barz=123asgfjasdg4;' => ['a' => 'test', 'b' => 'bar ;foo', 'c' => '123;459', 'barz' => '123asgfjasdg4'], - 'foo=test=bar;;bar=bazzz;' => ['foo' => 'test=bar;', 'bar' => 'bazzz'], - 'foo=test=bar;bar=;test=foo' => ['foo' => 'test=bar', 'bar' => '', 'test' => 'foo'], - 'foo=test=bar;bar=' => ['foo' => 'test=bar', 'bar' => ''], - ]]]; - } - - /** - * @dataProvider compositeIdentifiers - */ - public function testStringify(array $identifiers) - { - foreach ($identifiers as $string => $arr) { - $this->assertEquals(CompositeIdentifierParser::stringify($arr), $string); - } - } - - public function compositeIdentifiers(): array - { - return [[[ - 'a=bd;dc=d' => ['a' => 'bd', 'dc' => 'd'], - 'a=b;c=d foo;d23i=e' => ['a' => 'b', 'c' => 'd foo', 'd23i' => 'e'], - 'a=1;c=2;d=10-30-24' => ['a' => '1', 'c' => '2', 'd' => '10-30-24'], - 'a=test;b=bar;foo;c=123' => ['a' => 'test', 'b' => 'bar;foo', 'c' => '123'], - 'foo=test=bar;;bar=bazzz' => ['foo' => 'test=bar;', 'bar' => 'bazzz'], - 'foo=test=bar;bar=;test=foo' => ['foo' => 'test=bar', 'bar' => '', 'test' => 'foo'], - 'foo=test=bar;bar=' => ['foo' => 'test=bar', 'bar' => ''], - ]]]; - } -} diff --git a/tests/Core/Identifier/IdentifierConverterTest.php b/tests/Core/Identifier/IdentifierConverterTest.php deleted file mode 100644 index c2a39234f6d..00000000000 --- a/tests/Core/Identifier/IdentifierConverterTest.php +++ /dev/null @@ -1,147 +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); - -namespace ApiPlatform\Core\Tests\Identifier; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Identifier\IdentifierConverter; -use ApiPlatform\Core\Identifier\Normalizer\DateTimeIdentifierDenormalizer; -use ApiPlatform\Core\Identifier\Normalizer\IntegerDenormalizer; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * @author Antoine Bluchet - */ -class IdentifierConverterTest extends TestCase -{ - use ProphecyTrait; - - public function testCompositeIdentifier() - { - $identifiers = [ - 'a' => '1', - 'c' => '2', - 'd' => '2015-04-05', - ]; - - $class = 'Dummy'; - - $integerPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT)); - $identifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true); - $dateIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTime::class)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create($class, 'a')->shouldBeCalled()->willReturn($integerPropertyMetadata); - $propertyMetadataFactory->create($class, 'c')->shouldBeCalled()->willReturn($identifierPropertyMetadata); - $propertyMetadataFactory->create($class, 'd')->shouldBeCalled()->willReturn($dateIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass($class)->willReturn(['a', 'c', 'd']); - - $identifierDenormalizers = [new IntegerDenormalizer(), new DateTimeIdentifierDenormalizer()]; - - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $result = $identifierDenormalizer->convert($identifiers, $class); - $this->assertEquals(['a' => 1, 'c' => '2', 'd' => new \DateTime('2015-04-05')], $result); - $this->assertSame(1, $result['a']); - } - - public function testSingleDateIdentifier() - { - $identifier = ['funkyid' => '2015-04-05']; - $class = 'Dummy'; - - $dateIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTime::class)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create($class, 'funkyid')->shouldBeCalled()->willReturn($dateIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass($class)->willReturn(['funkyid']); - - $identifierDenormalizers = [new DateTimeIdentifierDenormalizer()]; - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $this->assertEquals($identifierDenormalizer->convert($identifier, $class), ['funkyid' => new \DateTime('2015-04-05')]); - } - - public function testIntegerIdentifier() - { - $identifier = ['id' => '42']; - $class = 'Dummy'; - - $integerIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create($class, 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass($class)->willReturn(['id']); - - $identifierDenormalizers = [new IntegerDenormalizer()]; - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $this->assertSame(['id' => 42], $identifierDenormalizer->convert($identifier, $class)); - } - - public function testShouldBreakAfterTransforming() - { - $identifier = ['id' => '42']; - $class = 'Dummy'; - - $integerIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create($class, 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass($class)->willReturn(['id']); - - $shouldNotBeCalled = $this->prophesize(DenormalizerInterface::class); - $shouldNotBeCalled->supportsDenormalization()->shouldNotBeCalled(); - - $identifierDenormalizers = [new IntegerDenormalizer(), $shouldNotBeCalled->reveal()]; - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $this->assertSame(['id' => 42], $identifierDenormalizer->convert($identifier, $class)); - } - - public function testWithContextAndMultipleIdentifiers() - { - $identifier = ['id' => '42', 'book' => '21']; - - $integerIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create('Author', 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata); - $propertyMetadataFactory->create('Book', 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass('Book')->willReturn(['id']); - $identifiersExtractor->getIdentifiersFromResourceClass('Author')->willReturn(['id']); - - $shouldNotBeCalled = $this->prophesize(DenormalizerInterface::class); - $shouldNotBeCalled->supportsDenormalization()->shouldNotBeCalled(); - - $identifierDenormalizers = [new IntegerDenormalizer(), $shouldNotBeCalled->reveal()]; - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $this->assertSame(['id' => 42, 'book' => 21], $identifierDenormalizer->convert($identifier, 'Book', ['identifiers' => ['id' => ['Author', 'id'], 'book' => ['Book', 'id']]])); - } -} diff --git a/tests/Core/Identifier/Normalizer/DateTimeIdentifierNormalizerTest.php b/tests/Core/Identifier/Normalizer/DateTimeIdentifierNormalizerTest.php deleted file mode 100644 index ccd386d93ad..00000000000 --- a/tests/Core/Identifier/Normalizer/DateTimeIdentifierNormalizerTest.php +++ /dev/null @@ -1,36 +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); - -namespace ApiPlatform\Core\Tests\Identifier\Normalizer; - -use ApiPlatform\Core\Identifier\Normalizer\DateTimeIdentifierDenormalizer; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class DateTimeIdentifierNormalizerTest extends TestCase -{ - public function testDenormalize() - { - $this->expectException(\ApiPlatform\Exception\InvalidIdentifierException::class); - - $normalizer = new DateTimeIdentifierDenormalizer(); - $normalizer->denormalize('not valid', \DateTimeImmutable::class); - } - - public function testHasCacheableSupportsMethod() - { - $this->assertTrue((new DateTimeIdentifierDenormalizer())->hasCacheableSupportsMethod()); - } -} diff --git a/tests/Core/Identifier/Normalizer/IntegerDenormalizerTest.php b/tests/Core/Identifier/Normalizer/IntegerDenormalizerTest.php deleted file mode 100644 index a900c24f7ca..00000000000 --- a/tests/Core/Identifier/Normalizer/IntegerDenormalizerTest.php +++ /dev/null @@ -1,37 +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); - -namespace ApiPlatform\Core\Tests\Identifier\Normalizer; - -use ApiPlatform\Core\Identifier\Normalizer\IntegerDenormalizer; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class IntegerDenormalizerTest extends TestCase -{ - public function testDenormalize() - { - $this->assertSame(2, (new IntegerDenormalizer())->denormalize('2', 'int')); - } - - public function testSupportsDenormalization() - { - $normalizer = new IntegerDenormalizer(); - $this->assertTrue($normalizer->supportsDenormalization('1', 'int')); - $this->assertFalse($normalizer->supportsDenormalization([], 'int')); - $this->assertFalse($normalizer->supportsDenormalization('1', 'foo')); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } -} diff --git a/tests/Core/Metadata/Extractor/ExtractorTestCase.php b/tests/Core/Metadata/Extractor/ExtractorTestCase.php deleted file mode 100644 index 61d95c152cd..00000000000 --- a/tests/Core/Metadata/Extractor/ExtractorTestCase.php +++ /dev/null @@ -1,614 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Extractor; - -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Extractor\ResourceExtractorInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; - -/** - * @author Théo Fidry - */ -abstract class ExtractorTestCase extends TestCase -{ - use ProphecyTrait; - - protected $extractorClass; - - final public function testEmptyResources() - { - $resources = $this->createExtractor([$this->getEmptyResourcesFile()])->getResources(); - - $this->assertEmpty($resources); - } - - final public function testEmptyOperation() - { - $resources = $this->createExtractor([$this->getEmptyOperationFile()])->getResources(); - - $this->assertSame(['filters' => ['greeting.search_filter']], $resources['App\Entity\Greeting']['collectionOperations']['get']); - // There is a difference between XML & YAML here for example, one will parse `null` or the lack of value as `null` - // whilst the other will parse it as an empty array. Since it doesn't affect the processing of those values, there is no - // real need to fix this. - $this->assertEmpty($resources['App\Entity\Greeting']['collectionOperations']['post']); - $this->assertEmpty($resources['App\Entity\Greeting']['itemOperations']['get']); - $this->assertEmpty($resources['App\Entity\Greeting']['itemOperations']['put']); - } - - final public function testCorrectResources() - { - $resources = $this->createExtractor([$this->getCorrectResourceFile()])->getResources(); - - $this->assertSame([ - Dummy::class => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => null, - ], - FileConfigDummy::class => [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'iri' => 'someirischema', - 'itemOperations' => [ - 'my_op_name' => [ - 'method' => 'GET', - ], - 'my_other_op_name' => [ - 'method' => 'POST', - ], - ], - 'collectionOperations' => [ - 'my_collection_op' => [ - 'method' => 'POST', - 'path' => 'the/collection/path', - ], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => [ - 'path' => 'the/subresource/path', - ], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - 'groups' => [ - 'graphql', - ], - ], - ], - ], - 'attributes' => [ - 'normalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'denormalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - 'stateless' => true, - ], - 'properties' => [ - 'foo' => [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => null, - 'iri' => null, - 'attributes' => [ - 'foo' => [ - 'Foo', - ], - 'bar' => [ - [ - 'Bar', - ], - 'baz' => 'Baz', - ], - 'baz' => 'Baz', - ], - 'subresource' => [ - 'collection' => true, - 'resourceClass' => 'Foo', - 'maxDepth' => 1, - ], - ], - 'name' => [ - 'description' => 'The dummy name', - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => null, - ], - ], - ], - ], $resources); - } - - final public function testResourcesParametersResolution() - { - $containerProphecy = $this->prophesize(ContainerInterface::class); - $containerProphecy->get('dummy_class')->willReturn(Dummy::class); - $containerProphecy->get('dummy_related_owned_class')->willReturn(RelatedOwnedDummy::class); - $containerProphecy->get('file_config_dummy_class')->willReturn(FileConfigDummy::class); - - $resources = $this->createExtractor([$this->getResourceWithParametersFile()], $containerProphecy->reveal())->getResources(); - - $this->assertSame([ - Dummy::class => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => [ - 'relatedOwnedDummy' => [ - 'description' => null, - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => [ - 'collection' => null, - 'resourceClass' => RelatedOwnedDummy::class, - 'maxDepth' => null, - ], - ], - ], - ], - 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyBis' => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => null, - ], - FileConfigDummy::class => [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'iri' => 'someirischema', - 'itemOperations' => [ - 'my_op_name' => [ - 'method' => 'GET', - ], - 'my_other_op_name' => [ - 'method' => 'POST', - ], - ], - 'collectionOperations' => [ - 'my_collection_op' => [ - 'method' => 'POST', - 'path' => 'the/collection/path', - ], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => [ - 'path' => 'the/subresource/path', - ], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - 'groups' => [ - 'graphql', - ], - ], - ], - ], - 'attributes' => [ - 'normalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'denormalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - ], - 'properties' => [ - 'foo' => [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => null, - 'iri' => null, - 'attributes' => [ - 'foo' => [ - 'Foo', - ], - 'bar' => [ - [ - 'Bar', - ], - 'baz' => 'Baz', - ], - 'baz' => 'Baz', - 'const' => 0, - ], - 'subresource' => [ - 'collection' => true, - 'resourceClass' => 'Foo', - 'maxDepth' => 1, - ], - ], - 'name' => [ - 'description' => 'The dummy name', - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => null, - ], - ], - ], - ], $resources); - - $containerProphecy->get(Argument::cetera())->shouldHaveBeenCalledTimes(3); - } - - final public function testResourcesParametersResolutionWithTheSymfonyContainer() - { - $containerProphecy = $this->prophesize(SymfonyContainerInterface::class); - $containerProphecy->getParameter('dummy_class')->willReturn(Dummy::class); - $containerProphecy->getParameter('dummy_related_owned_class')->willReturn(RelatedOwnedDummy::class); - $containerProphecy->getParameter('file_config_dummy_class')->willReturn(FileConfigDummy::class); - - $resources = $this->createExtractor([$this->getResourceWithParametersFile()], $containerProphecy->reveal())->getResources(); - - $this->assertSame([ - Dummy::class => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => [ - 'relatedOwnedDummy' => [ - 'description' => null, - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => [ - 'collection' => null, - 'resourceClass' => RelatedOwnedDummy::class, - 'maxDepth' => null, - ], - ], - ], - ], - 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyBis' => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => null, - ], - FileConfigDummy::class => [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'iri' => 'someirischema', - 'itemOperations' => [ - 'my_op_name' => [ - 'method' => 'GET', - ], - 'my_other_op_name' => [ - 'method' => 'POST', - ], - ], - 'collectionOperations' => [ - 'my_collection_op' => [ - 'method' => 'POST', - 'path' => 'the/collection/path', - ], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => [ - 'path' => 'the/subresource/path', - ], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - 'groups' => [ - 'graphql', - ], - ], - ], - ], - 'attributes' => [ - 'normalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'denormalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - ], - 'properties' => [ - 'foo' => [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => null, - 'iri' => null, - 'attributes' => [ - 'foo' => [ - 'Foo', - ], - 'bar' => [ - [ - 'Bar', - ], - 'baz' => 'Baz', - ], - 'baz' => 'Baz', - 'const' => 0, - ], - 'subresource' => [ - 'collection' => true, - 'resourceClass' => 'Foo', - 'maxDepth' => 1, - ], - ], - 'name' => [ - 'description' => 'The dummy name', - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => null, - ], - ], - ], - ], $resources); - - $containerProphecy->getParameter(Argument::cetera())->shouldHaveBeenCalledTimes(3); - } - - final public function testResourcesParametersResolutionWithoutAContainer() - { - $resources = $this->createExtractor([$this->getResourceWithParametersFile()])->getResources(); - - $this->assertSame([ - '%dummy_class%' => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => [ - 'relatedOwnedDummy' => [ - 'description' => null, - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => [ - 'collection' => null, - 'resourceClass' => '%dummy_related_owned_class%', - 'maxDepth' => null, - ], - ], - ], - ], - '%dummy_class%Bis' => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => null, - ], - '%file_config_dummy_class%' => [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'iri' => 'someirischema', - 'itemOperations' => [ - 'my_op_name' => [ - 'method' => 'GET', - ], - 'my_other_op_name' => [ - 'method' => 'POST', - ], - ], - 'collectionOperations' => [ - 'my_collection_op' => [ - 'method' => 'POST', - 'path' => 'the/collection/path', - ], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => [ - 'path' => 'the/subresource/path', - ], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - 'groups' => [ - 'graphql', - ], - ], - ], - ], - 'attributes' => [ - 'normalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'denormalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - ], - 'properties' => [ - 'foo' => [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => null, - 'iri' => null, - 'attributes' => [ - 'foo' => [ - 'Foo', - ], - 'bar' => [ - [ - 'Bar', - ], - 'baz' => 'Baz', - ], - 'baz' => 'Baz', - 'const' => 0, - ], - 'subresource' => [ - 'collection' => true, - 'resourceClass' => 'Foo', - 'maxDepth' => 1, - ], - ], - 'name' => [ - 'description' => 'The dummy name', - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => null, - ], - ], - ], - ], $resources); - } - - /** - * @param string[] $paths - */ - final protected function createExtractor(array $paths, ContainerInterface $container = null): ResourceExtractorInterface - { - $extractorClass = $this->getExtractorClass(); - - $this->assertTrue(is_a($extractorClass, ResourceExtractorInterface::class, true)); - - return new $extractorClass($paths, $container); - } - - abstract protected function getExtractorClass(): string; - - abstract protected function getEmptyResourcesFile(): string; - - abstract protected function getEmptyOperationFile(): string; - - abstract protected function getCorrectResourceFile(): string; - - abstract protected function getResourceWithParametersFile(): string; -} diff --git a/tests/Core/Metadata/Extractor/XmlExtractorTest.php b/tests/Core/Metadata/Extractor/XmlExtractorTest.php deleted file mode 100644 index cfa45257756..00000000000 --- a/tests/Core/Metadata/Extractor/XmlExtractorTest.php +++ /dev/null @@ -1,63 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Extractor; - -use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; - -/** - * @author Kévin Dunglas - * @author Théo Fidry - */ -class XmlExtractorTest extends ExtractorTestCase -{ - /** - * {@inheritdoc} - */ - protected function getExtractorClass(): string - { - return XmlExtractor::class; - } - - /** - * {@inheritdoc} - */ - protected function getEmptyResourcesFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources_empty.xml'; - } - - /** - * {@inheritdoc} - */ - protected function getEmptyOperationFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/empty-operation.xml'; - } - - /** - * {@inheritdoc} - */ - protected function getCorrectResourceFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources.xml'; - } - - /** - * {@inheritdoc} - */ - protected function getResourceWithParametersFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources_with_parameters.xml'; - } -} diff --git a/tests/Core/Metadata/Extractor/YamlExtractorTest.php b/tests/Core/Metadata/Extractor/YamlExtractorTest.php deleted file mode 100644 index a949062dbe6..00000000000 --- a/tests/Core/Metadata/Extractor/YamlExtractorTest.php +++ /dev/null @@ -1,121 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Extractor; - -use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Exception\InvalidArgumentException; -use Generator; - -/** - * @author Kévin Dunglas - * @author Théo Fidry - */ -class YamlExtractorTest extends ExtractorTestCase -{ - public function testInvalidProperty() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The property "shortName" must be a "string", "integer" given.'); - - (new YamlExtractor([__DIR__.'/../../../Fixtures/FileConfigurations/badpropertytype.yml']))->getResources(); - } - - public function testParseException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/Unable to parse in ".+\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/parse_exception.yml"/'); - - (new YamlExtractor([__DIR__.'/../../../Fixtures/FileConfigurations/parse_exception.yml']))->getResources(); - } - - /** - * @dataProvider provideInvalidResources - */ - public function testInvalidResources(string $path, string $exceptionRegex) - { - try { - (new YamlExtractor([$path]))->getResources(); - - $this->fail('Expected exception to be thrown.'); - } catch (\InvalidArgumentException $exception) { - $this->assertMatchesRegularExpression( - $exceptionRegex, - $exception->getMessage() - ); - } - } - - public function provideInvalidResources(): Generator - { - yield [ - __DIR__.'/../../../Fixtures/FileConfigurations/resourcesinvalid.yml', - '/^"resources" setting is expected to be null or an array, string given in ".*resourcesinvalid\.yml"\.$/', - ]; - - yield [ - __DIR__.'/../../../Fixtures/FileConfigurations/resourcesinvalid_2.yml', - '/^"Foo" setting is expected to be null or an array, string given in ".*resourcesinvalid_2\.yml"\.$/', - ]; - - yield [ - __DIR__.'/../../../Fixtures/FileConfigurations/resourcesinvalid_3.yml', - '/^"properties" setting is expected to be null or an array, string given in ".*resourcesinvalid_3\.yml"\.$/', - ]; - - yield [ - __DIR__.'/../../../Fixtures/FileConfigurations/resourcesinvalid_4.yml', - '/^"myprop" setting is expected to be null or an array, string given in ".*resourcesinvalid_4\.yml"\.$/', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExtractorClass(): string - { - return YamlExtractor::class; - } - - /** - * {@inheritdoc} - */ - protected function getEmptyResourcesFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources_empty.yml'; - } - - /** - * {@inheritdoc} - */ - protected function getEmptyOperationFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/empty-operation.yml'; - } - - /** - * {@inheritdoc} - */ - protected function getCorrectResourceFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources.yml'; - } - - /** - * {@inheritdoc} - */ - protected function getResourceWithParametersFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources_with_parameters.yml'; - } -} diff --git a/tests/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactoryTest.php deleted file mode 100644 index 680426ce8f5..00000000000 --- a/tests/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,163 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\Factory\AnnotationPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Kévin Dunglas - */ -class AnnotationPropertyMetadataFactoryTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - /** - * @dataProvider dependenciesProvider - * - * @param mixed $reader - * @param mixed $decorated - * @group legacy - */ - public function testCreateProperty($reader, $decorated, string $description) - { - $factory = new AnnotationPropertyMetadataFactory($reader->reveal(), $decorated ? $decorated->reveal() : null); - $metadata = $factory->create(Dummy::class, 'name'); - - $this->assertEquals($description, $metadata->getDescription()); - $this->assertTrue($metadata->isReadable()); - $this->assertTrue($metadata->isWritable()); - $this->assertFalse($metadata->isReadableLink()); - $this->assertFalse($metadata->isWritableLink()); - $this->assertFalse($metadata->isIdentifier()); - $this->assertTrue($metadata->isRequired()); - $this->assertEquals('foo', $metadata->getIri()); - $this->assertEquals(['foo' => 'bar'], $metadata->getAttributes()); - } - - /** - * @requires PHP 8.0 - * @group legacy - */ - public function testCreateAttribute() - { - $this->expectDeprecation('Since api-platform/core 2.7: Decorating the legacy ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface is deprecated, use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface instead.'); - $factory = new AnnotationPropertyMetadataFactory(); - - $metadata = $factory->create(DummyPhp8::class, 'id'); - $this->assertTrue($metadata->isIdentifier()); - $this->assertSame('the identifier', $metadata->getDescription()); - - $metadata = $factory->create(DummyPhp8::class, 'foo'); - $this->assertSame('a foo', $metadata->getDescription()); - } - - public function dependenciesProvider(): array - { - $annotation = new ApiProperty(); - $annotation->description = 'description'; - $annotation->readable = true; - $annotation->writable = true; - $annotation->readableLink = false; - $annotation->writableLink = false; - $annotation->identifier = false; - $annotation->required = true; - $annotation->iri = 'foo'; - $annotation->attributes = ['foo' => 'bar']; - - $propertyReaderProphecy = $this->prophesize(Reader::class); - $propertyReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn($annotation)->shouldBeCalled(); - - $getterReaderProphecy = $this->prophesize(Reader::class); - $getterReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $getterReaderProphecy->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn($annotation)->shouldBeCalled(); - - $setterReaderProphecy = $this->prophesize(Reader::class); - $setterReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $setterReaderProphecy->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $setterReaderProphecy->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn($annotation)->shouldBeCalled(); - - $decoratedThrowNotFoundProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedThrowNotFoundProphecy->create(Dummy::class, 'name', [])->willThrow(new PropertyNotFoundException())->shouldBeCalled(); - - $decoratedReturnProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedReturnProphecy->create(Dummy::class, 'name', [])->willReturn(new PropertyMetadata(null, 'Hi'))->shouldBeCalled(); - - return [ - [$propertyReaderProphecy, null, 'description'], - [$getterReaderProphecy, $decoratedThrowNotFoundProphecy, 'description'], - [$setterReaderProphecy, $decoratedThrowNotFoundProphecy, 'description'], - [$setterReaderProphecy, $decoratedReturnProphecy, 'description'], - ]; - } - - /** - * @group legacy - */ - public function testClassNotFound() - { - $this->expectDeprecation('Since api-platform/core 2.7: Decorating the legacy ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface is deprecated, use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface instead.'); - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "foo" of class "\\DoNotExist" not found.'); - - $factory = new AnnotationPropertyMetadataFactory($this->prophesize(Reader::class)->reveal()); - $factory->create('\DoNotExist', 'foo'); - } - - /** - * @group legacy - */ - public function testClassNotFoundButParentFound() - { - $this->expectDeprecation('Since api-platform/core 2.7: Decorating the legacy ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface is deprecated, use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface instead.'); - $propertyMetadata = new PropertyMetadata(); - - $decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedProphecy->create('\DoNotExist', 'foo', [])->willReturn($propertyMetadata); - - $factory = new AnnotationPropertyMetadataFactory($this->prophesize(Reader::class)->reveal(), $decoratedProphecy->reveal()); - $this->assertEquals($propertyMetadata, $factory->create('\DoNotExist', 'foo')); - } - - public function testSkipDeprecation() - { - $annotation = new ApiProperty(); - $annotation->description = 'description'; - $annotation->readable = true; - $annotation->writable = true; - $annotation->readableLink = false; - $annotation->writableLink = false; - $annotation->identifier = false; - $annotation->required = true; - $annotation->iri = 'foo'; - $annotation->attributes = ['foo' => 'bar']; - - $propertyReaderProphecy = $this->prophesize(Reader::class); - $propertyReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn($annotation)->shouldBeCalled(); - - $factory = new AnnotationPropertyMetadataFactory($propertyReaderProphecy->reveal()); - $metadata = $factory->create(Dummy::class, 'name', ['deprecate' => false]); - } -} diff --git a/tests/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactoryTest.php b/tests/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactoryTest.php deleted file mode 100644 index 9b284d864c4..00000000000 --- a/tests/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactoryTest.php +++ /dev/null @@ -1,126 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Metadata\Property\Factory\AnnotationPropertyNameCollectionFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\UpperCaseIdentifierDummy; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class AnnotationPropertyNameCollectionFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider dependenciesProvider - * - * @param mixed $decorated - */ - public function testCreate($decorated, array $results) - { - $reader = $this->prophesize(Reader::class); - $reader->getPropertyAnnotation(new \ReflectionProperty(Dummy::class, 'name'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(Dummy::class, 'getName'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(Dummy::class, 'getAlias'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(Dummy::class, 'staticMethod'), ApiProperty::class)->shouldNotBeCalled(); - $reader->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - - $factory = new AnnotationPropertyNameCollectionFactory($reader->reveal(), $decorated ? $decorated->reveal() : null); - $metadata = $factory->create(Dummy::class); - - $this->assertEquals($results, iterator_to_array($metadata)); - } - - public function dependenciesProvider(): array - { - $decoratedThrowsNotFound = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $decoratedThrowsNotFound->create(Dummy::class, [])->willThrow(new ResourceClassNotFoundException())->shouldBeCalled(); - - $decoratedReturnParent = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $decoratedReturnParent->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['foo']))->shouldBeCalled(); - - return [ - [null, ['name', 'alias']], - [$decoratedThrowsNotFound, ['name', 'alias']], - [$decoratedReturnParent, ['name', 'alias', 'foo']], - ]; - } - - /** - * @requires PHP 8.0 - */ - public function testCreateAttribute() - { - $factory = new AnnotationPropertyNameCollectionFactory(); - $metadata = $factory->create(DummyPhp8::class); - - $this->assertSame(['id', 'foo'], iterator_to_array($metadata)); - } - - /** - * @dataProvider upperCaseDependenciesProvider - * - * @param mixed $decorated - */ - public function testUpperCaseCreate($decorated, array $results) - { - $reader = $this->prophesize(Reader::class); - $reader->getPropertyAnnotation(new \ReflectionProperty(UpperCaseIdentifierDummy::class, 'name'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getPropertyAnnotation(new \ReflectionProperty(UpperCaseIdentifierDummy::class, 'Uuid'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(UpperCaseIdentifierDummy::class, 'getName'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(UpperCaseIdentifierDummy::class, 'getUuid'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - - $factory = new AnnotationPropertyNameCollectionFactory($reader->reveal(), $decorated ? $decorated->reveal() : null); - $metadata = $factory->create(UpperCaseIdentifierDummy::class); - - $this->assertEquals($results, iterator_to_array($metadata)); - } - - public function upperCaseDependenciesProvider(): array - { - $decoratedThrowsNotFound = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $decoratedThrowsNotFound->create(UpperCaseIdentifierDummy::class, [])->willThrow(new ResourceClassNotFoundException())->shouldBeCalled(); - - return [ - [null, ['Uuid', 'name']], - [$decoratedThrowsNotFound, ['Uuid', 'name']], - ]; - } - - public function testClassDoesNotExist() - { - $this->expectException(ResourceClassNotFoundException::class); - $this->expectExceptionMessage('The resource class "\\DoNotExist" does not exist.'); - - $reader = $this->prophesize(Reader::class); - - $factory = new AnnotationPropertyNameCollectionFactory($reader->reveal()); - $factory->create('\DoNotExist'); - } -} diff --git a/tests/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactoryTest.php deleted file mode 100644 index 6f6081f1cb2..00000000000 --- a/tests/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactoryTest.php +++ /dev/null @@ -1,86 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiSubresource; -use ApiPlatform\Core\Metadata\Property\Factory\AnnotationSubresourceMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidResourceException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use Doctrine\Common\Annotations\Reader; -use Doctrine\Common\Collections\ArrayCollection; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\PropertyInfo\Type; - -/** - * @group legacy - */ -class AnnotationSubresourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider dependenciesProvider - * - * @param mixed $reader - * @param mixed $decorated - */ - public function testCreateProperty($reader, $decorated) - { - $factory = new AnnotationSubresourceMetadataFactory($reader->reveal(), $decorated->reveal()); - $metadata = $factory->create(Dummy::class, 'relatedDummies'); - - $this->assertEquals(new SubresourceMetadata(RelatedDummy::class, true, null), $metadata->getSubresource()); - } - - public function dependenciesProvider(): array - { - $annotation = new ApiSubresource(); - - $propertyReaderProphecy = $this->prophesize(Reader::class); - $propertyReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiSubresource::class)->willReturn($annotation)->shouldBeCalled(); - - $relatedDummyType = new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class); - $subresourceType = new Type(Type::BUILTIN_TYPE_OBJECT, false, ArrayCollection::class, true, new Type(Type::BUILTIN_TYPE_INT), $relatedDummyType); - - $decoratedReturnProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedReturnProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new PropertyMetadata())->withType($subresourceType)->withDescription('Several dummies'))->shouldBeCalled(); - - return [ - [$propertyReaderProphecy, $decoratedReturnProphecy], - ]; - } - - public function testCreatePropertyUnknownType() - { - $this->expectException(InvalidResourceException::class); - $this->expectExceptionMessage('Property "relatedDummies" on resource "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy" is declared as a subresource, but its type could not be determined.'); - - $annotation = new ApiSubresource(); - - $propertyReaderProphecy = $this->prophesize(Reader::class); - $propertyReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiSubresource::class)->willReturn($annotation)->shouldBeCalled(); - - $decoratedReturnProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedReturnProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new PropertyMetadata())->withDescription('Several dummies'))->shouldBeCalled(); - - $factory = new AnnotationSubresourceMetadataFactory($propertyReaderProphecy->reveal(), $decoratedReturnProphecy->reveal()); - $factory->create(Dummy::class, 'relatedDummies'); - } -} diff --git a/tests/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactoryTest.php deleted file mode 100644 index 4653ed682cb..00000000000 --- a/tests/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,259 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; - -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; -use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\DummyResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use Doctrine\Common\Collections\ArrayCollection; -use Symfony\Component\PropertyInfo\Type; - -/** - * @author Baptiste Meyer - * @group legacy - */ -class ExtractorPropertyMetadataFactoryTest extends FileConfigurationMetadataFactoryProvider -{ - use ProphecyTrait; - - /** - * @dataProvider propertyMetadataProvider - */ - public function testCreateXml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath])); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - /** - * @dataProvider decoratedPropertyMetadataProvider - */ - public function testCreateWithParentPropertyMetadataFactoryXml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - $decorated = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated - ->create(FileConfigDummy::class, 'foo', []) - ->willReturn(new PropertyMetadata(null, null, null, null, true, null, null, false, null, null, ['Foo'], new SubresourceMetadata('Foo', false))) - ->shouldBeCalled(); - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath]), $decorated->reveal()); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - public function testCreateWithNonexistentResourceXml() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "foo" of the resource class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\ThisDoesNotExist" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcenotfound.xml'; - - (new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath])))->create('ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThisDoesNotExist', 'foo'); - } - - public function testCreateWithNonexistentPropertyXml() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "bar" of the resource class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\FileConfigDummy" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - (new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath])))->create(FileConfigDummy::class, 'bar'); - } - - public function testCreateWithInvalidXml() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('#.+Element \'\\{https://api-platform.com/schema/metadata\\}foo\': This element is not expected\\..+#'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/propertyinvalid.xml'; - - (new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - /** - * @dataProvider propertyMetadataProvider - */ - public function testCreateYaml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - /** - * @dataProvider decoratedPropertyMetadataProvider - */ - public function testCreateWithParentPropertyMetadataFactoryYaml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $decorated = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated - ->create(FileConfigDummy::class, 'foo', []) - ->willReturn(new PropertyMetadata(null, null, null, null, true, null, null, false, null, null, ['Foo'], new SubresourceMetadata('Foo', false))) - ->shouldBeCalled(); - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - /** - * @dataProvider decoratedPropertyMetadataProvider - */ - public function testCreateWithCollectionTypedParentPropertyMetadataFactoryYaml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $collectionType = new Type(Type::BUILTIN_TYPE_OBJECT, - false, - ArrayCollection::class, - true, - new Type(Type::BUILTIN_TYPE_INT), - new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class) - ); - - $expectedPropertyMetadata = $expectedPropertyMetadata->withType($collectionType); - $expectedPropertyMetadata = $expectedPropertyMetadata->withSubresource(new SubresourceMetadata(RelatedDummy::class, true, 1)); - - $decorated = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated - ->create(FileConfigDummy::class, 'foo', []) - ->willReturn(new PropertyMetadata($collectionType, null, null, null, true, null, null, false, null, null, ['Foo'], null)) - ->shouldBeCalled(); - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - /** - * @dataProvider decoratedPropertyMetadataProvider - */ - public function testCreateWithTypedParentPropertyMetadataFactoryYaml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $type = new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class); - - $expectedPropertyMetadata = $expectedPropertyMetadata->withType($type); - $expectedPropertyMetadata = $expectedPropertyMetadata->withSubresource(new SubresourceMetadata(RelatedDummy::class, false, 1)); - - $decorated = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated - ->create(FileConfigDummy::class, 'foo', []) - ->willReturn(new PropertyMetadata($type, null, null, null, true, null, null, false, null, null, ['Foo'], null)) - ->shouldBeCalled(); - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - public function testCreateWithNonexistentResourceYaml() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "foo" of the resource class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\ThisDoesNotExist" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcenotfound.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create('ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThisDoesNotExist', 'foo'); - } - - public function testCreateWithNonexistentPropertyYaml() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "bar" of the resource class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\FileConfigDummy" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'bar'); - } - - public function testCreateWithMalformedResourcesSettingYaml() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"resources" setting is expected to be null or an array, string given in ".+\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/resourcesinvalid\\.yml"\\./'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesinvalid.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - public function testCreateWithMalformedPropertiesSettingYaml() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"properties" setting is expected to be null or an array, string given in ".+\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/propertiesinvalid\\.yml"\\./'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/propertiesinvalid.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - public function testCreateWithMalformedPropertySettingYaml() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"foo" setting is expected to be null or an array, string given in ".+\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/propertyinvalid\\.yml"\\./'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/propertyinvalid.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - public function testCreateWithMalformedYaml() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/parse_exception.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - public function testItExtractPropertiesFromInterfaceResources() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/interface_resource.yml'; - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])); - $metadataSomething = $propertyMetadataFactory->create(DummyResourceInterface::class, 'something'); - $metadataSomethingElse = $propertyMetadataFactory->create(DummyResourceInterface::class, 'somethingElse'); - - $this->assertInstanceOf(PropertyMetadata::class, $metadataSomething); - $this->assertInstanceOf(PropertyMetadata::class, $metadataSomethingElse); - $this->assertTrue($metadataSomething->isIdentifier()); - $this->assertFalse($metadataSomethingElse->isWritable()); - } -} diff --git a/tests/Core/Metadata/Property/Factory/FileConfigurationMetadataFactoryProvider.php b/tests/Core/Metadata/Property/Factory/FileConfigurationMetadataFactoryProvider.php deleted file mode 100644 index 431d04b8853..00000000000 --- a/tests/Core/Metadata/Property/Factory/FileConfigurationMetadataFactoryProvider.php +++ /dev/null @@ -1,79 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use PHPUnit\Framework\TestCase; - -/** - * Property metadata provider for file configured factories tests. - * - * @author Baptiste Meyer - * @group legacy - */ -abstract class FileConfigurationMetadataFactoryProvider extends TestCase -{ - public function propertyMetadataProvider() - { - $metadata = [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'attributes' => [ - 'foo' => ['Foo'], - 'bar' => [['Bar'], 'baz' => 'Baz'], - 'baz' => 'Baz', - ], - 'subresource' => new SubresourceMetadata('Foo', true, 1), - ]; - - return [[$this->getPropertyMetadata($metadata)]]; - } - - public function decoratedPropertyMetadataProvider() - { - $metadata = [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => false, - 'attributes' => [ - 'foo' => ['Foo'], - 'bar' => [['Bar'], 'baz' => 'Baz'], - 'baz' => 'Baz', - ], - 'subresource' => new SubresourceMetadata('Foo', false, null), - ]; - - return [[$this->getPropertyMetadata($metadata)]]; - } - - private function getPropertyMetadata(array $metadata): PropertyMetadata - { - $propertyMetadata = new PropertyMetadata(); - - foreach ($metadata as $propertyName => $propertyValue) { - $propertyMetadata = $propertyMetadata->{'with'.ucfirst($propertyName)}($propertyValue); - } - - return $propertyMetadata; - } -} diff --git a/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php deleted file mode 100644 index 84396146240..00000000000 --- a/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,50 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\Factory\InheritedPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; -use PHPUnit\Framework\TestCase; -use Symfony\Component\PropertyInfo\Type; - -/** - * @group legacy - */ -class InheritedPropertyMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreate() - { - $resourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactory->create()->willReturn(new ResourceNameCollection([DummyTableInheritance::class, DummyTableInheritanceChild::class]))->shouldBeCalled(); - - $type = new Type(Type::BUILTIN_TYPE_STRING); - $nicknameMetadata = (new PropertyMetadata())->withType($type)->withDescription('nickname')->withReadable(true)->withWritable(true)->withWritableLink(false)->withReadableLink(false)->withRequired(true)->withIdentifier(false)->withIri('http://example.com/foo')->withAttributes(['foo' => 'bar']); - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create(DummyTableInheritance::class, 'nickname', [])->willReturn($nicknameMetadata)->shouldBeCalled(); - $propertyMetadataFactory->create(DummyTableInheritanceChild::class, 'nickname', [])->willReturn($nicknameMetadata)->shouldBeCalled(); - - $factory = new InheritedPropertyMetadataFactory($resourceNameCollectionFactory->reveal(), $propertyMetadataFactory->reveal()); - $metadata = $factory->create(DummyTableInheritance::class, 'nickname'); - - $this->assertEquals($metadata, $nicknameMetadata->withChildInherited(DummyTableInheritanceChild::class)); - } -} diff --git a/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php b/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php deleted file mode 100644 index a828bf2801b..00000000000 --- a/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php +++ /dev/null @@ -1,62 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\Factory\InheritedPropertyNameCollectionFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class InheritedPropertyNameCollectionFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreateOnParent() - { - $resourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactory->create()->willReturn(new ResourceNameCollection([DummyTableInheritance::class, DummyTableInheritanceChild::class]))->shouldBeCalled(); - - $propertyNameCollectionFactory = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory->create(DummyTableInheritance::class, [])->willReturn(new PropertyNameCollection(['name']))->shouldBeCalled(); - $propertyNameCollectionFactory->create(DummyTableInheritanceChild::class, [])->shouldNotBeCalled(); - - $factory = new InheritedPropertyNameCollectionFactory($resourceNameCollectionFactory->reveal(), $propertyNameCollectionFactory->reveal()); - $metadata = $factory->create(DummyTableInheritance::class); - - $this->assertSame((array) new PropertyNameCollection(['name']), (array) $metadata); - } - - public function testCreateOnChild() - { - $resourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactory->create()->willReturn(new ResourceNameCollection([DummyTableInheritance::class, DummyTableInheritanceChild::class]))->shouldBeCalled(); - - $propertyNameCollectionFactory = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory->create(DummyTableInheritance::class, [])->willReturn(new PropertyNameCollection(['name']))->shouldBeCalled(); - $propertyNameCollectionFactory->create(DummyTableInheritanceChild::class, [])->willReturn(new PropertyNameCollection(['nickname', '169']))->shouldBeCalled(); - - $factory = new InheritedPropertyNameCollectionFactory($resourceNameCollectionFactory->reveal(), $propertyNameCollectionFactory->reveal()); - $metadata = $factory->create(DummyTableInheritanceChild::class); - - $this->assertSame((array) new PropertyNameCollection(['nickname', '169', 'name']), (array) $metadata); - } -} diff --git a/tests/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php deleted file mode 100644 index 7ab32e44c47..00000000000 --- a/tests/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,187 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; - -use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Mapping\AttributeMetadata as SerializerAttributeMetadata; -use Symfony\Component\Serializer\Mapping\ClassMetadata as SerializerClassMetadata; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface as SerializerClassMetadataFactoryInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -/** - * @group legacy - */ -class SerializerPropertyMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $serializerClassMetadataFactoryProphecy = $this->prophesize(SerializerClassMetadataFactoryInterface::class); - $serializerClassMetadataFactory = $serializerClassMetadataFactoryProphecy->reveal(); - - $decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated = $decoratedProphecy->reveal(); - - $serializerPropertyMetadataFactory = new SerializerPropertyMetadataFactory($resourceMetadataFactory, $serializerClassMetadataFactory, $decorated); - - $this->assertInstanceOf(PropertyMetadataFactoryInterface::class, $serializerPropertyMetadataFactory); - } - - /** - * @dataProvider groupsProvider - * - * @param mixed $readGroups - * @param mixed $writeGroups - */ - public function testCreateLegacy($readGroups, $writeGroups, ?string $relatedOutputClass = null) - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $dummyResourceMetadata = (new ResourceMetadata()) - ->withAttributes([ - 'normalization_context' => [ - AbstractNormalizer::GROUPS => $readGroups, - ], - 'denormalization_context' => [ - AbstractNormalizer::GROUPS => $writeGroups, - ], - ]); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata); - $relatedDummyResourceMetadata = new ResourceMetadata(); - if ($relatedOutputClass) { - $relatedDummyResourceMetadata = $relatedDummyResourceMetadata->withAttributes([ - 'output' => ['class' => $relatedOutputClass], - ]); - } - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedDummyResourceMetadata); - - $serializerClassMetadataFactoryProphecy = $this->prophesize(SerializerClassMetadataFactoryInterface::class); - $dummySerializerClassMetadata = new SerializerClassMetadata(Dummy::class); - $fooSerializerAttributeMetadata = new SerializerAttributeMetadata('foo'); - $fooSerializerAttributeMetadata->addGroup('dummy_read'); - $fooSerializerAttributeMetadata->addGroup('dummy_write'); - $dummySerializerClassMetadata->addAttributeMetadata($fooSerializerAttributeMetadata); - $relatedDummySerializerAttributeMetadata = new SerializerAttributeMetadata('relatedDummy'); - $relatedDummySerializerAttributeMetadata->addGroup('dummy_read'); - $relatedDummySerializerAttributeMetadata->addGroup('dummy_write'); - $dummySerializerClassMetadata->addAttributeMetadata($relatedDummySerializerAttributeMetadata); - $nameConvertedSerializerAttributeMetadata = new SerializerAttributeMetadata('nameConverted'); - $dummySerializerClassMetadata->addAttributeMetadata($nameConvertedSerializerAttributeMetadata); - $serializerClassMetadataFactoryProphecy->getMetadataFor(Dummy::class)->willReturn($dummySerializerClassMetadata); - $relatedDummySerializerClassMetadata = new SerializerClassMetadata(RelatedDummy::class); - $nameSerializerAttributeMetadata = new SerializerAttributeMetadata('name'); - $nameSerializerAttributeMetadata->addGroup('dummy_read'); - $relatedDummySerializerClassMetadata->addAttributeMetadata($nameSerializerAttributeMetadata); - $serializerClassMetadataFactoryProphecy->getMetadataFor(RelatedDummy::class)->willReturn($relatedDummySerializerClassMetadata); - $dummyCarSerializerClassMetadata = new SerializerClassMetadata(DummyCar::class); - $nameSerializerAttributeMetadata = new SerializerAttributeMetadata('name'); - $nameSerializerAttributeMetadata->addGroup('dummy_car_read'); - $nameSerializerAttributeMetadata->addGroup('dummy_write'); - $dummyCarSerializerClassMetadata->addAttributeMetadata($nameSerializerAttributeMetadata); - $serializerClassMetadataFactoryProphecy->getMetadataFor(DummyCar::class)->willReturn($dummyCarSerializerClassMetadata); - - $decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $fooPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_ARRAY, true)) - ->withReadable(false) - ->withWritable(true); - $decoratedProphecy->create(Dummy::class, 'foo', [])->willReturn($fooPropertyMetadata); - $relatedDummyPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class)); - $decoratedProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn($relatedDummyPropertyMetadata); - $nameConvertedPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, true)); - $decoratedProphecy->create(Dummy::class, 'nameConverted', [])->willReturn($nameConvertedPropertyMetadata); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - $resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class); - - $serializerPropertyMetadataFactory = new SerializerPropertyMetadataFactory($resourceMetadataFactoryProphecy->reveal(), $serializerClassMetadataFactoryProphecy->reveal(), $decoratedProphecy->reveal(), $resourceClassResolverProphecy->reveal()); - - $actual = []; - $actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'foo'); - $actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'relatedDummy'); - $actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'nameConverted'); - - $this->assertInstanceOf(PropertyMetadata::class, $actual[0]); - $this->assertFalse($actual[0]->isReadable()); - $this->assertTrue($actual[0]->isWritable()); - - $this->assertInstanceOf(PropertyMetadata::class, $actual[1]); - $this->assertTrue($actual[1]->isReadable()); - $this->assertTrue($actual[1]->isWritable()); - if ($relatedOutputClass) { - $this->assertFalse($actual[1]->isReadableLink()); - $this->assertTrue($actual[1]->isWritableLink()); - } else { - $this->assertTrue($actual[1]->isReadableLink()); - $this->assertFalse($actual[1]->isWritableLink()); - } - - $this->assertInstanceOf(PropertyMetadata::class, $actual[2]); - $this->assertFalse($actual[2]->isReadable()); - $this->assertFalse($actual[2]->isWritable()); - } - - public function groupsProvider(): array - { - return [ - [['dummy_read'], ['dummy_write']], - ['dummy_read', 'dummy_write'], - ['dummy_read', 'dummy_write', DummyCar::class], - ]; - } - - /** - * @group legacy - */ - public function testCreateInherited(): void - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyTableInheritanceChild::class)->willReturn(new ResourceMetadata()); - - $serializerClassMetadataFactoryProphecy = $this->prophesize(SerializerClassMetadataFactoryInterface::class); - $dummySerializerClassMetadata = new SerializerClassMetadata(DummyTableInheritanceChild::class); - $serializerClassMetadataFactoryProphecy->getMetadataFor(DummyTableInheritanceChild::class)->willReturn($dummySerializerClassMetadata); - - $decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $fooPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_ARRAY, true)) - ->withChildInherited(DummyTableInheritanceChild::class); - $decoratedProphecy->create(DummyTableInheritance::class, 'nickname', [])->willReturn($fooPropertyMetadata); - - $serializerPropertyMetadataFactory = new SerializerPropertyMetadataFactory($resourceMetadataFactoryProphecy->reveal(), $serializerClassMetadataFactoryProphecy->reveal(), $decoratedProphecy->reveal()); - - $actual = $serializerPropertyMetadataFactory->create(DummyTableInheritance::class, 'nickname'); - - $this->assertEquals($actual->getChildInherited(), DummyTableInheritanceChild::class); - } -} diff --git a/tests/Core/Metadata/Property/PropertyMetadataTest.php b/tests/Core/Metadata/Property/PropertyMetadataTest.php deleted file mode 100644 index d1c0d0a3add..00000000000 --- a/tests/Core/Metadata/Property/PropertyMetadataTest.php +++ /dev/null @@ -1,115 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Property; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use PHPUnit\Framework\TestCase; -use Symfony\Component\PropertyInfo\Type; - -/** - * @author Kévin Dunglas - */ -class PropertyMetadataTest extends TestCase -{ - public function testValueObject() - { - $type = new Type(Type::BUILTIN_TYPE_STRING); - $metadata = new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'desc', true, true, false, false, true, false, 'http://example.com/foo', null, ['foo' => 'bar']); - $this->assertEquals($type, $metadata->getType()); - $this->assertEquals('desc', $metadata->getDescription()); - $this->assertTrue($metadata->isReadable()); - $this->assertTrue($metadata->isWritable()); - $this->assertFalse($metadata->isReadableLink()); - $this->assertFalse($metadata->isWritableLink()); - $this->assertTrue($metadata->isRequired()); - $this->assertFalse($metadata->isIdentifier()); - $this->assertEquals('http://example.com/foo', $metadata->getIri()); - $this->assertEquals(['foo' => 'bar'], $metadata->getAttributes()); - - $newType = new Type(Type::BUILTIN_TYPE_BOOL); - $newMetadata = $metadata->withType($newType); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals($newType, $newMetadata->getType()); - - $newMetadata = $metadata->withDescription('description'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals('description', $newMetadata->getDescription()); - - $newMetadata = $metadata->withReadable(false); - $this->assertNotSame($metadata, $newMetadata); - $this->assertFalse($newMetadata->isReadable()); - - $newMetadata = $metadata->withWritable(false); - $this->assertNotSame($metadata, $newMetadata); - $this->assertFalse($newMetadata->isWritable()); - - $newMetadata = $metadata->withReadableLink(true); - $this->assertNotSame($metadata, $newMetadata); - $this->assertTrue($newMetadata->isReadableLink()); - - $newMetadata = $metadata->withWritableLink(true); - $this->assertNotSame($metadata, $newMetadata); - $this->assertTrue($newMetadata->isWritableLink()); - - $newMetadata = $metadata->withRequired(false); - $this->assertNotSame($metadata, $newMetadata); - $this->assertFalse($newMetadata->isRequired()); - - $newMetadata = $metadata->withIdentifier(true); - $this->assertNotSame($metadata, $newMetadata); - $this->assertTrue($newMetadata->isIdentifier()); - - $newMetadata = $metadata->withIri('foo:bar'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals('foo:bar', $newMetadata->getIri()); - - $newMetadata = $metadata->withAttributes(['a' => 'b']); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals(['a' => 'b'], $newMetadata->getAttributes()); - $this->assertEquals('b', $newMetadata->getAttribute('a')); - - $newMetadata = $metadata->withInitializable(true); - $this->assertNotSame($metadata, $newMetadata); - $this->assertTrue($newMetadata->isInitializable()); - - $newMetadata = $metadata->withDefault('foobar'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals('foobar', $newMetadata->getDefault()); - - $newMetadata = $metadata->withExample('foobarexample'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals('foobarexample', $newMetadata->getExample()); - } - - public function testShouldReturnRequiredFalseWhenRequiredTrueIsSetButMaskedByWritableFalse() - { - $metadata = new PropertyMetadata(); - - $metadata = $metadata->withRequired(true); - $metadata = $metadata->withWritable(false); - - $this->assertFalse($metadata->isRequired()); - } - - public function testShouldReturnPreviouslySetRequiredTrueWhenWritableFalseUnmasked() - { - $metadata = new PropertyMetadata(); - - $metadata = $metadata->withRequired(true); - $metadata = $metadata->withWritable(false); - $metadata = $metadata->withWritable(true); - - $this->assertTrue($metadata->isRequired()); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php deleted file mode 100644 index 75f35871ff7..00000000000 --- a/tests/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php +++ /dev/null @@ -1,55 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Metadata\Resource\Factory\AnnotationResourceFilterMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Orm\Filter\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class AnnotationResourceFilterMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreate() - { - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(Dummy::class)->willReturn(new ResourceMetadata('hello', 'blabla'))->shouldBeCalled(); - - $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotations(Argument::type(\ReflectionClass::class))->shouldBeCalled()->willReturn([ // @phpstan-ignore-next-line - new ApiFilter(['value' => DummyFilter::class]), - ]); - - $reader->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->shouldBeCalled()->willReturn([]); - - $factory = new AnnotationResourceFilterMetadataFactory($reader->reveal(), $decorated->reveal()); - - $metadata = $factory->create(Dummy::class); - - $this->assertEquals(['filters' => [ - 'annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_doctrine_orm_filter_dummy_filter', - ]], $metadata->getAttributes()); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php deleted file mode 100644 index bfd09e60dd2..00000000000 --- a/tests/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php +++ /dev/null @@ -1,156 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Metadata\Resource\Factory\AnnotationResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class AnnotationResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider getCreateDependencies - * - * @param mixed $reader - * @param mixed $decorated - */ - public function testCreate($reader, $decorated, string $expectedShortName, ?string $expectedDescription) - { - $factory = new AnnotationResourceMetadataFactory($reader->reveal(), $decorated ? $decorated->reveal() : null); - $metadata = $factory->create(Dummy::class); - - $this->assertEquals($expectedShortName, $metadata->getShortName()); - $this->assertEquals($expectedDescription, $metadata->getDescription()); - $this->assertEquals('http://example.com', $metadata->getIri()); - $this->assertEquals(['foo' => ['bar' => true]], $metadata->getItemOperations()); - $this->assertEquals(['baz' => ['tab' => false]], $metadata->getCollectionOperations()); - $this->assertEquals(['sub' => ['bus' => false]], $metadata->getSubresourceOperations()); - $this->assertEquals(['a' => 1, 'route_prefix' => '/foobar', 'stateless' => false], $metadata->getAttributes()); - $this->assertEquals(['foo' => 'bar'], $metadata->getGraphql()); - } - - /** - * @requires PHP 8.0 - */ - public function testCreateAttribute() - { - $factory = new AnnotationResourceMetadataFactory(); - $metadata = $factory->create(DummyPhp8::class); - - $this->assertSame('Hey PHP 8', $metadata->getDescription()); - } - - public function testCreateWithDefaults() - { - $defaults = [ - 'shortName' => 'Default shortname should not be ignored', - 'description' => 'CHANGEME!', - 'collection_operations' => ['get'], - 'item_operations' => ['get', 'put'], - 'attributes' => [ - 'pagination_items_per_page' => 4, - 'pagination_maximum_items_per_page' => 6, - 'stateless' => true, - ], - ]; - - $annotation = new ApiResource([ - 'itemOperations' => ['get', 'delete'], - 'attributes' => [ - 'pagination_client_enabled' => true, - 'pagination_maximum_items_per_page' => 10, - 'stateless' => null, - ], - ]); - $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotation)->shouldBeCalled(); - $factory = new AnnotationResourceMetadataFactory($reader->reveal(), null, $defaults); - $metadata = $factory->create(Dummy::class); - - $this->assertNull($metadata->getShortName()); - $this->assertEquals('CHANGEME!', $metadata->getDescription()); - $this->assertEquals(['get'], $metadata->getCollectionOperations()); - $this->assertEquals(['get', 'delete'], $metadata->getItemOperations()); - $this->assertTrue($metadata->getAttribute('pagination_client_enabled')); - $this->assertEquals(4, $metadata->getAttribute('pagination_items_per_page')); - $this->assertEquals(10, $metadata->getAttribute('pagination_maximum_items_per_page')); - $this->assertTrue($metadata->getAttribute('stateless')); - } - - public function testCreateWithoutAttributes() - { - $annotation = new ApiResource([]); - $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotation)->shouldBeCalled(); - $factory = new AnnotationResourceMetadataFactory($reader->reveal(), null); - $metadata = $factory->create(Dummy::class); - - $this->assertNull($metadata->getAttributes()); - } - - public function getCreateDependencies() - { - $resourceData = [ - 'shortName' => 'shortName', - 'description' => 'description', - 'iri' => 'http://example.com', - 'itemOperations' => ['foo' => ['bar' => true]], - 'collectionOperations' => ['baz' => ['tab' => false]], - 'subresourceOperations' => ['sub' => ['bus' => false]], - 'attributes' => ['a' => 1, 'route_prefix' => '/foobar'], - 'graphql' => ['foo' => 'bar'], - 'stateless' => false, - ]; - $annotationFull = new ApiResource($resourceData); - - $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotationFull)->shouldBeCalled(); - - $decoratedThrow = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedThrow->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); - - $decoratedReturn = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedReturn->create(Dummy::class)->willReturn(new ResourceMetadata('hello', 'blabla'))->shouldBeCalled(); - - $resourceData['description'] = null; - $annotationWithNull = new ApiResource($resourceData); - - $decoratedReturnWithNull = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedReturnWithNull->create(Dummy::class)->willReturn(new ResourceMetadata('hello'))->shouldBeCalled(); - - $readerWithNull = $this->prophesize(Reader::class); - $readerWithNull->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotationWithNull)->shouldBeCalled(); - - return [ - [$reader, $decoratedThrow, 'shortName', 'description'], - [$reader, null, 'shortName', 'description'], - [$reader, $decoratedReturn, 'hello', 'blabla'], - [$readerWithNull, $decoratedReturnWithNull, 'hello', null], - ]; - } -} diff --git a/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php b/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php deleted file mode 100644 index 97f62394e43..00000000000 --- a/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php +++ /dev/null @@ -1,52 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\AnnotationResourceNameCollectionFactory; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Antoine Bluchet - */ -class AnnotationResourceNameCollectionFactoryTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function testCreate() - { - $decorated = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $decorated->create()->willReturn(new ResourceNameCollection(['foo', 'bar']))->shouldBeCalled(); - - $reader = $this->prophesize(Reader::class); - - $metadata = new AnnotationResourceNameCollectionFactory($reader->reveal(), [], $decorated->reveal()); - - $this->assertEquals(new ResourceNameCollection(['foo', 'bar']), $metadata->create()); - } - - public function testCreateAttribute() - { - $decorated = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $decorated->create()->willReturn(new ResourceNameCollection(['foo', 'bar']))->shouldBeCalled(); - - $metadata = new AnnotationResourceNameCollectionFactory(null, [], $decorated->reveal()); - $this->assertEquals(new ResourceNameCollection(['foo', 'bar']), $metadata->create()); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php deleted file mode 100644 index d972c6a3101..00000000000 --- a/tests/Core/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php +++ /dev/null @@ -1,96 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\CachedResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @author Baptiste Meyer - * @group legacy - */ -class CachedResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreateWithItemHit() - { - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(true)->shouldBeCalled(); - $cacheItem->get()->willReturn(new ResourceMetadata(null, 'Dummy.'))->shouldBeCalled(); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willReturn($cacheItem->reveal())->shouldBeCalled(); - - $decoratedResourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $cachedResourceMetadataFactory = new CachedResourceMetadataFactory($cacheItemPool->reveal(), $decoratedResourceMetadataFactory->reveal()); - $resultedResourceMetadata = $cachedResourceMetadataFactory->create(Dummy::class); - - $this->assertEquals(new ResourceMetadata(null, 'Dummy.'), $resultedResourceMetadata); - } - - public function testCreateWithItemNotHit() - { - $propertyMetadata = new ResourceMetadata(null, 'Dummy.'); - - $decoratedResourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedResourceMetadataFactory->create(Dummy::class)->willReturn($propertyMetadata)->shouldBeCalled(); - - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(false)->shouldBeCalled(); - $cacheItem->set($propertyMetadata)->willReturn($cacheItem->reveal())->shouldBeCalled(); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willReturn($cacheItem->reveal())->shouldBeCalled(); - $cacheItemPool->save($cacheItem->reveal())->willReturn(true)->shouldBeCalled(); - - $cachedResourceMetadataFactory = new CachedResourceMetadataFactory($cacheItemPool->reveal(), $decoratedResourceMetadataFactory->reveal()); - $resultedResourceMetadata = $cachedResourceMetadataFactory->create(Dummy::class); - - $expectedResult = new ResourceMetadata(null, 'Dummy.'); - $this->assertEquals($expectedResult, $resultedResourceMetadata); - $this->assertEquals($expectedResult, $cachedResourceMetadataFactory->create(Dummy::class), 'Trigger the local cache'); - } - - public function testCreateWithGetCacheItemThrowsCacheException() - { - $decoratedResourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedResourceMetadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, 'Dummy.'))->shouldBeCalled(); - - $cacheException = new class() extends \Exception implements CacheException {}; - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willThrow($cacheException)->shouldBeCalled(); - - $cachedResourceMetadataFactory = new CachedResourceMetadataFactory($cacheItemPool->reveal(), $decoratedResourceMetadataFactory->reveal()); - $resultedResourceMetadata = $cachedResourceMetadataFactory->create(Dummy::class); - - $expectedResult = new ResourceMetadata(null, 'Dummy.'); - $this->assertEquals($expectedResult, $resultedResourceMetadata); - $this->assertEquals($expectedResult, $cachedResourceMetadataFactory->create(Dummy::class), 'Trigger the local cache'); - } - - private function generateCacheKey(string $resourceClass = Dummy::class) - { - return CachedResourceMetadataFactory::CACHE_KEY_PREFIX.md5($resourceClass); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php b/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php deleted file mode 100644 index 3965c3375f0..00000000000 --- a/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php +++ /dev/null @@ -1,92 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Resource\Factory\CachedResourceNameCollectionFactory; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @author Baptiste Meyer - */ -class CachedResourceNameCollectionFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreateWithItemHit() - { - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(true)->shouldBeCalled(); - $cacheItem->get()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem(CachedResourceNameCollectionFactory::CACHE_KEY)->willReturn($cacheItem->reveal())->shouldBeCalled(); - - $decoratedResourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - - $cachedResourceNameCollectionFactory = new CachedResourceNameCollectionFactory($cacheItemPool->reveal(), $decoratedResourceNameCollectionFactory->reveal()); - $resultedResourceNameCollection = $cachedResourceNameCollectionFactory->create(); - - $expectedResult = new ResourceNameCollection([Dummy::class]); - $this->assertEquals($expectedResult, $resultedResourceNameCollection); - $this->assertEquals($expectedResult, $cachedResourceNameCollectionFactory->create(), 'Trigger the local cache'); - } - - public function testCreateWithItemNotHit() - { - $resourceNameCollection = new ResourceNameCollection([Dummy::class]); - - $decoratedResourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $decoratedResourceNameCollectionFactory->create()->willReturn($resourceNameCollection)->shouldBeCalled(); - - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(false)->shouldBeCalled(); - $cacheItem->set($resourceNameCollection)->willReturn($cacheItem->reveal())->shouldBeCalled(); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem(CachedResourceNameCollectionFactory::CACHE_KEY)->willReturn($cacheItem->reveal())->shouldBeCalled(); - $cacheItemPool->save($cacheItem->reveal())->willReturn(true)->shouldBeCalled(); - - $cachedResourceNameCollectionFactory = new CachedResourceNameCollectionFactory($cacheItemPool->reveal(), $decoratedResourceNameCollectionFactory->reveal()); - $resultedResourceNameCollection = $cachedResourceNameCollectionFactory->create(); - - $expectedResult = new ResourceNameCollection([Dummy::class]); - $this->assertEquals($expectedResult, $resultedResourceNameCollection); - $this->assertEquals($expectedResult, $cachedResourceNameCollectionFactory->create(), 'Trigger the local cache'); - } - - public function testCreateWithGetCacheItemThrowsCacheException() - { - $decoratedResourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $decoratedResourceNameCollectionFactory->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $cacheException = new class() extends \Exception implements CacheException {}; - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem(CachedResourceNameCollectionFactory::CACHE_KEY)->willThrow($cacheException)->shouldBeCalled(); - - $cachedResourceNameCollectionFactory = new CachedResourceNameCollectionFactory($cacheItemPool->reveal(), $decoratedResourceNameCollectionFactory->reveal()); - $resultedResourceNameCollection = $cachedResourceNameCollectionFactory->create(); - - $expectedResult = new ResourceNameCollection([Dummy::class]); - $this->assertEquals($expectedResult, $resultedResourceNameCollection); - $this->assertEquals($expectedResult, $cachedResourceNameCollectionFactory->create(), 'Trigger the local cache'); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php deleted file mode 100644 index 629aee72ef3..00000000000 --- a/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php +++ /dev/null @@ -1,361 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Extractor\ExtractorInterface; -use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; -use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Core\Metadata\Resource\Factory\ExtractorResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ShortNameResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ExtractorResourceNameCollectionFactory; -use ApiPlatform\Tests\Fixtures\DummyResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * Tests extractor resource metadata factory. - * - * @author Antoine Bluchet - * @group legacy - */ -class ExtractorResourceMetadataFactoryTest extends FileConfigurationMetadataFactoryProvider -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - /** - * @dataProvider resourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testXmlCreateResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - public function testXmlDoesNotExistMetadataFactory() - { - $this->expectException(ResourceClassNotFoundException::class); - $this->expectExceptionMessage('Resource "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\ThisDoesNotExist" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcenotfound.xml'; - $factory = new ExtractorResourceNameCollectionFactory(new XmlExtractor([$configPath])); - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - - foreach ($factory->create() as $resourceName) { - $resourceMetadataFactory->create($resourceName); - } - } - - /** - * @dataProvider optionalResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testXmlOptionalResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesoptional.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @expectedDeprecation Configuring "%s" tags without using a parent "%ss" tag is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - * @group legacy - * @dataProvider legacyOperationsResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testLegacyOperationsResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/legacyoperations.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider noCollectionOperationsResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testXmlNoCollectionOperationsResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/nocollectionoperations.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider noItemOperationsResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testXmlNoItemOperationsResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/noitemoperations.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - public function testInvalidXmlResourceMetadataFactory() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesinvalid.xml'; - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - - $resourceMetadataFactory->create(FileConfigDummy::class); - } - - /** - * @dataProvider optionalResourceMetadataProvider - */ - public function testXmlParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesoptional.xml'; - - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn(new ResourceMetadata(null, 'test'))->shouldBeCalled(); - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath]), $decorated->reveal()); - - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - $expectedResourceMetadata = $expectedResourceMetadata->withDescription('test'); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider resourceMetadataProvider - */ - public function testXmlExistingParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn($expectedResourceMetadata)->shouldBeCalled(); - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath]), $decorated->reveal()); - - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider resourceMetadataProvider - */ - public function testYamlCreateResourceMetadata(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - public function testYamlDoesNotExistMetadataFactory() - { - $this->expectException(ResourceClassNotFoundException::class); - $this->expectExceptionMessage('Resource "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\ThisDoesNotExist" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcenotfound.yml'; - $factory = new ExtractorResourceNameCollectionFactory(new YamlExtractor([$configPath])); - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - - foreach ($factory->create() as $resourceName) { - $resourceMetadataFactory->create($resourceName); - } - } - - /** - * @dataProvider optionalResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testYamlOptionalResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesoptional.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider resourceMetadataProvider - */ - public function testYamlSingleResourceMetadata(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/single_resource.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider optionalResourceMetadataProvider - */ - public function testYamlParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesoptional.yml'; - - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn(new ResourceMetadata(null, 'test'))->shouldBeCalled(); - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - $expectedResourceMetadata = $expectedResourceMetadata->withDescription('test'); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider resourceMetadataProvider - */ - public function testYamlExistingParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn($expectedResourceMetadata)->shouldBeCalled(); - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - public function testCreateWithMalformedYaml() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/parse_exception.yml'; - - (new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class); - } - - public function testCreateWithBadDeclaration() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"ApiPlatform\\\\Tests\\\\Fixtures\\\\TestBundle\\\\Entity\\\\Dummy" setting is expected to be null or an array, string given in ".+\\/Fixtures\\/FileConfigurations\\/bad_declaration\\.yml"\\./'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/bad_declaration.yml'; - - (new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class); - } - - public function testCreateShortNameResourceMetadataForClassWithoutNamespace() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourceswithoutnamespace.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $shortNameResourceMetadataFactory = new ShortNameResourceMetadataFactory($resourceMetadataFactory); - - $resourceMetadata = $shortNameResourceMetadataFactory->create(\DateTime::class); - $this->assertSame(\DateTime::class, $resourceMetadata->getShortName()); - } - - public function testItSupportsInterfaceAsAResource() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/interface_resource.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $shortNameResourceMetadataFactory = new ShortNameResourceMetadataFactory($resourceMetadataFactory); - - $resourceMetadata = $shortNameResourceMetadataFactory->create(DummyResourceInterface::class); - $this->assertSame('DummyResourceInterface', $resourceMetadata->getShortName()); - } - - public function testItFallbacksToDefaultConfiguration() - { - $defaults = [ - 'shortName' => 'Default shortname should not be ignored', - 'description' => 'CHANGEME!', - 'collection_operations' => ['get'], - 'item_operations' => ['get', 'put'], - 'attributes' => [ - 'pagination_items_per_page' => 4, - 'pagination_maximum_items_per_page' => 6, - 'stateless' => true, - ], - ]; - $resourceConfiguration = [ - Dummy::class => [ - 'shortName' => null, - 'description' => null, - 'subresourceOperations' => null, - 'itemOperations' => ['get', 'delete'], - 'attributes' => [ - 'pagination_items_per_page' => null, - 'pagination_maximum_items_per_page' => 10, - 'stateless' => false, - ], - ], - ]; - - $extractor = new class($resourceConfiguration) implements ExtractorInterface { - private $resources; - - public function __construct(array $resources) - { - $this->resources = $resources; - } - - public function getResources(): array - { - return $this->resources; - } - }; - $factory = new ExtractorResourceMetadataFactory($extractor, null, $defaults); - $metadata = $factory->create(Dummy::class); - - $this->assertNull($metadata->getShortName()); - $this->assertEquals('CHANGEME!', $metadata->getDescription()); - $this->assertEquals(['get'], $metadata->getCollectionOperations()); - $this->assertEquals(['get', 'delete'], $metadata->getItemOperations()); - $this->assertEquals(4, $metadata->getAttribute('pagination_items_per_page')); - $this->assertEquals(10, $metadata->getAttribute('pagination_maximum_items_per_page')); - $this->assertFalse($metadata->getAttribute('stateless')); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php b/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php deleted file mode 100644 index a8617b5216a..00000000000 --- a/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php +++ /dev/null @@ -1,79 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; -use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Metadata\Resource\Factory\ExtractorResourceNameCollectionFactory; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; -use PHPUnit\Framework\TestCase; - -/** - * Tests extractor resource name collection factory. - * - * @author Antoine Bluchet - */ -class ExtractorResourceNameCollectionFactoryTest extends TestCase -{ - public function testXmlResourceName() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - $factory = new ExtractorResourceNameCollectionFactory(new XmlExtractor([$configPath])); - - $this->assertEquals($factory->create(), new ResourceNameCollection([ - Dummy::class, - FileConfigDummy::class, - ])); - } - - public function testInvalidExtractorResourceNameCollectionFactory() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesinvalid.xml'; - $factory = new ExtractorResourceNameCollectionFactory(new XmlExtractor([$configPath])); - $factory->create(); - } - - public function testYamlResourceName() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - $factory = new ExtractorResourceNameCollectionFactory(new YamlExtractor([$configPath])); - - $this->assertEquals($factory->create(), new ResourceNameCollection([ - Dummy::class, - FileConfigDummy::class, - ])); - } - - public function testYamlSingleResourceName() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/single_resource.yml'; - $factory = new ExtractorResourceNameCollectionFactory(new YamlExtractor([$configPath])); - - $this->assertEquals($factory->create(), new ResourceNameCollection([FileConfigDummy::class])); - } - - public function testCreateWithMalformedYaml() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/parse_exception.yml'; - - (new ExtractorResourceNameCollectionFactory(new YamlExtractor([$configPath])))->create(); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php b/tests/Core/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php deleted file mode 100644 index 39c81511c39..00000000000 --- a/tests/Core/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php +++ /dev/null @@ -1,114 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -/** - * Resource metadata provider for file configured factories tests. - * - * @author Antoine Bluchet - */ -abstract class FileConfigurationMetadataFactoryProvider extends TestCase -{ - public function resourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - - $metadata = [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'itemOperations' => [ - 'my_op_name' => ['method' => 'GET'], - 'my_other_op_name' => ['method' => 'POST'], - ], - 'collectionOperations' => [ - 'my_collection_op' => ['method' => 'POST', 'path' => 'the/collection/path'], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => ['path' => 'the/subresource/path'], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - AbstractNormalizer::GROUPS => ['graphql'], - ], - ], - ], - 'iri' => 'someirischema', - 'attributes' => [ - 'normalization_context' => [ - AbstractNormalizer::GROUPS => ['default'], - ], - 'denormalization_context' => [ - AbstractNormalizer::GROUPS => ['default'], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - 'stateless' => true, - ], - ]; - - foreach (['shortName', 'description', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'iri', 'attributes'] as $property) { - $wither = 'with'.ucfirst($property); - $resourceMetadata = $resourceMetadata->{$wither}($metadata[$property]); - } - - return [[$resourceMetadata]]; - } - - public function optionalResourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withItemOperations(['my_op_name' => ['method' => 'POST']]); - - return [[$resourceMetadata]]; - } - - public function noCollectionOperationsResourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withItemOperations(['my_op_name' => ['method' => 'POST']]); - $resourceMetadata = $resourceMetadata->withCollectionOperations([]); - - return [[$resourceMetadata]]; - } - - public function noItemOperationsResourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withCollectionOperations(['my_op_name' => ['method' => 'POST']]); - $resourceMetadata = $resourceMetadata->withItemOperations([]); - - return [[$resourceMetadata]]; - } - - public function legacyOperationsResourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'my_op_name' => ['method' => 'POST'], - 'my_other_op_name' => ['method' => 'GET'], - ]); - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'my_op_name' => ['method' => 'POST'], - ]); - - return [[$resourceMetadata]]; - } -} diff --git a/tests/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactoryTest.php deleted file mode 100644 index 6f247ff792f..00000000000 --- a/tests/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactoryTest.php +++ /dev/null @@ -1,193 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\FormatsResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class FormatsResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider createProvider - */ - public function testCreate(ResourceMetadata $previous, ResourceMetadata $expected, array $formats = [], array $patchFormats = []): void - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($previous); - - $actual = (new FormatsResourceMetadataFactory($resourceMetadataFactoryProphecy->reveal(), $formats, $patchFormats))->create('Foo'); - $this->assertEquals($expected, $actual); - } - - public function createProvider(): iterable - { - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => []], - ['get' => []], - ['formats' => 'json'], - ['get' => []] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]], - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]], - ['formats' => 'json'], - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]] - ), - ['json' => ['application/json']], - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => []], - ['get' => []], - ['formats' => ['json' => ['application/json']]], - ['get' => []] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]], - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]], - ['formats' => ['json' => ['application/json']]], - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]] - ), - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => []], - ['get' => []], - ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => 'text/csv']], - ['get' => []] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => ['text/csv']]]], - ['get' => ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => ['text/csv']]]], - ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => 'text/csv']], - ['get' => ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => ['text/csv']]]] - ), - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['patch' => ['method' => 'PATCH']] - ), - new ResourceMetadata( - null, - null, - null, - ['patch' => ['method' => 'PATCH', 'input_formats' => ['json' => ['application/merge-patch+json']], 'output_formats' => []]] - ), - [], - ['json' => ['application/merge-patch+json']], - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => ['formats' => 'json']] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['formats' => ['json' => ['application/json']], 'input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]] - ), - ['json' => ['application/json']], - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => 'json', 'output_formats' => 'json']] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]] - ), - ['json' => ['application/json']], - ]; - } - - public function testInvalidFormatType(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes value must be a string when trying to include an already configured format, object given.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - null, - ['formats' => [new \stdClass()]] - )); - - (new FormatsResourceMetadataFactory($resourceMetadataFactoryProphecy->reveal(), [], []))->create('Foo'); - } - - public function testNotConfiguredFormat(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('You either need to add the format \'xml\' to your project configuration or declare a mime type for it in your annotation.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - null, - ['formats' => ['xml']] - )); - - (new FormatsResourceMetadataFactory($resourceMetadataFactoryProphecy->reveal(), [], []))->create('Foo'); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php deleted file mode 100644 index 1d3f4ffa862..00000000000 --- a/tests/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php +++ /dev/null @@ -1,77 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\InputOutputResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class InputOutputResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider getAttributes - * - * @param mixed $attributes - * @param mixed $expected - */ - public function testInputOutputMetadata($attributes, $expected) - { - $resourceMetadata = (new ResourceMetadata(null))->withAttributes($attributes); - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new InputOutputResourceMetadataFactory($decorated); - $this->assertSame($expected, $factory->create('Foo')->getAttributes()['input']); - } - - /** - * @dataProvider getAttributes - * - * @param mixed $attributes - * @param mixed $expected - */ - public function testInputOutputViaGraphQlMetadata($attributes, $expected) - { - $resourceMetadata = (new ResourceMetadata(null))->withGraphQl(['create' => $attributes]); - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new InputOutputResourceMetadataFactory($decorated); - $this->assertSame($expected, $factory->create('Foo')->getGraphqlAttribute('create', 'input')); - } - - public function getAttributes(): array - { - return [ - // no input class defined - [[], null], - // input is a string - [['input' => DummyEntity::class], ['class' => DummyEntity::class, 'name' => 'DummyEntity']], - // input is false - [['input' => false], ['class' => null]], - // input is an array - [['input' => ['class' => DummyEntity::class, 'type' => 'Foo']], ['class' => DummyEntity::class, 'type' => 'Foo', 'name' => 'DummyEntity']], - ]; - } -} diff --git a/tests/Core/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php deleted file mode 100644 index 517ff91d407..00000000000 --- a/tests/Core/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php +++ /dev/null @@ -1,79 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\OperationResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class OperationResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider getMetadata - */ - public function testCreateOperation(ResourceMetadata $before, ResourceMetadata $after, array $formats = []): void - { - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($before); - - $this->assertEquals($after, (new OperationResourceMetadataFactory($decoratedProphecy->reveal(), $formats))->create(Dummy::class)); - } - - public function getMetadata(): iterable - { - $jsonapi = ['jsonapi' => ['application/vnd.api+json']]; - - // Item operations - yield [new ResourceMetadata(null, null, null, null, [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['get', 'put', 'delete']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, null, [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['get', 'put', 'patch', 'delete']), [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['get'], [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['get']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['put'], [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['put']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['delete'], [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['delete']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch']], [], null, [], []), new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch', 'stateless' => null]], [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch']], [], null, [], []), new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch', 'stateless' => null]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['untouched' => ['method' => 'GET']], [], null, [], []), new ResourceMetadata(null, null, null, ['untouched' => ['method' => 'GET', 'stateless' => null]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['untouched_custom' => ['route_name' => 'custom_route']], [], null, [], []), new ResourceMetadata(null, null, null, ['untouched_custom' => ['route_name' => 'custom_route', 'stateless' => null]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['stateless_operation' => ['method' => 'GET', 'stateless' => true]], [], null, [], []), new ResourceMetadata(null, null, null, ['stateless_operation' => ['method' => 'GET', 'stateless' => true]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['statefull_attribute' => ['method' => 'GET']], [], ['stateless' => false], [], []), new ResourceMetadata(null, null, null, ['statefull_attribute' => ['method' => 'GET', 'stateless' => false]], [], ['stateless' => false], [], []), $jsonapi]; - - // Collection operations - yield [new ResourceMetadata(null, null, null, [], null, null, [], []), new ResourceMetadata(null, null, null, [], $this->getOperations(['get', 'post']), null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['get'], null, [], []), new ResourceMetadata(null, null, null, [], $this->getOperations(['get']), null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['post'], null, [], []), new ResourceMetadata(null, null, null, [], $this->getOperations(['post']), null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['options' => ['method' => 'OPTIONS', 'route_name' => 'options']], null, [], []), new ResourceMetadata(null, null, null, [], ['options' => ['route_name' => 'options', 'method' => 'OPTIONS', 'stateless' => null]], null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['untouched' => ['method' => 'GET']], null, [], []), new ResourceMetadata(null, null, null, [], ['untouched' => ['method' => 'GET', 'stateless' => null]], null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['untouched_custom' => ['route_name' => 'custom_route']], null, [], []), new ResourceMetadata(null, null, null, [], ['untouched_custom' => ['route_name' => 'custom_route', 'stateless' => null]], null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['statefull_operation' => ['method' => 'GET', 'stateless' => false]], null, null, []), new ResourceMetadata(null, null, null, [], ['statefull_operation' => ['method' => 'GET', 'stateless' => false]], null, null, []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, [], ['stateless_attribute' => ['method' => 'GET']], ['stateless' => true], null, []), new ResourceMetadata(null, null, null, [], ['stateless_attribute' => ['method' => 'GET', 'stateless' => true]], ['stateless' => true], null, []), $jsonapi]; - } - - private function getOperations(array $names): array - { - $operations = []; - foreach ($names as $name) { - $operations[$name] = ['method' => strtoupper($name), 'stateless' => null]; - } - - return $operations; - } -} diff --git a/tests/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php deleted file mode 100644 index 7f75db1f485..00000000000 --- a/tests/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php +++ /dev/null @@ -1,62 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\PhpDocResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\ClassWithNoDocBlock; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class PhpDocResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testExistingDescription() - { - $resourceMetadata = new ResourceMetadata(null, 'My desc'); - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new PhpDocResourceMetadataFactory($decorated); - $this->assertSame($resourceMetadata, $factory->create('Foo')); - } - - public function testNoDocBlock() - { - $resourceMetadata = new ResourceMetadata(); - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(ClassWithNoDocBlock::class)->willReturn($resourceMetadata)->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new PhpDocResourceMetadataFactory($decorated); - $this->assertSame($resourceMetadata, $factory->create(ClassWithNoDocBlock::class)); - } - - public function testExtractDescription() - { - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(DummyEntity::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new PhpDocResourceMetadataFactory($decorated); - $this->assertSame('My dummy entity.', $factory->create(DummyEntity::class)->getDescription()); - } -} diff --git a/tests/Core/Metadata/Resource/ResourceMetadataTest.php b/tests/Core/Metadata/Resource/ResourceMetadataTest.php deleted file mode 100644 index 863f5a447f4..00000000000 --- a/tests/Core/Metadata/Resource/ResourceMetadataTest.php +++ /dev/null @@ -1,111 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class ResourceMetadataTest extends TestCase -{ - public function testValueObject() - { - $metadata = new ResourceMetadata('shortName', 'desc', 'http://example.com/foo', ['iop1' => ['foo' => 'a'], 'iop2' => ['bar' => 'b']], ['cop1' => ['foo' => 'c'], 'cop2' => ['bar' => 'd']], ['baz' => 'bar'], ['sop1' => ['sub' => 'bus']], ['query' => ['foo' => 'graphql']]); - $this->assertSame('shortName', $metadata->getShortName()); - $this->assertSame('desc', $metadata->getDescription()); - $this->assertSame('http://example.com/foo', $metadata->getIri()); - $this->assertSame(['iop1' => ['foo' => 'a'], 'iop2' => ['bar' => 'b']], $metadata->getItemOperations()); - $this->assertSame('a', $metadata->getItemOperationAttribute('iop1', 'foo', 'z')); - $this->assertSame('a', $metadata->getTypedOperationAttribute(OperationType::ITEM, 'iop1', 'foo', 'z')); - $this->assertSame('bar', $metadata->getItemOperationAttribute('iop1', 'baz', 'z', true)); - $this->assertSame('bar', $metadata->getItemOperationAttribute(null, 'baz', 'z', true)); - $this->assertSame('z', $metadata->getItemOperationAttribute('iop1', 'notExist', 'z', true)); - $this->assertSame('z', $metadata->getItemOperationAttribute('notExist', 'notExist', 'z', true)); - $this->assertSame(['cop1' => ['foo' => 'c'], 'cop2' => ['bar' => 'd']], $metadata->getCollectionOperations()); - $this->assertSame('c', $metadata->getCollectionOperationAttribute('cop1', 'foo', 'z')); - $this->assertSame('c', $metadata->getTypedOperationAttribute(OperationType::COLLECTION, 'cop1', 'foo', 'z')); - $this->assertSame('bar', $metadata->getCollectionOperationAttribute('cop1', 'baz', 'z', true)); - $this->assertSame('bar', $metadata->getCollectionOperationAttribute(null, 'baz', 'z', true)); - $this->assertSame('z', $metadata->getCollectionOperationAttribute('cop1', 'notExist', 'z', true)); - $this->assertSame('z', $metadata->getCollectionOperationAttribute('notExist', 'notExist', 'z', true)); - $this->assertSame(['baz' => 'bar'], $metadata->getAttributes()); - $this->assertSame('bar', $metadata->getAttribute('baz')); - $this->assertSame('z', $metadata->getAttribute('notExist', 'z')); - $this->assertSame(['sop1' => ['sub' => 'bus']], $metadata->getSubresourceOperations()); - $this->assertSame('bus', $metadata->getSubresourceOperationAttribute('sop1', 'sub')); - $this->assertSame('bus', $metadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, 'sop1', 'sub')); - $this->assertSame('sub', $metadata->getSubresourceOperationAttribute('sop1', 'bus', 'sub')); - $this->assertSame('bar', $metadata->getSubresourceOperationAttribute('sop1', 'baz', 'sub', true)); - $this->assertSame('graphql', $metadata->getGraphqlAttribute('query', 'foo')); - $this->assertSame('bar', $metadata->getGraphqlAttribute('query', 'baz', null, true)); - $this->assertSame('hey', $metadata->getGraphqlAttribute('query', 'notExist', 'hey', true)); - - $newMetadata = $metadata->withShortName('name'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame('name', $newMetadata->getShortName()); - - $newMetadata = $metadata->withDescription('description'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame('description', $newMetadata->getDescription()); - - $newMetadata = $metadata->withIri('foo:bar'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame('foo:bar', $newMetadata->getIri()); - - $newMetadata = $metadata->withItemOperations(['a' => ['b' => 'c']]); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame(['a' => ['b' => 'c']], $newMetadata->getItemOperations()); - } - - /** - * @dataProvider getWithMethods - * - * @param mixed $value - */ - public function testWithMethods(string $name, $value) - { - $metadata = new ResourceMetadata(); - $newMetadata = $metadata->{"with$name"}($value); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame($value, $newMetadata->{"get$name"}()); - } - - public function testGetOperationAttributeFallback() - { - $metadata = new ResourceMetadata(); - $this->assertSame('okay', $metadata->getOperationAttribute([], 'doh', 'okay')); - } - - public function testGetOperationAttributeFallbackToResourceAttribute() - { - $metadata = new ResourceMetadata(null, null, null, null, null, ['doh' => 'nuts']); - $this->assertSame('nuts', $metadata->getOperationAttribute([], 'doh', 'okay', true)); - } - - public function getWithMethods(): array - { - return [ - ['ShortName', 'shortName'], - ['Description', 'description'], - ['Iri', 'iri'], - ['ItemOperations', ['a' => ['b' => 'c']]], - ['CollectionOperations', ['a' => ['b' => 'c']]], - ['Attributes', ['a' => ['b' => 'c']]], - ['Graphql', ['query' => ['b' => 'c']]], - ]; - } -} diff --git a/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php b/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php deleted file mode 100644 index a36905990eb..00000000000 --- a/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php +++ /dev/null @@ -1,32 +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); - -namespace ApiPlatform\Core\Tests\Metadata\Resource; - -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class ResourceNameCollectionTest extends TestCase -{ - public function testValueObject() - { - $collection = new ResourceNameCollection(['foo', 'bar']); - $this->assertInstanceOf(\Countable::class, $collection); - $this->assertInstanceOf(\IteratorAggregate::class, $collection); - $this->assertCount(2, $collection); - $this->assertInstanceOf(\ArrayIterator::class, $collection->getIterator()); - } -} diff --git a/tests/Core/Metadata/schema/XmlSchemaTest.php b/tests/Core/Metadata/schema/XmlSchemaTest.php deleted file mode 100644 index a54fa18e6dc..00000000000 --- a/tests/Core/Metadata/schema/XmlSchemaTest.php +++ /dev/null @@ -1,38 +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); - -namespace ApiPlatform\Core\Tests\Metadata\schema; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Config\Util\XmlUtils; - -/** - * @author Grégoire Hébert - */ -class XmlSchemaTest extends TestCase -{ - public function testSchema(): void - { - $fixtures = __DIR__.'/../../../Fixtures/Metadata/schema/'; - $schema = __DIR__.'/../../../../src/Core/Metadata/schema/metadata.xsd'; - - try { - XmlUtils::loadFile($fixtures.'invalid.xml', $schema); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertStringContainsString('ERROR 1845', $e->getMessage()); - } - - $this->assertInstanceOf(\DOMDocument::class, XmlUtils::loadFile($fixtures.'valid.xml', $schema)); - } -} diff --git a/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php b/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php deleted file mode 100644 index 0d135462797..00000000000 --- a/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php +++ /dev/null @@ -1,818 +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); - -namespace ApiPlatform\Core\Tests\OpenApi\Factory; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\OpenApi\Factory\OpenApiFactory; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\JsonSchema\Schema; -use ApiPlatform\JsonSchema\SchemaFactory; -use ApiPlatform\JsonSchema\TypeFactory; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\OpenApi\Model; -use ApiPlatform\OpenApi\OpenApi; -use ApiPlatform\OpenApi\Options; -use ApiPlatform\OpenApi\Serializer\OpenApiNormalizer; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; -use ApiPlatform\State\Pagination\PaginationOptions; -use ApiPlatform\Tests\Fixtures\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Serializer\Encoder\JsonEncoder; -use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Serializer; - -/** - * @group legacy - */ -class OpenApiFactoryTest extends TestCase -{ - use ProphecyTrait; - - private const OPERATION_FORMATS = [ - 'input_formats' => ['jsonld' => ['application/ld+json']], - 'output_formats' => ['jsonld' => ['application/ld+json']], - ]; - - public function testInvoke(): void - { - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT'] + self::OPERATION_FORMATS, - 'delete' => ['method' => 'DELETE'] + self::OPERATION_FORMATS, - 'custom' => ['method' => 'HEAD', 'path' => '/foo/{id}', 'openapi_context' => [ - 'x-visibility' => 'hide', - 'description' => 'Custom description', - 'parameters' => [ - ['description' => 'Test parameter', 'name' => 'param', 'in' => 'path', 'required' => true], - ['description' => 'Replace parameter', 'name' => 'id', 'in' => 'path', 'required' => true, 'schema' => ['type' => 'string', 'format' => 'uuid']], - ], - 'tags' => ['Dummy', 'Profile'], - 'responses' => [ - '202' => [ - 'description' => 'Success', - 'content' => [ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'headers' => [ - 'Foo' => ['description' => 'A nice header', 'schema' => ['type' => 'integer']], - ], - 'links' => [ - 'Foo' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - '205' => [], - ], - 'requestBody' => [ - 'required' => true, - 'description' => 'Custom request body', - 'content' => [ - 'multipart/form-data' => [ - 'schema' => [ - 'type' => 'object', - 'properties' => [ - 'file' => [ - 'type' => 'string', - 'format' => 'binary', - ], - ], - ], - ], - ], - ], - ]] + self::OPERATION_FORMATS, - 'formats' => ['method' => 'PUT', 'path' => '/formatted/{id}', 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]], - ], - [ - 'get' => ['method' => 'GET', 'openapi_context' => [ - 'parameters' => [ - ['description' => 'Test modified collection page number', 'name' => 'page', 'in' => 'query', 'required' => false, 'schema' => ['type' => 'integer', 'default' => 1], 'allowEmptyValue' => true], - ], - ]] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - 'filtered' => ['method' => 'GET', 'filters' => ['f1', 'f2', 'f3', 'f4', 'f5'], 'path' => '/filtered'] + self::OPERATION_FORMATS, - 'paginated' => ['method' => 'GET', 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => true, 'pagination_items_per_page' => 20, 'pagination_maximum_items_per_page' => 80, 'path' => '/paginated'] + self::OPERATION_FORMATS, - ], - [ - 'pagination_client_items_per_page' => true, - 'output' => ['class' => OutputDto::class], - ] - ); - - $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); - $subresourceOperationFactoryProphecy->create(Argument::any())->willReturn([]); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->shouldBeCalled()->willReturn(new ResourceNameCollection([Dummy::class])); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate', 'enum'])); - $propertyNameCollectionFactoryProphecy->create(OutputDto::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate', 'enum'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, null, null, null, null, null)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$'])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'enum', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an enum.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'id', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, null, null, null, null, null)); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'name', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$'])); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'description', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'dummyDate', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'enum', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an enum.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filters = [ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'openapi' => ['example' => 'bar', 'deprecated' => true, 'allowEmptyValue' => true, 'allowReserved' => true, 'explode' => true], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - 'f4' => new DummyFilter(['order[name]' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => false, - 'schema' => [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ], - ]]), - ]; - - foreach ($filters as $filterId => $filter) { - $filterLocatorProphecy->has($filterId)->willReturn(true)->shouldBeCalled(); - $filterLocatorProphecy->get($filterId)->willReturn($filter)->shouldBeCalled(); - } - - $filterLocatorProphecy->has('f5')->willReturn(false)->shouldBeCalled(); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new CamelCaseToSnakeCaseNameConverter()); - $typeFactory->setSchemaFactory($schemaFactory); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $factory = new OpenApiFactory( - $resourceNameCollectionFactoryProphecy->reveal(), - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $schemaFactory, - $typeFactory, - $operationPathResolver, - $filterLocatorProphecy->reveal(), - $subresourceOperationFactoryProphecy->reveal(), - $identifiersExtractorProphecy->reveal(), - [], - new Options('Test API', 'This is a test API.', '1.2.3', true, 'oauth2', 'authorizationCode', '/oauth/v2/token', '/oauth/v2/auth', '/oauth/v2/refresh', ['scope param'], [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]), - new PaginationOptions(true, 'page', true, 'itemsPerPage', true, 'pagination') - ); - - $dummySchema = new Schema('openapi'); - // $dummySchema = new Model\Schema(false, null, false, false, null, ['url' => 'http://schema.example.com/Dummy']); - $dummySchema->setDefinitions(new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'minLength' => 3, - 'maxLength' => 20, - 'pattern' => '^dummyPattern$', - ]), - 'description' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is an initializable but not writable property.', - ]), - 'dummy_date' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a \DateTimeInterface object.', - 'format' => 'date-time', - 'nullable' => true, - ]), - 'enum' => new \ArrayObject([ - 'type' => 'string', - 'enum' => ['one', 'two'], - 'example' => 'one', - 'description' => 'This is an enum.', - ]), - ], - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - ])); - - $openApi = $factory(['base_url' => '/app_dev.php/']); - - $this->assertInstanceOf(OpenApi::class, $openApi); - $this->assertEquals($openApi->getInfo(), new Model\Info('Test API', '1.2.3', 'This is a test API.')); - $this->assertEquals($openApi->getServers(), [new Model\Server('/app_dev.php/')]); - - $components = $openApi->getComponents(); - $this->assertInstanceOf(Model\Components::class, $components); - - $this->assertEquals($components->getSchemas(), new \ArrayObject(['Dummy' => $dummySchema->getDefinitions(), 'Dummy.OutputDto' => $dummySchema->getDefinitions()])); - - $this->assertEquals($components->getSecuritySchemes(), new \ArrayObject([ - 'oauth' => new Model\SecurityScheme('oauth2', 'OAuth 2.0 authorization code Grant', null, null, null, null, new Model\OAuthFlows(null, null, null, new Model\OAuthFlow('/oauth/v2/auth', '/oauth/v2/token', '/oauth/v2/refresh', new \ArrayObject(['scope param'])))), - 'header' => new Model\SecurityScheme('apiKey', 'Value for the Authorization header parameter.', 'Authorization', 'header'), - 'query' => new Model\SecurityScheme('apiKey', 'Value for the key query parameter.', 'key', 'query'), - ])); - - $this->assertSame([ - ['oauth' => []], - ['header' => []], - ['query' => []], - ], $openApi->getSecurity()); - - $paths = $openApi->getPaths(); - $dummiesPath = $paths->getPath('/dummies'); - $this->assertNotNull($dummiesPath); - foreach (['Put', 'Head', 'Trace', 'Delete', 'Options', 'Patch'] as $method) { - $this->assertNull($dummiesPath->{'get'.$method}()); - } - - $this->assertEquals($dummiesPath->getGet(), new Model\Operation( - 'getDummyCollection', - ['Dummy'], - [ - '200' => new Model\Response('Dummy collection', new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject([ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy.OutputDto'], - ]))), - ])), - ], - 'Retrieves the collection of Dummy resources.', - 'Retrieves the collection of Dummy resources.', - null, - [ - new Model\Parameter('page', 'query', 'Test modified collection page number', false, false, true, [ - 'type' => 'integer', - 'default' => 1, - ]), - new Model\Parameter('itemsPerPage', 'query', 'The number of items per page', false, false, true, [ - 'type' => 'integer', - 'default' => 30, - 'minimum' => 0, - ]), - new Model\Parameter('pagination', 'query', 'Enable or disable pagination', false, false, true, [ - 'type' => 'boolean', - ]), - ] - )); - - $this->assertEquals($dummiesPath->getPost(), new Model\Operation( - 'postDummyCollection', - ['Dummy'], - [ - '201' => new Model\Response( - 'Dummy resource created', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto']))), - ]), - null, - new \ArrayObject(['GetDummyItem' => new Model\Link('getDummyItem', new \ArrayObject(['id' => '$response.body#/id']), null, 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.')]) - ), - '400' => new Model\Response('Invalid input'), - '422' => new Model\Response('Unprocessable entity'), - ], - 'Creates a Dummy resource.', - 'Creates a Dummy resource.', - null, - [], - new Model\RequestBody( - 'The new Dummy resource', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Dummy']))), - ]), - true - ) - )); - - $dummyPath = $paths->getPath('/dummies/{id}'); - $this->assertNotNull($dummyPath); - foreach (['Post', 'Head', 'Trace', 'Options', 'Patch'] as $method) { - $this->assertNull($dummyPath->{'get'.$method}()); - } - - $this->assertEquals($dummyPath->getGet(), new Model\Operation( - 'getDummyItem', - ['Dummy'], - [ - '200' => new Model\Response( - 'Dummy resource', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto']))), - ]) - ), - '404' => new Model\Response('Resource not found'), - ], - 'Retrieves a Dummy resource.', - 'Retrieves a Dummy resource.', - null, - [new Model\Parameter('id', 'path', 'Resource identifier', true, false, false, ['type' => 'string'])] - )); - - $this->assertEquals($dummyPath->getPut(), new Model\Operation( - 'putDummyItem', - ['Dummy'], - [ - '200' => new Model\Response( - 'Dummy resource updated', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto'])), - ]), - null, - new \ArrayObject(['GetDummyItem' => new Model\Link('getDummyItem', new \ArrayObject(['id' => '$response.body#/id']), null, 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.')]) - ), - '400' => new Model\Response('Invalid input'), - '422' => new Model\Response('Unprocessable entity'), - '404' => new Model\Response('Resource not found'), - ], - 'Replaces the Dummy resource.', - 'Replaces the Dummy resource.', - null, - [new Model\Parameter('id', 'path', 'Resource identifier', true, false, false, ['type' => 'string'])], - new Model\RequestBody( - 'The updated Dummy resource', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy'])), - ]), - true - ) - )); - - $this->assertEquals($dummyPath->getDelete(), new Model\Operation( - 'deleteDummyItem', - ['Dummy'], - [ - '204' => new Model\Response('Dummy resource deleted'), - '404' => new Model\Response('Resource not found'), - ], - 'Removes the Dummy resource.', - 'Removes the Dummy resource.', - null, - [new Model\Parameter('id', 'path', 'Resource identifier', true, false, false, ['type' => 'string'])] - )); - - $customPath = $paths->getPath('/foo/{id}'); - $this->assertEquals($customPath->getHead(), new Model\Operation( - 'customDummyItem', - ['Dummy', 'Profile'], - [ - '202' => new Model\Response('Success', new \ArrayObject([ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ]), new \ArrayObject([ - 'Foo' => ['description' => 'A nice header', 'schema' => ['type' => 'integer']], - ]), new \ArrayObject([ - 'Foo' => ['$ref' => '#/components/schemas/Dummy'], - ])), - '205' => new Model\Response(), - '404' => new Model\Response('Resource not found'), - ], - 'Dummy', - 'Custom description', - null, - [new Model\Parameter('param', 'path', 'Test parameter', true), new Model\Parameter('id', 'path', 'Replace parameter', true, false, false, ['type' => 'string', 'format' => 'uuid'])], - new Model\RequestBody('Custom request body', new \ArrayObject([ - 'multipart/form-data' => [ - 'schema' => [ - 'type' => 'object', - 'properties' => [ - 'file' => [ - 'type' => 'string', - 'format' => 'binary', - ], - ], - ], - ], - ]), true), - null, - false, - null, - null, - ['x-visibility' => 'hide'] - )); - - $formattedPath = $paths->getPath('/formatted/{id}'); - $this->assertEquals($formattedPath->getPut(), new Model\Operation( - 'formatsDummyItem', - ['Dummy'], - [ - '200' => new Model\Response( - 'Dummy resource updated', - new \ArrayObject([ - 'application/json' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto'])), - 'text/csv' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto'])), - ]), - null, - new \ArrayObject(['GetDummyItem' => new Model\Link('getDummyItem', new \ArrayObject(['id' => '$response.body#/id']), null, 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.')]) - ), - '400' => new Model\Response('Invalid input'), - '422' => new Model\Response('Unprocessable entity'), - '404' => new Model\Response('Resource not found'), - ], - 'Replaces the Dummy resource.', - 'Replaces the Dummy resource.', - null, - [new Model\Parameter('id', 'path', 'Resource identifier', true, false, false, ['type' => 'string'])], - new Model\RequestBody( - 'The updated Dummy resource', - new \ArrayObject([ - 'application/json' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy'])), - 'text/csv' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy'])), - ]), - true - ) - )); - - $filteredPath = $paths->getPath('/filtered'); - $this->assertEquals($filteredPath->getGet(), new Model\Operation( - 'filteredDummyCollection', - ['Dummy'], - [ - '200' => new Model\Response('Dummy collection', new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject([ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy.OutputDto'], - ])), - ])), - ], - 'Retrieves the collection of Dummy resources.', - 'Retrieves the collection of Dummy resources.', - null, - [ - new Model\Parameter('page', 'query', 'The collection page number', false, false, true, [ - 'type' => 'integer', - 'default' => 1, - ]), - new Model\Parameter('itemsPerPage', 'query', 'The number of items per page', false, false, true, [ - 'type' => 'integer', - 'default' => 30, - 'minimum' => 0, - ]), - new Model\Parameter('pagination', 'query', 'Enable or disable pagination', false, false, true, [ - 'type' => 'boolean', - ]), - new Model\Parameter('name', 'query', '', true, true, true, [ - 'type' => 'string', - ], 'form', true, true, 'bar'), - new Model\Parameter('ha', 'query', '', false, false, true, [ - 'type' => 'integer', - ]), - new Model\Parameter('toto', 'query', '', true, false, true, [ - 'type' => 'array', - 'items' => ['type' => 'string'], - ], 'deepObject', true), - new Model\Parameter('order[name]', 'query', '', false, false, true, [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ]), - ] - )); - - $paginatedPath = $paths->getPath('/paginated'); - $this->assertEquals($paginatedPath->getGet(), new Model\Operation( - 'paginatedDummyCollection', - ['Dummy'], - [ - '200' => new Model\Response('Dummy collection', new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject([ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy.OutputDto'], - ])), - ])), - ], - 'Retrieves the collection of Dummy resources.', - 'Retrieves the collection of Dummy resources.', - null, - [ - new Model\Parameter('page', 'query', 'The collection page number', false, false, true, [ - 'type' => 'integer', - 'default' => 1, - ]), - new Model\Parameter('itemsPerPage', 'query', 'The number of items per page', false, false, true, [ - 'type' => 'integer', - 'default' => 20, - 'minimum' => 0, - 'maximum' => 80, - ]), - new Model\Parameter('pagination', 'query', 'Enable or disable pagination', false, false, true, [ - 'type' => 'boolean', - ]), - ] - )); - } - - public function testOverrideDocumentation() - { - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT'] + self::OPERATION_FORMATS, - 'delete' => ['method' => 'DELETE'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ], - [] - ); - - $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); - $subresourceOperationFactoryProphecy->create(Argument::any())->willReturn([]); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->shouldBeCalled()->willReturn(new ResourceNameCollection([Dummy::class])); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate'])); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, null, null, null, null, null)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$'])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new CamelCaseToSnakeCaseNameConverter()); - $typeFactory->setSchemaFactory($schemaFactory); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $factory = new OpenApiFactory( - $resourceNameCollectionFactoryProphecy->reveal(), - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $schemaFactory, - $typeFactory, - $operationPathResolver, - $filterLocatorProphecy->reveal(), - $subresourceOperationFactoryProphecy->reveal(), - $identifiersExtractorProphecy->reveal(), - [], - new Options('Test API', 'This is a test API.', '1.2.3', true, 'oauth2', 'authorizationCode', '/oauth/v2/token', '/oauth/v2/auth', '/oauth/v2/refresh', ['scope param'], [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]), - new PaginationOptions(true, 'page', true, 'itemsPerPage', true, 'pagination') - ); - - $openApi = $factory(['base_url' => '/app_dev.php/']); - - $pathItem = $openApi->getPaths()->getPath('/dummies/{id}'); - $operation = $pathItem->getGet(); - - $openApi->getPaths()->addPath('/dummies/{id}', $pathItem->withGet( - $operation->withParameters(array_merge( - $operation->getParameters(), - [new Model\Parameter('fields', 'query', 'Fields to remove of the output')] - )) - )); - - $openApi = $openApi->withInfo((new Model\Info('New Title', 'v2', 'Description of my custom API'))->withExtensionProperty('info-key', 'Info value')); - $openApi = $openApi->withExtensionProperty('key', 'Custom x-key value'); - $openApi = $openApi->withExtensionProperty('x-value', 'Custom x-value value'); - - $this->assertEquals($openApi->getInfo()->getExtensionProperties(), ['x-info-key' => 'Info value']); - $this->assertEquals($openApi->getExtensionProperties(), ['x-key' => 'Custom x-key value', 'x-value' => 'Custom x-value value']); - } - - public function testSubresourceDocumentation() - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Question::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['answer'])); - $propertyNameCollectionFactoryProphecy->create(Answer::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['content'])); - - $questionMetadata = new ResourceMetadata( - 'Question', - 'This is a question.', - 'http://schema.example.com/Question', - ['get' => ['method' => 'GET', 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]]] - ); - $answerMetadata = new ResourceMetadata( - 'Answer', - 'This is an answer.', - 'http://schema.example.com/Answer', - [], - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS], - [], - ['get' => ['method' => 'GET', 'input_formats' => ['xml' => ['text/xml']], 'output_formats' => ['xml' => ['text/xml']]]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Question::class)->shouldBeCalled()->willReturn($questionMetadata); - $resourceMetadataFactoryProphecy->create(Answer::class)->shouldBeCalled()->willReturn($answerMetadata); - - $subresourceMetadata = new SubresourceMetadata(Answer::class, false); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Question::class, 'answer', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [], $subresourceMetadata)); - - $propertyMetadataFactoryProphecy->create(Answer::class, 'content', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $routeCollection = new RouteCollection(); - $routeCollection->add('api_answers_get_collection', new Route('/api/answers.{_format}')); - $routeCollection->add('api_questions_answer_get_subresource', new Route('/api/questions/{id}/answer.{_format}')); - $routeCollection->add('api_questions_get_item', new Route('/api/questions/{id}.{_format}')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->shouldBeCalled()->willReturn($routeCollection); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()))); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - $identifiersExtractor = $identifiersExtractorProphecy->reveal(); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new UnderscorePathSegmentNameGenerator(), $identifiersExtractor); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->shouldBeCalled()->willReturn(new ResourceNameCollection([Question::class, Answer::class])); - - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new CamelCaseToSnakeCaseNameConverter()); - $typeFactory->setSchemaFactory($schemaFactory); - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - - $factory = new OpenApiFactory( - $resourceNameCollectionFactoryProphecy->reveal(), - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $schemaFactory, - $typeFactory, - $operationPathResolver, - $filterLocatorProphecy->reveal(), - $subresourceOperationFactory, - $identifiersExtractor, - ['jsonld' => ['application/ld+json']], - new Options('Test API', 'This is a test API.', '1.2.3', true, 'oauth2', 'authorizationCode', '/oauth/v2/token', '/oauth/v2/auth', '/oauth/v2/refresh', ['scope param'], [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]), - new PaginationOptions(true, 'page', true, 'itemsPerPage', true, 'pagination') - ); - - $openApi = $factory(['base_url', '/app_dev.php/']); - - $paths = $openApi->getPaths(); - $pathItem = $paths->getPath('/api/questions/{id}/answer'); - - $this->assertEquals($pathItem->getGet(), new Model\Operation( - 'api_questions_answer_get_subresourceQuestionSubresource', - ['Answer', 'Question'], - [ - '200' => new Model\Response( - 'Question resource', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Answer']))), - ]) - ), - ], - 'Retrieves a Question resource.', - 'Retrieves a Question resource.', - null, - [new Model\Parameter('id', 'path', 'Question identifier', true, false, false, ['type' => 'string'])] - )); - - $encoders = [new JsonEncoder()]; - $normalizers = [new ObjectNormalizer()]; - - $serializer = new Serializer($normalizers, $encoders); - $normalizers[0]->setSerializer($serializer); - - // Call the normalizer to see if everything is smooth - $normalizer = new OpenApiNormalizer($normalizers[0]); - $normalizer->normalize($openApi); - } - - public function testResetPathItem() - { - $pathItem = new Model\PathItem( - null, - '', - '', - new Model\Operation(), - new Model\Operation(), - new Model\Operation(), - new Model\Operation(), - new Model\Operation() - ); - - $this->assertNull($pathItem->withGet(null)->getGet()); - $this->assertNull($pathItem->withDelete(null)->getDelete()); - $this->assertNull($pathItem->withPost(null)->getPost()); - $this->assertNull($pathItem->withPut(null)->getPut()); - $this->assertNull($pathItem->withPatch(null)->getPatch()); - } -} diff --git a/tests/Core/Operation/DashedPathSegmentNameGeneratorTest.php b/tests/Core/Operation/DashedPathSegmentNameGeneratorTest.php deleted file mode 100644 index 40aa614f96a..00000000000 --- a/tests/Core/Operation/DashedPathSegmentNameGeneratorTest.php +++ /dev/null @@ -1,27 +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); - -namespace ApiPlatform\Core\Tests\Operation; - -use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator; -use PHPUnit\Framework\TestCase; - -class DashedPathSegmentNameGeneratorTest extends TestCase -{ - public function testCreateSegmentNameGeneration() - { - $generator = new DashPathSegmentNameGenerator(); - $this->assertSame('ordering-people', $generator->getSegmentName('orderingPerson')); - $this->assertSame('some-person-names', $generator->getSegmentName('somePersonName')); - } -} diff --git a/tests/Core/Operation/Factory/CachedSubresourceOperationFactoryTest.php b/tests/Core/Operation/Factory/CachedSubresourceOperationFactoryTest.php deleted file mode 100644 index 6e0d826ad71..00000000000 --- a/tests/Core/Operation/Factory/CachedSubresourceOperationFactoryTest.php +++ /dev/null @@ -1,92 +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); - -namespace ApiPlatform\Core\Tests\Operation\Factory; - -use ApiPlatform\Core\Operation\Factory\CachedSubresourceOperationFactory; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @author Antoine Bluchet - */ -class CachedSubresourceOperationFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreateWithItemHit() - { - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(true)->shouldBeCalledTimes(1); - $cacheItem->get()->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willReturn($cacheItem->reveal())->shouldBeCalledTimes(1); - - $decoratedSubresourceOperationFactory = $this->prophesize(SubresourceOperationFactoryInterface::class); - $decoratedSubresourceOperationFactory->create()->shouldNotBeCalled(); - - $cachedSubresourceOperationFactory = new CachedSubresourceOperationFactory($cacheItemPool->reveal(), $decoratedSubresourceOperationFactory->reveal()); - - $expectedResult = ['foo' => 'bar']; - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class)); - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class), 'Trigger the local cache'); - } - - public function testCreateWithItemNotHit() - { - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(false)->shouldBeCalledTimes(1); - $cacheItem->set(['foo' => 'bar'])->willReturn($cacheItem->reveal())->shouldBeCalledTimes(1); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willReturn($cacheItem->reveal())->shouldBeCalledTimes(1); - $cacheItemPool->save($cacheItem->reveal())->willReturn(true)->shouldBeCalledTimes(1); - - $decoratedSubresourceOperationFactory = $this->prophesize(SubresourceOperationFactoryInterface::class); - $decoratedSubresourceOperationFactory->create(Dummy::class)->shouldBeCalledTimes(1)->willReturn(['foo' => 'bar']); - - $cachedSubresourceOperationFactory = new CachedSubresourceOperationFactory($cacheItemPool->reveal(), $decoratedSubresourceOperationFactory->reveal()); - - $expectedResult = ['foo' => 'bar']; - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class)); - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class), 'Trigger the local cache'); - } - - public function testCreateWithGetCacheItemThrowsCacheException() - { - $cacheException = new class() extends \Exception implements CacheException {}; - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willThrow($cacheException)->shouldBeCalledTimes(1); - - $decoratedSubresourceOperationFactory = $this->prophesize(SubresourceOperationFactoryInterface::class); - $decoratedSubresourceOperationFactory->create(Dummy::class)->shouldBeCalledTimes(1)->willReturn(['foo' => 'bar']); - - $cachedSubresourceOperationFactory = new CachedSubresourceOperationFactory($cacheItemPool->reveal(), $decoratedSubresourceOperationFactory->reveal()); - - $expectedResult = ['foo' => 'bar']; - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class)); - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class), 'Trigger the local cache'); - } - - private function generateCacheKey(string $resourceClass = Dummy::class) - { - return CachedSubresourceOperationFactory::CACHE_KEY_PREFIX.md5($resourceClass); - } -} diff --git a/tests/Core/Operation/Factory/SubresourceOperationFactoryTest.php b/tests/Core/Operation/Factory/SubresourceOperationFactoryTest.php deleted file mode 100644 index 2974f30be05..00000000000 --- a/tests/Core/Operation/Factory/SubresourceOperationFactoryTest.php +++ /dev/null @@ -1,988 +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); - -namespace ApiPlatform\Core\Tests\Operation\Factory; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Operation\PathSegmentNameGeneratorInterface; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use ApiPlatform\Tests\Fixtures\DummyValidatedEntity; -use ApiPlatform\Tests\Fixtures\RelatedDummyEntity; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class SubresourceOperationFactoryTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function testCreate() - { - $this->expectDeprecation('Since api-platform/core 2.7: A subresource is declared on "ApiPlatform\Tests\Fixtures\DummyEntity::subresource". Subresources are deprecated, use another #[ApiResource] instead.'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo', 'subresource', 'subcollection'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - - $subresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class)); - $subresourceMetadataCollection = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, true)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'foo', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadata); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subcollection', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollection); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subcollection', true)->shouldBeCalled()->willReturn('subcollections'); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('anotherSubresource', false)->shouldBeCalled()->willReturn('another_subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $pathSegmentNameGeneratorProphecy->reveal(), $identifiersExtractorProphecy->reveal()); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_another_subresource_get_subresource' => [ - 'property' => 'anotherSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_another_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/another_subresource.{_format}', - 'operation_name' => 'subresource_another_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_another_subresource_subcollections_get_subresource' => [ - 'property' => 'subcollection', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', false], - 'anotherSubresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_another_subresource_subcollections_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/another_subresource/subcollections.{_format}', - 'operation_name' => 'subresource_another_subresource_subcollections_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_get_subresource' => [ - 'property' => 'subcollection', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subcollections_get_subresource', - 'path' => '/dummy_entities/{id}/subcollections.{_format}', - 'operation_name' => 'subcollections_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_another_subresource_get_subresource' => [ - 'property' => 'anotherSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subcollection' => [RelatedDummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subcollections_another_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subcollections/{subcollection}/another_subresource.{_format}', - 'operation_name' => 'subcollections_another_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_another_subresource_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subcollection' => [RelatedDummyEntity::class, 'id', true], - 'anotherSubresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subcollections_another_subresource_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subcollections/{subcollection}/another_subresource/subresource.{_format}', - 'operation_name' => 'subcollections_another_subresource_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateByOverriding() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn((new ResourceMetadata('dummyEntity'))->withSubresourceOperations([ - 'subcollections_get_subresource' => [ - 'path' => '/dummy_entities/{id}/foobars', - ], - 'subcollections_another_subresource_get_subresource' => [ - 'path' => '/dummy_entities/{id}/foobars/{subcollection}/another_foobar.{_format}', - ], - ])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo', 'subresource', 'subcollection'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - - $subresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class)); - $subresourceMetadataCollection = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, true)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'foo', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadata); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subcollection', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollection); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subcollection', true)->shouldBeCalled()->willReturn('subcollections'); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('anotherSubresource', false)->shouldBeCalled()->willReturn('another_subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $pathSegmentNameGeneratorProphecy->reveal(), $identifiersExtractorProphecy->reveal()); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_another_subresource_get_subresource' => [ - 'property' => 'anotherSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_another_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/another_subresource.{_format}', - 'operation_name' => 'subresource_another_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_another_subresource_subcollections_get_subresource' => [ - 'property' => 'subcollection', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', false], - 'anotherSubresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_another_subresource_subcollections_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/another_subresource/subcollections.{_format}', - 'operation_name' => 'subresource_another_subresource_subcollections_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_get_subresource' => [ - 'property' => 'subcollection', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subcollections_get_subresource', - 'path' => '/dummy_entities/{id}/foobars', - 'operation_name' => 'subcollections_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_another_subresource_get_subresource' => [ - 'property' => 'anotherSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subcollection' => [RelatedDummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subcollections_another_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/foobars/{subcollection}/another_foobar.{_format}', - 'operation_name' => 'subcollections_another_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_another_subresource_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subcollection' => [RelatedDummyEntity::class, 'id', true], - 'anotherSubresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subcollections_another_subresource_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/foobars/{subcollection}/another_foobar/subresource.{_format}', - 'operation_name' => 'subcollections_another_subresource_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateWithMaxDepth() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - - $subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false, 1)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollectionWithMaxDepth); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - /** - * Test for issue: https://github.com/api-platform/core/issues/1711. - */ - public function testCreateWithMaxDepthMultipleSubresources() - { - /** - * DummyEntity -subresource-> RelatedDummyEntity -anotherSubresource-> DummyEntity - * DummyEntity -secondSubresource-> dummyValidatedEntity -moreSubresource-> RelatedDummyEntity. - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyValidatedEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'secondSubresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - $propertyNameCollectionFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['moreSubresource'])); - - $subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false, 1)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - $secondSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyValidatedEntity::class, false, 2)); - $moreSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollectionWithMaxDepth); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'secondSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($secondSubresourceMetadata); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - $propertyMetadataFactoryProphecy->create(DummyValidatedEntity::class, 'moreSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($moreSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('secondSubresource', false)->shouldBeCalled()->willReturn('second_subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('moreSubresource', false)->shouldBeCalled()->willReturn('mode_subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_second_subresource_get_subresource' => [ - 'property' => 'secondSubresource', - 'collection' => false, - 'resource_class' => DummyValidatedEntity::class, - 'shortNames' => ['dummyValidatedEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_second_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/second_subresources.{_format}', - 'operation_name' => 'second_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_second_subresource_more_subresource_get_subresource' => [ - 'property' => 'moreSubresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyValidatedEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'secondSubresource' => [DummyValidatedEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_second_subresource_more_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/second_subresources/mode_subresources.{_format}', - 'operation_name' => 'second_subresource_more_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - /** - * Test for issue: https://github.com/api-platform/core/issues/2103. - */ - public function testCreateWithMaxDepthMultipleSubresourcesSameMaxDepth() - { - /** - * DummyEntity -subresource (maxDepth=1)-> RelatedDummyEntity -anotherSubresource-> DummyEntity - * DummyEntity -secondSubresource (maxDepth=1)-> dummyValidatedEntity -moreSubresource-> RelatedDummyEntity. - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyValidatedEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'secondSubresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - $propertyNameCollectionFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['moreSubresource'])); - - $subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false, 1)); - $secondSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyValidatedEntity::class, false, 1)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - $moreSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollectionWithMaxDepth); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'secondSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($secondSubresourceMetadata); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - $propertyMetadataFactoryProphecy->create(DummyValidatedEntity::class, 'moreSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($moreSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('secondSubresource', false)->shouldBeCalled()->willReturn('second_subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_second_subresource_get_subresource' => [ - 'property' => 'secondSubresource', - 'collection' => false, - 'resource_class' => DummyValidatedEntity::class, - 'shortNames' => ['dummyValidatedEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_second_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/second_subresources.{_format}', - 'operation_name' => 'second_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateSelfReferencingSubresources() - { - /** - * DummyEntity -subresource-> DummyEntity --> DummyEntity ... - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - - $subresource = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresource); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - /** - * Test for issue: https://github.com/api-platform/core/issues/2533. - */ - public function testCreateWithDifferentMaxDepthSelfReferencingSubresources() - { - /** - * subresource: maxDepth = 2 - * secondSubresource: maxDepth = 1 - * DummyEntity -subresource-> DummyEntity -secondSubresource-> DummyEntity ... - * DummyEntity -secondSubresource-> DummyEntity !!!-subresource-> DummyEntity ... - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'secondSubresource'])); - - $subresourceWithMaxDepthMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false, 2)); - $secondSubresourceWithMaxDepthMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false, 1)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceWithMaxDepthMetadata); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'secondSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($secondSubresourceWithMaxDepthMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('secondSubresource', false)->shouldBeCalled()->willReturn('second_subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_second_subresource_get_subresource' => [ - 'property' => 'secondSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_second_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources/second_subresources.{_format}', - 'operation_name' => 'subresource_second_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_second_subresource_get_subresource' => [ - 'property' => 'secondSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_second_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/second_subresources.{_format}', - 'operation_name' => 'second_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateWithEnd() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['id'])); - - $subresourceMetadataCollection = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, true)); - $identifierSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false))->withIdentifier(true); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollection); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'id', Argument::type('array'))->shouldBeCalled()->willReturn($identifierSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', true)->shouldBeCalled()->willReturn('subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $result = $subresourceOperationFactory->create(DummyEntity::class); - $this->assertEquals([ - 'api_dummy_entities_subresources_get_subresource' => [ - 'property' => 'subresource', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresources_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresources_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresources_item_get_subresource' => [ - 'property' => 'id', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresources_item_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/{subresource}.{_format}', - 'operation_name' => 'subresources_item_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $result); - } - - public function testCreateWithEndButNoCollection() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['id'])); - - $subresourceMetadataCollection = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - $identifierSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false))->withIdentifier(true); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollection); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'id', Argument::type('array'))->shouldBeCalled()->willReturn($identifierSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $result = $subresourceOperationFactory->create(DummyEntity::class); - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $result); - } - - public function testCreateWithRootResourcePrefix() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity', null, null, null, null, ['route_prefix' => 'root_resource_prefix'])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - - $subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false, 1)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollectionWithMaxDepth); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/root_resource_prefix/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateSelfReferencingSubresourcesWithSubresources() - { - /** - * DummyEntity -otherSubresource-> RelatedDummyEntity - * DummyEntity -subresource (maxDepth=1) -> DummyEntity -otherSubresource-> RelatedDummyEntity. - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'otherSubresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection([])); - - $subresource = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false, 1)); - $otherSubresourceSubresource = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresource); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'otherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($otherSubresourceSubresource); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('otherSubresource', false)->shouldBeCalled()->willReturn('other_subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_other_subresource_get_subresource' => [ - 'property' => 'otherSubresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_other_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/other_subresources.{_format}', - 'operation_name' => 'other_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateWithOpenapiContext() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn((new ResourceMetadata('dummyEntity'))->withSubresourceOperations([ - 'subresource_get_subresource' => [ - 'openapi_context' => [ - 'summary' => 'Get related dummy entities', - 'tags' => ['Dummy'], - ], - ], - ])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection([])); - - $subresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'openapi_context' => [ - 'summary' => 'Get related dummy entities', - 'tags' => ['Dummy'], - ], - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } -} diff --git a/tests/Core/PathResolver/DashOperationPathResolverTest.php b/tests/Core/PathResolver/DashOperationPathResolverTest.php deleted file mode 100644 index d789228c847..00000000000 --- a/tests/Core/PathResolver/DashOperationPathResolverTest.php +++ /dev/null @@ -1,71 +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); - -namespace ApiPlatform\Core\Tests\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\PathResolver\DashOperationPathResolver; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; - -/** - * @author Guilhem N. - * - * @group legacy - */ -class DashOperationPathResolverTest extends TestCase -{ - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\DashOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator instead. - */ - public function testResolveCollectionOperationPath() - { - $dashOperationPathResolver = new DashOperationPathResolver(); - - $this->assertSame('/short-names.{_format}', $dashOperationPathResolver->resolveOperationPath('ShortName', [], OperationType::COLLECTION, 'get')); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\DashOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator instead. - */ - public function testResolveItemOperationPath() - { - $dashOperationPathResolver = new DashOperationPathResolver(); - - $this->assertSame('/short-names/{id}.{_format}', $dashOperationPathResolver->resolveOperationPath('ShortName', [], OperationType::ITEM, 'get')); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\DashOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator instead. - */ - public function testResolveSubresourceOperationPath() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Subresource operations are not supported by the OperationPathResolver.'); - - $dashOperationPathResolver = new DashOperationPathResolver(); - - $dashOperationPathResolver->resolveOperationPath('ShortName', ['property' => 'bar', 'identifiers' => [['id', 'class'], ['relatedId', 'class']], 'collection' => false], OperationType::SUBRESOURCE, 'get'); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\DashOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator instead. - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testLegacyResolveOperationPath() - { - $dashOperationPathResolver = new DashOperationPathResolver(); - - $this->assertSame('/short-names.{_format}', $dashOperationPathResolver->resolveOperationPath('ShortName', [], true)); - } -} diff --git a/tests/Core/PathResolver/UnderscoreOperationPathResolverTest.php b/tests/Core/PathResolver/UnderscoreOperationPathResolverTest.php deleted file mode 100644 index 0c7a5df2a84..00000000000 --- a/tests/Core/PathResolver/UnderscoreOperationPathResolverTest.php +++ /dev/null @@ -1,71 +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); - -namespace ApiPlatform\Core\Tests\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; - -/** - * @author Guilhem N. - * - * @group legacy - */ -class UnderscoreOperationPathResolverTest extends TestCase -{ - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator instead. - */ - public function testResolveCollectionOperationPath() - { - $underscoreOperationPathResolver = new UnderscoreOperationPathResolver(); - - $this->assertSame('/short_names.{_format}', $underscoreOperationPathResolver->resolveOperationPath('ShortName', [], OperationType::COLLECTION, 'get')); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator instead. - */ - public function testResolveItemOperationPath() - { - $underscoreOperationPathResolver = new UnderscoreOperationPathResolver(); - - $this->assertSame('/short_names/{id}.{_format}', $underscoreOperationPathResolver->resolveOperationPath('ShortName', [], OperationType::ITEM, 'get')); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator instead. - */ - public function testResolveSubresourceOperationPath() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Subresource operations are not supported by the OperationPathResolver.'); - - $dashOperationPathResolver = new UnderscoreOperationPathResolver(); - - $dashOperationPathResolver->resolveOperationPath('ShortName', ['property' => 'relatedFoo', 'identifiers' => [['id', 'class']], 'collection' => true], OperationType::SUBRESOURCE, 'get'); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator instead. - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testLegacyResolveOperationPath() - { - $underscoreOperationPathResolver = new UnderscoreOperationPathResolver(); - - $this->assertSame('/short_names.{_format}', $underscoreOperationPathResolver->resolveOperationPath('ShortName', [], true)); - } -} diff --git a/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php b/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php deleted file mode 100644 index 58bd0c9bb32..00000000000 --- a/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php +++ /dev/null @@ -1,3483 +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); - -namespace ApiPlatform\Core\Tests\Swagger\Serializer; - -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\JsonSchema\SchemaFactory; -use ApiPlatform\JsonSchema\TypeFactory; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use ApiPlatform\Tests\Fixtures\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPropertyWithDefaultValue; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -/** - * @author Amrouche Hamza - * @author Kévin Dunglas - * @group legacy - */ -class DocumentationNormalizerV2Test extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - private const OPERATION_FORMATS = [ - 'input_formats' => ['jsonld' => ['application/ld+json']], - 'output_formats' => ['jsonld' => ['application/ld+json']], - ]; - - /** - * @group legacy - */ - public function testLegacyConstruct(): void - { - $this->expectDeprecation('Passing an instance of ApiPlatform\Core\Api\UrlGeneratorInterface to ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer::__construct() is deprecated since version 2.1 and will be removed in 3.0.'); - - $normalizer = new DocumentationNormalizer( - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal(), - $this->prophesize(OperationPathResolverInterface::class)->reveal(), - $this->prophesize(UrlGeneratorInterface::class)->reveal() - ); - - $this->assertInstanceOf(DocumentationNormalizer::class, $normalizer); - } - - public function testNormalize(): void - { - $this->doTestNormalize(); - } - - public function testLegacyNormalize(): void - { - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET'); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'put')->willReturn('PUT'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'post')->willReturn('POST'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'custom')->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'custom2')->willReturn('POST'); - - $this->doTestNormalize($operationMethodResolverProphecy->reveal()); - } - - private function doTestNormalize(OperationMethodResolverInterface $operationMethodResolver = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET', 'status' => '202'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'status' => '202'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET', 'status' => '202'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST', 'status' => '202'] + self::OPERATION_FORMATS, - 'custom' => ['method' => 'GET', 'path' => '/foo', 'status' => '202'] + self::OPERATION_FORMATS, - 'custom2' => ['method' => 'POST', 'path' => '/foo'] + self::OPERATION_FORMATS, - ], - ['pagination_client_items_per_page' => true, 'normalization_context' => [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTimeInterface::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - $operationMethodResolver, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/foo' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'customDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'custom2DummyCollection', - 'produces' => ['application/ld+json'], - 'consumes' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'additionalProperties' => false, - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'description' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is an initializable but not writable property.', - ]), - 'dummyDate' => new \ArrayObject([ - 'type' => 'string', - 'format' => 'date-time', - 'description' => 'This is a \DateTimeInterface object.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithNameConverter(): void - { - $this->doTestNormalizeWithNameConverter(); - } - - public function testLegacyNormalizeWithNameConverter(): void - { - $this->doTestNormalizeWithNameConverter(true); - } - - private function doTestNormalizeWithNameConverter(bool $legacy = false): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Dummy API', 'This is a dummy API', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name', 'nameConverted'])); - - $dummyMetadata = new ResourceMetadata('Dummy', 'This is a dummy.', null, ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, null, null, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'nameConverted', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a converted name.', true, true, null, null, false)); - - if (interface_exists(AdvancedNameConverterInterface::class)) { - $nameConverter = $this->createMock(AdvancedNameConverterInterface::class); - } else { - $nameConverter = $this->createMock(NameConverterInterface::class); - } - - $nameConverter->method('normalize') - ->with(self::logicalOr('name', 'nameConverted')) - ->willReturnCallback(static function (string $nameToNormalize): string { - return 'nameConverted' === $nameToNormalize - ? 'name_converted' - : $nameToNormalize; - }); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $typeFactory = null; - $schemaFactory = null; - - if (!$legacy) { - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $nameConverter); - $typeFactory->setSchemaFactory($schemaFactory); - } - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $schemaFactory, - $typeFactory, - $operationPathResolver, - null, - null, - $legacy ? $nameConverter : null, - true, - 'oauth2', - 'application', - '/oauth/v2/token', - '/oauth/v2/auth', - ['scope param'], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Dummy API', - 'description' => 'This is a dummy API', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'name_converted' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a converted name.', - ]), - ], - ]), - ]), - 'securityDefinitions' => [ - 'oauth' => [ - 'type' => 'oauth2', - 'description' => 'OAuth 2.0 application Grant', - 'flow' => 'application', - 'tokenUrl' => '/oauth/v2/token', - 'authorizationUrl' => '/oauth/v2/auth', - 'scopes' => new \ArrayObject(['scope param']), - ], - ], - 'security' => [['oauth' => []]], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithApiKeysEnabled(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata('Dummy', 'This is a dummy.', null, ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, null, null, false)); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $apiKeysConfiguration = [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]; - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - $apiKeysConfiguration, - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - 'securityDefinitions' => [ - 'header' => [ - 'type' => 'apiKey', - 'in' => 'header', - 'description' => 'Value for the Authorization header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'apiKey', - 'in' => 'query', - 'description' => 'Value for the key query parameter', - 'name' => 'key', - ], - ], - 'security' => [ - ['header' => []], - ['query' => []], - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithOnlyNormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - - $ref = 'Dummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/'.$ref], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeNotAddExtraBodyParameters(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - - $ref = 'Dummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => [ - 'method' => 'POST', - 'swagger_context' => [ - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new custom Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new custom Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/'.$ref], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithSwaggerDefinitionName(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => [ - 'method' => 'GET', - 'normalization_context' => [ - DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'Read', - ], - ] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy-Read'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy-Read' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithOnlyDenormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', ['dummy']) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => 'dummy']] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy-dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - 'Dummy-dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithNormalizationAndDenormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', ['dummy']) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => [ - 'method' => 'PUT', - 'normalization_context' => [AbstractNormalizer::GROUPS => 'dummy'], 'denormalization_context' => [AbstractNormalizer::GROUPS => 'dummy'], - ] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy-dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy-dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - 'Dummy-dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeSkipsNotReadableAndNotWritableProperties(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'dummy', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET', 'status' => '202'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'status' => '202'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET', 'status' => '202'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST', 'status' => '202'] + self::OPERATION_FORMATS, - ], - ['pagination_client_items_per_page' => true] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), null, false, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummy', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a public id.', true, false, true, true, false, true, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'dummy' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a public id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testFilters(): void - { - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filters = [ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'swagger' => ['x-foo' => 'bar'], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - ]; - - foreach ($filters as $filterId => $filter) { - $filterLocatorProphecy->has($filterId)->willReturn(true); - $filterLocatorProphecy->get($filterId)->willReturn($filter); - } - - $filterLocatorProphecy->has('f4')->willReturn(false); - - $this->doTestNormalizeWithFilters($filterLocatorProphecy->reveal()); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testFiltersWithDeprecatedFilterCollection(): void - { - $this->doTestNormalizeWithFilters(new FilterCollection([ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'swagger' => ['x-foo' => 'bar'], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - ])); - } - - public function testConstructWithInvalidFilterLocator(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface or null.'); - - new DocumentationNormalizer( - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), - null, - null, - $this->prophesize(OperationPathResolverInterface::class)->reveal(), - null, - new \ArrayObject(), - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $this->prophesize(IdentifiersExtractorInterface::class)->reveal() - ); - } - - public function testSupports(): void - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $this->assertTrue($normalizer->supportsNormalization($documentation, 'json')); - $this->assertFalse($normalizer->supportsNormalization($documentation)); - $this->assertFalse($normalizer->supportsNormalization(new Dummy(), 'json')); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } - - public function testNormalizeWithNoOperations(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->shouldNotBeCalled(); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.' - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name')->shouldNotBeCalled(); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithCustomMethod(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - ['get' => ['method' => 'FOO']] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'foo' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - ]), - ], - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithNestedNormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - $ref = 'Dummy-'.implode('_', $groups); - $relatedDummyRef = 'RelatedDummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['name', 'relatedDummy', 'relatedDummyWithCustomOpenApiContextType'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - - $relatedDummyMetadata = new ResourceMetadata( - 'RelatedDummy', - 'This is a related dummy.', - 'http://schema.example.com/RelatedDummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - ] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedDummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class), 'This is a related dummy \o/.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummyWithCustomOpenApiContextType', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class), 'This is a related dummy with type string \o/.', true, true, true, true, false, false, null, null, ['swagger_context' => ['type' => 'string']])); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/'.$ref], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'relatedDummy' => new \ArrayObject([ - 'description' => 'This is a related dummy \o/.', - '$ref' => '#/definitions/'.$relatedDummyRef, - ]), - 'relatedDummyWithCustomOpenApiContextType' => new \ArrayObject([ - 'description' => 'This is a related dummy with type string \o/.', - 'type' => 'string', - ]), - ], - ]), - $relatedDummyRef => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a related dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/RelatedDummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - private function doTestNormalizeWithFilters($filterLocator): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - ['get' => ['method' => 'GET', 'filters' => ['f1', 'f2', 'f3', 'f4']] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - $filterLocator, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - 'parameters' => [ - [ - 'x-foo' => 'bar', - 'name' => 'name', - 'in' => 'query', - 'required' => true, - 'type' => 'string', - ], - [ - 'name' => 'ha', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - ], - [ - 'name' => 'toto', - 'in' => 'query', - 'required' => true, - 'type' => 'array', - 'items' => [ - 'type' => 'string', - ], - 'collectionFormat' => 'csv', - ], - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'description' => 'This is a name.', - 'type' => 'string', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithSubResource(): void - { - $this->doTestNormalizeWithSubResource(); - } - - public function testLegacyNormalizeWithSubResource(): void - { - $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class); - $formatProviderProphecy->getFormatsFromOperation(Question::class, 'get', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]); - $formatProviderProphecy->getFormatsFromOperation(Answer::class, 'get', OperationType::SUBRESOURCE)->willReturn(['xml' => ['text/xml']]); - - $this->doTestNormalizeWithSubResource($formatProviderProphecy->reveal()); - } - - private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInterface $formatsProvider = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Question::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Question::class, Argument::cetera())->willReturn(new PropertyNameCollection(['answer'])); - $propertyNameCollectionFactoryProphecy->create(Answer::class, Argument::cetera())->willReturn(new PropertyNameCollection(['content'])); - - $questionMetadata = new ResourceMetadata( - 'Question', - 'This is a question.', - 'http://schema.example.com/Question', - ['get' => ['method' => 'GET', 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]]] - ); - $answerMetadata = new ResourceMetadata( - 'Answer', - 'This is an answer.', - 'http://schema.example.com/Answer', - [], - ['get' => ['method' => 'GET']] + self::OPERATION_FORMATS, - [], - ['get' => ['method' => 'GET', 'input_formats' => ['xml' => ['text/xml']], 'output_formats' => ['xml' => ['text/xml']]]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Question::class)->willReturn($questionMetadata); - $resourceMetadataFactoryProphecy->create(Answer::class)->willReturn($answerMetadata); - - $subresourceMetadata = new SubresourceMetadata(Answer::class, false); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Question::class, 'answer', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [], $subresourceMetadata)); - $propertyMetadataFactoryProphecy->create(Answer::class, 'content', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $routeCollection = new RouteCollection(); - $routeCollection->add('api_questions_answer_get_subresource', new Route('/api/questions/{id}/answer.{_format}')); - $routeCollection->add('api_questions_get_item', new Route('/api/questions/{id}.{_format}')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()))); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new UnderscorePathSegmentNameGenerator(), $identifiersExtractorProphecy->reveal()); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - $subresourceOperationFactory, - true, - 'page', - false, - 'itemsPerPage', - $formatsProvider ?? ['json' => ['application/json'], 'csv' => ['text/csv']], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/api/questions/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Question'], - 'operationId' => 'getQuestionItem', - 'produces' => ['application/json', 'text/csv'], - 'summary' => 'Retrieves a Question resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Question resource response', - 'schema' => ['$ref' => '#/definitions/Question'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - '/api/questions/{id}/answer' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Answer', 'Question'], - 'operationId' => 'api_questions_answer_get_subresource', - 'produces' => ['text/xml'], - 'summary' => 'Retrieves a Answer resource.', - 'responses' => [ - 200 => [ - 'description' => 'Answer resource response', - 'schema' => ['$ref' => '#/definitions/Answer'], - ], - 404 => ['description' => 'Resource not found'], - ], - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Question' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a question.', - 'externalDocs' => ['url' => 'http://schema.example.com/Question'], - 'properties' => [ - 'answer' => new \ArrayObject([ - 'type' => 'array', - 'description' => 'This is a name.', - 'items' => ['$ref' => '#/definitions/Answer'], - ]), - ], - ]), - 'Answer' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is an answer.', - 'externalDocs' => ['url' => 'http://schema.example.com/Answer'], - 'properties' => [ - 'content' => new \ArrayObject([ - 'type' => 'array', - 'description' => 'This is a name.', - 'items' => ['$ref' => '#/definitions/Answer'], - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithPropertySwaggerContext(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['swagger_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithPaginationClientEnabled(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [], - ['get' => ['method' => 'GET', 'pagination_client_enabled' => true] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['swagger_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - [ - 'name' => 'pagination', - 'in' => 'query', - 'required' => false, - 'type' => 'boolean', - 'description' => 'Enable or disable pagination', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithCustomFormatsDefinedAtOperationLevel(): void - { - $this->doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(); - } - - public function testLegacyNormalizeWithCustomFormatsDefinedAtOperationLevel(): void - { - $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::ITEM)->willReturn(['jsonapi' => ['application/vnd.api+json']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'put', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::COLLECTION)->willReturn(['xml' => ['application/xml', 'text/xml']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'post', OperationType::COLLECTION)->willReturn(['xml' => ['text/xml'], 'csv' => ['text/csv']]); - - $this->doTestNormalizeWithCustomFormatsDefinedAtOperationLevel($formatProviderProphecy->reveal()); - } - - private function doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAwareFormatsProviderInterface $formatProvider = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET', 'output_formats' => ['jsonapi' => ['application/vnd.api+json']]], - 'put' => ['method' => 'PUT', 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]], ], - [ - 'get' => ['method' => 'GET', 'output_formats' => ['xml' => ['application/xml', 'text/xml']]], - 'post' => ['method' => 'POST', 'output_formats' => ['xml' => ['text/xml'], 'csv' => ['text/csv']], 'input_formats' => ['xml' => ['text/xml'], 'csv' => ['text/csv']]], - ]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, false, - '', - '', - '', - '', - [], - [], - null, - false, - 'page', - false, - 'itemsPerPage', - $formatProvider, - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/xml', 'text/xml'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['text/xml', 'text/csv'], - 'produces' => ['text/xml', 'text/csv'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/vnd.api+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/json', 'text/csv'], - 'produces' => ['application/json', 'text/csv'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/'])); - } - - public function testLegacyNormalizeWithInputAndOutputClass(): void - { - $this->doTestNormalizeWithInputAndOutputClass(); - } - - private function doTestNormalizeWithInputAndOutputClass(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(InputDto::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['foo', 'bar'])); - $propertyNameCollectionFactoryProphecy->create(OutputDto::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['baz', 'bat'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ], - [ - 'input' => ['class' => InputDto::class], - 'output' => ['class' => OutputDto::class], - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - // InputDto - $propertyMetadataFactoryProphecy->create(InputDto::class, 'foo', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'foo', true, false)); - $propertyMetadataFactoryProphecy->create(InputDto::class, 'bar', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'bar', true, true, true, true, false, false, null, null, [])); - // OutputDto - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'baz', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'baz', true, false)); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'bat', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'bat', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - '', - [], - [], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'version' => '1.2.3', - 'description' => 'This is a test API.', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => [ - '$ref' => '#/definitions/Dummy.OutputDto', - ], - ], - ], - ], - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'description' => 'The collection page number', - 'type' => 'integer', - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => [ - '$ref' => '#/definitions/Dummy.OutputDto', - ], - ], - 400 => [ - 'description' => 'Invalid input', - ], - 404 => [ - 'description' => 'Resource not found', - ], - 422 => [ - 'description' => 'Unprocessable entity', - ], - ], - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => [ - '$ref' => '#/definitions/Dummy.InputDto', - ], - ], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'required' => true, - 'type' => 'string', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => [ - '$ref' => '#/definitions/Dummy.OutputDto', - ], - ], - 404 => [ - 'description' => 'Resource not found', - ], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'required' => true, - 'type' => 'string', - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => [ - '$ref' => '#/definitions/Dummy.InputDto', - ], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => [ - '$ref' => '#/definitions/Dummy.OutputDto', - ], - ], - 400 => [ - 'description' => 'Invalid input', - ], - 404 => [ - 'description' => 'Resource not found', - ], - 422 => [ - 'description' => 'Unprocessable entity', - ], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy.OutputDto' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => [ - 'url' => 'http://schema.example.com/Dummy', - ], - 'properties' => [ - 'baz' => new \ArrayObject([ - 'readOnly' => true, - 'description' => 'baz', - 'type' => 'string', - ]), - 'bat' => new \ArrayObject([ - 'description' => 'bat', - 'type' => 'integer', - ]), - ], - ]), - 'Dummy.InputDto' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => [ - 'url' => 'http://schema.example.com/Dummy', - ], - 'properties' => [ - 'foo' => new \ArrayObject([ - 'readOnly' => true, - 'description' => 'foo', - 'type' => 'string', - ]), - 'bar' => new \ArrayObject([ - 'description' => 'bar', - 'type' => 'integer', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - /** - * @dataProvider propertyWithDefaultProvider - * - * @param mixed $expectedDefault - * @param mixed $expectedExample - */ - public function testNormalizeWithDefaultProperty($expectedDefault, $expectedExample, PropertyMetadata $propertyMetadata) - { - $documentation = new Documentation(new ResourceNameCollection([DummyPropertyWithDefaultValue::class])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyPropertyWithDefaultValue::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo'])); - - $dummyMetadata = new ResourceMetadata('DummyPropertyWithDefaultValue', null, null, ['get' => ['method' => 'GET']]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyPropertyWithDefaultValue::class)->shouldBeCalled()->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyPropertyWithDefaultValue::class, 'foo', Argument::any())->shouldBeCalled()->willReturn($propertyMetadata); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - '', - [], - [], - $identifiersExtractorProphecy->reveal() - ); - - $result = $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT); - - $this->assertIsArray($result); - $this->assertEquals($expectedDefault, $result['definitions']['DummyPropertyWithDefaultValue']['properties']['foo']['default']); - $this->assertEquals($expectedExample, $result['definitions']['DummyPropertyWithDefaultValue']['properties']['foo']['example']); - } - - public function propertyWithDefaultProvider() - { - yield 'default should be use for the example if it is not defined' => [ - 'default name', - 'default name', - $this->createStringPropertyMetada('default name'), - ]; - - yield 'should use default and example if they are defined' => [ - 'default name', - 'example name', - $this->createStringPropertyMetada('default name', 'example name'), - ]; - - yield 'should use default and example from swagger context if they are defined' => [ - 'swagger default', - 'swagger example', - $this->createStringPropertyMetada('default name', 'example name', ['swagger_context' => ['default' => 'swagger default', 'example' => 'swagger example']]), - ]; - } - - protected function createStringPropertyMetada($default = null, $example = null, $attributes = []): PropertyMetadata - { - return new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), null, true, true, true, true, false, false, null, null, $attributes, null, null, $default, $example); - } -} diff --git a/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php b/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php deleted file mode 100644 index c5fbdf0dc3f..00000000000 --- a/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php +++ /dev/null @@ -1,3280 +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); - -namespace ApiPlatform\Core\Tests\Swagger\Serializer; - -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\JsonSchema\SchemaFactory; -use ApiPlatform\JsonSchema\SchemaFactoryInterface; -use ApiPlatform\JsonSchema\TypeFactory; -use ApiPlatform\JsonSchema\TypeFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\OpenApi\Model; -use ApiPlatform\OpenApi\OpenApi; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use ApiPlatform\Tests\Fixtures\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * @author Amrouche Hamza - * @author Kévin Dunglas - * @author Anthony GRASSIOT - * @group legacy - */ -class DocumentationNormalizerV3Test extends TestCase -{ - use ProphecyTrait; - - private const OPERATION_FORMATS = [ - 'input_formats' => ['jsonld' => ['application/ld+json']], - 'output_formats' => ['jsonld' => ['application/ld+json']], - ]; - - public function testNormalize(): void - { - $this->doTestNormalize(); - } - - public function testLegacyNormalize(): void - { - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET'); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'put')->willReturn('PUT'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'post')->willReturn('POST'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'custom')->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'custom2')->willReturn('POST'); - - $this->doTestNormalize($operationMethodResolverProphecy->reveal()); - } - - private function doTestNormalize(OperationMethodResolverInterface $operationMethodResolver = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - 'custom' => ['method' => 'GET', 'path' => '/foo'] + self::OPERATION_FORMATS, - 'custom2' => ['method' => 'POST', 'path' => '/foo'] + self::OPERATION_FORMATS, - ], - ['pagination_client_items_per_page' => true, 'normalization_context' => [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::cetera())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, null, null, null, null, null)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$'])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::cetera())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::cetera())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - $operationMethodResolver, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 30, - 'minimum' => 0, - ], - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'links' => [ - 'GetDummyItem' => [ - 'operationId' => 'getDummyItem', - 'parameters' => ['id' => '$response.body#/id'], - 'description' => 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.', - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/foo' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'customDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 30, - 'minimum' => 0, - ], - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'custom2DummyCollection', - 'summary' => 'Creates a Dummy resource.', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'links' => [ - 'GetDummyItem' => [ - 'operationId' => 'getDummyItem', - 'parameters' => ['id' => '$response.body#/id'], - 'description' => 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.', - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'additionalProperties' => false, - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'minLength' => 3, - 'maxLength' => 20, - 'pattern' => '^dummyPattern$', - ]), - 'description' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is an initializable but not writable property.', - ]), - 'dummyDate' => new \ArrayObject([ - 'nullable' => true, - 'type' => 'string', - 'format' => 'date-time', - 'description' => 'This is a \DateTimeInterface object.', - ]), - ], - ]), - ]), - ], - 'servers' => [['url' => '/app_dev.php/']], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - $this->assertArrayNotHasKey('servers', (array) $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/'])); - $this->assertArrayNotHasKey('servers', (array) $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => ''])); - } - - public function testNormalizeWithNameConverter(): void - { - $this->doTestNormalizeWithNameConverter(); - } - - public function testLegacyNormalizeWithNameConverter(): void - { - $this->doTestNormalizeWithNameConverter(true); - } - - private function doTestNormalizeWithNameConverter(bool $legacy = false): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Dummy API', 'This is a dummy API', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name', 'nameConverted'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, null, null, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'nameConverted', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a converted name.', true, true, null, null, false)); - - $nameConverterProphecy = $this->prophesize(NameConverterInterface::class); - $nameConverterProphecy->normalize('name', Dummy::class, 'jsonld', [])->willReturn('name'); - $nameConverterProphecy->normalize('nameConverted', Dummy::class, 'jsonld', [])->willReturn('name_converted'); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - /** - * @var ResourceMetadataFactoryInterface - */ - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - /** - * @var PropertyNameCollectionFactoryInterface - */ - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - /** - * @var PropertyMetadataFactoryInterface - */ - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - /** - * @var NameConverterInterface - */ - $nameConverter = $nameConverterProphecy->reveal(); - - /** - * @var TypeFactoryInterface|null - */ - $typeFactory = null; - /** - * @var SchemaFactoryInterface|null - */ - $schemaFactory = null; - - if (!$legacy) { - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $nameConverter); - $typeFactory->setSchemaFactory($schemaFactory); - } - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $schemaFactory, - $typeFactory, - $operationPathResolver, - null, - null, - $legacy ? $nameConverter : null, - true, - 'oauth2', - 'authorizationCode', - '/oauth/v2/token', - '/oauth/v2/auth', - ['scope param'], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Dummy API', - 'description' => 'This is a dummy API', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'name_converted' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a converted name.', - ]), - ], - ]), - ]), - 'securitySchemes' => [ - 'oauth' => [ - 'type' => 'oauth2', - 'description' => 'OAuth 2.0 authorization code Grant', - 'flows' => [ - 'authorizationCode' => [ - 'tokenUrl' => '/oauth/v2/token', - 'authorizationUrl' => '/oauth/v2/auth', - 'scopes' => new \ArrayObject(['scope param']), - ], - ], - ], - ], - ], - 'security' => [['oauth' => []]], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithApiKeysEnabled(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, null, null, false)); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $apiKeysConfiguration = [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]; - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - $apiKeysConfiguration, - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - 'securitySchemes' => [ - 'header' => [ - 'type' => 'apiKey', - 'in' => 'header', - 'description' => 'Value for the Authorization header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'apiKey', - 'in' => 'query', - 'description' => 'Value for the key query parameter', - 'name' => 'key', - ], - ], - ], - 'security' => [ - ['header' => []], - ['query' => []], - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithOnlyNormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - - $ref = 'Dummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'summary' => 'Creates a Dummy resource.', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/'.$ref], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithOpenApiDefinitionName(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['id'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => [ - 'method' => 'GET', - 'normalization_context' => [ - DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'Read', - ], - ] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy-Read'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy-Read' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - ], - ]), - ]), - ], - 'servers' => [['url' => '/app_dev.php/']], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithOnlyDenormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', ['dummy']) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => 'dummy']] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ]], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy-dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - 'Dummy-dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithNormalizationAndDenormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', ['dummy']) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => [ - 'method' => 'PUT', - 'normalization_context' => [AbstractNormalizer::GROUPS => 'dummy'], 'denormalization_context' => [AbstractNormalizer::GROUPS => 'dummy'], - ] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ]], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy-dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy-dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - 'Dummy-dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testFilters(): void - { - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filters = [ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'openapi' => ['x-foo' => 'bar'], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - 'f4' => new DummyFilter(['order[name]' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => false, - 'schema' => [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ], - ]]), - ]; - - foreach ($filters as $filterId => $filter) { - $filterLocatorProphecy->has($filterId)->willReturn(true); - $filterLocatorProphecy->get($filterId)->willReturn($filter); - } - - $filterLocatorProphecy->has('f5')->willReturn(false); - - $this->doTestNormalizeWithFilters($filterLocatorProphecy->reveal()); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testFiltersWithDeprecatedFilterCollection(): void - { - $this->doTestNormalizeWithFilters(new FilterCollection([ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'openapi' => ['x-foo' => 'bar'], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - 'f4' => new DummyFilter(['order[name]' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => false, - 'schema' => [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ], - ]]), - ])); - } - - public function testConstructWithInvalidFilterLocator(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface or null.'); - - new DocumentationNormalizer( - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), - null, - null, - $this->prophesize(OperationPathResolverInterface::class)->reveal(), - null, - new \ArrayObject(), - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $this->prophesize(IdentifiersExtractorInterface::class)->reveal() - ); - } - - public function testSupports(): void - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $this->assertTrue($normalizer->supportsNormalization($documentation, 'json')); - $this->assertFalse($normalizer->supportsNormalization($documentation)); - $this->assertFalse($normalizer->supportsNormalization(new Dummy(), 'json')); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } - - public function testNormalizeWithNoOperations(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->shouldNotBeCalled(); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - [], - ['formats' => ['jsonld' => ['application/ld+json']]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name')->shouldNotBeCalled(); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithCustomMethod(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - ['get' => ['method' => 'FOO'] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'foo' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - ]), - ], - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithNestedNormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - $ref = 'Dummy-'.implode('_', $groups); - $relatedDummyRef = 'RelatedDummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['name', 'relatedDummy'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - - $relatedDummyMetadata = new ResourceMetadata( - 'RelatedDummy', - 'This is a related dummy.', - 'http://schema.example.com/RelatedDummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - ] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedDummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class), 'This is a related dummy \o/.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ]], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/'.$ref], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'relatedDummy' => new \ArrayObject([ - 'description' => 'This is a related dummy \o/.', - 'nullable' => true, - 'anyOf' => [ - ['$ref' => '#/components/schemas/'.$relatedDummyRef], - ], - ]), - ], - ]), - $relatedDummyRef => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a related dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/RelatedDummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - private function doTestNormalizeWithFilters($filterLocator): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - ['get' => ['method' => 'GET', 'filters' => ['f1', 'f2', 'f3', 'f4', 'f5']] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - $filterLocator, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - 'parameters' => [ - [ - 'x-foo' => 'bar', - 'name' => 'name', - 'in' => 'query', - 'required' => true, - 'schema' => ['type' => 'string'], - ], - [ - 'name' => 'ha', - 'in' => 'query', - 'required' => false, - 'schema' => ['type' => 'integer'], - ], - [ - 'name' => 'toto', - 'in' => 'query', - 'required' => true, - 'schema' => [ - 'type' => 'array', - 'items' => [ - 'type' => 'string', - ], - ], - 'style' => 'deepObject', - 'explode' => true, - ], - [ - 'name' => 'order[name]', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ], - ], - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'description' => 'This is a name.', - 'type' => 'string', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithSubResource(): void - { - $this->doTestNormalizeWithSubResource(); - } - - public function testLegacytNormalizeWithSubResource(): void - { - $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class); - $formatProviderProphecy->getFormatsFromOperation(Question::class, 'get', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]); - $formatProviderProphecy->getFormatsFromOperation(Answer::class, 'get', OperationType::SUBRESOURCE)->willReturn(['xml' => ['text/xml']]); - - $this->doTestNormalizeWithSubResource($formatProviderProphecy->reveal()); - } - - private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInterface $formatProvider = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Question::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Question::class, Argument::cetera())->willReturn(new PropertyNameCollection(['answer'])); - $propertyNameCollectionFactoryProphecy->create(Answer::class, Argument::cetera())->willReturn(new PropertyNameCollection(['content'])); - - $questionMetadata = new ResourceMetadata( - 'Question', - 'This is a question.', - 'http://schema.example.com/Question', - ['get' => ['method' => 'GET', 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]]] - ); - $answerMetadata = new ResourceMetadata( - 'Answer', - 'This is an answer.', - 'http://schema.example.com/Answer', - [], - ['get' => ['method' => 'GET']] + self::OPERATION_FORMATS, - [], - ['get' => ['method' => 'GET', 'input_formats' => ['xml' => ['text/xml']], 'output_formats' => ['xml' => ['text/xml']]]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Question::class)->willReturn($questionMetadata); - $resourceMetadataFactoryProphecy->create(Answer::class)->willReturn($answerMetadata); - - $subresourceMetadata = new SubresourceMetadata(Answer::class, false); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Question::class, 'answer', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [], $subresourceMetadata)); - $propertyMetadataFactoryProphecy->create(Answer::class, 'content', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $routeCollection = new RouteCollection(); - $routeCollection->add('api_questions_answer_get_subresource', new Route('/api/questions/{id}/answer.{_format}')); - $routeCollection->add('api_questions_get_item', new Route('/api/questions/{id}.{_format}')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()))); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new UnderscorePathSegmentNameGenerator(), $identifiersExtractorProphecy->reveal()); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - $subresourceOperationFactory, - true, - 'page', - false, - 'itemsPerPage', - $formatProvider ?? [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/api/questions/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Question'], - 'operationId' => 'getQuestionItem', - 'summary' => 'Retrieves a Question resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Question resource response', - 'content' => [ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Question'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Question'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - '/api/questions/{id}/answer' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Answer', 'Question'], - 'operationId' => 'api_questions_answer_get_subresource', - 'summary' => 'Retrieves a Answer resource.', - 'responses' => [ - '200' => [ - 'description' => 'Answer resource response', - 'content' => [ - 'text/xml' => [ - 'schema' => ['$ref' => '#/components/schemas/Answer'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Question' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a question.', - 'externalDocs' => ['url' => 'http://schema.example.com/Question'], - 'properties' => [ - 'answer' => new \ArrayObject([ - 'type' => 'array', - 'description' => 'This is a name.', - 'items' => ['$ref' => '#/components/schemas/Answer'], - ]), - ], - ]), - 'Answer' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is an answer.', - 'externalDocs' => ['url' => 'http://schema.example.com/Answer'], - 'properties' => [ - 'content' => new \ArrayObject([ - 'type' => 'array', - 'description' => 'This is a name.', - 'items' => ['$ref' => '#/components/schemas/Answer'], - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithPropertyOpenApiContext(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithPaginationClientEnabled(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [], - ['get' => ['method' => 'GET', 'pagination_client_enabled' => true] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'pagination', - 'in' => 'query', - 'required' => false, - 'schema' => ['type' => 'boolean'], - 'description' => 'Enable or disable pagination', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithPaginationCustomDefaultAndMaxItemsPerPage(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [], - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS], - ['pagination_client_items_per_page' => true, 'pagination_items_per_page' => 20, 'pagination_maximum_items_per_page' => 80] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 20, - 'minimum' => 0, - 'maximum' => 80, - ], - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - /** - * @group legacy - * @expectedDeprecation The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3. - */ - public function testLegacyNormalizeWithPaginationCustomDefaultAndMaxItemsPerPage(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [], - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS], - ['pagination_client_items_per_page' => true, 'pagination_items_per_page' => 20, 'maximum_items_per_page' => 80] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 20, - 'minimum' => 0, - 'maximum' => 80, - ], - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithCustomFormatsDefinedAtOperationLevel(): void - { - $this->doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(); - } - - public function testLegacyNormalizeWithCustomFormatsDefinedAtOperationLevel(): void - { - $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::ITEM)->willReturn(['jsonapi' => ['application/vnd.api+json']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'put', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::COLLECTION)->willReturn(['xml' => ['application/xml', 'text/xml']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'post', OperationType::COLLECTION)->willReturn(['xml' => ['text/xml'], 'csv' => ['text/csv']]); - - $this->doTestNormalizeWithCustomFormatsDefinedAtOperationLevel($formatProviderProphecy->reveal()); - } - - private function doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAwareFormatsProviderInterface $formatsProvider = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET', 'output_formats' => ['jsonapi' => ['application/vnd.api+json']]], - 'put' => ['method' => 'PUT', 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]], ], - [ - 'get' => ['method' => 'GET', 'output_formats' => ['xml' => ['application/xml', 'text/xml']]], - 'post' => ['method' => 'POST', 'output_formats' => ['xml' => ['text/xml'], 'csv' => ['text/csv']], 'input_formats' => ['xml' => ['text/xml'], 'csv' => ['text/csv']]], - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, false, - '', - '', - '', - '', - [], - [], - null, - false, - 'page', - false, - 'itemsPerPage', - $formatsProvider ?? [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/xml' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'text/xml' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'summary' => 'Creates a Dummy resource.', - 'requestBody' => [ - 'content' => [ - 'text/xml' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'text/xml' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'links' => [ - 'GetDummyItem' => [ - 'operationId' => 'getDummyItem', - 'parameters' => ['id' => '$response.body#/id'], - 'description' => 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.', - ], - ], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/vnd.api+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'requestBody' => [ - 'content' => [ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/'])); - } - - /** - * @group legacy - * @expectedDeprecation Using the swagger DocumentationNormalizer is deprecated in favor of decorating the OpenApiFactory, use the "openapi.backward_compatibility_layer" configuration to change this behavior. - */ - public function testNormalizeOpenApi() - { - $openapi = new OpenApi(new Model\Info('api', 'v1'), [], new Model\Paths()); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - - $openApiNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $openApiNormalizerProphecy->normalize($openapi, null, [])->willReturn([])->shouldBeCalled(); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, false, - '', - '', - '', - '', - [], - [], - null, - false, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal(), - $openApiNormalizerProphecy->reveal() - ); - - $this->assertTrue($normalizer->supportsNormalization($openapi, 'json')); - $this->assertEquals([], $normalizer->normalize($openapi)); - } -} diff --git a/tests/Core/Test/BookTestDeprecatedClient.php b/tests/Core/Test/BookTestDeprecatedClient.php deleted file mode 100644 index 74dc5ea72ee..00000000000 --- a/tests/Core/Test/BookTestDeprecatedClient.php +++ /dev/null @@ -1,36 +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); - -namespace ApiPlatform\Core\Tests\Test; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase; -use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client; -use ApiPlatform\Core\Bridge\Symfony\Routing\Router; - -class BookTestDeprecatedClient extends ApiTestCase -{ - /** @phpstan-ignore-next-line */ - private Client $client; - /** @phpstan-ignore-next-line */ - private Router $router; - - protected function setup(): void - { - $this->client = static::createClient(); - } - - public function testWorks(): void - { - $this->assertTrue(true); - } -} diff --git a/tests/Core/Upgrade/SubresourceTransformerTest.php b/tests/Core/Upgrade/SubresourceTransformerTest.php deleted file mode 100644 index aa70709adee..00000000000 --- a/tests/Core/Upgrade/SubresourceTransformerTest.php +++ /dev/null @@ -1,337 +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); - -namespace ApiPlatform\Tests\Core\Bridge\Rector\Service; - -use ApiPlatform\Core\Upgrade\SubresourceTransformer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyOffer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FourthLevel; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Greeting; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Person; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel; -use PHPUnit\Framework\TestCase; - -class SubresourceTransformerTest extends TestCase -{ - /** - * @dataProvider toUriVariablesProvider - */ - public function testToUriVariables(array $metadata, array $expectedMetadata): void - { - $subresourceTransformer = new SubresourceTransformer(); - self::assertEquals($expectedMetadata, $subresourceTransformer->toUriVariables($metadata)); - } - - public function toUriVariablesProvider(): \Generator - { - yield '/questions/{id}/answer' => [ - [ - 'property' => 'answer', - 'collection' => false, - 'resource_class' => Answer::class, - 'identifiers' => ['id' => [Question::class, 'id', true]], - 'path' => '/questions/{id}/answer.{_format}', - ], - [ - 'id' => [ - 'from_class' => Question::class, - 'from_property' => 'answer', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/questions/{id}/answer/related_questions' => [ - [ - 'property' => 'relatedQuestions', - 'collection' => true, - 'resource_class' => Question::class, - 'identifiers' => [ - 'id' => [Question::class, 'id', true], - 'answer' => [Answer::class, 'id', false], - ], - 'path' => '/questions/{id}/answer/related_questions.{_format}', - ], - [ - 'id' => [ - 'from_class' => Question::class, - 'from_property' => 'answer', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'answer' => [ - 'from_class' => Answer::class, - 'from_property' => null, - 'to_property' => 'answer', - 'identifiers' => [], - 'composite_identifier' => false, - 'expanded_value' => 'answer', - ], - ], - ]; - - yield '/dummies/{id}/related_dummies' => [ - [ - 'property' => 'relatedDummies', - 'collection' => true, - 'resource_class' => RelatedDummy::class, - 'identifiers' => ['id' => [Dummy::class, 'id', true]], - 'path' => '/dummies/{id}/related_dummies.{_format}', - ], - [ - 'id' => [ - 'from_class' => Dummy::class, - 'from_property' => 'relatedDummies', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/dummies/{id}/related_dummies/{relatedDummies}' => [ - [ - 'property' => 'id', - 'collection' => false, - 'resource_class' => RelatedDummy::class, - 'identifiers' => [ - 'id' => [Dummy::class, 'id', true], - 'relatedDummies' => [RelatedDummy::class, 'id', true], - ], - 'path' => '/dummies/{id}/related_dummies/{relatedDummies}.{_format}', - ], - [ - 'id' => [ - 'from_class' => Dummy::class, - 'from_property' => 'relatedDummies', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'relatedDummies' => [ - 'from_class' => RelatedDummy::class, - 'from_property' => null, - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/dummies/{id}/related_dummies/{relatedDummies}/third_level' => [ - [ - 'property' => 'thirdLevel', - 'collection' => false, - 'resource_class' => ThirdLevel::class, - 'identifiers' => [ - 'id' => [Dummy::class, 'id', true], - 'relatedDummies' => [RelatedDummy::class, 'id', true], - ], - 'path' => '/dummies/{id}/related_dummies/{relatedDummies}/third_level.{_format}', - ], - [ - 'id' => [ - 'from_class' => Dummy::class, - 'from_property' => 'relatedDummies', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'relatedDummies' => [ - 'from_class' => RelatedDummy::class, - 'from_property' => 'thirdLevel', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level' => [ - [ - 'property' => 'fourthLevel', - 'collection' => false, - 'resource_class' => FourthLevel::class, - 'identifiers' => [ - 'id' => [Dummy::class, 'id', true], - 'relatedDummies' => [RelatedDummy::class, 'id', true], - 'thirdLevel' => [ThirdLevel::class, 'id', false], - ], - 'path' => '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', - ], - [ - 'id' => [ - 'from_class' => Dummy::class, - 'from_property' => 'relatedDummies', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'relatedDummies' => [ - 'from_class' => RelatedDummy::class, - 'from_property' => 'thirdLevel', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'thirdLevel' => [ - 'from_class' => ThirdLevel::class, - 'from_property' => 'fourthLevel', - 'to_property' => null, - 'identifiers' => [], - 'composite_identifier' => false, - 'expanded_value' => 'third_level', - ], - ], - ]; - - yield '/dummy_products/{id}/offers/{offers}/offers' => [ - [ - 'property' => 'offers', - 'collection' => true, - 'resource_class' => DummyOffer::class, - 'identifiers' => [ - 'id' => [DummyProduct::class, 'id', true], - 'offers' => [DummyAggregateOffer::class, 'id', true], - ], - 'path' => '/dummy_products/{id}/offers/{offers}/offers.{_format}', - ], - [ - 'id' => [ - 'from_class' => DummyProduct::class, - 'from_property' => null, - 'to_property' => 'product', - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'offers' => [ - 'from_class' => DummyAggregateOffer::class, - 'from_property' => null, - 'to_property' => 'aggregate', - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/dummy_aggregate_offers/{id}/offers' => [ - [ - 'property' => 'offers', - 'collection' => true, - 'resource_class' => DummyOffer::class, - 'identifiers' => [ - 'id' => [DummyAggregateOffer::class, 'id', true], - ], - 'path' => '/dummy_aggregate_offers/{id}/offers.{_format}', - ], - [ - 'id' => [ - 'from_class' => DummyAggregateOffer::class, - 'from_property' => null, - 'to_property' => 'aggregate', - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/people/{id}/sent_greetings' => [ - [ - 'property' => 'sentGreetings', - 'collection' => true, - 'resource_class' => Greeting::class, - 'identifiers' => [ - 'id' => [Person::class, 'id', true], - ], - 'path' => '/people/{id}/sent_greetings.{_format}', - ], - [ - 'id' => [ - 'from_class' => Person::class, - 'from_property' => null, - 'to_property' => 'sender', - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/related_owned_dummies/{id}/owning_dummy' => [ - [ - 'property' => 'owningDummy', - 'collection' => false, - 'resource_class' => Dummy::class, - 'identifiers' => [ - 'id' => [RelatedOwnedDummy::class, 'id', true], - ], - 'path' => '/related_owned_dummies/{id}/owned_dummy.{_format}', - ], - [ - 'id' => [ - 'from_class' => RelatedOwnedDummy::class, - 'from_property' => 'owningDummy', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/related_owning_dummies/{id}/owned_dummy' => [ - [ - 'property' => 'ownedDummy', - 'collection' => false, - 'resource_class' => Dummy::class, - 'identifiers' => [ - 'id' => [RelatedOwningDummy::class, 'id', true], - ], - 'path' => '/related_owning_dummies/{id}/owned_dummy.{_format}', - ], - [ - 'id' => [ - 'from_class' => RelatedOwningDummy::class, - 'from_property' => 'ownedDummy', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - } -} diff --git a/tests/Core/Validator/EventListener/ValidateListenerTest.php b/tests/Core/Validator/EventListener/ValidateListenerTest.php deleted file mode 100644 index 4600840bc8c..00000000000 --- a/tests/Core/Validator/EventListener/ValidateListenerTest.php +++ /dev/null @@ -1,189 +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); - -namespace ApiPlatform\Core\Tests\Validator\EventListener; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Symfony\EventListener\ValidateListener; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use ApiPlatform\Validator\Exception\ValidationException; -use ApiPlatform\Validator\ValidatorInterface; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * @author Samuel ROZE - * @author Kévin Dunglas - * - * @group legacy - */ -class ValidateListenerTest extends TestCase -{ - use ProphecyTrait; - - public function testNotAnApiPlatformRequest() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $request = new Request(); - $request->setMethod('POST'); - - $listener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - - $event = new ViewEvent($this->prophesize(HttpKernelInterface::class)->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, []); - $listener->onKernelView($event); - } - - public function testValidatorIsCalled() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, ['groups' => $expectedValidationGroups])->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - public function testDoNotValidateWhenControllerResultIsResponse() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $dummy = new DummyEntity(); - - $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => DummyEntity::class, '_api_collection_operation_name' => 'post', '_api_receive' => false]); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testDoNotValidateWhenReceiveFlagIsFalse() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $dummy = new DummyEntity(); - - $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => DummyEntity::class, '_api_collection_operation_name' => 'post', '_api_receive' => false]); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testDoNotValidateWhenDisabledInOperationAttribute() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - - $resourceMetadata = new ResourceMetadata('DummyEntity', null, null, [], [ - 'post' => [ - 'validate' => false, - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata); - - $dummy = new DummyEntity(); - - $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => DummyEntity::class, '_api_collection_operation_name' => 'post']); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testThrowsValidationExceptionWithViolationsFound() - { - $this->expectException(ValidationException::class); - - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, ['groups' => $expectedValidationGroups])->willThrow(new ValidationException())->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - private function createEventObject($expectedValidationGroups, $data, bool $receive = true): array - { - $resourceMetadata = new ResourceMetadata(null, null, null, [ - 'create' => ['validation_groups' => $expectedValidationGroups], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - if ($receive) { - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata)->shouldBeCalled(); - } - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $kernel = $this->prophesize(HttpKernelInterface::class)->reveal(); - $request = new Request([], [], [ - '_api_resource_class' => DummyEntity::class, - '_api_item_operation_name' => 'create', - '_api_format' => 'json', - '_api_mime_type' => 'application/json', - '_api_receive' => $receive, - ]); - - $request->setMethod('POST'); - $event = new ViewEvent($kernel, $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $data); - - return [$resourceMetadataFactory, $event]; - } -} diff --git a/tests/Doctrine/Common/State/PersistProcessorTest.php b/tests/Doctrine/Common/State/PersistProcessorTest.php index bd10fdce00d..0881f65e3e1 100644 --- a/tests/Doctrine/Common/State/PersistProcessorTest.php +++ b/tests/Doctrine/Common/State/PersistProcessorTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Common\State; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Metadata\Get; use ApiPlatform\State\ProcessorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\Persistence\ManagerRegistry; diff --git a/tests/Doctrine/Common/State/RemoveProcessorTest.php b/tests/Doctrine/Common/State/RemoveProcessorTest.php index c63d425693d..420b96a4e9e 100644 --- a/tests/Doctrine/Common/State/RemoveProcessorTest.php +++ b/tests/Doctrine/Common/State/RemoveProcessorTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Common\State; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Metadata\Delete; use ApiPlatform\State\ProcessorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ObjectManager; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php b/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php index 483c450eca2..772b12851cd 100644 --- a/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php +++ b/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php @@ -16,8 +16,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\EventListener\PublishMercureUpdatesListener; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface as GraphQlMercureSubscriptionIriGeneratorInterface; @@ -33,6 +31,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyFriend; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyMercure; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyOffer; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\UnitOfWork; @@ -309,7 +308,9 @@ public function testPublishUpdate(): void $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyMercure::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => []])); + $resourceMetadataFactoryProphecy->create(DummyMercure::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations([ + 'get' => (new Get())->withMercure([]), + ]))])); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations([ 'get' => (new Get())->withMercure(['hub' => 'managed', 'enable_async_update' => false])->withNormalizationContext(['groups' => ['foo', 'bar']]), diff --git a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php index 06d6128faf0..23429e167b8 100644 --- a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php +++ b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\EventListener\PurgeHttpCacheListener; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ItemNotFoundException; @@ -25,6 +24,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyNoGetOperation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\Event\PreUpdateEventArgs; diff --git a/tests/Doctrine/EventListener/WriteListenerTest.php b/tests/Doctrine/EventListener/WriteListenerTest.php index bd1c9bcfa41..0e4cad1aa2a 100644 --- a/tests/Doctrine/EventListener/WriteListenerTest.php +++ b/tests/Doctrine/EventListener/WriteListenerTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Doctrine\EventListener; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\EventListener\WriteListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ObjectManager; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Odm/Extension/FilterExtensionTest.php b/tests/Doctrine/Odm/Extension/FilterExtensionTest.php index 330ffefa5c8..06a4bb6e431 100644 --- a/tests/Doctrine/Odm/Extension/FilterExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/FilterExtensionTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; use ApiPlatform\Api\FilterInterface as ApiFilterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\FilterExtension; use ApiPlatform\Doctrine\Odm\Filter\FilterInterface; use ApiPlatform\Metadata\ApiResource; @@ -23,6 +22,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Doctrine/Odm/Extension/OrderExtensionTest.php b/tests/Doctrine/Odm/Extension/OrderExtensionTest.php index 7b9b1532e68..9354f2ea689 100644 --- a/tests/Doctrine/Odm/Extension/OrderExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/OrderExtensionTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\OrderExtension; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; @@ -21,6 +20,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Aggregation\Stage\Lookup; use Doctrine\ODM\MongoDB\Aggregation\Stage\Sort; diff --git a/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php b/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php index 9729f1d6a52..237254611db 100644 --- a/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\PaginationExtension; use ApiPlatform\Doctrine\Odm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; @@ -27,6 +26,7 @@ use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Test\DoctrineMongoDbOdmSetup; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Aggregation\Stage\Count; use Doctrine\ODM\MongoDB\Aggregation\Stage\Facet; diff --git a/tests/Doctrine/Odm/Filter/SearchFilterTest.php b/tests/Doctrine/Odm/Filter/SearchFilterTest.php index 54b72fff03a..67fa41815c4 100644 --- a/tests/Doctrine/Odm/Filter/SearchFilterTest.php +++ b/tests/Doctrine/Odm/Filter/SearchFilterTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase; @@ -23,6 +22,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use MongoDB\BSON\Regex; use Prophecy\Argument; diff --git a/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php b/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php index 81be28b8e1f..075f169d731 100644 --- a/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php +++ b/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Metadata\Property; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Metadata\Property\DoctrineMongoDbOdmPropertyMetadataFactory; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\Persistence\ManagerRegistry; diff --git a/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php b/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php index 5793373b06a..2dc7ac2a522 100644 --- a/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php +++ b/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Metadata\Resource; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Odm\Metadata\Resource\DoctrineMongoDbOdmResourceCollectionMetadataFactory; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Odm/PaginatorTest.php b/tests/Doctrine/Odm/PaginatorTest.php index f12f71b9eb0..a6f447a47c3 100644 --- a/tests/Doctrine/Odm/PaginatorTest.php +++ b/tests/Doctrine/Odm/PaginatorTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Odm; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Test\DoctrineMongoDbOdmSetup; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Iterator\Iterator; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Odm/State/CollectionProviderTest.php b/tests/Doctrine/Odm/State/CollectionProviderTest.php index c8e8920a376..bd976a3102f 100644 --- a/tests/Doctrine/Odm/State/CollectionProviderTest.php +++ b/tests/Doctrine/Odm/State/CollectionProviderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\State; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\State\CollectionProvider; @@ -24,6 +23,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ProviderEntity; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Iterator\Iterator; diff --git a/tests/Doctrine/Odm/State/ItemProviderTest.php b/tests/Doctrine/Odm/State/ItemProviderTest.php index eda8b7bf0f4..3c1f43f237e 100644 --- a/tests/Doctrine/Odm/State/ItemProviderTest.php +++ b/tests/Doctrine/Odm/State/ItemProviderTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\State; use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface; use ApiPlatform\Doctrine\Odm\State\ItemProvider; @@ -26,6 +25,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ProviderEntity; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Aggregation\Stage\MatchStage as AggregationMatch; use Doctrine\ODM\MongoDB\DocumentManager; diff --git a/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php b/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php index 4879505f575..6a3ee4d8049 100644 --- a/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php @@ -13,27 +13,26 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Extension; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AbstractDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ConcreteDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\EmbeddableDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\UnknownDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; @@ -42,7 +41,6 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Serializer\Mapping\AttributeMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadataInterface; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; @@ -51,8 +49,6 @@ /** * @author Amrouche Hamza * @author Antoine Bluchet - * - * @group legacy */ class EagerLoadingExtensionTest extends TestCase { @@ -62,8 +58,8 @@ public function testApplyToCollection() { $context = ['groups' => ['foo']]; $callContext = ['serializer_groups' => ['foo']]; - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -132,7 +128,7 @@ public function testApplyToCollection() $queryBuilderProphecy->getDQLPart('join')->willReturn([]); $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, null, $context); } @@ -141,8 +137,8 @@ public function testApplyToItem() $context = ['groups' => ['foo']]; $callContext = ['serializer_groups' => ['foo']]; - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -240,15 +236,15 @@ public function testApplyToItem() $queryBuilderProphecy->getDQLPart('select')->willReturn([]); $queryBuilder = $queryBuilderProphecy->reveal(); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $orderExtensionTest->applyToItem($queryBuilder, new QueryNameGenerator(), Dummy::class, [], null, $context); } public function testCreateItemWithOperationName() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -265,14 +261,14 @@ public function testCreateItemWithOperationName() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, [], 'item_operation', ['groups' => ['foo']]); } public function testCreateCollectionWithOperationName() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -289,17 +285,16 @@ public function testCreateCollectionWithOperationName() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, 'collection_operation', ['groups' => ['foo']]); } public function testDenormalizeItemWithCorrectResourceClass() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); // Dummy is the correct class for the denormalization context serialization groups, and we're fetching RelatedDummy - $resourceMetadata = (new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]]); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($resourceMetadata)->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata)->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($this->getMetadataWithNormalizationContext(RelatedDummy::class, ['groups' => ['foo']]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldNotBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -312,15 +307,15 @@ public function testDenormalizeItemWithCorrectResourceClass() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); - $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], 'item_operation', ['resource_class' => Dummy::class]); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], 'get', ['resource_class' => Dummy::class]); } public function testDenormalizeItemWithExistingGroups() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); // groups exist from the context, we don't need to compute them again - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($this->getMetadataWithNormalizationContext(RelatedDummy::class, ['groups' => ['foo']]))->shouldBeCalled(); $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldNotBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -334,7 +329,7 @@ public function testDenormalizeItemWithExistingGroups() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], 'item_operation', [AbstractNormalizer::GROUPS => 'some_groups']); } @@ -343,8 +338,8 @@ public function testMaxJoinsReached() $this->expectException(RuntimeException::class); $this->expectExceptionMessage('The total number of joined relations has exceeded the specified maximum. Raise the limit if necessary with the "api_platform.eager_loading.max_joins" configuration key (https://api-platform.com/docs/core/performance/#eager-loading), or limit the maximum serialization depth using the "enable_max_depth" option of the Symfony serializer (https://symfony.com/doc/current/components/serializer.html#handling-serialization-depth).'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class))->shouldBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -387,17 +382,14 @@ public function testMaxJoinsReached() $queryBuilderProphecy->addSelect(Argument::type('string'))->shouldBeCalled(); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, null, ['groups' => ['foo']]); } public function testMaxDepth() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => ['enable_max_depth' => 'true', 'groups' => ['foo']]]); - - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class, ['enable_max_depth' => 'true', 'groups' => ['foo']])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -411,12 +403,12 @@ public function testMaxDepth() $relationPropertyMetadata = new ApiProperty(); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo'], 'normalization_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $relatedPropertyMetadata = new ApiProperty(); $relatedPropertyMetadata = $relatedPropertyMetadata->withReadableLink(true); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'dummy', ['serializer_groups' => ['foo']])->willReturn($relatedPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'dummy', ['serializer_groups' => ['foo'], 'normalization_groups' => ['foo']])->willReturn($relatedPropertyMetadata)->shouldBeCalled(); $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->associationMappings = [ @@ -456,16 +448,14 @@ public function testMaxDepth() $queryBuilderProphecy->addSelect(Argument::type('string'))->shouldBeCalled(); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true, $classMetadataFactoryProphecy->reveal()); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true, $classMetadataFactoryProphecy->reveal()); $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class); } public function testForceEager() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => [AbstractNormalizer::GROUPS => 'foobar']]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class, [AbstractNormalizer::GROUPS => 'foobar'])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(UnknownDummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled(); @@ -477,8 +467,8 @@ public function testForceEager() $idPropertyMetadata = new ApiProperty(); $idPropertyMetadata = $idPropertyMetadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create(UnknownDummy::class, 'id', ['serializer_groups' => ['foobar']])->willReturn($idPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foobar']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(UnknownDummy::class, 'id', ['serializer_groups' => ['foobar'], 'normalization_groups' => 'foobar'])->willReturn($idPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foobar'], 'normalization_groups' => 'foobar'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -501,16 +491,14 @@ public function testForceEager() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } public function testExtraLazy() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => [AbstractNormalizer::GROUPS => 'foobar']]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class, [AbstractNormalizer::GROUPS => 'foobar'])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); // $propertyNameCollectionFactoryProphecy->create(UnknownDummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled(); @@ -519,7 +507,7 @@ public function testExtraLazy() $relationPropertyMetadata = new ApiProperty(); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foobar']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foobar'], 'normalization_groups' => 'foobar'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -537,7 +525,7 @@ public function testExtraLazy() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } @@ -561,7 +549,7 @@ public function testResourceClassNotFoundException() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } @@ -585,7 +573,7 @@ public function testPropertyNotFoundException() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } @@ -615,75 +603,10 @@ public function testResourceClassNotFoundExceptionPropertyNameCollection() $queryBuilderProphecy->innerJoin('o.relation', 'relation_a1')->shouldBeCalledTimes(1); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } - public function testApplyToCollectionWithSerializerContextBuilder() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - - $relatedNameCollection = new PropertyNameCollection(['id', 'name']); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedNameCollection)->shouldBeCalled(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new ApiProperty(); - $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); - - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); - - $idPropertyMetadata = new ApiProperty(); - $idPropertyMetadata = $idPropertyMetadata->withIdentifier(true); - $namePropertyMetadata = new ApiProperty(); - $namePropertyMetadata = $namePropertyMetadata->withReadable(true); - - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'id', ['serializer_groups' => ['foo']])->willReturn($idPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', ['serializer_groups' => ['foo']])->willReturn($namePropertyMetadata)->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->associationMappings = [ - 'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class], - ]; - - $relatedClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - - foreach ($relatedNameCollection as $property) { - if ('id' !== $property) { - $relatedClassMetadataProphecy->hasField($property)->willReturn(true)->shouldBeCalled(); - } - } - - $relatedClassMetadataProphecy->associationMappings = []; - - $emProphecy = $this->prophesize(EntityManager::class); - $emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $emProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($relatedClassMetadataProphecy->reveal()); - - $queryBuilderProphecy->getRootAliases()->willReturn(['o']); - $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - - $queryBuilderProphecy->leftJoin('o.relatedDummy', 'relatedDummy_a1')->shouldBeCalledTimes(1); - $queryBuilderProphecy->addSelect('partial relatedDummy_a1.{id,name}')->shouldBeCalledTimes(1); - $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - - $request = Request::create('/api/dummies', 'GET', []); - - $requestStack = new RequestStack(); - $requestStack->push($request); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest($request, true)->shouldBeCalled()->willReturn([AbstractNormalizer::GROUPS => ['foo']]); - - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, $requestStack, $serializerContextBuilderProphecy->reveal(), true); - $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); - } - public function testAttributes() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); @@ -742,14 +665,8 @@ public function testAttributes() $request = Request::create('/api/dummies', 'GET', []); - $requestStack = new RequestStack(); - $requestStack->push($request); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest($request, true)->shouldBeCalled()->willReturn([AbstractNormalizer::GROUPS => ['foo'], AbstractNormalizer::ATTRIBUTES => ['relatedDummies' => ['id', 'name'], 'relatedDummy' => ['id', 'name']]]); - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, $requestStack, $serializerContextBuilderProphecy->reveal(), true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); } @@ -783,14 +700,8 @@ public function testNotInAttributes() $request = Request::create('/api/dummies', 'GET', []); - $requestStack = new RequestStack(); - $requestStack->push($request); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest($request, true)->shouldBeCalled()->willReturn([AbstractNormalizer::GROUPS => ['foo'], AbstractNormalizer::ATTRIBUTES => ['relatedDummy']]); - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, $requestStack, $serializerContextBuilderProphecy->reveal(), true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); } @@ -850,14 +761,8 @@ public function testOnlyOneRelationNotInAttributes() $request = Request::create('/api/dummies', 'GET', []); - $requestStack = new RequestStack(); - $requestStack->push($request); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest($request, true)->shouldBeCalled()->willReturn([AbstractNormalizer::GROUPS => ['foo'], AbstractNormalizer::ATTRIBUTES => ['relatedDummy' => ['id', 'name']]]); - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, $requestStack, $serializerContextBuilderProphecy->reveal(), true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); } @@ -905,36 +810,17 @@ public function testApplyToCollectionNoPartial() } public function testApplyToCollectionWithANonReadableButFetchEagerProperty() - { - $this->doTestApplyToCollectionWithANonReadableButFetchEagerProperty(false); - } - - /** - * @group legacy - */ - public function testLegacyApplyToCollectionWithANonReadableButFetchEagerProperty() - { - $this->doTestApplyToCollectionWithANonReadableButFetchEagerProperty(true); - } - - private function doTestApplyToCollectionWithANonReadableButFetchEagerProperty(bool $legacy) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - if ($legacy) { - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new PropertyMetadata(); - $relationPropertyMetadata = $relationPropertyMetadata->withAttributes(['fetchEager' => true]); - } else { - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new ApiProperty(); - $relationPropertyMetadata = $relationPropertyMetadata->withFetchEager(true); - $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(false); - $relationPropertyMetadata = $relationPropertyMetadata->withReadable(false); - } + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $relationPropertyMetadata = new ApiProperty(); + $relationPropertyMetadata = $relationPropertyMetadata->withFetchEager(true); + $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(false); + $relationPropertyMetadata = $relationPropertyMetadata->withReadable(false); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(false); $relationPropertyMetadata = $relationPropertyMetadata->withReadable(false); @@ -1024,34 +910,15 @@ public function provideExistingJoinCases(): iterable } public function testApplyToCollectionWithAReadableButNotFetchEagerProperty() - { - $this->doTestApplyToCollectionWithAReadableButNotFetchEagerProperty(false); - } - - /** - * @group legacy - */ - public function testLegacyApplyToCollectionWithAReadableButNotFetchEagerProperty() - { - $this->doTestApplyToCollectionWithAReadableButNotFetchEagerProperty(true); - } - - private function doTestApplyToCollectionWithAReadableButNotFetchEagerProperty(bool $legacy) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - if ($legacy) { - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new PropertyMetadata(); - $relationPropertyMetadata = $relationPropertyMetadata->withAttributes(['fetchEager' => false]); - } else { - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new ApiProperty(); - $relationPropertyMetadata = $relationPropertyMetadata->withFetchEager(false); - } + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $relationPropertyMetadata = new ApiProperty(); + $relationPropertyMetadata = $relationPropertyMetadata->withFetchEager(false); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); $relationPropertyMetadata = $relationPropertyMetadata->withReadable(true); @@ -1082,4 +949,13 @@ private function doTestApplyToCollectionWithAReadableButNotFetchEagerProperty(bo $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); } + + private function getMetadataWithNormalizationContext(string $class, array $context = []): ResourceMetadataCollection + { + return new ResourceMetadataCollection($class, [ + new ApiResource(operations: [ + 'get' => new Get(name: 'get', normalizationContext: $context), + ]), + ]); + } } diff --git a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php index 9b6162ead11..3381dc26c72 100644 --- a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\ResourceClassResolver; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; @@ -26,6 +25,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeRelation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTravel; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Query\Expr; diff --git a/tests/Doctrine/Orm/Extension/FilterExtensionTest.php b/tests/Doctrine/Orm/Extension/FilterExtensionTest.php index 9ad978f6ecd..23d7f3ed36a 100644 --- a/tests/Doctrine/Orm/Extension/FilterExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/FilterExtensionTest.php @@ -17,12 +17,12 @@ use ApiPlatform\Core\Api\FilterCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\FilterExtension; use ApiPlatform\Doctrine\Orm\Filter\FilterInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\QueryBuilder; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Doctrine/Orm/Extension/OrderExtensionTest.php b/tests/Doctrine/Orm/Extension/OrderExtensionTest.php index db811c33a5d..083052490ca 100644 --- a/tests/Doctrine/Orm/Extension/OrderExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/OrderExtensionTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\OrderExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\EmbeddedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr\OrderBy; diff --git a/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php b/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php index 44982d9bcf8..e8505d3ac07 100644 --- a/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\AbstractPaginator; use ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\PaginationExtension; @@ -25,6 +24,7 @@ use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; diff --git a/tests/Doctrine/Orm/Filter/CommonFilterTest.php b/tests/Doctrine/Orm/Filter/CommonFilterTest.php index 2cb39aa7185..4547721dbfd 100644 --- a/tests/Doctrine/Orm/Filter/CommonFilterTest.php +++ b/tests/Doctrine/Orm/Filter/CommonFilterTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Filter; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Orm\Filter\DummyFilter; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Orm/Filter/SearchFilterTest.php b/tests/Doctrine/Orm/Filter/SearchFilterTest.php index 9872b3b1686..fb9939e9714 100644 --- a/tests/Doctrine/Orm/Filter/SearchFilterTest.php +++ b/tests/Doctrine/Orm/Filter/SearchFilterTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Exception\InvalidArgumentException; @@ -24,6 +23,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php b/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php index b3a474ffb19..5ac12c8d7e5 100644 --- a/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php +++ b/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Metadata\Property; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPropertyWithDefaultValue; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\Mapping\ClassMetadata; diff --git a/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php b/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php index 7bce670e5cc..cc44706dcfd 100644 --- a/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php +++ b/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Metadata\Resource; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Orm\Metadata\Resource\DoctrineOrmResourceCollectionMetadataFactory; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Orm/PaginatorTest.php b/tests/Doctrine/Orm/PaginatorTest.php index 09ae2ac5fd6..a18336bc92d 100644 --- a/tests/Doctrine/Orm/PaginatorTest.php +++ b/tests/Doctrine/Orm/PaginatorTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Orm; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Tests\Fixtures\Query; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Orm/State/CollectionProviderTest.php b/tests/Doctrine/Orm/State/CollectionProviderTest.php index 01e97627bfb..192d436abd3 100644 --- a/tests/Doctrine/Orm/State/CollectionProviderTest.php +++ b/tests/Doctrine/Orm/State/CollectionProviderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Orm\State; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\State\CollectionProvider; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\OperationResource; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Mapping\ClassMetadata; diff --git a/tests/Doctrine/Orm/State/ItemProviderTest.php b/tests/Doctrine/Orm/State/ItemProviderTest.php index a9e5b4e26ab..1081a492e08 100644 --- a/tests/Doctrine/Orm/State/ItemProviderTest.php +++ b/tests/Doctrine/Orm/State/ItemProviderTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Doctrine\Orm\State; use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; use ApiPlatform\Doctrine\Orm\State\ItemProvider; @@ -30,6 +29,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Company; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Employee; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\OperationResource; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\Types; diff --git a/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php b/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php index f3af0c0eddc..d983c0aaa4f 100644 --- a/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php +++ b/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Util; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\QueryBuilder; diff --git a/tests/Doctrine/Orm/Util/QueryCheckerTest.php b/tests/Doctrine/Orm/Util/QueryCheckerTest.php index cce39743b12..677e572e660 100644 --- a/tests/Doctrine/Orm/Util/QueryCheckerTest.php +++ b/tests/Doctrine/Orm/Util/QueryCheckerTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Util; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Util\QueryChecker; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\QueryBuilder; diff --git a/tests/Doctrine/Orm/Util/QueryJoinParserTest.php b/tests/Doctrine/Orm/Util/QueryJoinParserTest.php index f2449bee92e..7c945d35c92 100644 --- a/tests/Doctrine/Orm/Util/QueryJoinParserTest.php +++ b/tests/Doctrine/Orm/Util/QueryJoinParserTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Util; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Util\QueryJoinParser; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr\Join; diff --git a/tests/Documentation/Action/DocumentationActionTest.php b/tests/Documentation/Action/DocumentationActionTest.php index ce6aafefd6c..184c6a2fc2c 100644 --- a/tests/Documentation/Action/DocumentationActionTest.php +++ b/tests/Documentation/Action/DocumentationActionTest.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Tests\Documentation\Action; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Action\DocumentationAction; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; @@ -23,6 +21,7 @@ use ApiPlatform\OpenApi\Model\Info; use ApiPlatform\OpenApi\Model\Paths; use ApiPlatform\OpenApi\OpenApi; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; @@ -36,65 +35,6 @@ class DocumentationActionTest extends TestCase { use ProphecyTrait; - /** - * @group legacy - * @expectedDeprecation Not passing an instance of "ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface" as 7th parameter of the constructor of "ApiPlatform\Documentation\Action\DocumentationAction" is deprecated since API Platform 2.6 - */ - public function testDocumentationAction(): void - { - $requestProphecy = $this->prophesize(Request::class); - $requestProphecy->getRequestFormat()->willReturn('json'); - $attributesProphecy = $this->prophesize(ParameterBagInterface::class); - $queryProphecy = $this->prophesize(ParameterBag::class); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummies'])); - $requestProphecy->attributes = $attributesProphecy->reveal(); - $requestProphecy->query = $queryProphecy->reveal(); - $requestProphecy->getBaseUrl()->willReturn('/api')->shouldBeCalledTimes(1); - $queryProphecy->getBoolean('api_gateway')->willReturn(true)->shouldBeCalledTimes(1); - $queryProphecy->getInt('spec_version', 2)->willReturn(2)->shouldBeCalledTimes(1); - $attributesProphecy->all()->willReturn(['_api_normalization_context' => ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2]])->shouldBeCalledTimes(1); - $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); - $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2])->shouldBeCalledTimes(1); - - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0'); - $this->assertEquals(new Documentation(new ResourceNameCollection(['dummies']), 'My happy hippie api', 'lots of chocolate', '1.0.0'), $documentation($requestProphecy->reveal())); - } - - public function testLegacyDocumentationAction(): void - { - $requestProphecy = $this->prophesize(Request::class); - $requestProphecy->getRequestFormat()->willReturn('json'); - $attributesProphecy = $this->prophesize(ParameterBagInterface::class); - $queryProphecy = $this->prophesize(ParameterBag::class); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummies'])); - $requestProphecy->attributes = $attributesProphecy->reveal(); - $requestProphecy->query = $queryProphecy->reveal(); - $requestProphecy->getBaseUrl()->willReturn('/api')->shouldBeCalledTimes(1); - $queryProphecy->getBoolean('api_gateway')->willReturn(true)->shouldBeCalledTimes(1); - $queryProphecy->getInt('spec_version', 2)->willReturn(2)->shouldBeCalledTimes(1); - $attributesProphecy->all()->willReturn(['_api_normalization_context' => ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2]])->shouldBeCalledTimes(1); - $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); - $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2])->shouldBeCalledTimes(1); - $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); - $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->willReturn(['formats' => ['jsonld' => 'application/ld+json']])->shouldBeCalled(); - - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', $formatsProviderProphecy->reveal()); - $this->assertEquals(new Documentation(new ResourceNameCollection(['dummies']), 'My happy hippie api', 'lots of chocolate', '1.0.0', ['formats' => ['jsonld' => 'application/ld+json']]), $documentation($requestProphecy->reveal())); - } - - /** - * @group legacy - * @expectedDeprecation Passing an array or an instance of "ApiPlatform\Core\Api\FormatsProviderInterface" as 5th parameter of the constructor of "ApiPlatform\Documentation\Action\DocumentationAction" is deprecated since API Platform 2.5 - */ - public function testDocumentationActionFormatDeprecation() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummies'])); - new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), '', '', '', ['formats' => ['jsonld' => 'application/ld+json']]); - } - public function testDocumentationActionV2(): void { $openApiFactoryProphecy = $this->prophesize(OpenApiFactoryInterface::class); @@ -113,7 +53,7 @@ public function testDocumentationActionV2(): void $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2])->shouldBeCalledTimes(1); - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', null, [2, 3], $openApiFactoryProphecy->reveal()); + $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', [2, 3], $openApiFactoryProphecy->reveal()); $this->assertEquals(new Documentation(new ResourceNameCollection(['dummies']), 'My happy hippie api', 'lots of chocolate', '1.0.0'), $documentation($requestProphecy->reveal())); } @@ -137,7 +77,7 @@ public function testDocumentationActionV3(): void $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 3])->shouldBeCalledTimes(1); - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', null, [2, 3], $openApiFactoryProphecy->reveal()); + $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', [2, 3], $openApiFactoryProphecy->reveal()); $this->assertInstanceOf(OpenApi::class, $documentation($requestProphecy->reveal())); } } diff --git a/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php b/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php index ecc963ee5f5..8d65f918be5 100644 --- a/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php +++ b/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\SortFilterInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Elasticsearch/Extension/SortExtensionTest.php b/tests/Elasticsearch/Extension/SortExtensionTest.php index ede6bb3b793..84ac48264d2 100644 --- a/tests/Elasticsearch/Extension/SortExtensionTest.php +++ b/tests/Elasticsearch/Extension/SortExtensionTest.php @@ -17,12 +17,12 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Extension\SortExtension; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; diff --git a/tests/Elasticsearch/Extension/SortFilterExtensionTest.php b/tests/Elasticsearch/Extension/SortFilterExtensionTest.php index 226ebd6d5e1..96c71761466 100644 --- a/tests/Elasticsearch/Extension/SortFilterExtensionTest.php +++ b/tests/Elasticsearch/Extension/SortFilterExtensionTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Extension\SortFilterExtension; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\SortFilterInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Elasticsearch/Filter/MatchFilterTest.php b/tests/Elasticsearch/Filter/MatchFilterTest.php index f0578f82c2d..6e3bf334b14 100644 --- a/tests/Elasticsearch/Filter/MatchFilterTest.php +++ b/tests/Elasticsearch/Filter/MatchFilterTest.php @@ -18,13 +18,13 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\MatchFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; diff --git a/tests/Elasticsearch/Filter/OrderFilterTest.php b/tests/Elasticsearch/Filter/OrderFilterTest.php index 250952257e8..d63b92f5b62 100644 --- a/tests/Elasticsearch/Filter/OrderFilterTest.php +++ b/tests/Elasticsearch/Filter/OrderFilterTest.php @@ -16,12 +16,12 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Filter\OrderFilter; use ApiPlatform\Elasticsearch\Filter\SortFilterInterface; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Elasticsearch/Filter/TermFilterTest.php b/tests/Elasticsearch/Filter/TermFilterTest.php index e2cca9eb6f9..b46194e119f 100644 --- a/tests/Elasticsearch/Filter/TermFilterTest.php +++ b/tests/Elasticsearch/Filter/TermFilterTest.php @@ -18,13 +18,13 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\TermFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php index 6f7a6392a7e..aa9be8d45af 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php index 6501b6a261e..0d3f2ce7d3a 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Elasticsearch\Metadata\Document\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\Cache\CacheItemInterface; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php index 87cda14a0e7..ed64686c209 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use Elasticsearch\Client; use Elasticsearch\Common\Exceptions\Missing404Exception; use Elasticsearch\Namespaces\CatNamespace; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php index 33ed62e56e3..6b67b56549a 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Elasticsearch\Metadata\Document\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class ConfiguredDocumentMetadataFactoryTest extends TestCase diff --git a/tests/Elasticsearch/PaginatorTest.php b/tests/Elasticsearch/PaginatorTest.php index 2b6090cb771..0fa19ade210 100644 --- a/tests/Elasticsearch/PaginatorTest.php +++ b/tests/Elasticsearch/PaginatorTest.php @@ -14,10 +14,10 @@ namespace ApiPlatform\Core\Tests\Bridge\Elasticsearch\DataProvider; use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Paginator; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; diff --git a/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php b/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php index 109a1f4a3c4..375ec6bfaa0 100644 --- a/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php +++ b/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php @@ -14,9 +14,9 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer; use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; diff --git a/tests/Elasticsearch/Serializer/ItemNormalizerTest.php b/tests/Elasticsearch/Serializer/ItemNormalizerTest.php index 481f8ca6652..3c682ac785f 100644 --- a/tests/Elasticsearch/Serializer/ItemNormalizerTest.php +++ b/tests/Elasticsearch/Serializer/ItemNormalizerTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; use ApiPlatform\Elasticsearch\Serializer\ItemNormalizer; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; diff --git a/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php b/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php index 97787c9a68b..42a8a12abee 100644 --- a/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php +++ b/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer\NameConverter; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; diff --git a/tests/Elasticsearch/State/CollectionProviderTest.php b/tests/Elasticsearch/State/CollectionProviderTest.php index c38c5991e81..e8e1f07b5a3 100644 --- a/tests/Elasticsearch/State/CollectionProviderTest.php +++ b/tests/Elasticsearch/State/CollectionProviderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Core\Tests\Elasticsearch\State; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; @@ -24,6 +23,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use Elasticsearch\Client; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Elasticsearch/State/ItemProviderTest.php b/tests/Elasticsearch/State/ItemProviderTest.php index fd0930289c7..6d98fb67f80 100644 --- a/tests/Elasticsearch/State/ItemProviderTest.php +++ b/tests/Elasticsearch/State/ItemProviderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Elasticsearch\State; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; @@ -21,6 +20,7 @@ use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use Elasticsearch\Client; use Elasticsearch\Common\Exceptions\Missing404Exception; use PHPUnit\Framework\TestCase; diff --git a/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php b/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php index 9a601359dcf..fa1b82ea24f 100644 --- a/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php +++ b/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php @@ -14,12 +14,12 @@ namespace ApiPlatform\Tests\Elasticsearch\Util; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Fixtures/DummyEntityFilterAnnotated.php b/tests/Fixtures/DummyEntityFilterAnnotated.php index 3801ff315e1..d0c7d9c7710 100644 --- a/tests/Fixtures/DummyEntityFilterAnnotated.php +++ b/tests/Fixtures/DummyEntityFilterAnnotated.php @@ -16,9 +16,7 @@ use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; -/** - * @ApiFilter(OrderFilter::class, arguments={"orderParameterName"="positionOrder"}, properties={"position"}) - */ +#[ApiFilter(OrderFilter::class, arguments: ['orderParameterName' => 'positionOrder'], properties: ['position'])] class DummyEntityFilterAnnotated { public $position; diff --git a/tests/Fixtures/Elasticsearch/Model/Tweet.php b/tests/Fixtures/Elasticsearch/Model/Tweet.php index d75f7d37a7e..af691d3473d 100644 --- a/tests/Fixtures/Elasticsearch/Model/Tweet.php +++ b/tests/Fixtures/Elasticsearch/Model/Tweet.php @@ -13,44 +13,29 @@ namespace ApiPlatform\Tests\Fixtures\Elasticsearch\Model; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Elasticsearch\Filter\MatchFilter; use ApiPlatform\Elasticsearch\Filter\OrderFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * normalizationContext={ - * "groups"={"tweet:read"} - * } - * ) - * @ApiFilter(OrderFilter::class, properties={"id", "author.id"}) - * @ApiFilter(MatchFilter::class, properties={"message", "author.firstName"}) - */ +#[ApiResource(normalizationContext: ['groups' => ['tweet:read']])] +#[ApiFilter(OrderFilter::class, properties: ['id', 'author.id'])] +#[ApiFilter(MatchFilter::class, properties: ['message', 'author.firstName'])] class Tweet { - /** - * @ApiProperty(identifier=true) - * - * @Groups({"tweet:read", "user:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] + #[ApiProperty(identifier: true)] private $id; - /** - * @Groups({"tweet:read"}) - */ + #[Groups(['tweet:read'])] private $author; - /** - * @Groups({"tweet:read", "user:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $date; - /** - * @Groups({"tweet:read", "user:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $message; public function getId(): ?string diff --git a/tests/Fixtures/Elasticsearch/Model/User.php b/tests/Fixtures/Elasticsearch/Model/User.php index 8f0dc9c4d0a..309ffa8f4a4 100644 --- a/tests/Fixtures/Elasticsearch/Model/User.php +++ b/tests/Fixtures/Elasticsearch/Model/User.php @@ -13,57 +13,36 @@ namespace ApiPlatform\Tests\Fixtures\Elasticsearch\Model; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Elasticsearch\Filter\TermFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * normalizationContext={ - * "groups"={"user:read"} - * } - * ) - * @ApiFilter(TermFilter::class, properties={"id", "gender", "age", "firstName", "tweets.id", "tweets.date"}) - */ +#[ApiResource(normalizationContext: ['groups' => ['user:read']])] +#[ApiFilter(TermFilter::class, properties: ['id', 'gender', 'age', 'firstName', 'tweets.id', 'tweets.date'])] class User { - /** - * @ApiProperty(identifier=true) - * - * @Groups({"user:read", "tweet:read"}) - */ + #[ApiProperty(identifier: true)] + #[Groups(['tweet:read', 'user:read'])] private $id; - /** - * @Groups({"user:read", "tweet:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $gender; - /** - * @Groups({"user:read", "tweet:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $age; - /** - * @Groups({"user:read", "tweet:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $firstName; - /** - * @Groups({"user:read", "tweet:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $lastName; - /** - * @Groups({"user:read"}) - */ + #[Groups(['user:read'])] private $registeredAt; - /** - * @Groups({"user:read"}) - */ + #[Groups(['user:read'])] private $tweets = []; public function getId(): ?string diff --git a/tests/Fixtures/TestBundle/Action/ConfigCustom.php b/tests/Fixtures/TestBundle/Action/ConfigCustom.php index 580fe839e07..d0666149a82 100644 --- a/tests/Fixtures/TestBundle/Action/ConfigCustom.php +++ b/tests/Fixtures/TestBundle/Action/ConfigCustom.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Action; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; +use ApiPlatform\Metadata\Get; +use ApiPlatform\State\ProviderInterface; use ApiPlatform\Util\RequestAttributesExtractor; use Symfony\Component\HttpFoundation\Request; @@ -24,17 +25,14 @@ */ class ConfigCustom { - private $dataProvider; - - public function __construct(ItemDataProviderInterface $dataProvider) + public function __construct(private readonly ProviderInterface $provider) { - $this->dataProvider = $dataProvider; } public function __invoke(Request $request, $id) { $attributes = RequestAttributesExtractor::extractAttributes($request); - return $this->dataProvider->getItem($attributes['resource_class'], $id); + return $this->provider->provide(new Get(class: $attributes['resource_class']), ['id' => $id]); } } diff --git a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php index 86dab54944c..4091bb30db2 100644 --- a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php +++ b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php @@ -23,14 +23,7 @@ */ class CustomActionController extends AbstractController { - /** - * @Route( - * methods={"GET"}, - * name="custom_normalization", - * path="/custom/{id}/normalization", - * defaults={"_api_resource_class"=CustomActionDummy::class, "_api_item_operation_name"="custom_normalization"} - * ) - */ + #[Route(methods: ['GET'], name: 'custom_normalization', path: '/custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] public function customNormalizationAction(CustomActionDummy $data) { $data->setFoo('foo'); @@ -38,38 +31,19 @@ public function customNormalizationAction(CustomActionDummy $data) return $this->json($data); } - /** - * @Route( - * methods={"POST"}, - * name="custom_denormalization", - * path="/custom/denormalization", - * defaults={ - * "_api_resource_class"=CustomActionDummy::class, - * "_api_collection_operation_name"="custom_denormalization", - * "_api_receive"=false - * } - * ) - */ + #[Route(methods: ['POST'], name: 'custom_denormalization', path: '/custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function customDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { throw new \RuntimeException('The "data" attribute must not be set.'); } - $object = new CustomActionDummy(); $object->setFoo('custom!'); return $object; } - /** - * @Route( - * methods={"GET"}, - * name="short_custom_normalization", - * path="/short_custom/{id}/normalization", - * defaults={"_api_resource_class"=CustomActionDummy::class, "_api_item_operation_name"="custom_normalization"} - * ) - */ + #[Route(methods: ['GET'], name: 'short_custom_normalization', path: '/short_custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] public function shortCustomNormalizationAction(CustomActionDummy $data) { $data->setFoo('short'); @@ -77,24 +51,12 @@ public function shortCustomNormalizationAction(CustomActionDummy $data) return $this->json($data); } - /** - * @Route( - * methods={"POST"}, - * name="short_custom_denormalization", - * path="/short_custom/denormalization", - * defaults={ - * "_api_resource_class"=CustomActionDummy::class, - * "_api_collection_operation_name"="custom_denormalization", - * "_api_receive"=false - * } - * ) - */ + #[Route(methods: ['POST'], name: 'short_custom_denormalization', path: '/short_custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function shortCustomDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { throw new \RuntimeException('The "data" attribute must not be set.'); } - $object = new CustomActionDummy(); $object->setFoo('short declaration'); diff --git a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/DummyValidationController.php b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/DummyValidationController.php index c5023fd5853..7107416b3d5 100644 --- a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/DummyValidationController.php +++ b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/DummyValidationController.php @@ -19,30 +19,18 @@ class DummyValidationController { /** - * @Route( - * methods={"POST"}, - * name="post_validation_groups", - * path="/dummy_validation/validation_groups", - * defaults={"_api_resource_class"=DummyValidation::class, "_api_collection_operation_name"="post_validation_groups"} - * ) - * * @param mixed $data */ + #[Route(methods: ['POST'], name: 'post_validation_groups', path: '/dummy_validation/validation_groups', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_groups'])] public function postValidationGroups($data) { return $data; } /** - * @Route( - * methods={"POST"}, - * name="post_validation_sequence", - * path="/dummy_validation/validation_sequence", - * defaults={"_api_resource_class"=DummyValidation::class, "_api_collection_operation_name"="post_validation_sequence"} - * ) - * * @param mixed $data */ + #[Route(methods: ['POST'], name: 'post_validation_sequence', path: '/dummy_validation/validation_sequence', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_sequence'])] public function postValidationSequence($data) { return $data; diff --git a/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php b/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php index f638e3272fb..c9bea651d10 100644 --- a/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php +++ b/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php @@ -23,14 +23,7 @@ */ class CustomActionController extends AbstractController { - /** - * @Route( - * methods={"GET"}, - * name="custom_normalization", - * path="/custom/{id}/normalization", - * defaults={"_api_resource_class"=CustomActionDummy::class, "_api_item_operation_name"="custom_normalization"} - * ) - */ + #[Route(methods: ['GET'], name: 'custom_normalization', path: '/custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] public function customNormalizationAction(CustomActionDummy $data) { $data->setFoo('foo'); @@ -38,38 +31,19 @@ public function customNormalizationAction(CustomActionDummy $data) return $this->json($data); } - /** - * @Route( - * methods={"POST"}, - * name="custom_denormalization", - * path="/custom/denormalization", - * defaults={ - * "_api_resource_class"=CustomActionDummy::class, - * "_api_collection_operation_name"="custom_denormalization", - * "_api_receive"=false - * } - * ) - */ + #[Route(methods: ['POST'], name: 'custom_denormalization', path: '/custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function customDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { throw new \RuntimeException('The "data" attribute must not be set.'); } - $object = new CustomActionDummy(); $object->setFoo('custom!'); return $object; } - /** - * @Route( - * methods={"GET"}, - * name="short_custom_normalization", - * path="/short_custom/{id}/normalization", - * defaults={"_api_resource_class"=CustomActionDummy::class, "_api_item_operation_name"="custom_normalization"} - * ) - */ + #[Route(methods: ['GET'], name: 'short_custom_normalization', path: '/short_custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] public function shortCustomNormalizationAction(CustomActionDummy $data) { $data->setFoo('short'); @@ -77,24 +51,12 @@ public function shortCustomNormalizationAction(CustomActionDummy $data) return $this->json($data); } - /** - * @Route( - * methods={"POST"}, - * name="short_custom_denormalization", - * path="/short_custom/denormalization", - * defaults={ - * "_api_resource_class"=CustomActionDummy::class, - * "_api_collection_operation_name"="custom_denormalization", - * "_api_receive"=false - * } - * ) - */ + #[Route(methods: ['POST'], name: 'short_custom_denormalization', path: '/short_custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function shortCustomDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { throw new \RuntimeException('The "data" attribute must not be set.'); } - $object = new CustomActionDummy(); $object->setFoo('short declaration'); diff --git a/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php b/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php index 7c37df63dad..2b6d837d995 100644 --- a/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php +++ b/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php @@ -19,30 +19,18 @@ class DummyValidationController { /** - * @Route( - * methods={"POST"}, - * name="post_validation_groups", - * path="/dummy_validation/validation_groups", - * defaults={"_api_resource_class"=DummyValidation::class, "_api_collection_operation_name"="post_validation_groups"} - * ) - * * @param mixed $data */ + #[Route(methods: ['POST'], name: 'post_validation_groups', path: '/dummy_validation/validation_groups', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_groups'])] public function postValidationGroups($data) { return $data; } /** - * @Route( - * methods={"POST"}, - * name="post_validation_sequence", - * path="/dummy_validation/validation_sequence", - * defaults={"_api_resource_class"=DummyValidation::class, "_api_collection_operation_name"="post_validation_sequence"} - * ) - * * @param mixed $data */ + #[Route(methods: ['POST'], name: 'post_validation_sequence', path: '/dummy_validation/validation_sequence', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_sequence'])] public function postValidationSequence($data) { return $data; diff --git a/tests/Fixtures/TestBundle/DataPersister/DummyDtoNoOutputDataPersister.php b/tests/Fixtures/TestBundle/DataPersister/DummyDtoNoOutputDataPersister.php deleted file mode 100644 index 8b85c25e6b9..00000000000 --- a/tests/Fixtures/TestBundle/DataPersister/DummyDtoNoOutputDataPersister.php +++ /dev/null @@ -1,69 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataPersister; - -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoNoOutput as DummyDtoNoOutputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\InputDto as InputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoNoOutput; -use Doctrine\Persistence\ManagerRegistry; - -class DummyDtoNoOutputDataPersister implements DataPersisterInterface -{ - private $registry; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - /** - * {@inheritdoc} - */ - public function supports($data): bool - { - return $data instanceof InputDto || $data instanceof InputDtoDocument; - } - - /** - * {@inheritdoc} - */ - public function persist($data) - { - $isOrm = true; - $em = $this->registry->getManagerForClass(DummyDtoNoOutput::class); - if (null === $em) { - $em = $this->registry->getManagerForClass(DummyDtoNoOutputDocument::class); - $isOrm = false; - } - - $output = $isOrm ? new DummyDtoNoOutput() : new DummyDtoNoOutputDocument(); - $output->lorem = $data->foo; - $output->ipsum = (string) $data->bar; - - $em->persist($output); - $em->flush(); - - return $output; - } - - /** - * {@inheritdoc} - */ - public function remove($data) - { - return null; - } -} diff --git a/tests/Fixtures/TestBundle/DataPersister/UserResetPasswordDataPersister.php b/tests/Fixtures/TestBundle/DataPersister/UserResetPasswordDataPersister.php deleted file mode 100644 index 1239ae9a0fb..00000000000 --- a/tests/Fixtures/TestBundle/DataPersister/UserResetPasswordDataPersister.php +++ /dev/null @@ -1,40 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataPersister; - -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\UserResetPasswordDto; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -final class UserResetPasswordDataPersister implements DataPersisterInterface -{ - public function persist($data) - { - if ('user@example.com' === $data->email) { - return $data; - } - - throw new NotFoundHttpException(); - } - - public function remove($data) - { - throw new \LogicException(sprintf('Unexpected "%s()" call.', __METHOD__)); - } - - public function supports($data): bool - { - return $data instanceof UserResetPasswordDto; - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/ContainNonResourceItemDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/ContainNonResourceItemDataProvider.php deleted file mode 100644 index b09139bc5b6..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/ContainNonResourceItemDataProvider.php +++ /dev/null @@ -1,51 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\NotAResource; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\ContainNonResource as ContainNonResourceDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ContainNonResource; - -/** - * @author Kévin Dunglas - */ -class ContainNonResourceItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return \in_array($resourceClass, [ContainNonResource::class, ContainNonResourceDocument::class], true); - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - if (!\is_scalar($id)) { - throw new \InvalidArgumentException('The id must be a scalar.'); - } - - // Retrieve the blog post item from somewhere - $cnr = new $resourceClass(); - $cnr->id = $id; - $cnr->notAResource = new NotAResource('f1', 'b1'); - $cnr->nested = new $resourceClass(); - $cnr->nested->id = "$id-nested"; - $cnr->nested->notAResource = new NotAResource('f2', 'b2'); - - return $cnr; - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/DummyDtoNoInputCollectionDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/DummyDtoNoInputCollectionDataProvider.php deleted file mode 100644 index 8b8ecb182ab..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/DummyDtoNoInputCollectionDataProvider.php +++ /dev/null @@ -1,62 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\State\Pagination\ArrayPaginator; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoNoInput as DummyDtoNoInputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto as OutputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoNoInput; -use Doctrine\Persistence\ManagerRegistry; - -/** - * @author Vincent Chalamon - */ -final class DummyDtoNoInputCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - private $registry; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return \in_array($resourceClass, [DummyDtoNoInput::class, DummyDtoNoInputDocument::class], true); - } - - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []) - { - /** @var DummyDtoNoInput[]|DummyDtoNoInputDocument[] $dummyDtos */ - $dummyDtos = $this->registry->getManagerForClass($resourceClass)->getRepository($resourceClass)->findAll(); - $objects = []; - foreach ($dummyDtos as $dummyDto) { - $object = DummyDtoNoInput::class === $resourceClass ? new OutputDto() : new OutputDtoDocument(); - $object->bat = $dummyDto->lorem; - $object->baz = $dummyDto->ipsum; - $objects[] = $object; - } - - return new ArrayPaginator($objects, 0, \count($objects)); - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/GeneratorDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/GeneratorDataProvider.php deleted file mode 100644 index 96658def507..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/GeneratorDataProvider.php +++ /dev/null @@ -1,33 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SecuredDummy; - -class GeneratorDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface -{ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return SecuredDummy::class === $resourceClass && 'get_from_data_provider_generator' === $operationName; - } - - public function getCollection(string $resourceClass, string $operationName = null) - { - yield from [new class() { - }, new class() { - }]; - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/ProductItemDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/ProductItemDataProvider.php deleted file mode 100644 index 420d8148834..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/ProductItemDataProvider.php +++ /dev/null @@ -1,51 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Product as ProductDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Product; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ProductInterface; -use Doctrine\Persistence\ManagerRegistry; - -class ProductItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - private $managerRegistry; - private $orm; - - public function __construct(ManagerRegistry $managerRegistry, bool $orm = true) - { - $this->managerRegistry = $managerRegistry; - $this->orm = $orm; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return is_a($resourceClass, ProductInterface::class, true); - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return $this->managerRegistry->getRepository($this->orm ? Product::class : ProductDocument::class)->findOneBy([ - 'code' => $id, - ]); - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/ResourceInterfaceImplementationDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/ResourceInterfaceImplementationDataProvider.php deleted file mode 100644 index 48f35338a5d..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/ResourceInterfaceImplementationDataProvider.php +++ /dev/null @@ -1,43 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceInterfaceImplementation; - -class ResourceInterfaceImplementationDataProvider implements ItemDataProviderInterface, CollectionDataProviderInterface, RestrictedDataProviderInterface -{ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return ResourceInterface::class === $resourceClass; - } - - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - if ('some-id' === $id) { - return (new ResourceInterfaceImplementation())->setFoo('single item'); - } - - return null; - } - - public function getCollection(string $resourceClass, string $operationName = null): iterable - { - yield (new ResourceInterfaceImplementation())->setFoo('item1'); - yield (new ResourceInterfaceImplementation())->setFoo('item2'); - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/SerializableItemDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/SerializableItemDataProvider.php deleted file mode 100644 index 05e53b6a278..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/SerializableItemDataProvider.php +++ /dev/null @@ -1,51 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderInterface; -use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\SerializableResource; - -/** - * @author Vincent Chalamon - */ -class SerializableItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface, SerializerAwareDataProviderInterface -{ - use SerializerAwareDataProviderTrait; - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return $this->getSerializer()->deserialize(<<<'JSON' -{ - "id": 1, - "foo": "Lorem", - "bar": "Ipsum" -} -JSON - , $resourceClass, 'json'); - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return SerializableResource::class === $resourceClass; - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/TaxonItemDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/TaxonItemDataProvider.php deleted file mode 100644 index ee04570084f..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/TaxonItemDataProvider.php +++ /dev/null @@ -1,51 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Taxon as TaxonDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Taxon; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; -use Doctrine\Persistence\ManagerRegistry; - -class TaxonItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - private $managerRegistry; - private $orm; - - public function __construct(ManagerRegistry $managerRegistry, bool $orm = true) - { - $this->managerRegistry = $managerRegistry; - $this->orm = $orm; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return is_a($resourceClass, TaxonInterface::class, true); - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return $this->managerRegistry->getRepository($this->orm ? Taxon::class : TaxonDocument::class)->findOneBy([ - 'code' => $id, - ]); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/CustomInputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/CustomInputDtoDataTransformer.php deleted file mode 100644 index 8374881e57b..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/CustomInputDtoDataTransformer.php +++ /dev/null @@ -1,52 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Serializer\AbstractItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoCustom as DummyDtoCustomDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomInputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoCustom; - -final class CustomInputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if (!$object instanceof CustomInputDto) { - throw new \InvalidArgumentException(); - } - - /** - * @var \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoCustom - */ - $resourceObject = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? new $context['resource_class'](); - $resourceObject->lorem = $object->foo; - $resourceObject->ipsum = (string) $object->bar; - - return $resourceObject; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - return (DummyDtoCustom::class === $to || DummyDtoCustomDocument::class === $to) && CustomInputDto::class === ($context['input']['class'] ?? null); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/CustomOutputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/CustomOutputDtoDataTransformer.php deleted file mode 100644 index 0e3586e10bf..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/CustomOutputDtoDataTransformer.php +++ /dev/null @@ -1,64 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoCustom as DummyDtoCustomDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomOutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoCustom; - -final class CustomOutputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if ($object instanceof \Traversable) { - foreach ($object as &$value) { - $value = $this->doTransformation($value); - } - - return $object; - } - - return $this->doTransformation($object); - } - - private function doTransformation($object): CustomOutputDto - { - $output = new CustomOutputDto(); - $output->foo = $object->lorem; - $output->bar = (int) $object->ipsum; - - return $output; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - if ($object instanceof \IteratorAggregate) { - $iterator = $object->getIterator(); - if ($iterator instanceof \Iterator) { - $object = $iterator->current(); - } - } - - return ($object instanceof DummyDtoCustom || $object instanceof DummyDtoCustomDocument) && CustomOutputDto::class === $to; - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/DummyDtoNoInputToOutputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/DummyDtoNoInputToOutputDtoDataTransformer.php deleted file mode 100644 index e9eb4cb7d2e..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/DummyDtoNoInputToOutputDtoDataTransformer.php +++ /dev/null @@ -1,50 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoNoInput as DummyDtoNoInputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto as OutputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoNoInput; - -final class DummyDtoNoInputToOutputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if (!$object instanceof DummyDtoNoInput && !$object instanceof DummyDtoNoInputDocument) { - throw new \InvalidArgumentException(); - } - - $output = $object instanceof DummyDtoNoInput ? new OutputDto() : new OutputDtoDocument(); - $output->id = $object->getId(); - $output->bat = (string) $object->lorem; - $output->baz = (float) $object->ipsum; - - return $output; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return ($data instanceof DummyDtoNoInput || $data instanceof DummyDtoNoInputDocument) && \in_array($to, [OutputDto::class, OutputDtoDocument::class], true); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/InitializeInputDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/InitializeInputDataTransformer.php deleted file mode 100644 index 122c13cd671..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/InitializeInputDataTransformer.php +++ /dev/null @@ -1,64 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; -use ApiPlatform\Serializer\AbstractItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\InitializeInput as InitializeInputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InitializeInputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\InitializeInput; - -final class InitializeInputDataTransformer implements DataTransformerInitializerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - /** @var InitializeInputDto */ - $data = $object; - - /** @var InitializeInput|InitializeInputDocument */ - $resourceObject = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? new $context['resource_class'](); - $resourceObject->name = $data->name; - - return $resourceObject; - } - - /** - * {@inheritdoc} - */ - public function initialize(string $inputClass, array $context = []) - { - $currentResource = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? null; - if (!$currentResource) { - return new InitializeInputDto(); - } - - $dto = new InitializeInputDto(); - $dto->manager = $currentResource->manager; - - return $dto; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return (InitializeInput::class === $to || InitializeInputDocument::class === $to) && InitializeInputDto::class === ($context['input']['class'] ?? null); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/InputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/InputDtoDataTransformer.php deleted file mode 100644 index 41f55532fb5..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/InputDtoDataTransformer.php +++ /dev/null @@ -1,56 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Serializer\AbstractItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoInputOutput as DummyDtoInputOutputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\InputDto as InputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoInputOutput; - -final class InputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - /** @var InputDtoDocument|InputDto */ - $data = $object; - - /** @var DummyDtoInputOutputDocument|DummyDtoInputOutput */ - $resourceObject = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? new $context['resource_class'](); - $resourceObject->str = $data->foo; - $resourceObject->num = $data->bar; - // @phpstan-ignore-next-line - $resourceObject->relatedDummies = $data->relatedDummies; - - return $resourceObject; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - if ($object instanceof DummyDtoInputOutput || $object instanceof DummyDtoInputOutputDocument) { - return false; - } - - return \in_array($to, [DummyDtoInputOutput::class, DummyDtoInputOutputDocument::class], true) && \in_array($context['input']['class'], [InputDto::class, InputDtoDocument::class], true); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/OutputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/OutputDtoDataTransformer.php deleted file mode 100644 index cfdec547e6a..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/OutputDtoDataTransformer.php +++ /dev/null @@ -1,53 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\State\Pagination\ArrayPaginator; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoInputOutput as DummyDtoInputOutputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto as OutputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoInputOutput; - -final class OutputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if (!$object instanceof DummyDtoInputOutput && !$object instanceof DummyDtoInputOutputDocument) { - throw new \InvalidArgumentException(); - } - - $output = $object instanceof DummyDtoInputOutput ? new OutputDto() : new OutputDtoDocument(); - $output->id = $object->id; - $output->bat = (string) $object->str; - $output->baz = (float) $object->num; - // @phpstan-ignore-next-line - $output->relatedDummies = new ArrayPaginator($object->relatedDummies->toArray(), 0, \count($object->relatedDummies->toArray())); - - return $output; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return ($data instanceof DummyDtoInputOutput || $data instanceof DummyDtoInputOutputDocument) && \in_array($to, [OutputDto::class, OutputDtoDocument::class], true); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/OutputDtoSameClassTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/OutputDtoSameClassTransformer.php deleted file mode 100644 index f8a776016c1..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/OutputDtoSameClassTransformer.php +++ /dev/null @@ -1,56 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoOutputFallbackToSameClass as DummyDtoOutputFallbackToSameClassDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoOutputSameClass as DummyDtoOutputSameClassDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDtoDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoOutputFallbackToSameClass; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoOutputSameClass; - -/** - * @author Daniel West - */ -final class OutputDtoSameClassTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if ( - !$object instanceof DummyDtoOutputFallbackToSameClass && - !$object instanceof DummyDtoOutputFallbackToSameClassDocument && - !$object instanceof DummyDtoOutputSameClass && - !$object instanceof DummyDtoOutputSameClassDocument - ) { - throw new \InvalidArgumentException(); - } - $object->ipsum = 'modified'; - - return $object; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return (($data instanceof DummyDtoOutputFallbackToSameClass || $data instanceof DummyDtoOutputFallbackToSameClassDocument) && OutputDtoDummy::class === $to) || - (($data instanceof DummyDtoOutputSameClass || $data instanceof DummyDtoOutputSameClassDocument) && (DummyDtoOutputSameClass::class === $to || DummyDtoOutputSameClassDocument::class === $to)); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/RPCOutputDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/RPCOutputDataTransformer.php deleted file mode 100644 index 24d6bc442c0..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/RPCOutputDataTransformer.php +++ /dev/null @@ -1,40 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\RPC as RPCDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RPCOutput; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RPC; - -final class RPCOutputDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - return new RPCOutput(); - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - return ($object instanceof RPC || $object instanceof RPCDocument) && RPCOutput::class === $to; - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordInputDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordInputDataTransformer.php deleted file mode 100644 index 30113044dd5..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordInputDataTransformer.php +++ /dev/null @@ -1,46 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Serializer\AbstractItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\User as UserDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordInput; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\User; - -final class RecoverPasswordInputDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($data, string $to, array $context = []) - { - // Because we're in a PUT operation, we will use the retrieved object... - $resourceObject = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? new $context['resource_class'](); - // ...where we remove the credentials - $resourceObject->eraseCredentials(); - - return $resourceObject; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return (User::class === $to || UserDocument::class === $to) && RecoverPasswordInput::class === ($context['input']['class'] ?? null); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordOutputDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordOutputDataTransformer.php deleted file mode 100644 index 5a19c76b525..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordOutputDataTransformer.php +++ /dev/null @@ -1,44 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordOutput; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\User; - -final class RecoverPasswordOutputDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - $output = new RecoverPasswordOutput(); - $output->dummy = new Dummy(); - $output->dummy->setId(1); - - return $output; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - return $object instanceof User && RecoverPasswordOutput::class === $to; - } -} diff --git a/tests/Fixtures/TestBundle/Doctrine/Generator/Uuid.php b/tests/Fixtures/TestBundle/Doctrine/Generator/Uuid.php index 249af556bd0..d58d7675b6c 100644 --- a/tests/Fixtures/TestBundle/Doctrine/Generator/Uuid.php +++ b/tests/Fixtures/TestBundle/Doctrine/Generator/Uuid.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator; -class Uuid implements \JsonSerializable +class Uuid implements \JsonSerializable, \Stringable { private $id; @@ -22,7 +22,7 @@ public function __construct() $this->id = 'foo'; } - public function __toString() + public function __toString(): string { return $this->id; } diff --git a/tests/Fixtures/TestBundle/Doctrine/Orm/EntityManager.php b/tests/Fixtures/TestBundle/Doctrine/Orm/EntityManager.php index aca2035901a..1e66df65da3 100644 --- a/tests/Fixtures/TestBundle/Doctrine/Orm/EntityManager.php +++ b/tests/Fixtures/TestBundle/Doctrine/Orm/EntityManager.php @@ -24,13 +24,9 @@ final class EntityManager extends EntityManagerDecorator { public static $dql; - private $repositoryFactory; - - public function __construct(EntityManagerInterface $wrapped, RepositoryFactory $repositoryFactory) + public function __construct(EntityManagerInterface $wrapped, private readonly RepositoryFactory $repositoryFactory) { parent::__construct($wrapped); - - $this->repositoryFactory = $repositoryFactory; } public function getRepository($className): ObjectRepository diff --git a/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php b/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php index 47af2b329fa..5e9f22fdecf 100644 --- a/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php @@ -14,23 +14,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::ABS_URL) - * @ODM\Document - */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] +#[ApiResource(uriTemplate: '/absolute_url_relation_dummies/{id}/absolute_url_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\AbsoluteUrlRelationDummy::class, identifiers: ['id'], toProperty: 'absoluteUrlRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::ABS_URL, operations: [new GetCollection()])] +#[ODM\Document] class AbsoluteUrlDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\ReferenceOne(targetDocument=AbsoluteUrlRelationDummy::class, inversedBy="absoluteUrlDummies", storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: AbsoluteUrlRelationDummy::class, inversedBy: 'absoluteUrlDummies', storeAs: 'id')] public $absoluteUrlRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php b/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php index 1e80a1461ea..8c1684f8eee 100644 --- a/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php @@ -14,26 +14,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::ABS_URL) - * @ODM\Document - */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] +#[ODM\Document] class AbsoluteUrlRelationDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\ReferenceMany(targetDocument=AbsoluteUrlDummy::class, mappedBy="absoluteUrlRelationDummy") - * @ApiSubresource - */ + #[ODM\ReferenceMany(targetDocument: AbsoluteUrlDummy::class, mappedBy: 'absoluteUrlRelationDummy')] public $absoluteUrlDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/AbstractDummy.php b/tests/Fixtures/TestBundle/Document/AbstractDummy.php index eff751901a4..69c55c89dd8 100644 --- a/tests/Fixtures/TestBundle/Document/AbstractDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbstractDummy.php @@ -13,8 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; @@ -22,32 +27,25 @@ * Abstract Dummy. * * @author Jérémy Derussé - * @ApiResource( - * collectionOperations={"get", "post"}, - * itemOperations={"get", "put", "delete"}, - * attributes={"filters"={"my_dummy.mongodb.search", "my_dummy.mongodb.order", "my_dummy.mongodb.date"}} - * ) - * @ODM\Document - * @ODM\InheritanceType("SINGLE_COLLECTION") - * @ODM\DiscriminatorField(value="discr") - * @ODM\DiscriminatorMap({"concrete"=ConcreteDummy::class}) */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new GetCollection(), new Post()], filters: ['my_dummy.mongodb.search', 'my_dummy.mongodb.order', 'my_dummy.mongodb.date'])] +#[ODM\Document] +#[ODM\InheritanceType('SINGLE_COLLECTION')] +#[ODM\DiscriminatorField(value: 'discr')] +#[ODM\DiscriminatorMap(['concrete' => ConcreteDummy::class])] abstract class AbstractDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The dummy name - * - * @ODM\Field - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[Assert\NotBlank] + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Address.php b/tests/Fixtures/TestBundle/Document/Address.php index 6d886bb79b7..7d2bf5c19a2 100644 --- a/tests/Fixtures/TestBundle/Document/Address.php +++ b/tests/Fixtures/TestBundle/Document/Address.php @@ -13,30 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * attributes={"normalization_context"={"groups"={"order_read"}}} - * ) - * @ODM\Document - */ +#[ApiResource(normalizationContext: ['groups' => ['order_read']])] +#[ODM\Document] class Address { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"order_read"}) - */ - private $id; - - /** - * @ODM\Field(type="string") - * @Groups({"order_read"}) - */ + #[Groups(['order_read'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[Groups(['order_read'])] + #[ODM\Field(type: 'string')] public $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Answer.php b/tests/Fixtures/TestBundle/Document/Answer.php index 0710e32030c..3865bc862f4 100644 --- a/tests/Fixtures/TestBundle/Document/Answer.php +++ b/tests/Fixtures/TestBundle/Document/Answer.php @@ -13,8 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -22,37 +27,24 @@ /** * Answer. - * - * @ODM\Document - * @ApiResource(collectionOperations={ - * "get_subresource_answer"={"method"="GET", "normalization_context"={"groups"={"foobar"}}} - * }) */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(normalizationContext: ['groups' => ['foobar']])])] +#[ApiResource(uriTemplate: '/answers/{id}/related_questions/{relatedQuestions}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], toProperty: 'answer'), 'relatedQuestions' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/questions/{id}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] +#[ODM\Document] class Answer { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - * @Serializer\Groups({"foobar"}) - */ + #[Serializer\Groups(['foobar'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(nullable=false) - * @Serializer\Groups({"foobar"}) - */ + #[Serializer\Groups(['foobar'])] + #[ODM\Field(nullable: false)] private $content; - - /** - * @ODM\ReferenceOne(targetDocument=Question::class, mappedBy="answer") - * @Serializer\Groups({"foobar"}) - */ + #[Serializer\Groups(['foobar'])] + #[ODM\ReferenceOne(targetDocument: Question::class, mappedBy: 'answer')] private $question; - - /** - * @ODM\ReferenceMany(targetDocument=Question::class, mappedBy="answer") - * @Serializer\Groups({"foobar"}) - * @ApiSubresource - */ + #[Serializer\Groups(['foobar'])] + #[ODM\ReferenceMany(targetDocument: Question::class, mappedBy: 'answer')] private $relatedQuestions; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php b/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php index 66445aeeb3a..cc6eb675783 100644 --- a/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php +++ b/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayRequiredFilter; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -23,29 +23,22 @@ * * @author Julien Deniau * @author Alan Poulain - * - * @ApiResource(attributes={ - * "filters"={ - * ArrayRequiredFilter::class - * } - * }) - * @ODM\Document */ +#[ApiResource(filters: [ArrayRequiredFilter::class])] +#[ODM\Document] class ArrayFilterValidator { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string A name - * - * @ODM\Field - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Book.php b/tests/Fixtures/TestBundle/Document/Book.php index b9846f71b07..e95179ce536 100644 --- a/tests/Fixtures/TestBundle/Document/Book.php +++ b/tests/Fixtures/TestBundle/Document/Book.php @@ -13,35 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Book. * * @author Antoine Bluchet - * - * @ApiResource(collectionOperations={}, itemOperations={ - * "get", - * "get_by_isbn"={"method"="GET", "path"="/books/by_isbn/{isbn}.{_format}", "requirements"={"isbn"=".+"}, "identifiers"="isbn"} - * }) - * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Get(uriTemplate: '/books/by_isbn/{isbn}.{_format}', requirements: ['isbn' => '.+'], uriVariables: 'isbn')])] +#[ODM\Document] class Book { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string", nullable=true) - */ + #[ODM\Field(type: 'string', nullable: true)] public $name; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $isbn; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/CircularReference.php b/tests/Fixtures/TestBundle/Document/CircularReference.php index f49deadd91f..8aed20583fc 100644 --- a/tests/Fixtures/TestBundle/Document/CircularReference.php +++ b/tests/Fixtures/TestBundle/Document/CircularReference.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,29 +22,18 @@ * Circular Reference. * * @author Kévin Dunglas - * - * @ApiResource(attributes={"normalization_context"={"groups"={"circular"}}}) - * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['circular']])] +#[ODM\Document] class CircularReference { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - - /** - * @ODM\ReferenceOne(targetDocument=CircularReference::class, inversedBy="children") - * - * @Groups({"circular"}) - */ + #[Groups(['circular'])] + #[ODM\ReferenceOne(targetDocument: self::class, inversedBy: 'children')] public $parent; - - /** - * @ODM\ReferenceMany(targetDocument=CircularReference::class, mappedBy="parent") - * - * @Groups({"circular"}) - */ + #[Groups(['circular'])] + #[ODM\ReferenceMany(targetDocument: self::class, mappedBy: 'parent')] public $children; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/Comment.php b/tests/Fixtures/TestBundle/Document/Comment.php index 340f4eed62d..af77b18ad73 100644 --- a/tests/Fixtures/TestBundle/Document/Comment.php +++ b/tests/Fixtures/TestBundle/Document/Comment.php @@ -17,29 +17,17 @@ /** * @author Vincent Chalamon - * - * @ODM\Document */ +#[ODM\Document] class Comment { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $comment; - - /** - * @ODM\Field(type="date") - */ + #[ODM\Field(type: 'date')] public $date; - - /** - * @ODM\ReferenceOne(targetDocument=User::class, storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: User::class, storeAs: 'id')] public $author; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Company.php b/tests/Fixtures/TestBundle/Document/Company.php index ea00a67ded2..e2eda4cbefb 100644 --- a/tests/Fixtures/TestBundle/Document/Company.php +++ b/tests/Fixtures/TestBundle/Document/Company.php @@ -19,29 +19,25 @@ use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] #[Get] #[Post] #[ApiResource(uriTemplate: '/employees/{employeeId}/rooms/{roomId}/company/{companyId}', uriVariables: ['employeeId' => ['from_class' => Employee::class, 'from_property' => 'company']])] #[Get] #[ApiResource(uriTemplate: '/employees/{employeeId}/company', uriVariables: ['employeeId' => ['from_class' => Employee::class, 'from_property' => 'company']])] +#[ODM\Document] class Company { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] public $name; /** @var Employee[] */ diff --git a/tests/Fixtures/TestBundle/Document/CompositeItem.php b/tests/Fixtures/TestBundle/Document/CompositeItem.php index c20b6409b4c..bc6e90fbe0e 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeItem.php +++ b/tests/Fixtures/TestBundle/Document/CompositeItem.php @@ -13,33 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Item. - * - * @ApiResource - * @ODM\Document */ -class CompositeItem +#[ApiResource] +#[ODM\Document] +class CompositeItem implements \Stringable { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string", nullable=true) - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\Field(type: 'string', nullable: true)] private $field1; - - /** - * @ODM\ReferenceMany(targetDocument=CompositeRelation::class, mappedBy="compositeItem") - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\ReferenceMany(targetDocument: CompositeRelation::class, mappedBy: 'compositeItem')] private $compositeValues; /** @@ -76,7 +67,7 @@ public function getCompositeValues(): ?CompositeRelation return $this->compositeValues; } - public function __toString() + public function __toString(): string { return (string) $this->id; } diff --git a/tests/Fixtures/TestBundle/Document/CompositeLabel.php b/tests/Fixtures/TestBundle/Document/CompositeLabel.php index 76ca3463157..dccf6d23f4a 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeLabel.php +++ b/tests/Fixtures/TestBundle/Document/CompositeLabel.php @@ -13,27 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Label. - * - * @ApiResource - * @ODM\Document */ -class CompositeLabel +#[ApiResource] +#[ODM\Document] +class CompositeLabel implements \Stringable { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string", nullable=true) - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\Field(type: 'string', nullable: true)] private $value; /** @@ -62,7 +56,7 @@ public function setValue($value = null) $this->value = $value; } - public function __toString() + public function __toString(): string { return (string) $this->id; } diff --git a/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php b/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php index 71d27234ca5..e447ed1aebe 100644 --- a/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php +++ b/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php @@ -13,41 +13,25 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Composite Primitive Item. - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class CompositePrimitiveItem { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string") - */ - private $name; - - /** - * @ODM\Field(type="int") - */ - private $year; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] private $description; - public function __construct(string $name, int $year) - { - $this->name = $name; - $this->year = $year; + public function __construct( + #[ODM\Field(type: 'string')] private readonly string $name, + #[ODM\Field(type: 'int')] private readonly int $year + ) { } /** diff --git a/tests/Fixtures/TestBundle/Document/CompositeRelation.php b/tests/Fixtures/TestBundle/Document/CompositeRelation.php index e061d544d57..a4c82989161 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeRelation.php +++ b/tests/Fixtures/TestBundle/Document/CompositeRelation.php @@ -13,39 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Relation. - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class CompositeRelation { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string", nullable=true) - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\Field(type: 'string', nullable: true)] private $value; - - /** - * @ODM\ReferenceOne(targetDocument=CompositeItem::class, inversedBy="compositeValues") - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\ReferenceOne(targetDocument: CompositeItem::class, inversedBy: 'compositeValues')] private $compositeItem; - - /** - * @ODM\ReferenceOne(targetDocument=CompositeLabel::class) - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\ReferenceOne(targetDocument: CompositeLabel::class)] private $compositeLabel; /** diff --git a/tests/Fixtures/TestBundle/Document/ConcreteDummy.php b/tests/Fixtures/TestBundle/Document/ConcreteDummy.php index a5adb8f9bfe..41794c1cb00 100644 --- a/tests/Fixtures/TestBundle/Document/ConcreteDummy.php +++ b/tests/Fixtures/TestBundle/Document/ConcreteDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; @@ -21,18 +21,16 @@ * Concrete Dummy. * * @author Jérémy Derusse - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class ConcreteDummy extends AbstractDummy { /** * @var string a concrete thing - * - * @ODM\Field - * @Assert\NotBlank */ + #[Assert\NotBlank] + #[ODM\Field] private $instance; public function setInstance($instance) diff --git a/tests/Fixtures/TestBundle/Document/ContainNonResource.php b/tests/Fixtures/TestBundle/Document/ContainNonResource.php index f328bb2f96c..b24ef937dd4 100644 --- a/tests/Fixtures/TestBundle/Document/ContainNonResource.php +++ b/tests/Fixtures/TestBundle/Document/ContainNonResource.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\NotAResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,39 +21,23 @@ /** * Resource linked to a standard object. * - * @ODM\Document - * - * @ApiResource( - * attributes={ - * "filters"={"my_dummy.property"} - * }, - * normalizationContext={ - * "groups"={"contain_non_resource"} - * } - * ) - * * @author Kévin Dunglas */ +#[ApiResource(filters: ['my_dummy.property'], normalizationContext: ['groups' => ['contain_non_resource']])] +#[ODM\Document] class ContainNonResource { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups("contain_non_resource") - */ + #[Groups('contain_non_resource')] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - /** * @var ContainNonResource - * - * @Groups("contain_non_resource") */ + #[Groups('contain_non_resource')] public $nested; - /** * @var NotAResource - * - * @Groups("contain_non_resource") */ + #[Groups('contain_non_resource')] public $notAResource; } diff --git a/tests/Fixtures/TestBundle/Document/Content.php b/tests/Fixtures/TestBundle/Document/Content.php index 914bfc2d968..f02394c102e 100644 --- a/tests/Fixtures/TestBundle/Document/Content.php +++ b/tests/Fixtures/TestBundle/Document/Content.php @@ -13,56 +13,28 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Enum\ContentStatus; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * normalizationContext={ - * "groups"={"get_content"}, - * }, - * ) - * - * @ODM\Document - */ +#[ApiResource(normalizationContext: ['groups' => ['get_content']])] +#[ODM\Document] class Content implements \JsonSerializable { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var string|null - * - * @ODM\Field(type="string") - */ - private $contentType; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field(type: 'string')] + private ?string $contentType = null; /** * @var Collection - * - * @ODM\ReferenceMany( - * targetDocument=Field::class, - * mappedBy="content", - * strategy="set", - * cascade={"persist"}, - * ) */ - private $fields; - - /** - * @var string - * - * @ODM\Field(type="string") - */ - private $status; + #[ODM\ReferenceMany(targetDocument: Field::class, mappedBy: 'content', strategy: 'set', cascade: ['persist'])] + private \Doctrine\Common\Collections\Collection & iterable $fields; + #[ODM\Field(type: 'string')] + private readonly string $status; public function __construct() { @@ -70,17 +42,13 @@ public function __construct() $this->status = ContentStatus::DRAFT; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getId(): ?int { return $this->id; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getContentType(): ?string { return $this->contentType; @@ -109,7 +77,6 @@ public function addField(Field $field): void if ($this->hasField($field->getName())) { throw new \InvalidArgumentException(sprintf("Content already has '%s' field", $field->getName())); } - $this->fields[$field->getName()] = $field; $field->setContent($this); } @@ -117,16 +84,13 @@ public function addField(Field $field): void public function removeField(Field $field): void { unset($this->fields[$field->getName()]); - // set the owning side to null (unless already changed) if ($field->getContent() === $this) { $field->setContent(null); } } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getFieldValues(): array { $fieldValues = []; @@ -137,9 +101,7 @@ public function getFieldValues(): array return $fieldValues; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getStatus(): ContentStatus { return new ContentStatus($this->status); @@ -153,10 +115,6 @@ public function getStatus(): ContentStatus #[\ReturnTypeWillChange] public function jsonSerialize() { - return [ - 'id' => $this->id, - 'contentType' => $this->contentType, - 'fields' => $this->fields, - ]; + return ['id' => $this->id, 'contentType' => $this->contentType, 'fields' => $this->fields]; } } diff --git a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php index c0c2e660ac1..009438126f7 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php @@ -13,30 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\BooleanFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - * @ApiFilter(BooleanFilter::class) - */ +#[ApiFilter(BooleanFilter::class)] +#[ApiResource] +#[ODM\Document] class ConvertedBoolean { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var bool - * - * @ODM\Field(type="bool") */ + #[ODM\Field(type: 'bool')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedDate.php b/tests/Fixtures/TestBundle/Document/ConvertedDate.php index 4439ccf57e2..e97203f21f9 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedDate.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedDate.php @@ -13,30 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - * @ApiFilter(DateFilter::class) - */ +#[ApiFilter(DateFilter::class)] +#[ApiResource] +#[ODM\Document] class ConvertedDate { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var \DateTime - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php index 0b590cf004e..e8e7675b5b6 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php @@ -13,34 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\NumericFilter; use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; use ApiPlatform\Doctrine\Odm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - * @ApiFilter(NumericFilter::class, properties={"nameConverted"}) - * @ApiFilter(RangeFilter::class, properties={"nameConverted"}) - * @ApiFilter(OrderFilter::class, properties={"nameConverted"}) - */ +#[ApiFilter(NumericFilter::class, properties: ['nameConverted'])] +#[ApiFilter(RangeFilter::class, properties: ['nameConverted'])] +#[ApiFilter(OrderFilter::class, properties: ['nameConverted'])] +#[ApiResource] +#[ODM\Document] class ConvertedInteger { + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var int - * - * @ODM\Field(type="int") */ + #[ODM\Field(type: 'int')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php index cfebc9e52a1..7a225498ac5 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php @@ -14,29 +14,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - * @ApiFilter(SearchFilter::class, properties={"nameConverted.nameConverted"="partial"}) - */ +#[ApiFilter(SearchFilter::class, properties: ['nameConverted.nameConverted' => 'partial'])] +#[ApiResource] +#[ODM\Document] class ConvertedOwner { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var ConvertedRelated - * - * @ODM\ReferenceOne(targetDocument=ConvertedRelated::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceOne(targetDocument: ConvertedRelated::class, storeAs: 'id', nullable: true)] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedRelated.php b/tests/Fixtures/TestBundle/Document/ConvertedRelated.php index 01e3a7037a5..e7b36afeb8c 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedRelated.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedRelated.php @@ -13,27 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class ConvertedRelated { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedString.php b/tests/Fixtures/TestBundle/Document/ConvertedString.php index 09186981079..e9c38df3ee4 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedString.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedString.php @@ -13,30 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\ExistsFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - * @ApiFilter(ExistsFilter::class, properties={"nameConverted"}) - */ +#[ApiFilter(ExistsFilter::class, properties: ['nameConverted'])] +#[ApiResource] +#[ODM\Document] class ConvertedString { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null - * - * @ODM\Field(type="string", nullable=true) */ + #[ODM\Field(type: 'string', nullable: true)] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/CustomActionDummy.php b/tests/Fixtures/TestBundle/Document/CustomActionDummy.php index d46f1dcb19d..30323168e25 100644 --- a/tests/Fixtures/TestBundle/Document/CustomActionDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomActionDummy.php @@ -13,41 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ODM\Document - * @ApiResource(itemOperations={ - * "get", - * "get_custom"={"method"="GET", "path"="custom_action_collection_dummies/{id}"}, - * "custom_normalization"={"method"="GET", "route_name"="custom_normalization"}, - * "short_custom_normalization"={"method"="GET", "route_name"="short_custom_normalization"}, - * }, - * collectionOperations={ - * "get", - * "get_custom"={"method"="GET", "path"="custom_action_collection_dummies"}, - * "custom_denormalization"={"method"="POST", "route_name"="custom_denormalization"}, - * "short_custom_denormalization"={"method"="GET", "route_name"="short_custom_denormalization"}, - * }) - * * @author Kévin Dunglas */ +#[ApiResource(operations: [new Get(), new Get(uriTemplate: 'custom_action_collection_dummies/{id}'), new Get(routeName: 'custom_normalization'), new Get(routeName: 'short_custom_normalization'), new GetCollection(), new GetCollection(uriTemplate: 'custom_action_collection_dummies'), new Post(routeName: 'custom_denormalization'), new GetCollection(routeName: 'short_custom_denormalization')])] +#[ODM\Document] class CustomActionDummy { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var string - * - * @ODM\Field - */ - private $foo = ''; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field] + private string $foo = ''; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php b/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php index 8cf70fc25e0..22e134d951d 100644 --- a/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php +++ b/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php @@ -13,24 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom identifier. - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class CustomGeneratedIdentifier { - /** - * @var Uuid - * - * @ODM\Id(strategy="CUSTOM", type="string", options={"class"="ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\DocumentUuidGenerator"}) - */ - private $id; + #[ODM\Id(strategy: 'CUSTOM', type: 'string', options: ['class' => \ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\DocumentUuidGenerator::class])] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php index 976ed067c8b..7c419226bd6 100644 --- a/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php @@ -13,30 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom Identifier Dummy. - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class CustomIdentifierDummy { /** * @var int The custom identifier - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $customId; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $customId = null; /** * @var string The dummy name - * - * @ODM\Field */ - private $name; + #[ODM\Field] + private ?string $name = null; public function getCustomId(): int { diff --git a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php index f727d7dab6b..f2aa4f849ab 100644 --- a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php @@ -13,39 +13,36 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom Identifier Dummy. - * - * @ApiResource(compositeIdentifier=false) - * @ODM\Document */ +#[ApiResource(uriVariables: ['firstId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['firstId']), 'secondId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['secondId'])])] +#[ODM\Document] class CustomMultipleIdentifierDummy { /** * @var int The custom identifier - * - * @ODM\Id(strategy="NONE", type="int") */ - private $firstId; + #[ODM\Id(strategy: 'NONE', type: 'int')] + private ?int $firstId = null; /** * @var int The custom identifier - * - * @ApiProperty(identifier=true) - * @ODM\Field(type="int") */ - private $secondId; + #[ApiProperty(identifier: true)] + #[ODM\Field(type: 'int')] + private ?int $secondId = null; /** * @var string The dummy name - * - * @ODM\Field(type="string") */ - private $name; + #[ODM\Field(type: 'string')] + private ?string $name = null; public function getFirstId(): int { diff --git a/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php b/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php index a64c74a0ec8..8e3cff9d05d 100644 --- a/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,41 +23,34 @@ * Custom Normalized Dummy. * * @author Mikaël Labrut - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"output"}}, - * "denormalization_context"={"groups"={"input"}} - * }) - * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['output']], denormalizationContext: ['groups' => ['input']])] +#[ODM\Document] class CustomNormalizedDummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"input", "output"}) */ - private $id; + #[Groups(['input', 'output'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"input", "output"}) */ - private $name; + #[ApiProperty(types: ['http://schema.org/name'])] + #[Assert\NotBlank] + #[Groups(['input', 'output'])] + #[ODM\Field] + private ?string $name = null; /** * @var string|null The dummy name alias - * - * @ODM\Field(nullable=true) - * @ApiProperty(iri="https://schema.org/alternateName") - * @Groups({"input", "output"}) */ - private $alias; + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[Groups(['input', 'output'])] + #[ODM\Field(nullable: true)] + private ?string $alias = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php index 8cdf14a1597..167e91516e6 100644 --- a/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php @@ -13,30 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom Writable Identifier Dummy. - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class CustomWritableIdentifierDummy { /** * @var string The special identifier - * - * @ODM\Id(strategy="NONE", type="string") */ - private $slug; - + #[ODM\Id(strategy: 'NONE', type: 'string')] + private ?string $slug = null; /** * @var string The dummy name - * - * @ODM\Field(name="name", type="string") */ - private $name; + #[ODM\Field(name: 'name', type: 'string')] + private ?string $name = null; /** * @param string $slug diff --git a/tests/Fixtures/TestBundle/Document/Customer.php b/tests/Fixtures/TestBundle/Document/Customer.php index 05a9f3a7802..3c442fd6bb7 100644 --- a/tests/Fixtures/TestBundle/Document/Customer.php +++ b/tests/Fixtures/TestBundle/Document/Customer.php @@ -13,37 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * attributes={"normalization_context"={"groups"={"order_read"}}} - * ) - * @ODM\Document - */ +#[ApiResource(normalizationContext: ['groups' => ['order_read']])] +#[ODM\Document] class Customer { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"order_read"}) - */ - private $id; - - /** - * @ODM\Field(type="string") - * @Groups({"order_read"}) - */ + #[Groups(['order_read'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[Groups(['order_read'])] + #[ODM\Field(type: 'string')] public $name; - - /** - * @ODM\ReferenceMany(targetDocument=Address::class) - * @Groups({"order_read"}) - */ + #[Groups(['order_read'])] + #[ODM\ReferenceMany(targetDocument: Address::class)] public $addresses; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DeprecatedResource.php b/tests/Fixtures/TestBundle/Document/DeprecatedResource.php index c591eb5036c..3a792c1a956 100644 --- a/tests/Fixtures/TestBundle/Document/DeprecatedResource.php +++ b/tests/Fixtures/TestBundle/Document/DeprecatedResource.php @@ -13,28 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource(deprecationReason="This resource is deprecated") - * @ODM\Document - * * @author Kévin Dunglas */ +#[ApiResource(deprecationReason: 'This resource is deprecated')] +#[ODM\Document] class DeprecatedResource { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; /** * @var string - * - * @ApiProperty(attributes={"deprecation_reason"="This field is deprecated"}) - * @ODM\Field */ + #[ApiProperty(deprecationReason: 'This field is deprecated')] + #[ODM\Field] public $deprecatedField; } diff --git a/tests/Fixtures/TestBundle/Document/DisableItemOperation.php b/tests/Fixtures/TestBundle/Document/DisableItemOperation.php index aa083412728..973ca42ca50 100644 --- a/tests/Fixtures/TestBundle/Document/DisableItemOperation.php +++ b/tests/Fixtures/TestBundle/Document/DisableItemOperation.php @@ -14,36 +14,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Action\NotFoundAction; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource( - * collectionOperations={ - * "get", - * }, - * itemOperations={ - * "get"={ - * "controller"=NotFoundAction::class, - * "read"=false, - * "output"=false, - * }, - * }, - * ) - * @ODM\Document - */ +#[ApiResource(operations: [new Get(controller: NotFoundAction::class, read: false, output: false), new GetCollection()])] +#[ODM\Document] class DisableItemOperation { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] public $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Dummy.php b/tests/Fixtures/TestBundle/Document/Dummy.php index e9f58f3d5d5..411af813faf 100644 --- a/tests/Fixtures/TestBundle/Document/Dummy.php +++ b/tests/Fixtures/TestBundle/Document/Dummy.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; @@ -26,149 +26,101 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * - * @ApiResource(attributes={ - * "doctrine_mongodb"={ - * "execute_options"={ - * "allowDiskUse"=true - * } - * }, - * "filters"={ - * "my_dummy.mongodb.boolean", - * "my_dummy.mongodb.date", - * "my_dummy.mongodb.exists", - * "my_dummy.mongodb.numeric", - * "my_dummy.mongodb.order", - * "my_dummy.mongodb.range", - * "my_dummy.mongodb.search", - * "my_dummy.property" - * } - * }) - * @ODM\Document */ +#[ApiResource(extraProperties: ['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]], filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])] +#[ODM\Document] class Dummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] private $id; - /** * @var string|null The dummy name - * - * @ODM\Field(type="string") - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[Assert\NotBlank] + #[ODM\Field(type: 'string')] private $name; - /** * @var string|null The dummy name alias - * - * @ODM\Field(nullable=true) - * @ApiProperty(iri="https://schema.org/alternateName") */ + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[ODM\Field(nullable: true)] private $alias; - /** * @var array|null foo */ - private $foo; - + private ?array $foo = null; /** * @var string|null A short description of the item - * - * @ODM\Field(type="string", nullable=true) - * @ApiProperty(iri="https://schema.org/description") */ + #[ApiProperty(types: ['http://schema.org/description'])] + #[ODM\Field(type: 'string', nullable: true)] public $description; - /** * @var string|null A dummy - * - * @ODM\Field(nullable=true) */ + #[ODM\Field(nullable: true)] public $dummy; - /** * @var bool|null A dummy boolean - * - * @ODM\Field(type="bool", nullable=true) */ + #[ODM\Field(type: 'bool', nullable: true)] public $dummyBoolean; - /** * @var \DateTime|null A dummy date - * - * @ODM\Field(type="date", nullable=true) - * @ApiProperty(iri="http://schema.org/DateTime") */ + #[ApiProperty(types: ['http://schema.org/DateTime'])] + #[ODM\Field(type: 'date', nullable: true)] public $dummyDate; - /** * @var float|null A dummy float - * - * @ODM\Field(type="float", nullable=true) */ + #[ODM\Field(type: 'float', nullable: true)] public $dummyFloat; - /** * @var float|null A dummy price - * - * @ODM\Field(type="float", nullable=true) */ + #[ODM\Field(type: 'float', nullable: true)] public $dummyPrice; - /** * @var RelatedDummy|null A related dummy - * - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummy; - /** - * @var Collection Several dummies - * - * @ODM\ReferenceMany(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) - * @ApiSubresource + * @var \Collection Several dummies */ + #[ODM\ReferenceMany(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummies; - /** * @var array serialize data - * - * @ODM\Field(type="hash", nullable=true) */ + #[ODM\Field(type: 'hash', nullable: true)] public $jsonData; - /** * @var array - * - * @ODM\Field(type="collection", nullable=true) */ + #[ODM\Field(type: 'collection', nullable: true)] public $arrayData; - /** * @var string|null - * - * @ODM\Field(nullable=true) */ + #[ODM\Field(nullable: true)] public $nameConverted; - /** * @var RelatedOwnedDummy|null - * - * @ODM\ReferenceOne(targetDocument=RelatedOwnedDummy::class, cascade={"persist"}, mappedBy="owningDummy", nullable=true) */ + #[ODM\ReferenceOne(targetDocument: RelatedOwnedDummy::class, cascade: ['persist'], mappedBy: 'owningDummy', nullable: true)] public $relatedOwnedDummy; - /** * @var RelatedOwningDummy|null - * - * @ODM\ReferenceOne(targetDocument=RelatedOwningDummy::class, cascade={"persist"}, inversedBy="ownedDummy", nullable=true, storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: RelatedOwningDummy::class, cascade: ['persist'], inversedBy: 'ownedDummy', nullable: true, storeAs: 'id')] public $relatedOwningDummy; public static function staticMethod(): void @@ -297,7 +249,6 @@ public function getRelatedOwnedDummy() public function setRelatedOwnedDummy(RelatedOwnedDummy $relatedOwnedDummy) { $this->relatedOwnedDummy = $relatedOwnedDummy; - if ($this !== $this->relatedOwnedDummy->getOwningDummy()) { $this->relatedOwnedDummy->setOwningDummy($this); } diff --git a/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php b/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php index f2be0264129..c7a0f0ceaf7 100644 --- a/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php +++ b/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php @@ -13,49 +13,41 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy Aggregate Offer. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_products/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class DummyAggregateOffer { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - - /** - * @var ArrayCollection - * - * @ApiSubresource - * @ODM\ReferenceMany(targetDocument=DummyOffer::class, mappedBy="aggregate", cascade={"persist"}) - */ - private $offers; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\ReferenceMany(targetDocument: DummyOffer::class, mappedBy: 'aggregate', cascade: ['persist'])] + private \Doctrine\Common\Collections\ArrayCollection $offers; /** * @var DummyProduct The dummy product - * - * @ODM\ReferenceOne(targetDocument=DummyProduct::class, inversedBy="offers", storeAs="id") */ - private $product; - + #[ODM\ReferenceOne(targetDocument: DummyProduct::class, inversedBy: 'offers', storeAs: 'id')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct $product = null; /** * @var int The dummy aggregate offer value - * - * @ODM\Field(type="int") */ + #[ODM\Field(type: 'int')] private $value; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DummyBoolean.php b/tests/Fixtures/TestBundle/Document/DummyBoolean.php index 7a3fe973deb..3662d42a5b9 100644 --- a/tests/Fixtures/TestBundle/Document/DummyBoolean.php +++ b/tests/Fixtures/TestBundle/Document/DummyBoolean.php @@ -13,32 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class DummyBoolean { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) - */ - private $id; - - /** - * @var bool - * - * @ODM\Field(type="bool", nullable=true) - */ - private $isDummyBoolean; - - public function __construct(bool $isDummyBoolean) - { - $this->isDummyBoolean = $isDummyBoolean; + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] + private ?int $id = null; + + public function __construct( + #[ODM\Field(type: 'bool', nullable: true)] private readonly bool $isDummyBoolean + ) { } public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyCar.php b/tests/Fixtures/TestBundle/Document/DummyCar.php index 8c8783d9905..254b6b9211a 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCar.php +++ b/tests/Fixtures/TestBundle/Document/DummyCar.php @@ -13,112 +13,75 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Serializer\Filter\GroupFilter; use ApiPlatform\Serializer\Filter\PropertyFilter; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ApiResource( - * itemOperations={"get"={"swagger_context"={"tags"={}}, "openapi_context"={"tags"={}}}, "put", "delete"}, - * attributes={ - * "sunset"="2050-01-01", - * "normalization_context"={"groups"={"colors"}} - * } - * ) - * @ODM\Document - * @ApiFilter(DateFilter::class, strategy=DateFilter::EXCLUDE_NULL) - * @ApiFilter(BooleanFilter::class) - * @ApiFilter(PropertyFilter::class, arguments={"parameterName"="foobar"}) - * @ApiFilter(GroupFilter::class, arguments={"parameterName"="foobargroups"}) - * @ApiFilter(GroupFilter::class, arguments={"parameterName"="foobargroups_override"}, id="override") - */ +#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)] +#[ApiFilter(BooleanFilter::class)] +#[ApiFilter(PropertyFilter::class, arguments: ['parameterName' => 'foobar'])] +#[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups'])] +#[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups_override'], id: 'override')] +#[ApiResource(operations: [new Get(openapiContext: ['tags' => []]), new Put(), new Delete(), new Post(), new GetCollection()], sunset: '2050-01-01', normalizationContext: ['groups' => ['colors']])] +#[ODM\Document] class DummyCar { /** * @var int The entity Id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var mixed Something else - * - * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") - * - * @Serializer\Groups({"colors"}) - * @ApiFilter(SearchFilter::class, properties={"colors.prop"="ipartial", "colors"="exact"}) */ + #[ApiFilter(SearchFilter::class, properties: ['colors.prop' => 'ipartial', 'colors' => 'exact'])] + #[Serializer\Groups(['colors'])] + #[ODM\ReferenceMany(targetDocument: DummyCarColor::class, mappedBy: 'car')] private $colors; - /** * @var mixed Something else - * - * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") - * - * @Serializer\Groups({"colors"}) - * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $secondColors; - + #[ApiFilter(SearchFilter::class, strategy: 'exact')] + #[Serializer\Groups(['colors'])] + #[ODM\ReferenceMany(targetDocument: DummyCarColor::class, mappedBy: 'car')] + private mixed $secondColors = null; /** * @var mixed Something else - * - * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") - * - * @Serializer\Groups({"colors"}) - * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $thirdColors; - + #[ApiFilter(SearchFilter::class, strategy: 'exact')] + #[Serializer\Groups(['colors'])] + #[ODM\ReferenceMany(targetDocument: DummyCarColor::class, mappedBy: 'car')] + private mixed $thirdColors = null; /** * @var mixed Something else - * - * @ODM\ReferenceMany(targetDocument=UuidIdentifierDummy::class) - * - * @Serializer\Groups({"colors"}) - * @ApiFilter(SearchFilter::class, strategy="exact") - */ - private $uuid; - - /** - * @var string - * - * @ODM\Field(type="string") - * @ApiFilter(SearchFilter::class, strategy="partial") - */ - private $name; - - /** - * @var bool - * - * @ODM\Field(type="bool") - */ - private $canSell; - - /** - * @var \DateTime - * - * @ODM\Field(type="date") - */ - private $availableAt; - - /** - * @var string - * - * @Serializer\Groups({"colors"}) - * @Serializer\SerializedName("carBrand") - * - * @ODM\Field */ - private $brand = 'DummyBrand'; + #[ApiFilter(SearchFilter::class, strategy: 'exact')] + #[Serializer\Groups(['colors'])] + #[ODM\ReferenceMany(targetDocument: UuidIdentifierDummy::class)] + private mixed $uuid = null; + #[ApiFilter(SearchFilter::class, strategy: 'partial')] + #[ODM\Field(type: 'string')] + private ?string $name = null; + #[ODM\Field(type: 'bool')] + private ?bool $canSell = null; + #[ODM\Field(type: 'date')] + private ?\DateTime $availableAt = null; + #[Serializer\Groups(['colors'])] + #[Serializer\SerializedName('carBrand')] + #[ODM\Field] + private string $brand = 'DummyBrand'; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/DummyCarColor.php b/tests/Fixtures/TestBundle/Document/DummyCarColor.php index d2f4e50d454..1f7b5aa94f0 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Document/DummyCarColor.php @@ -13,44 +13,30 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class DummyCarColor { /** * @var int The entity Id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var DummyCar - * - * @ODM\ReferenceOne(targetDocument=DummyCar::class, inversedBy="colors", storeAs="id") - * @Assert\NotBlank - */ - private $car; - - /** - * @var string - * - * @ODM\Field(nullable=false) - * @ApiFilter(SearchFilter::class) - * @Assert\NotBlank - * - * @Serializer\Groups({"colors"}) */ - private $prop = ''; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[Assert\NotBlank] + #[ODM\ReferenceOne(targetDocument: DummyCar::class, inversedBy: 'colors', storeAs: 'id')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyCar $car = null; + #[ApiFilter(SearchFilter::class)] + #[Assert\NotBlank] + #[Serializer\Groups(['colors'])] + #[ODM\Field(nullable: false)] + private string $prop = ''; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php b/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php index 234c9b69a53..78c29971aac 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php @@ -13,29 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource(attributes={"formats"={"xml", "jsonld", "csv"={"text/csv"}, "pdf"="application/pdf"}}) - * @ODM\Document - */ +#[ApiResource(formats: ['xml', 'jsonld', 'csv' => ['text/csv'], 'pdf' => 'application/pdf'])] +#[ODM\Document] class DummyCustomFormat { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** * @var string - * - * @ODM\Field - * @Assert\NotBlank */ + #[Assert\NotBlank] + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php index 36621125f89..95eca0cf0ab 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php @@ -13,79 +13,30 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Dummy with a custom GraphQL mutation resolver. * - * @ODM\Document - * @ApiResource(graphql={ - * "sum"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNotPersisted"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNoWriteCustomResult"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "write"=false - * }, - * "sumOnlyPersist"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist_document", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "read"=false, - * "deserialize"=false, - * "validate"=false, - * "serialize"=false - * }, - * "testCustomArguments"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "args"={"operandC"={"type"="Int!"}} - * } - * }) - * * @author Raoul Clais */ +#[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist_document', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']])])] +#[ODM\Document] class DummyCustomMutation { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var int|null - * - * @ODM\Field(type="int") - */ - private $operandA; - - /** - * @var int|null - * - * @Groups({"sum"}) - * @ODM\Field(type="int", nullable=true) - */ - private $operandB; - - /** - * @var int|null - * - * @Groups({"result"}) - * @ODM\Field(type="int", nullable=true) - */ - private $result; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field(type: 'int')] + private ?int $operandA = null; + #[Groups(['sum'])] + #[ODM\Field(type: 'int', nullable: true)] + private ?int $operandB = null; + #[Groups(['result'])] + #[ODM\Field(type: 'int', nullable: true)] + private ?int $result = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php index c8e0ba438f5..6a5260ba82f 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php @@ -13,71 +13,29 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy with custom GraphQL query resolvers. * * @author Lukas Lücke - * - * @ApiResource(graphql={ - * "testItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item" - * }, - * "testNotRetrievedItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_not_retrieved_item_document", - * "args"={} - * }, - * "testNoReadAndSerializeItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document", - * "read"=false, - * "serialize"=false - * }, - * "testItemCustomArguments"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item", - * "args"={ - * "id"={"type"="ID"}, - * "customArgumentNullableBool"={"type"="Boolean"}, - * "customArgumentBool"={"type"="Boolean!"}, - * "customArgumentInt"={"type"="Int!"}, - * "customArgumentString"={"type"="String!"}, - * "customArgumentFloat"={"type"="Float!"}, - * "customArgumentIntArray"={"type"="[Int!]!"}, - * "customArgumentCustomType"={"type"="DateTime!"} - * } - * }, - * "testCollection"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection" - * }, - * "testCollectionNoReadAndSerialize"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize", - * "read"=false, - * "serialize"=false - * }, - * "testCollectionCustomArguments"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection", - * "args"={ - * "customArgumentString"={"type"="String!"} - * } - * } - * }) - * @ODM\Document */ +#[ApiResource(graphQlOperations: [new Query(name: 'testItem', resolver: 'app.graphql.query_resolver.dummy_custom_item'), new Query(name: 'testNotRetrievedItem', resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item_document', args: []), new Query(name: 'testNoReadAndSerializeItem', resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document', read: false, serialize: false), new Query(name: 'testItemCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_item', args: ['id' => ['type' => 'ID'], 'customArgumentNullableBool' => ['type' => 'Boolean'], 'customArgumentBool' => ['type' => 'Boolean!'], 'customArgumentInt' => ['type' => 'Int!'], 'customArgumentString' => ['type' => 'String!'], 'customArgumentFloat' => ['type' => 'Float!'], 'customArgumentIntArray' => ['type' => '[Int!]!'], 'customArgumentCustomType' => ['type' => 'DateTime!']]), new QueryCollection(name: 'testCollection', resolver: 'app.graphql.query_resolver.dummy_custom_collection'), new QueryCollection(name: 'testCollectionNoReadAndSerialize', resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false), new QueryCollection(name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']])])] +#[ODM\Document] class DummyCustomQuery { /** * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - /** * @var string */ public $message; - /** * @var array */ diff --git a/tests/Fixtures/TestBundle/Document/DummyDate.php b/tests/Fixtures/TestBundle/Document/DummyDate.php index 047384ef83d..48b3d85e650 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDate.php +++ b/tests/Fixtures/TestBundle/Document/DummyDate.php @@ -13,65 +13,52 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy Date. * - * @author Antoine Bluchet * @author Alan Poulain - * - * @ApiResource(attributes={ - * "filters"={"my_dummy_date.mongodb.date"} - * }) - * @ApiFilter(SearchFilter::class, properties={"dummyDate"}) - * @ApiFilter(DateFilter::class, properties={ - * "dateIncludeNullAfter"=DateFilter::INCLUDE_NULL_AFTER, - * "dateIncludeNullBefore"=DateFilter::INCLUDE_NULL_BEFORE, - * "dateIncludeNullBeforeAndAfter"=DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER - * }) - * - * @ODM\Document */ +#[ApiFilter(DateFilter::class, properties: [ + 'dateIncludeNullAfter' => DateFilter::INCLUDE_NULL_AFTER, + 'dateIncludeNullBefore' => DateFilter::INCLUDE_NULL_BEFORE, + 'dateIncludeNullBeforeAndAfter' => DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER, +])] +#[ApiFilter(SearchFilter::class, properties: ['dummyDate'])] +#[ApiResource(filters: ['my_dummy_date.mongodb.date'])] +#[ODM\Document] class DummyDate { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var \DateTime|null The dummy date - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $dummyDate; - /** * @var \DateTime|null - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $dateIncludeNullAfter; - /** * @var \DateTime|null - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $dateIncludeNullBefore; - /** * @var \DateTime|null - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $dateIncludeNullBeforeAndAfter; /** diff --git a/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php b/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php index a31a1ca6ac7..9f154aa58f0 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php +++ b/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,40 +23,29 @@ * Dummy with different serialization groups for item_query and collection_query. * * @author Mahmood Bazdar - * - * @ApiResource( - * graphql={ - * "item_query"={"normalization_context"={"groups"={"item_query"}}}, - * "collection_query"={"normalization_context"={"groups"={"collection_query"}}} - * } - * ) - * @ODM\Document */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['item_query']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['collection_query']])])] +#[ODM\Document] class DummyDifferentGraphQlSerializationGroup { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) - * @Groups({"item_query", "collection_query"}) */ - private $id; - + #[Groups(['item_query', 'collection_query'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field(type="string") - * @Groups({"item_query", "collection_query"}) */ - private $name; - + #[Groups(['item_query', 'collection_query'])] + #[ODM\Field(type: 'string')] + private ?string $name = null; /** * @var string|null The dummy title - * - * @ODM\Field(nullable=true) - * @Groups({"item_query"}) */ - private $title; + #[Groups(['item_query'])] + #[ODM\Field(nullable: true)] + private ?string $title = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php b/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php index 804df82333e..4e4f703222b 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php @@ -13,42 +13,37 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomInputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomOutputDto; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * DummyDtoCustom. - * - * @ODM\Document - * - * @ApiResource( - * collectionOperations={"post"={"input"=CustomInputDto::class}, "get", "custom_output"={"output"=CustomOutputDto::class, "path"="dummy_dto_custom_output", "method"="GET"}, "post_without_output"={"output"=false, "method"="POST", "path"="dummy_dto_custom_post_without_output"}}, - * itemOperations={"get", "custom_output"={"output"=CustomOutputDto::class, "method"="GET", "path"="dummy_dto_custom_output/{id}"}, "put", "delete"} - * ) */ +#[ApiResource(operations: [new Get(), new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}'), new Put(), new Delete(), new Post(input: CustomInputDto::class), new GetCollection(), new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output'), new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output')])] +#[ODM\Document] class DummyDtoCustom { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; - /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php b/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php index 3001d0901c6..f37ee5ecdf3 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\InputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto; use Doctrine\Common\Collections\ArrayCollection; @@ -24,38 +24,33 @@ * Dummy InputOutput. * * @author Kévin Dunglas - * - * @ApiResource(attributes={"input"=InputDto::class, "output"=OutputDto::class}) - * @ODM\Document */ +#[ApiResource(input: InputDto::class, output: OutputDto::class)] +#[ODM\Document] class DummyDtoInputOutput { public function __construct() { $this->relatedDummies = new ArrayCollection(); } - /** * @var int The id - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] public $id; - /** * @var string - * @ODM\Field */ + #[ODM\Field] public $str; - /** * @var int - * @ODM\Field(type="float") */ + #[ODM\Field(type: 'float')] public $num; - /** * @var Collection - * @ODM\ReferenceMany(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceMany(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummies; } diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php b/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php index 2166bf2a69a..40324afc0d8 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php @@ -13,7 +13,11 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\CreateItemAction; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\DoubleBatAction; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto; @@ -23,55 +27,25 @@ * DummyDtoNoInput. * * @author Vincent Chalamon - * - * @ODM\Document - * - * @ApiResource( - * attributes={ - * "input"=false, - * "output"=OutputDto::class - * }, - * collectionOperations={ - * "post"={ - * "method"="POST", - * "path"="/dummy_dto_no_inputs", - * "controller"=CreateItemAction::class, - * }, - * "get", - * }, - * itemOperations={ - * "get", - * "delete", - * "post_double_bat"={ - * "method"="POST", - * "path"="/dummy_dto_no_inputs/{id}/double_bat", - * "controller"=DoubleBatAction::class, - * "status"=200, - * }, - * }, - * ) */ +#[ApiResource(operations: [new Get(), new Delete(), new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200), new Post(uriTemplate: '/dummy_dto_no_inputs', controller: CreateItemAction::class), new GetCollection()], input: false, output: OutputDto::class)] +#[ODM\Document] class DummyDtoNoInput { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; - /** * @var float - * - * @ODM\Field(type="float") */ + #[ODM\Field(type: 'float')] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php b/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php index ac627a8652f..84b53e78cad 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -21,37 +21,25 @@ * DummyDtoNoOutput. * * @author Vincent Chalamon - * - * @ODM\Document - * - * @ApiResource( - * attributes={ - * "input"=InputDto::class, - * "output"=false - * } - * ) */ +#[ApiResource(input: InputDto::class, output: false)] +#[ODM\Document] class DummyDtoNoOutput { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; - /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php index 399bec0645b..d5b7828b25e 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDtoDummy; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -21,31 +21,25 @@ * Dummy InputOutput. * * @author Daniel West - * - * @ApiResource(attributes={"output"=OutputDtoDummy::class}) - * @ODM\Document */ +#[ApiResource(output: OutputDtoDummy::class)] +#[ODM\Document] class DummyDtoOutputFallbackToSameClass { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] + private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; - /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php index b99988cba90..4ffceb19d42 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php @@ -13,38 +13,32 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy InputOutput. * * @author Daniel West - * - * @ApiResource(attributes={"output"=DummyDtoOutputSameClass::class}) - * @ODM\Document */ +#[ApiResource(output: DummyDtoOutputSameClass::class)] +#[ODM\Document] class DummyDtoOutputSameClass { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] + private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; - /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php b/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php index e8ddbd35b51..09594088341 100644 --- a/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php +++ b/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php @@ -13,69 +13,43 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\DummyObjectWithoutConstructor; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Dummy entity built with constructor. + * * https://github.com/api-platform/core/issues/1747. * * @author Maxime Veber - * - * @ApiResource( - * itemOperations={ - * "get", - * "put"={"denormalization_context"={"groups"={"put"}}} - * } - * ) - * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(denormalizationContext: ['groups' => ['put']]), new Post(), new GetCollection()])] +#[ODM\Document] class DummyEntityWithConstructor { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var string - * - * @ODM\Field - */ - private $foo; - - /** - * @var string - * - * @ODM\Field */ - private $bar; - - /** - * @var string|null - * - * @ODM\Field(nullable=true) - * @Groups({"put"}) - */ - private $baz; - - /** - * @var DummyObjectWithoutConstructor[] - */ - private $items; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[Groups(['put'])] + #[ODM\Field(nullable: true)] + private ?string $baz = null; /** * @param DummyObjectWithoutConstructor[] $items */ - public function __construct(string $foo, string $bar, array $items) - { - $this->foo = $foo; - $this->bar = $bar; - $this->items = $items; + public function __construct( + #[ODM\Field] private readonly string $foo, + #[ODM\Field] private readonly string $bar, + private readonly array $items + ) { } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyFriend.php b/tests/Fixtures/TestBundle/Document/DummyFriend.php index 15c16f985a2..8590c3fd803 100644 --- a/tests/Fixtures/TestBundle/Document/DummyFriend.php +++ b/tests/Fixtures/TestBundle/Document/DummyFriend.php @@ -13,8 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -24,28 +25,24 @@ * * @author Kévin Dunglas * @author Alan Poulain - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class DummyFriend { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field(type="string") - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"fakemanytomany", "friends"}) */ - private $name; + #[Assert\NotBlank] + #[ApiProperty(types: ['http://schema.org/name'])] + #[Groups(['fakemanytomany', 'friends'])] + #[ODM\Field(type: 'string')] + private ?string $name = null; /** * Get id. diff --git a/tests/Fixtures/TestBundle/Document/DummyGroup.php b/tests/Fixtures/TestBundle/Document/DummyGroup.php index dd3690af07a..f5519375c42 100644 --- a/tests/Fixtures/TestBundle/Document/DummyGroup.php +++ b/tests/Fixtures/TestBundle/Document/DummyGroup.php @@ -13,7 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,76 +25,37 @@ * * @author Baptiste Meyer * @author Alan Poulain - * - * @ODM\Document - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}}, - * "filters"={ - * "dummy_group.group", - * "dummy_group.override_group", - * "dummy_group.whitelist_group", - * "dummy_group.override_whitelist_group" - * } - * }, - * graphql={ - * "item_query"={"normalization_context"={"groups"={"dummy_foo"}}}, - * "collection_query"={"normalization_context"={"groups"={"dummy_foo"}}}, - * "delete", - * "create"={ - * "normalization_context"={"groups"={"dummy_bar"}}, - * "denormalization_context"={"groups"={"dummy_bar", "dummy_baz"}} - * } - * } - * ) */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['dummy_foo']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['dummy_foo']]), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_bar']], denormalizationContext: ['groups' => ['dummy_bar', 'dummy_baz']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_group.group', 'dummy_group.override_group', 'dummy_group.whitelist_group', 'dummy_group.override_whitelist_group'])] +#[ODM\Document] class DummyGroup { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups({"dummy", "dummy_read", "dummy_id"}) - */ - private $id; - + #[Groups(['dummy', 'dummy_read', 'dummy_id'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null - * - * @ODM\Field(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_foo"}) */ + #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_foo'])] + #[ODM\Field(nullable: true)] public $foo; - /** * @var string|null - * - * @ODM\Field(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_bar"}) */ + #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_bar'])] + #[ODM\Field(nullable: true)] public $bar; - /** * @var string|null - * - * @ODM\Field(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_baz"}) */ + #[Groups(['dummy', 'dummy_read', 'dummy_baz'])] + #[ODM\Field(nullable: true)] public $baz; - /** * @var string|null - * - * @ODM\Field(nullable=true) - * - * @Groups({"dummy", "dummy_write", "dummy_qux"}) */ + #[Groups(['dummy', 'dummy_write', 'dummy_qux'])] + #[ODM\Field(nullable: true)] public $qux; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php b/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php index a46d64b3cbb..6219a76f4d8 100644 --- a/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php +++ b/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php @@ -13,32 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy Date Immutable. - * - * @ApiResource(attributes={ - * "filters"={"my_dummy_immutable_date.mongodb.date"} - * }) - * - * @ODM\Document */ +#[ApiResource(filters: ['my_dummy_immutable_date.mongodb.date'])] +#[ODM\Document] class DummyImmutableDate { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var \DateTimeImmutable The dummy date - * - * @ODM\Field(type="date_immutable") */ + #[ODM\Field(type: 'date_immutable')] public $dummyDate; /** diff --git a/tests/Fixtures/TestBundle/Document/DummyMercure.php b/tests/Fixtures/TestBundle/Document/DummyMercure.php index 728727a18c4..34cdbdfc55a 100644 --- a/tests/Fixtures/TestBundle/Document/DummyMercure.php +++ b/tests/Fixtures/TestBundle/Document/DummyMercure.php @@ -13,34 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ODM\Document - * @ApiResource(mercure=true) - * * @author Kévin Dunglas */ +#[ApiResource(mercure: true)] +#[ODM\Document] class DummyMercure { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $name; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $description; - - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) - */ + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummy; } diff --git a/tests/Fixtures/TestBundle/Document/DummyOffer.php b/tests/Fixtures/TestBundle/Document/DummyOffer.php index 6d9be6aa65c..fb5632a4994 100644 --- a/tests/Fixtures/TestBundle/Document/DummyOffer.php +++ b/tests/Fixtures/TestBundle/Document/DummyOffer.php @@ -13,40 +13,40 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy Offer. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_aggregate_offers/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class DummyOffer { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var int The dummy aggregate offer value - * - * @ODM\Field(type="int") */ - private $value; - + #[ODM\Field(type: 'int')] + private ?int $value = null; /** * @var DummyAggregateOffer The dummy aggregate offer value - * - * @ODM\ReferenceOne(targetDocument=DummyAggregateOffer::class, inversedBy="offers", storeAs="id") */ - private $aggregate; + #[ODM\ReferenceOne(targetDocument: DummyAggregateOffer::class, inversedBy: 'offers', storeAs: 'id')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer $aggregate = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/DummyPassenger.php b/tests/Fixtures/TestBundle/Document/DummyPassenger.php index f66c1a079ce..3cb272ad681 100644 --- a/tests/Fixtures/TestBundle/Document/DummyPassenger.php +++ b/tests/Fixtures/TestBundle/Document/DummyPassenger.php @@ -13,23 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class DummyPassenger { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $nickname; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyProduct.php b/tests/Fixtures/TestBundle/Document/DummyProduct.php index 7d5dc130b61..bf7b238135c 100644 --- a/tests/Fixtures/TestBundle/Document/DummyProduct.php +++ b/tests/Fixtures/TestBundle/Document/DummyProduct.php @@ -13,56 +13,40 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy Product. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class DummyProduct { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var Collection - * - * @ApiSubresource - * @ODM\ReferenceMany(targetDocument=DummyAggregateOffer::class, mappedBy="product", cascade={"persist"}) */ - private $offers; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\ReferenceMany(targetDocument: DummyAggregateOffer::class, mappedBy: 'product', cascade: ['persist'])] + private \Doctrine\Common\Collections\Collection $offers; /** * @var string The tour name - * - * @ODM\Field */ + #[ODM\Field] private $name; - - /** - * @var Collection - * - * @ApiSubresource - * @ODM\ReferenceMany(targetDocument=DummyProduct::class, mappedBy="parent") - */ - private $relatedProducts; - - /** - * @ODM\ReferenceOne(targetDocument=DummyProduct::class, inversedBy="relatedProducts") - */ + #[ODM\ReferenceMany(targetDocument: self::class, mappedBy: 'parent')] + private \Doctrine\Common\Collections\Collection $relatedProducts; + #[ODM\ReferenceOne(targetDocument: self::class, inversedBy: 'relatedProducts')] private $parent; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DummyProperty.php b/tests/Fixtures/TestBundle/Document/DummyProperty.php index c3803c0c0de..5d8732cda83 100644 --- a/tests/Fixtures/TestBundle/Document/DummyProperty.php +++ b/tests/Fixtures/TestBundle/Document/DummyProperty.php @@ -13,7 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,92 +24,49 @@ * DummyProperty. * * @author Baptiste Meyer - * - * @ODM\Document - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}}, - * "filters"={ - * "dummy_property.property", - * "dummy_property.whitelist_property", - * "dummy_property.whitelisted_properties" - * } - * }, - * graphql={ - * "item_query", - * "collection_query", - * "update", - * "delete", - * "create"={ - * "normalization_context"={"groups"={"dummy_graphql_read"}}, - * } - * } - * ) */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query'), new Mutation(name: 'update'), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_graphql_read']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_property.property', 'dummy_property.whitelist_property', 'dummy_property.whitelisted_properties'])] +#[ODM\Document] class DummyProperty { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups({"dummy_read", "dummy_graphql_read"}) - */ - private $id; - + #[Groups(['dummy_read', 'dummy_graphql_read'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null - * - * @ODM\Field(nullable=true) - * - * @Groups({"dummy_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_write'])] + #[ODM\Field(nullable: true)] public $foo; - /** * @var string|null - * - * @ODM\Field(nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] + #[ODM\Field(nullable: true)] public $bar; - /** * @var string|null - * - * @ODM\Field(nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] + #[ODM\Field(nullable: true)] public $baz; - /** * @var DummyGroup|null - * - * @ODM\ReferenceOne(targetDocument=DummyGroup::class, cascade={"persist"}, nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] + #[ODM\ReferenceOne(targetDocument: DummyGroup::class, cascade: ['persist'], nullable: true)] public $group; - /** * @var DummyGroup[]|null - * - * @ODM\ReferenceMany(targetDocument=DummyGroup::class, cascade={"persist"}) - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] + #[ODM\ReferenceMany(targetDocument: DummyGroup::class, cascade: ['persist'])] public $groups; - /** * @var string|null - * - * @ODM\Field(nullable=true) - * - * @Groups({"dummy_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_write'])] + #[ODM\Field(nullable: true)] public $nameConverted; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php index 4eaea82d145..2b32967280c 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php @@ -13,48 +13,31 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - * @ODM\InheritanceType("SINGLE_COLLECTION") - * @ODM\DiscriminatorField(value="discr") - * @ODM\DiscriminatorMap({ - * "dummyTableInheritance"=DummyTableInheritance::class, - * "dummyTableInheritanceChild"=DummyTableInheritanceChild::class, - * "dummyTableInheritanceDifferentChild"=DummyTableInheritanceDifferentChild::class, - * "dummyTableInheritanceNotApiResourceChild"=DummyTableInheritanceNotApiResourceChild::class - * }) - * @ApiResource - */ +#[ApiResource] +#[ODM\Document] +#[ODM\InheritanceType('SINGLE_COLLECTION')] +#[ODM\DiscriminatorField(value: 'discr')] +#[ODM\DiscriminatorMap(['dummyTableInheritance' => DummyTableInheritance::class, 'dummyTableInheritanceChild' => DummyTableInheritanceChild::class, 'dummyTableInheritanceDifferentChild' => DummyTableInheritanceDifferentChild::class, 'dummyTableInheritanceNotApiResourceChild' => DummyTableInheritanceNotApiResourceChild::class])] class DummyTableInheritance { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups({"default"}) */ - private $id; - + #[Groups(['default'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field - * - * @Groups({"default"}) - */ - private $name; - - /** - * @var DummyTableInheritanceRelated|null - * - * @ODM\ReferenceOne(targetDocument=DummyTableInheritanceRelated::class, inversedBy="children") */ - private $parent; + #[Groups(['default'])] + #[ODM\Field] + private ?string $name = null; + #[ODM\ReferenceOne(targetDocument: DummyTableInheritanceRelated::class, inversedBy: 'children')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyTableInheritanceRelated $parent = null; public function getName(): ?string { diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php index 775a9357903..874b2393a38 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php @@ -13,23 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - * @ApiResource - */ +#[ApiResource] +#[ODM\Document] class DummyTableInheritanceChild extends DummyTableInheritance { /** * @var string The dummy nickname - * - * @ODM\Field - * - * @Groups({"default"}) */ + #[Groups(['default'])] + #[ODM\Field] private $nickname; public function getNickname() diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php index b738bd28c53..58df7162ab6 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php @@ -13,23 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - * @ApiResource - */ +#[ApiResource] +#[ODM\Document] class DummyTableInheritanceDifferentChild extends DummyTableInheritance { /** * @var string The dummy email - * - * @ODM\Field - * - * @Groups({"default"}) */ + #[Groups(['default'])] + #[ODM\Field] private $email; public function getEmail() diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php index b0a65151c7c..b4616c4ad59 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php @@ -15,17 +15,14 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ +#[ODM\Document] class DummyTableInheritanceNotApiResourceChild extends DummyTableInheritance { /** * @var bool The dummy swagg - * - * @ODM\Field(type="bool") */ - private $swaggerThanParent; + #[ODM\Field(type: 'bool')] + private bool $swaggerThanParent; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php index 8ddf0f6714f..7741ee0e676 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php @@ -13,40 +13,28 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"default"}}, - * "denormalization_context"={"groups"={"default"}} - * } - * ) - */ +#[ApiResource(normalizationContext: ['groups' => ['default']], denormalizationContext: ['groups' => ['default']])] +#[ODM\Document] class DummyTableInheritanceRelated { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups({"default"}) */ - private $id; - + #[Groups(['default'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var Collection Related children - * - * @ODM\ReferenceMany(targetDocument=DummyTableInheritance::class, mappedBy="parent") - * - * @Groups({"default"}) */ - private $children; + #[Groups(['default'])] + #[ODM\ReferenceMany(targetDocument: DummyTableInheritance::class, mappedBy: 'parent')] + private \Doctrine\Common\Collections\Collection $children; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/DummyTravel.php b/tests/Fixtures/TestBundle/Document/DummyTravel.php index 6fd7e5bd85d..40affaca63d 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTravel.php +++ b/tests/Fixtures/TestBundle/Document/DummyTravel.php @@ -13,33 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource(filters={"dummy_travel.property"}) - * @ODM\Document - */ +#[ApiResource(filters: ['dummy_travel.property'])] +#[ODM\Document] class DummyTravel { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\ReferenceOne(targetDocument=DummyCar::class) - */ + #[ODM\ReferenceOne(targetDocument: DummyCar::class)] public $car; - - /** - * @ODM\Field(type="bool") - */ + #[ODM\Field(type: 'bool')] public $confirmed; - - /** - * @ODM\ReferenceOne(targetDocument=DummyPassenger::class) - */ + #[ODM\ReferenceOne(targetDocument: DummyPassenger::class)] public $passenger; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyValidation.php b/tests/Fixtures/TestBundle/Document/DummyValidation.php index d042da0c952..08848c1e793 100644 --- a/tests/Fixtures/TestBundle/Document/DummyValidation.php +++ b/tests/Fixtures/TestBundle/Document/DummyValidation.php @@ -13,51 +13,42 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ODM\Document - * @ApiResource( - * collectionOperations={ - * "get"={"method"="GET"}, - * "post"={"path"="dummy_validation.{_format}", "method"="POST"}, - * "post_validation_groups"={"route_name"="post_validation_groups", "validation_groups"={"a"}, "method"="GET"}, - * "post_validation_sequence"={"route_name"="post_validation_sequence", "validation_groups"="app.dummy_validation.group_generator", "method"="GET"} - * } - * ) - */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new Post(uriTemplate: 'dummy_validation.{_format}'), new GetCollection(routeName: 'post_validation_groups', validationContext: ['groups' => ['a']]), new GetCollection(routeName: 'post_validation_sequence', validationContext: ['groups' => 'app.dummy_validation.group_generator'])])] +#[ODM\Document] class DummyValidation { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field(nullable=true) - * @Assert\NotNull(groups={"a"}) */ - private $name; - + #[Assert\NotNull(groups: ['a'])] + #[ODM\Field(nullable: true)] + private ?string $name = null; /** * @var string|null The dummy title - * - * @ODM\Field(nullable=true) - * @Assert\NotNull(groups={"b"}) */ - private $title; - + #[Assert\NotNull(groups: ['b'])] + #[ODM\Field(nullable: true)] + private ?string $title = null; /** * @var string|null The dummy code - * @ODM\Field */ - private $code; + #[ODM\Field] + private ?string $code = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php b/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php index 60e40ae026e..26ea3405325 100644 --- a/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php +++ b/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php @@ -13,30 +13,25 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class DummyWithEmbedManyOmittingTargetDocument { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var EmbeddableDummy[]|Collection - * - * @ODM\EmbedMany */ - private $embeddedDummies; + #[ODM\EmbedMany] + private readonly array|\Doctrine\Common\Collections\Collection $embeddedDummies; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php b/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php index 180b6cf6fb9..8fba54a7a92 100644 --- a/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php +++ b/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php @@ -22,52 +22,39 @@ * * @author Jordan Samouh * @author Alexandre Delplace - * - * @ODM\EmbeddedDocument */ +#[ODM\EmbeddedDocument] class EmbeddableDummy { /** * @var string|null The dummy name - * - * @ODM\Field(type="string") - * @Groups({"embed"}) */ - private $dummyName; - + #[Groups(['embed'])] + #[ODM\Field(type: 'string')] + private ?string $dummyName = null; /** * @var bool|null A dummy boolean - * - * @ODM\Field(type="bool") */ + #[ODM\Field(type: 'bool')] public $dummyBoolean; - /** * @var \DateTime|null A dummy date - * - * @ODM\Field(type="date") - * @Assert\DateTime */ + #[Assert\DateTime] + #[ODM\Field(type: 'date')] public $dummyDate; - /** * @var float|null A dummy float - * - * @ODM\Field(type="float") */ + #[ODM\Field(type: 'float')] public $dummyFloat; - /** * @var float|null A dummy price - * - * @ODM\Field(type="float") */ + #[ODM\Field(type: 'float')] public $dummyPrice; - - /** - * @ODM\Field(type="string") - * @Groups({"barcelona", "chicago"}) - */ + #[Groups(['barcelona', 'chicago'])] + #[ODM\Field(type: 'string')] protected $symfony; public static function staticMethod(): void diff --git a/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php b/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php index bb81f658554..69ed9ee5c41 100644 --- a/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php +++ b/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,51 +28,38 @@ * * @author Jordan Samouh * @author Alexandre Delplace - * - * @ApiResource( - * attributes={"filters"={"my_dummy.mongodb.search", "my_dummy.mongodb.order", "my_dummy.mongodb.date", "my_dummy.mongodb.boolean"}}, - * itemOperations={"get", "put", "delete", "groups"={"method"="GET", "path"="/embedded_dummies_groups/{id}", "normalization_context"={"groups"={"embed"}}}} - * ) - * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(uriTemplate: '/embedded_dummies_groups/{id}', normalizationContext: ['groups' => ['embed']]), new Post(), new GetCollection()], filters: ['my_dummy.mongodb.search', 'my_dummy.mongodb.order', 'my_dummy.mongodb.date', 'my_dummy.mongodb.boolean'])] +#[ODM\Document] class EmbeddedDummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field(type="string") - * @Groups({"embed"}) */ - private $name; - + #[Groups(['embed'])] + #[ODM\Field(type: 'string')] + private ?string $name = null; /** * @var \DateTime|null A dummy date - * - * @ODM\Field(type="date") - * @Assert\DateTime */ + #[Assert\DateTime] + #[ODM\Field(type: 'date')] public $dummyDate; - /** * @var EmbeddableDummy - * - * @ODM\EmbedOne(targetDocument=EmbeddableDummy::class) - * @Groups({"embed"}) */ + #[Groups(['embed'])] + #[ODM\EmbedOne(targetDocument: EmbeddableDummy::class)] public $embeddedDummy; - /** * @var RelatedDummy|null A related dummy - * - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, storeAs: 'id')] public $relatedDummy; public static function staticMethod(): void diff --git a/tests/Fixtures/TestBundle/Document/Employee.php b/tests/Fixtures/TestBundle/Document/Employee.php index 3ca2d5a499c..ed6ff6f4412 100644 --- a/tests/Fixtures/TestBundle/Document/Employee.php +++ b/tests/Fixtures/TestBundle/Document/Employee.php @@ -19,36 +19,31 @@ use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] #[Post] #[ApiResource(uriTemplate: '/companies/{companyId}/employees/{id}', uriVariables: ['companyId' => ['from_class' => Company::class, 'to_property' => 'company'], 'id' => ['from_class' => Employee::class]])] #[Get] #[ApiResource(uriTemplate: '/companies/{companyId}/employees', uriVariables: ['companyId' => ['from_class' => Company::class, 'to_property' => 'company']])] #[GetCollection] +#[ODM\Document] class Employee { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] public $name; /** * @var ?Company - * - * @ODM\ReferenceOne(targetDocument=Company::class, storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: Company::class, storeAs: 'id')] public $company; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Field.php b/tests/Fixtures/TestBundle/Document/Field.php index c9206c41f37..d7333885294 100644 --- a/tests/Fixtures/TestBundle/Document/Field.php +++ b/tests/Fixtures/TestBundle/Document/Field.php @@ -15,38 +15,17 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ +#[ODM\Document] class Field implements \JsonSerializable { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var Content|null - * - * @ODM\ReferenceOne(targetDocument=Content::class, inversedBy="fields") - */ - private $content; - - /** - * @var string|null - * - * @ODM\Field(type="string") - */ - private $name; - - /** - * @var string|null - * - * @ODM\Field(type="string") - */ - private $value; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\ReferenceOne(targetDocument: Content::class, inversedBy: 'fields')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\Content $content = null; + #[ODM\Field(type: 'string')] + private ?string $name = null; + #[ODM\Field(type: 'string')] + private ?string $value = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/FileConfigDummy.php b/tests/Fixtures/TestBundle/Document/FileConfigDummy.php index fa70962cdb2..88d6ddfa37b 100644 --- a/tests/Fixtures/TestBundle/Document/FileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Document/FileConfigDummy.php @@ -17,32 +17,25 @@ /** * File Config Dummy. - * - * @ODM\Document */ +#[ODM\Document] class FileConfigDummy { - public const HYDRA_TITLE = 'File config Dummy'; - + final public const HYDRA_TITLE = 'File config Dummy'; /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] private $name; - /** * @var string - * - * @ODM\Field */ + #[ODM\Field] private $foo; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/FilterValidator.php b/tests/Fixtures/TestBundle/Document/FilterValidator.php index 8977d654295..602f13a27fd 100644 --- a/tests/Fixtures/TestBundle/Document/FilterValidator.php +++ b/tests/Fixtures/TestBundle/Document/FilterValidator.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayItemsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\BoundsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\EnumFilter; @@ -30,36 +30,22 @@ * * @author Julien Deniau * @author Alan Poulain - * - * @ApiResource(attributes={ - * "filters"={ - * ArrayItemsFilter::class, - * BoundsFilter::class, - * EnumFilter::class, - * LengthFilter::class, - * MultipleOfFilter::class, - * PatternFilter::class, - * RequiredFilter::class, - * RequiredAllowEmptyFilter::class - * } - * }) - * @ODM\Document */ +#[ApiResource(filters: [ArrayItemsFilter::class, BoundsFilter::class, EnumFilter::class, LengthFilter::class, MultipleOfFilter::class, PatternFilter::class, RequiredFilter::class, RequiredAllowEmptyFilter::class])] +#[ODM\Document] class FilterValidator { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string A name - * - * @ODM\Field - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Foo.php b/tests/Fixtures/TestBundle/Document/Foo.php index a514338d251..36108d02506 100644 --- a/tests/Fixtures/TestBundle/Document/Foo.php +++ b/tests/Fixtures/TestBundle/Document/Foo.php @@ -13,53 +13,40 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Foo. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={ - * "order"={"bar", "name"="DESC"} - * }, - * graphql={ - * "item_query", - * "collection_query"={"pagination_enabled"=false}, - * "create", - * "delete" - * }, - * collectionOperations={ - * "get", - * "get_desc_custom"={"method"="GET", "path"="custom_collection_desc_foos", "order"={"name"="DESC"}}, - * "get_asc_custom"={"method"="GET", "path"="custom_collection_asc_foos", "order"={ "name"="ASC"}}, - * } - * ) - * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new GetCollection(uriTemplate: 'custom_collection_desc_foos', order: ['name' => 'DESC']), new GetCollection(uriTemplate: 'custom_collection_asc_foos', order: ['name' => 'ASC'])], graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query', paginationEnabled: false), new Mutation(name: 'create'), new Mutation(name: 'delete')], order: ['bar', 'name' => 'DESC'])] +#[ODM\Document] class Foo { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The foo name - * - * @ODM\Field */ + #[ODM\Field] private $name; - /** * @var string The foo bar - * - * @ODM\Field */ + #[ODM\Field] private $bar; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/FooDummy.php b/tests/Fixtures/TestBundle/Document/FooDummy.php index 745ec75903f..edcc63e56bb 100644 --- a/tests/Fixtures/TestBundle/Document/FooDummy.php +++ b/tests/Fixtures/TestBundle/Document/FooDummy.php @@ -13,46 +13,34 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * FooDummy. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={ - * "order"={"dummy.name"} - * }, - * graphql={ - * "collection_query"={"pagination_type"="page"} - * } - * ) - * @ODM\Document */ +#[ApiResource(graphQlOperations: [new QueryCollection(name: 'collection_query', paginationType: 'page')], order: ['dummy.name'])] +#[ODM\Document] class FooDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The foo name - * - * @ODM\Field */ + #[ODM\Field] private $name; - /** * @var Dummy The foo dummy - * - * @ODM\ReferenceOne(targetDocument=Dummy::class, cascade={"persist"}, storeAs="id") */ - private $dummy; + #[ODM\ReferenceOne(targetDocument: Dummy::class, cascade: ['persist'], storeAs: 'id')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy $dummy = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/FourthLevel.php b/tests/Fixtures/TestBundle/Document/FourthLevel.php index 4d98d78339d..ac52e1956c1 100644 --- a/tests/Fixtures/TestBundle/Document/FourthLevel.php +++ b/tests/Fixtures/TestBundle/Document/FourthLevel.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,30 +23,26 @@ * Fourth Level. * * @author Alan Poulain - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/third_levels/{id}/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: ['id'], fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ODM\Document] class FourthLevel { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var int|null - * - * @ODM\Field(type="int") - * @Groups({"barcelona", "chicago"}) - */ - private $level = 4; - - /** - * @ODM\ReferenceMany(targetDocument=ThirdLevel::class, cascade={"persist"}, mappedBy="badFourthLevel", storeAs="id") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[Groups(['barcelona', 'chicago'])] + #[ODM\Field(type: 'int')] + private ?int $level = 4; + #[ODM\ReferenceMany(targetDocument: ThirdLevel::class, cascade: ['persist'], mappedBy: 'badFourthLevel', storeAs: 'id')] public $badThirdLevel; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/Greeting.php b/tests/Fixtures/TestBundle/Document/Greeting.php index 06b347281a4..5e17a4bf7e7 100644 --- a/tests/Fixtures/TestBundle/Document/Greeting.php +++ b/tests/Fixtures/TestBundle/Document/Greeting.php @@ -13,33 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ApiResource(uriTemplate: '/people/{id}/sent_greetings.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Person::class, identifiers: ['id'], toProperty: 'sender')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class Greeting { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field - */ + #[ODM\Field] public $message = ''; - - /** - * @ODM\ReferenceOne(targetDocument=Person::class, inversedBy="sentGreetings", storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: Person::class, inversedBy: 'sentGreetings', storeAs: 'id')] public $sender; - - /** - * @ODM\ReferenceOne(targetDocument=Person::class) - */ + #[ODM\ReferenceOne(targetDocument: Person::class)] public $recipient; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/InitializeInput.php b/tests/Fixtures/TestBundle/Document/InitializeInput.php index 5b289212c74..903067842fa 100644 --- a/tests/Fixtures/TestBundle/Document/InitializeInput.php +++ b/tests/Fixtures/TestBundle/Document/InitializeInput.php @@ -13,28 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InitializeInputDto; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource(input=InitializeInputDto::class) - * @ODM\Document - */ +#[ApiResource(input: InitializeInputDto::class)] +#[ODM\Document] class InitializeInput { - /** - * @ODM\Id(strategy="NONE", type="int") - */ + #[ODM\Id(strategy: 'NONE', type: 'int')] public $id; - - /** - * @ODM\Field - */ + #[ODM\Field] public $manager; - - /** - * @ODM\Field - */ + #[ODM\Field] public $name; } diff --git a/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php b/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php index 7ace4cfc07b..a36a4e394a1 100644 --- a/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php +++ b/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php @@ -13,37 +13,25 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy with iri_only. * * @author Pierre Thibaudeau - * - * @ApiResource( - * normalizationContext={ - * "iri_only"=true, - * "jsonld_embed_context"=true - * } - * ) - * @ODM\Document */ +#[ApiResource(normalizationContext: ['iri_only' => true, 'jsonld_embed_context' => true])] +#[ODM\Document] class IriOnlyDummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var string|null - * - * @ODM\Field(type="string") */ - private $foo; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field(type: 'string')] + private ?string $foo = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php b/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php index 4e2085fcd04..ac2b6828a45 100644 --- a/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php +++ b/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php @@ -13,39 +13,30 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Jsonld Context Dummy. - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class JsonldContextDummy { /** * @var int The id - * - * @ApiProperty(identifier=true) - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ApiProperty(identifier: true)] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The dummy person - * - * @ApiProperty( - * attributes={ - * "jsonld_context"={ - * "@id"="http://example.com/id", - * "@type"="@id", - * "foo"="bar" - * } - * }, - * ) */ + #[ApiProperty( + jsonldContext: ['@id' => 'https://example.com/id', '@type' => '@id', 'foo' => 'bar'] + )] private $person; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php b/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php index 0392dc42137..45a3ae6f2f1 100644 --- a/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php @@ -13,7 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; @@ -21,57 +27,30 @@ * Secured resource with legacy access_control attribute. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={"access_control"="is_granted('ROLE_USER')"}, - * collectionOperations={ - * "get", - * "post"={"access_control"="is_granted('ROLE_ADMIN')"} - * }, - * itemOperations={ - * "get"={"access_control"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "put"={"access_control"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * }, - * graphql={ - * "item_query"={"access_control"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "delete"={}, - * "update"={"access_control"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * "create"={"access_control"="is_granted('ROLE_ADMIN')", "access_control_message"="Only admins can create a secured dummy."} - * } - * ) - * @ODM\Document */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Mutation(name: 'delete'), new Mutation(name: 'update', security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] +#[ODM\Document] class LegacySecuredDummy { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null The title - * - * @ODM\Field - * @Assert\NotBlank */ - private $title; - + #[Assert\NotBlank] + #[ODM\Field] + private ?string $title = null; /** * @var string The description - * - * @ODM\Field */ - private $description = ''; - + #[ODM\Field] + private string $description = ''; /** * @var string|null The owner - * - * @ODM\Field - * @Assert\NotBlank */ - private $owner; + #[Assert\NotBlank] + #[ODM\Field] + private ?string $owner = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php b/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php index 079c43c18a1..9b6d6251df2 100644 --- a/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php +++ b/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php @@ -13,39 +13,30 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\MaxDepth; -/** * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"default"}, "enable_max_depth"=true}, - * "denormalization_context"={"groups"={"default"}, "enable_max_depth"=true} - * }) - * @ODM\Document +/** + * * + * * * @author Brian Fox */ +#[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] +#[ODM\Document] class MaxDepthDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(name="name", type="string") - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\Field(name: 'name', type: 'string')] public $name; - - /** - * @ODM\ReferenceOne(targetDocument=MaxDepthDummy::class, cascade={"persist"}) - * @Groups({"default"}) - * @MaxDepth(1) - */ + #[Groups(['default'])] + #[MaxDepth(1)] + #[ODM\ReferenceOne(targetDocument: self::class, cascade: ['persist'])] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php b/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php index f401a1ef6f9..9f71f094a70 100644 --- a/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php +++ b/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php @@ -13,39 +13,30 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\MaxDepth; -/** * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"default"}, "enable_max_depth"=true}, - * "denormalization_context"={"groups"={"default"}, "enable_max_depth"=true} - * }) - * @ODM\Document +/** + * * + * * * @author Brian Fox */ +#[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] +#[ODM\Document] class MaxDepthEagerDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(name="name", type="string") - * @Groups({"default"}) - */ + #[Groups(['default'])] + #[ODM\Field(name: 'name', type: 'string')] public $name; - - /** - * @ODM\ReferenceOne(targetDocument=MaxDepthEagerDummy::class, cascade={"persist"}) - * @Groups({"default"}) - * @MaxDepth(1) - */ + #[Groups(['default'])] + #[MaxDepth(1)] + #[ODM\ReferenceOne(targetDocument: self::class, cascade: ['persist'])] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/MessengerWithInput.php b/tests/Fixtures/TestBundle/Document/MessengerWithInput.php index eb61a226990..09f87095566 100644 --- a/tests/Fixtures/TestBundle/Document/MessengerWithInput.php +++ b/tests/Fixtures/TestBundle/Document/MessengerWithInput.php @@ -13,21 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Symfony\Messenger\Processor; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MessengerInput; -/** - * @ApiResource(messenger="input", input=MessengerInput::class, graphql={"create"={"input"=MessengerInput::class, "messenger"="input"}}) - */ +#[ApiResource( + graphQlOperations: [new Mutation(name: 'create', input: MessengerInput::class, processor: Processor::class)], + processor: Processor::class, + input: MessengerInput::class +)] class MessengerWithInput { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public $id; - /** - * @var string - */ - public $name; + + public string $name; } diff --git a/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php b/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php index 42bc81c93b4..4ad7520872a 100644 --- a/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php +++ b/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php @@ -14,23 +14,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::NET_PATH) - * @ODM\Document - */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] +#[ApiResource(uriTemplate: '/network_path_relation_dummies/{id}/network_path_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\NetworkPathRelationDummy::class, identifiers: ['id'], toProperty: 'networkPathRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::NET_PATH, operations: [new GetCollection()])] +#[ODM\Document] class NetworkPathDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\ReferenceOne(targetDocument=NetworkPathRelationDummy::class, inversedBy="networkPathDummies", storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: NetworkPathRelationDummy::class, inversedBy: 'networkPathDummies', storeAs: 'id')] public $networkPathRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php b/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php index f760fcb0427..7335610f5d8 100644 --- a/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php +++ b/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php @@ -14,26 +14,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::NET_PATH) - * @ODM\Document - */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] +#[ODM\Document] class NetworkPathRelationDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\ReferenceMany(targetDocument=NetworkPathDummy::class, mappedBy="networkPathRelationDummy") - * @ApiSubresource - */ + #[ODM\ReferenceMany(targetDocument: NetworkPathDummy::class, mappedBy: 'networkPathRelationDummy')] public $networkPathDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php b/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php index b0dd85e1130..6344b9c3132 100644 --- a/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php +++ b/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php @@ -13,23 +13,25 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * No Collection Dummy. - * - * @ApiResource(collectionOperations={}) - * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete()])] +#[ODM\Document] class NoCollectionDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/Order.php b/tests/Fixtures/TestBundle/Document/Order.php index 15d4b02d990..a2b20778504 100644 --- a/tests/Fixtures/TestBundle/Document/Order.php +++ b/tests/Fixtures/TestBundle/Document/Order.php @@ -13,39 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource( - * attributes={"normalization_context"={"groups"={"order_read"}}}, - * forceEager=false - * ) - * @ODM\Document - */ +#[ApiResource(normalizationContext: ['groups' => ['order_read']], forceEager: false)] +#[ODM\Document] class Order { - /** - * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"order_read"}) - */ - private $id; - - /** - * @ODM\ReferenceOne(targetDocument=Customer::class) - * @Groups({"order_read"}) - */ + #[Groups(['order_read'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[Groups(['order_read'])] + #[ODM\ReferenceOne(targetDocument: Customer::class)] public $customer; - - /** - * @ODM\ReferenceOne(targetDocument=Customer::class) - * @Assert\NotNull - * @Groups({"order_read"}) - */ + #[Assert\NotNull] + #[Groups(['order_read'])] + #[ODM\ReferenceOne(targetDocument: Customer::class)] public $recipient; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php b/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php index eee6a993ce2..399919077d4 100644 --- a/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php +++ b/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php @@ -13,8 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,80 +28,44 @@ * Overridden Operation Dummy. * * @author Amrouche Hamza - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"overridden_operation_dummy_read"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_write"}} - * }, - * collectionOperations={ - * "get"={"method"="GET"}, - * "post"={"method"="POST"}, - * "swagger"={ - * "path"="/override/swagger", - * "method"="GET", - * } - * }, - * itemOperations={ - * "swagger"={ - * "method"="GET", - * }, - * "get"={ - * "method"="GET", - * "normalization_context"={"groups"={"overridden_operation_dummy_get"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_get"}} - * }, - * "put"={ - * "method"="PUT", - * "normalization_context"={"groups"={"overridden_operation_dummy_put"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_put"}} - * }, - * "delete"={"method"="DELETE"} - * } - * ) - * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Get(normalizationContext: ['groups' => ['overridden_operation_dummy_get']], denormalizationContext: ['groups' => ['overridden_operation_dummy_get']]), new Put(normalizationContext: ['groups' => ['overridden_operation_dummy_put']], denormalizationContext: ['groups' => ['overridden_operation_dummy_put']]), new Delete(), new GetCollection(), new Post(), new GetCollection(uriTemplate: '/override/swagger')], normalizationContext: ['groups' => ['overridden_operation_dummy_read']], denormalizationContext: ['groups' => ['overridden_operation_dummy_write']])] +#[ODM\Document] class OverriddenOperationDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The dummy name - * - * @ODM\Field - * @Assert\NotBlank - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_write", "overridden_operation_dummy_get"}) - * @ApiProperty(iri="http://schema.org/name") */ + #[Assert\NotBlank] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get'])] + #[ApiProperty(types: ['http://schema.org/name'])] + #[ODM\Field] private $name; /** * @var string The dummy name alias - * - * @ODM\Field(nullable=true) - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_put", "overridden_operation_dummy_get"}) - * @ApiProperty(iri="https://schema.org/alternateName") */ + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_put', 'overridden_operation_dummy_get'])] + #[ODM\Field(nullable: true)] private $alias; /** * @var string A short description of the item - * - * @ODM\Field(nullable=true) - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_write", "overridden_operation_dummy_get", "overridden_operation_dummy_put"}) - * @ApiProperty(iri="https://schema.org/description") */ + #[ApiProperty(types: ['http://schema.org/description'])] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get', 'overridden_operation_dummy_put'])] + #[ODM\Field(nullable: true)] public $description; - /** - * @ODM\Field(nullable=true) - * @Groups({"overridden_operation_dummy_write"}) - */ + #[Groups(['overridden_operation_dummy_write'])] + #[ODM\Field(nullable: true)] public $notGettable; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ParentDummy.php b/tests/Fixtures/TestBundle/Document/ParentDummy.php index 8ed02ecba9c..09f6569cf11 100644 --- a/tests/Fixtures/TestBundle/Document/ParentDummy.php +++ b/tests/Fixtures/TestBundle/Document/ParentDummy.php @@ -21,17 +21,15 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * - * @ODM\MappedSuperclass */ +#[ODM\MappedSuperclass] class ParentDummy { /** * @var int The age - * - * @ODM\Field(type="int", nullable=true) - * @Groups({"friends"}) */ + #[Groups(['friends'])] + #[ODM\Field(type: 'int', nullable: true)] private $age; public function getAge() diff --git a/tests/Fixtures/TestBundle/Document/PatchDummy.php b/tests/Fixtures/TestBundle/Document/PatchDummy.php index 8a42bef9070..b86e852b60f 100644 --- a/tests/Fixtures/TestBundle/Document/PatchDummy.php +++ b/tests/Fixtures/TestBundle/Document/PatchDummy.php @@ -13,29 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @author Kévin Dunglas - * - * @ApiResource( - * itemOperations={ - * "get", - * "patch"={"input_formats"={"json"={"application/merge-patch+json"}, "jsonapi"}} - * } - * ) - * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()])] +#[ODM\Document] class PatchDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $name; } diff --git a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php index c2decdcf666..ae5a9b477b1 100644 --- a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php @@ -13,36 +13,25 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * @author Kévin Dunglas - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"chicago"}}, - * "denormalization_context"={"groups"={"chicago"}}, - * }, - * itemOperations={ - * "get", - * "patch"={"input_formats"={"json"={"application/merge-patch+json"}, "jsonapi"}} - * } - * ) - * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] +#[ODM\Document] class PatchDummyRelation { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class) - * @Groups({"chicago"}) - */ + #[Groups(['chicago'])] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class)] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Document/Payment.php b/tests/Fixtures/TestBundle/Document/Payment.php index 83ef5f839bc..c5e24d41006 100644 --- a/tests/Fixtures/TestBundle/Document/Payment.php +++ b/tests/Fixtures/TestBundle/Document/Payment.php @@ -13,47 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\Payment\VoidPaymentAction; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - * - * @ApiResource( - * itemOperations={ - * "get", - * "post_void"={ - * "method"="POST", - * "path"="/payments/{id}/void", - * "controller"=VoidPaymentAction::class, - * "deserialize"=false, - * }, - * }, - * ) - */ +#[ApiResource(operations: [new Get(), new Post(uriTemplate: '/payments/{id}/void', controller: VoidPaymentAction::class, deserialize: false), new Post(), new GetCollection()])] +#[ODM\Document] class Payment { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var string|null - */ - private $amount; - - /** - * @ODM\ReferenceOne(targetDocument=VoidPayment::class, mappedBy="payment") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\ReferenceOne(targetDocument: VoidPayment::class, mappedBy: 'payment')] private $voidPayment; - public function __construct(string $amount) + public function __construct(private readonly ?string $amount) { - $this->amount = $amount; } public function getId(): ?int @@ -71,7 +48,6 @@ public function void(): void if (null !== $this->voidPayment) { return; } - $this->voidPayment = new VoidPayment($this); } diff --git a/tests/Fixtures/TestBundle/Document/Person.php b/tests/Fixtures/TestBundle/Document/Person.php index 873fb23df97..b3de016d6e4 100644 --- a/tests/Fixtures/TestBundle/Document/Person.php +++ b/tests/Fixtures/TestBundle/Document/Person.php @@ -13,8 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -23,35 +22,23 @@ * Person. * * @author Antoine Bluchet - * - * @ApiResource(attributes={"normalization_context"={"groups"={"people.pets"}}}) - * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['people.pets']])] +#[ODM\Document] class Person { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string") - * @Groups({"people.pets"}) - */ + #[Groups(['people.pets'])] + #[ODM\Field(type: 'string')] public $name; - /** - * @ODM\ReferenceMany(targetDocument=PersonToPet::class, mappedBy="person") - * @Groups({"people.pets"}) - * * @var ArrayCollection */ + #[Groups(['people.pets'])] + #[ODM\ReferenceMany(targetDocument: PersonToPet::class, mappedBy: 'person')] public $pets; - - /** - * @ApiSubresource - * @ODM\ReferenceMany(targetDocument=Greeting::class, mappedBy="sender") - */ + #[ODM\ReferenceMany(targetDocument: Greeting::class, mappedBy: 'sender')] public $sentGreetings; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/PersonToPet.php b/tests/Fixtures/TestBundle/Document/PersonToPet.php index 9e7cc7490cf..819221e7d82 100644 --- a/tests/Fixtures/TestBundle/Document/PersonToPet.php +++ b/tests/Fixtures/TestBundle/Document/PersonToPet.php @@ -20,28 +20,22 @@ * PersonToPet. * * @author Antoine Bluchet - * @ODM\Document */ +#[ODM\Document] class PersonToPet { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\ReferenceOne(targetDocument=Pet::class) - * @Groups({"people.pets"}) - * * @var Pet */ + #[Groups(['people.pets'])] + #[ODM\ReferenceOne(targetDocument: Pet::class)] public $pet; - /** - * @ODM\ReferenceOne(targetDocument=Person::class) - * * @var Person */ + #[ODM\ReferenceOne(targetDocument: Person::class)] public $person; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Pet.php b/tests/Fixtures/TestBundle/Document/Pet.php index 248d5d3738c..9e73c844cd4 100644 --- a/tests/Fixtures/TestBundle/Document/Pet.php +++ b/tests/Fixtures/TestBundle/Document/Pet.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,28 +22,20 @@ * Pet. * * @author Antoine Bluchet - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class Pet { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string") - * @Groups({"people.pets"}) - */ + #[Groups(['people.pets'])] + #[ODM\Field(type: 'string')] public $name; - /** - * @ODM\ReferenceMany(targetDocument=PersonToPet::class, mappedBy="pet") - * * @var ArrayCollection */ + #[ODM\ReferenceMany(targetDocument: PersonToPet::class, mappedBy: 'pet')] public $people; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/ProcessorEntity.php b/tests/Fixtures/TestBundle/Document/ProcessorEntity.php index 4b56e753d6c..bfb3046b31e 100644 --- a/tests/Fixtures/TestBundle/Document/ProcessorEntity.php +++ b/tests/Fixtures/TestBundle/Document/ProcessorEntity.php @@ -21,28 +21,19 @@ /** * ProcessorEntity. - * - * @ODM\Document */ #[ApiResource] #[Get] #[Post] +#[ODM\Document] class ProcessorEntity { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; - /** - * @var string - * - * @ODM\Field - * @Assert\NotBlank - */ - private $foo; + #[Assert\NotBlank] + #[ODM\Field] + private ?string $foo = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Document/Product.php b/tests/Fixtures/TestBundle/Document/Product.php index d242787b045..60c9bd18a19 100644 --- a/tests/Fixtures/TestBundle/Document/Product.php +++ b/tests/Fixtures/TestBundle/Document/Product.php @@ -17,31 +17,15 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ +#[ODM\Document] class Product implements ProductInterface { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var string|null - * - * @ODM\Field(type="string") - */ - private $code; - - /** - * @var Taxon|null - * - * @ODM\ReferenceOne(targetDocument=Taxon::class) - */ - private $mainTaxon; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field(type: 'string')] + private ?string $code = null; + #[ODM\ReferenceOne(targetDocument: Taxon::class)] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\Taxon $mainTaxon = null; /** * {@inheritdoc} diff --git a/tests/Fixtures/TestBundle/Document/Program.php b/tests/Fixtures/TestBundle/Document/Program.php index 6d69b40b763..3a681aedda5 100644 --- a/tests/Fixtures/TestBundle/Document/Program.php +++ b/tests/Fixtures/TestBundle/Document/Program.php @@ -17,29 +17,17 @@ /** * @author Vincent Chalamon - * - * @ODM\Document */ +#[ODM\Document] class Program { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $name; - - /** - * @ODM\Field(type="date") - */ + #[ODM\Field(type: 'date')] public $date; - - /** - * @ODM\ReferenceOne(targetDocument=User::class, storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: User::class, storeAs: 'id')] public $author; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ProviderEntity.php b/tests/Fixtures/TestBundle/Document/ProviderEntity.php index bd4063fbf63..cca5a15a781 100644 --- a/tests/Fixtures/TestBundle/Document/ProviderEntity.php +++ b/tests/Fixtures/TestBundle/Document/ProviderEntity.php @@ -22,29 +22,20 @@ /** * ProviderEntity. - * - * @ODM\Document */ #[ApiResource] #[Get] #[GetCollection] #[Post] +#[ODM\Document] class ProviderEntity { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; - /** - * @var string - * - * @ODM\Field - * @Assert\NotBlank - */ - private $foo; + #[Assert\NotBlank] + #[ODM\Field] + private ?string $foo = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Document/Question.php b/tests/Fixtures/TestBundle/Document/Question.php index 730749e4db7..91bb15c207f 100644 --- a/tests/Fixtures/TestBundle/Document/Question.php +++ b/tests/Fixtures/TestBundle/Document/Question.php @@ -13,30 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - * @ApiResource - */ +#[ApiResource] +#[ApiResource(uriTemplate: '/answers/{id}/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Answer::class, identifiers: ['id'], toProperty: 'answer')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/questions/{id}/answer/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], fromProperty: 'answer'), 'answer' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Answer::class, identifiers: [], expandedValue: 'answer', toProperty: 'answer')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class Question { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(nullable=true) - */ + #[ODM\Field(nullable: true)] private $content; - - /** - * @ODM\ReferenceOne(targetDocument=Answer::class, inversedBy="question", storeAs="id") - * @ApiSubresource - */ + #[ODM\ReferenceOne(targetDocument: Answer::class, inversedBy: 'question', storeAs: 'id')] private $answer; /** diff --git a/tests/Fixtures/TestBundle/Document/RPC.php b/tests/Fixtures/TestBundle/Document/RPC.php index dbb93ab1606..d8767deb383 100644 --- a/tests/Fixtures/TestBundle/Document/RPC.php +++ b/tests/Fixtures/TestBundle/Document/RPC.php @@ -13,20 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RPCOutput; /** * RPC-like resource. - * - * @ApiResource( - * itemOperations={}, - * collectionOperations={ - * "post"={"status"=202, "messenger"=true, "path"="rpc", "output"=false}, - * "post_output"={"method"="POST", "status"=200, "path"="rpc_output", "output"=RPCOutput::class} - * }, - * ) */ +#[ApiResource(operations: [new Post(status: 202, messenger: true, uriTemplate: 'rpc', output: false), new Post(status: 200, uriTemplate: 'rpc_output', output: RPCOutput::class)])] class RPC { /** diff --git a/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php b/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php index d2e2164ad8f..d42e588e879 100644 --- a/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php +++ b/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php @@ -13,30 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class ReadableOnlyProperty { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The foo name - * - * @ODM\Field - * @ApiProperty(writable=false) */ - private $name; + #[ApiProperty(writable: false)] + #[ODM\Field] + private readonly string $name; public function __construct() { @@ -48,7 +44,7 @@ public function getId() return $this->id; } - public function setName($name) + public function setName($name): never { throw new \Exception('Can not write name.'); } diff --git a/tests/Fixtures/TestBundle/Document/RelatedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedDummy.php index eb85808f17c..f23f6ac1fb9 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedDummy.php @@ -13,9 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -27,71 +31,55 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * - * @ApiResource(graphql={"item_query", "update"={"normalization_context"={"groups"={"chicago", "fakemanytomany"}}, "denormalization_context"={"groups"={"friends"}}}}, iri="https://schema.org/Product", attributes={"normalization_context"={"groups"={"friends"}}, "filters"={"related_dummy.mongodb.friends"}}) - * @ODM\Document */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']])], types: ['https://schema.org/Product'], normalizationContext: ['groups' => ['friends']], filters: ['related_dummy.mongodb.friends'])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ODM\Document] class RelatedDummy extends ParentDummy { - /** - * @ApiProperty(writable=false) - * @ApiSubresource - * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"chicago", "friends"}) - */ + #[Groups(['chicago', 'friends'])] + #[ApiProperty(writable: false)] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** * @var string A name - * - * @ODM\Field(type="string", nullable=true) - * @Groups({"friends"}) */ + #[Groups(['friends'])] + #[ODM\Field(type: 'string', nullable: true)] public $name; - - /** - * @ODM\Field(type="string") - * @Groups({"barcelona", "chicago", "friends"}) - */ + #[Groups(['barcelona', 'chicago', 'friends'])] + #[ODM\Field(type: 'string')] protected $symfony = 'symfony'; - /** * @var \DateTime A dummy date - * - * @ODM\Field(type="date", nullable=true) - * @Assert\DateTime - * @Groups({"friends"}) */ + #[Assert\DateTime] + #[Groups(['friends'])] + #[ODM\Field(type: 'date', nullable: true)] public $dummyDate; - - /** - * @ApiSubresource - * @ODM\ReferenceOne(targetDocument=ThirdLevel::class, cascade={"persist"}, nullable=true, storeAs="id") - * @Groups({"barcelona", "chicago", "friends"}) - */ + #[Groups(['barcelona', 'chicago', 'friends'])] + #[ODM\ReferenceOne(targetDocument: ThirdLevel::class, cascade: ['persist'], nullable: true, storeAs: 'id')] public $thirdLevel; - - /** - * @ApiSubresource - * @ODM\ReferenceMany(targetDocument=RelatedToDummyFriend::class, cascade={"persist"}, mappedBy="relatedDummy", storeAs="id") - * @Groups({"fakemanytomany", "friends"}) - */ + #[Groups(['fakemanytomany', 'friends'])] + #[ODM\ReferenceMany(targetDocument: RelatedToDummyFriend::class, cascade: ['persist'], mappedBy: 'relatedDummy', storeAs: 'id')] public $relatedToDummyFriend; - /** * @var bool A dummy bool - * - * @ODM\Field(type="bool") - * @Groups({"friends"}) */ + #[Groups(['friends'])] + #[ODM\Field(type: 'bool')] public $dummyBoolean; - /** * @var EmbeddableDummy - * - * @ODM\EmbedOne(targetDocument=EmbeddableDummy::class) - * @Groups({"friends"}) */ + #[Groups(['friends'])] + #[ODM\EmbedOne(targetDocument: EmbeddableDummy::class)] public $embeddedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php index 61036cf30ee..a9ff3629cd9 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -25,39 +25,31 @@ * Related to Normalized Dummy. * * @author Amrouche Hamza - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"related_output", "output"}}, - * "denormalization_context"={"groups"={"related_input", "input"}} - * }) - * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['related_output', 'output']], denormalizationContext: ['groups' => ['related_input', 'input']])] +#[ODM\Document] class RelatedNormalizedDummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"related_output", "related_input"}) */ - private $id; - + #[Groups(['related_output', 'related_input'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"related_output", "related_input"}) */ - private $name; + #[Assert\NotBlank] + #[ApiProperty(types: ['http://schema.org/name'])] + #[Groups(['related_output', 'related_input'])] + #[ODM\Field] + private ?string $name = null; /** * @var iterable Several Normalized dummies - * - * @ODM\ReferenceMany(targetDocument=CustomNormalizedDummy::class) - * @Groups({"related_output", "related_input"}) */ + #[Groups(['related_output', 'related_input'])] + #[ODM\ReferenceMany(targetDocument: CustomNormalizedDummy::class)] public $customNormalizedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php index 2ce46d9fd78..2621e028f5a 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** @@ -22,30 +22,22 @@ * * @author Sergey V. Ryabov * @author Alan Poulain - * - * @ApiResource(iri="https://schema.org/Product") - * @ODM\Document */ +#[ApiResource(types: ['https://schema.org/Product'])] +#[ODM\Document] class RelatedOwnedDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** * @var string|null A name - * - * @ODM\Field(type="string") */ + #[ODM\Field(type: 'string')] public $name; - /** - * @var Dummy|null - * - * @ODM\ReferenceOne(targetDocument=Dummy::class, cascade={"persist"}, inversedBy="relatedOwnedDummy", storeAs="id") - * @ApiSubresource + * @var \Dummy|null */ + #[ODM\ReferenceOne(targetDocument: Dummy::class, cascade: ['persist'], inversedBy: 'relatedOwnedDummy', storeAs: 'id')] public $owningDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php b/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php index 4424ae71bc3..785d0110d4d 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** @@ -22,30 +22,22 @@ * * @author Sergey V. Ryabov * @author Alan Poulain - * - * @ApiResource(iri="https://schema.org/Product") - * @ODM\Document */ +#[ApiResource(types: ['https://schema.org/Product'])] +#[ODM\Document] class RelatedOwningDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** * @var string A name - * - * @ODM\Field(type="string") */ + #[ODM\Field(type: 'string')] public $name; - /** - * @var Dummy - * - * @ODM\ReferenceOne(targetDocument=Dummy::class, cascade={"persist"}, mappedBy="relatedOwningDummy") - * @ApiSubresource + * @var \Dummy */ + #[ODM\ReferenceOne(targetDocument: Dummy::class, cascade: ['persist'], mappedBy: 'relatedOwningDummy')] public $ownedDummy; public function getId() @@ -84,7 +76,6 @@ public function getOwnedDummy(): Dummy public function setOwnedDummy(Dummy $ownedDummy) { $this->ownedDummy = $ownedDummy; - if ($this !== $this->ownedDummy->getRelatedOwningDummy()) { $this->ownedDummy->setRelatedOwningDummy($this); } diff --git a/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php b/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php index f84b28ed002..97df42e8beb 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php @@ -13,32 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource( - * attributes={"security"="is_granted('ROLE_ADMIN')"}, - * collectionOperations={ - * "get"={"security"="is_granted('ROLE_ADMIN')"}, - * }, - * itemOperations={ - * "get"={"security"="is_granted('ROLE_ADMIN')"}, - * }, - * graphql={ - * "item_query"={"security"="is_granted('ROLE_ADMIN')"}, - * "collection_query"={"security"="is_granted('ROLE_ADMIN')"}, - * } - * ) - * @ODM\Document - */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_ADMIN\')'), new GetCollection(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\')'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')')], security: 'is_granted(\'ROLE_ADMIN\')')] +#[ODM\Document] class RelatedSecuredDummy { /** * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php b/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php index bfe438b35e0..7db18122581 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php +++ b/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php @@ -13,54 +13,48 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; /** * Related To Dummy Friend represent an association table for a manytomany relation. - * - * @ApiResource(attributes={"normalization_context"={"groups"={"fakemanytomany"}}, "filters"={"related_to_dummy_friend.mongodb.name"}}) - * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['fakemanytomany']], filters: ['related_to_dummy_friend.mongodb.name'])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ODM\Document] class RelatedToDummyFriend { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** * @var string The dummy name - * - * @ODM\Field(type="string") - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"fakemanytomany", "friends"}) */ + #[Assert\NotBlank] + #[ApiProperty(types: ['http://schema.org/name'])] + #[Groups(['fakemanytomany', 'friends'])] + #[ODM\Field(type: 'string')] private $name; - /** * @var string|null The dummy description - * - * @ODM\Field(type="string") - * @Groups({"fakemanytomany", "friends"}) - */ - private $description; - - /** - * @ODM\ReferenceOne(targetDocument=DummyFriend::class, storeAs="id") - * @Groups({"fakemanytomany", "friends"}) - * @Assert\NotNull */ + #[Groups(['fakemanytomany', 'friends'])] + #[ODM\Field(type: 'string')] + private ?string $description = null; + #[Groups(['fakemanytomany', 'friends'])] + #[Assert\NotNull] + #[ODM\ReferenceOne(targetDocument: DummyFriend::class, storeAs: 'id')] private $dummyFriend; - - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, inversedBy="relatedToDummyFriend", storeAs="id") - * @Assert\NotNull - */ + #[Assert\NotNull] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, inversedBy: 'relatedToDummyFriend', storeAs: 'id')] private $relatedDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/RelationEmbedder.php b/tests/Fixtures/TestBundle/Document/RelationEmbedder.php index 51ccb2ac60b..b96cfe2b355 100644 --- a/tests/Fixtures/TestBundle/Document/RelationEmbedder.php +++ b/tests/Fixtures/TestBundle/Document/RelationEmbedder.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,53 +26,24 @@ * Relation Embedder. * * @author Kévin Dunglas - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"barcelona"}}, - * "denormalization_context"={"groups"={"chicago"}}, - * "hydra_context"={"@type"="hydra:Operation", "hydra:title"="A custom operation", "returns"="xmls:string"} - * }, - * itemOperations={ - * "get", - * "put"={}, - * "delete", - * "custom_get"={"route_name"="relation_embedded.custom_get", "method"="GET"}, - * "custom1"={"path"="/api/custom-call/{id}", "method"="GET"}, - * "custom2"={"path"="/api/custom-call/{id}", "method"="PUT"}, - * } - * ) - * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(routeName: 'relation_embedded.custom_get'), new Get(uriTemplate: '/api/custom-call/{id}'), new Put(uriTemplate: '/api/custom-call/{id}'), new Post(), new GetCollection()], normalizationContext: ['groups' => ['barcelona']], denormalizationContext: ['groups' => ['chicago']], hydraContext: ['@type' => 'hydra:Operation', 'hydra:title' => 'A custom operation', 'returns' => 'xmls:string'])] +#[ODM\Document] class RelationEmbedder { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - - /** - * @ODM\Field - * @Groups({"chicago"}) - */ + #[Groups(['chicago'])] + #[ODM\Field] public $paris = 'Paris'; - - /** - * @ODM\Field - * @Groups({"barcelona", "chicago"}) - */ + #[Groups(['barcelona', 'chicago'])] + #[ODM\Field] public $krondstadt = 'Krondstadt'; - - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, cascade={"persist"}) - * @Groups({"chicago", "barcelona"}) - */ + #[Groups(['chicago', 'barcelona'])] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, cascade: ['persist'])] public $anotherRelated; - - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class) - * @Groups({"barcelona", "chicago"}) - */ + #[Groups(['barcelona', 'chicago'])] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class)] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php b/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php index dc13428b365..ebe50eb2a11 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php @@ -13,28 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class ResourceWithBoolean { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var bool - * - * @ODM\Field(type="bool") */ - private $myBooleanField = false; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field(type: 'bool')] + private bool $myBooleanField = false; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php b/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php index ddd615aa7ad..5e0b73f84c1 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php @@ -13,28 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class ResourceWithFloat { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var float - * - * @ODM\Field(type="float") */ - private $myFloatField = 0.0; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field(type: 'float')] + private float $myFloatField = 0.0; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php b/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php index 4c6232a9142..16258b8c99e 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php @@ -13,28 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class ResourceWithInteger { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var int - * - * @ODM\Field(type="int") */ - private $myIntegerField = 0; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field(type: 'int')] + private int $myIntegerField = 0; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithString.php b/tests/Fixtures/TestBundle/Document/ResourceWithString.php index 5d3c333436e..f1afac729f8 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithString.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithString.php @@ -13,28 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class ResourceWithString { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var string - * - * @ODM\Field(type="string") */ - private $myStringField = ''; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field(type: 'string')] + private string $myStringField = ''; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/SecuredDummy.php b/tests/Fixtures/TestBundle/Document/SecuredDummy.php index 0551d3b74a9..7e8dbe547b9 100644 --- a/tests/Fixtures/TestBundle/Document/SecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/SecuredDummy.php @@ -13,8 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -25,135 +32,92 @@ * * @author Kévin Dunglas * @author Alan Poulain - * - * @ApiResource( - * attributes={"security"="is_granted('ROLE_USER')"}, - * collectionOperations={ - * "get"={"security"="is_granted('ROLE_USER') or is_granted('ROLE_ADMIN')"}, - * "get_from_data_provider_generator"={ - * "method"="GET", - * "path"="custom_data_provider_generator", - * "security"="is_granted('ROLE_USER')" - * }, - * "post"={"security"="is_granted('ROLE_ADMIN')"} - * }, - * itemOperations={ - * "get"={"security"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "put"={"security_post_denormalize"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * }, - * graphql={ - * "item_query"={"security"="is_granted('ROLE_ADMIN') or (is_granted('ROLE_USER') and object.getOwner() == user)"}, - * "collection_query"={"security"="is_granted('ROLE_ADMIN')"}, - * "delete"={}, - * "update"={"security_post_denormalize"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * "create"={"security"="is_granted('ROLE_ADMIN')", "security_message"="Only admins can create a secured dummy."} - * } - * ) - * @ODM\Document */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(security: 'is_granted(\'ROLE_USER\') or is_granted(\'ROLE_ADMIN\')'), new GetCollection(uriTemplate: 'custom_data_provider_generator', security: 'is_granted(\'ROLE_USER\')'), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\') or (is_granted(\'ROLE_USER\') and object.getOwner() == user)'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')'), new Mutation(name: 'delete'), new Mutation(name: 'update', securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] +#[ODM\Document] class SecuredDummy { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null The title - * - * @ODM\Field - * @Assert\NotBlank */ - private $title; + #[Assert\NotBlank] + #[ODM\Field] + private ?string $title = null; /** * @var string The description - * - * @ODM\Field */ - private $description = ''; + #[ODM\Field] + private string $description = ''; /** * @var string The dummy secret property, only readable/writable by specific users - * - * @ODM\Field - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ - private $adminOnlyProperty = ''; + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ODM\Field] + private ?string $adminOnlyProperty = ''; /** * @var string Secret property, only readable/writable by owners - * - * @ODM\Field - * @ApiProperty( - * security="object == null or object.getOwner() == user", - * securityPostDenormalize="object.getOwner() == user", - * ) */ - private $ownerOnlyProperty = ''; + #[ApiProperty(security: 'object == null or object.getOwner() == user', securityPostDenormalize: 'object.getOwner() == user')] + #[ODM\Field] + private ?string $ownerOnlyProperty = ''; /** * @var string|null The owner - * - * @ODM\Field - * @Assert\NotBlank */ - private $owner; + #[Assert\NotBlank] + #[ODM\Field] + private ?string $owner = null; /** * @var Collection Several dummies - * - * @ODM\ReferenceMany(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ODM\ReferenceMany(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummies; /** * @var RelatedDummy - * - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] protected $relatedDummy; /** * A collection of dummies that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var Collection Several dummies - * - * @ODM\ReferenceMany(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) - * @ApiProperty(security="is_granted('ROLE_USER')") */ + #[ApiProperty(security: "is_granted('ROLE_USER')")] + #[ODM\ReferenceMany(targetDocument: RelatedSecuredDummy::class, storeAs: 'id', nullable: true)] public $relatedSecuredDummies; /** * A dummy that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var RelatedSecuredDummy - * - * @ODM\ReferenceOne(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) - * @ApiProperty(security="is_granted('ROLE_USER')") */ + #[ApiProperty(security: "is_granted('ROLE_USER')")] + #[ODM\ReferenceOne(targetDocument: RelatedSecuredDummy::class, storeAs: 'id', nullable: true)] protected $relatedSecuredDummy; - /** * Collection of dummies that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * * @var Collection Several dummies - * - * @ODM\ReferenceMany(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceMany(targetDocument: RelatedSecuredDummy::class, storeAs: 'id', nullable: true)] public $publicRelatedSecuredDummies; - /** * A dummy that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * * @var RelatedSecuredDummy - * - * @ODM\ReferenceOne(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceOne(targetDocument: RelatedSecuredDummy::class, storeAs: 'id', nullable: true)] protected $publicRelatedSecuredDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php b/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php index 5e74998802d..6e4de942ade 100644 --- a/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php @@ -17,23 +17,19 @@ /** * File Config Dummy. - * - * @ODM\Document */ +#[ODM\Document] class SingleFileConfigDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/SlugChildDummy.php b/tests/Fixtures/TestBundle/Document/SlugChildDummy.php index 2cf79bcc691..543a4ac8963 100644 --- a/tests/Fixtures/TestBundle/Document/SlugChildDummy.php +++ b/tests/Fixtures/TestBundle/Document/SlugChildDummy.php @@ -13,40 +13,33 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugParentDummy::class, identifiers: ['slug'], toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], fromProperty: 'parentDummy'), 'parentDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugParentDummy::class, identifiers: [], expandedValue: 'parent_dummy', toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class SlugChildDummy { /** * @var int The identifier - * - * @ApiProperty(identifier=false) - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ApiProperty(identifier: false)] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string The slug used as API identifier - * - * @ApiProperty(identifier=true) - * - * @ODM\Field */ - private $slug; + #[ApiProperty(identifier: true)] + #[ODM\Field] + private ?string $slug = null; - /** - * @ODM\ReferenceOne(targetDocument=SlugParentDummy::class, inversedBy="childDummies", storeAs="id") - * - * @ApiSubresource - */ + #[ODM\ReferenceOne(targetDocument: SlugParentDummy::class, inversedBy: 'childDummies', storeAs: 'id')] private $parentDummy; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/SlugParentDummy.php b/tests/Fixtures/TestBundle/Document/SlugParentDummy.php index 641fff4ebbc..12318bf5ab3 100644 --- a/tests/Fixtures/TestBundle/Document/SlugParentDummy.php +++ b/tests/Fixtures/TestBundle/Document/SlugParentDummy.php @@ -13,47 +13,42 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom Identifier Dummy With Subresource. - * - * @ApiResource(attributes={"identifiers"="slug"}) - * @ODM\Document */ +#[ApiResource(uriVariables: 'slug')] +#[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies/{childDummies}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], toProperty: 'parentDummy'), 'childDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] +#[ODM\Document] class SlugParentDummy { /** * @var int|null The database identifier - * - * @ApiProperty(identifier=false) - * - * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ApiProperty(identifier: false)] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; /** * @var string|null The slug used a API identifier - * - * @ApiProperty(identifier=true) - * - * @ODM\Field */ - private $slug; + #[ApiProperty(identifier: true)] + #[ODM\Field] + private ?string $slug = null; /** - * @ODM\ReferenceMany(targetDocument=SlugChildDummy::class, mappedBy="parentDummy") - * - * @var Collection - * - * @ApiSubresource + * @var \Collection */ - private $childDummies; + #[ODM\ReferenceMany(targetDocument: SlugChildDummy::class, mappedBy: 'parentDummy')] + private \Collection $childDummies; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/SoMany.php b/tests/Fixtures/TestBundle/Document/SoMany.php index 50fe29a985e..3fcc1fb03ef 100644 --- a/tests/Fixtures/TestBundle/Document/SoMany.php +++ b/tests/Fixtures/TestBundle/Document/SoMany.php @@ -13,33 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; use ApiPlatform\Doctrine\Odm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - * @ApiResource(attributes={ - * "pagination_partial"=true, - * "pagination_via_cursor"={ - * {"field"="id", "direction"="DESC"} - * } - * }) - * - * @ApiFilter(RangeFilter::class, properties={"id"}) - * @ApiFilter(OrderFilter::class, properties={"id"="DESC"}) - */ +#[ApiFilter(RangeFilter::class, properties: ['id'])] +#[ApiFilter(OrderFilter::class, properties: ['id' => 'DESC'])] +#[ApiResource(paginationPartial: true, paginationViaCursor: [['field' => 'id', 'direction' => 'DESC']])] +#[ODM\Document] class SoMany { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - - /** - * @ODM\Field(nullable=true) - */ + #[ODM\Field(nullable: true)] public $content; } diff --git a/tests/Fixtures/TestBundle/Document/Taxon.php b/tests/Fixtures/TestBundle/Document/Taxon.php index 501905d3f92..30e948be12f 100644 --- a/tests/Fixtures/TestBundle/Document/Taxon.php +++ b/tests/Fixtures/TestBundle/Document/Taxon.php @@ -16,24 +16,13 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ +#[ODM\Document] class Taxon implements TaxonInterface { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var string|null - * - * @ODM\Field(type="string") - */ - private $code; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[ODM\Field(type: 'string')] + private ?string $code = null; /** * {@inheritdoc} diff --git a/tests/Fixtures/TestBundle/Document/ThirdLevel.php b/tests/Fixtures/TestBundle/Document/ThirdLevel.php index 1ad880ff897..2b0c83aa2d8 100644 --- a/tests/Fixtures/TestBundle/Document/ThirdLevel.php +++ b/tests/Fixtures/TestBundle/Document/ThirdLevel.php @@ -13,8 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -23,44 +24,30 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ODM\Document] class ThirdLevel { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @var int - * - * @ODM\Field(type="int") - * @Groups({"barcelona", "chicago"}) - */ - private $level = 3; - - /** - * @var bool - * - * @ODM\Field(type="bool") - */ - private $test = true; - - /** - * @ApiSubresource - * @ODM\ReferenceOne(targetDocument=FourthLevel::class, cascade={"persist"}, storeAs="id") - * @Groups({"barcelona", "chicago", "friends"}) */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + #[Groups(['barcelona', 'chicago'])] + #[ODM\Field(type: 'int')] + private int $level = 3; + #[ODM\Field(type: 'bool')] + private bool $test = true; + #[Groups(['barcelona', 'chicago', 'friends'])] + #[ODM\ReferenceOne(targetDocument: FourthLevel::class, cascade: ['persist'], storeAs: 'id')] public $fourthLevel; - - /** - * @ODM\ReferenceOne(targetDocument=FourthLevel::class, cascade={"persist"}) - */ + #[ODM\ReferenceOne(targetDocument: FourthLevel::class, cascade: ['persist'])] public $badFourthLevel; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/UrlEncodedId.php b/tests/Fixtures/TestBundle/Document/UrlEncodedId.php index 029736d5d3b..f6b430443a7 100644 --- a/tests/Fixtures/TestBundle/Document/UrlEncodedId.php +++ b/tests/Fixtures/TestBundle/Document/UrlEncodedId.php @@ -13,31 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @author Daniel West * * Resource with an ID that will be URL encoded - * - * @ODM\Document - * - * @ApiResource( - * itemOperations={ - * "get"={ - * "method"="GET", - * "requirements"={"id"=".+"} - * } - * } - * ) */ +#[ApiResource(operations: [new Get(requirements: ['id' => '.+']), new Post(), new GetCollection()])] +#[ODM\Document] class UrlEncodedId { - /** - * @ODM\Id(strategy="none") - */ - private $id = '%encode:id'; + #[ODM\Id(strategy: 'none')] + private string $id = '%encode:id'; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/User.php b/tests/Fixtures/TestBundle/Document/User.php index b148452a2f3..d7c3290cf14 100644 --- a/tests/Fixtures/TestBundle/Document/User.php +++ b/tests/Fixtures/TestBundle/Document/User.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\PasswordResetRequest; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\PasswordResetRequestResult; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordInput; @@ -25,75 +30,38 @@ /** * A User. * - * @ODM\Document(collection="user_test") - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"user", "user-read"}}, - * "denormalization_context"={"groups"={"user", "user-write"}} - * }, - * collectionOperations={ - * "post", - * "get", - * "post_password_reset_request"={ - * "method"="POST", - * "path"="/users/password_reset_request", - * "messenger"="input", - * "input"=PasswordResetRequest::class, - * "output"=PasswordResetRequestResult::class, - * "normalization_context"={ - * "groups"={"user_password_reset_request"}, - * }, - * "denormalization_context"={ - * "groups"={"user_password_reset_request"}, - * }, - * }, - * }, - * itemOperations={"get", "put", "delete", - * "recover_password"={ - * "input"=RecoverPasswordInput::class, "output"=RecoverPasswordOutput::class, "method"="PUT", "path"="users/recover/{id}" - * } - * } - * ) - * * @author Théo FIDRY * @author Kévin Dunglas */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Put(input: RecoverPasswordInput::class, output: RecoverPasswordOutput::class, uriTemplate: 'users/recover/{id}'), new Post(), new GetCollection(), new Post(uriTemplate: '/users/password_reset_request', messenger: 'input', input: PasswordResetRequest::class, output: PasswordResetRequestResult::class, normalizationContext: ['groups' => ['user_password_reset_request']], denormalizationContext: ['groups' => ['user_password_reset_request']])], normalizationContext: ['groups' => ['user', 'user-read']], denormalizationContext: ['groups' => ['user', 'user-write']])] +#[ODM\Document(collection: 'user_test')] class User extends AbstractSecurityUser { /** * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] protected $id; - /** * @var string|null - * - * @Groups({"user"}) */ + #[Groups(['user'])] protected $email; - /** * @var string|null - * - * @ODM\Field(type="string", nullable=true) - * @Groups({"user"}) */ + #[Groups(['user'])] + #[ODM\Field(type: 'string', nullable: true)] protected $fullname; - /** * @var string|null - * - * @Groups({"user-write"}) */ + #[Groups(['user-write'])] protected $plainPassword; - /** * @var string|null - * - * @Groups({"user"}) */ + #[Groups(['user'])] protected $username; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php index db914748f4d..e681eb6bba2 100644 --- a/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php @@ -13,30 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom identifier dummy. - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class UuidIdentifierDummy { /** * @var string The custom identifier - * - * @ODM\Id(strategy="UUID") */ - private $uuid; - + #[ODM\Id(strategy: 'UUID')] + private ?string $uuid = null; /** * @var string The dummy name - * - * @ODM\Field */ - private $name; + #[ODM\Field] + private ?string $name = null; public function getUuid(): string { diff --git a/tests/Fixtures/TestBundle/Document/VoDummyCar.php b/tests/Fixtures/TestBundle/Document/VoDummyCar.php index e83de67299b..f8473c5925d 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyCar.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyCar.php @@ -13,55 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"car_read"}}, - * "denormalization_context"={"groups"={"car_write"}} - * }) - * @ODM\Document - */ +#[ApiResource(normalizationContext: ['groups' => ['car_read']], denormalizationContext: ['groups' => ['car_write']])] +#[ODM\Document] class VoDummyCar extends VoDummyVehicle { - /** - * @var int - * - * @ODM\Field(type="int") - * @Groups({"car_read", "car_write"}) - */ - private $mileage; - - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $bodyType; - /** * @var VoDummyInspection[]|Collection - * - * @ODM\ReferenceMany(targetDocument=VoDummyInspection::class, mappedBy="car", cascade={"persist"}) - * @Groups({"car_read", "car_write"}) */ - private $inspections; + #[Groups(['car_read', 'car_write'])] + #[ODM\ReferenceMany(targetDocument: VoDummyInspection::class, mappedBy: 'car', cascade: ['persist'])] + private readonly array|\Doctrine\Common\Collections\Collection $inspections; - public function __construct( - string $make, - VoDummyInsuranceCompany $insuranceCompany, - array $drivers, - int $mileage, - string $bodyType = 'coupe' - ) { + public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, #[Groups(['car_read', 'car_write'])] #[ODM\Field(type: 'int')] private readonly int $mileage, #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $bodyType = 'coupe') + { parent::__construct($make, $insuranceCompany, $drivers); - $this->mileage = $mileage; - $this->bodyType = $bodyType; $this->inspections = new ArrayCollection(); } diff --git a/tests/Fixtures/TestBundle/Document/VoDummyDriver.php b/tests/Fixtures/TestBundle/Document/VoDummyDriver.php index de206dc218b..5e059fe276c 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyDriver.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyDriver.php @@ -13,38 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class VoDummyDriver { use VoDummyIdAwareTrait; - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $firstName; - - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $lastName; - - public function __construct(string $firstName, string $lastName) - { - $this->firstName = $firstName; - $this->lastName = $lastName; + public function __construct( + #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $firstName, + #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $lastName + ) { } public function getFirstName() diff --git a/tests/Fixtures/TestBundle/Document/VoDummyIdAwareTrait.php b/tests/Fixtures/TestBundle/Document/VoDummyIdAwareTrait.php index 2dc3cd328b0..e396227747e 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyIdAwareTrait.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyIdAwareTrait.php @@ -19,9 +19,8 @@ trait VoDummyIdAwareTrait { /** * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] protected $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/VoDummyInspection.php b/tests/Fixtures/TestBundle/Document/VoDummyInspection.php index ddc584d7a38..c6313e282f5 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyInspection.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyInspection.php @@ -13,57 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use DateTime; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"inspection_read"}}, - * "denormalization_context"={"groups"={"inspection_write"}} - * }, - * graphql={} - * ) - * @ODM\Document - */ +#[ApiResource(graphQlOperations: [], normalizationContext: ['groups' => ['inspection_read']], denormalizationContext: ['groups' => ['inspection_write']])] +#[ODM\Document] class VoDummyInspection { use VoDummyIdAwareTrait; + #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] + #[ODM\Field(type: 'date')] + private \DateTime $performed; - /** - * @var bool - * - * @ODM\Field(type="bool") - * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) - */ - private $accepted; - - /** - * @var VoDummyCar - * - * @ODM\ReferenceOne(targetDocument=VoDummyCar::class, inversedBy="inspections") - * @Groups({"inspection_read", "inspection_write"}) - */ - private $car; - - /** - * @var DateTime - * - * @ODM\Field(type="date") - * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) - */ - private $performed; - - private $attributeWithoutConstructorEquivalent; - - public function __construct(bool $accepted, VoDummyCar $car, DateTime $performed = null, string $parameterWhichIsNotClassAttribute = '') + public function __construct(#[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] #[ODM\Field(type: 'bool')] private readonly bool $accepted, #[Groups(['inspection_read', 'inspection_write'])] #[ODM\ReferenceOne(targetDocument: VoDummyCar::class, inversedBy: 'inspections')] private readonly VoDummyCar $car, DateTime $performed = null, private readonly string $attributeWithoutConstructorEquivalent = '') { - $this->accepted = $accepted; - $this->car = $car; $this->performed = $performed ?: new DateTime(); - $this->attributeWithoutConstructorEquivalent = $parameterWhichIsNotClassAttribute; } public function isAccepted() diff --git a/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php b/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php index 387bd7dbaf0..3f2d3f5a7bd 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php @@ -13,29 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class VoDummyInsuranceCompany { use VoDummyIdAwareTrait; - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $name; - - public function __construct(string $name) - { - $this->name = $name; + public function __construct( + #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $name + ) { } public function getName() diff --git a/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php b/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php index e686c14b8bf..6c7abaf4c6f 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php @@ -18,44 +18,22 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\MappedSuperclass - */ +#[ODM\MappedSuperclass] abstract class VoDummyVehicle { use VoDummyIdAwareTrait; - - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $make; - - /** - * @var VoDummyInsuranceCompany - * - * @ODM\ReferenceOne(targetDocument=VoDummyInsuranceCompany::class, cascade={"persist"}) - * @Groups({"car_read", "car_write"}) - */ - private $insuranceCompany; - /** * @var VoDummyDriver[]|Collection - * - * @ODM\ReferenceMany(targetDocument=VoDummyDriver::class, cascade={"persist"}) - * @Groups({"car_read", "car_write"}) */ - private $drivers; + #[Groups(['car_read', 'car_write'])] + #[ODM\ReferenceMany(targetDocument: VoDummyDriver::class, cascade: ['persist'])] + private readonly array|\Doctrine\Common\Collections\Collection $drivers; public function __construct( - string $make, - VoDummyInsuranceCompany $insuranceCompany, + #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $make, + #[Groups(['car_read', 'car_write'])] #[ODM\ReferenceOne(targetDocument: VoDummyInsuranceCompany::class, cascade: ['persist'])] private readonly VoDummyInsuranceCompany $insuranceCompany, array $drivers ) { - $this->make = $make; - $this->insuranceCompany = $insuranceCompany; $this->drivers = new ArrayCollection($drivers); } diff --git a/tests/Fixtures/TestBundle/Document/VoidPayment.php b/tests/Fixtures/TestBundle/Document/VoidPayment.php index af1f7b6d82c..4e86efd8c39 100644 --- a/tests/Fixtures/TestBundle/Document/VoidPayment.php +++ b/tests/Fixtures/TestBundle/Document/VoidPayment.php @@ -13,31 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - * - * @ApiResource - */ +#[ApiResource] +#[ODM\Document] class VoidPayment { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") - */ - private $id; - - /** - * @ODM\ReferenceOne(targetDocument=Payment::class, inversedBy="voidPayment") - */ - private $payment; - - public function __construct(Payment $payment) - { - $this->payment = $payment; + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] + private ?int $id = null; + + public function __construct( + #[ODM\ReferenceOne(targetDocument: Payment::class, inversedBy: 'voidPayment')] private readonly Payment $payment + ) { } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/WithJsonDummy.php b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php index 323a8ef08a1..98c33558e89 100644 --- a/tests/Fixtures/TestBundle/Document/WithJsonDummy.php +++ b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php @@ -13,27 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ApiResource - * @ODM\Document - */ +#[ApiResource] +#[ODM\Document] class WithJsonDummy { - /** - * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) - */ - private $id; - + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] + private ?int $id = null; /** * @var array|null - * - * @ODM\Field(type="hash", nullable=true) */ + #[ODM\Field(type: 'hash', nullable: true)] public $json; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/WritableId.php b/tests/Fixtures/TestBundle/Document/WritableId.php index 1899ef30388..096b7c1e43f 100644 --- a/tests/Fixtures/TestBundle/Document/WritableId.php +++ b/tests/Fixtures/TestBundle/Document/WritableId.php @@ -13,26 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; /** * @author Kévin Dunglas - * - * @ApiResource - * @ODM\Document */ +#[ApiResource] +#[ODM\Document] class WritableId { - /** - * @ODM\Id(strategy="UUID", type="string") - * @Assert\Uuid - */ + #[Assert\Uuid] + #[ODM\Id(strategy: 'UUID', type: 'string')] public $id; - - /** - * @ODM\Field - */ + #[ODM\Field] public $name; } diff --git a/tests/Fixtures/TestBundle/Dto/NonResourceClass.php b/tests/Fixtures/TestBundle/Dto/NonResourceClass.php index 6acb6723490..f58bc080337 100644 --- a/tests/Fixtures/TestBundle/Dto/NonResourceClass.php +++ b/tests/Fixtures/TestBundle/Dto/NonResourceClass.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Dto; -class NonResourceClass +class NonResourceClass implements \Stringable { /** * @var string */ public $foo; - public function __toString() + public function __toString(): string { return $this->foo; } diff --git a/tests/Fixtures/TestBundle/Dto/PasswordResetRequest.php b/tests/Fixtures/TestBundle/Dto/PasswordResetRequest.php index df002e7e19a..5aabbac378d 100644 --- a/tests/Fixtures/TestBundle/Dto/PasswordResetRequest.php +++ b/tests/Fixtures/TestBundle/Dto/PasswordResetRequest.php @@ -17,14 +17,8 @@ final class PasswordResetRequest { - /** - * @Groups({"user_password_reset_request"}) - */ - private $email; - - public function __construct(string $email = '') + public function __construct(#[Groups(['user_password_reset_request'])] private readonly string $email = '') { - $this->email = $email; } public function getEmail(): string diff --git a/tests/Fixtures/TestBundle/Dto/PasswordResetRequestResult.php b/tests/Fixtures/TestBundle/Dto/PasswordResetRequestResult.php index 8f38f6a8221..97c37ce8b74 100644 --- a/tests/Fixtures/TestBundle/Dto/PasswordResetRequestResult.php +++ b/tests/Fixtures/TestBundle/Dto/PasswordResetRequestResult.php @@ -17,14 +17,8 @@ final class PasswordResetRequestResult { - /** - * @Groups({"user_password_reset_request"}) - */ - private $emailSentAt; - - public function __construct(\DateTimeInterface $emailSentAt) + public function __construct(#[Groups(['user_password_reset_request'])] private readonly \DateTimeInterface $emailSentAt) { - $this->emailSentAt = $emailSentAt; } public function getEmailSentAt(): \DateTimeInterface diff --git a/tests/Fixtures/TestBundle/Dto/RecoverPasswordInput.php b/tests/Fixtures/TestBundle/Dto/RecoverPasswordInput.php index e6ab58dffa1..cc3d2707d1f 100644 --- a/tests/Fixtures/TestBundle/Dto/RecoverPasswordInput.php +++ b/tests/Fixtures/TestBundle/Dto/RecoverPasswordInput.php @@ -19,7 +19,7 @@ class RecoverPasswordInput { /** * @var \ApiPlatform\Tests\Fixtures\TestBundle\Entity\User - * @Groups({"user"}) */ + #[Groups(['user'])] public $user; } diff --git a/tests/Fixtures/TestBundle/Dto/RecoverPasswordOutput.php b/tests/Fixtures/TestBundle/Dto/RecoverPasswordOutput.php index ef7e78488c7..b152c3b0564 100644 --- a/tests/Fixtures/TestBundle/Dto/RecoverPasswordOutput.php +++ b/tests/Fixtures/TestBundle/Dto/RecoverPasswordOutput.php @@ -19,7 +19,7 @@ class RecoverPasswordOutput { /** * @var \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy - * @Groups({"user"}) */ + #[Groups(['user'])] public $dummy; } diff --git a/tests/Fixtures/TestBundle/Dto/UserResetPasswordDto.php b/tests/Fixtures/TestBundle/Dto/UserResetPasswordDto.php index f8a85e11bb5..119d55b69c2 100644 --- a/tests/Fixtures/TestBundle/Dto/UserResetPasswordDto.php +++ b/tests/Fixtures/TestBundle/Dto/UserResetPasswordDto.php @@ -17,8 +17,6 @@ final class UserResetPasswordDto { - /** - * @Assert\Email - */ + #[Assert\Email] public $email; } diff --git a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php index a4c2bc4e166..7e77c5a4885 100644 --- a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php @@ -14,25 +14,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::ABS_URL) - * @ORM\Entity - */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] +#[ApiResource(uriTemplate: '/absolute_url_relation_dummies/{id}/absolute_url_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\AbsoluteUrlRelationDummy::class, identifiers: ['id'], toProperty: 'absoluteUrlRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::ABS_URL, operations: [new GetCollection()])] +#[ORM\Entity] class AbsoluteUrlDummy { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - - /** - * @ORM\ManyToOne(targetEntity="AbsoluteUrlRelationDummy", inversedBy="absoluteUrlDummies") - */ + #[ORM\ManyToOne(targetEntity: 'AbsoluteUrlRelationDummy', inversedBy: 'absoluteUrlDummies')] public $absoluteUrlRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php index e689c5efd39..325d559018f 100644 --- a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php @@ -14,28 +14,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::ABS_URL) - * @ORM\Entity - */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] +#[ORM\Entity] class AbsoluteUrlRelationDummy { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - - /** - * @ORM\OneToMany(targetEntity="AbsoluteUrlDummy", mappedBy="absoluteUrlRelationDummy") - * @ApiSubresource - */ + #[ORM\OneToMany(targetEntity: 'AbsoluteUrlDummy', mappedBy: 'absoluteUrlRelationDummy')] public $absoluteUrlDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/AbstractDummy.php b/tests/Fixtures/TestBundle/Entity/AbstractDummy.php index 5bd9d03f0e5..0badb81e2ca 100644 --- a/tests/Fixtures/TestBundle/Entity/AbstractDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbstractDummy.php @@ -13,8 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; @@ -22,35 +27,28 @@ * Abstract Dummy. * * @author Jérémy Derussé - * - * @ApiResource( - * collectionOperations={"get", "post"}, - * itemOperations={"get", "put", "delete"}, - * attributes={"filters"={"my_dummy.search", "my_dummy.order", "my_dummy.date"}} - * ) - * @ORM\Entity - * @ORM\InheritanceType("SINGLE_TABLE") - * @ORM\DiscriminatorColumn(name="discr", type="string", length=16) - * @ORM\DiscriminatorMap({"concrete"="ConcreteDummy"}) */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new GetCollection(), new Post()], filters: ['my_dummy.search', 'my_dummy.order', 'my_dummy.date'])] +#[ORM\Entity] +#[ORM\InheritanceType('SINGLE_TABLE')] +#[ORM\DiscriminatorColumn(name: 'discr', type: 'string', length: 16)] +#[ORM\DiscriminatorMap(['concrete' => 'ConcreteDummy'])] abstract class AbstractDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/AbstractUser.php b/tests/Fixtures/TestBundle/Entity/AbstractUser.php index d454c320fd6..ff0c7571c97 100644 --- a/tests/Fixtures/TestBundle/Entity/AbstractUser.php +++ b/tests/Fixtures/TestBundle/Entity/AbstractUser.php @@ -13,40 +13,25 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * @ORM\InheritanceType("JOINED") - * @ApiResource( - * collectionOperations={ - * "get"={"path"="/custom_users"} - * }, - * itemOperations={ - * "get"={"path"="/custom_users/{id}"} - * } - * ) - */ +#[ApiResource(operations: [new Get(uriTemplate: '/custom_users/{id}'), new GetCollection(uriTemplate: '/custom_users')])] +#[ORM\Entity] +#[ORM\InheritanceType('JOINED')] abstract class AbstractUser { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column - */ + #[ORM\Column] private $firstname; - /** - * @ORM\Column - */ + #[ORM\Column] private $lastname; - /** - * @ORM\Column - */ + #[ORM\Column] private $email; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/Address.php b/tests/Fixtures/TestBundle/Entity/Address.php index 2086b7ae979..2b966107e09 100644 --- a/tests/Fixtures/TestBundle/Entity/Address.php +++ b/tests/Fixtures/TestBundle/Entity/Address.php @@ -13,30 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class Address { - /** - * @var int - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"order_read"}) - */ - private $id; - - /** - * @ORM\Column(type="string") - * @Groups({"order_read"}) - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['order_read'])] + private ?int $id = null; + #[ORM\Column(type: 'string')] + #[Groups(['order_read'])] public $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/AlternateResource.php b/tests/Fixtures/TestBundle/Entity/AlternateResource.php index 95961030a7d..c7db685f8ab 100644 --- a/tests/Fixtures/TestBundle/Entity/AlternateResource.php +++ b/tests/Fixtures/TestBundle/Entity/AlternateResource.php @@ -21,12 +21,8 @@ #[Get('/alternate/{id}', uriVariables: ['id' => ['from_class' => AlternateResource::class, 'identifiers' => ['id']]])] final class AlternateResource { - #[ApiProperty(identifier: true)] - public string $id; - - public function __construct(string $id) + public function __construct(#[ApiProperty(identifier: true)] public string $id) { - $this->id = $id; } public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Answer.php b/tests/Fixtures/TestBundle/Entity/Answer.php index 68425c5f247..794abea9866 100644 --- a/tests/Fixtures/TestBundle/Entity/Answer.php +++ b/tests/Fixtures/TestBundle/Entity/Answer.php @@ -13,8 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -22,41 +27,30 @@ /** * Answer. - * - * @ORM\Entity - * @ApiResource(collectionOperations={ - * "get_subresource_answer"={"method"="GET", "normalization_context"={"groups"={"foobar"}}} - * }) */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(normalizationContext: ['groups' => ['foobar']])])] +#[ApiResource(uriTemplate: '/answers/{id}/related_questions/{relatedQuestions}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], toProperty: 'answer'), 'relatedQuestions' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/questions/{id}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] +#[ORM\Entity] class Answer { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Serializer\Groups({"foobar"}) - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Serializer\Groups(['foobar'])] private $id; - - /** - * @ORM\Column(nullable=false) - * @Serializer\Groups({"foobar"}) - */ + #[ORM\Column(nullable: false)] + #[Serializer\Groups(['foobar'])] private $content; - - /** - * @ORM\OneToOne(targetEntity="Question", mappedBy="answer") - * @Serializer\Groups({"foobar"}) - */ + #[ORM\OneToOne(targetEntity: 'Question', mappedBy: 'answer')] + #[Serializer\Groups(['foobar'])] private $question; - /** - * @var Collection - * @ORM\OneToMany(targetEntity="Question", mappedBy="answer") - * @Serializer\Groups({"foobar"}) - * @ApiSubresource + * @var \Collection */ - private $relatedQuestions; + #[ORM\OneToMany(targetEntity: 'Question', mappedBy: 'answer')] + #[Serializer\Groups(['foobar'])] + private readonly \Collection $relatedQuestions; public function __construct() { @@ -93,8 +87,6 @@ public function getContent(): ?string /** * Set question. - * - * @param Question $question */ public function setQuestion(Question $question = null): self { diff --git a/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php b/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php index a78a881f78e..717a576017d 100644 --- a/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php +++ b/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayRequiredFilter; use Doctrine\ORM\Mapping as ORM; @@ -22,31 +22,24 @@ * Filter Validator entity. * * @author Julien Deniau - * - * @ApiResource(attributes={ - * "filters"={ - * ArrayRequiredFilter::class - * } - * }) - * @ORM\Entity */ +#[ApiResource(filters: [ArrayRequiredFilter::class])] +#[ORM\Entity] class ArrayFilterValidator { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string A name - * - * @ORM\Column - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php b/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php index f4ea98bb512..ef54ab11855 100644 --- a/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php +++ b/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php @@ -19,14 +19,8 @@ #[ApiResource(paginationItemsPerPage: 10, graphQlOperations: [])] final class AttributeDefaultOperations { - #[ApiProperty(identifier: true)] - private $identifier; - private $name; - - public function __construct(int $identifier, string $name) + public function __construct(#[ApiProperty(identifier: true)] private readonly int $identifier, private readonly string $name) { - $this->identifier = $identifier; - $this->name = $name; } public function getIdentifier() diff --git a/tests/Fixtures/TestBundle/Entity/AttributeResource.php b/tests/Fixtures/TestBundle/Entity/AttributeResource.php index ca4f003a1cd..50f355d72cc 100644 --- a/tests/Fixtures/TestBundle/Entity/AttributeResource.php +++ b/tests/Fixtures/TestBundle/Entity/AttributeResource.php @@ -41,24 +41,14 @@ #[Patch] final class AttributeResource { - #[ApiProperty(identifier: true)] - private $identifier; - /** * @var ?Dummy */ #[Link('dummyId')] public $dummy = null; - /** - * @var string - */ - public $name; - - public function __construct(int $identifier, string $name) + public function __construct(#[ApiProperty(identifier: true)] private readonly int $identifier, public string $name) { - $this->identifier = $identifier; - $this->name = $name; } public function getIdentifier() diff --git a/tests/Fixtures/TestBundle/Entity/AttributeResources.php b/tests/Fixtures/TestBundle/Entity/AttributeResources.php index 235a99dc7bf..44ba83f2037 100644 --- a/tests/Fixtures/TestBundle/Entity/AttributeResources.php +++ b/tests/Fixtures/TestBundle/Entity/AttributeResources.php @@ -33,7 +33,7 @@ final class AttributeResources implements IteratorAggregate /** * @var AttributeResource[] */ - private $collection; + private readonly array $collection; public function __construct(AttributeResource ...$collection) { diff --git a/tests/Fixtures/TestBundle/Entity/Book.php b/tests/Fixtures/TestBundle/Entity/Book.php index 9ba7911a638..45a30eb6807 100644 --- a/tests/Fixtures/TestBundle/Entity/Book.php +++ b/tests/Fixtures/TestBundle/Entity/Book.php @@ -13,37 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Book. * * @author Antoine Bluchet - * - * @ApiResource(collectionOperations={}, itemOperations={ - * "get", - * "get_by_isbn"={"method"="GET", "path"="/books/by_isbn/{isbn}.{_format}", "requirements"={"isbn"=".+"}, "identifiers"="isbn"} - * }) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Get(uriTemplate: '/books/by_isbn/{isbn}.{_format}', requirements: ['isbn' => '.+'], uriVariables: 'isbn')])] +#[ORM\Entity] class Book { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column - */ + #[ORM\Column] public $name; - - /** - * @ORM\Column(unique=true) - */ + #[ORM\Column(unique: true)] public $isbn; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/CircularReference.php b/tests/Fixtures/TestBundle/Entity/CircularReference.php index 244d65a9afa..fd39438fa51 100644 --- a/tests/Fixtures/TestBundle/Entity/CircularReference.php +++ b/tests/Fixtures/TestBundle/Entity/CircularReference.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,31 +22,20 @@ * Circular Reference. * * @author Kévin Dunglas - * - * @ApiResource(attributes={"normalization_context"={"groups"={"circular"}}}) - * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['circular']])] +#[ORM\Entity] class CircularReference { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - - /** - * @ORM\ManyToOne(targetEntity="CircularReference", inversedBy="children") - * - * @Groups({"circular"}) - */ + #[ORM\ManyToOne(targetEntity: 'CircularReference', inversedBy: 'children')] + #[Groups(['circular'])] public $parent; - - /** - * @ORM\OneToMany(targetEntity="CircularReference", mappedBy="parent") - * - * @Groups({"circular"}) - */ + #[ORM\OneToMany(targetEntity: 'CircularReference', mappedBy: 'parent')] + #[Groups(['circular'])] public $children; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/Comment.php b/tests/Fixtures/TestBundle/Entity/Comment.php index 2b98e5401a8..6191eee1dd8 100644 --- a/tests/Fixtures/TestBundle/Entity/Comment.php +++ b/tests/Fixtures/TestBundle/Entity/Comment.php @@ -17,32 +17,20 @@ /** * @author Vincent Chalamon - * - * @ORM\Entity */ +#[ORM\Entity] class Comment { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column(type="text") - */ + #[ORM\Column(type: 'text')] public $comment; - - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: 'datetime')] public $date; - - /** - * @ORM\ManyToOne(targetEntity=User::class) - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: false)] public $author; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Company.php b/tests/Fixtures/TestBundle/Entity/Company.php index 690797d4338..151349ab9c9 100644 --- a/tests/Fixtures/TestBundle/Entity/Company.php +++ b/tests/Fixtures/TestBundle/Entity/Company.php @@ -19,9 +19,6 @@ use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] #[Get] #[Post] @@ -38,22 +35,21 @@ 'employeeId' => ['from_class' => Employee::class, 'from_property' => 'company'], ], )] +#[ORM\Entity] class Company { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] public string $name; /** @var Employee[] */ diff --git a/tests/Fixtures/TestBundle/Entity/CompositeItem.php b/tests/Fixtures/TestBundle/Entity/CompositeItem.php index 6e35171bee7..b3c3a3acd54 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeItem.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeItem.php @@ -13,36 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Item. - * - * @ApiResource - * @ORM\Entity */ -class CompositeItem +#[ApiResource] +#[ORM\Entity] +class CompositeItem implements \Stringable { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column(type="string", nullable=true) - * @Groups({"default"}) - */ + #[ORM\Column(type: 'string', nullable: true)] + #[Groups(['default'])] private $field1; - - /** - * @ORM\OneToMany(targetEntity="CompositeRelation", mappedBy="compositeItem", fetch="EAGER") - * @Groups({"default"}) - */ + #[ORM\OneToMany(targetEntity: 'CompositeRelation', mappedBy: 'compositeItem', fetch: 'EAGER')] + #[Groups(['default'])] private $compositeValues; /** diff --git a/tests/Fixtures/TestBundle/Entity/CompositeLabel.php b/tests/Fixtures/TestBundle/Entity/CompositeLabel.php index 681c6edfb2f..3d8b9624241 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeLabel.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeLabel.php @@ -13,29 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Label. - * - * @ApiResource - * @ORM\Entity */ -class CompositeLabel +#[ApiResource] +#[ORM\Entity] +class CompositeLabel implements \Stringable { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column(type="string", nullable=true) - * @Groups({"default"}) - */ + #[ORM\Column(type: 'string', nullable: true)] + #[Groups(['default'])] private $value; /** diff --git a/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php b/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php index e3cce5ba0e1..7953ed24e09 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php +++ b/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php @@ -13,38 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Composite Primitive Item. - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class CompositePrimitiveItem { - /** - * @ORM\Id - * @ORM\Column(type="string") - */ - private $name; - - /** - * @ORM\Id - * @ORM\Column(type="integer") - */ - private $year; - - /** - * @ORM\Column(type="text") - */ + #[ORM\Column(type: 'text')] private $description; - public function __construct(string $name, int $year) + public function __construct(#[ORM\Id] #[ORM\Column(type: 'string')] private readonly string $name, #[ORM\Id] #[ORM\Column(type: 'integer')] private readonly int $year) { - $this->name = $name; - $this->year = $year; } /** diff --git a/tests/Fixtures/TestBundle/Entity/CompositeRelation.php b/tests/Fixtures/TestBundle/Entity/CompositeRelation.php index c768bdcbc1b..986190d039f 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeRelation.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeRelation.php @@ -13,38 +13,29 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Relation. - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class CompositeRelation { - /** - * @ORM\Column(type="string", nullable=true) - * @Groups({"default"}) - */ + #[ORM\Column(type: 'string', nullable: true)] + #[Groups(['default'])] private $value; - - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="CompositeItem", inversedBy="compositeValues") - * @ORM\JoinColumn(name="composite_item_id", referencedColumnName="id", nullable=false) - * @Groups({"default"}) - */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'CompositeItem', inversedBy: 'compositeValues')] + #[ORM\JoinColumn(name: 'composite_item_id', referencedColumnName: 'id', nullable: false)] + #[Groups(['default'])] private $compositeItem; - - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="CompositeLabel") - * @ORM\JoinColumn(name="composite_label_id", referencedColumnName="id", nullable=false) - * @Groups({"default"}) - */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'CompositeLabel')] + #[ORM\JoinColumn(name: 'composite_label_id', referencedColumnName: 'id', nullable: false)] + #[Groups(['default'])] private $compositeLabel; /** diff --git a/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php b/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php index e37ccc48d58..9ed6cc11c03 100644 --- a/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php +++ b/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; @@ -21,18 +21,16 @@ * Concrete Dummy. * * @author Jérémy Derusse - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class ConcreteDummy extends AbstractDummy { /** * @var string a concrete thing - * - * @ORM\Column - * @Assert\NotBlank */ + #[ORM\Column] + #[Assert\NotBlank] private $instance; public function setInstance($instance) diff --git a/tests/Fixtures/TestBundle/Entity/ContainNonResource.php b/tests/Fixtures/TestBundle/Entity/ContainNonResource.php index a6c2dd5198a..b1d0236609f 100644 --- a/tests/Fixtures/TestBundle/Entity/ContainNonResource.php +++ b/tests/Fixtures/TestBundle/Entity/ContainNonResource.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\NotAResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,41 +21,25 @@ /** * Resource linked to a standard object. * - * @ORM\Entity - * - * @ApiResource( - * attributes={ - * "filters"={"my_dummy.property"} - * }, - * normalizationContext={ - * "groups"={"contain_non_resource"} - * } - * ) - * * @author Kévin Dunglas */ +#[ApiResource(filters: ['my_dummy.property'], normalizationContext: ['groups' => ['contain_non_resource']])] +#[ORM\Entity] class ContainNonResource { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups("contain_non_resource") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups('contain_non_resource')] public $id; - /** * @var ContainNonResource - * - * @Groups("contain_non_resource") */ + #[Groups('contain_non_resource')] public $nested; - /** * @var NotAResource - * - * @Groups("contain_non_resource") */ + #[Groups('contain_non_resource')] public $notAResource; } diff --git a/tests/Fixtures/TestBundle/Entity/Content.php b/tests/Fixtures/TestBundle/Entity/Content.php index 5edf39c6623..21eb1f0430b 100644 --- a/tests/Fixtures/TestBundle/Entity/Content.php +++ b/tests/Fixtures/TestBundle/Entity/Content.php @@ -13,60 +13,31 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Enum\ContentStatus; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * normalizationContext={ - * "groups"={"get_content"}, - * }, - * ) - * - * @ORM\Entity - */ +#[ApiResource(normalizationContext: ['groups' => ['get_content']])] +#[ORM\Entity] class Content implements \JsonSerializable { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column(type="string") - */ - private $contentType; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string')] + private ?string $contentType = null; /** * @var Collection - * - * @ORM\OneToMany( - * targetEntity=Field::class, - * mappedBy="content", - * cascade={"persist"}, - * orphanRemoval=true, - * indexBy="name", - * ) - * @ORM\OrderBy({"id"="ASC"}) */ - private $fields; - - /** - * @var string - * - * @ORM\Column(type="string") - */ - private $status; + #[ORM\OneToMany(targetEntity: Field::class, mappedBy: 'content', cascade: ['persist'], orphanRemoval: true, indexBy: 'name')] + #[ORM\OrderBy(['id' => 'ASC'])] + private \Doctrine\Common\Collections\Collection $fields; + #[ORM\Column(type: 'string')] + private readonly string $status; public function __construct() { @@ -74,17 +45,13 @@ public function __construct() $this->status = ContentStatus::DRAFT; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getId(): ?int { return $this->id; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getContentType(): ?string { return $this->contentType; @@ -113,7 +80,6 @@ public function addField(Field $field): void if ($this->hasField($field->getName())) { throw new \InvalidArgumentException(sprintf("Content already has '%s' field", $field->getName())); } - $this->fields[$field->getName()] = $field; $field->setContent($this); } @@ -121,16 +87,13 @@ public function addField(Field $field): void public function removeField(Field $field): void { unset($this->fields[$field->getName()]); - // set the owning side to null (unless already changed) if ($field->getContent() === $this) { $field->setContent(null); } } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getFieldValues(): array { $fieldValues = []; @@ -141,9 +104,7 @@ public function getFieldValues(): array return $fieldValues; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getStatus(): ContentStatus { return new ContentStatus($this->status); @@ -157,10 +118,6 @@ public function getStatus(): ContentStatus #[\ReturnTypeWillChange] public function jsonSerialize() { - return [ - 'id' => $this->id, - 'contentType' => $this->contentType, - 'fields' => $this->fields, - ]; + return ['id' => $this->id, 'contentType' => $this->contentType, 'fields' => $this->fields]; } } diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php b/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php index 82a162ab7fa..fc3d59a0395 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php @@ -13,32 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - * @ApiFilter(BooleanFilter::class) - */ +#[ApiFilter(BooleanFilter::class)] +#[ApiResource] +#[ORM\Entity] class ConvertedBoolean { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var bool - * - * @ORM\Column(type="boolean") */ + #[ORM\Column(type: 'boolean')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedDate.php b/tests/Fixtures/TestBundle/Entity/ConvertedDate.php index 2ac10c4bae8..c160926efc4 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedDate.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedDate.php @@ -13,32 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - * @ApiFilter(DateFilter::class) - */ +#[ApiFilter(DateFilter::class)] +#[ApiResource] +#[ORM\Entity] class ConvertedDate { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var \DateTime - * - * @ORM\Column(type="date") */ + #[ORM\Column(type: 'date')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php b/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php index fea4365608b..73f2f1f98e6 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php @@ -13,36 +13,28 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\NumericFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - * @ApiFilter(NumericFilter::class, properties={"nameConverted"}) - * @ApiFilter(RangeFilter::class, properties={"nameConverted"}) - * @ApiFilter(OrderFilter::class, properties={"nameConverted"}) - */ +#[ApiFilter(NumericFilter::class, properties: ['nameConverted'])] +#[ApiFilter(RangeFilter::class, properties: ['nameConverted'])] +#[ApiFilter(OrderFilter::class, properties: ['nameConverted'])] +#[ApiResource] +#[ORM\Entity] class ConvertedInteger { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var int - * - * @ORM\Column(type="integer") */ + #[ORM\Column(type: 'integer')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php index bc48be22175..527bfa3e1b0 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php @@ -13,32 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - * @ApiFilter(SearchFilter::class, properties={"nameConverted.nameConverted"="partial"}) - */ +#[ApiFilter(SearchFilter::class, properties: ['nameConverted.nameConverted' => 'partial'])] +#[ApiResource] +#[ORM\Entity] class ConvertedOwner { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var ConvertedRelated|null - * - * @ORM\ManyToOne(targetEntity="ConvertedRelated") */ + #[ORM\ManyToOne(targetEntity: 'ConvertedRelated')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php b/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php index c8adbc83e6c..44cd596f5ce 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php @@ -13,29 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class ConvertedRelated { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column(type="string") */ + #[ORM\Column(type: 'string')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedString.php b/tests/Fixtures/TestBundle/Entity/ConvertedString.php index 5cc47430d48..e74d72f4e61 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedString.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedString.php @@ -13,32 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\ExistsFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - * @ApiFilter(ExistsFilter::class, properties={"nameConverted"}) - */ +#[ApiFilter(ExistsFilter::class, properties: ['nameConverted'])] +#[ApiResource] +#[ORM\Entity] class ConvertedString { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string|null - * - * @ORM\Column(type="string", nullable=true) */ + #[ORM\Column(type: 'string', nullable: true)] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php b/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php index 4b82412cad5..37aa3934d19 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php @@ -13,43 +13,25 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity - * @ApiResource(itemOperations={ - * "get", - * "get_custom"={"method"="GET", "path"="custom_action_collection_dummies/{id}"}, - * "custom_normalization"={"route_name"="custom_normalization", "method"="GET"}, - * "short_custom_normalization"={"route_name"="short_custom_normalization", "method"="GET"}, - * }, - * collectionOperations={ - * "get", - * "get_custom"={"method"="GET", "path"="custom_action_collection_dummies"}, - * "custom_denormalization"={"route_name"="custom_denormalization", "method"="POST"}, - * "short_custom_denormalization"={"route_name"="short_custom_denormalization", "method"="GET"}, - * }) - * * @author Kévin Dunglas */ +#[ApiResource(operations: [new Get(), new Get(uriTemplate: 'custom_action_collection_dummies/{id}'), new Get(routeName: 'custom_normalization'), new Get(routeName: 'short_custom_normalization'), new GetCollection(), new GetCollection(uriTemplate: 'custom_action_collection_dummies'), new Post(routeName: 'custom_denormalization'), new GetCollection(routeName: 'short_custom_denormalization')])] +#[ORM\Entity] class CustomActionDummy { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column - */ - private $foo = ''; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column] + private string $foo = ''; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php b/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php index 58cbe190cd0..b37d968a25d 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php +++ b/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php @@ -13,26 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Custom identifier. - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class CustomGeneratedIdentifier { - /** - * @var mixed - * - * @ORM\Id - * @ORM\Column(type="string") - * @ORM\GeneratedValue(strategy="CUSTOM") - * @ORM\CustomIdGenerator(class="ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\UuidGenerator") - */ - private $id; + #[ORM\Id] + #[ORM\Column(type: 'string')] + #[ORM\GeneratedValue(strategy: 'CUSTOM')] + #[ORM\CustomIdGenerator(class: \ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\UuidGenerator::class)] + private ?string $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php index 7f47550d7cc..e93ed077334 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php @@ -13,32 +13,28 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Custom Identifier Dummy. - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class CustomIdentifierDummy { /** * @var int The custom identifier - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $customId; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $customId = null; /** * @var string The dummy name - * - * @ORM\Column(length=30) */ - private $name; + #[ORM\Column(length: 30)] + private ?string $name = null; public function getCustomId(): int { diff --git a/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php index 6ef2c1b9e18..e9d777e2285 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php @@ -13,39 +13,34 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; /** * Custom Identifier Dummy. - * - * @ApiResource(compositeIdentifier=false) - * @ORM\Entity */ +#[ApiResource(uriVariables: ['firstId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['firstId']), 'secondId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['secondId'])])] +#[ORM\Entity] class CustomMultipleIdentifierDummy { /** * @var int The custom identifier - * - * @ORM\Column(type="integer") - * @ORM\Id */ - private $firstId; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + private ?int $firstId = null; /** * @var int The custom identifier - * - * @ORM\Column(type="integer") - * @ORM\Id */ - private $secondId; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + private ?int $secondId = null; /** * @var string The dummy name - * - * @ORM\Column(length=30) */ - private $name; + #[ORM\Column(length: 30)] + private ?string $name = null; public function getFirstId(): int { diff --git a/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php b/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php index edb7685fccf..471c6375749 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,43 +23,36 @@ * Custom Normalized Dummy. * * @author Mikaël Labrut - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"output"}}, - * "denormalization_context"={"groups"={"input"}} - * }) - * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['output']], denormalizationContext: ['groups' => ['input']])] +#[ORM\Entity] class CustomNormalizedDummy { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"input", "output"}) */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['input', 'output'])] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"input", "output"}) */ - private $name; + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['input', 'output'])] + private ?string $name = null; /** * @var string|null The dummy name alias - * - * @ORM\Column(nullable=true) - * @ApiProperty(iri="https://schema.org/alternateName") - * @Groups({"input", "output"}) */ - private $alias; + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[ORM\Column(nullable: true)] + #[Groups(['input', 'output'])] + private ?string $alias = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php index 5df74ba433b..15f6da268e1 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php @@ -13,31 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Custom Writable Identifier Dummy. - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class CustomWritableIdentifierDummy { /** * @var string The special identifier - * - * @ORM\Column(name="slug", type="string", length=30) - * @ORM\Id */ - private $slug; - + #[ORM\Column(name: 'slug', type: 'string', length: 30)] + #[ORM\Id] + private ?string $slug = null; /** * @var string The dummy name - * - * @ORM\Column(name="name", type="string", length=30) */ - private $name; + #[ORM\Column(name: 'name', type: 'string', length: 30)] + private ?string $name = null; /** * @param string $slug diff --git a/tests/Fixtures/TestBundle/Entity/Customer.php b/tests/Fixtures/TestBundle/Entity/Customer.php index fdac6244361..9b1cd169869 100644 --- a/tests/Fixtures/TestBundle/Entity/Customer.php +++ b/tests/Fixtures/TestBundle/Entity/Customer.php @@ -13,38 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class Customer { - /** - * @var int - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"order_read"}) - */ - private $id; - - /** - * @ORM\Column(type="string") - * @Groups({"order_read"}) - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['order_read'])] + private ?int $id = null; + #[ORM\Column(type: 'string')] + #[Groups(['order_read'])] public $name; - - /** - * @ORM\ManyToMany(targetEntity="Address") - * @ORM\JoinColumn(nullable=false) - * @Groups({"order_read"}) - */ + #[ORM\ManyToMany(targetEntity: 'Address')] + #[ORM\JoinColumn(nullable: false)] + #[Groups(['order_read'])] public $addresses; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php b/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php index 501d11af9b4..08a86a93c55 100644 --- a/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php +++ b/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php @@ -13,29 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource(deprecationReason="This resource is deprecated") - * @ORM\Entity - * * @author Kévin Dunglas */ +#[ApiResource(deprecationReason: 'This resource is deprecated')] +#[ORM\Entity] class DeprecatedResource { - /** - * @ORM\Id - * @ORM\Column - */ + #[ORM\Id] + #[ORM\Column] public $id; - /** - * @var string - * - * @ApiProperty(attributes={"deprecation_reason"="This field is deprecated"}) - * @ORM\Column - */ - public $deprecatedField; + #[ApiProperty(deprecationReason: 'This field is deprecated')] + #[ORM\Column] + public string $deprecatedField; } diff --git a/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php b/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php index e2636a48db2..9ef9fbcc74a 100644 --- a/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php +++ b/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php @@ -14,40 +14,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Action\NotFoundAction; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource( - * collectionOperations={ - * "get", - * }, - * itemOperations={ - * "get"={ - * "controller"=NotFoundAction::class, - * "read"=false, - * "output"=false, - * }, - * }, - * ) - * @ORM\Entity - */ +#[ApiResource(operations: [new Get(controller: NotFoundAction::class, read: false, output: false), new GetCollection()])] +#[ORM\Entity] class DisableItemOperation { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] public $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Dummy.php b/tests/Fixtures/TestBundle/Entity/Dummy.php index 00e44f10566..e0ec439d089 100644 --- a/tests/Fixtures/TestBundle/Entity/Dummy.php +++ b/tests/Fixtures/TestBundle/Entity/Dummy.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; @@ -25,147 +25,120 @@ * Dummy. * * @author Kévin Dunglas - * - * @ApiResource(attributes={ - * "filters"={ - * "my_dummy.boolean", - * "my_dummy.date", - * "my_dummy.exists", - * "my_dummy.numeric", - * "my_dummy.order", - * "my_dummy.range", - * "my_dummy.search", - * "my_dummy.property" - * } - * }) - * @ORM\Entity */ +#[ApiResource(filters: ['my_dummy.boolean', 'my_dummy.date', 'my_dummy.exists', 'my_dummy.numeric', 'my_dummy.order', 'my_dummy.range', 'my_dummy.search', 'my_dummy.property'])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy')], status: 200, filters: ['my_dummy.boolean', 'my_dummy.date', 'my_dummy.exists', 'my_dummy.numeric', 'my_dummy.order', 'my_dummy.range', 'my_dummy.search', 'my_dummy.property'], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy')], status: 200, filters: ['my_dummy.boolean', 'my_dummy.date', 'my_dummy.exists', 'my_dummy.numeric', 'my_dummy.order', 'my_dummy.range', 'my_dummy.search', 'my_dummy.property'], operations: [new Get()])] +#[ORM\Entity] class Dummy { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") */ - private $name; + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + private ?string $name = null; /** * @var string|null The dummy name alias - * - * @ORM\Column(nullable=true) - * @ApiProperty(iri="https://schema.org/alternateName") */ + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[ORM\Column(nullable: true)] private $alias; /** * @var array foo */ - private $foo; + private ?array $foo = null; /** * @var string|null A short description of the item - * - * @ORM\Column(nullable=true) - * @ApiProperty(iri="https://schema.org/description") */ + #[ApiProperty(types: ['http://schema.org/description'])] + #[ORM\Column(nullable: true)] public $description; /** * @var string|null A dummy - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $dummy; /** * @var bool|null A dummy boolean - * - * @ORM\Column(type="boolean", nullable=true) */ - public $dummyBoolean; + #[ORM\Column(type: 'boolean', nullable: true)] + public $dummyBoolean; /** * @var \DateTime|null A dummy date - * - * @ORM\Column(type="datetime", nullable=true) - * @ApiProperty(iri="http://schema.org/DateTime") */ + #[ApiProperty(types: ['http://schema.org/DateTime'])] + #[ORM\Column(type: 'datetime', nullable: true)] public $dummyDate; /** * @var float|null A dummy float - * - * @ORM\Column(type="float", nullable=true) */ + #[ORM\Column(type: 'float', nullable: true)] public $dummyFloat; /** * @var string|null A dummy price - * - * @ORM\Column(type="decimal", precision=10, scale=2, nullable=true) */ + #[ORM\Column(type: 'decimal', precision: 10, scale: 2, nullable: true)] public $dummyPrice; /** * @var RelatedDummy|null A related dummy - * - * @ORM\ManyToOne(targetEntity="RelatedDummy") - * @ApiProperty(push=true) */ + #[ApiProperty(push: true)] + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] public $relatedDummy; /** - * @var Collection Several dummies - * - * @ORM\ManyToMany(targetEntity="RelatedDummy") - * @ApiSubresource + * @var \Collection Several dummies */ + #[ORM\ManyToMany(targetEntity: 'RelatedDummy')] public $relatedDummies; /** * @var array|null serialize data - * - * @ORM\Column(type="json", nullable=true) */ + #[ORM\Column(type: 'json', nullable: true)] public $jsonData; /** * @var array|null - * - * @ORM\Column(type="simple_array", nullable=true) */ + #[ORM\Column(type: 'simple_array', nullable: true)] public $arrayData; /** * @var string|null - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $nameConverted; /** * @var RelatedOwnedDummy|null - * - * @ORM\OneToOne(targetEntity="RelatedOwnedDummy", cascade={"persist"}, mappedBy="owningDummy") */ + #[ORM\OneToOne(targetEntity: 'RelatedOwnedDummy', cascade: ['persist'], mappedBy: 'owningDummy')] public $relatedOwnedDummy; /** * @var RelatedOwningDummy|null - * - * @ORM\OneToOne(targetEntity="RelatedOwningDummy", cascade={"persist"}, inversedBy="ownedDummy") */ + #[ORM\OneToOne(targetEntity: 'RelatedOwningDummy', cascade: ['persist'], inversedBy: 'ownedDummy')] public $relatedOwningDummy; public static function staticMethod() @@ -298,7 +271,6 @@ public function getRelatedOwnedDummy() public function setRelatedOwnedDummy(RelatedOwnedDummy $relatedOwnedDummy) { $this->relatedOwnedDummy = $relatedOwnedDummy; - if ($this !== $this->relatedOwnedDummy->getOwningDummy()) { $this->relatedOwnedDummy->setOwningDummy($this); } diff --git a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php index 7bda8e1f077..0170447827f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php +++ b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php @@ -13,52 +13,46 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; /** * Dummy Aggregate Offer. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_products/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class DummyAggregateOffer { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** - * @var Collection - * - * @ApiSubresource - * @ORM\OneToMany(targetEntity="DummyOffer", mappedBy="aggregate", cascade={"persist"}) + * @var \Collection */ - private $offers; - + #[ORM\OneToMany(targetEntity: 'DummyOffer', mappedBy: 'aggregate', cascade: ['persist'])] + private \Collection $offers; /** * @var DummyProduct|null The dummy product - * - * @ORM\ManyToOne(targetEntity="DummyProduct", inversedBy="offers") */ - private $product; - + #[ORM\ManyToOne(targetEntity: 'DummyProduct', inversedBy: 'offers')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct $product = null; /** * @var int The dummy aggregate offer value - * - * @ORM\Column(type="integer") */ + #[ORM\Column(type: 'integer')] private $value; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/DummyBoolean.php b/tests/Fixtures/TestBundle/Entity/DummyBoolean.php index ba37166cadc..27c4bcf237d 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/DummyBoolean.php @@ -13,34 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class DummyBoolean { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var bool|null - * - * @ORM\Column(type="boolean", nullable=true) - */ - private $isDummyBoolean; - - public function __construct(bool $isDummyBoolean) + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + public function __construct(#[ORM\Column(type: 'boolean', nullable: true)] private readonly ?bool $isDummyBoolean) { - $this->isDummyBoolean = $isDummyBoolean; } public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyCar.php b/tests/Fixtures/TestBundle/Entity/DummyCar.php index cd1385b2db0..602626d8caf 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCar.php @@ -13,123 +13,78 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Serializer\Filter\GroupFilter; use ApiPlatform\Serializer\Filter\PropertyFilter; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ApiResource( - * itemOperations={"get"={"swagger_context"={"tags"={}}, "openapi_context"={"tags"={}}}, "put", "delete"}, - * attributes={ - * "sunset"="2050-01-01", - * "normalization_context"={"groups"={"colors"}} - * } - * ) - * @ORM\Entity - * @ApiFilter(DateFilter::class, strategy=DateFilter::EXCLUDE_NULL) - * @ApiFilter(BooleanFilter::class) - * @ApiFilter(PropertyFilter::class, arguments={"parameterName"="foobar"}) - * @ApiFilter(GroupFilter::class, arguments={"parameterName"="foobargroups"}) - * @ApiFilter(GroupFilter::class, arguments={"parameterName"="foobargroups_override"}, id="override") - */ +#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)] +#[ApiFilter(BooleanFilter::class)] +#[ApiFilter(PropertyFilter::class, arguments: ['parameterName' => 'foobar'])] +#[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups'])] +#[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups_override'], id: 'override')] +#[ApiResource(operations: [new Get(openapiContext: ['tags' => []]), new Put(), new Delete(), new Post(), new GetCollection()], sunset: '2050-01-01', normalizationContext: ['groups' => ['colors']])] +#[ORM\Entity] class DummyCar { /** * @var DummyCarIdentifier The entity Id - * - * @ORM\Id - * @ORM\OneToOne(targetEntity="DummyCarIdentifier", cascade={"persist"}) */ - private $id; - + #[ORM\Id] + #[ORM\OneToOne(targetEntity: 'DummyCarIdentifier', cascade: ['persist'])] + private readonly \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarIdentifier $id; /** * @var mixed Something else - * - * @ORM\OneToMany(targetEntity="DummyCarColor", mappedBy="car") - * - * @Serializer\Groups({"colors"}) - * @ApiFilter(SearchFilter::class, properties={"colors.prop"="ipartial", "colors"="exact"}) */ + #[ApiFilter(SearchFilter::class, properties: ['colors.prop' => 'ipartial', 'colors' => 'exact'])] + #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] + #[Serializer\Groups(['colors'])] private $colors; - /** * @var mixed Something else - * - * @ORM\OneToMany(targetEntity="DummyCarColor", mappedBy="car") - * - * @Serializer\Groups({"colors"}) - * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $secondColors; - + #[ApiFilter(SearchFilter::class, strategy: 'exact')] + #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] + #[Serializer\Groups(['colors'])] + private mixed $secondColors = null; /** * @var mixed Something else - * - * @ORM\OneToMany(targetEntity="DummyCarColor", mappedBy="car") - * - * @Serializer\Groups({"colors"}) - * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $thirdColors; - + #[ApiFilter(SearchFilter::class, strategy: 'exact')] + #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] + #[Serializer\Groups(['colors'])] + private mixed $thirdColors = null; /** * @var mixed Something else - * - * @ORM\ManyToMany(targetEntity="UuidIdentifierDummy", indexBy="uuid") - * * @ORM\JoinTable(name="uuid_cars", - * joinColumns={@ORM\JoinColumn(name="car_id", referencedColumnName="id_id")}, - * inverseJoinColumns={@ORM\JoinColumn(name="uuid_uuid", referencedColumnName="uuid")} - * ) - * @Serializer\Groups({"colors"}) - * @ApiFilter(SearchFilter::class, strategy="exact") - */ - private $uuid; - - /** - * @var string - * - * @ORM\Column(type="string") - * @ApiFilter(SearchFilter::class, strategy="partial") - */ - private $name; - - /** - * @var bool - * - * @ORM\Column(type="boolean") - */ - private $canSell; - - /** - * @var \DateTime - * - * @ORM\Column(type="datetime") - */ - private $availableAt; - - /** - * @var string - * - * @Serializer\Groups({"colors"}) - * @Serializer\SerializedName("carBrand") - * - * @ORM\Column - */ - private $brand = 'DummyBrand'; - - /** - * @var DummyCarInfo - * - * @ORM\Embedded(class="DummyCarInfo") */ - private $info; + #[ApiFilter(SearchFilter::class, strategy: 'exact')] + #[ORM\ManyToMany(targetEntity: 'UuidIdentifierDummy', indexBy: 'uuid')] + #[Serializer\Groups(['colors'])] + private mixed $uuid = null; + #[ApiFilter(SearchFilter::class, strategy: 'partial')] + #[ORM\Column(type: 'string')] + private ?string $name = null; + #[ORM\Column(type: 'boolean')] + private ?bool $canSell = null; + #[ORM\Column(type: 'datetime')] + private ?\DateTime $availableAt = null; + #[Serializer\Groups(['colors'])] + #[Serializer\SerializedName('carBrand')] + #[ORM\Column] + private string $brand = 'DummyBrand'; + #[ORM\Embedded(class: 'DummyCarInfo')] + private \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarInfo $info; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php index 08468c15058..70bf44e4563 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php @@ -13,47 +13,33 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class DummyCarColor { /** * @var int The entity Id - * - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ - private $id; - - /** - * @var DummyCar - * - * @ORM\ManyToOne(targetEntity="DummyCar", inversedBy="colors") - * @ORM\JoinColumn(nullable=false, onDelete="CASCADE", referencedColumnName="id_id") - * @Assert\NotBlank - */ - private $car; - - /** - * @var string - * - * @ORM\Column(nullable=false) - * @ApiFilter(SearchFilter::class) - * @Assert\NotBlank - * - * @Serializer\Groups({"colors"}) */ - private $prop = ''; + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] + private ?int $id = null; + #[ORM\ManyToOne(targetEntity: 'DummyCar', inversedBy: 'colors')] + #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE', referencedColumnName: 'id_id')] + #[Assert\NotBlank] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar $car = null; + #[ApiFilter(SearchFilter::class)] + #[ORM\Column(nullable: false)] + #[Assert\NotBlank] + #[Serializer\Groups(['colors'])] + private string $prop = ''; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyCarIdentifier.php b/tests/Fixtures/TestBundle/Entity/DummyCarIdentifier.php index aa2b822ae46..89fe64e3699 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCarIdentifier.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCarIdentifier.php @@ -15,19 +15,15 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ -class DummyCarIdentifier +#[ORM\Entity] +class DummyCarIdentifier implements \Stringable { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - public function __toString() + public function __toString(): string { return (string) $this->id; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyCarInfo.php b/tests/Fixtures/TestBundle/Entity/DummyCarInfo.php index 51209343b30..9b789f873a3 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCarInfo.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCarInfo.php @@ -17,15 +17,13 @@ /** * @author Sergey Balasov - * - * @ORM\Embeddable */ +#[ORM\Embeddable] class DummyCarInfo { /** * @var string - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $name; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php b/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php index e8bb542f332..9d85b7a94be 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php @@ -13,31 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource(attributes={"formats"={"xml", "jsonld", "csv"={"text/csv"}, "pdf"="application/pdf"}}) - * @ORM\Entity - */ +#[ApiResource(formats: ['xml', 'jsonld', 'csv' => ['text/csv'], 'pdf' => 'application/pdf'])] +#[ORM\Entity] class DummyCustomFormat { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** * @var string - * - * @ORM\Column - * @Assert\NotBlank */ + #[ORM\Column] + #[Assert\NotBlank] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php index d14ccdb0f86..f2a483a62cf 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php @@ -13,81 +13,32 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Dummy with a custom GraphQL mutation resolver. * - * @ORM\Entity - * @ApiResource(graphql={ - * "sum"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNotPersisted"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNoWriteCustomResult"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "write"=false - * }, - * "sumOnlyPersist"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "read"=false, - * "deserialize"=false, - * "validate"=false, - * "serialize"=false - * }, - * "testCustomArguments"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "args"={"operandC"={"type"="Int!"}} - * } - * }) - * * @author Raoul Clais */ +#[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']])])] +#[ORM\Entity] class DummyCustomMutation { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - */ - private $operandA; - - /** - * @var int|null - * - * @Groups({"sum"}) - * @ORM\Column(type="integer", nullable=true) - */ - private $operandB; - - /** - * @var int|null - * - * @Groups({"result"}) - * @ORM\Column(type="integer", nullable=true) - */ - private $result; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'integer', nullable: true)] + private ?int $operandA = null; + #[Groups(['sum'])] + #[ORM\Column(type: 'integer', nullable: true)] + private ?int $operandB = null; + #[Groups(['result'])] + #[ORM\Column(type: 'integer', nullable: true)] + private ?int $result = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php index 56240c35a35..f6d7d64c8b4 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php @@ -13,73 +13,31 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; /** * Dummy with custom GraphQL query resolvers. * * @author Lukas Lücke - * - * @ApiResource(graphql={ - * "testItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item" - * }, - * "testNotRetrievedItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_not_retrieved_item", - * "args"={} - * }, - * "testNoReadAndSerializeItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize", - * "read"=false, - * "serialize"=false - * }, - * "testItemCustomArguments"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item", - * "args"={ - * "id"={"type"="ID"}, - * "customArgumentNullableBool"={"type"="Boolean"}, - * "customArgumentBool"={"type"="Boolean!"}, - * "customArgumentInt"={"type"="Int!"}, - * "customArgumentString"={"type"="String!"}, - * "customArgumentFloat"={"type"="Float!"}, - * "customArgumentIntArray"={"type"="[Int!]!"}, - * "customArgumentCustomType"={"type"="DateTime!"} - * } - * }, - * "testCollection"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection" - * }, - * "testCollectionNoReadAndSerialize"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize", - * "read"=false, - * "serialize"=false - * }, - * "testCollectionCustomArguments"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection", - * "args"={ - * "customArgumentString"={"type"="String!"} - * } - * } - * }) - * @ORM\Entity */ +#[ApiResource(graphQlOperations: [new Query(name: 'testItem', resolver: 'app.graphql.query_resolver.dummy_custom_item'), new Query(name: 'testNotRetrievedItem', resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item', args: []), new Query(name: 'testNoReadAndSerializeItem', resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize', read: false, serialize: false), new Query(name: 'testItemCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_item', args: ['id' => ['type' => 'ID'], 'customArgumentNullableBool' => ['type' => 'Boolean'], 'customArgumentBool' => ['type' => 'Boolean!'], 'customArgumentInt' => ['type' => 'Int!'], 'customArgumentString' => ['type' => 'String!'], 'customArgumentFloat' => ['type' => 'Float!'], 'customArgumentIntArray' => ['type' => '[Int!]!'], 'customArgumentCustomType' => ['type' => 'DateTime!']]), new QueryCollection(name: 'testCollection', resolver: 'app.graphql.query_resolver.dummy_custom_collection'), new QueryCollection(name: 'testCollectionNoReadAndSerialize', resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false), new QueryCollection(name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']])])] +#[ORM\Entity] class DummyCustomQuery { /** * @var int - * - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] public $id; - /** * @var string */ public $message; - /** * @var array */ diff --git a/tests/Fixtures/TestBundle/Entity/DummyDate.php b/tests/Fixtures/TestBundle/Entity/DummyDate.php index ff34bbed65c..899b92fde20 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDate.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDate.php @@ -13,66 +13,54 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Dummy Date. * * @author Antoine Bluchet - * - * @ApiResource(attributes={ - * "filters"={"my_dummy_date.date"} - * }) - * @ApiFilter(SearchFilter::class, properties={"dummyDate"}) - * @ApiFilter(DateFilter::class, properties={ - * "dateIncludeNullAfter"=DateFilter::INCLUDE_NULL_AFTER, - * "dateIncludeNullBefore"=DateFilter::INCLUDE_NULL_BEFORE, - * "dateIncludeNullBeforeAndAfter"=DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER - * }) - * - * @ORM\Entity */ +#[ApiFilter(DateFilter::class, properties: [ + 'dateIncludeNullAfter' => DateFilter::INCLUDE_NULL_AFTER, + 'dateIncludeNullBefore' => DateFilter::INCLUDE_NULL_BEFORE, + 'dateIncludeNullBeforeAndAfter' => DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER, +])] +#[ApiFilter(SearchFilter::class, properties: ['dummyDate'])] +#[ApiResource(filters: ['my_dummy_date.date'])] +#[ORM\Entity] class DummyDate { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var \DateTime The dummy date - * - * @ORM\Column(type="date") */ + #[ORM\Column(type: 'date')] public $dummyDate; - /** * @var \DateTime|null - * - * @ORM\Column(type="date", nullable=true) */ + #[ORM\Column(type: 'date', nullable: true)] public $dateIncludeNullAfter; - /** * @var \DateTime|null - * - * @ORM\Column(type="date", nullable=true) */ + #[ORM\Column(type: 'date', nullable: true)] public $dateIncludeNullBefore; - /** * @var \DateTime|null - * - * @ORM\Column(type="date", nullable=true) */ + #[ORM\Column(type: 'date', nullable: true)] public $dateIncludeNullBeforeAndAfter; /** diff --git a/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php b/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php index 71470f01e32..80219ba60eb 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,42 +23,31 @@ * Dummy with different serialization groups for item_query and collection_query. * * @author Mahmood Bazdar - * - * @ApiResource( - * graphql={ - * "item_query"={"normalization_context"={"groups"={"item_query"}}}, - * "collection_query"={"normalization_context"={"groups"={"collection_query"}}} - * } - * ) - * @ORM\Entity */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['item_query']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['collection_query']])])] +#[ORM\Entity] class DummyDifferentGraphQlSerializationGroup { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"item_query", "collection_query"}) */ - private $id; - + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['item_query', 'collection_query'])] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column - * @Groups({"item_query", "collection_query"}) */ - private $name; - + #[ORM\Column] + #[Groups(['item_query', 'collection_query'])] + private ?string $name = null; /** * @var string|null The dummy title - * - * @ORM\Column(nullable=true) - * @Groups({"item_query"}) */ - private $title; + #[ORM\Column(nullable: true)] + #[Groups(['item_query'])] + private ?string $title = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php index acf177fb630..f6e3eae814b 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php @@ -13,44 +13,39 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomInputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomOutputDto; use Doctrine\ORM\Mapping as ORM; /** * DummyDtoCustom. - * - * @ORM\Entity - * - * @ApiResource( - * collectionOperations={"post"={"input"=CustomInputDto::class}, "get", "custom_output"={"output"=CustomOutputDto::class, "path"="dummy_dto_custom_output", "method"="GET"}, "post_without_output"={"output"=false, "method"="POST", "path"="dummy_dto_custom_post_without_output"}}, - * itemOperations={"get", "custom_output"={"output"=CustomOutputDto::class, "method"="GET", "path"="dummy_dto_custom_output/{id}"}, "put", "delete"} - * ) */ +#[ApiResource(operations: [new Get(), new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}'), new Put(), new Delete(), new Post(input: CustomInputDto::class), new GetCollection(), new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output'), new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output')])] +#[ORM\Entity] class DummyDtoCustom { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; - /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php index 51c35321713..fd64076d9df 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use Doctrine\Common\Collections\ArrayCollection; @@ -24,40 +24,35 @@ * Dummy InputOutput. * * @author Kévin Dunglas - * - * @ApiResource(attributes={"input"=InputDto::class, "output"=OutputDto::class}) - * @ORM\Entity */ +#[ApiResource(input: InputDto::class, output: OutputDto::class)] +#[ORM\Entity] class DummyDtoInputOutput { public function __construct() { $this->relatedDummies = new ArrayCollection(); } - /** * @var int The id - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - /** * @var string - * @ORM\Column(type="string") */ + #[ORM\Column(type: 'string')] public $str; - /** * @var float - * @ORM\Column(type="float") */ + #[ORM\Column(type: 'float')] public $num; - /** * @var Collection - * @ORM\ManyToMany(targetEntity="RelatedDummy") */ + #[ORM\ManyToMany(targetEntity: 'RelatedDummy')] public $relatedDummies; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php index 937223861ac..126627ce62f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php @@ -13,7 +13,11 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\CreateItemAction; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\DoubleBatAction; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; @@ -23,57 +27,27 @@ * DummyDtoNoInput. * * @author Vincent Chalamon - * - * @ORM\Entity - * - * @ApiResource( - * attributes={ - * "input"=false, - * "output"=OutputDto::class - * }, - * collectionOperations={ - * "post"={ - * "method"="POST", - * "path"="/dummy_dto_no_inputs", - * "controller"=CreateItemAction::class, - * }, - * "get", - * }, - * itemOperations={ - * "get", - * "delete", - * "post_double_bat"={ - * "method"="POST", - * "path"="/dummy_dto_no_inputs/{id}/double_bat", - * "controller"=DoubleBatAction::class, - * "status"=200, - * }, - * }, - * ) */ +#[ApiResource(operations: [new Get(), new Delete(), new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200), new Post(uriTemplate: '/dummy_dto_no_inputs', controller: CreateItemAction::class), new GetCollection()], input: false, output: OutputDto::class)] +#[ORM\Entity] class DummyDtoNoInput { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; - /** * @var float - * - * @ORM\Column(type="float") */ + #[ORM\Column(type: 'float')] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php index 79e4b46cb1f..2b5e789f30c 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use Doctrine\ORM\Mapping as ORM; @@ -21,39 +21,27 @@ * DummyDtoNoOutput. * * @author Vincent Chalamon - * - * @ORM\Entity - * - * @ApiResource( - * attributes={ - * "input"=InputDto::class, - * "output"=false - * } - * ) */ +#[ApiResource(input: InputDto::class, output: false)] +#[ORM\Entity] class DummyDtoNoOutput { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; - /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php index 28cc949d384..e1d647f57b8 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDtoDummy; use Doctrine\ORM\Mapping as ORM; @@ -21,33 +21,27 @@ * Dummy InputOutput. * * @author Daniel West - * - * @ApiResource(attributes={"output"=OutputDtoDummy::class}) - * @ORM\Entity */ +#[ApiResource(output: OutputDtoDummy::class)] +#[ORM\Entity] class DummyDtoOutputFallbackToSameClass { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; - /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php index 6545480f116..277bdc9ba58 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php @@ -13,40 +13,34 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Dummy InputOutput. * * @author Daniel West - * - * @ApiResource(attributes={"output"=DummyDtoOutputSameClass::class}) - * @ORM\Entity */ +#[ApiResource(output: DummyDtoOutputSameClass::class)] +#[ORM\Entity] class DummyDtoOutputSameClass { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; - /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php b/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php index 9acbdee4ac1..d59b045f272 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php +++ b/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php @@ -13,71 +13,42 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\DummyObjectWithoutConstructor; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Dummy entity built with constructor. + * * https://github.com/api-platform/core/issues/1747. * * @author Maxime Veber - * - * @ApiResource( - * itemOperations={ - * "get", - * "put"={"denormalization_context"={"groups"={"put"}}} - * } - * ) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(denormalizationContext: ['groups' => ['put']]), new Post(), new GetCollection()])] +#[ORM\Entity] class DummyEntityWithConstructor { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column - */ - private $foo; - - /** - * @var string - * - * @ORM\Column - */ - private $bar; - - /** - * @var string|null - * - * @ORM\Column(nullable=true) - * @Groups({"put"}) - */ - private $baz; - - /** - * @var DummyObjectWithoutConstructor[] */ - private $items; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(nullable: true)] + #[Groups(['put'])] + private ?string $baz = null; /** * @param DummyObjectWithoutConstructor[] $items */ - public function __construct(string $foo, string $bar, array $items) + public function __construct(#[ORM\Column] private readonly string $foo, #[ORM\Column] private readonly string $bar, private readonly array $items) { - $this->foo = $foo; - $this->bar = $bar; - $this->items = $items; } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php index 6156b3afeeb..4a946430e1a 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php +++ b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php @@ -13,30 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class DummyForAdditionalFields { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** @ORM\Column */ - private $name; - /** @ORM\Column */ - private $slug; - public function __construct(string $name, string $slug) + public function __construct(#[ORM\Column] private readonly string $name, #[ORM\Column] private readonly string $slug) { - $this->name = $name; - $this->slug = $slug; } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php index d0be5c4941e..25ade655161 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php @@ -14,23 +14,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; -/** - * @ApiResource - */ +#[ApiResource] final class DummyForAdditionalFieldsInput { /** - * @ApiProperty(identifier=true) + * #[ApiProperty(identifier: true)]. */ public $id; - private $dummyName; - - public function __construct(string $dummyName) + public function __construct(private readonly string $dummyName) { - $this->dummyName = $dummyName; } public function getDummyName(): string diff --git a/tests/Fixtures/TestBundle/Entity/DummyFriend.php b/tests/Fixtures/TestBundle/Entity/DummyFriend.php index 8bc22120760..bceb0b587ae 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyFriend.php +++ b/tests/Fixtures/TestBundle/Entity/DummyFriend.php @@ -13,8 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,30 +24,27 @@ * Dummy Friend. * * @author Kévin Dunglas - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class DummyFriend { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"fakemanytomany", "friends"}) */ - private $name; + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['fakemanytomany', 'friends'])] + private ?string $name = null; /** * Get id. diff --git a/tests/Fixtures/TestBundle/Entity/DummyGroup.php b/tests/Fixtures/TestBundle/Entity/DummyGroup.php index 4089de74bdd..5586c0d1077 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyGroup.php +++ b/tests/Fixtures/TestBundle/Entity/DummyGroup.php @@ -13,7 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,78 +24,39 @@ * DummyGroup. * * @author Baptiste Meyer - * - * @ORM\Entity - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}}, - * "filters"={ - * "dummy_group.group", - * "dummy_group.override_group", - * "dummy_group.whitelist_group", - * "dummy_group.override_whitelist_group" - * } - * }, - * graphql={ - * "item_query"={"normalization_context"={"groups"={"dummy_foo"}}}, - * "collection_query"={"normalization_context"={"groups"={"dummy_foo"}}}, - * "delete", - * "create"={ - * "normalization_context"={"groups"={"dummy_bar"}}, - * "denormalization_context"={"groups"={"dummy_bar", "dummy_baz"}} - * } - * } - * ) */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['dummy_foo']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['dummy_foo']]), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_bar']], denormalizationContext: ['groups' => ['dummy_bar', 'dummy_baz']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_group.group', 'dummy_group.override_group', 'dummy_group.whitelist_group', 'dummy_group.override_whitelist_group'])] +#[ORM\Entity] class DummyGroup { - /** - * @var int|null - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"dummy", "dummy_read", "dummy_id"}) - */ - private $id; - + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['dummy', 'dummy_read', 'dummy_id'])] + private ?int $id = null; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_foo"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_foo'])] public $foo; - /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_bar"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_bar'])] public $bar; - /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_baz"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy', 'dummy_read', 'dummy_baz'])] public $baz; - /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy", "dummy_write", "dummy_qux"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy', 'dummy_write', 'dummy_qux'])] public $qux; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php b/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php index 138003fe91a..8bd65599afa 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php +++ b/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php @@ -13,33 +13,28 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Dummy Immutable Date. - * - * @ApiResource(attributes={ - * "filters"={"my_dummy_immutable_date.date"} - * }) - * @ORM\Entity */ +#[ApiResource(filters: ['my_dummy_immutable_date.date'])] +#[ORM\Entity] class DummyImmutableDate { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var \DateTimeImmutable The dummy date - * - * @ORM\Column(type="date_immutable") */ + #[ORM\Column(type: 'date_immutable')] public $dummyDate; /** diff --git a/tests/Fixtures/TestBundle/Entity/DummyMercure.php b/tests/Fixtures/TestBundle/Entity/DummyMercure.php index 5b6cba7fdd7..a105d78c0ab 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyMercure.php +++ b/tests/Fixtures/TestBundle/Entity/DummyMercure.php @@ -13,36 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity - * @ApiResource(mercure=true) - * * @author Kévin Dunglas */ +#[ApiResource(mercure: true)] +#[ORM\Entity] class DummyMercure { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - - /** - * @ORM\Column - */ + #[ORM\Column] public $name; - - /** - * @ORM\Column - */ + #[ORM\Column] public $description; - - /** - * @ORM\ManyToOne(targetEntity="RelatedDummy") - */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] public $relatedDummy; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php b/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php index 6561346bfb9..6f6106b9539 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php @@ -13,37 +13,31 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; /** * DummyNoGetOperation. * * @author Grégoire Hébert gregoire@les-tilleuls.coop - * - * @ORM\Entity - * - * @ApiResource( - * collectionOperations={"post"}, - * itemOperations={"put"} - * ) */ +#[ApiResource(operations: [new Put(), new Post()])] +#[ORM\Entity] class DummyNoGetOperation { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; public function setId($id) diff --git a/tests/Fixtures/TestBundle/Entity/DummyOffer.php b/tests/Fixtures/TestBundle/Entity/DummyOffer.php index f8cd95f67c8..83ca3822670 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyOffer.php +++ b/tests/Fixtures/TestBundle/Entity/DummyOffer.php @@ -13,42 +13,42 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; /** * Dummy Offer. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_aggregate_offers/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class DummyOffer { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var int The dummy aggregate offer value - * - * @ORM\Column(type="integer") */ - private $value; - + #[ORM\Column(type: 'integer')] + private ?int $value = null; /** * @var DummyAggregateOffer|null The dummy aggregate offer value - * - * @ORM\ManyToOne(targetEntity="DummyAggregateOffer", inversedBy="offers") */ - private $aggregate; + #[ORM\ManyToOne(targetEntity: 'DummyAggregateOffer', inversedBy: 'offers')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer $aggregate = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyPassenger.php b/tests/Fixtures/TestBundle/Entity/DummyPassenger.php index 5f6da5bd642..68f5271cfe1 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPassenger.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPassenger.php @@ -13,27 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class DummyPassenger { /** * @var int The entity Id - * - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ - private $id; - - /** - * @ORM\Column(type="string") */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] + private ?int $id = null; + #[ORM\Column(type: 'string')] public $nickname; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php index 1e0514f82ce..811bc29f14f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php @@ -9,37 +9,34 @@ * file that was distributed with this source code. */ -declare(strict_types=1); +declare (strict_types=1); namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use Doctrine\ORM\Mapping as ORM; - -/** - * @ORM\Entity - */ -#[ApiResource(description: "Hey PHP 8")] +#[ApiResource(description: 'Hey PHP 8')] +#[ORM\Entity] class DummyPhp8 { - /** - * @ORM\Id - * @ORM\Column(type="integer") - */ #[ApiProperty(identifier: true, description: 'the identifier')] + #[ORM\Id] + #[ORM\Column(type: 'integer')] public $id; - - /** - * @ORM\Column - */ #[ApiFilter(SearchFilter::class)] + #[ORM\Column] public $filtered; - #[ApiProperty(description: 'a foo')] - public function getFoo(): int + public function getFoo() : int { return 0; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyPhp8ApiPropertyAttribute.php b/tests/Fixtures/TestBundle/Entity/DummyPhp8ApiPropertyAttribute.php index f0ccca4b613..8f42706b746 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPhp8ApiPropertyAttribute.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPhp8ApiPropertyAttribute.php @@ -17,22 +17,16 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(description: 'Hey PHP 8')] +#[ORM\Entity] class DummyPhp8ApiPropertyAttribute { - /** - * @ORM\Id - * @ORM\Column(type="integer") - */ #[ApiProperty(identifier: true, description: 'the identifier')] + #[ORM\Id] + #[ORM\Column(type: 'integer')] public $id; - /** - * @ORM\Column - */ + #[ORM\Column] public $filtered; #[ApiProperty] diff --git a/tests/Fixtures/TestBundle/Entity/DummyProduct.php b/tests/Fixtures/TestBundle/Entity/DummyProduct.php index 3930d62aa14..df599baa2bd 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyProduct.php +++ b/tests/Fixtures/TestBundle/Entity/DummyProduct.php @@ -13,58 +13,48 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; /** * Dummy Product. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class DummyProduct { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** - * @var Collection - * - * @ApiSubresource - * @ORM\OneToMany(targetEntity="DummyAggregateOffer", mappedBy="product", cascade={"persist"}) + * @var \Collection */ - private $offers; - + #[ORM\OneToMany(targetEntity: 'DummyAggregateOffer', mappedBy: 'product', cascade: ['persist'])] + private \Collection $offers; /** * @var string The tour name - * - * @ORM\Column */ + #[ORM\Column] private $name; - - /** - * @var Collection - * - * @ApiSubresource - * @ORM\OneToMany(targetEntity="DummyProduct", mappedBy="parent") - */ - private $relatedProducts; - /** - * @ORM\ManyToOne(targetEntity="DummyProduct", inversedBy="relatedProducts") + * @var \Collection */ + #[ORM\OneToMany(targetEntity: 'DummyProduct', mappedBy: 'parent')] + private \Collection $relatedProducts; + #[ORM\ManyToOne(targetEntity: 'DummyProduct', inversedBy: 'relatedProducts')] private $parent; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/DummyProperty.php b/tests/Fixtures/TestBundle/Entity/DummyProperty.php index 5251bea16bb..7fd3cbd9c5b 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyProperty.php +++ b/tests/Fixtures/TestBundle/Entity/DummyProperty.php @@ -13,7 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,94 +25,51 @@ * DummyProperty. * * @author Baptiste Meyer - * - * @ORM\Entity - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}}, - * "filters"={ - * "dummy_property.property", - * "dummy_property.whitelist_property", - * "dummy_property.whitelisted_properties" - * } - * }, - * graphql={ - * "item_query", - * "collection_query", - * "update", - * "delete", - * "create"={ - * "normalization_context"={"groups"={"dummy_graphql_read"}}, - * } - * } - * ) */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query'), new Mutation(name: 'update'), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_graphql_read']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_property.property', 'dummy_property.whitelist_property', 'dummy_property.whitelisted_properties'])] +#[ORM\Entity] class DummyProperty { - /** - * @var int|null - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"dummy_read", "dummy_graphql_read"}) - */ - private $id; - + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['dummy_read', 'dummy_graphql_read'])] + private ?int $id = null; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read", "dummy_write"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read', 'dummy_write'])] public $foo; - /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $bar; - /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $baz; - /** * @var DummyGroup|null - * - * @ORM\ManyToOne(targetEntity=DummyGroup::class, cascade={"persist"}) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[ORM\ManyToOne(targetEntity: DummyGroup::class, cascade: ['persist'])] + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $group; - /** * @var Collection - * - * @ORM\ManyToMany(targetEntity=DummyGroup::class, cascade={"persist"}) - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[ORM\ManyToMany(targetEntity: DummyGroup::class, cascade: ['persist'])] + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $groups; - /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read'])] public $nameConverted; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php b/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php index 755893931c7..8aeed68c43a 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php @@ -13,47 +13,32 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * DummyPropertyWithDefaultValue. - * - * @ORM\Entity - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}} - * }) */ +#[ApiResource(normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']])] +#[ORM\Entity] class DummyPropertyWithDefaultValue { - /** - * @var int|null - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups("dummy_read") - */ - private $id; - + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups('dummy_read')] + private ?int $id = null; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read", "dummy_write"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read', 'dummy_write'])] public $foo = 'foo'; - /** * @var string A dummy with a Doctrine default options - * - * @ORM\Column(options={"default"="default value"}) */ + #[ORM\Column(options: ['default' => 'default value'])] public $dummyDefaultOption; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php index e6ee7fb9b03..5ab4ee6d8a8 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php @@ -13,51 +13,34 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - * @ORM\InheritanceType("JOINED") - * @ORM\DiscriminatorColumn(name="discr", type="string") - * @ORM\DiscriminatorMap({ - * "dummyTableInheritance"="DummyTableInheritance", - * "dummyTableInheritanceChild"="DummyTableInheritanceChild", - * "dummyTableInheritanceDifferentChild"="DummyTableInheritanceDifferentChild", - * "dummyTableInheritanceNotApiResourceChild"="DummyTableInheritanceNotApiResourceChild" - * }) - * @ApiResource - */ +#[ApiResource] +#[ORM\Entity] +#[ORM\InheritanceType('JOINED')] +#[ORM\DiscriminatorColumn(name: 'discr', type: 'string')] +#[ORM\DiscriminatorMap(['dummyTableInheritance' => 'DummyTableInheritance', 'dummyTableInheritanceChild' => 'DummyTableInheritanceChild', 'dummyTableInheritanceDifferentChild' => 'DummyTableInheritanceDifferentChild', 'dummyTableInheritanceNotApiResourceChild' => 'DummyTableInheritanceNotApiResourceChild'])] class DummyTableInheritance { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"default"}) */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['default'])] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column - * - * @Groups({"default"}) - */ - private $name; - - /** - * @var DummyTableInheritanceRelated|null - * - * @ORM\ManyToOne(targetEntity="DummyTableInheritanceRelated", inversedBy="children") - * @ORM\JoinColumn(nullable=true, onDelete="CASCADE") */ - private $parent; + #[ORM\Column] + #[Groups(['default'])] + private ?string $name = null; + #[ORM\ManyToOne(targetEntity: 'DummyTableInheritanceRelated', inversedBy: 'children')] + #[ORM\JoinColumn(nullable: true, onDelete: 'CASCADE')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceRelated $parent = null; public function getName(): ?string { diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php index 385c90f2cc4..8564988a11f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php @@ -13,23 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - * @ApiResource - */ +#[ApiResource] +#[ORM\Entity] class DummyTableInheritanceChild extends DummyTableInheritance { /** * @var string The dummy nickname - * - * @ORM\Column - * - * @Groups({"default"}) */ + #[ORM\Column] + #[Groups(['default'])] private $nickname; public function getNickname() diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php index d0d940405a7..0a8ba5c0f62 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php @@ -13,23 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - * @ApiResource - */ +#[ApiResource] +#[ORM\Entity] class DummyTableInheritanceDifferentChild extends DummyTableInheritance { /** * @var string The dummy email - * - * @ORM\Column - * - * @Groups({"default"}) */ + #[ORM\Column] + #[Groups(['default'])] private $email; public function getEmail() diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceNotApiResourceChild.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceNotApiResourceChild.php index 0cda91af305..1037906a912 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceNotApiResourceChild.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceNotApiResourceChild.php @@ -15,17 +15,14 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class DummyTableInheritanceNotApiResourceChild extends DummyTableInheritance { /** * @var bool The dummy swagg - * - * @ORM\Column(type="boolean") */ - private $swaggerThanParent; + #[ORM\Column(type: 'boolean')] + private bool $swaggerThanParent; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php index 60a57d5dc4e..a363fbc1207 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php @@ -13,43 +13,31 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"default"}}, - * "denormalization_context"={"groups"={"default"}} - * } - * ) - */ +#[ApiResource(normalizationContext: ['groups' => ['default']], denormalizationContext: ['groups' => ['default']])] +#[ORM\Entity] class DummyTableInheritanceRelated { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"default"}) */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['default'])] + private ?int $id = null; /** * @var Collection Related children - * - * @ORM\OneToMany(targetEntity="DummyTableInheritance", mappedBy="parent") - * @ORM\OrderBy({"id"="ASC"}) - * - * @Groups({"default"}) */ - private $children; + #[ORM\OneToMany(targetEntity: 'DummyTableInheritance', mappedBy: 'parent')] + #[ORM\OrderBy(['id' => 'ASC'])] + #[Groups(['default'])] + private \Doctrine\Common\Collections\Collection $children; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyTravel.php b/tests/Fixtures/TestBundle/Entity/DummyTravel.php index fbf3285b764..67e220ebbee 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTravel.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTravel.php @@ -13,36 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource(filters={"dummy_travel.property"}) - * @ORM\Entity - */ +#[ApiResource(filters: ['dummy_travel.property'])] +#[ORM\Entity] class DummyTravel { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - - /** - * @ORM\ManyToOne(targetEntity="DummyCar") - * @ORM\JoinColumn(name="car_id", referencedColumnName="id_id") - */ + #[ORM\ManyToOne(targetEntity: 'DummyCar')] + #[ORM\JoinColumn(name: 'car_id', referencedColumnName: 'id_id')] public $car; - - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: 'boolean')] public $confirmed; - /** - * @ORM\ManyToOne(targetEntity="DummyPassenger") - * @ORM\JoinColumn(name="passenger_id", referencedColumnName="id") - */ + #[ORM\ManyToOne(targetEntity: 'DummyPassenger')] + #[ORM\JoinColumn(name: 'passenger_id', referencedColumnName: 'id')] public $passenger; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyValidation.php b/tests/Fixtures/TestBundle/Entity/DummyValidation.php index a8721e2e9dd..45e192a7247 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyValidation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyValidation.php @@ -13,53 +13,44 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * @ApiResource( - * collectionOperations={ - * "get"={"method"="GET"}, - * "post"={"path"="dummy_validation.{_format}", "method"="POST"}, - * "post_validation_groups"={"route_name"="post_validation_groups", "validation_groups"={"a"}, "method"="GET"}, - * "post_validation_sequence"={"route_name"="post_validation_sequence", "validation_groups"="app.dummy_validation.group_generator", "method"="GET"} - * } - * ) - */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new Post(uriTemplate: 'dummy_validation.{_format}'), new GetCollection(routeName: 'post_validation_groups', validationContext: ['groups' => ['a']]), new GetCollection(routeName: 'post_validation_sequence', validationContext: ['groups' => 'app.dummy_validation.group_generator'])])] +#[ORM\Entity] class DummyValidation { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ORM\Column(nullable=true) - * @Assert\NotNull(groups={"a"}) */ - private $name; - + #[ORM\Column(nullable: true)] + #[Assert\NotNull(groups: ['a'])] + private ?string $name = null; /** * @var string|null The dummy title - * - * @ORM\Column(nullable=true) - * @Assert\NotNull(groups={"b"}) */ - private $title; - + #[ORM\Column(nullable: true)] + #[Assert\NotNull(groups: ['b'])] + private ?string $title = null; /** * @var string The dummy code - * @ORM\Column */ - private $code; + #[ORM\Column] + private ?string $code = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/EmbeddableDummy.php b/tests/Fixtures/TestBundle/Entity/EmbeddableDummy.php index 924b763a87b..54969d1acc7 100644 --- a/tests/Fixtures/TestBundle/Entity/EmbeddableDummy.php +++ b/tests/Fixtures/TestBundle/Entity/EmbeddableDummy.php @@ -21,52 +21,39 @@ * Embeddable Dummy. * * @author Jordan Samouh - * - * @ORM\Embeddable */ +#[ORM\Embeddable] class EmbeddableDummy { /** * @var string The dummy name - * - * @ORM\Column(nullable=true) - * @Groups({"embed"}) */ - private $dummyName; - + #[ORM\Column(nullable: true)] + #[Groups(['embed'])] + private ?string $dummyName = null; /** * @var bool|null A dummy boolean - * - * @ORM\Column(type="boolean", nullable=true) */ + #[ORM\Column(type: 'boolean', nullable: true)] public $dummyBoolean; - /** * @var \DateTime|null A dummy date - * - * @ORM\Column(type="datetime", nullable=true) - * @Assert\DateTime */ + #[ORM\Column(type: 'datetime', nullable: true)] + #[Assert\DateTime] public $dummyDate; - /** * @var float|null A dummy float - * - * @ORM\Column(type="float", nullable=true) */ + #[ORM\Column(type: 'float', nullable: true)] public $dummyFloat; - /** * @var string|null A dummy price - * - * @ORM\Column(type="decimal", precision=10, scale=2, nullable=true) */ + #[ORM\Column(type: 'decimal', precision: 10, scale: 2, nullable: true)] public $dummyPrice; - - /** - * @ORM\Column(type="string", nullable=true) - * @Groups({"barcelona", "chicago"}) - */ + #[ORM\Column(type: 'string', nullable: true)] + #[Groups(['barcelona', 'chicago'])] protected $symfony; public static function staticMethod() diff --git a/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php b/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php index 1900edf2ad3..962086052b6 100644 --- a/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -22,53 +27,40 @@ * Embedded Dummy. * * @author Jordan Samouh - * - * @ApiResource( - * attributes={"filters"={"my_dummy.search", "my_dummy.order", "my_dummy.date", "my_dummy.range", "my_dummy.boolean", "my_dummy.numeric"}}, - * itemOperations={"get", "put", "delete", "groups"={"method"="GET", "path"="/embedded_dummies_groups/{id}", "normalization_context"={"groups"={"embed"}}}} - * ) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(uriTemplate: '/embedded_dummies_groups/{id}', normalizationContext: ['groups' => ['embed']]), new Post(), new GetCollection()], filters: ['my_dummy.search', 'my_dummy.order', 'my_dummy.date', 'my_dummy.range', 'my_dummy.boolean', 'my_dummy.numeric'])] +#[ORM\Entity] class EmbeddedDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ORM\Column(nullable=true) - * @Groups({"embed"}) */ - private $name; - + #[ORM\Column(nullable: true)] + #[Groups(['embed'])] + private ?string $name = null; /** * @var \DateTime|null A dummy date - * - * @ORM\Column(type="datetime", nullable=true) - * @Assert\DateTime */ + #[ORM\Column(type: 'datetime', nullable: true)] + #[Assert\DateTime] public $dummyDate; - /** * @var EmbeddableDummy - * - * @ORM\Embedded(class="EmbeddableDummy") - * @Groups({"embed"}) */ + #[ORM\Embedded(class: 'EmbeddableDummy')] + #[Groups(['embed'])] public $embeddedDummy; - /** * @var RelatedDummy|null A related dummy - * - * @ORM\ManyToOne(targetEntity="RelatedDummy") */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] public $relatedDummy; public static function staticMethod() diff --git a/tests/Fixtures/TestBundle/Entity/Employee.php b/tests/Fixtures/TestBundle/Entity/Employee.php index ca970b747fb..202ea51c2c8 100644 --- a/tests/Fixtures/TestBundle/Entity/Employee.php +++ b/tests/Fixtures/TestBundle/Entity/Employee.php @@ -19,9 +19,6 @@ use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] #[Post] #[ApiResource( @@ -39,28 +36,25 @@ ] )] #[GetCollection] +#[ORM\Entity] class Employee { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] public string $name; - /** - * @ORM\ManyToOne(targetEntity="ApiPlatform\Tests\Fixtures\TestBundle\Entity\Company") - */ - public ?Company $company; + #[ORM\ManyToOne(targetEntity: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Company::class)] + public ?Company $company = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/ExternalUser.php b/tests/Fixtures/TestBundle/Entity/ExternalUser.php index 5346b2e6399..ee8a7d39ee2 100644 --- a/tests/Fixtures/TestBundle/Entity/ExternalUser.php +++ b/tests/Fixtures/TestBundle/Entity/ExternalUser.php @@ -13,18 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * @ApiResource - */ +#[ApiResource] +#[ORM\Entity] class ExternalUser extends AbstractUser { - /** - * @ORM\Column - */ + #[ORM\Column] private $externalId; public function getExternalId(): ?string diff --git a/tests/Fixtures/TestBundle/Entity/Field.php b/tests/Fixtures/TestBundle/Entity/Field.php index ddcc01f3c6f..b9df7e451ec 100644 --- a/tests/Fixtures/TestBundle/Entity/Field.php +++ b/tests/Fixtures/TestBundle/Entity/Field.php @@ -15,41 +15,20 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class Field implements \JsonSerializable { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var Content - * - * @ORM\ManyToOne(targetEntity=Content::class, inversedBy="fields") - * @ORM\JoinColumn(nullable=false) - */ - private $content; - - /** - * @var string - * - * @ORM\Column(type="string") - */ - private $name; - - /** - * @var string - * - * @ORM\Column(type="text") - */ - private $value; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\ManyToOne(targetEntity: Content::class, inversedBy: 'fields')] + #[ORM\JoinColumn(nullable: false)] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\Content $content = null; + #[ORM\Column(type: 'string')] + private ?string $name = null; + #[ORM\Column(type: 'text')] + private ?string $value = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/FileConfigDummy.php b/tests/Fixtures/TestBundle/Entity/FileConfigDummy.php index 64d2f4a9a5a..0cdd5053309 100644 --- a/tests/Fixtures/TestBundle/Entity/FileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Entity/FileConfigDummy.php @@ -17,34 +17,27 @@ /** * File Config Dummy. - * - * @ORM\Entity */ +#[ORM\Entity] class FileConfigDummy { - public const HYDRA_TITLE = 'File config Dummy'; - + final public const HYDRA_TITLE = 'File config Dummy'; /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] private $name; - /** * @var string - * - * @ORM\Column */ + #[ORM\Column] private $foo; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/FilterValidator.php b/tests/Fixtures/TestBundle/Entity/FilterValidator.php index 8b0c48593bb..df13aaf2028 100644 --- a/tests/Fixtures/TestBundle/Entity/FilterValidator.php +++ b/tests/Fixtures/TestBundle/Entity/FilterValidator.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayItemsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\BoundsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\EnumFilter; @@ -29,39 +29,22 @@ * Filter Validator entity. * * @author Julien Deniau - * - * @ApiResource(attributes={ - * "filters"={ - * ArrayItemsFilter::class, - * BoundsFilter::class, - * EnumFilter::class, - * LengthFilter::class, - * MultipleOfFilter::class, - * PatternFilter::class, - * RequiredFilter::class, - * RequiredAllowEmptyFilter::class - * } - * }) - * @ORM\Entity */ +#[ApiResource(filters: [ArrayItemsFilter::class, BoundsFilter::class, EnumFilter::class, LengthFilter::class, MultipleOfFilter::class, PatternFilter::class, RequiredFilter::class, RequiredAllowEmptyFilter::class])] +#[ORM\Entity] class FilterValidator { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string A name - * - * @ORM\Column - * @ApiProperty(iri="http://schema.org/name") */ - private $name; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + #[ApiProperty(types: ["http://schema.org/name"]) + #[ORM\Column] + private string $name; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/FlexConfig.php b/tests/Fixtures/TestBundle/Entity/FlexConfig.php index 7a3a33f8ebd..88669290ebd 100644 --- a/tests/Fixtures/TestBundle/Entity/FlexConfig.php +++ b/tests/Fixtures/TestBundle/Entity/FlexConfig.php @@ -17,16 +17,13 @@ /** * This entity is configure in tests/Fixtures/app/config/api_platform/flex.yaml. - * - * @ORM\Entity */ +#[ORM\Entity] class FlexConfig { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Foo.php b/tests/Fixtures/TestBundle/Entity/Foo.php index 2c0d3348fb3..242a4b3180f 100644 --- a/tests/Fixtures/TestBundle/Entity/Foo.php +++ b/tests/Fixtures/TestBundle/Entity/Foo.php @@ -13,55 +13,42 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; /** * Foo. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={ - * "order"={"bar", "name"="DESC"} - * }, - * graphql={ - * "item_query", - * "collection_query"={"pagination_enabled"=false}, - * "create", - * "delete" - * }, - * collectionOperations={ - * "get", - * "get_desc_custom"={"method"="GET", "path"="custom_collection_desc_foos", "order"={"name"="DESC"}}, - * "get_asc_custom"={"method"="GET", "path"="custom_collection_asc_foos", "order"={ "name"="ASC"}}, - * } - * ) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new GetCollection(uriTemplate: 'custom_collection_desc_foos', order: ['name' => 'DESC']), new GetCollection(uriTemplate: 'custom_collection_asc_foos', order: ['name' => 'ASC'])], graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query', paginationEnabled: false), new Mutation(name: 'create'), new Mutation(name: 'delete')], order: ['bar', 'name' => 'DESC'])] +#[ORM\Entity] class Foo { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The foo name - * - * @ORM\Column */ + #[ORM\Column] private $name; - /** * @var string The foo bar - * - * @ORM\Column */ + #[ORM\Column] private $bar; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/FooDummy.php b/tests/Fixtures/TestBundle/Entity/FooDummy.php index 672d4bea900..f86d52590a0 100644 --- a/tests/Fixtures/TestBundle/Entity/FooDummy.php +++ b/tests/Fixtures/TestBundle/Entity/FooDummy.php @@ -13,48 +13,36 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; /** * FooDummy. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={ - * "order"={"dummy.name"} - * }, - * graphql={ - * "collection_query"={"pagination_type"="page"} - * } - * ) - * @ORM\Entity */ +#[ApiResource(graphQlOperations: [new QueryCollection(name: 'collection_query', paginationType: 'page')], order: ['dummy.name'])] +#[ORM\Entity] class FooDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The foo name - * - * @ORM\Column */ + #[ORM\Column] private $name; - /** * @var Dummy|null The foo dummy - * - * @ORM\ManyToOne(targetEntity="Dummy", cascade={"persist"}) */ - private $dummy; + #[ORM\ManyToOne(targetEntity: 'Dummy', cascade: ['persist'])] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy $dummy = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/FourthLevel.php b/tests/Fixtures/TestBundle/Entity/FourthLevel.php index a00cef25524..40bdbe77ef8 100644 --- a/tests/Fixtures/TestBundle/Entity/FourthLevel.php +++ b/tests/Fixtures/TestBundle/Entity/FourthLevel.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,32 +23,28 @@ * Fourth Level. * * @author Alan Poulain - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/third_levels/{id}/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: ['id'], fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ORM\Entity] class FourthLevel { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ - private $id; - - /** - * @var int - * - * @ORM\Column(type="integer") - * @Groups({"barcelona", "chicago"}) - */ - private $level = 4; - - /** - * @ORM\OneToMany(targetEntity=ThirdLevel::class, cascade={"persist"}, mappedBy="badFourthLevel") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] + private ?int $id = null; + #[ORM\Column(type: 'integer')] + #[Groups(['barcelona', 'chicago'])] + private int $level = 4; + #[ORM\OneToMany(targetEntity: ThirdLevel::class, cascade: ['persist'], mappedBy: 'badFourthLevel')] public $badThirdLevel; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/Greeting.php b/tests/Fixtures/TestBundle/Entity/Greeting.php index 84eb5936e64..bb837e60f26 100644 --- a/tests/Fixtures/TestBundle/Entity/Greeting.php +++ b/tests/Fixtures/TestBundle/Entity/Greeting.php @@ -13,37 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ApiResource(uriTemplate: '/people/{id}/sent_greetings.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Person::class, identifiers: ['id'], toProperty: 'sender')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class Greeting { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - - /** - * @ORM\Column - */ + #[ORM\Column] public $message = ''; - - /** - * @ORM\ManyToOne(targetEntity="Person", inversedBy="sentGreetings") - * @ORM\JoinColumn(name="sender_id") - */ + #[ORM\ManyToOne(targetEntity: 'Person', inversedBy: 'sentGreetings')] + #[ORM\JoinColumn(name: 'sender_id')] public $sender; - - /** - * @ORM\ManyToOne(targetEntity="Person") - * @ORM\JoinColumn(name="recipient_id", nullable=true) - */ + #[ORM\ManyToOne(targetEntity: 'Person')] + #[ORM\JoinColumn(name: 'recipient_id', nullable: true)] public $recipient; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/InitializeInput.php b/tests/Fixtures/TestBundle/Entity/InitializeInput.php index 8059a8eb2ed..6e571a53a50 100644 --- a/tests/Fixtures/TestBundle/Entity/InitializeInput.php +++ b/tests/Fixtures/TestBundle/Entity/InitializeInput.php @@ -13,29 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InitializeInputDto; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource(input=InitializeInputDto::class) - * @ORM\Entity - */ +#[ApiResource(input: InitializeInputDto::class)] +#[ORM\Entity] class InitializeInput { - /** - * @ORM\Id - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] public $id; - - /** - * @ORM\Column - */ + #[ORM\Column] public $manager; - - /** - * @ORM\Column - */ + #[ORM\Column] public $name; } diff --git a/tests/Fixtures/TestBundle/Entity/InternalUser.php b/tests/Fixtures/TestBundle/Entity/InternalUser.php index a5cebccf664..065545f6787 100644 --- a/tests/Fixtures/TestBundle/Entity/InternalUser.php +++ b/tests/Fixtures/TestBundle/Entity/InternalUser.php @@ -15,14 +15,10 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class InternalUser extends AbstractUser { - /** - * @ORM\Column - */ + #[ORM\Column] private $internalId; public function getInternalId(): ?string diff --git a/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php b/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php index 9aceb5f7b8f..a944232e7da 100644 --- a/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php +++ b/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php @@ -13,39 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Dummy with iri_only. * * @author Pierre Thibaudeau - * - * @ApiResource( - * normalizationContext={ - * "iri_only"=true, - * "jsonld_embed_context"=true - * } - * ) - * @ORM\Entity */ +#[ApiResource(normalizationContext: ['iri_only' => true, 'jsonld_embed_context' => true])] +#[ORM\Entity] class IriOnlyDummy { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column(type="string") */ - private $foo; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string')] + private ?string $foo = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php b/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php index 8550e066d8c..8058c9a9714 100644 --- a/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php +++ b/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php @@ -13,41 +13,32 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Jsonld Context Dummy. - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class JsonldContextDummy { /** * @var int The id - * - * @ApiProperty(identifier=true) - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ApiProperty(identifier: true)] + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy person - * - * @ApiProperty( - * attributes={ - * "jsonld_context"={ - * "@id"="http://example.com/id", - * "@type"="@id", - * "foo"="bar" - * } - * }, - * ) */ + #[ApiProperty( + jsonldContext: ['@id' => 'https://example.com/id', '@type' => '@id', 'foo' => 'bar'] + )] private $person; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php b/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php index f9530a6384f..9818381d137 100644 --- a/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php @@ -13,7 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; @@ -21,59 +27,32 @@ * Secured resource with legacy access_control attribute. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={"access_control"="is_granted('ROLE_USER')"}, - * collectionOperations={ - * "get", - * "post"={"access_control"="is_granted('ROLE_ADMIN')"} - * }, - * itemOperations={ - * "get"={"access_control"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "put"={"access_control"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * }, - * graphql={ - * "item_query"={"access_control"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "delete"={}, - * "update"={"access_control"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * "create"={"access_control"="is_granted('ROLE_ADMIN')", "access_control_message"="Only admins can create a secured dummy."} - * } - * ) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Mutation(name: 'delete'), new Mutation(name: 'update', security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] +#[ORM\Entity] class LegacySecuredDummy { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The title - * - * @ORM\Column - * @Assert\NotBlank */ - private $title; - + #[ORM\Column] + #[Assert\NotBlank] + private ?string $title = null; /** * @var string The description - * - * @ORM\Column */ - private $description = ''; - + #[ORM\Column] + private string $description = ''; /** * @var string The owner - * - * @ORM\Column - * @Assert\NotBlank */ - private $owner; + #[ORM\Column] + #[Assert\NotBlank] + private ?string $owner = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php index 58c7a1fe0f5..68145c42e65 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php @@ -13,43 +13,33 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\MaxDepth; -/** * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"default"}, "enable_max_depth"=true}, - * "denormalization_context"={"groups"={"default"}, "enable_max_depth"=true} - * }) - * @ORM\Entity - * +/** * @author Brian Fox */ +#[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] +#[ORM\Entity] class MaxDepthDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"default"}) - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['default'])] private $id; - /** - * @ORM\Column(name="name", type="string", length=30) - * @Groups({"default"}) - */ + #[ORM\Column(name: 'name', type: 'string', length: 30)] + #[Groups(['default'])] public $name; - /** - * @ORM\ManyToOne(targetEntity="MaxDepthDummy", cascade={"persist"}) - * @ApiProperty(attributes={"fetch_eager"=false}) - * @Groups({"default"}) - * @MaxDepth(1) - */ + #[ApiProperty(fetchEager: false)] + #[ORM\ManyToOne(targetEntity: 'MaxDepthDummy', cascade: ['persist'])] + #[Groups(['default'])] + #[MaxDepth(1)] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php index 082c4e90e1b..decfa604b06 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php @@ -13,41 +13,32 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\MaxDepth; -/** * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"default"}, "enable_max_depth"=true}, - * "denormalization_context"={"groups"={"default"}, "enable_max_depth"=true} - * }) - * @ORM\Entity +/** + * * + * * * @author Brian Fox */ +#[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] +#[ORM\Entity] class MaxDepthEagerDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"default"}) - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['default'])] private $id; - - /** - * @ORM\Column(name="name", type="string", length=30) - * @Groups({"default"}) - */ + #[ORM\Column(name: 'name', type: 'string', length: 30)] + #[Groups(['default'])] public $name; - - /** - * @ORM\ManyToOne(targetEntity="MaxDepthEagerDummy", cascade={"persist"}) - * @Groups({"default"}) - * @MaxDepth(1) - */ + #[ORM\ManyToOne(targetEntity: 'MaxDepthEagerDummy', cascade: ['persist'])] + #[Groups(['default'])] + #[MaxDepth(1)] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php b/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php index ed1db8c4c5b..9b3ba1d9bd7 100644 --- a/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php +++ b/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php @@ -13,21 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Symfony\Messenger\Processor; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MessengerInput; -/** - * @ApiResource(messenger="input", input=MessengerInput::class, graphql={"create"={"input"=MessengerInput::class, "messenger"="input"}}) - */ +#[ApiResource( + graphQlOperations: [new Mutation(name: 'create', input: MessengerInput::class, processor: Processor::class)], + processor: Processor::class, + input: MessengerInput::class +)] class MessengerWithInput { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public $id; - /** - * @var string - */ - public $name; + + public string $name; } diff --git a/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php b/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php index 9a5b3ab3192..8086fbadc26 100644 --- a/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php +++ b/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php @@ -13,21 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Symfony\Messenger\Processor; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MessengerResponseInput; -/** - * @ApiResource(messenger="input", input=MessengerResponseInput::class) - */ +#[ApiResource(processor: Processor::class, input: MessengerResponseInput::class)] class MessengerWithResponse { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public $id; - /** - * @var string - */ - public $name; + + public string $name; } diff --git a/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php b/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php index 50e1ff91dec..a53282c9343 100644 --- a/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php @@ -14,25 +14,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::NET_PATH) - * @ORM\Entity - */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] +#[ApiResource(uriTemplate: '/network_path_relation_dummies/{id}/network_path_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\NetworkPathRelationDummy::class, identifiers: ['id'], toProperty: 'networkPathRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::NET_PATH, operations: [new GetCollection()])] +#[ORM\Entity] class NetworkPathDummy { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - - /** - * @ORM\ManyToOne(targetEntity="NetworkPathRelationDummy", inversedBy="networkPathDummies") - */ + #[ORM\ManyToOne(targetEntity: 'NetworkPathRelationDummy', inversedBy: 'networkPathDummies')] public $networkPathRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php b/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php index 2b3a973abe5..aaef9ffd342 100644 --- a/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php @@ -14,28 +14,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::NET_PATH) - * @ORM\Entity - */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] +#[ORM\Entity] class NetworkPathRelationDummy { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - - /** - * @ORM\OneToMany(targetEntity="NetworkPathDummy", mappedBy="networkPathRelationDummy") - * @ApiSubresource - */ + #[ORM\OneToMany(targetEntity: 'NetworkPathDummy', mappedBy: 'networkPathRelationDummy')] public $networkPathDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php b/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php index 9050019e2de..267c42a88ac 100644 --- a/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php @@ -13,25 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; /** * No Collection Dummy. - * - * @ApiResource(collectionOperations={}) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete()])] +#[ORM\Entity] class NoCollectionDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/NonRelationResource.php b/tests/Fixtures/TestBundle/Entity/NonRelationResource.php index c48f6bf4268..00b4d656b20 100644 --- a/tests/Fixtures/TestBundle/Entity/NonRelationResource.php +++ b/tests/Fixtures/TestBundle/Entity/NonRelationResource.php @@ -13,23 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\NonResourceClass; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class NonRelationResource { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** * @var NonResourceClass */ diff --git a/tests/Fixtures/TestBundle/Entity/OperationResource.php b/tests/Fixtures/TestBundle/Entity/OperationResource.php index 5fe30a480c9..955a72d204f 100644 --- a/tests/Fixtures/TestBundle/Entity/OperationResource.php +++ b/tests/Fixtures/TestBundle/Entity/OperationResource.php @@ -23,34 +23,17 @@ use ApiPlatform\Tests\Fixtures\TestBundle\State\OperationResourceProcessor; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(normalizationContext: ['skip_null_values' => true], processor: OperationResourceProcessor::class)] #[Get] #[Patch(inputFormats: ['json' => ['application/merge-patch+json']])] #[Post] #[Put] #[Delete] +#[ORM\Entity] class OperationResource { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ - #[ApiProperty(identifier: true)] - private $identifier; - - /** - * @var string - */ - public $name; - - public function __construct(int $identifier, string $name) + public function __construct(#[ApiProperty(identifier: true)] #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private readonly int $identifier, public string $name) { - $this->identifier = $identifier; - $this->name = $name; } public function getIdentifier() diff --git a/tests/Fixtures/TestBundle/Entity/Order.php b/tests/Fixtures/TestBundle/Entity/Order.php index 1d9b4f3e2a5..ef60d9fc4a8 100644 --- a/tests/Fixtures/TestBundle/Entity/Order.php +++ b/tests/Fixtures/TestBundle/Entity/Order.php @@ -13,44 +13,29 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource( - * attributes={"normalization_context"={"groups"={"order_read"}}}, - * forceEager=false - * ) - * @ORM\Entity - * @ORM\Table(name="`order`") - */ +#[ApiResource(normalizationContext: ['groups' => ['order_read']], forceEager: false)] +#[ORM\Entity] +#[ORM\Table(name: '`order`')] class Order { - /** - * @var int - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"order_read"}) - */ - private $id; - - /** - * @ORM\ManyToOne(targetEntity="Customer") - * @ORM\JoinColumn(nullable=false) - * @Groups({"order_read"}) - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['order_read'])] + private ?int $id = null; + #[ORM\ManyToOne(targetEntity: 'Customer')] + #[ORM\JoinColumn(nullable: false)] + #[Groups(['order_read'])] public $customer; - - /** - * @ORM\ManyToOne(targetEntity="Customer") - * @ORM\JoinColumn(nullable=false) - * @Assert\NotNull - * @Groups({"order_read"}) - */ + #[ORM\ManyToOne(targetEntity: 'Customer')] + #[ORM\JoinColumn(nullable: false)] + #[Assert\NotNull] + #[Groups(['order_read'])] public $recipient; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php b/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php index f91ece8bed6..5e4c28c9f96 100644 --- a/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php @@ -13,8 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,82 +28,46 @@ * Overridden Operation Dummy. * * @author Amrouche Hamza - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"overridden_operation_dummy_read"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_write"}} - * }, - * collectionOperations={ - * "get"={"method"="GET"}, - * "post"={"method"="POST"}, - * "swagger"={ - * "path"="/override/swagger", - * "method"="GET", - * } - * }, - * itemOperations={ - * "swagger"={ - * "method"="GET", - * }, - * "get"={ - * "method"="GET", - * "normalization_context"={"groups"={"overridden_operation_dummy_get"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_get"}} - * }, - * "put"={ - * "method"="PUT", - * "normalization_context"={"groups"={"overridden_operation_dummy_put"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_put"}} - * }, - * "delete"={"method"="DELETE"} - * } - * ) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Get(normalizationContext: ['groups' => ['overridden_operation_dummy_get']], denormalizationContext: ['groups' => ['overridden_operation_dummy_get']]), new Put(normalizationContext: ['groups' => ['overridden_operation_dummy_put']], denormalizationContext: ['groups' => ['overridden_operation_dummy_put']]), new Delete(), new GetCollection(), new Post(), new GetCollection(uriTemplate: '/override/swagger')], normalizationContext: ['groups' => ['overridden_operation_dummy_read']], denormalizationContext: ['groups' => ['overridden_operation_dummy_write']])] +#[ORM\Entity] class OverriddenOperationDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_write", "overridden_operation_dummy_get"}) - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get'])] private $name; /** * @var string|null The dummy name alias - * - * @ORM\Column(nullable=true) - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_put", "overridden_operation_dummy_get"}) - * @ApiProperty(iri="https://schema.org/alternateName") */ + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[ORM\Column(nullable: true)] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_put', 'overridden_operation_dummy_get'])] private $alias; /** * @var string|null A short description of the item - * - * @ORM\Column(nullable=true) - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_write", "overridden_operation_dummy_get", "overridden_operation_dummy_put"}) - * @ApiProperty(iri="https://schema.org/description") */ + #[ApiProperty(types: ['http://schema.org/description'])] + #[ORM\Column(nullable: true)] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get', 'overridden_operation_dummy_put'])] public $description; - /** - * @ORM\Column(nullable=true) - * @Groups({"overridden_operation_dummy_write"}) - */ + #[ORM\Column(nullable: true)] + #[Groups(['overridden_operation_dummy_write'])] public $notGettable; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/PaginationEntity.php b/tests/Fixtures/TestBundle/Entity/PaginationEntity.php index 4f586bdf8d6..5281ca038d0 100644 --- a/tests/Fixtures/TestBundle/Entity/PaginationEntity.php +++ b/tests/Fixtures/TestBundle/Entity/PaginationEntity.php @@ -20,8 +20,6 @@ /** * ProviderEntity. - * - * @ORM\Entity */ #[ApiResource] #[Get] @@ -30,16 +28,13 @@ paginationItemsPerPage: 5, paginationMaximumItemsPerPage: 30 )] +#[ORM\Entity] class PaginationEntity { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Entity/ParentDummy.php b/tests/Fixtures/TestBundle/Entity/ParentDummy.php index 21f9c890a9b..185830f8cb0 100644 --- a/tests/Fixtures/TestBundle/Entity/ParentDummy.php +++ b/tests/Fixtures/TestBundle/Entity/ParentDummy.php @@ -20,17 +20,15 @@ * Parent Dummy. * * @author Kévin Dunglas - * - * @ORM\MappedSuperclass */ +#[ORM\MappedSuperclass] class ParentDummy { /** * @var int|null The age - * - * @ORM\Column(type="integer", nullable=true) - * @Groups({"friends"}) */ + #[ORM\Column(type: 'integer', nullable: true)] + #[Groups(['friends'])] private $age; public function getAge() diff --git a/tests/Fixtures/TestBundle/Entity/PatchDummy.php b/tests/Fixtures/TestBundle/Entity/PatchDummy.php index 1a842597c29..aaa4bb7c718 100644 --- a/tests/Fixtures/TestBundle/Entity/PatchDummy.php +++ b/tests/Fixtures/TestBundle/Entity/PatchDummy.php @@ -13,31 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; /** * @author Kévin Dunglas - * - * @ApiResource( - * itemOperations={ - * "get", - * "patch"={"input_formats"={"json"={"application/merge-patch+json"}, "jsonapi"}} - * } - * ) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()])] +#[ORM\Entity] class PatchDummy { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - - /** - * @ORM\Column(nullable=true) - */ + #[ORM\Column(nullable: true)] public $name; } diff --git a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php index 0100c0854d9..221e39fc8af 100644 --- a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php @@ -13,38 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * @author Kévin Dunglas - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"chicago"}}, - * "denormalization_context"={"groups"={"chicago"}}, - * }, - * itemOperations={ - * "get", - * "patch"={"input_formats"={"json"={"application/merge-patch+json"}, "jsonapi"}} - * } - * ) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] +#[ORM\Entity] class PatchDummyRelation { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - - /** - * @ORM\ManyToOne(targetEntity="RelatedDummy") - * @Groups({"chicago"}) - */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[Groups(['chicago'])] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Entity/Payment.php b/tests/Fixtures/TestBundle/Entity/Payment.php index 6351fb11dea..21d728d7d9a 100644 --- a/tests/Fixtures/TestBundle/Entity/Payment.php +++ b/tests/Fixtures/TestBundle/Entity/Payment.php @@ -13,51 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\Payment\VoidPaymentAction; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ApiResource( - * itemOperations={ - * "get", - * "post_void"={ - * "method"="POST", - * "path"="/payments/{id}/void", - * "controller"=VoidPaymentAction::class, - * "deserialize"=false, - * }, - * }, - * ) - */ +#[ApiResource(operations: [new Get(), new Post(uriTemplate: '/payments/{id}/void', controller: VoidPaymentAction::class, deserialize: false), new Post(), new GetCollection()])] +#[ORM\Entity] class Payment { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column(type="decimal", precision=6, scale=2) - */ - private $amount; - - /** - * @ORM\OneToOne(targetEntity=VoidPayment::class, mappedBy="payment") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\OneToOne(targetEntity: VoidPayment::class, mappedBy: 'payment')] private $voidPayment; - public function __construct(string $amount) + public function __construct(#[ORM\Column(type: 'decimal', precision: 6, scale: 2)] private readonly string $amount) { - $this->amount = $amount; } public function getId(): ?int @@ -75,7 +50,6 @@ public function void(): void if (null !== $this->voidPayment) { return; } - $this->voidPayment = new VoidPayment($this); } diff --git a/tests/Fixtures/TestBundle/Entity/Person.php b/tests/Fixtures/TestBundle/Entity/Person.php index d21a6ea4415..f53b1b484a6 100644 --- a/tests/Fixtures/TestBundle/Entity/Person.php +++ b/tests/Fixtures/TestBundle/Entity/Person.php @@ -13,8 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -24,37 +23,25 @@ * Person. * * @author Antoine Bluchet - * - * @ApiResource(attributes={"normalization_context"={"groups"={"people.pets"}}}) - * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['people.pets']])] +#[ORM\Entity] class Person { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column(type="string") - * @Groups({"people.pets"}) - */ + #[ORM\Column(type: 'string')] + #[Groups(['people.pets'])] public $name; - /** - * @ORM\OneToMany(targetEntity="PersonToPet", mappedBy="person") - * @Groups({"people.pets"}) - * * @var Collection */ + #[ORM\OneToMany(targetEntity: 'PersonToPet', mappedBy: 'person')] + #[Groups(['people.pets'])] public $pets; - - /** - * @ApiSubresource - * @ORM\OneToMany(targetEntity="Greeting", mappedBy="sender") - */ + #[ORM\OneToMany(targetEntity: 'Greeting', mappedBy: 'sender')] public $sentGreetings; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/PersonToPet.php b/tests/Fixtures/TestBundle/Entity/PersonToPet.php index 9c9876577bd..8e098f5f91d 100644 --- a/tests/Fixtures/TestBundle/Entity/PersonToPet.php +++ b/tests/Fixtures/TestBundle/Entity/PersonToPet.php @@ -20,26 +20,23 @@ * PersonToPet. * * @author Antoine Bluchet - * @ORM\Entity */ +#[ORM\Entity] class PersonToPet { /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="Pet") - * @ORM\JoinColumn(referencedColumnName="id") - * @Groups({"people.pets"}) - * * @var Pet */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'Pet')] + #[ORM\JoinColumn(referencedColumnName: 'id')] + #[Groups(['people.pets'])] public $pet; - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="Person") - * @ORM\JoinColumn(referencedColumnName="id") - * * @var Person */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'Person')] + #[ORM\JoinColumn(referencedColumnName: 'id')] public $person; } diff --git a/tests/Fixtures/TestBundle/Entity/Pet.php b/tests/Fixtures/TestBundle/Entity/Pet.php index 159a67353eb..27ed27166c2 100644 --- a/tests/Fixtures/TestBundle/Entity/Pet.php +++ b/tests/Fixtures/TestBundle/Entity/Pet.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -23,30 +23,22 @@ * Pet. * * @author Antoine Bluchet - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class Pet { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column(type="string") - * @Groups({"people.pets"}) - */ + #[ORM\Column(type: 'string')] + #[Groups(['people.pets'])] public $name; - /** - * @ORM\OneToMany(targetEntity="PersonToPet", mappedBy="pet") - * * @var Collection */ + #[ORM\OneToMany(targetEntity: 'PersonToPet', mappedBy: 'pet')] public $people; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php b/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php index c40d98a67b5..398460c59a0 100644 --- a/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php +++ b/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php @@ -13,31 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Regression test for https://github.com/api-platform/api-platform/issues/1085. * * @author Antoine Bluchet - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class PlainObjectDummy { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** * @var string */ private $content; - /** * @var array */ @@ -46,7 +41,7 @@ class PlainObjectDummy public function setContent($content) { $this->content = $content; - $this->data = (array) json_decode($content); + $this->data = (array) json_decode($content, null, 512, \JSON_THROW_ON_ERROR); } public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ProcessorEntity.php b/tests/Fixtures/TestBundle/Entity/ProcessorEntity.php index 8264bbb95cd..76e8a3d737a 100644 --- a/tests/Fixtures/TestBundle/Entity/ProcessorEntity.php +++ b/tests/Fixtures/TestBundle/Entity/ProcessorEntity.php @@ -21,30 +21,21 @@ /** * ProcessorEntity. - * - * @ORM\Entity */ #[ApiResource] #[Get] #[Post] +#[ORM\Entity] class ProcessorEntity { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column - * @Assert\NotBlank - */ - private $foo; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + #[ORM\Column] + #[Assert\NotBlank] + private ?string $foo = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Entity/Product.php b/tests/Fixtures/TestBundle/Entity/Product.php index 5d101978b2f..f1c75a2ec0b 100644 --- a/tests/Fixtures/TestBundle/Entity/Product.php +++ b/tests/Fixtures/TestBundle/Entity/Product.php @@ -17,33 +17,17 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class Product implements ProductInterface { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column(type="string", unique=true) - */ - private $code; - - /** - * @var Taxon|null - * - * @ORM\ManyToOne(targetEntity=Taxon::class) - */ - private $mainTaxon; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string', unique: true)] + private ?string $code = null; + #[ORM\ManyToOne(targetEntity: Taxon::class)] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\Taxon $mainTaxon = null; /** * {@inheritdoc} diff --git a/tests/Fixtures/TestBundle/Entity/Program.php b/tests/Fixtures/TestBundle/Entity/Program.php index 5a6f3ea60ef..fc87e7ad4cc 100644 --- a/tests/Fixtures/TestBundle/Entity/Program.php +++ b/tests/Fixtures/TestBundle/Entity/Program.php @@ -17,32 +17,20 @@ /** * @author Vincent Chalamon - * - * @ORM\Entity */ +#[ORM\Entity] class Program { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column - */ + #[ORM\Column] public $name; - - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: 'datetime')] public $date; - - /** - * @ORM\ManyToOne(targetEntity=User::class) - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: false)] public $author; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ProviderEntity.php b/tests/Fixtures/TestBundle/Entity/ProviderEntity.php index cfa498dbdbc..f5a1c4012a5 100644 --- a/tests/Fixtures/TestBundle/Entity/ProviderEntity.php +++ b/tests/Fixtures/TestBundle/Entity/ProviderEntity.php @@ -22,31 +22,22 @@ /** * ProviderEntity. - * - * @ORM\Entity */ #[ApiResource] #[Get] #[GetCollection] #[Post] +#[ORM\Entity] class ProviderEntity { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column - * @Assert\NotBlank - */ - private $foo; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + #[ORM\Column] + #[Assert\NotBlank] + private ?string $foo = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Entity/Question.php b/tests/Fixtures/TestBundle/Entity/Question.php index 3943ca0a00a..09949775e3b 100644 --- a/tests/Fixtures/TestBundle/Entity/Question.php +++ b/tests/Fixtures/TestBundle/Entity/Question.php @@ -13,33 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * @ApiResource - */ +#[ApiResource] +#[ApiResource(uriTemplate: '/answers/{id}/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer::class, identifiers: ['id'], toProperty: 'answer')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/questions/{id}/answer/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], fromProperty: 'answer'), 'answer' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer::class, identifiers: [], expandedValue: 'answer', toProperty: 'answer')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class Question { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column(nullable=true) - */ + #[ORM\Column(nullable: true)] private $content; - - /** - * @ORM\OneToOne(targetEntity="Answer", inversedBy="question") - * @ORM\JoinColumn(name="answer_id", referencedColumnName="id", unique=true) - * @ApiSubresource - */ + #[ORM\OneToOne(targetEntity: 'Answer', inversedBy: 'question')] + #[ORM\JoinColumn(name: 'answer_id', referencedColumnName: 'id', unique: true)] private $answer; /** @@ -72,8 +65,6 @@ public function getId(): ?int /** * Set answer. - * - * @param Answer $answer */ public function setAnswer(Answer $answer = null): self { diff --git a/tests/Fixtures/TestBundle/Entity/RPC.php b/tests/Fixtures/TestBundle/Entity/RPC.php index 0647a570f91..2f3fac9d713 100644 --- a/tests/Fixtures/TestBundle/Entity/RPC.php +++ b/tests/Fixtures/TestBundle/Entity/RPC.php @@ -13,20 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RPCOutput; /** * RPC-like resource. - * - * @ApiResource( - * itemOperations={}, - * collectionOperations={ - * "post"={"status"=202, "messenger"=true, "path"="rpc", "output"=false}, - * "post_output"={"method"="POST", "status"=200, "path"="rpc_output", "output"=RPCOutput::class} - * }, - * ) */ +#[ApiResource(operations: [new Post(status: 202, messenger: true, uriTemplate: 'rpc', output: false), new Post(status: 200, uriTemplate: 'rpc_output', output: RPCOutput::class)])] class RPC { /** diff --git a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php index 87472305a71..b42c9236a82 100644 --- a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php @@ -13,31 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; -/** - * @ORM\Entity - * @ApiResource - */ +#[ApiResource] +#[ORM\Entity] class RamseyUuidDummy { - /** - * @var \Ramsey\Uuid\UuidInterface - * - * @ORM\Id - * @ORM\Column(type="uuid", unique=true) - */ - private $id; - - /** - * @var \Ramsey\Uuid\UuidInterface|null - * - * @ORM\Column(type="uuid", nullable=true) - */ - private $other; + #[ORM\Id] + #[ORM\Column(type: 'uuid', unique: true)] + private readonly \Ramsey\Uuid\UuidInterface $id; + #[ORM\Column(type: 'uuid', nullable: true)] + private ?\Ramsey\Uuid\UuidInterface $other = null; public function __construct(?UuidInterface $id = null) { diff --git a/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php b/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php index 40e44dcf4d5..7e3d5832441 100644 --- a/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php +++ b/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php @@ -13,32 +13,28 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class ReadableOnlyProperty { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The foo name - * - * @ORM\Column - * @ApiProperty(writable=false) */ - private $name; + #[ApiProperty(writable: false)] + #[ORM\Column] + private readonly string $name; public function __construct() { @@ -50,7 +46,7 @@ public function getId() return $this->id; } - public function setName($name) + public function setName($name): never { throw new \Exception('Can not write name.'); } diff --git a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php index f9b15024a2e..5cbbf05a777 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php @@ -13,9 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -26,73 +30,64 @@ * Related Dummy. * * @author Kévin Dunglas - * - * @ApiResource(graphql={"item_query", "update"={"normalization_context"={"groups"={"chicago", "fakemanytomany"}}, "denormalization_context"={"groups"={"friends"}}}}, iri="https://schema.org/Product", attributes={"normalization_context"={"groups"={"friends"}}, "filters"={"related_dummy.friends", "related_dummy.complex_sub_query"}}) - * @ORM\Entity */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']])], types: ['https://schema.org/Product'], normalizationContext: ['groups' => ['friends']], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ORM\Entity] class RelatedDummy extends ParentDummy { - /** - * @ApiProperty(writable=false) - * @ApiSubresource - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"chicago", "friends"}) - */ + #[ApiProperty(writable: false)] + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['chicago', 'friends'])] private $id; /** * @var string|null A name - * - * @ORM\Column(nullable=true) - * @Groups({"friends"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['friends'])] public $name; - /** - * @ORM\Column - * @Groups({"barcelona", "chicago", "friends"}) - */ + #[ORM\Column] + #[Groups(['barcelona', 'chicago', 'friends'])] protected $symfony = 'symfony'; /** * @var \DateTime|null A dummy date - * - * @ORM\Column(type="datetime", nullable=true) - * @Assert\DateTime - * @Groups({"friends"}) */ + #[ORM\Column(type: 'datetime', nullable: true)] + #[Assert\DateTime] + #[Groups(['friends'])] public $dummyDate; - /** - * @ApiSubresource - * @ORM\ManyToOne(targetEntity="ThirdLevel", cascade={"persist"}) - * @Groups({"barcelona", "chicago", "friends"}) - */ + #[ORM\ManyToOne(targetEntity: 'ThirdLevel', cascade: ['persist'])] + #[Groups(['barcelona', 'chicago', 'friends'])] public $thirdLevel; - /** - * @ApiSubresource - * @ORM\OneToMany(targetEntity="RelatedToDummyFriend", cascade={"persist"}, mappedBy="relatedDummy") - * @Groups({"fakemanytomany", "friends"}) - */ + #[ORM\OneToMany(targetEntity: 'RelatedToDummyFriend', cascade: ['persist'], mappedBy: 'relatedDummy')] + #[Groups(['fakemanytomany', 'friends'])] public $relatedToDummyFriend; /** * @var bool|null A dummy bool - * - * @ORM\Column(type="boolean", nullable=true) - * @Groups({"friends"}) */ + #[ORM\Column(type: 'boolean', nullable: true)] + #[Groups(['friends'])] public $dummyBoolean; /** * @var EmbeddableDummy - * - * @ORM\Embedded(class="EmbeddableDummy") - * @Groups({"friends"}) */ + #[ORM\Embedded(class: 'EmbeddableDummy')] + #[Groups(['friends'])] public $embeddedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php index 3d79617e3df..56216cdd0a1 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -25,41 +25,33 @@ * Related to Normalized Dummy. * * @author Amrouche Hamza - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"related_output", "output"}}, - * "denormalization_context"={"groups"={"related_input", "input"}} - * }) - * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['related_output', 'output']], denormalizationContext: ['groups' => ['related_input', 'input']])] +#[ORM\Entity] class RelatedNormalizedDummy { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"related_output", "related_input"}) */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['related_output', 'related_input'])] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"related_output", "related_input"}) */ - private $name; - + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['related_output', 'related_input'])] + private ?string $name = null; /** * @var Collection Several Normalized dummies - * - * @ORM\ManyToMany(targetEntity="CustomNormalizedDummy") - * @Groups({"related_output", "related_input"}) */ + #[ORM\ManyToMany(targetEntity: 'CustomNormalizedDummy')] + #[Groups(['related_output', 'related_input'])] public $customNormalizedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php index ceace5fb9ab..f13139a6150 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php @@ -13,41 +13,33 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Related Owned Dummy. * * @author Sergey V. Ryabov - * - * @ApiResource(iri="https://schema.org/Product") - * @ORM\Entity */ +#[ApiResource(types: ['https://schema.org/Product'])] +#[ORM\Entity] class RelatedOwnedDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** * @var string|null A name - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $name; - /** - * @var Dummy - * - * @ORM\OneToOne(targetEntity="Dummy", cascade={"persist"}, inversedBy="relatedOwnedDummy") - * @ORM\JoinColumn(nullable=false) - * @ApiSubresource + * @var \Dummy */ + #[ORM\OneToOne(targetEntity: 'Dummy', cascade: ['persist'], inversedBy: 'relatedOwnedDummy')] + #[ORM\JoinColumn(nullable: false)] public $owningDummy; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php index 0a8fc0589c8..b11b684a2f0 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php @@ -13,40 +13,32 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Related Owning Dummy. * * @author Sergey V. Ryabov - * - * @ApiResource(iri="https://schema.org/Product") - * @ORM\Entity */ +#[ApiResource(types: ['https://schema.org/Product'])] +#[ORM\Entity] class RelatedOwningDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** * @var string|null A name - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $name; - /** - * @var Dummy|null - * - * @ORM\OneToOne(targetEntity="Dummy", cascade={"persist"}, mappedBy="relatedOwningDummy") - * @ApiSubresource + * @var \Dummy|null */ + #[ORM\OneToOne(targetEntity: 'Dummy', cascade: ['persist'], mappedBy: 'relatedOwningDummy')] public $ownedDummy; public function getId() @@ -85,7 +77,6 @@ public function getOwnedDummy(): Dummy public function setOwnedDummy(Dummy $ownedDummy) { $this->ownedDummy = $ownedDummy; - if ($this !== $this->ownedDummy->getRelatedOwningDummy()) { $this->ownedDummy->setRelatedOwningDummy($this); } diff --git a/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php index 063a2bc5383..f18abb68506 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php @@ -13,34 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource( - * attributes={"security"="is_granted('ROLE_ADMIN')"}, - * collectionOperations={ - * "get"={"security"="is_granted('ROLE_ADMIN')"}, - * }, - * itemOperations={ - * "get"={"security"="is_granted('ROLE_ADMIN')"}, - * }, - * graphql={ - * "item_query"={"security"="is_granted('ROLE_ADMIN')"}, - * "collection_query"={"security"="is_granted('ROLE_ADMIN')"}, - * } - * ) - * @ORM\Entity - */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_ADMIN\')'), new GetCollection(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\')'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')')], security: 'is_granted(\'ROLE_ADMIN\')')] +#[ORM\Entity] class RelatedSecuredDummy { /** * @var int - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php b/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php index bee990b00a1..108c343108a 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php @@ -13,53 +13,50 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; /** * Related To Dummy Friend represent an association table for a manytomany relation. - * - * @ApiResource(attributes={"normalization_context"={"groups"={"fakemanytomany"}}, "filters"={"related_to_dummy_friend.name"}}) - * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['fakemanytomany']], filters: ['related_to_dummy_friend.name'])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ORM\Entity] class RelatedToDummyFriend { /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"fakemanytomany", "friends"}) */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['fakemanytomany', 'friends'])] private $name; - /** * @var string|null The dummy description - * - * @ORM\Column(nullable=true) - * @Groups({"fakemanytomany", "friends"}) - */ - private $description; - - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="DummyFriend") - * @ORM\JoinColumn(name="dummyfriend_id", referencedColumnName="id", nullable=false) - * @Groups({"fakemanytomany", "friends"}) - * @Assert\NotNull */ + #[ORM\Column(nullable: true)] + #[Groups(['fakemanytomany', 'friends'])] + private ?string $description = null; + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'DummyFriend')] + #[ORM\JoinColumn(name: 'dummyfriend_id', referencedColumnName: 'id', nullable: false)] + #[Groups(['fakemanytomany', 'friends'])] + #[Assert\NotNull] private $dummyFriend; - - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="RelatedDummy", inversedBy="relatedToDummyFriend") - * @ORM\JoinColumn(name="relateddummy_id", referencedColumnName="id", nullable=false, onDelete="CASCADE") - * @Assert\NotNull - */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'RelatedDummy', inversedBy: 'relatedToDummyFriend')] + #[ORM\JoinColumn(name: 'relateddummy_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] + #[Assert\NotNull] private $relatedDummy; public function setName($name) diff --git a/tests/Fixtures/TestBundle/Entity/Relation1.php b/tests/Fixtures/TestBundle/Entity/Relation1.php index cadf4f9cf28..501347320b5 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation1.php +++ b/tests/Fixtures/TestBundle/Entity/Relation1.php @@ -13,26 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource - * @ORM\Entity - * * @author Kévin Dunglas */ +#[ApiResource] +#[ORM\Entity] class Relation1 { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] public $id; - - /** - * @ORM\ManyToOne(targetEntity="Relation2", inversedBy="relation1s") - */ + #[ORM\ManyToOne(targetEntity: 'Relation2', inversedBy: 'relation1s')] public $relation2; } diff --git a/tests/Fixtures/TestBundle/Entity/Relation2.php b/tests/Fixtures/TestBundle/Entity/Relation2.php index 784ceb6dd86..61597d71a30 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation2.php +++ b/tests/Fixtures/TestBundle/Entity/Relation2.php @@ -13,28 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource - * @ORM\Entity - * * @author Kévin Dunglas */ +#[ApiResource] +#[ORM\Entity] class Relation2 { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] public $id; - - /** - * @ORM\OneToMany(targetEntity="Relation1", mappedBy="relation2") - */ + #[ORM\OneToMany(targetEntity: 'Relation1', mappedBy: 'relation2')] public $relation1s; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/Relation3.php b/tests/Fixtures/TestBundle/Entity/Relation3.php index fcc5e6aebd7..dd7acd4e412 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation3.php +++ b/tests/Fixtures/TestBundle/Entity/Relation3.php @@ -13,29 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class Relation3 { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] public $id; - /** * @var Collection - * @ORM\ManyToMany(targetEntity="Relation2", orphanRemoval=true) */ - private $relation2s; + #[ORM\ManyToMany(targetEntity: 'Relation2', orphanRemoval: true)] + private readonly \Doctrine\Common\Collections\Collection $relation2s; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php index 6a5784b5dc2..8eb6cc79e06 100644 --- a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php +++ b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,55 +26,26 @@ * Relation Embedder. * * @author Kévin Dunglas - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"barcelona"}}, - * "denormalization_context"={"groups"={"chicago"}}, - * "hydra_context"={"@type"="hydra:Operation", "hydra:title"="A custom operation", "returns"="xmls:string"} - * }, - * itemOperations={ - * "get", - * "put"={}, - * "delete", - * "custom_get"={"route_name"="relation_embedded.custom_get", "method"="GET"}, - * "custom1"={"path"="/api/custom-call/{id}", "method"="GET"}, - * "custom2"={"path"="/api/custom-call/{id}", "method"="PUT"}, - * } - * ) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(routeName: 'relation_embedded.custom_get'), new Get(uriTemplate: '/api/custom-call/{id}'), new Put(uriTemplate: '/api/custom-call/{id}'), new Post(), new GetCollection()], normalizationContext: ['groups' => ['barcelona']], denormalizationContext: ['groups' => ['chicago']], hydraContext: ['@type' => 'hydra:Operation', 'hydra:title' => 'A custom operation', 'returns' => 'xmls:string'])] +#[ORM\Entity] class RelationEmbedder { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - - /** - * @ORM\Column - * @Groups({"chicago"}) - */ + #[ORM\Column] + #[Groups(['chicago'])] public $paris = 'Paris'; - - /** - * @ORM\Column - * @Groups({"barcelona", "chicago"}) - */ + #[ORM\Column] + #[Groups(['barcelona', 'chicago'])] public $krondstadt = 'Krondstadt'; - - /** - * @ORM\ManyToOne(targetEntity="RelatedDummy", cascade={"persist"}) - * @Groups({"chicago", "barcelona"}) - */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy', cascade: ['persist'])] + #[Groups(['chicago', 'barcelona'])] public $anotherRelated; - - /** - * @ORM\ManyToOne(targetEntity="RelatedDummy") - * @Groups({"barcelona", "chicago"}) - */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[Groups(['barcelona', 'chicago'])] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php b/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php index 93a6bcc8f45..c4c65f0b1fa 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php @@ -13,30 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class ResourceWithBoolean { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var bool - * - * @ORM\Column(type="boolean") */ - private $myBooleanField = false; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'boolean')] + private bool $myBooleanField = false; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php b/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php index 41407e74951..026263a354d 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php @@ -13,30 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class ResourceWithFloat { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var float - * - * @ORM\Column(type="float") */ - private $myFloatField = 0.0; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'float')] + private float $myFloatField = 0.0; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php b/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php index be76f2571f8..c9221df653a 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php @@ -13,30 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class ResourceWithInteger { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var int - * - * @ORM\Column(type="integer") */ - private $myIntegerField = 0; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'integer')] + private int $myIntegerField = 0; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithString.php b/tests/Fixtures/TestBundle/Entity/ResourceWithString.php index 07020e1a4f1..731edc28985 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithString.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithString.php @@ -13,30 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class ResourceWithString { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column(type="string") */ - private $myStringField = ''; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string')] + private string $myStringField = ''; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/SecuredDummy.php b/tests/Fixtures/TestBundle/Entity/SecuredDummy.php index 198d8f39c35..c82f789baaa 100644 --- a/tests/Fixtures/TestBundle/Entity/SecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SecuredDummy.php @@ -13,8 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -24,147 +31,106 @@ * Secured resource. * * @author Kévin Dunglas - * - * @ApiResource( - * attributes={"security"="is_granted('ROLE_USER')"}, - * collectionOperations={ - * "get"={"security"="is_granted('ROLE_USER') or is_granted('ROLE_ADMIN')"}, - * "get_from_data_provider_generator"={ - * "method"="GET", - * "path"="custom_data_provider_generator", - * "security"="is_granted('ROLE_USER')" - * }, - * "post"={"security"="is_granted('ROLE_ADMIN')"} - * }, - * itemOperations={ - * "get"={"security"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "put"={"security_post_denormalize"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * }, - * graphql={ - * "item_query"={"security"="is_granted('ROLE_ADMIN') or (is_granted('ROLE_USER') and object.getOwner() == user)"}, - * "collection_query"={"security"="is_granted('ROLE_ADMIN')"}, - * "delete"={}, - * "update"={"security_post_denormalize"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * "create"={"security"="is_granted('ROLE_ADMIN')", "security_message"="Only admins can create a secured dummy."} - * } - * ) - * @ORM\Entity */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(security: 'is_granted(\'ROLE_USER\') or is_granted(\'ROLE_ADMIN\')'), new GetCollection(uriTemplate: 'custom_data_provider_generator', security: 'is_granted(\'ROLE_USER\')'), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\') or (is_granted(\'ROLE_USER\') and object.getOwner() == user)'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')'), new Mutation(name: 'delete'), new Mutation(name: 'update', securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] +#[ORM\Entity] class SecuredDummy { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The title - * - * @ORM\Column - * @Assert\NotBlank */ - private $title; + #[ORM\Column] + #[Assert\NotBlank] + private ?string $title = null; /** * @var string The description - * - * @ORM\Column */ - private $description = ''; + #[ORM\Column] + private string $description = ''; /** * @var string The dummy secret property, only readable/writable by specific users - * - * @ORM\Column - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ - private $adminOnlyProperty = ''; + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ORM\Column] + private ?string $adminOnlyProperty = ''; /** * @var string Secret property, only readable/writable by owners - * - * @ORM\Column - * @ApiProperty( - * security="object == null or object.getOwner() == user", - * securityPostDenormalize="object.getOwner() == user", - * ) */ - private $ownerOnlyProperty = ''; + #[ApiProperty(security: 'object == null or object.getOwner() == user', securityPostDenormalize: 'object.getOwner() == user')] + #[ORM\Column] + private ?string $ownerOnlyProperty = ''; /** * @var string The owner - * - * @ORM\Column - * @Assert\NotBlank */ - private $owner; + #[ORM\Column] + #[Assert\NotBlank] + private ?string $owner = null; /** * A collection of dummies that only admins can access. * * @var Collection Several dummies - * - * @ORM\ManyToMany(targetEntity="RelatedDummy") - * @ORM\JoinTable(name="secured_dummy_related_dummy") - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ORM\ManyToMany(targetEntity: 'RelatedDummy')] + #[ORM\JoinTable(name: 'secured_dummy_related_dummy')] public $relatedDummies; /** * A dummy that only admins can access. * * @var RelatedDummy|null - * - * @ORM\ManyToOne(targetEntity="RelatedDummy") - * @ORM\JoinColumn(name="related_dummy_id") - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[ORM\JoinColumn(name: 'related_dummy_id')] protected $relatedDummy; /** * A collection of dummies that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var Collection Several dummies - * - * @ORM\ManyToMany(targetEntity="RelatedSecuredDummy") - * @ORM\JoinTable(name="secured_dummy_related_secured_dummy") - * @ApiProperty(security="is_granted('ROLE_USER')") */ + #[ApiProperty(security: "is_granted('ROLE_USER')")] + #[ORM\ManyToMany(targetEntity: 'RelatedSecuredDummy')] + #[ORM\JoinTable(name: 'secured_dummy_related_secured_dummy')] public $relatedSecuredDummies; /** * A dummy that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var RelatedSecuredDummy|null - * - * @ORM\ManyToOne(targetEntity="RelatedSecuredDummy") - * @ORM\JoinColumn(name="related_secured_dummy_id") - * @ApiProperty(security="is_granted('ROLE_USER')") */ + #[ApiProperty(security: "is_granted('ROLE_USER')")] + #[ORM\ManyToOne(targetEntity: 'RelatedSecuredDummy')] + #[ORM\JoinColumn(name: 'related_secured_dummy_id')] protected $relatedSecuredDummy; /** * Collection of dummies that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * * @var Collection Several dummies - * - * @ORM\ManyToMany(targetEntity="RelatedSecuredDummy") - * @ORM\JoinTable(name="secured_dummy_public_related_secured_dummy") */ + #[ORM\ManyToMany(targetEntity: 'RelatedSecuredDummy')] + #[ORM\JoinTable(name: 'secured_dummy_public_related_secured_dummy')] public $publicRelatedSecuredDummies; /** * A dummy that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * * @var RelatedSecuredDummy|null - * - * @ORM\ManyToOne(targetEntity="RelatedSecuredDummy") - * @ORM\JoinColumn(name="public_related_secured_dummy_id") */ + #[ORM\ManyToOne(targetEntity: 'RelatedSecuredDummy')] + #[ORM\JoinColumn(name: 'public_related_secured_dummy_id')] protected $publicRelatedSecuredDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/SingleFileConfigDummy.php b/tests/Fixtures/TestBundle/Entity/SingleFileConfigDummy.php index b139fadd149..1299c20bd56 100644 --- a/tests/Fixtures/TestBundle/Entity/SingleFileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SingleFileConfigDummy.php @@ -17,25 +17,21 @@ /** * File Config Dummy. - * - * @ORM\Entity */ +#[ORM\Entity] class SingleFileConfigDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Site.php b/tests/Fixtures/TestBundle/Entity/Site.php index 15e4aa6a3d1..1dcfdd5d35f 100644 --- a/tests/Fixtures/TestBundle/Entity/Site.php +++ b/tests/Fixtures/TestBundle/Entity/Site.php @@ -13,33 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class Site { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column - */ + #[ORM\Column] private $title; - /** - * @ORM\Column - */ + #[ORM\Column] private $description; - /** - * @ORM\OneToOne(targetEntity="AbstractUser", cascade={"persist", "remove"}) - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\OneToOne(targetEntity: 'AbstractUser', cascade: ['persist', 'remove'])] + #[ORM\JoinColumn(nullable: false)] private $owner; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php b/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php index d8870357047..eb326ad96c8 100644 --- a/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php @@ -13,43 +13,36 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy::class, identifiers: ['slug'], toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], fromProperty: 'parentDummy'), 'parentDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy::class, identifiers: [], expandedValue: 'parent_dummy', toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class SlugChildDummy { /** * @var int|null The identifier - * - * @ApiProperty(identifier=false) - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ApiProperty(identifier: false)] + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The slug used as API identifier - * - * @ApiProperty(identifier=true) - * - * @ORM\Column(type="string", length=255, unique=true) */ - private $slug; + #[ApiProperty(identifier: true)] + #[ORM\Column(type: 'string', length: 255, unique: true)] + private ?string $slug = null; - /** - * @ORM\ManyToOne(targetEntity="ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy", inversedBy="childDummies") - * @ORM\JoinColumn(name="parent_dummy_id", referencedColumnName="id") - * - * @ApiSubresource - */ + #[ORM\ManyToOne(targetEntity: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy::class, inversedBy: 'childDummies')] + #[ORM\JoinColumn(name: 'parent_dummy_id', referencedColumnName: 'id')] private $parentDummy; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php b/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php index 6b60db60dc6..9d48c141ad3 100644 --- a/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php @@ -13,48 +13,42 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; /** * Custom Identifier Dummy With Subresource. - * - * @ApiResource(attributes={"identifiers"="slug"}) - * @ORM\Entity */ +#[ApiResource(uriVariables: 'slug')] +#[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies/{childDummies}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], toProperty: 'parentDummy'), 'childDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] +#[ORM\Entity] class SlugParentDummy { /** * @var int|null The database identifier - * - * @ApiProperty(identifier=false) - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ApiProperty(identifier: false)] + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The slug used a API identifier - * - * @ApiProperty(identifier=true) - * - * @ORM\Column(type="string", length=255, unique=true) */ - private $slug; - + #[ApiProperty(identifier: true)] + #[ORM\Column(type: 'string', length: 255, unique: true)] + private ?string $slug = null; /** - * @var Collection - * @ORM\OneToMany(targetEntity="ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy", mappedBy="parentDummy") - * - * @ApiSubresource + * @var \Collection */ - private $childDummies; + #[ORM\OneToMany(targetEntity: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy::class, mappedBy: 'parentDummy')] + private \Collection $childDummies; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/SoMany.php b/tests/Fixtures/TestBundle/Entity/SoMany.php index b2404392ea7..65a2ad93790 100644 --- a/tests/Fixtures/TestBundle/Entity/SoMany.php +++ b/tests/Fixtures/TestBundle/Entity/SoMany.php @@ -13,35 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * @ApiResource(attributes={ - * "pagination_partial"=true, - * "pagination_via_cursor"={ - * {"field"="id", "direction"="DESC"} - * } - * }) - * - * @ApiFilter(RangeFilter::class, properties={"id"}) - * @ApiFilter(OrderFilter::class, properties={"id"="DESC"}) - */ +#[ApiFilter(RangeFilter::class, properties: ['id'])] +#[ApiFilter(OrderFilter::class, properties: ['id' => 'DESC'])] +#[ApiResource(paginationPartial: true, paginationViaCursor: [['field' => 'id', 'direction' => 'DESC']])] +#[ORM\Entity] class SoMany { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - - /** - * @ORM\Column(nullable=true) - */ + #[ORM\Column(nullable: true)] public $content; } diff --git a/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php b/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php index f6e4c4cbc66..663224cde77 100644 --- a/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Component\Uid\Uuid; @@ -21,23 +21,17 @@ /* @TODO remove this check in 3.0 */ if (\PHP_VERSION_ID >= 70200 && class_exists(Uuid::class) && class_exists(UuidType::class)) { /** - * @ORM\Entity - * @ApiResource - * * @author Vincent Chalamon */ + #[ApiResource] + #[ORM\Entity] class SymfonyUuidDummy { - /** - * @ORM\Id - * @ORM\Column(type="symfony_uuid", unique=true) - * @ORM\GeneratedValue(strategy="NONE") - */ + #[ORM\Id] + #[ORM\Column(type: 'symfony_uuid', unique: true)] + #[ORM\GeneratedValue(strategy: 'NONE')] private $id; - - /** - * @ORM\Column(nullable=true) - */ + #[ORM\Column(nullable: true)] private $number; public function __construct(?Uuid $id = null) diff --git a/tests/Fixtures/TestBundle/Entity/Taxon.php b/tests/Fixtures/TestBundle/Entity/Taxon.php index 251f5485daf..da820734dd6 100644 --- a/tests/Fixtures/TestBundle/Entity/Taxon.php +++ b/tests/Fixtures/TestBundle/Entity/Taxon.php @@ -16,26 +16,15 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class Taxon implements TaxonInterface { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column(type="string", unique=true) - */ - private $code; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string', unique: true)] + private ?string $code = null; /** * {@inheritdoc} diff --git a/tests/Fixtures/TestBundle/Entity/ThirdLevel.php b/tests/Fixtures/TestBundle/Entity/ThirdLevel.php index 12f2d6fe66f..67502e04e43 100644 --- a/tests/Fixtures/TestBundle/Entity/ThirdLevel.php +++ b/tests/Fixtures/TestBundle/Entity/ThirdLevel.php @@ -13,8 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,46 +23,32 @@ * Third Level. * * @author Kévin Dunglas - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ORM\Entity] class ThirdLevel { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var int - * - * @ORM\Column(type="integer") - * @Groups({"barcelona", "chicago"}) - */ - private $level = 3; - - /** - * @var bool - * - * @ORM\Column(type="boolean") - */ - private $test = true; - - /** - * @ApiSubresource - * @ORM\ManyToOne(targetEntity="FourthLevel", cascade={"persist"}) - * @Groups({"barcelona", "chicago", "friends"}) */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'integer')] + #[Groups(['barcelona', 'chicago'])] + private int $level = 3; + #[ORM\Column(type: 'boolean')] + private bool $test = true; + #[ORM\ManyToOne(targetEntity: 'FourthLevel', cascade: ['persist'])] + #[Groups(['barcelona', 'chicago', 'friends'])] public $fourthLevel; - - /** - * @ORM\ManyToOne(targetEntity=FourthLevel::class, cascade={"persist"}) - */ + #[ORM\ManyToOne(targetEntity: FourthLevel::class, cascade: ['persist'])] public $badFourthLevel; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php b/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php index c25bdea09eb..6051b7537ed 100644 --- a/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php @@ -13,25 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * @ApiResource - */ +#[ApiResource] +#[ORM\Entity] class TruncatedDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column(type="decimal", precision=4, scale=1, nullable=false) - */ + #[ORM\Column(type: 'decimal', precision: 4, scale: 1, nullable: false)] public $value; /** diff --git a/tests/Fixtures/TestBundle/Entity/UnknownDummy.php b/tests/Fixtures/TestBundle/Entity/UnknownDummy.php index 5d23654b4da..18719eb85dd 100644 --- a/tests/Fixtures/TestBundle/Entity/UnknownDummy.php +++ b/tests/Fixtures/TestBundle/Entity/UnknownDummy.php @@ -17,19 +17,17 @@ /** * Unknown dummy. - * - * @ORM\Entity */ +#[ORM\Entity] class UnknownDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php index 0e4f1b11947..6c329b47d2c 100644 --- a/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php @@ -13,33 +13,29 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * UpperCaseIdentifier dummy. * * @author Exploit.cz - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class UpperCaseIdentifierDummy { /** * @var string The custom identifier - * - * @ORM\Column(type="guid") - * @ORM\Id */ - private $Uuid; - + #[ORM\Column(type: 'guid')] + #[ORM\Id] + private ?string $Uuid = null; /** * @var string The dummy name - * - * @ORM\Column(length=30) */ - private $name; + #[ORM\Column(length: 30)] + private ?string $name = null; public function getUuid(): string { diff --git a/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php b/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php index 652eae1a1f2..04eb01dcb56 100644 --- a/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php +++ b/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php @@ -13,32 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; /** * @author Daniel West * * Resource with an ID that will be URL encoded - * - * @ORM\Entity - * - * @ApiResource( - * itemOperations={ - * "get"={ - * "method"="GET", - * "requirements"={"id"=".+"} - * } - * } - * ) */ +#[ApiResource(operations: [new Get(requirements: ['id' => '.+']), new Post(), new GetCollection()])] +#[ORM\Entity] class UrlEncodedId { - /** - * @ORM\Column(type="string") - * @ORM\Id - */ - private $id = '%encode:id'; + #[ORM\Column(type: 'string')] + #[ORM\Id] + private string $id = '%encode:id'; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/User.php b/tests/Fixtures/TestBundle/Entity/User.php index 5c237dfa812..b9c6f8d6a47 100644 --- a/tests/Fixtures/TestBundle/Entity/User.php +++ b/tests/Fixtures/TestBundle/Entity/User.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\PasswordResetRequest; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\PasswordResetRequestResult; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordInput; @@ -25,72 +30,25 @@ /** * A User. * - * @ORM\Entity - * @ORM\Table(name="user_test") - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"user", "user-read"}}, - * "denormalization_context"={"groups"={"user", "user-write"}} - * }, - * collectionOperations={ - * "post", - * "get", - * "post_password_reset_request"={ - * "method"="POST", - * "path"="/users/password_reset_request", - * "messenger"="input", - * "input"=PasswordResetRequest::class, - * "output"=PasswordResetRequestResult::class, - * "normalization_context"={ - * "groups"={"user_password_reset_request"}, - * }, - * "denormalization_context"={ - * "groups"={"user_password_reset_request"}, - * }, - * }, - * }, - * itemOperations={"get", "put", "delete", - * "recover_password"={ - * "input"=RecoverPasswordInput::class, "output"=RecoverPasswordOutput::class, "method"="PUT", "path"="users/recover/{id}" - * } - * } - * ) - * * @author Théo FIDRY * @author Kévin Dunglas */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Put(input: RecoverPasswordInput::class, output: RecoverPasswordOutput::class, uriTemplate: 'users/recover/{id}'), new Post(), new GetCollection(), new Post(uriTemplate: '/users/password_reset_request', messenger: 'input', input: PasswordResetRequest::class, output: PasswordResetRequestResult::class, normalizationContext: ['groups' => ['user_password_reset_request']], denormalizationContext: ['groups' => ['user_password_reset_request']])], normalizationContext: ['groups' => ['user', 'user-read']], denormalizationContext: ['groups' => ['user', 'user-write']])] +#[ORM\Entity] +#[ORM\Table(name: 'user_test')] class User extends AbstractSecurityUser { - /** - * @var int|null - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string|null - * - * @Groups({"user"}) - */ - private $email; - - /** - * @var string|null - * - * @ORM\Column(type="string", length=255, nullable=true) - * @Groups({"user"}) - */ - private $fullname; - - /** - * @var string|null - * - * @Groups({"user-write"}) - */ - private $plainPassword; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[Groups(['user'])] + private ?string $email = null; + #[ORM\Column(type: 'string', length: 255, nullable: true)] + #[Groups(['user'])] + private ?string $fullname = null; + #[Groups(['user-write'])] + private ?string $plainPassword = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/UserResource.php b/tests/Fixtures/TestBundle/Entity/UserResource.php index 919eb688b26..84abe0dd338 100644 --- a/tests/Fixtures/TestBundle/Entity/UserResource.php +++ b/tests/Fixtures/TestBundle/Entity/UserResource.php @@ -13,26 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\UserResetPasswordDto; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource( - * collectionOperations={ - * "post"={ - * "method"="POST", - * "path"="/user-reset-password", - * "input"=UserResetPasswordDto::class - * } - * }, - * itemOperations={} - * ) - */ +#[ApiResource(operations: [new Post(uriTemplate: '/user-reset-password', input: UserResetPasswordDto::class)])] final class UserResource { - /** - * @Assert\NotBlank - */ + #[Assert\NotBlank] public $username; } diff --git a/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php index ca55c118c21..1723be3103e 100644 --- a/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php @@ -13,31 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Custom identifier dummy. - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class UuidIdentifierDummy { /** * @var string The custom identifier - * - * @ORM\Column(type="guid") - * @ORM\Id */ - private $uuid; - + #[ORM\Column(type: 'guid')] + #[ORM\Id] + private ?string $uuid = null; /** * @var string The dummy name - * - * @ORM\Column(length=30) */ - private $name; + #[ORM\Column(length: 30)] + private ?string $name = null; public function getUuid(): string { diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php index 363c3358fe1..228618067b5 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php @@ -13,55 +13,26 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"car_read"}}, - * "denormalization_context"={"groups"={"car_write"}} - * }) - * @ORM\Entity - */ +#[ApiResource(normalizationContext: ['groups' => ['car_read']], denormalizationContext: ['groups' => ['car_write']])] +#[ORM\Entity] class VoDummyCar extends VoDummyVehicle { - /** - * @var int - * - * @ORM\Column(type="integer") - * @Groups({"car_read", "car_write"}) - */ - private $mileage; - - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $bodyType; - /** * @var VoDummyInspection[]|Collection - * - * @ORM\OneToMany(targetEntity="VoDummyInspection", mappedBy="car", cascade={"persist"}) - * @Groups({"car_read", "car_write"}) */ - private $inspections; + #[ORM\OneToMany(targetEntity: 'VoDummyInspection', mappedBy: 'car', cascade: ['persist'])] + #[Groups(['car_read', 'car_write'])] + private readonly array|\Doctrine\Common\Collections\Collection $inspections; - public function __construct( - string $make, - VoDummyInsuranceCompany $insuranceCompany, - array $drivers, - int $mileage, - string $bodyType = 'coupe' - ) { + public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, #[ORM\Column(type: 'integer')] #[Groups(['car_read', 'car_write'])] private readonly int $mileage, #[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $bodyType = 'coupe') + { parent::__construct($make, $insuranceCompany, $drivers); - $this->mileage = $mileage; - $this->bodyType = $bodyType; $this->inspections = new ArrayCollection(); } diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php b/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php index a0b0569291b..0d558eb74d7 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php @@ -13,38 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class VoDummyDriver { use VoDummyIdAwareTrait; - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $firstName; - - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $lastName; - - public function __construct(string $firstName, string $lastName) + public function __construct(#[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $firstName, #[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $lastName) { - $this->firstName = $firstName; - $this->lastName = $lastName; } public function getFirstName() diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyIdAwareTrait.php b/tests/Fixtures/TestBundle/Entity/VoDummyIdAwareTrait.php index c2b07790bf5..0c6ac5dff14 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyIdAwareTrait.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyIdAwareTrait.php @@ -19,11 +19,10 @@ trait VoDummyIdAwareTrait { /** * @var int - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] protected $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php index d4d8ee89385..21aac8dc940 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php @@ -13,57 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use DateTime; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"inspection_read"}}, - * "denormalization_context"={"groups"={"inspection_write"}} - * }, - * graphql={} - * ) - * @ORM\Entity - */ +#[ApiResource(graphQlOperations: [], normalizationContext: ['groups' => ['inspection_read']], denormalizationContext: ['groups' => ['inspection_write']])] +#[ORM\Entity] class VoDummyInspection { use VoDummyIdAwareTrait; + #[ORM\Column(type: 'datetime')] + #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] + private \DateTime $performed; - /** - * @var bool - * - * @ORM\Column(type="boolean") - * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) - */ - private $accepted; - - /** - * @var VoDummyCar|null - * - * @ORM\ManyToOne(targetEntity="VoDummyCar", inversedBy="inspections") - * @Groups({"inspection_read", "inspection_write"}) - */ - private $car; - - /** - * @var DateTime - * - * @ORM\Column(type="datetime") - * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) - */ - private $performed; - - private $attributeWithoutConstructorEquivalent; - - public function __construct(bool $accepted, VoDummyCar $car, DateTime $performed = null, string $parameterWhichIsNotClassAttribute = '') + public function __construct(#[ORM\Column(type: 'boolean')] #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] private readonly bool $accepted, #[ORM\ManyToOne(targetEntity: 'VoDummyCar', inversedBy: 'inspections')] #[Groups(['inspection_read', 'inspection_write'])] private readonly ?VoDummyCar $car, DateTime $performed = null, private readonly string $attributeWithoutConstructorEquivalent = '') { - $this->accepted = $accepted; - $this->car = $car; $this->performed = $performed ?: new DateTime(); - $this->attributeWithoutConstructorEquivalent = $parameterWhichIsNotClassAttribute; } public function isAccepted() diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php b/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php index 0795a0ad55d..be7e55e7ae6 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php @@ -13,29 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class VoDummyInsuranceCompany { use VoDummyIdAwareTrait; - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $name; - - public function __construct(string $name) + public function __construct(#[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $name) { - $this->name = $name; } public function getName() diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php b/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php index 4e74857a052..0ae2c6a2125 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php @@ -18,44 +18,22 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\MappedSuperclass - */ +#[ORM\MappedSuperclass] abstract class VoDummyVehicle { use VoDummyIdAwareTrait; - - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $make; - - /** - * @var VoDummyInsuranceCompany|null - * - * @ORM\ManyToOne(targetEntity="VoDummyInsuranceCompany", cascade={"persist"}) - * @Groups({"car_read", "car_write"}) - */ - private $insuranceCompany; - /** * @var VoDummyDriver[]|Collection - * - * @ORM\ManyToMany(targetEntity="VoDummyDriver", cascade={"persist"}) - * @Groups({"car_read", "car_write"}) */ - private $drivers; + #[ORM\ManyToMany(targetEntity: 'VoDummyDriver', cascade: ['persist'])] + #[Groups(['car_read', 'car_write'])] + private readonly array|\Doctrine\Common\Collections\Collection $drivers; public function __construct( - string $make, - VoDummyInsuranceCompany $insuranceCompany, + #[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $make, + #[ORM\ManyToOne(targetEntity: 'VoDummyInsuranceCompany', cascade: ['persist'])] #[Groups(['car_read', 'car_write'])] private readonly ?VoDummyInsuranceCompany $insuranceCompany, array $drivers ) { - $this->make = $make; - $this->insuranceCompany = $insuranceCompany; $this->drivers = new ArrayCollection($drivers); } diff --git a/tests/Fixtures/TestBundle/Entity/VoidPayment.php b/tests/Fixtures/TestBundle/Entity/VoidPayment.php index 09bcc880681..30ccff469c9 100644 --- a/tests/Fixtures/TestBundle/Entity/VoidPayment.php +++ b/tests/Fixtures/TestBundle/Entity/VoidPayment.php @@ -13,34 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * - * @ApiResource - */ +#[ApiResource] +#[ORM\Entity] class VoidPayment { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @ORM\OneToOne(targetEntity=Payment::class, inversedBy="voidPayment") - * @ORM\JoinColumn(nullable=false) - */ - private $payment; - - public function __construct(Payment $payment) + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + public function __construct(#[ORM\OneToOne(targetEntity: Payment::class, inversedBy: 'voidPayment')] #[ORM\JoinColumn(nullable: false)] private readonly Payment $payment) { - $this->payment = $payment; } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php index e9553d1cf0c..0e6913ded2c 100644 --- a/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php +++ b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php @@ -13,29 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiResource - * @ORM\Entity - */ +#[ApiResource] +#[ORM\Entity] class WithJsonDummy { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var array|null - * - * @ORM\Column(type="json", nullable=true) */ + #[ORM\Column(type: 'json', nullable: true)] public $json; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/WritableId.php b/tests/Fixtures/TestBundle/Entity/WritableId.php index 0d465adab31..98f114f1463 100644 --- a/tests/Fixtures/TestBundle/Entity/WritableId.php +++ b/tests/Fixtures/TestBundle/Entity/WritableId.php @@ -13,27 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * @author Kévin Dunglas - * - * @ApiResource - * @ORM\Entity */ +#[ApiResource] +#[ORM\Entity] class WritableId { - /** - * @ORM\Id - * @Assert\Uuid - * @ORM\Column(type="guid") - */ + #[ORM\Id] + #[Assert\Uuid] + #[ORM\Column(type: 'guid')] public $id; - - /** - * @ORM\Column - */ + #[ORM\Column] public $name; } diff --git a/tests/Fixtures/TestBundle/Enum/ContentStatus.php b/tests/Fixtures/TestBundle/Enum/ContentStatus.php index 2ef678e51e0..3f61ff16df5 100644 --- a/tests/Fixtures/TestBundle/Enum/ContentStatus.php +++ b/tests/Fixtures/TestBundle/Enum/ContentStatus.php @@ -23,16 +23,13 @@ final class ContentStatus implements \JsonSerializable public function __construct(string $value) { if (!self::isValid($value)) { - throw new \UnexpectedValueException("Value '$value' is not part of the enum ".__CLASS__); + throw new \UnexpectedValueException("Value '$value' is not part of the enum ".self::class); } $this->value = $value; } - /** - * @return string|bool - */ - public function getKey() + public function getKey(): string|bool { return static::search($this->value); } @@ -58,10 +55,7 @@ public static function isValid(string $value): bool return \in_array($value, self::toArray(), true); } - /** - * @return string|bool - */ - public static function search(string $value) + public static function search(string $value): string|bool { return array_search($value, self::toArray(), true); } diff --git a/tests/Fixtures/TestBundle/Filter/NoPropertiesArgumentFilter.php b/tests/Fixtures/TestBundle/Filter/NoPropertiesArgumentFilter.php index 02fc55e4f6d..3a4cb58399a 100644 --- a/tests/Fixtures/TestBundle/Filter/NoPropertiesArgumentFilter.php +++ b/tests/Fixtures/TestBundle/Filter/NoPropertiesArgumentFilter.php @@ -17,11 +17,8 @@ final class NoPropertiesArgumentFilter implements FilterInterface { - private $foo; - - public function __construct(string $foo = 'bar') + public function __construct(private readonly string $foo = 'bar') { - $this->foo = $foo; } /** diff --git a/tests/Fixtures/TestBundle/GraphQl/Type/Definition/DateTimeType.php b/tests/Fixtures/TestBundle/GraphQl/Type/Definition/DateTimeType.php index 553b5703883..08748c72a89 100644 --- a/tests/Fixtures/TestBundle/GraphQl/Type/Definition/DateTimeType.php +++ b/tests/Fixtures/TestBundle/GraphQl/Type/Definition/DateTimeType.php @@ -29,7 +29,7 @@ final class DateTimeType extends ScalarType implements TypeInterface { public function __construct() { - $this->name = 'DateTime'; + $this->name = \DateTime::class; $this->description = 'The `DateTime` scalar type represents time data.'; parent::__construct(); diff --git a/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverter.php b/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverter.php index 58d473a24c4..c9b4bd36d8e 100644 --- a/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverter.php +++ b/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverter.php @@ -27,11 +27,8 @@ */ final class TypeConverter implements TypeConverterInterface { - private $defaultTypeConverter; - - public function __construct(TypeConverterInterface $defaultTypeConverter) + public function __construct(private readonly TypeConverterInterface $defaultTypeConverter) { - $this->defaultTypeConverter = $defaultTypeConverter; } /** @@ -44,7 +41,7 @@ public function convertType(Type $type, bool $input, Operation $rootOperation, s && Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType() && is_a($type->getClassName(), \DateTimeInterface::class, true) ) { - return 'DateTime'; + return \DateTime::class; } return $this->defaultTypeConverter->convertType($type, $input, $rootOperation, $resourceClass, $rootResource, $property, $depth); diff --git a/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverterLegacy.php b/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverterLegacy.php deleted file mode 100644 index 8f5319b3619..00000000000 --- a/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverterLegacy.php +++ /dev/null @@ -1,59 +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); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\GraphQl\Type; - -use ApiPlatform\Core\GraphQl\Type\TypeConverterInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy as DummyDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use GraphQL\Type\Definition\Type as GraphQLType; -use Symfony\Component\PropertyInfo\Type; - -/** - * Converts a built-in type to its GraphQL equivalent. - * - * @author Alan Poulain - */ -final class TypeConverterLegacy implements TypeConverterInterface -{ - private $defaultTypeConverter; - - public function __construct(TypeConverterInterface $defaultTypeConverter) - { - $this->defaultTypeConverter = $defaultTypeConverter; - } - - /** - * {@inheritdoc} - */ - public function convertType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $resourceClass, string $rootResource, ?string $property, int $depth) - { - if ('dummyDate' === $property - && \in_array($rootResource, [Dummy::class, DummyDocument::class], true) - && Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType() - && is_a($type->getClassName(), \DateTimeInterface::class, true) - ) { - return 'DateTime'; - } - - return $this->defaultTypeConverter->convertType($type, $input, $queryName, $mutationName, $subscriptionName, $resourceClass, $rootResource, $property, $depth); - } - - /** - * {@inheritdoc} - */ - public function resolveType(string $type): ?GraphQLType - { - return $this->defaultTypeConverter->resolveType($type); - } -} diff --git a/tests/Fixtures/TestBundle/Metadata/ProviderResourceMetadatatCollectionFactory.php b/tests/Fixtures/TestBundle/Metadata/ProviderResourceMetadatatCollectionFactory.php index c415d3ec1f8..95bcbea3682 100644 --- a/tests/Fixtures/TestBundle/Metadata/ProviderResourceMetadatatCollectionFactory.php +++ b/tests/Fixtures/TestBundle/Metadata/ProviderResourceMetadatatCollectionFactory.php @@ -30,14 +30,8 @@ class ProviderResourceMetadatatCollectionFactory implements ResourceMetadataCollectionFactoryInterface { - /** - * @var ResourceMetadataCollectionFactoryInterface - */ - private $decorated; - - public function __construct(ResourceMetadataCollectionFactoryInterface $decorated) + public function __construct(private readonly ResourceMetadataCollectionFactoryInterface $decorated) { - $this->decorated = $decorated; } /** diff --git a/tests/Fixtures/TestBundle/Model/MediaObject.php b/tests/Fixtures/TestBundle/Model/MediaObject.php index 18cda6d2a96..1cd289180c5 100644 --- a/tests/Fixtures/TestBundle/Model/MediaObject.php +++ b/tests/Fixtures/TestBundle/Model/MediaObject.php @@ -13,39 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; /** - * @ApiResource( - * iri="http://schema.org/MediaObject", - * graphql={ - * "upload"={ - * "mutation"="app.graphql.mutation_resolver.upload_media_object", - * "args"={ - * "file"={"type"="Upload!", "description"="Upload a file"} - * } - * }, - * "uploadMultiple"={ - * "mutation"="app.graphql.mutation_resolver.upload_multiple_media_object", - * "args"={ - * "files"={"type"="[Upload!]!", "description"="Upload multiple files"} - * } - * } - * } - * ) - * * @author Mahmood Bazdar */ +#[ApiResource(graphQlOperations: [new Mutation(name: 'upload', resolver: 'app.graphql.mutation_resolver.upload_media_object', args: ['file' => ['type' => 'Upload!', 'description' => 'Upload a file']]), new Mutation(name: 'uploadMultiple', resolver: 'app.graphql.mutation_resolver.upload_multiple_media_object', args: ['files' => ['type' => '[Upload!]!', 'description' => 'Upload multiple files']])], types: ['http://schema.org/MediaObject'])] class MediaObject { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public $id; - /** - * @var string - */ - public $contentUrl; + public string $contentUrl; } diff --git a/tests/Fixtures/TestBundle/Model/ProductInterface.php b/tests/Fixtures/TestBundle/Model/ProductInterface.php index a2780efbcd8..05f1c9f67d8 100644 --- a/tests/Fixtures/TestBundle/Model/ProductInterface.php +++ b/tests/Fixtures/TestBundle/Model/ProductInterface.php @@ -13,49 +13,28 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource( - * shortName="Product", - * attributes={"identifiers"="code", "provider"=ProductProvider::class}, - * normalizationContext={ - * "groups"={"product_read"}, - * }, - * denormalizationContext={ - * "groups"={"product_write"}, - * }, - * ) - */ +#[ApiResource(shortName: 'Product', uriVariables: 'code', provider: ProductProvider::class, normalizationContext: ['groups' => ['product_read']], denormalizationContext: ['groups' => ['product_write']])] interface ProductInterface { public function getId(); - /** - * @ApiProperty(identifier=true) - * - * @Groups({"product_read"}) - * - * @Assert\NotBlank - */ + #[ApiProperty(identifier: true)] + #[Groups(['product_read'])] + #[Assert\NotBlank] public function getCode(): ?string; - /** - * @Groups({"product_write"}) - */ + #[Groups(['product_write'])] public function setCode(?string $code): void; - /** - * @Groups({"product_read"}) - */ + #[Groups(['product_read'])] public function getMainTaxon(): ?TaxonInterface; - /** - * @Groups({"product_write"}) - */ + #[Groups(['product_write'])] public function setMainTaxon(?TaxonInterface $mainTaxon): void; } diff --git a/tests/Fixtures/TestBundle/Model/ResourceBarInterface.php b/tests/Fixtures/TestBundle/Model/ResourceBarInterface.php index ec79c8e6ce5..9094d397c60 100644 --- a/tests/Fixtures/TestBundle/Model/ResourceBarInterface.php +++ b/tests/Fixtures/TestBundle/Model/ResourceBarInterface.php @@ -13,12 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; interface ResourceBarInterface { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public function getBar(): ?string; } diff --git a/tests/Fixtures/TestBundle/Model/ResourceInterfaceImplementation.php b/tests/Fixtures/TestBundle/Model/ResourceInterfaceImplementation.php index 1b9c87c273c..5969df5fc0b 100644 --- a/tests/Fixtures/TestBundle/Model/ResourceInterfaceImplementation.php +++ b/tests/Fixtures/TestBundle/Model/ResourceInterfaceImplementation.php @@ -18,15 +18,9 @@ */ class ResourceInterfaceImplementation implements ResourceInterface, ResourceBarInterface { - /** - * @var string - */ - private $foo; - - /** - * @var ?string - */ - private $bar; + private ?string $foo = null; + + private ?string $bar = null; public function setFoo(string $foo) { diff --git a/tests/Fixtures/TestBundle/Model/SerializableResource.php b/tests/Fixtures/TestBundle/Model/SerializableResource.php index 1a7cb80c30b..fdc6d549121 100644 --- a/tests/Fixtures/TestBundle/Model/SerializableResource.php +++ b/tests/Fixtures/TestBundle/Model/SerializableResource.php @@ -13,32 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; /** * Resource linked to an external API. * - * @ApiResource - * * @author Vincent Chalamon */ +#[ApiResource] class SerializableResource { - /** - * @var int - * - * @ApiProperty(identifier=true) - */ - public $id; + #[ApiProperty(identifier: true)] + public int $id; - /** - * @var string - */ - public $foo; + public string $foo; - /** - * @var string - */ - public $bar; + public string $bar; } diff --git a/tests/Fixtures/TestBundle/Model/TaxonInterface.php b/tests/Fixtures/TestBundle/Model/TaxonInterface.php index 80d29146736..23ce666d0e5 100644 --- a/tests/Fixtures/TestBundle/Model/TaxonInterface.php +++ b/tests/Fixtures/TestBundle/Model/TaxonInterface.php @@ -13,38 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource( - * attributes={"identifiers"="code"}, - * shortName="Taxon", - * normalizationContext={ - * "groups"={"taxon_read"}, - * }, - * denormalizationContext={ - * "groups"={"taxon_write"}, - * }, - * ) - */ +#[ApiResource(shortName: 'Taxon', uriVariables: 'code', normalizationContext: ['groups' => ['taxon_read']], denormalizationContext: ['groups' => ['taxon_write']])] interface TaxonInterface { public function getId(); - /** - * @ApiProperty(identifier=true) - * - * @Groups({"product_read", "taxon_read"}) - * - * @Assert\NotBlank - */ + #[ApiProperty(identifier: true)] + #[Groups(['product_read', 'taxon_read'])] + #[Assert\NotBlank] public function getCode(): ?string; - /** - * @Groups({"taxon_write"}) - */ + #[Groups(['taxon_write'])] public function setCode(?string $code): void; } diff --git a/tests/Fixtures/TestBundle/Security/AuthenticationEntryPoint.php b/tests/Fixtures/TestBundle/Security/AuthenticationEntryPoint.php index 125bd0d9e45..7ce006e4e3e 100644 --- a/tests/Fixtures/TestBundle/Security/AuthenticationEntryPoint.php +++ b/tests/Fixtures/TestBundle/Security/AuthenticationEntryPoint.php @@ -24,11 +24,8 @@ final class AuthenticationEntryPoint implements AuthenticationEntryPointInterface { - private $router; - - public function __construct(RouterInterface $router) + public function __construct(private readonly RouterInterface $router) { - $this->router = $router; } public function start(Request $request, AuthenticationException $authException = null): Response diff --git a/tests/Fixtures/TestBundle/Serializer/Denormalizer/DummyPlainIdentifierDenormalizer.php b/tests/Fixtures/TestBundle/Serializer/Denormalizer/DummyPlainIdentifierDenormalizer.php index bc28865946c..fe7fbb4ef5c 100644 --- a/tests/Fixtures/TestBundle/Serializer/Denormalizer/DummyPlainIdentifierDenormalizer.php +++ b/tests/Fixtures/TestBundle/Serializer/Denormalizer/DummyPlainIdentifierDenormalizer.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Denormalizer; -use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; use ApiPlatform\Metadata\Get; @@ -35,14 +34,8 @@ class DummyPlainIdentifierDenormalizer implements ContextAwareDenormalizerInterf { use DenormalizerAwareTrait; - /** - * @var IriConverterInterface|LegacyIriConverterInterface - */ - private $iriConverter; - - public function __construct($iriConverter) + public function __construct(private $iriConverter) { - $this->iriConverter = $iriConverter; } /** @@ -63,7 +56,7 @@ public function denormalize($data, $class, $format = null, array $context = []) } } - return $this->denormalizer->denormalize($data, $class, $format, $context + [__CLASS__ => true]); + return $this->denormalizer->denormalize($data, $class, $format, $context + [self::class => true]); } $relatedDummyClass = DummyEntity::class === $class ? RelatedDummyEntity::class : RelatedDummyDocument::class; @@ -81,7 +74,7 @@ public function denormalize($data, $class, $format = null, array $context = []) } } - return $this->denormalizer->denormalize($data, $class, $format, $context + [__CLASS__ => true]); + return $this->denormalizer->denormalize($data, $class, $format, $context + [self::class => true]); } /** @@ -92,6 +85,6 @@ public function supportsDenormalization($data, $type, $format = null, array $con return 'json' === $format && (is_a($type, DummyEntity::class, true) || is_a($type, DummyDocument::class, true)) && ('1' === ($data['relatedDummy'] ?? null) || ['1'] === ($data['relatedDummies'] ?? null)) - && !isset($context[__CLASS__]); + && !isset($context[self::class]); } } diff --git a/tests/Fixtures/TestBundle/Serializer/Denormalizer/RelatedDummyPlainIdentifierDenormalizer.php b/tests/Fixtures/TestBundle/Serializer/Denormalizer/RelatedDummyPlainIdentifierDenormalizer.php index a72e1bf7b87..2f52bad8cc6 100644 --- a/tests/Fixtures/TestBundle/Serializer/Denormalizer/RelatedDummyPlainIdentifierDenormalizer.php +++ b/tests/Fixtures/TestBundle/Serializer/Denormalizer/RelatedDummyPlainIdentifierDenormalizer.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Denormalizer; -use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; use ApiPlatform\Metadata\Get; @@ -35,14 +34,8 @@ class RelatedDummyPlainIdentifierDenormalizer implements ContextAwareDenormalize { use DenormalizerAwareTrait; - /** - * @var IriConverterInterface|LegacyIriConverterInterface - */ - private $iriConverter; - - public function __construct($iriConverter) + public function __construct(private $iriConverter) { - $this->iriConverter = $iriConverter; } /** @@ -55,7 +48,7 @@ public function denormalize($data, $class, $format = null, array $context = []) if ($this->iriConverter instanceof LegacyIriConverterInterface) { $data['thirdLevel'] = '/third_levels/'.$data['thirdLevel']; - return $this->denormalizer->denormalize($data, $class, $format, $context + [__CLASS__ => true]); + return $this->denormalizer->denormalize($data, $class, $format, $context + [self::class => true]); } $iriConverterContext = ['uri_variables' => ['id' => $data['thirdLevel']]] + $context; @@ -67,7 +60,7 @@ public function denormalize($data, $class, $format = null, array $context = []) $iriConverterContext ); - return $this->denormalizer->denormalize($data, $class, $format, $context + [__CLASS__ => true]); + return $this->denormalizer->denormalize($data, $class, $format, $context + [self::class => true]); } /** @@ -78,6 +71,6 @@ public function supportsDenormalization($data, $type, $format = null, array $con return 'json' === $format && (is_a($type, RelatedDummyEntity::class, true) || is_a($type, RelatedDummyDocument::class, true)) && '1' === ($data['thirdLevel'] ?? null) - && !isset($context[__CLASS__]); + && !isset($context[self::class]); } } diff --git a/tests/Fixtures/TestBundle/Serializer/Normalizer/OverrideDocumentationNormalizer.php b/tests/Fixtures/TestBundle/Serializer/Normalizer/OverrideDocumentationNormalizer.php index f33cd420e41..3dc6a8fb9ad 100644 --- a/tests/Fixtures/TestBundle/Serializer/Normalizer/OverrideDocumentationNormalizer.php +++ b/tests/Fixtures/TestBundle/Serializer/Normalizer/OverrideDocumentationNormalizer.php @@ -21,11 +21,8 @@ */ final class OverrideDocumentationNormalizer implements NormalizerInterface { - private $documentationNormalizer; - - public function __construct(NormalizerInterface $documentationNormalizer) + public function __construct(private readonly NormalizerInterface $documentationNormalizer) { - $this->documentationNormalizer = $documentationNormalizer; } /** diff --git a/tests/Fixtures/TestBundle/State/DummyDtoNoOutputProcessor.php b/tests/Fixtures/TestBundle/State/DummyDtoNoOutputProcessor.php index e613766edbc..fca74c8265f 100644 --- a/tests/Fixtures/TestBundle/State/DummyDtoNoOutputProcessor.php +++ b/tests/Fixtures/TestBundle/State/DummyDtoNoOutputProcessor.php @@ -23,11 +23,8 @@ class DummyDtoNoOutputProcessor implements ProcessorInterface { - private $registry; - - public function __construct(ManagerRegistry $registry) + public function __construct(private readonly ManagerRegistry $registry) { - $this->registry = $registry; } /** diff --git a/tests/Fixtures/TestBundle/State/OperationResourceProcessor.php b/tests/Fixtures/TestBundle/State/OperationResourceProcessor.php index 26739e258d4..f723534e888 100644 --- a/tests/Fixtures/TestBundle/State/OperationResourceProcessor.php +++ b/tests/Fixtures/TestBundle/State/OperationResourceProcessor.php @@ -26,11 +26,8 @@ final class OperationResourceProcessor implements ProcessorInterface { use ClassInfoTrait; - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry) + public function __construct(private readonly ManagerRegistry $managerRegistry) { - $this->managerRegistry = $managerRegistry; } private function persist($data, array $context = []) diff --git a/tests/Fixtures/TestBundle/State/ProductProvider.php b/tests/Fixtures/TestBundle/State/ProductProvider.php index 9f02ffa7a67..bc86477c501 100644 --- a/tests/Fixtures/TestBundle/State/ProductProvider.php +++ b/tests/Fixtures/TestBundle/State/ProductProvider.php @@ -22,13 +22,8 @@ class ProductProvider implements ProviderInterface { - private $managerRegistry; - private $orm; - - public function __construct(ManagerRegistry $managerRegistry, bool $orm = true) + public function __construct(private readonly ManagerRegistry $managerRegistry, private readonly bool $orm = true) { - $this->managerRegistry = $managerRegistry; - $this->orm = $orm; } /** diff --git a/tests/Fixtures/TestBundle/State/RelatedQuestionsProvider.php b/tests/Fixtures/TestBundle/State/RelatedQuestionsProvider.php index b21ad5ce54c..c5d4b4c3c7f 100644 --- a/tests/Fixtures/TestBundle/State/RelatedQuestionsProvider.php +++ b/tests/Fixtures/TestBundle/State/RelatedQuestionsProvider.php @@ -21,11 +21,8 @@ class RelatedQuestionsProvider implements ProviderInterface { - private $registry; - - public function __construct(ManagerRegistry $registry) + public function __construct(private readonly ManagerRegistry $registry) { - $this->registry = $registry; } public function provide(Operation $operation, array $uriVariables = [], array $context = []) diff --git a/tests/Fixtures/TestBundle/State/TaxonItemProvider.php b/tests/Fixtures/TestBundle/State/TaxonItemProvider.php index 29b34f0cd63..e71808a78a8 100644 --- a/tests/Fixtures/TestBundle/State/TaxonItemProvider.php +++ b/tests/Fixtures/TestBundle/State/TaxonItemProvider.php @@ -21,13 +21,8 @@ class TaxonItemProvider implements ProviderInterface { - private $managerRegistry; - private $orm; - - public function __construct(ManagerRegistry $managerRegistry, bool $orm = true) + public function __construct(private readonly ManagerRegistry $managerRegistry, private readonly bool $orm = true) { - $this->managerRegistry = $managerRegistry; - $this->orm = $orm; } /** diff --git a/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php b/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php index 9e2e4dbcc72..20f4f42628c 100644 --- a/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php +++ b/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php @@ -20,11 +20,8 @@ class AnnotationFilterExtractor { use AnnotationFilterExtractorTrait; - private $reader; - - public function __construct(?Reader $reader = null) + public function __construct(private readonly ?Reader $reader = null) { - $this->reader = $reader; } public function getFilters(\ReflectionClass $reflectionClass) diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index 1348cfc0c0d..31eb496bd97 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -11,8 +11,8 @@ declare(strict_types=1); -use ApiPlatform\Core\Tests\Behat\DoctrineContext; use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; +use ApiPlatform\Tests\Behat\DoctrineContext; use ApiPlatform\Tests\Fixtures\TestBundle\Document\User as UserDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\User; use ApiPlatform\Tests\Fixtures\TestBundle\TestBundle; diff --git a/tests/Fixtures/app/config/config_behat_mongodb.yml b/tests/Fixtures/app/config/config_behat_mongodb.yml index a8e05c132d1..d5974d086ca 100644 --- a/tests/Fixtures/app/config/config_behat_mongodb.yml +++ b/tests/Fixtures/app/config/config_behat_mongodb.yml @@ -3,15 +3,15 @@ services: autowire: true autoconfigure: true - ApiPlatform\Core\Tests\Behat\CommandContext: ~ - ApiPlatform\Core\Tests\Behat\DoctrineContext: + ApiPlatform\Tests\Behat\CommandContext: ~ + ApiPlatform\Tests\Behat\DoctrineContext: $doctrine: '@doctrine_mongodb' - ApiPlatform\Core\Tests\Behat\HttpCacheContext: ~ - ApiPlatform\Core\Tests\Behat\HydraContext: ~ - ApiPlatform\Core\Tests\Behat\JsonApiContext: + ApiPlatform\Tests\Behat\HttpCacheContext: ~ + ApiPlatform\Tests\Behat\HydraContext: ~ + ApiPlatform\Tests\Behat\JsonApiContext: $doctrine: '@doctrine_mongodb' $jsonApiSchemaFile: '%kernel.project_dir%/../JsonSchema/jsonapi.json' - ApiPlatform\Core\Tests\Behat\JsonHalContext: + ApiPlatform\Tests\Behat\JsonHalContext: $schemaFile: '%kernel.project_dir%/../JsonHal/jsonhal.json' - ApiPlatform\Core\Tests\Behat\MercureContext: + ApiPlatform\Tests\Behat\MercureContext: $driverContainer: '@behat.driver.service_container' diff --git a/tests/Fixtures/app/config/config_behat_orm.yml b/tests/Fixtures/app/config/config_behat_orm.yml index b053ac286c8..071ade50e0c 100644 --- a/tests/Fixtures/app/config/config_behat_orm.yml +++ b/tests/Fixtures/app/config/config_behat_orm.yml @@ -3,15 +3,15 @@ services: autowire: true autoconfigure: true - ApiPlatform\Core\Tests\Behat\CommandContext: ~ - ApiPlatform\Core\Tests\Behat\DoctrineContext: + ApiPlatform\Tests\Behat\CommandContext: ~ + ApiPlatform\Tests\Behat\DoctrineContext: $doctrine: '@doctrine' - ApiPlatform\Core\Tests\Behat\HttpCacheContext: ~ - ApiPlatform\Core\Tests\Behat\HydraContext: ~ - ApiPlatform\Core\Tests\Behat\JsonApiContext: + ApiPlatform\Tests\Behat\HttpCacheContext: ~ + ApiPlatform\Tests\Behat\HydraContext: ~ + ApiPlatform\Tests\Behat\JsonApiContext: $doctrine: '@doctrine' $jsonApiSchemaFile: '%kernel.project_dir%/../JsonSchema/jsonapi.json' - ApiPlatform\Core\Tests\Behat\JsonHalContext: + ApiPlatform\Tests\Behat\JsonHalContext: $schemaFile: '%kernel.project_dir%/../JsonHal/jsonhal.json' - ApiPlatform\Core\Tests\Behat\MercureContext: + ApiPlatform\Tests\Behat\MercureContext: $driverContainer: '@behat.driver.service_container' diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index 83f2ec184e2..5eda4135aad 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -230,7 +230,7 @@ services: app.config_dummy_resource.action: class: 'ApiPlatform\Tests\Fixtures\TestBundle\Action\ConfigCustom' - arguments: ['@api_platform.item_data_provider'] + arguments: ['@api_platform.state_provider'] public: true app.entity.filter.dummy_property.property: @@ -425,8 +425,8 @@ services: arguments: $router: '@router' - app.serializer.normalizer.override_documentation: - class: ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Normalizer\OverrideDocumentationNormalizer - decorates: api_platform.swagger.normalizer.documentation - public: false - arguments: ['@app.serializer.normalizer.override_documentation.inner'] + # app.serializer.normalizer.override_documentation: + # class: ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Normalizer\OverrideDocumentationNormalizer + # decorates: api_platform.swagger.normalizer.documentation + # public: false + # arguments: ['@app.serializer.normalizer.override_documentation.inner'] diff --git a/tests/Fixtures/app/config/config_mongodb.yml b/tests/Fixtures/app/config/config_mongodb.yml index 86283b057d2..dcea3511ae8 100644 --- a/tests/Fixtures/app/config/config_mongodb.yml +++ b/tests/Fixtures/app/config/config_mongodb.yml @@ -72,14 +72,6 @@ services: arguments: [ { 'name': 'ipartial', 'description': 'ipartial' } ] tags: [ { name: 'api_platform.filter', id: 'related_to_dummy_friend.mongodb.name' } ] - ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\ProductItemDataProvider: - public: false - arguments: - $managerRegistry: '@doctrine_mongodb' - $orm: false - tags: - - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider: class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider' public: false @@ -89,14 +81,6 @@ services: tags: - name: 'api_platform.state_provider' - ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\TaxonItemDataProvider: - public: false - arguments: - $managerRegistry: '@doctrine_mongodb' - $orm: false - tags: - - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider: class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider' public: false @@ -113,19 +97,19 @@ services: tags: - { name: 'api_platform.state_provider' } - app.dummy_dto_no_input.data_provider: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\DummyDtoNoInputCollectionDataProvider' - public: false - arguments: ['@doctrine_mongodb'] - tags: - - { name: 'api_platform.collection_data_provider' } - - app.dummy_dto_no_output_data_persister: - class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\DummyDtoNoOutputDataPersister - arguments: ['@doctrine_mongodb'] - public: false - tags: - - { name: 'api_platform.data_persister' } + # app.dummy_dto_no_input.data_provider: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\DummyDtoNoInputCollectionDataProvider' + # public: false + # arguments: ['@doctrine_mongodb'] + # tags: + # - { name: 'api_platform.collection_data_provider' } + # + # app.dummy_dto_no_output_data_persister: + # class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\DummyDtoNoOutputDataPersister + # arguments: ['@doctrine_mongodb'] + # public: false + # tags: + # - { name: 'api_platform.data_persister' } app.graphql.query_resolver.dummy_custom_not_retrieved_item_document: class: 'ApiPlatform\Tests\Fixtures\TestBundle\GraphQl\Resolver\DummyCustomQueryNotRetrievedItemDocumentResolver' diff --git a/tests/Fixtures/app/config/config_test.yml b/tests/Fixtures/app/config/config_test.yml index 6ae4f627efa..d1e00619e7c 100644 --- a/tests/Fixtures/app/config/config_test.yml +++ b/tests/Fixtures/app/config/config_test.yml @@ -81,13 +81,6 @@ services: tags: - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\ProductItemDataProvider: - public: false - arguments: - $managerRegistry: '@doctrine' - tags: - - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider: class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider' public: false @@ -96,13 +89,6 @@ services: tags: - name: 'api_platform.state_provider' - ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\TaxonItemDataProvider: - public: false - arguments: - $managerRegistry: '@doctrine' - tags: - - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider: class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider' public: false @@ -111,19 +97,19 @@ services: tags: - name: 'api_platform.state_provider' - app.dummy_dto_no_input.data_provider: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\DummyDtoNoInputCollectionDataProvider' - public: false - arguments: ['@doctrine'] - tags: - - { name: 'api_platform.collection_data_provider' } - - app.dummy_dto_no_output_data_persister: - class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\DummyDtoNoOutputDataPersister - arguments: ['@doctrine'] - public: false - tags: - - { name: 'api_platform.data_persister' } + # app.dummy_dto_no_input.data_provider: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\DummyDtoNoInputCollectionDataProvider' + # public: false + # arguments: ['@doctrine'] + # tags: + # - { name: 'api_platform.collection_data_provider' } + + # app.dummy_dto_no_output_data_persister: + # class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\DummyDtoNoOutputDataPersister + # arguments: ['@doctrine'] + # public: false + # tags: + # - { name: 'api_platform.data_persister' } app.user_reset_password_data_persister: class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\UserResetPasswordDataPersister diff --git a/tests/GraphQl/Action/EntrypointActionTest.php b/tests/GraphQl/Action/EntrypointActionTest.php index 6623de9fc6e..f0dc0651ac3 100644 --- a/tests/GraphQl/Action/EntrypointActionTest.php +++ b/tests/GraphQl/Action/EntrypointActionTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Action; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Action\EntrypointAction; use ApiPlatform\GraphQl\Action\GraphiQlAction; use ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction; @@ -22,6 +21,7 @@ use ApiPlatform\GraphQl\Serializer\Exception\ErrorNormalizer; use ApiPlatform\GraphQl\Serializer\Exception\HttpExceptionNormalizer; use ApiPlatform\GraphQl\Type\SchemaBuilderInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Error\DebugFlag; use GraphQL\Executor\ExecutionResult; use GraphQL\Type\Schema; diff --git a/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php b/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php index e1f785aafe7..a4d2de46c90 100644 --- a/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php +++ b/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Core\Tests\GraphQl\Action; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/GraphQl/Action/GraphiQlActionTest.php b/tests/GraphQl/Action/GraphiQlActionTest.php index bc0875287f7..a436d34bcda 100644 --- a/tests/GraphQl/Action/GraphiQlActionTest.php +++ b/tests/GraphQl/Action/GraphiQlActionTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Core\Tests\GraphQl\Action; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Action\GraphiQlAction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php index cb204b4c245..40d03b83a97 100644 --- a/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\CollectionResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface; use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php index 2fc9c097096..26cfda051e1 100644 --- a/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ItemMutationResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\DeserializeStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; @@ -25,6 +24,7 @@ use ApiPlatform\GraphQl\Resolver\Stage\WriteStageInterface; use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php index 4be983c4e31..fdf0ecc3bfc 100644 --- a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Core\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ItemResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; @@ -21,6 +20,7 @@ use ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php index 848b02ccdbd..3faa06e802b 100644 --- a/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ItemSubscriptionResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityStageInterface; @@ -22,6 +21,7 @@ use ApiPlatform\GraphQl\Subscription\SubscriptionManagerInterface; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Subscription; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/ResourceFieldResolverTest.php b/tests/GraphQl/Resolver/ResourceFieldResolverTest.php index 58462b82a1d..af0b9eb7fb0 100644 --- a/tests/GraphQl/Resolver/ResourceFieldResolverTest.php +++ b/tests/GraphQl/Resolver/ResourceFieldResolverTest.php @@ -15,10 +15,10 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\ResourceFieldResolver; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\FieldDefinition; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ResolveInfo; diff --git a/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php b/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php index 288f2ee4847..5d153fc349d 100644 --- a/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\DeserializeStage; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; diff --git a/tests/GraphQl/Resolver/Stage/ReadStageTest.php b/tests/GraphQl/Resolver/Stage/ReadStageTest.php index 4ddc07510cc..29f34cd7dd2 100644 --- a/tests/GraphQl/Resolver/Stage/ReadStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ReadStageTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\GraphQl\Resolver\Stage\ReadStage; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Metadata\GraphQl\QueryCollection; use ApiPlatform\State\ProviderInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php index 68df039c990..47254665c7c 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php index 1d02153b2a1..2d169ccb1be 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostValidationStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php index 28d0b9c9d2b..ebf4225c657 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SecurityStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php index d9d1d057cde..6bfcb44d63c 100644 --- a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SerializeStage; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface; @@ -27,6 +26,7 @@ use ApiPlatform\State\Pagination\ArrayPaginator; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\State\Pagination\PartialPaginatorInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/ValidateStageTest.php b/tests/GraphQl/Resolver/Stage/ValidateStageTest.php index 7cfdbc4ce10..e725cb47b7d 100644 --- a/tests/GraphQl/Resolver/Stage/ValidateStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ValidateStageTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\ValidateStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Validator\Exception\ValidationException; use ApiPlatform\Validator\ValidatorInterface; use GraphQL\Type\Definition\ResolveInfo; diff --git a/tests/GraphQl/Resolver/Stage/WriteStageTest.php b/tests/GraphQl/Resolver/Stage/WriteStageTest.php index 6551431ac11..1027eec74a4 100644 --- a/tests/GraphQl/Resolver/Stage/WriteStageTest.php +++ b/tests/GraphQl/Resolver/Stage/WriteStageTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Core\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\WriteStage; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/GraphQl/Serializer/ItemNormalizerTest.php b/tests/GraphQl/Serializer/ItemNormalizerTest.php index 5a85b9d7baa..7911bbbc9fd 100644 --- a/tests/GraphQl/Serializer/ItemNormalizerTest.php +++ b/tests/GraphQl/Serializer/ItemNormalizerTest.php @@ -18,12 +18,12 @@ use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; @@ -164,8 +164,6 @@ public function testNormalizeNoResolverData(): void null, null, null, - false, - null, [], null ); @@ -213,8 +211,6 @@ public function testDenormalize() null, null, null, - false, - null, [], null ); diff --git a/tests/GraphQl/Serializer/SerializerContextBuilderTest.php b/tests/GraphQl/Serializer/SerializerContextBuilderTest.php index 2f88f1bcf1a..e5227b0ee1d 100644 --- a/tests/GraphQl/Serializer/SerializerContextBuilderTest.php +++ b/tests/GraphQl/Serializer/SerializerContextBuilderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Core\Tests\GraphQl\Serializer; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilder; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Mutation; @@ -22,6 +21,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Subscription/SubscriptionManagerTest.php b/tests/GraphQl/Subscription/SubscriptionManagerTest.php index 2ee4cfcea29..376220d6d68 100644 --- a/tests/GraphQl/Subscription/SubscriptionManagerTest.php +++ b/tests/GraphQl/Subscription/SubscriptionManagerTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\GraphQl\Subscription; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface; use ApiPlatform\GraphQl\Subscription\SubscriptionIdentifierGeneratorInterface; use ApiPlatform\GraphQl\Subscription\SubscriptionManager; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheItemInterface; diff --git a/tests/GraphQl/Type/FieldsBuilderTest.php b/tests/GraphQl/Type/FieldsBuilderTest.php index ee2f4e2561d..86cc2d45d25 100644 --- a/tests/GraphQl/Type/FieldsBuilderTest.php +++ b/tests/GraphQl/Type/FieldsBuilderTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface; use ApiPlatform\GraphQl\Type\FieldsBuilder; use ApiPlatform\GraphQl\Type\TypeBuilderInterface; @@ -35,6 +34,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\ListOfType; diff --git a/tests/GraphQl/Type/SchemaBuilderTest.php b/tests/GraphQl/Type/SchemaBuilderTest.php index 99ae40b0e9a..3ef4c6cafaf 100644 --- a/tests/GraphQl/Type/SchemaBuilderTest.php +++ b/tests/GraphQl/Type/SchemaBuilderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\FieldsBuilderInterface; use ApiPlatform\GraphQl\Type\SchemaBuilder; use ApiPlatform\GraphQl\Type\TypesContainerInterface; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type as GraphQLType; use PHPUnit\Framework\TestCase; diff --git a/tests/GraphQl/Type/TypeBuilderTest.php b/tests/GraphQl/Type/TypeBuilderTest.php index 743af8d74aa..b84c3a6f866 100644 --- a/tests/GraphQl/Type/TypeBuilderTest.php +++ b/tests/GraphQl/Type/TypeBuilderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Type\FieldsBuilderInterface; use ApiPlatform\GraphQl\Type\TypeBuilder; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\ListOfType; diff --git a/tests/GraphQl/Type/TypeConverterTest.php b/tests/GraphQl/Type/TypeConverterTest.php index bb1c098444f..1a8b20aedb3 100644 --- a/tests/GraphQl/Type/TypeConverterTest.php +++ b/tests/GraphQl/Type/TypeConverterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\GraphQl\Type\TypeBuilderInterface; use ApiPlatform\GraphQl\Type\TypeConverter; @@ -26,6 +25,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\GraphQl\Type\Definition\DateTimeType; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type as GraphQLType; use PHPUnit\Framework\TestCase; diff --git a/tests/GraphQl/Type/TypesContainerTest.php b/tests/GraphQl/Type/TypesContainerTest.php index 9a98289028e..da2c68fe345 100644 --- a/tests/GraphQl/Type/TypesContainerTest.php +++ b/tests/GraphQl/Type/TypesContainerTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\TypeNotFoundException; use ApiPlatform\GraphQl\Type\TypesContainer; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\Type as GraphQLType; use PHPUnit\Framework\TestCase; diff --git a/tests/GraphQl/Type/TypesFactoryTest.php b/tests/GraphQl/Type/TypesFactoryTest.php index 4af8c64a6bc..42d5f407ffb 100644 --- a/tests/GraphQl/Type/TypesFactoryTest.php +++ b/tests/GraphQl/Type/TypesFactoryTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\Definition\TypeInterface; use ApiPlatform\GraphQl\Type\TypesFactory; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Hal/JsonSchema/SchemaFactoryTest.php b/tests/Hal/JsonSchema/SchemaFactoryTest.php index 7cf6ff4cfe2..a2dfb65fd82 100644 --- a/tests/Hal/JsonSchema/SchemaFactoryTest.php +++ b/tests/Hal/JsonSchema/SchemaFactoryTest.php @@ -19,13 +19,13 @@ use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hal\JsonSchema\SchemaFactory; use ApiPlatform\Hydra\JsonSchema\SchemaFactory as HydraSchemaFactory; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory as BaseSchemaFactory; use ApiPlatform\JsonSchema\TypeFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Hal/Serializer/CollectionNormalizerTest.php b/tests/Hal/Serializer/CollectionNormalizerTest.php index 618d3f1f846..b1bc4d57954 100644 --- a/tests/Hal/Serializer/CollectionNormalizerTest.php +++ b/tests/Hal/Serializer/CollectionNormalizerTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\CollectionNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/Hal/Serializer/EntrypointNormalizerTest.php b/tests/Hal/Serializer/EntrypointNormalizerTest.php index 49fa5282bc3..788ec6fea2a 100644 --- a/tests/Hal/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hal/Serializer/EntrypointNormalizerTest.php @@ -18,10 +18,10 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Hal/Serializer/ItemNormalizerTest.php b/tests/Hal/Serializer/ItemNormalizerTest.php index 80c31dc60c9..00e1740a226 100644 --- a/tests/Hal/Serializer/ItemNormalizerTest.php +++ b/tests/Hal/Serializer/ItemNormalizerTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; @@ -24,6 +23,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\MaxDepthDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Hal/Serializer/ObjectNormalizerTest.php b/tests/Hal/Serializer/ObjectNormalizerTest.php index 5ff401e139f..375a326466a 100644 --- a/tests/Hal/Serializer/ObjectNormalizerTest.php +++ b/tests/Hal/Serializer/ObjectNormalizerTest.php @@ -14,9 +14,9 @@ namespace ApiPlatform\Tests\Hal\Serializer; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\ObjectNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/HttpCache/EventListener/AddHeadersListenerTest.php b/tests/HttpCache/EventListener/AddHeadersListenerTest.php index 40abcd69676..fb1389054ee 100644 --- a/tests/HttpCache/EventListener/AddHeadersListenerTest.php +++ b/tests/HttpCache/EventListener/AddHeadersListenerTest.php @@ -13,11 +13,9 @@ namespace ApiPlatform\Tests\HttpCache\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\HttpCache\EventListener\AddHeadersListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -26,7 +24,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class AddHeadersListenerTest extends TestCase { @@ -34,7 +31,7 @@ class AddHeadersListenerTest extends TestCase public function testDoNotSetHeaderWhenMethodNotCacheable() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $request->setMethod('PUT'); $response = new Response(); $event = new ResponseEvent( @@ -52,7 +49,7 @@ public function testDoNotSetHeaderWhenMethodNotCacheable() public function testDoNotSetHeaderOnUnsuccessfulResponse() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $response = new Response('{}', Response::HTTP_BAD_REQUEST); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), @@ -88,7 +85,7 @@ public function testDoNotSetHeaderWhenNoContent() $response = new Response(); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); @@ -103,15 +100,12 @@ public function testAddHeaders() $response = new Response('some content', 200, ['Vary' => ['Accept', 'Cookie']]); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - - $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30); + $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, 15, 30); $listener->onKernelResponse($event); $this->assertSame('"9893532233caff98cd083a116b013c0b"', $response->getEtag()); @@ -129,148 +123,16 @@ public function testDoNotSetHeaderWhenAlreadySet() $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - - $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30); + $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, 15, 30); $listener->onKernelResponse($event); $this->assertSame('"etag"', $response->getEtag()); $this->assertSame('max-age=300, public, s-maxage=400, stale-if-error=30, stale-while-revalidate=15', $response->headers->get('Cache-Control')); $this->assertSame(['Accept', 'Cookie', 'Accept-Encoding'], $response->getVary()); } - - public function testSetHeadersFromResourceMetadata() - { - $response = new Response('some content', 200, ['Vary' => ['Accept', 'Cookie']]); - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $response - ); - - $metadata = new ResourceMetadata(null, null, null, null, null, ['cache_headers' => ['max_age' => 123, 'shared_max_age' => 456, 'stale_while_revalidate' => 928, 'stale_if_error' => 70, 'vary' => ['Vary-1', 'Vary-2']]]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); - - $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30); - $listener->onKernelResponse($event); - - $this->assertSame('max-age=123, public, s-maxage=456, stale-if-error=70, stale-while-revalidate=928', $response->headers->get('Cache-Control')); - $this->assertSame(['Accept', 'Cookie', 'Vary-1', 'Vary-2'], $response->getVary()); - } - - public function testSetHeadersFromResourceMetadataMarkedAsPrivate() - { - $response = new Response('some content', 200); - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $response - ); - - $metadata = new ResourceMetadata(null, null, null, null, null, [ - 'cache_headers' => [ - 'max_age' => 123, - 'public' => false, - 'shared_max_age' => 456, - ], - ]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); - - $listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal()); - $listener->onKernelResponse($event); - - $this->assertSame('max-age=123, private', $response->headers->get('Cache-Control')); - - // resource's cache marked as private must not contain s-maxage - $this->assertStringNotContainsString('s-maxage', $response->headers->get('Cache-Control')); - } - - public function testSetHeadersFromResourceMetadataMarkedAsPublic() - { - $response = new Response('some content', 200); - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $response - ); - - $metadata = new ResourceMetadata(null, null, null, null, null, [ - 'cache_headers' => [ - 'max_age' => 123, - 'public' => true, - 'shared_max_age' => 456, - ], - ]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); - - $listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal()); - $listener->onKernelResponse($event); - - $this->assertSame('max-age=123, public, s-maxage=456', $response->headers->get('Cache-Control')); - } - - public function testSetHeadersFromResourceMetadataWithNoPrivacy() - { - $response = new Response('some content', 200); - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $response - ); - - $metadata = new ResourceMetadata(null, null, null, null, null, [ - 'cache_headers' => [ - 'max_age' => 123, - 'shared_max_age' => 456, - ], - ]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); - - $listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal()); - $listener->onKernelResponse($event); - - $this->assertSame('max-age=123, public, s-maxage=456', $response->headers->get('Cache-Control')); - } - - public function testSetHeadersFromResourceMetadataWithNoPrivacyDefaultsPrivate() - { - $response = new Response('some content', 200); - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $response - ); - - $metadata = new ResourceMetadata(null, null, null, null, null, [ - 'cache_headers' => [ - 'max_age' => 123, - 'shared_max_age' => 456, - ], - ]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); - - $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], false, $factory->reveal()); - $listener->onKernelResponse($event); - - $this->assertSame('max-age=123, private', $response->headers->get('Cache-Control')); - - // resource's cache marked as private must not contain s-maxage - $this->assertStringNotContainsString('s-maxage', $response->headers->get('Cache-Control')); - } } diff --git a/tests/HttpCache/EventListener/AddTagsListenerTest.php b/tests/HttpCache/EventListener/AddTagsListenerTest.php index bbe3cffda76..93bfd0dd341 100644 --- a/tests/HttpCache/EventListener/AddTagsListenerTest.php +++ b/tests/HttpCache/EventListener/AddTagsListenerTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\HttpCache\EventListener\AddTagsListener; use ApiPlatform\HttpCache\PurgerInterface; use ApiPlatform\Metadata\ApiResource; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/HttpCache/VarnishPurgerTest.php b/tests/HttpCache/VarnishPurgerTest.php index c6ebe1c234c..c1d590b87e4 100644 --- a/tests/HttpCache/VarnishPurgerTest.php +++ b/tests/HttpCache/VarnishPurgerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\HttpCache; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\HttpCache\VarnishPurger; +use ApiPlatform\Tests\ProphecyTrait; use GuzzleHttp\ClientInterface; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7\Response; diff --git a/tests/HttpCache/VarnishXKeyPurgerTest.php b/tests/HttpCache/VarnishXKeyPurgerTest.php index 4b720a7c30b..89334a55673 100644 --- a/tests/HttpCache/VarnishXKeyPurgerTest.php +++ b/tests/HttpCache/VarnishXKeyPurgerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\HttpCache; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\HttpCache\VarnishXKeyPurger; +use ApiPlatform\Tests\ProphecyTrait; use GuzzleHttp\ClientInterface; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7\Response; diff --git a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php index 9f6b19ed729..59328f7018b 100644 --- a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php @@ -14,8 +14,8 @@ namespace ApiPlatform\Tests\Hydra\EventListener; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hydra\EventListener\AddLinkHeaderListener; +use ApiPlatform\Tests\ProphecyTrait; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; use PHPUnit\Framework\TestCase; diff --git a/tests/Hydra/JsonSchema/SchemaFactoryTest.php b/tests/Hydra/JsonSchema/SchemaFactoryTest.php index e2b6939a755..bb97d184794 100644 --- a/tests/Hydra/JsonSchema/SchemaFactoryTest.php +++ b/tests/Hydra/JsonSchema/SchemaFactoryTest.php @@ -19,13 +19,13 @@ use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hydra\JsonSchema\SchemaFactory; use ApiPlatform\JsonLd\ContextBuilder; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory as BaseSchemaFactory; use ApiPlatform\JsonSchema\TypeFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php index 3738825a5d7..af309bea518 100644 --- a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php @@ -18,7 +18,6 @@ use ApiPlatform\Core\Api\OperationType; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\FilterInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer; @@ -26,6 +25,7 @@ use ApiPlatform\Tests\Fixtures\Foo; use ApiPlatform\Tests\Fixtures\NotAResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\Container\ContainerInterface; diff --git a/tests/Hydra/Serializer/CollectionNormalizerTest.php b/tests/Hydra/Serializer/CollectionNormalizerTest.php index 666cb38b4ae..3b025f1b3d6 100644 --- a/tests/Hydra/Serializer/CollectionNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionNormalizerTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Hydra\Serializer\CollectionNormalizer; use ApiPlatform\JsonLd\ContextBuilderInterface; @@ -25,6 +24,7 @@ use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Tests\Fixtures\Foo; use ApiPlatform\Tests\Fixtures\NotAResource; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php b/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php index 653edb38eda..70a46f22fbd 100644 --- a/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php +++ b/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php @@ -14,8 +14,8 @@ namespace ApiPlatform\Tests\Hydra\Serializer; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\ConstraintViolationListNormalizer; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; diff --git a/tests/Hydra/Serializer/DocumentationNormalizerTest.php b/tests/Hydra/Serializer/DocumentationNormalizerTest.php index f4bff5021da..d5390f910d2 100644 --- a/tests/Hydra/Serializer/DocumentationNormalizerTest.php +++ b/tests/Hydra/Serializer/DocumentationNormalizerTest.php @@ -22,7 +22,6 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Hydra\Serializer\DocumentationNormalizer; use ApiPlatform\Metadata\ApiProperty; @@ -39,6 +38,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Hydra/Serializer/EntrypointNormalizerTest.php b/tests/Hydra/Serializer/EntrypointNormalizerTest.php index 5d52dc8cd21..69ef89c04ec 100644 --- a/tests/Hydra/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hydra/Serializer/EntrypointNormalizerTest.php @@ -18,7 +18,6 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FooDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Hydra/Serializer/ErrorNormalizerTest.php b/tests/Hydra/Serializer/ErrorNormalizerTest.php index 68111cc03f5..ac132633020 100644 --- a/tests/Hydra/Serializer/ErrorNormalizerTest.php +++ b/tests/Hydra/Serializer/ErrorNormalizerTest.php @@ -14,8 +14,8 @@ namespace ApiPlatform\Tests\Hydra\Serializer; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\ErrorNormalizer; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\HttpFoundation\Response; diff --git a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php index 88382552151..0501963ca1c 100644 --- a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php +++ b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SoMany; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; diff --git a/tests/JsonApi/Serializer/CollectionNormalizerTest.php b/tests/JsonApi/Serializer/CollectionNormalizerTest.php index 1d1ddb61932..37348e9fd54 100644 --- a/tests/JsonApi/Serializer/CollectionNormalizerTest.php +++ b/tests/JsonApi/Serializer/CollectionNormalizerTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonApi\Serializer\CollectionNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php b/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php index 19913dd6799..c8324818684 100644 --- a/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php +++ b/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\JsonApi\Serializer; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonApi\Serializer\ConstraintViolationListNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; diff --git a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php index f9575fcdece..17e65def0f6 100644 --- a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php +++ b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php @@ -18,13 +18,13 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\JsonApi\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/JsonApi/Serializer/ErrorNormalizerTest.php b/tests/JsonApi/Serializer/ErrorNormalizerTest.php index 1803bd75e9d..d3688d50308 100644 --- a/tests/JsonApi/Serializer/ErrorNormalizerTest.php +++ b/tests/JsonApi/Serializer/ErrorNormalizerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\JsonApi\Serializer; -use ApiPlatform\Core\Tests\Mock\Exception\ErrorCodeSerializable; use ApiPlatform\JsonApi\Serializer\ErrorNormalizer; +use ApiPlatform\Tests\Mock\Exception\ErrorCodeSerializable; use PHPUnit\Framework\TestCase; use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\HttpFoundation\Response; diff --git a/tests/JsonApi/Serializer/ItemNormalizerTest.php b/tests/JsonApi/Serializer/ItemNormalizerTest.php index b2e8a31e463..6df819cc6c6 100644 --- a/tests/JsonApi/Serializer/ItemNormalizerTest.php +++ b/tests/JsonApi/Serializer/ItemNormalizerTest.php @@ -21,7 +21,6 @@ use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\JsonApi\Serializer\ItemNormalizer; @@ -31,6 +30,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CircularReference; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Collections\ArrayCollection; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/JsonLd/Action/ContextActionTest.php b/tests/JsonLd/Action/ContextActionTest.php index ca1ab6ab322..d0bf3073217 100644 --- a/tests/JsonLd/Action/ContextActionTest.php +++ b/tests/JsonLd/Action/ContextActionTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonLd\Action\ContextAction; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; diff --git a/tests/JsonLd/ContextBuilderTest.php b/tests/JsonLd/ContextBuilderTest.php index 8b12d15c939..9df102a1d60 100644 --- a/tests/JsonLd/ContextBuilderTest.php +++ b/tests/JsonLd/ContextBuilderTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonLd\ContextBuilder; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; @@ -26,6 +25,7 @@ use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/JsonLd/Serializer/ItemNormalizerTest.php b/tests/JsonLd/Serializer/ItemNormalizerTest.php index ab225838996..26ac57588ec 100644 --- a/tests/JsonLd/Serializer/ItemNormalizerTest.php +++ b/tests/JsonLd/Serializer/ItemNormalizerTest.php @@ -17,7 +17,6 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\JsonLd\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/JsonLd/Serializer/ObjectNormalizerTest.php b/tests/JsonLd/Serializer/ObjectNormalizerTest.php index 9d242e29c00..61fbde5b9ad 100644 --- a/tests/JsonLd/Serializer/ObjectNormalizerTest.php +++ b/tests/JsonLd/Serializer/ObjectNormalizerTest.php @@ -14,10 +14,10 @@ namespace ApiPlatform\Tests\JsonLd\Serializer; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonLd\AnonymousContextBuilderInterface; use ApiPlatform\JsonLd\Serializer\ObjectNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/JsonSchema/SchemaFactoryTest.php b/tests/JsonSchema/SchemaFactoryTest.php index c691115274a..f16ab699f3e 100644 --- a/tests/JsonSchema/SchemaFactoryTest.php +++ b/tests/JsonSchema/SchemaFactoryTest.php @@ -17,7 +17,6 @@ use ApiPlatform\Core\Api\OperationType; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactoryInterface; @@ -27,6 +26,7 @@ use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\NotAResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\OverriddenOperationDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/JsonSchema/TypeFactoryTest.php b/tests/JsonSchema/TypeFactoryTest.php index 44fd50fd886..823280e464b 100644 --- a/tests/JsonSchema/TypeFactoryTest.php +++ b/tests/JsonSchema/TypeFactoryTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\JsonSchema; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\JsonSchema\TypeFactory; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php index 8b3b53aaf1d..09891a231cc 100644 --- a/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\AttributePropertyMetadataFactory; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8ApiPropertyAttribute; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php index d9a3177d841..f5e4573ce16 100644 --- a/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\CachedPropertyMetadataFactory; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheException; use Psr\Cache\CacheItemInterface; diff --git a/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php b/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php index aaf1f4c7d6a..bbe2d7b7eb7 100644 --- a/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php +++ b/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheException; use Psr\Cache\CacheItemInterface; diff --git a/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php index 5aa5cd755f9..d13dd450c78 100644 --- a/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\DefaultPropertyMetadataFactory; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPropertyWithDefaultValue; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class DefaultPropertyMetadataFactoryTest extends TestCase diff --git a/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php b/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php index 4cb24362a2b..f2ada8d8e04 100644 --- a/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php +++ b/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php @@ -15,13 +15,13 @@ use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php index 39049295f4d..d72715836d8 100644 --- a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory; @@ -22,6 +21,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\Annotation\Ignore; diff --git a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php index e6df50ba6b8..53d38505faf 100644 --- a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -33,6 +32,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResources; use ApiPlatform\Tests\Fixtures\TestBundle\State\AttributeResourceProcessor; use ApiPlatform\Tests\Fixtures\TestBundle\State\AttributeResourceProvider; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php index 1e1cd9660a3..51aebcd77dc 100644 --- a/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; @@ -21,6 +20,7 @@ use ApiPlatform\Metadata\Resource\Factory\FormatsResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class FormatsResourceMetadataCollectionFactoryTest extends TestCase diff --git a/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php index 06902ca838b..92667f60bb6 100644 --- a/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Resource\Factory\InputOutputResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\DummyEntity; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class InputOutputResourceMetadataCollectionFactoryTest extends TestCase diff --git a/tests/Metadata/Resource/Factory/LinkFactoryTest.php b/tests/Metadata/Resource/Factory/LinkFactoryTest.php index 9073bc2f9ab..562035efa5e 100644 --- a/tests/Metadata/Resource/Factory/LinkFactoryTest.php +++ b/tests/Metadata/Resource/Factory/LinkFactoryTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; @@ -26,6 +25,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; diff --git a/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php index 0b28987a8e3..030e62f06b9 100644 --- a/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Query; @@ -29,6 +28,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Collections\Collection; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php index c6dc236dcfa..0961e74aa0d 100644 --- a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Resource\Factory\PhpDocResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\ClassWithNoDocBlock; use ApiPlatform\Tests\Fixtures\DummyEntity; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class PhpDocResourceMetadataCollectionFactoryTest extends TestCase diff --git a/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php index 4b54258dd2d..9481cd620c8 100644 --- a/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -31,6 +30,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Metadata/Resource/ResourceMetadataCollectionTest.php b/tests/Metadata/Resource/ResourceMetadataCollectionTest.php index d9c3b94cbde..52b97deb092 100644 --- a/tests/Metadata/Resource/ResourceMetadataCollectionTest.php +++ b/tests/Metadata/Resource/ResourceMetadataCollectionTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Metadata\Resource; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; final class ResourceMetadataCollectionTest extends TestCase diff --git a/tests/Core/Mock/Exception/ErrorCodeSerializable.php b/tests/Mock/Exception/ErrorCodeSerializable.php similarity index 91% rename from tests/Core/Mock/Exception/ErrorCodeSerializable.php rename to tests/Mock/Exception/ErrorCodeSerializable.php index 2d1fb46371c..2531b33f207 100644 --- a/tests/Core/Mock/Exception/ErrorCodeSerializable.php +++ b/tests/Mock/Exception/ErrorCodeSerializable.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Mock\Exception; +namespace ApiPlatform\Tests\Mock\Exception; use ApiPlatform\Exception\ErrorCodeSerializableInterface; diff --git a/tests/OpenApi/Factory/OpenApiFactoryTest.php b/tests/OpenApi/Factory/OpenApiFactoryTest.php index 170e031134e..1468c7ec395 100644 --- a/tests/OpenApi/Factory/OpenApiFactoryTest.php +++ b/tests/OpenApi/Factory/OpenApiFactoryTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\OpenApi\Factory; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; @@ -46,6 +45,7 @@ use ApiPlatform\Tests\Fixtures\DummyFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\Container\ContainerInterface; diff --git a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php index 113c90a232f..1050884d9c5 100644 --- a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php +++ b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php @@ -14,11 +14,11 @@ namespace ApiPlatform\Tests\OpenApi\Serializer; use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php index 6f9a4a322d7..426d768454b 100644 --- a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php +++ b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php @@ -23,7 +23,6 @@ use ApiPlatform\Core\OpenApi\Factory\OpenApiFactory as LegacyOpenApiFactory; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; use ApiPlatform\Metadata\ApiResource; @@ -47,6 +46,7 @@ use ApiPlatform\PathResolver\OperationPathResolver; use ApiPlatform\State\Pagination\PaginationOptions; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\Container\ContainerInterface; diff --git a/tests/PathResolver/CustomOperationPathResolverTest.php b/tests/PathResolver/CustomOperationPathResolverTest.php deleted file mode 100644 index 55d9d2783f9..00000000000 --- a/tests/PathResolver/CustomOperationPathResolverTest.php +++ /dev/null @@ -1,56 +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); - -namespace ApiPlatform\Tests\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use PHPUnit\Framework\TestCase; - -/** - * @author Baptiste Meyer - */ -class CustomOperationPathResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testResolveOperationPath() - { - $operationPathResolver = new CustomOperationPathResolver($this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $this->assertEquals('/foos.{_format}', $operationPathResolver->resolveOperationPath('Foo', ['path' => '/foos.{_format}'], OperationType::COLLECTION, 'get')); - } - - public function testResolveOperationPathWithDeferred() - { - $operationPathResolverProphecy = $this->prophesize(OperationPathResolverInterface::class); - $operationPathResolverProphecy->resolveOperationPath('Foo', [], OperationType::ITEM, 'get')->willReturn('/foos/{id}.{_format}')->shouldBeCalled(); - - $operationPathResolver = new CustomOperationPathResolver($operationPathResolverProphecy->reveal()); - - $this->assertEquals('/foos/{id}.{_format}', $operationPathResolver->resolveOperationPath('Foo', [], OperationType::ITEM, 'get')); - } - - /** - * @group legacy - * @expectedDeprecation Method ApiPlatform\PathResolver\CustomOperationPathResolver::resolveOperationPath() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1. - */ - public function testLegacyResolveOperationPath() - { - $operationPathResolver = new CustomOperationPathResolver($this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $this->assertEquals('/foos.{_format}', $operationPathResolver->resolveOperationPath('Foo', ['path' => '/foos.{_format}'], true)); - } -} diff --git a/tests/PathResolver/OperationPathResolverTest.php b/tests/PathResolver/OperationPathResolverTest.php deleted file mode 100644 index c70b5e9abcb..00000000000 --- a/tests/PathResolver/OperationPathResolverTest.php +++ /dev/null @@ -1,34 +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); - -namespace ApiPlatform\Tests\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\PathResolver\OperationPathResolver; -use PHPUnit\Framework\TestCase; - -class OperationPathResolverTest extends TestCase -{ - public function testResolveItemOperationPath() - { - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - $this->assertEquals('/foos/{id}.{_format}', $operationPathResolver->resolveOperationPath('Foo', [], OperationType::ITEM, 'get')); - } - - public function testResolveItemOperationPathIdentifiedBy() - { - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - $this->assertSame('/short_names/{isbn}.{_format}', $operationPathResolver->resolveOperationPath('ShortName', ['identifiers' => ['isbn']], OperationType::ITEM, 'get')); - } -} diff --git a/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php b/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php index 8bc6adc5fd3..44d21b3153b 100644 --- a/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php +++ b/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Problem\Serializer; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Problem\Serializer\ConstraintViolationListNormalizer; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; diff --git a/tests/Core/ProphecyTrait.php b/tests/ProphecyTrait.php similarity index 99% rename from tests/Core/ProphecyTrait.php rename to tests/ProphecyTrait.php index e9058776377..6bc57c772a3 100644 --- a/tests/Core/ProphecyTrait.php +++ b/tests/ProphecyTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests; +namespace ApiPlatform\Tests; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\TestCase; diff --git a/tests/Serializer/AbstractItemNormalizerTest.php b/tests/Serializer/AbstractItemNormalizerTest.php index a0a26cf4619..7557ac07b3d 100644 --- a/tests/Serializer/AbstractItemNormalizerTest.php +++ b/tests/Serializer/AbstractItemNormalizerTest.php @@ -13,41 +13,25 @@ namespace ApiPlatform\Tests\Serializer; -use ApiPlatform\Api\IriConverterInterface as NewIriConverterInterface; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Get; -use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Serializer\AbstractItemNormalizer; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyForAdditionalFields; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyForAdditionalFieldsInput; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SecuredDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Collections\ArrayCollection; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\Exception\UnexpectedValueException; @@ -60,45 +44,12 @@ /** * @author Amrouche Hamza * @author Kévin Dunglas - * @group legacy */ class AbstractItemNormalizerTest extends TestCase { use ExpectDeprecationTrait; use ProphecyTrait; - /** - * @group legacy - */ - public function testLegacySupportNormalizationAndSupportDenormalization() - { - $std = new \stdClass(); - $dummy = new Dummy(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true)->shouldBeCalled(); - $resourceClassResolverProphecy->isResourceClass(\stdClass::class)->willReturn(false)->shouldBeCalled(); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - ]); - - $this->assertTrue($normalizer->supportsNormalization($dummy)); - $this->assertFalse($normalizer->supportsNormalization($std)); - $this->assertTrue($normalizer->supportsDenormalization($dummy, Dummy::class)); - $this->assertFalse($normalizer->supportsDenormalization($std, \stdClass::class)); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } - public function testSupportNormalizationAndSupportDenormalization() { $std = new \stdClass(); @@ -121,9 +72,6 @@ public function testSupportNormalizationAndSupportDenormalization() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -162,8 +110,8 @@ public function testNormalize() $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummiesType])->withReadable(true)->withWritable(false)->withReadableLink(false)); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1'); - $iriConverterProphecy->getIriFromItem($relatedDummy)->willReturn('/dummies/2'); + $iriConverterProphecy->getIriFromResource($dummy, Argument::cetera())->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($relatedDummy, Argument::cetera())->willReturn('/dummies/2'); $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); $propertyAccessorProphecy->getValue($dummy, 'name')->willReturn('foo'); @@ -190,9 +138,6 @@ public function testNormalize() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -228,7 +173,7 @@ public function testNormalizeWithSecuredProperty() $propertyMetadataFactoryProphecy->create(SecuredDummy::class, 'adminOnlyProperty', [])->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(true)->withSecurity('is_granted(\'ROLE_ADMIN\')')); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/secured_dummies/1'); + $iriConverterProphecy->getIriFromResource($dummy, Argument::cetera())->willReturn('/secured_dummies/1'); $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); $propertyAccessorProphecy->getValue($dummy, 'title')->willReturn('myPublicTitle'); @@ -257,9 +202,6 @@ public function testNormalizeWithSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -318,9 +260,6 @@ public function testDenormalizeWithSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -375,9 +314,6 @@ public function testDenormalizeCreateWithDeniedPostDenormalizeSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -440,9 +376,6 @@ public function testDenormalizeUpdateWithSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -506,9 +439,6 @@ public function testDenormalizeUpdateWithDeniedSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -568,9 +498,6 @@ public function testDenormalizeUpdateWithDeniedPostDenormalizeSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -608,7 +535,7 @@ public function testNormalizeReadableLinks() $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummiesType])->withReadable(true)->withWritable(false)->withReadableLink(true)); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($dummy, Argument::cetera())->willReturn('/dummies/1'); $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); $propertyAccessorProphecy->getValue($dummy, 'relatedDummy')->willReturn($relatedDummy); @@ -640,9 +567,6 @@ public function testNormalizeReadableLinks() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -682,8 +606,8 @@ public function testDenormalize() $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummiesType])->withReadable(false)->withWritable(true)->withReadableLink(false)->withWritableLink(false)); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getItemFromIri('/dummies/1', Argument::type('array'))->willReturn($relatedDummy1); - $iriConverterProphecy->getItemFromIri('/dummies/2', Argument::type('array'))->willReturn($relatedDummy2); + $iriConverterProphecy->getResourceFromIri('/dummies/1', Argument::type('array'))->willReturn($relatedDummy1); + $iriConverterProphecy->getResourceFromIri('/dummies/2', Argument::type('array'))->willReturn($relatedDummy2); $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); @@ -704,9 +628,6 @@ public function testDenormalize() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -724,57 +645,57 @@ public function testDenormalize() public function testCanDenormalizeInputClassWithDifferentFieldsThanResourceClass() { - $data = [ - 'dummyName' => 'Dummy Name', - ]; - - $context = [ - 'resource_class' => DummyForAdditionalFields::class, - 'input' => ['class' => DummyForAdditionalFieldsInput::class], - 'output' => ['class' => DummyForAdditionalFields::class], - ]; - $augmentedContext = $context + ['api_denormalize' => true]; - - $preHydratedDummy = new DummyForAdditionalFieldsInput('Name Dummy'); - $cleanedContext = array_diff_key($augmentedContext, [ - 'input' => null, - 'resource_class' => null, - ]); - $cleanedContextWithObjectToPopulate = array_merge($cleanedContext, [ - AbstractObjectNormalizer::OBJECT_TO_POPULATE => $preHydratedDummy, - AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE => true, - ]); - - $dummyInputDto = new DummyForAdditionalFieldsInput('Dummy Name'); - $dummy = new DummyForAdditionalFields('Dummy Name', 'name-dummy'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, DummyForAdditionalFields::class)->willReturn(DummyForAdditionalFields::class); - - $inputDataTransformerProphecy = $this->prophesize(DataTransformerInitializerInterface::class); - $inputDataTransformerProphecy->willImplement(DataTransformerInitializerInterface::class); - $inputDataTransformerProphecy->initialize(DummyForAdditionalFieldsInput::class, $cleanedContext)->willReturn($preHydratedDummy); - $inputDataTransformerProphecy->supportsTransformation($data, DummyForAdditionalFields::class, $augmentedContext)->willReturn(true); - $inputDataTransformerProphecy->transform($dummyInputDto, DummyForAdditionalFields::class, $augmentedContext)->willReturn($dummy); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - $serializerProphecy->denormalize($data, DummyForAdditionalFieldsInput::class, 'json', $cleanedContextWithObjectToPopulate)->willReturn($dummyInputDto); - - $normalizer = new class($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), null, null, null, null, false, [], [$inputDataTransformerProphecy->reveal()], null, null) extends AbstractItemNormalizer { - }; - $normalizer->setSerializer($serializerProphecy->reveal()); - - $actual = $normalizer->denormalize($data, DummyForAdditionalFields::class, 'json', $context); - - $this->assertInstanceOf(DummyForAdditionalFields::class, $actual); - $this->assertEquals('Dummy Name', $actual->getName()); + // $data = [ + // 'dummyName' => 'Dummy Name', + // ]; + // + // $context = [ + // 'resource_class' => DummyForAdditionalFields::class, + // 'input' => ['class' => DummyForAdditionalFieldsInput::class], + // 'output' => ['class' => DummyForAdditionalFields::class], + // ]; + // $augmentedContext = $context + ['api_denormalize' => true]; + // + // $preHydratedDummy = new DummyForAdditionalFieldsInput('Name Dummy'); + // $cleanedContext = array_diff_key($augmentedContext, [ + // 'input' => null, + // 'resource_class' => null, + // ]); + // $cleanedContextWithObjectToPopulate = array_merge($cleanedContext, [ + // AbstractObjectNormalizer::OBJECT_TO_POPULATE => $preHydratedDummy, + // AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE => true, + // ]); + // + // $dummyInputDto = new DummyForAdditionalFieldsInput('Dummy Name'); + // $dummy = new DummyForAdditionalFields('Dummy Name', 'name-dummy'); + // + // $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + // + // $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + // + // $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); + // + // $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + // $resourceClassResolverProphecy->getResourceClass(null, DummyForAdditionalFields::class)->willReturn(DummyForAdditionalFields::class); + // + // $inputDataTransformerProphecy = $this->prophesize(DataTransformerInitializerInterface::class); + // $inputDataTransformerProphecy->willImplement(DataTransformerInitializerInterface::class); + // $inputDataTransformerProphecy->initialize(DummyForAdditionalFieldsInput::class, $cleanedContext)->willReturn($preHydratedDummy); + // $inputDataTransformerProphecy->supportsTransformation($data, DummyForAdditionalFields::class, $augmentedContext)->willReturn(true); + // $inputDataTransformerProphecy->transform($dummyInputDto, DummyForAdditionalFields::class, $augmentedContext)->willReturn($dummy); + // + // $serializerProphecy = $this->prophesize(SerializerInterface::class); + // $serializerProphecy->willImplement(DenormalizerInterface::class); + // $serializerProphecy->denormalize($data, DummyForAdditionalFieldsInput::class, 'json', $cleanedContextWithObjectToPopulate)->willReturn($dummyInputDto); + // + // $normalizer = new class($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), null, null, null, [], null, null) extends AbstractItemNormalizer { + // }; + // $normalizer->setSerializer($serializerProphecy->reveal()); + // + // $actual = $normalizer->denormalize($data, DummyForAdditionalFields::class, 'json', $context); + // + // $this->assertInstanceOf(DummyForAdditionalFields::class, $actual); + // $this->assertEquals('Dummy Name', $actual->getName()); } public function testDenormalizeWritableLinks() @@ -822,9 +743,6 @@ public function testDenormalizeWritableLinks() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -878,9 +796,6 @@ public function testBadRelationType() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -930,9 +845,6 @@ public function testInnerDocumentNotAllowed() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -976,9 +888,6 @@ public function testBadType() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1019,9 +928,6 @@ public function testTypeChecksCanBeDisabled() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1066,9 +972,6 @@ public function testJsonAllowIntAsFloat() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1137,9 +1040,6 @@ public function testDenormalizeBadKeyType() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1180,9 +1080,6 @@ public function testNullable() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1196,356 +1093,6 @@ public function testNullable() $propertyAccessorProphecy->setValue($actual, 'name', null)->shouldHaveBeenCalled(); } - /** - * @group legacy - */ - public function testChildInheritedProperty(): void - { - $dummy = new DummyTableInheritance(); - $dummy->setName('foo'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyTableInheritance::class, [])->willReturn( - new PropertyNameCollection(['name', 'nickname']) - )->shouldBeCalled(); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyTableInheritance::class, 'name', [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), '', true) - )->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(DummyTableInheritance::class, 'nickname', [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING, true), '', true, true, false, false, false, false, null, DummyTableInheritanceChild::class) - )->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1')->shouldBeCalled(); - - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - $propertyAccessorProphecy->getValue($dummy, 'name')->willReturn('foo')->shouldBeCalled(); - $propertyAccessorProphecy->getValue($dummy, 'nickname')->willThrow(new NoSuchPropertyException())->shouldBeCalled(); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($dummy, DummyTableInheritance::class)->willReturn(DummyTableInheritance::class)->shouldBeCalled(); - $resourceClassResolverProphecy->isResourceClass(DummyTableInheritance::class)->willReturn(true)->shouldBeCalled(); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(NormalizerInterface::class); - $serializerProphecy->normalize('foo', null, Argument::type('array'))->willReturn('foo')->shouldBeCalled(); - $serializerProphecy->normalize(null, null, Argument::type('array'))->willReturn(null)->shouldBeCalled(); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - null, - false, - [], - [], - null, - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $this->assertEquals([ - 'name' => 'foo', - 'nickname' => null, - ], $normalizer->normalize($dummy, null, ['resource_class' => DummyTableInheritance::class, 'resources' => []])); - } - - /** - * TODO: to remove in 3.0. - * - * @group legacy - */ - public function testDenormalizeRelationWithPlainId() - { - $data = [ - 'relatedDummy' => 1, - ]; - - $relatedDummy = new RelatedDummy(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['relatedDummy'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), '', false, true, false, false)); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(RelatedDummy::class, 1, null, Argument::type('array'))->willReturn($relatedDummy); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - $itemDataProviderProphecy->reveal(), - true, - [], - [], - null, - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $actual = $normalizer->denormalize($data, Dummy::class, 'jsonld'); - - $this->assertInstanceOf(Dummy::class, $actual); - - $propertyAccessorProphecy->setValue($actual, 'relatedDummy', $relatedDummy)->shouldHaveBeenCalled(); - } - - /** - * TODO: to remove in 3.0. - * - * @group legacy - */ - public function testDenormalizeRelationWithPlainIdNotFound() - { - $this->expectException(ItemNotFoundException::class); - $this->expectExceptionMessage(sprintf('Item not found for resource "%s" with id "1".', RelatedDummy::class)); - - $data = [ - 'relatedDummy' => 1, - ]; - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['relatedDummy'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn( - new PropertyMetadata( - new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), - '', - false, - true, - false, - false - ) - ); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(RelatedDummy::class, 1, null, Argument::type('array'))->willReturn(null); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - $itemDataProviderProphecy->reveal(), - true, - [], - [], - null, - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $normalizer->denormalize($data, Dummy::class, 'jsonld'); - } - - /** - * TODO: to remove in 3.0. - */ - public function testDoNotDenormalizeRelationWithPlainIdWhenPlainIdentifiersAreNotAllowed() - { - $this->expectException(UnexpectedValueException::class); - $this->expectExceptionMessage('Expected IRI or nested document for attribute "relatedDummy", "integer" given.'); - - $data = [ - 'relatedDummy' => 1, - ]; - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['relatedDummy'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn( - new PropertyMetadata( - new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), - '', - false, - true, - false, - false - ) - ); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(RelatedDummy::class, 1, null, Argument::type('array'))->shouldNotBeCalled(); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - $itemDataProviderProphecy->reveal(), - false, - [], - [], - null, - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $normalizer->denormalize($data, Dummy::class, 'jsonld'); - } - - /** - * Test case: - * 1. Request `PUT {InputDto} /recover_password` - * 2. The `AbstractItemNormalizer` denormalizes the json representation of `{InputDto}` in a `RecoverPasswordInput` - * 3. The `DataTransformer` transforms this `InputDto` in a `Dummy` - * 4. Messenger is used, we send the `Dummy` - * 5. The handler receives a `{Dummy}` json representation and tries to denormalize it - * 6. Because it has an `input`, the `AbstractItemNormalizer` tries to denormalize it as a `InputDto` which is wrong, it's a `{Dummy}`. - * - * @group legacy - */ - public function testNormalizationWithDataTransformer() - { - $this->expectDeprecation('Since api-platform/core 2.7: The DataTransformer pattern is deprecated, use a Provider or a Processor and either use your input or return a new output there.'); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->willReturn(new PropertyNameCollection(['name'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(false)->withWritable(true)); - - $iriConverterProphecy = $this->prophesize(NewIriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(InputDto::class)->willReturn(false); - - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $jsonInput = ['foo' => 'f', 'bar' => 8]; - $inputDto = new InputDto(); - $inputDto->foo = 'f'; - $inputDto->bar = 8; - $transformed = new Dummy(); - $context = [ - 'operation' => new Get(), - 'operation_type' => 'collection', - 'collection_operation_name' => 'post', - 'resource_class' => Dummy::class, - 'input' => [ - 'class' => InputDto::class, - 'name' => 'InputDto', - ], - 'output' => ['class' => 'null'], - 'api_denormalize' => true, // this is added by the normalizer - ]; - $cleanedContext = array_diff_key($context, [ - 'input' => null, - 'resource_class' => null, - ]); - - $secondJsonInput = ['name' => 'Dummy']; - $secondContext = ['api_denormalize' => true, 'resource_class' => Dummy::class]; - $secondTransformed = new Dummy(); - $secondTransformed->setName('Dummy'); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - $serializerProphecy->denormalize($jsonInput, InputDto::class, 'jsonld', $cleanedContext)->willReturn($inputDto); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection( - Dummy::class, - [(new ApiResource())->withOperations(new Operations([(new Get())->withShortName('dummy')->withInput(['class' => InputDto::class])]))] - )); - - $dataTransformerProphecy = $this->prophesize(DataTransformerInterface::class); - $dataTransformerProphecy->supportsTransformation($jsonInput, Dummy::class, $context)->willReturn(true); - $dataTransformerProphecy->supportsTransformation($secondJsonInput, Dummy::class, $secondContext)->willReturn(false); - $dataTransformerProphecy->transform($inputDto, Dummy::class, $context)->willReturn($transformed); - - $secondDataTransformerProphecy = $this->prophesize(DataTransformerInterface::class); - $secondDataTransformerProphecy->supportsTransformation(Argument::any(), Dummy::class, Argument::any())->willReturn(false); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - $itemDataProviderProphecy->reveal(), - false, - [], - [$dataTransformerProphecy->reveal(), $secondDataTransformerProphecy->reveal()], - $resourceMetadataFactoryProphecy->reveal(), - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - // This is step 1-3, {InputDto} to Dummy - $this->assertEquals($transformed, $normalizer->denormalize($jsonInput, Dummy::class, 'jsonld', $context)); - - // Messenger sends {InputDto} - $actualDummy = $normalizer->denormalize($secondJsonInput, Dummy::class, 'jsonld'); - - $this->assertInstanceOf(Dummy::class, $actualDummy); - - $propertyAccessorProphecy->setValue($actualDummy, 'name', 'Dummy')->shouldHaveBeenCalled(); - } - public function testDenormalizeBasicTypePropertiesFromXml() { $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -1587,7 +1134,7 @@ public function testDenormalizeBasicTypePropertiesFromXml() $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'boolFalse2', false)->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'int1', 4711)->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'int2', -4711)->shouldBeCalled(); - $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'float1', Argument::approximate(123.456, 0.01))->shouldBeCalled(); + $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'float1', Argument::approximate(123.456, 0))->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'float2', Argument::approximate(-1.2344e56, 1))->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'float3', Argument::approximate(45E-6, 1))->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'floatNaN', Argument::that(static function (float $arg) { @@ -1611,9 +1158,6 @@ public function testDenormalizeBasicTypePropertiesFromXml() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1685,9 +1229,6 @@ public function testDenormalizeCollectionDecodedFromXmlWithOneChild() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, diff --git a/tests/Serializer/ItemNormalizerTest.php b/tests/Serializer/ItemNormalizerTest.php index 462f78fcfd3..7cbf7ae306d 100644 --- a/tests/Serializer/ItemNormalizerTest.php +++ b/tests/Serializer/ItemNormalizerTest.php @@ -13,18 +13,15 @@ namespace ApiPlatform\Tests\Serializer; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Serializer\ItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; @@ -35,7 +32,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class ItemNormalizerTest extends TestCase { @@ -93,7 +89,7 @@ public function testNormalize() $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadata); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($dummy, Argument::cetera())->willReturn('/dummies/1'); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, null)->willReturn(Dummy::class); @@ -107,15 +103,7 @@ public function testNormalize() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -142,20 +130,11 @@ public function testDenormalize() $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->willImplement(DenormalizerInterface::class); - $normalizer = new ItemNormalizer( $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -176,7 +155,7 @@ public function testDenormalizeWithIri() $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadata)->shouldBeCalled(); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getItemFromIri('/dummies/12', ['resource_class' => Dummy::class, 'api_allow_update' => true, 'fetch_data' => true])->shouldBeCalled(); + $iriConverterProphecy->getResourceFromIri('/dummies/12', ['resource_class' => Dummy::class, 'api_allow_update' => true, 'fetch_data' => true])->shouldBeCalled(); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); @@ -189,15 +168,7 @@ public function testDenormalizeWithIri() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -226,15 +197,7 @@ public function testDenormalizeWithIdAndUpdateNotAllowed() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); $normalizer->denormalize(['id' => '12', 'name' => 'hello'], Dummy::class, null, $context); @@ -266,15 +229,7 @@ public function testDenormalizeWithIdAndNoResourceClass() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -283,51 +238,4 @@ public function testDenormalizeWithIdAndNoResourceClass() $this->assertSame('42', $object->getId()); $this->assertSame('hello', $object->getName()); } - - /** - * @group legacy - */ - public function testNormalizeWithDataTransformers() - { - $this->expectDeprecation('Since api-platform/core 2.7: The DataTransformer pattern is deprecated, use a Provider or a Processor and either use your input or return a new output there.'); - $dummy = new Dummy(); - $dummy->setName('hello'); - $output = new OutputDto(); - - $propertyNameCollection = new PropertyNameCollection(['baz']); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadata = new ApiProperty(null, null, true); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($output, null)->willThrow(InvalidArgumentException::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(NormalizerInterface::class); - $serializerProphecy->normalize(Argument::type(OutputDto::class), null, Argument::type('array'))->willReturn(['baz' => 'hello'])->shouldBeCalled(); - - $dataTransformer = $this->prophesize(DataTransformerInterface::class); - $dataTransformer->supportsTransformation($dummy, OutputDto::class, Argument::any())->shouldBeCalled()->willReturn(true); - $dataTransformer->transform($dummy, OutputDto::class, Argument::any())->shouldBeCalled()->willReturn($output); - - $normalizer = new ItemNormalizer( - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [$dataTransformer->reveal()], - null - ); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $this->assertEquals(['baz' => 'hello'], $normalizer->normalize($dummy, null, ['resources' => [], 'output' => ['class' => OutputDto::class]])); - } } diff --git a/tests/Serializer/LegacySerializerContextBuilderTest.php b/tests/Serializer/LegacySerializerContextBuilderTest.php deleted file mode 100644 index dd0e95be199..00000000000 --- a/tests/Serializer/LegacySerializerContextBuilderTest.php +++ /dev/null @@ -1,122 +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); - -namespace ApiPlatform\Tests\Serializer; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Serializer\SerializerContextBuilder; -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Request; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class LegacySerializerContextBuilderTest extends TestCase -{ - use ProphecyTrait; - - /** - * @var SerializerContextBuilder - */ - private $builder; - - protected function setUp(): void - { - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - [], - [], - [ - 'normalization_context' => ['foo' => 'bar', DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'MyDefinition'], - 'denormalization_context' => ['bar' => 'baz'], - ] - ); - - $resourceMetadataWithPatch = new ResourceMetadata( - null, - null, - null, - ['patch' => ['method' => 'PATCH', 'input_formats' => ['json' => ['application/merge-patch+json']]]], - [] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata); - $resourceMetadataFactoryProphecy->create('FooWithPatch')->willReturn($resourceMetadataWithPatch); - - $this->builder = new SerializerContextBuilder($resourceMetadataFactoryProphecy->reveal()); - } - - public function testCreateFromRequest() - { - $request = Request::create('/foos/1'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['foo' => 'bar', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, true)); - - $request = Request::create('/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'pot', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['foo' => 'bar', 'collection_operation_name' => 'pot', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, true)); - - $request = Request::create('/foos/1'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/foos', 'POST'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'collection_operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/foos', 'PUT'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'put', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'collection_operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/bars/1/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'subresource_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'operation_type' => 'subresource', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/foowithpatch/1', 'PATCH'); - $request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_item_operation_name' => 'patch', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $expected = ['item_operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'operation_type' => 'item', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/bars/1/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', '_api_subresource_context' => ['identifiers' => ['id' => ['Foo', 'id']]], 'id' => '1']); - $expected = ['bar' => 'baz', 'subresource_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'operation_type' => 'subresource', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'subresource_identifiers' => ['id' => '1'], 'subresource_resources' => ['Foo' => ['id' => '1']]]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - } - - public function testThrowExceptionOnInvalidRequest() - { - $this->expectException(RuntimeException::class); - - $this->builder->createFromRequest(new Request(), false); - } - - public function testReuseExistingAttributes() - { - $expected = ['bar' => 'baz', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest(Request::create('/foos/1'), false, ['resource_class' => 'Foo', 'item_operation_name' => 'get'])); - } -} diff --git a/tests/Serializer/SerializerContextBuilderTest.php b/tests/Serializer/SerializerContextBuilderTest.php index 24926fb8a27..c7002b7d747 100644 --- a/tests/Serializer/SerializerContextBuilderTest.php +++ b/tests/Serializer/SerializerContextBuilderTest.php @@ -13,51 +13,49 @@ namespace ApiPlatform\Tests\Serializer; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\HttpOperation; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Serializer\SerializerContextBuilder; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; /** * @author Kévin Dunglas - * @group legacy */ class SerializerContextBuilderTest extends TestCase { use ProphecyTrait; - /** - * @var SerializerContextBuilder - */ - private $builder; + private SerializerContextBuilder $builder; + private HttpOperation $operation; + private HttpOperation $patchOperation; protected function setUp(): void { - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - [], - [], - [ - 'normalization_context' => ['foo' => 'bar', DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'MyDefinition'], - 'denormalization_context' => ['bar' => 'baz'], - ] - ); - - $resourceMetadataWithPatch = new ResourceMetadata( - null, - null, - null, - ['patch' => ['method' => 'PATCH', 'input_formats' => ['json' => ['application/merge-patch+json']]]], - [] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $this->operation = new Get(normalizationContext: ['foo' => 'bar'], denormalizationContext: ['bar' => 'baz'], name: 'get'); + $resourceMetadata = new ResourceMetadataCollection('Foo', [ + new ApiResource(operations: [ + 'get' => $this->operation, + 'post' => $this->operation->withName('post'), + 'put' => $this->operation->withName('put')->withMethod(HttpOperation::METHOD_PUT), + 'get_collection' => $this->operation->withName('get_collection'), + ]), + ]); + + $this->patchOperation = new Patch(inputFormats: ['json' => ['application/merge-patch+json']], name: 'patch'); + $resourceMetadataWithPatch = new ResourceMetadataCollection('Foo', [ + new ApiResource(operations: [ + 'patch' => $this->patchOperation, + ]), + ]); + + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata); $resourceMetadataFactoryProphecy->create('FooWithPatch')->willReturn($resourceMetadataWithPatch); @@ -67,43 +65,43 @@ protected function setUp(): void public function testCreateFromRequest() { $request = Request::create('/foos/1'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['foo' => 'bar', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['foo' => 'bar', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation]; $this->assertEquals($expected, $this->builder->createFromRequest($request, true)); $request = Request::create('/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'pot', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['foo' => 'bar', 'collection_operation_name' => 'pot', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get_collection', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['foo' => 'bar', 'operation_name' => 'get_collection', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('get_collection')]; $this->assertEquals($expected, $this->builder->createFromRequest($request, true)); $request = Request::create('/foos/1'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/foos', 'POST'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'collection_operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['bar' => 'baz', 'operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('post')]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/foos', 'PUT'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'put', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'collection_operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'put', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['bar' => 'baz', 'operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('put')->withMethod(HttpOperation::METHOD_PUT)]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/bars/1/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'subresource_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'operation_type' => 'subresource', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/foowithpatch/1', 'PATCH'); - $request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_item_operation_name' => 'patch', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $expected = ['item_operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'operation_type' => 'item', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_operation_name' => 'patch', '_api_format' => 'json', '_api_mime_type' => 'application/json']); + $expected = ['operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false, 'operation' => $this->patchOperation]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/bars/1/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', '_api_subresource_context' => ['identifiers' => ['id' => ['Foo', 'id']]], 'id' => '1']); - $expected = ['bar' => 'baz', 'subresource_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'operation_type' => 'subresource', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'subresource_identifiers' => ['id' => '1'], 'subresource_resources' => ['Foo' => ['id' => '1']]]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', '_api_subresource_context' => ['identifiers' => ['id' => ['Foo', 'id']]], 'id' => '1']); + $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'operation' => $this->operation, 'skip_null_values' => true]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); } @@ -116,7 +114,7 @@ public function testThrowExceptionOnInvalidRequest() public function testReuseExistingAttributes() { - $expected = ['bar' => 'baz', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest(Request::create('/foos/1'), false, ['resource_class' => 'Foo', 'item_operation_name' => 'get'])); + $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation]; + $this->assertEquals($expected, $this->builder->createFromRequest(Request::create('/foos/1'), false, ['resource_class' => 'Foo', 'operation_name' => 'get'])); } } diff --git a/tests/Serializer/SerializerFilterContextBuilderTest.php b/tests/Serializer/SerializerFilterContextBuilderTest.php index 0780f2279c7..a7e281774ea 100644 --- a/tests/Serializer/SerializerFilterContextBuilderTest.php +++ b/tests/Serializer/SerializerFilterContextBuilderTest.php @@ -14,21 +14,22 @@ namespace ApiPlatform\Tests\Serializer; use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Serializer\Filter\FilterInterface as SerializerFilterInterface; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Serializer\SerializerFilterContextBuilder; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyGroup; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Component\HttpFoundation\Request; /** * @author Baptiste Meyer - * @group legacy */ class SerializerFilterContextBuilderTest extends TestCase { @@ -40,21 +41,15 @@ public function testCreateFromRequestWithCollectionOperation() $attributes = [ 'resource_class' => DummyGroup::class, - 'collection_operation_name' => 'get', + 'operation_name' => 'get', ]; - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['filters' => ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']]] - ); + $resourceMetadata = $this->getMetadataWithFilter(DummyGroup::class, ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $decoratedProphecy->createFromRequest($request, true, $attributes)->willReturn([])->shouldBeCalled(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyGroup::class)->willReturn($resourceMetadata)->shouldBeCalled(); $dummyGroupGroupFilterProphecy = $this->prophesize(SerializerFilterInterface::class); @@ -79,21 +74,14 @@ public function testCreateFromRequestWithItemOperation() $attributes = [ 'resource_class' => DummyGroup::class, - 'item_operation_name' => 'put', + 'operation_name' => 'get', ]; - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - ['put' => ['filters' => ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']]], - null - ); - + $resourceMetadata = $this->getMetadataWithFilter(DummyGroup::class, ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $decoratedProphecy->createFromRequest($request, true, $attributes)->willReturn([])->shouldBeCalled(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyGroup::class)->willReturn($resourceMetadata)->shouldBeCalled(); $dummyGroupGroupFilterProphecy = $this->prophesize(SerializerFilterInterface::class); @@ -118,21 +106,15 @@ public function testCreateFromRequestWithoutFilters() $attributes = [ 'resource_class' => DummyGroup::class, - 'collection_operation_name' => 'get', + 'operation_name' => 'get', ]; - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - null, - ['get' => []] - ); + $resourceMetadata = $this->getMetadataWithFilter(DummyGroup::class, null); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $decoratedProphecy->createFromRequest($request, false, $attributes)->willReturn([])->shouldBeCalled(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyGroup::class)->willReturn($resourceMetadata)->shouldBeCalled(); $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); @@ -145,33 +127,24 @@ public function testCreateFromRequestWithoutAttributes() { $request = new Request([], [], [ '_api_resource_class' => DummyGroup::class, - '_api_collection_operation_name' => 'get', + '_api_operation_name' => 'get', ]); $attributes = [ 'resource_class' => DummyGroup::class, - 'collection_operation_name' => 'get', - 'identifiers' => [ - 'id' => [DummyGroup::class, 'id'], - ], + 'operation_name' => 'get', 'has_composite_identifier' => false, 'receive' => true, 'respond' => true, 'persist' => true, ]; - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['filters' => ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']]] - ); + $resourceMetadata = $this->getMetadataWithFilter(DummyGroup::class, ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $decoratedProphecy->createFromRequest($request, true, $attributes)->willReturn([])->shouldBeCalled(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyGroup::class)->willReturn($resourceMetadata)->shouldBeCalled(); $dummyGroupGroupFilterProphecy = $this->prophesize(SerializerFilterInterface::class); @@ -197,11 +170,20 @@ public function testCreateFromRequestThrowsExceptionWithoutAttributesAndRequestA $request = new Request(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderFilter = new SerializerFilterContextBuilder($resourceMetadataFactoryProphecy->reveal(), $filterLocatorProphecy->reveal(), $decoratedProphecy->reveal()); $serializerContextBuilderFilter->createFromRequest($request, true); } + + private function getMetadataWithFilter(string $class, ?array $filters = null): ResourceMetadataCollection + { + return new ResourceMetadataCollection($class, [ + new ApiResource(operations: [ + 'get' => new Get(name: 'get', filters: $filters), + ]), + ]); + } } diff --git a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php b/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php index 59df7d57e5c..a298918a51c 100644 --- a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php +++ b/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; diff --git a/tests/Symfony/Bundle/ApiPlatformBundleTest.php b/tests/Symfony/Bundle/ApiPlatformBundleTest.php index 8fcd90bcc8c..d6123c7e127 100644 --- a/tests/Symfony/Bundle/ApiPlatformBundleTest.php +++ b/tests/Symfony/Bundle/ApiPlatformBundleTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Symfony\Bundle; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; @@ -26,6 +25,7 @@ use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\PassConfig; diff --git a/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php b/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php index 51722ce4c1d..aab2eb2e472 100644 --- a/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php +++ b/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Symfony\Bundle\ArgumentResolver; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Post; @@ -24,6 +23,7 @@ use ApiPlatform\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ResourceImplementation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ResourceInterface; +use ApiPlatform\Tests\ProphecyTrait; use Prophecy\Argument; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php b/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php index 09a0f859f60..d1259193e87 100644 --- a/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php +++ b/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\Symfony\Bundle\Command; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Resource\Factory\AttributesResourceMetadataCollectionFactory; use ApiPlatform\Symfony\Bundle\Command\DebugResourceCommand; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Console\Application; diff --git a/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php b/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php index d2a26923157..3c9e1680b7c 100644 --- a/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php +++ b/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php @@ -25,12 +25,12 @@ use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Symfony\Bundle\DataCollector\RequestDataCollector; use ApiPlatform\Tests\Fixtures\DummyEntity; +use ApiPlatform\Tests\ProphecyTrait; use PackageVersions\Versions; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index 8fd7b6bd9d6..c2cd7039067 100644 --- a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -21,7 +21,6 @@ use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; @@ -48,6 +47,7 @@ use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\TestBundle; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Doctrine\Common\Annotations\Annotation; use Doctrine\ORM\OptimisticLockException; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php index e41f8f7dff1..8b2fe8fbf9f 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Serializer\Filter\GroupFilter; @@ -25,6 +24,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Filter\DoesNotImplementInterfaceFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\NoConstructorFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\NoPropertiesArgumentFilter; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Annotations\Reader; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php index ffa887ea47a..037f1f449a8 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php index 791bcaebadc..91dee4d93d9 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\BaseNode; use Symfony\Component\DependencyInjection\Alias; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php index 81d7fbcca3b..20f12bb6dc5 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass; +use ApiPlatform\Tests\ProphecyTrait; use Elasticsearch\ClientBuilder; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php index 1cf1644045c..5b6ae6d21d7 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php index 5310dc5615e..90de196c0ea 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php index 4f65c1cdec6..0bc4d0d9b80 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php index 4abb2bdb354..bdd99a8c72c 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php index cb6cee6dbcd..f5eddcd8974 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php index 1f87b5c3128..4990ad14e92 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; use ApiPlatform\Symfony\Bundle\Test\Client; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php b/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php index 080eaa62f64..8ab04043adb 100644 --- a/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php +++ b/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\EventListener; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\EventListener\SwaggerUiListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php b/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php index bf2795f4ae4..596be0e4524 100644 --- a/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php +++ b/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\DocumentationInterface; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Model\Info; @@ -24,6 +23,7 @@ use ApiPlatform\OpenApi\Options; use ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction; use ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiContext; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/AddFormatListenerTest.php b/tests/Symfony/EventListener/AddFormatListenerTest.php index a353e505397..98d325089d1 100644 --- a/tests/Symfony/EventListener/AddFormatListenerTest.php +++ b/tests/Symfony/EventListener/AddFormatListenerTest.php @@ -16,8 +16,8 @@ use ApiPlatform\Core\Api\FormatsProviderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\AddFormatListener; +use ApiPlatform\Tests\ProphecyTrait; use Negotiation\Negotiator; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php index 455ab047a9b..77bc4c24f2c 100644 --- a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\AddLinkHeaderListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/EventListener/DenyAccessListenerTest.php b/tests/Symfony/EventListener/DenyAccessListenerTest.php index 2c4331d67e6..5050a51649c 100644 --- a/tests/Symfony/EventListener/DenyAccessListenerTest.php +++ b/tests/Symfony/EventListener/DenyAccessListenerTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\DenyAccessListener; use ApiPlatform\Symfony\Security\ExpressionLanguage; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; use ApiPlatform\Tests\Fixtures\Serializable; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/DeserializeListenerTest.php b/tests/Symfony/EventListener/DeserializeListenerTest.php index 92598f22a5b..89fff6ef9d3 100644 --- a/tests/Symfony/EventListener/DeserializeListenerTest.php +++ b/tests/Symfony/EventListener/DeserializeListenerTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Core\Api\FormatsProviderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Symfony\EventListener\DeserializeListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/ExceptionListenerTest.php b/tests/Symfony/EventListener/ExceptionListenerTest.php index afc5223240a..0df0d81f307 100644 --- a/tests/Symfony/EventListener/ExceptionListenerTest.php +++ b/tests/Symfony/EventListener/ExceptionListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\ExceptionListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php index 472d75db8be..0843ea0e342 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php index c3498dbe14e..751e6761fbd 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformFilteringParametersListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php index 551be244100..c8d74aea832 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformPaginationParametersListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php index b1b42b05907..5c88b6d16d0 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformSortingParametersListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php b/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php index 27885a58bdb..fe56e285333 100644 --- a/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php +++ b/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Core\Filter\QueryParameterValidator; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Symfony\EventListener\QueryParameterValidateListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/ReadListenerTest.php b/tests/Symfony/EventListener/ReadListenerTest.php index 5cbb87294ee..ba9b23a0739 100644 --- a/tests/Symfony/EventListener/ReadListenerTest.php +++ b/tests/Symfony/EventListener/ReadListenerTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Symfony\EventListener; use ApiPlatform\Api\UriVariablesConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; @@ -26,6 +25,7 @@ use ApiPlatform\State\ProviderInterface; use ApiPlatform\Symfony\EventListener\ReadListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/RespondListenerTest.php b/tests/Symfony/EventListener/RespondListenerTest.php index 5cc70487540..b60cee1fb06 100644 --- a/tests/Symfony/EventListener/RespondListenerTest.php +++ b/tests/Symfony/EventListener/RespondListenerTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\RespondListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; diff --git a/tests/Symfony/EventListener/SerializeListenerTest.php b/tests/Symfony/EventListener/SerializeListenerTest.php index d40463568e5..ece915bed83 100644 --- a/tests/Symfony/EventListener/SerializeListenerTest.php +++ b/tests/Symfony/EventListener/SerializeListenerTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Serializer\ResourceList; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Symfony\EventListener\SerializeListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/WriteListenerTest.php b/tests/Symfony/EventListener/WriteListenerTest.php index 528a66e17fd..e6b6e6bb524 100644 --- a/tests/Symfony/EventListener/WriteListenerTest.php +++ b/tests/Symfony/EventListener/WriteListenerTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -31,6 +30,7 @@ use ApiPlatform\Symfony\EventListener\WriteListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\OperationResource; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/Messenger/ProcessorTest.php b/tests/Symfony/Messenger/ProcessorTest.php index 6a6fe2f72f1..7822ef2eb0b 100644 --- a/tests/Symfony/Messenger/ProcessorTest.php +++ b/tests/Symfony/Messenger/ProcessorTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Symfony\Messenger; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; use ApiPlatform\Symfony\Messenger\ContextStamp; use ApiPlatform\Symfony\Messenger\Processor; use ApiPlatform\Symfony\Messenger\RemoveStamp; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Messenger\Envelope; diff --git a/tests/Symfony/Routing/ApiLoaderTest.php b/tests/Symfony/Routing/ApiLoaderTest.php index 9f004247084..9bbb901173e 100644 --- a/tests/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Symfony/Routing/ApiLoaderTest.php @@ -18,7 +18,6 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; @@ -37,6 +36,7 @@ use ApiPlatform\Tests\Fixtures\DummyEntity; use ApiPlatform\Tests\Fixtures\RelatedDummyEntity; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\ContainerInterface; diff --git a/tests/Symfony/Routing/IriConverterTest.php b/tests/Symfony/Routing/IriConverterTest.php index 1e8674bc19d..79049d83a30 100644 --- a/tests/Symfony/Routing/IriConverterTest.php +++ b/tests/Symfony/Routing/IriConverterTest.php @@ -17,7 +17,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; @@ -30,6 +29,7 @@ use ApiPlatform\State\ProviderInterface; use ApiPlatform\Symfony\Routing\IriConverter; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Routing\RouterInterface; diff --git a/tests/Symfony/Routing/RouterTest.php b/tests/Symfony/Routing/RouterTest.php index 89a859118a1..b5ca68ae3b9 100644 --- a/tests/Symfony/Routing/RouterTest.php +++ b/tests/Symfony/Routing/RouterTest.php @@ -14,8 +14,8 @@ namespace ApiPlatform\Tests\Symfony\Routing; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Routing\Router; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Routing\Exception\ExceptionInterface as RoutingExceptionInterface; diff --git a/tests/Symfony/Security/ResourceAccessCheckerTest.php b/tests/Symfony/Security/ResourceAccessCheckerTest.php index f5d39f8717b..3c84d9af89f 100644 --- a/tests/Symfony/Security/ResourceAccessCheckerTest.php +++ b/tests/Symfony/Security/ResourceAccessCheckerTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Symfony\Security; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Security\ExpressionLanguage; use ApiPlatform\Symfony\Security\ResourceAccessChecker; use ApiPlatform\Tests\Fixtures\Serializable; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php index 11a8694c595..b676c1c1e10 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaChoiceRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php index c5a84217e24..896a0e11bd6 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaCollectionRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaFormat; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLengthRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Collection; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php index 93b910e9a8c..5ca4edb02f5 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaCountRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Count; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php index 9af541d34ee..a9ea787ee13 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaFormat; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Email; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php index d88154c5b7c..7a3ddca2b60 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaGreaterThanOrEqualRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php index f5341ff61b0..9bf4bc22cf0 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaGreaterThanRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php index 7d0bf45a472..acca8dfe383 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLessThanOrEqualRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php index 28ee8be5bed..3607ae329a1 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLessThanRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php index 9428b535f95..3168c1bf9ac 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLengthRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaOneOfRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php index bac30a00caf..70e3bc0c285 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRangeRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php index 5a92104fb64..e7fa1ecfc96 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Positive; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php index b9cc2945198..58f94bea1f3 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaUniqueRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Positive; diff --git a/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php b/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php index 57c2bf2a113..89ca7ae97e7 100644 --- a/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php +++ b/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaChoiceRestriction; @@ -43,6 +42,7 @@ use ApiPlatform\Tests\Fixtures\DummyValidatedEntity; use ApiPlatform\Tests\Fixtures\DummyValidatedHostnameEntity; use ApiPlatform\Tests\Fixtures\DummyValidatedUlidEntity; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php b/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php index 69e43938f4c..a5bab52138b 100644 --- a/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php +++ b/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Symfony\Validator\EventListener; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Symfony\Validator\EventListener\ValidationExceptionListener; use ApiPlatform\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface; use ApiPlatform\Symfony\Validator\Exception\ValidationException; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Validator\Exception\ValidationException as BaseValidationException; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/Validator/Metadata/ValidatorTest.php b/tests/Symfony/Validator/Metadata/ValidatorTest.php index 6fb6ff2ea0c..9e72faf6cc1 100644 --- a/tests/Symfony/Validator/Metadata/ValidatorTest.php +++ b/tests/Symfony/Validator/Metadata/ValidatorTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Symfony\Validator; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\Validator\Exception\ValidationException; use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface; use ApiPlatform\Symfony\Validator\Validator; use ApiPlatform\Tests\Fixtures\DummyEntity; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Component\Validator\ConstraintViolationListInterface;