Skip to content

Commit 0357a41

Browse files
authored
Merge pull request #855 from soyuka/hotfix-api-platform-179
Do not eager join properties or associations that are not linked to a resource
2 parents 62f26d1 + e37424a commit 0357a41

File tree

2 files changed

+67
-3
lines changed

2 files changed

+67
-3
lines changed

src/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Extension;
1313

1414
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
15+
use ApiPlatform\Core\Exception\PropertyNotFoundException;
16+
use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
1517
use ApiPlatform\Core\Exception\RuntimeException;
1618
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
1719
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
@@ -53,9 +55,14 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator
5355
}
5456

5557
$forceEager = $this->isForceEager($resourceClass, $options);
56-
$groups = $this->getSerializerGroups($resourceClass, $options, 'normalization_context');
5758

58-
$this->joinRelations($queryBuilder, $queryNameGenerator, $resourceClass, $forceEager, $queryBuilder->getRootAliases()[0], $groups);
59+
try {
60+
$groups = $this->getSerializerGroups($resourceClass, $options, 'normalization_context');
61+
62+
$this->joinRelations($queryBuilder, $queryNameGenerator, $resourceClass, $forceEager, $queryBuilder->getRootAliases()[0], $groups);
63+
} catch (ResourceClassNotFoundException $resourceClassNotFoundException) {
64+
//ignore the not found exception
65+
}
5966
}
6067

6168
/**
@@ -107,7 +114,15 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt
107114
$classMetadata = $entityManager->getClassMetadata($resourceClass);
108115

109116
foreach ($classMetadata->associationMappings as $association => $mapping) {
110-
$propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $association, $propertyMetadataOptions);
117+
try {
118+
$propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $association, $propertyMetadataOptions);
119+
} catch (PropertyNotFoundException $propertyNotFoundException) {
120+
//skip properties not found
121+
continue;
122+
} catch (ResourceClassNotFoundException $resourceClassNotFoundException) {
123+
//skip associations that are not resource classes
124+
continue;
125+
}
111126

112127
if (false === $forceEager && ClassMetadataInfo::FETCH_EAGER !== $mapping['fetch']) {
113128
continue;

tests/Bridge/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\EagerLoadingExtension;
1515
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator;
16+
use ApiPlatform\Core\Exception\PropertyNotFoundException;
17+
use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
1618
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
1719
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
1820
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
@@ -284,4 +286,51 @@ public function testForceEager()
284286
$orderExtensionTest = new EagerLoadingExtension($propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true);
285287
$orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []);
286288
}
289+
290+
public function testResourceClassNotFoundException()
291+
{
292+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
293+
$resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata());
294+
295+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
296+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', [])->willThrow(new ResourceClassNotFoundException());
297+
298+
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
299+
$classMetadataProphecy->associationMappings = [
300+
'relation' => ['fetch' => 2, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
301+
];
302+
$emProphecy = $this->prophesize(EntityManager::class);
303+
$emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal());
304+
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
305+
$queryBuilderProphecy->getRootAliases()->willReturn(['o']);
306+
$queryBuilderProphecy->getEntityManager()->willReturn($emProphecy);
307+
308+
$orderExtensionTest = new EagerLoadingExtension($propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true);
309+
$orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []);
310+
}
311+
312+
public function testPropertyNotFoundException()
313+
{
314+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
315+
$resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata());
316+
317+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
318+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', [])->willThrow(new PropertyNotFoundException());
319+
320+
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
321+
$classMetadataProphecy->associationMappings = [
322+
'relation' => ['fetch' => 2, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
323+
];
324+
$emProphecy = $this->prophesize(EntityManager::class);
325+
$emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal());
326+
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
327+
$queryBuilderProphecy->getRootAliases()->willReturn(['o']);
328+
$queryBuilderProphecy->getEntityManager()->willReturn($emProphecy);
329+
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
330+
$queryBuilderProphecy->getRootAliases()->willReturn(['o']);
331+
$queryBuilderProphecy->getEntityManager()->willReturn($emProphecy);
332+
333+
$orderExtensionTest = new EagerLoadingExtension($propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true);
334+
$orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []);
335+
}
287336
}

0 commit comments

Comments
 (0)