diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb0de9ebd18..d9477a45d26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -156,6 +156,7 @@ jobs: - '7.2' - '7.3' - '7.4' + - 'rc' include: - php: '7.4' coverage: true @@ -170,7 +171,7 @@ jobs: bash \ unzip \ - name: Cache mongodb PHP extension build - if: (!startsWith(matrix.php, '7.1')) + if: (!startsWith(matrix.php, '7.1') && !startsWith(matrix.php, 'rc')) uses: actions/cache@v2 with: path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} @@ -179,7 +180,7 @@ jobs: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- continue-on-error: true - name: Install mongodb PHP extension - if: (!startsWith(matrix.php, '7.1')) + if: (!startsWith(matrix.php, '7.1') && !startsWith(matrix.php, 'rc')) env: BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} SRC_DIR: /usr/src/php/ext/mongodb @@ -230,11 +231,14 @@ jobs: composer global require --prefer-dist --no-progress --no-suggest --ansi \ symfony/flex - name: Remove Doctrine MongoDB ODM - if: startsWith(matrix.php, '7.1') + if: (startsWith(matrix.php, '7.1') || startsWith(matrix.php, 'rc')) run: | composer remove --dev --no-progress --no-update --ansi \ doctrine/mongodb-odm \ doctrine/mongodb-odm-bundle \ + - name: Set Composer platform config + if: (startsWith(matrix.php, 'rc')) + run: composer config platform.php 7.4.99 - name: Update project dependencies run: | mkdir -p /tmp/api-platform/core/vendor @@ -2348,7 +2352,7 @@ jobs: with: php-version: '7.4' tools: pecl, composer, flex - extensions: intl, openssl, mbstring, pdo_sqlite + extensions: intl, openssl, mbstring, pdo_sqlite coverage: none ini-values: memory_limit=-1 - name: Cache Composer packages @@ -2385,7 +2389,7 @@ jobs: with: php-version: '7.4' tools: pecl, composer, flex - extensions: intl, openssl, mbstring, pdo_sqlite + extensions: intl, openssl, mbstring, pdo_sqlite coverage: none ini-values: memory_limit=-1 - name: Cache Composer packages diff --git a/composer.json b/composer.json index 3a0bba7ee23..8583952eec8 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "symfony/property-info": "^3.4 || ^4.0 || ^5.0", "symfony/serializer": "^4.3 || ^5.0", "symfony/web-link": "^4.1 || ^5.0", - "willdurand/negotiation": "^2.0.3" + "willdurand/negotiation": "^2.0.3 || 3.0.x-dev" }, "require-dev": { "behat/behat": "^3.1", @@ -47,8 +47,8 @@ "jangregor/phpstan-prophecy": "^0.6", "justinrainbow/json-schema": "^5.2.1", "nelmio/api-doc-bundle": "^2.13.4", - "phpdocumentor/reflection-docblock": "^3.0 || ^4.0", - "phpdocumentor/type-resolver": "^0.3 || ^0.4", + "phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.0", + "phpdocumentor/type-resolver": "^0.3 || ^0.4 || ^1.0", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^0.12.4", "phpstan/phpstan-doctrine": "^0.12.7", diff --git a/src/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php b/src/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php index f18c5f4b057..e2b67f60d0d 100644 --- a/src/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php +++ b/src/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php @@ -152,7 +152,7 @@ private function getQueryBuilderWithNewAliases(QueryBuilder $queryBuilder, Query $newAlias = $queryNameGenerator->generateJoinAlias($association); $aliases[] = "{$joinPart->getAlias()}."; $replacements[] = "$newAlias."; - $condition = str_replace($aliases, $replacements, $joinPart->getCondition()); + $condition = str_replace($aliases, $replacements, $joinPart->getCondition() ?? ''); QueryBuilderHelper::addJoinOnce($queryBuilderClone, $queryNameGenerator, $alias, $association, $joinPart->getJoinType(), $joinPart->getConditionType(), $condition, $originAlias, $newAlias); } diff --git a/src/Hal/Serializer/ItemNormalizer.php b/src/Hal/Serializer/ItemNormalizer.php index bb1ad6909f5..e61c44d24bc 100644 --- a/src/Hal/Serializer/ItemNormalizer.php +++ b/src/Hal/Serializer/ItemNormalizer.php @@ -105,7 +105,7 @@ public function denormalize($data, $class, $format = null, array $context = []) /** * {@inheritdoc} */ - protected function getAttributes($object, $format = null, array $context): array + protected function getAttributes($object, $format = null, array $context = []): array { return $this->getComponents($object, $format, $context)['states']; } diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index ca869d67f0b..afb27e57edd 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -160,7 +160,7 @@ public function denormalize($data, $class, $format = null, array $context = []) /** * {@inheritdoc} */ - protected function getAttributes($object, $format = null, array $context): array + protected function getAttributes($object, $format = null, array $context = []): array { return $this->getComponents($object, $format, $context)['attributes']; } diff --git a/src/JsonSchema/SchemaFactory.php b/src/JsonSchema/SchemaFactory.php index b27aad82c24..9594361fc7a 100644 --- a/src/JsonSchema/SchemaFactory.php +++ b/src/JsonSchema/SchemaFactory.php @@ -233,7 +233,7 @@ private function buildDefinitionName(string $className, string $format = 'json', return $name; } - private function getMetadata(string $className, string $type = Schema::TYPE_OUTPUT, ?string $operationType, ?string $operationName, ?array $serializerContext): ?array + private function getMetadata(string $className, string $type = Schema::TYPE_OUTPUT, ?string $operationType = null, ?string $operationName = null, ?array $serializerContext = null): ?array { if (!$this->isResourceClass($className)) { return [ @@ -263,7 +263,7 @@ private function getMetadata(string $className, string $type = Schema::TYPE_OUTP ]; } - private function getSerializerContext(ResourceMetadata $resourceMetadata, string $type = Schema::TYPE_OUTPUT, ?string $operationType, ?string $operationName): array + private function getSerializerContext(ResourceMetadata $resourceMetadata, string $type = Schema::TYPE_OUTPUT, ?string $operationType = null, ?string $operationName = null): array { $attribute = Schema::TYPE_OUTPUT === $type ? 'normalization_context' : 'denormalization_context'; diff --git a/src/Swagger/Serializer/DocumentationNormalizer.php b/src/Swagger/Serializer/DocumentationNormalizer.php index 37961d2b7e2..8b1c1a1b5b7 100644 --- a/src/Swagger/Serializer/DocumentationNormalizer.php +++ b/src/Swagger/Serializer/DocumentationNormalizer.php @@ -105,7 +105,7 @@ final class DocumentationNormalizer implements NormalizerInterface, CacheableSup * @param mixed|null $jsonSchemaTypeFactory * @param int[] $swaggerVersions */ - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, $jsonSchemaFactory = null, $jsonSchemaTypeFactory = null, OperationPathResolverInterface $operationPathResolver, 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]) + public function __construct(ResourceMetadataFactoryInterface $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]) { 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); diff --git a/tests/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtensionTest.php b/tests/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtensionTest.php index b1fae50c806..0ba8a4adb0a 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtensionTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtensionTest.php @@ -27,7 +27,7 @@ use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Aggregation\Stage\Count; use Doctrine\ODM\MongoDB\Aggregation\Stage\Facet; -use Doctrine\ODM\MongoDB\Aggregation\Stage\Match; +use Doctrine\ODM\MongoDB\Aggregation\Stage\Match as AggregationMatch; use Doctrine\ODM\MongoDB\Aggregation\Stage\Skip; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Iterator\Iterator; @@ -467,7 +467,7 @@ private function mockAggregationBuilder($expectedOffset, $expectedLimit) if ($expectedLimit > 0) { $skipProphecy->limit($expectedLimit)->shouldBeCalled(); } else { - $matchProphecy = $this->prophesize(Match::class); + $matchProphecy = $this->prophesize(AggregationMatch::class); $matchProphecy->field(Paginator::LIMIT_ZERO_MARKER_FIELD)->shouldBeCalled()->willReturn($matchProphecy); $matchProphecy->equals(Paginator::LIMIT_ZERO_MARKER)->shouldBeCalled(); $skipProphecy->match()->shouldBeCalled()->willReturn($matchProphecy->reveal()); diff --git a/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php b/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php index 47f0a23d265..f9214edf883 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php @@ -26,7 +26,7 @@ use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\Aggregation\Stage\Match; +use Doctrine\ODM\MongoDB\Aggregation\Stage\Match as AggregationMatch; use Doctrine\ODM\MongoDB\Iterator\Iterator; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Repository\DocumentRepository; @@ -49,7 +49,7 @@ public function testGetItemSingleIdentifier() { $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $matchProphecy = $this->prophesize(Match::class); + $matchProphecy = $this->prophesize(AggregationMatch::class); $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); $matchProphecy->equals(1)->shouldBeCalled(); @@ -78,7 +78,7 @@ public function testGetItemSingleIdentifier() public function testGetItemDoubleIdentifier() { - $matchProphecy = $this->prophesize(Match::class); + $matchProphecy = $this->prophesize(AggregationMatch::class); $matchProphecy->field('ida')->willReturn($matchProphecy)->shouldBeCalled(); $matchProphecy->field('idb')->willReturn($matchProphecy)->shouldBeCalled(); $matchProphecy->equals(1)->shouldBeCalled(); @@ -135,7 +135,7 @@ public function testGetItemWrongCompositeIdentifier() public function testAggregationResultExtension() { - $matchProphecy = $this->prophesize(Match::class); + $matchProphecy = $this->prophesize(AggregationMatch::class); $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); $matchProphecy->equals(1)->shouldBeCalled(); diff --git a/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php b/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php index 4d42742c396..3bf7b1fa367 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php @@ -29,7 +29,7 @@ use ApiPlatform\Core\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Aggregation\Stage\Lookup; -use Doctrine\ODM\MongoDB\Aggregation\Stage\Match; +use Doctrine\ODM\MongoDB\Aggregation\Stage\Match as AggregationMatch; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Iterator\Iterator; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; @@ -122,7 +122,7 @@ public function testGetSubresource() $dummyLookup->alias('relatedDummies')->shouldBeCalled(); $dummyAggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($dummyLookup->reveal()); - $dummyMatch = $this->prophesize(Match::class); + $dummyMatch = $this->prophesize(AggregationMatch::class); $dummyMatch->equals(1)->shouldBeCalled(); $dummyMatch->field('id')->shouldBeCalled()->willReturn($dummyMatch); $dummyAggregationBuilder->match()->shouldBeCalled()->willReturn($dummyMatch->reveal()); @@ -133,7 +133,7 @@ public function testGetSubresource() $managerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($dummyAggregationBuilder->reveal()); - $match = $this->prophesize(Match::class); + $match = $this->prophesize(AggregationMatch::class); $match->in([2])->shouldBeCalled(); $match->field('_id')->shouldBeCalled()->willReturn($match); $aggregationBuilder->match()->shouldBeCalled()->willReturn($match); @@ -167,7 +167,7 @@ public function testGetSubSubresourceItem() $dummyLookup->alias('relatedDummies')->shouldBeCalled(); $dummyAggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($dummyLookup->reveal()); - $dummyMatch = $this->prophesize(Match::class); + $dummyMatch = $this->prophesize(AggregationMatch::class); $dummyMatch->equals(1)->shouldBeCalled(); $dummyMatch->field('id')->shouldBeCalled()->willReturn($dummyMatch); $dummyAggregationBuilder->match()->shouldBeCalled()->willReturn($dummyMatch->reveal()); @@ -191,10 +191,10 @@ public function testGetSubSubresourceItem() $rLookup->alias('thirdLevel')->shouldBeCalled(); $rAggregationBuilder->lookup('thirdLevel')->shouldBeCalled()->willReturn($rLookup->reveal()); - $rMatch = $this->prophesize(Match::class); + $rMatch = $this->prophesize(AggregationMatch::class); $rMatch->equals(1)->shouldBeCalled(); $rMatch->field('id')->shouldBeCalled()->willReturn($rMatch); - $previousRMatch = $this->prophesize(Match::class); + $previousRMatch = $this->prophesize(AggregationMatch::class); $previousRMatch->in([2])->shouldBeCalled(); $previousRMatch->field('_id')->shouldBeCalled()->willReturn($previousRMatch); $rAggregationBuilder->match()->shouldBeCalled()->willReturn($rMatch->reveal(), $previousRMatch->reveal()); @@ -216,7 +216,7 @@ public function testGetSubSubresourceItem() // Origin manager (ThirdLevel) $aggregationBuilder = $this->prophesize(Builder::class); - $match = $this->prophesize(Match::class); + $match = $this->prophesize(AggregationMatch::class); $match->in([3])->shouldBeCalled(); $match->field('_id')->shouldBeCalled()->willReturn($match); $aggregationBuilder->match()->shouldBeCalled()->willReturn($match); @@ -265,10 +265,10 @@ public function testGetSubresourceOneToOneOwningRelation() $aggregationBuilder->lookup('ownedDummy')->shouldBeCalled()->willReturn($lookup->reveal()); $managerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - $match = $this->prophesize(Match::class); + $match = $this->prophesize(AggregationMatch::class); $match->equals(1)->shouldBeCalled(); $match->field('id')->shouldBeCalled()->willReturn($match); - $previousMatch = $this->prophesize(Match::class); + $previousMatch = $this->prophesize(AggregationMatch::class); $previousMatch->in([3])->shouldBeCalled(); $previousMatch->field('_id')->shouldBeCalled()->willReturn($previousMatch); $aggregationBuilder->match()->shouldBeCalled()->willReturn($match->reveal(), $previousMatch->reveal()); @@ -314,10 +314,10 @@ public function testAggregationResultExtension() $aggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($lookup->reveal()); $managerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - $match = $this->prophesize(Match::class); + $match = $this->prophesize(AggregationMatch::class); $match->equals(1)->shouldBeCalled(); $match->field('id')->shouldBeCalled()->willReturn($match); - $previousMatch = $this->prophesize(Match::class); + $previousMatch = $this->prophesize(AggregationMatch::class); $previousMatch->in([3])->shouldBeCalled(); $previousMatch->field('_id')->shouldBeCalled()->willReturn($previousMatch); $aggregationBuilder->match()->shouldBeCalled()->willReturn($match->reveal(), $previousMatch->reveal()); @@ -385,7 +385,7 @@ public function testGetSubresourceCollectionItem() $rAggregationBuilder = $this->prophesize(Builder::class); - $rMatch = $this->prophesize(Match::class); + $rMatch = $this->prophesize(AggregationMatch::class); $rMatch->equals(2)->shouldBeCalled(); $rMatch->field('id')->shouldBeCalled()->willReturn($rMatch); $rAggregationBuilder->match()->shouldBeCalled()->willReturn($rMatch->reveal()); diff --git a/tests/Bridge/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php b/tests/Bridge/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php index 7621d124ef2..20ea4ff61c2 100644 --- a/tests/Bridge/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php +++ b/tests/Bridge/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php @@ -180,7 +180,8 @@ public function testWithResourceWithTraceables() $dataProvider = $dataCollector->getCollectionDataProviders(); foreach ($dataProvider['responses'] as $class => $response) { - $this->assertStringStartsWith('class@anonymous', $class); + $this->assertStringContainsString('@anonymous', $class); + $this->assertTrue($response); } $context = $dataProvider['context']; @@ -189,7 +190,7 @@ public function testWithResourceWithTraceables() $dataProvider = $dataCollector->getItemDataProviders(); foreach ($dataProvider['responses'] as $class => $response) { - $this->assertStringStartsWith('class@anonymous', $class); + $this->assertStringContainsString('@anonymous', $class); $this->assertTrue($response); } $context = $dataProvider['context']; @@ -198,7 +199,7 @@ public function testWithResourceWithTraceables() $dataProvider = $dataCollector->getSubresourceDataProviders(); foreach ($dataProvider['responses'] as $class => $response) { - $this->assertStringStartsWith('class@anonymous', $class); + $this->assertStringContainsString('@anonymous', $class); $this->assertTrue($response); } $context = $dataProvider['context']; @@ -207,7 +208,7 @@ public function testWithResourceWithTraceables() $dataPersister = $dataCollector->getDataPersisters(); foreach ($dataPersister['responses'] as $class => $response) { - $this->assertStringStartsWith('class@anonymous', $class); + $this->assertStringContainsString('@anonymous', $class); $this->assertTrue($response); } } diff --git a/tests/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php b/tests/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php index 168f1a3c98c..ab7b0d2b819 100644 --- a/tests/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php +++ b/tests/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php @@ -32,6 +32,10 @@ public function testPersist($persister, $expected) $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)); @@ -46,6 +50,10 @@ public function testRemove($persister, $expected) $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)); diff --git a/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php b/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php index c09de7cac69..d7b7da4a722 100644 --- a/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php +++ b/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php @@ -34,6 +34,10 @@ public function testGetCollection($provider, $context, $expected) $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)); @@ -52,6 +56,10 @@ public function testDeprecatedGetCollection($provider, $context, $expected) $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)); diff --git a/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php b/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php index 8c610c497fd..de55ab2bb5b 100644 --- a/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php +++ b/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php @@ -35,6 +35,10 @@ public function testGetItem($provider, $context, $expected) $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)); @@ -53,6 +57,10 @@ public function testDeprecatedGetItem($provider, $context, $expected) $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)); @@ -91,7 +99,7 @@ public function getItem(string $resourceClass, $id, string $operationName = null return null; } }, - new class() implements RestrictedDataProviderInterface, DenormalizedIdentifiersAwareItemDataProviderInterface { + new class() implements ItemDataProviderInterface, RestrictedDataProviderInterface, DenormalizedIdentifiersAwareItemDataProviderInterface { public function getItem(string $resourceClass, /* array */ $id, string $operationName = null, array $context = []) { return null; diff --git a/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php b/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php index 6b3e9259fc1..87ef63c8e45 100644 --- a/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php +++ b/tests/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php @@ -34,6 +34,10 @@ public function testGetSubresource($provider, $context, $expected) $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)); @@ -52,6 +56,10 @@ public function testDeprecatedGetSubResource($provider, $context, $expected) $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)); diff --git a/tests/Fixtures/Serializable.php b/tests/Fixtures/Serializable.php new file mode 100644 index 00000000000..6fab71907ea --- /dev/null +++ b/tests/Fixtures/Serializable.php @@ -0,0 +1,21 @@ + + * + * For the 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\Fixtures; + +interface Serializable +{ + public function __serialize(): array; + + public function __unserialize(array $data); +} diff --git a/tests/Security/EventListener/DenyAccessListenerTest.php b/tests/Security/EventListener/DenyAccessListenerTest.php index bdc4b4d9265..7385205ffdf 100644 --- a/tests/Security/EventListener/DenyAccessListenerTest.php +++ b/tests/Security/EventListener/DenyAccessListenerTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Core\Security\EventListener\DenyAccessListener; use ApiPlatform\Core\Security\ExpressionLanguage; use ApiPlatform\Core\Security\ResourceAccessCheckerInterface; +use ApiPlatform\Core\Tests\Fixtures\Serializable; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; @@ -253,7 +254,7 @@ public function testExpressionLanguageNotInstalled() $authenticationTrustResolverProphecy = $this->prophesize(AuthenticationTrustResolverInterface::class); $tokenStorageProphecy = $this->prophesize(TokenStorageInterface::class); - $tokenStorageProphecy->getToken()->willReturn($this->prophesize(TokenInterface::class)->reveal()); + $tokenStorageProphecy->getToken()->willReturn($this->prophesize(TokenInterface::class)->willImplement(Serializable::class)->reveal()); $listener = new DenyAccessListener($resourceMetadataFactoryProphecy->reveal(), null, $authenticationTrustResolverProphecy->reveal(), null, $tokenStorageProphecy->reveal()); $listener->onSecurity($event); diff --git a/tests/Security/ResourceAccessCheckerTest.php b/tests/Security/ResourceAccessCheckerTest.php index d12ec10cab6..d219603fde9 100644 --- a/tests/Security/ResourceAccessCheckerTest.php +++ b/tests/Security/ResourceAccessCheckerTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Security\ExpressionLanguage; use ApiPlatform\Core\Security\ResourceAccessChecker; +use ApiPlatform\Core\Tests\Fixtures\Serializable; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -42,8 +43,10 @@ public function testIsGranted(bool $granted) $tokenStorageProphecy = $this->prophesize(TokenStorageInterface::class); $tokenProphecy = $this->prophesize(TokenInterface::class); + $tokenProphecy->willImplement(Serializable::class); $token = $tokenProphecy->reveal(); $tokenProphecy->getUser()->shouldBeCalled(); + if (method_exists($token, 'getRoleNames')) { $tokenProphecy->getRoleNames()->willReturn([])->shouldBeCalled(); } else { @@ -77,7 +80,7 @@ public function testExpressionLanguageNotInstalled() $authenticationTrustResolverProphecy = $this->prophesize(AuthenticationTrustResolverInterface::class); $tokenStorageProphecy = $this->prophesize(TokenStorageInterface::class); - $tokenStorageProphecy->getToken()->willReturn($this->prophesize(TokenInterface::class)->reveal()); + $tokenStorageProphecy->getToken()->willReturn($this->prophesize(TokenInterface::class)->willImplement(Serializable::class)->reveal()); $checker = new ResourceAccessChecker(null, $authenticationTrustResolverProphecy->reveal(), null, $tokenStorageProphecy->reveal()); $checker->isGranted(Dummy::class, 'is_granted("ROLE_ADMIN")');