diff --git a/.gitattributes b/.gitattributes
index 0939daedba5..1bc7f690e59 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -8,7 +8,6 @@
/features export-ignore
/phpstan.neon.dist export-ignore
/phpunit.xml.dist export-ignore
-/phpunit_mongodb.xml export-ignore
/tests export-ignore
/update-js.sh export-ignore
/yarn.lock export-ignore
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d110e5a730c..269b34d8173 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -485,7 +485,7 @@ jobs:
run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction
mongodb:
- name: Behat (PHP ${{ matrix.php }}) (MongoDB)
+ name: PHPUnit + Behat (PHP ${{ matrix.php }}) (MongoDB)
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
@@ -528,8 +528,8 @@ jobs:
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
run: tests/Fixtures/app/console cache:clear --ansi
- - name: Run PHPUnit
- run: vendor/bin/simple-phpunit
+ - name: Run PHPUnit tests
+ run: vendor/bin/simple-phpunit --group mongodb
- name: Run Behat tests
run: vendor/bin/behat -vv --out=std --format=progress --profile=mongodb --no-interaction
@@ -584,8 +584,6 @@ jobs:
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
run: tests/Fixtures/app/console cache:clear --ansi
- - name: Run PHPUnit tests
- run: vendor/bin/simple-phpunit
- name: Run Behat tests
run: vendor/bin/behat --out=std --format=progress --profile=elasticsearch --no-interaction
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0bd71c6aeb..148362352a0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@
* OpenAPI: Fix error when schema is empty (#4051)
* OpenAPI: Do not set scheme to oauth2 when generating securitySchemes (#4073)
* OpenAPI: Fix missing `$ref` when no `type` is used in context (#4076)
+* GraphQL: Fix "Resource class cannot be determined." error when a null iterable field is returned (#4092)
## 2.6.2
diff --git a/features/graphql/query.feature b/features/graphql/query.feature
index 149d39eaef1..fc8441da537 100644
--- a/features/graphql/query.feature
+++ b/features/graphql/query.feature
@@ -59,6 +59,23 @@ Feature: GraphQL query support
And the JSON node "data.dummy.jsonData.bar" should be equal to 5
And the JSON node "data.dummy.arrayData[2]" should be equal to baz
+ Scenario: Retrieve an item with an iterable null field
+ Given there are 2 dummy with null JSON objects
+ When I send the following GraphQL request:
+ """
+ {
+ withJsonDummy(id: "/with_json_dummies/2") {
+ id
+ json
+ }
+ }
+ """
+ Then the response status code should be 200
+ And the response should be in JSON
+ And the header "Content-Type" should be equal to "application/json"
+ And the JSON node "data.withJsonDummy.id" should be equal to "/with_json_dummies/2"
+ And the JSON node "data.withJsonDummy.json" should be null
+
Scenario: Retrieve an item through a GraphQL query with variables
When I have the following GraphQL request:
"""
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 4518373e404..7b52597293e 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -16,7 +16,7 @@
-
+
diff --git a/phpunit_mongodb.xml b/phpunit_mongodb.xml
deleted file mode 100644
index 0ef9e7e4d5b..00000000000
--- a/phpunit_mongodb.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- tests
-
-
-
-
-
- .
-
- features
- tests
- vendor
- src/Bridge/NelmioApiDoc
- src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php
-
-
-
-
-
-
-
-
diff --git a/src/GraphQl/Resolver/Factory/ItemResolverFactory.php b/src/GraphQl/Resolver/Factory/ItemResolverFactory.php
index 1b257b94f69..f96794dd964 100644
--- a/src/GraphQl/Resolver/Factory/ItemResolverFactory.php
+++ b/src/GraphQl/Resolver/Factory/ItemResolverFactory.php
@@ -59,7 +59,7 @@ public function __invoke(?string $resourceClass = null, ?string $rootClass = nul
{
return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) {
// Data already fetched and normalized (field or nested resource)
- if (isset($source[$info->fieldName])) {
+ if ($source && \array_key_exists($info->fieldName, $source)) {
return $source[$info->fieldName];
}
diff --git a/tests/Behat/DoctrineContext.php b/tests/Behat/DoctrineContext.php
index c57510af27d..b2f7ae5066d 100644
--- a/tests/Behat/DoctrineContext.php
+++ b/tests/Behat/DoctrineContext.php
@@ -81,6 +81,7 @@
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\ThirdLevel as ThirdLevelDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\UrlEncodedId as UrlEncodedIdDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\User as UserDocument;
+use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\WithJsonDummy as WithJsonDummyDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\AbsoluteUrlDummy;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\AbsoluteUrlRelationDummy;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Address;
@@ -155,6 +156,7 @@
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UrlEncodedId;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\User;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UuidIdentifierDummy;
+use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\WithJsonDummy;
use Behat\Behat\Context\Context;
use Behat\Gherkin\Node\PyStringNode;
use Doctrine\ODM\MongoDB\DocumentManager;
@@ -574,6 +576,21 @@ public function thereAreDummyObjectsWithJsonData(int $nb)
$this->manager->flush();
}
+ /**
+ * @Given there are :nb dummy with null JSON objects
+ */
+ public function thereAreDummyWithNullJsonObjects(int $nb)
+ {
+ for ($i = 1; $i <= $nb; ++$i) {
+ $dummy = $this->buildWithJsonDummy();
+ $dummy->json = null;
+
+ $this->manager->persist($dummy);
+ }
+
+ $this->manager->flush();
+ }
+
/**
* @Given there are :nb dummy objects with relatedDummy and its thirdLevel
* @Given there is :nb dummy object with relatedDummy and its thirdLevel
@@ -2199,4 +2216,12 @@ private function buildCustomMultipleIdentifierDummy()
{
return $this->isOrm() ? new CustomMultipleIdentifierDummy() : new CustomMultipleIdentifierDummyDocument();
}
+
+ /**
+ * @return WithJsonDummy|WithJsonDummyDocument
+ */
+ private function buildWithJsonDummy()
+ {
+ return $this->isOrm() ? new WithJsonDummy() : new WithJsonDummyDocument();
+ }
}
diff --git a/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php b/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php
index 0f1f163cc6c..b090f818409 100644
--- a/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php
+++ b/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php
@@ -395,6 +395,36 @@ public function provideApplyTestData(): array
],
$filterFactory,
],
+ 'partial (multiple values)' => [
+ [
+ [
+ '$match' => [
+ 'name' => [
+ '$in' => [
+ new Regex('CaSE'),
+ new Regex('SENSitive'),
+ ],
+ ],
+ ],
+ ],
+ ],
+ $filterFactory,
+ ],
+ 'partial (multiple values; case insensitive)' => [
+ [
+ [
+ '$match' => [
+ 'name' => [
+ '$in' => [
+ new Regex('CaSE', 'i'),
+ new Regex('inSENSitive', 'i'),
+ ],
+ ],
+ ],
+ ],
+ ],
+ $filterFactory,
+ ],
'start' => [
[
[
@@ -423,6 +453,36 @@ public function provideApplyTestData(): array
],
$filterFactory,
],
+ 'start (multiple values)' => [
+ [
+ [
+ '$match' => [
+ 'name' => [
+ '$in' => [
+ new Regex('^CaSE'),
+ new Regex('^SENSitive'),
+ ],
+ ],
+ ],
+ ],
+ ],
+ $filterFactory,
+ ],
+ 'start (multiple values; case insensitive)' => [
+ [
+ [
+ '$match' => [
+ 'name' => [
+ '$in' => [
+ new Regex('^CaSE', 'i'),
+ new Regex('^inSENSitive', 'i'),
+ ],
+ ],
+ ],
+ ],
+ ],
+ $filterFactory,
+ ],
'end' => [
[
[
@@ -451,6 +511,36 @@ public function provideApplyTestData(): array
],
$filterFactory,
],
+ 'end (multiple values)' => [
+ [
+ [
+ '$match' => [
+ 'name' => [
+ '$in' => [
+ new Regex('CaSE$'),
+ new Regex('SENSitive$'),
+ ],
+ ],
+ ],
+ ],
+ ],
+ $filterFactory,
+ ],
+ 'end (multiple values; case insensitive)' => [
+ [
+ [
+ '$match' => [
+ 'name' => [
+ '$in' => [
+ new Regex('CaSE$', 'i'),
+ new Regex('inSENSitive$', 'i'),
+ ],
+ ],
+ ],
+ ],
+ ],
+ $filterFactory,
+ ],
'word_start' => [
[
[
@@ -479,6 +569,36 @@ public function provideApplyTestData(): array
],
$filterFactory,
],
+ 'word_start (multiple values)' => [
+ [
+ [
+ '$match' => [
+ 'name' => [
+ '$in' => [
+ new Regex('(^CaSE.*|.*\sCaSE.*)'),
+ new Regex('(^SENSitive.*|.*\sSENSitive.*)'),
+ ],
+ ],
+ ],
+ ],
+ ],
+ $filterFactory,
+ ],
+ 'word_start (multiple values; case insensitive)' => [
+ [
+ [
+ '$match' => [
+ 'name' => [
+ '$in' => [
+ new Regex('(^CaSE.*|.*\sCaSE.*)', 'i'),
+ new Regex('(^inSENSitive.*|.*\sinSENSitive.*)', 'i'),
+ ],
+ ],
+ ],
+ ],
+ ],
+ $filterFactory,
+ ],
'invalid value for relation' => [
[],
$filterFactory,
diff --git a/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php b/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php
index b38d3cd1073..8bce94b8b21 100644
--- a/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php
+++ b/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php
@@ -47,18 +47,6 @@ 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];
@@ -77,17 +65,15 @@ public function testGetItemSingleIdentifier()
$aggregationBuilderProphecy->execute([])->willReturn($iterator->reveal())->shouldBeCalled();
$aggregationBuilder = $aggregationBuilderProphecy->reveal();
- [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [
+ [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $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()]);
+ $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]);
$this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context));
}
@@ -115,7 +101,8 @@ public function testGetItemWithExecuteOptions()
]);
$managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder);
- $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(
+ $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class);
+ $resourceMetadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(
'Dummy',
null,
null,
@@ -125,7 +112,7 @@ public function testGetItemWithExecuteOptions()
$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()]);
+ $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]);
$this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context));
}
@@ -148,19 +135,17 @@ public function testGetItemDoubleIdentifier()
$aggregationBuilderProphecy->execute([])->willReturn($iterator->reveal())->shouldBeCalled();
$aggregationBuilder = $aggregationBuilderProphecy->reveal();
- [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [
+ [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $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()]);
+ $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]);
$this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context));
}
@@ -172,7 +157,7 @@ public function testGetItemWrongCompositeIdentifier()
{
$this->expectException(PropertyNotFoundException::class);
- [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [
+ [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [
'ida',
'idb',
]);
@@ -185,7 +170,7 @@ public function testGetItemWrongCompositeIdentifier()
],
]);
- $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory);
+ $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory);
$dataProvider->getItem(Dummy::class, 'ida=1;', 'foo');
}
@@ -199,7 +184,7 @@ public function testAggregationResultExtension()
$aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled();
$aggregationBuilder = $aggregationBuilderProphecy->reveal();
- [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [
+ [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [
'id',
]);
$managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder);
@@ -210,7 +195,7 @@ public function testAggregationResultExtension()
$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()]);
+ $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]);
$this->assertEquals([], $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context));
}
@@ -222,11 +207,11 @@ public function testUnsupportedClass()
$extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class);
- [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [
+ [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [
'id',
]);
- $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]);
+ $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]);
$this->assertFalse($dataProvider->supports(Dummy::class, 'foo'));
}
@@ -245,11 +230,11 @@ public function testCannotCreateAggregationBuilder()
$extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class);
- [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [
+ [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $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]);
+ (new ItemDataProvider($managerRegistryProphecy->reveal(), $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]))->getItem(Dummy::class, 'foo', null, [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]);
}
/**
@@ -259,6 +244,7 @@ private function getMetadataFactories(string $resourceClass, array $identifiers)
{
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
+ $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
$nameCollection = ['foobar'];
@@ -274,8 +260,9 @@ private function getMetadataFactories(string $resourceClass, array $identifiers)
$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()];
+ return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()];
}
/**
diff --git a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractorTest.php b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractorTest.php
index 1638b933ea9..8edae6b8a26 100644
--- a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractorTest.php
+++ b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractorTest.php
@@ -55,10 +55,8 @@ public function testGetProperties(): void
'dateImmutable',
'float',
'bool',
- 'boolean',
'customFoo',
'int',
- 'integer',
'string',
'key',
'hash',
@@ -145,9 +143,7 @@ public function typesProvider(): array
['dateImmutable', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')]],
['float', [new Type(Type::BUILTIN_TYPE_FLOAT)]],
['bool', [new Type(Type::BUILTIN_TYPE_BOOL)]],
- ['boolean', [new Type(Type::BUILTIN_TYPE_BOOL)]],
['int', [new Type(Type::BUILTIN_TYPE_INT)]],
- ['integer', [new Type(Type::BUILTIN_TYPE_INT)]],
['string', [new Type(Type::BUILTIN_TYPE_STRING)]],
['key', [new Type(Type::BUILTIN_TYPE_INT)]],
['hash', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]],
diff --git a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineDummy.php b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineDummy.php
index e54438a4190..58896f2eb64 100644
--- a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineDummy.php
+++ b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineDummy.php
@@ -106,11 +106,6 @@ class DoctrineDummy
*/
private $bool;
- /**
- * @Field(type="boolean")
- */
- private $boolean;
-
/**
* @Field(type="custom_foo")
*/
@@ -121,11 +116,6 @@ class DoctrineDummy
*/
private $int;
- /**
- * @Field(type="integer")
- */
- private $integer;
-
/**
* @Field(type="string")
*/
diff --git a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineGeneratedValue.php b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineGeneratedValue.php
index 46ece808957..e286195a2b3 100644
--- a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineGeneratedValue.php
+++ b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineGeneratedValue.php
@@ -26,7 +26,7 @@
class DoctrineGeneratedValue
{
/**
- * @Id(strategy="INCREMENT", type="integer")
+ * @Id(strategy="INCREMENT", type="int")
*/
public $id;
diff --git a/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php b/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php
index 0130565ffcc..879a630431c 100644
--- a/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php
+++ b/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php
@@ -167,7 +167,7 @@ public function testGetSubresource()
$dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory);
- $context = ['property' => 'relatedDummies', 'identifiers' => [['id', Dummy::class]], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true];
+ $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));
}
@@ -256,7 +256,7 @@ public function testGetSubSubresourceItem()
$dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory);
- $context = ['property' => 'thirdLevel', 'identifiers' => [['id', Dummy::class], ['relatedDummies', RelatedDummy::class]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true];
+ $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));
}
@@ -353,7 +353,7 @@ public function testGetSubSubresourceItemWithExecuteOptions()
$dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory);
- $context = ['property' => 'thirdLevel', 'identifiers' => [['id', Dummy::class], ['relatedDummies', RelatedDummy::class]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true];
+ $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'));
}
@@ -405,7 +405,7 @@ public function testGetSubresourceOneToOneOwningRelation()
$dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory);
- $context = ['property' => 'ownedDummy', 'identifiers' => [['id', Dummy::class]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true];
+ $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));
}
@@ -458,7 +458,7 @@ public function testAggregationResultExtension()
$dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]);
- $context = ['property' => 'relatedDummies', 'identifiers' => [['id', Dummy::class]], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true];
+ $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));
}
@@ -504,11 +504,6 @@ public function testGetSubresourceCollectionItem()
$rAggregationBuilder = $this->prophesize(Builder::class);
- $rMatch = $this->prophesize(AggregationMatch::class);
- $rMatch->equals(2)->shouldBeCalled();
- $rMatch->field('id')->shouldBeCalled()->willReturn($rMatch);
- $rAggregationBuilder->match()->shouldBeCalled()->willReturn($rMatch->reveal());
-
$rClassMetadataProphecy = $this->prophesize(ClassMetadata::class);
$rClassMetadataProphecy->hasAssociation('id')->shouldBeCalled()->willReturn(false);
$rClassMetadataProphecy->isIdentifier('id')->shouldBeCalled()->willReturn(true);
@@ -539,7 +534,7 @@ public function testGetSubresourceCollectionItem()
$dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory);
- $context = ['property' => 'id', 'identifiers' => [['id', Dummy::class, true], ['relatedDummies', RelatedDummy::class, true]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true];
+ $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/Fixtures/TestBundle/Document/WithJsonDummy.php b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php
new file mode 100644
index 00000000000..a0a82da40b8
--- /dev/null
+++ b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the 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\TestBundle\Document;
+
+use ApiPlatform\Core\Annotation\ApiResource;
+use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
+
+/**
+ * @ApiResource
+ * @ODM\Document
+ */
+class WithJsonDummy
+{
+ /**
+ * @var int
+ *
+ * @ODM\Id(strategy="INCREMENT", type="int", nullable=true)
+ */
+ private $id;
+
+ /**
+ * @var array|null
+ *
+ * @ODM\Field(type="hash", nullable=true)
+ */
+ public $json;
+
+ public function getId(): int
+ {
+ return $this->id;
+ }
+}
diff --git a/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php
new file mode 100644
index 00000000000..a2769c87c1f
--- /dev/null
+++ b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php
@@ -0,0 +1,45 @@
+
+ *
+ * For the 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\TestBundle\Entity;
+
+use ApiPlatform\Core\Annotation\ApiResource;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ApiResource
+ * @ORM\Entity
+ */
+class WithJsonDummy
+{
+ /**
+ * @var int
+ *
+ * @ORM\Column(type="integer", nullable=true)
+ * @ORM\Id
+ * @ORM\GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+
+ /**
+ * @var array|null
+ *
+ * @ORM\Column(type="json", nullable=true)
+ */
+ public $json;
+
+ public function getId(): int
+ {
+ return $this->id;
+ }
+}
diff --git a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php
index 69cc1b31576..06d2c66f627 100644
--- a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php
+++ b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php
@@ -118,6 +118,15 @@ public function testResolveNested(): void
$this->assertSame(['already_serialized'], ($this->itemResolverFactory)('resourceClass')($source, [], null, $info));
}
+ public function testResolveNestedNullValue(): void
+ {
+ $source = ['nestedNullValue' => null];
+ $info = $this->prophesize(ResolveInfo::class)->reveal();
+ $info->fieldName = 'nestedNullValue';
+
+ $this->assertNull(($this->itemResolverFactory)('resourceClass')($source, [], null, $info));
+ }
+
public function testResolveBadReadStageItem(): void
{
$resourceClass = 'stdClass';