Skip to content

Commit ac65ba1

Browse files
committed
fix OneToOne bidirectional + unitTest WIP
1 parent a18f7cf commit ac65ba1

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

src/Bridge/Doctrine/Orm/SubresourceDataProvider.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,22 @@ private function buildQuery(array $identifiers, array $context, QueryNameGenerat
175175
$mappedBy = $classMetadata->getAssociationMapping($previousAssociationProperty)['mappedBy'];
176176
$previousAlias = "$previousAlias.$mappedBy";
177177

178+
$qb->select($alias)
179+
->from($identifierResourceClass, $alias);
180+
break;
181+
case ClassMetadataInfo::ONE_TO_ONE:
182+
$association = $classMetadata->getAssociationMapping($previousAssociationProperty);
183+
if (!isset($association['mappedBy'])) {
184+
goto def;
185+
}
186+
$mappedBy = $association['mappedBy'];
187+
$previousAlias = "$previousAlias.$mappedBy";
188+
178189
$qb->select($alias)
179190
->from($identifierResourceClass, $alias);
180191
break;
181192
default:
193+
def:
182194
$qb->select("IDENTITY($alias.$previousAssociationProperty)")
183195
->from($identifierResourceClass, $alias);
184196
}

tests/Bridge/Doctrine/Orm/SubresourceDataProviderTest.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
use ApiPlatform\Core\Metadata\Property\PropertyNameCollection;
2626
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
2727
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
28+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy;
29+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy;
2830
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\ThirdLevel;
2931
use Doctrine\Common\Persistence\ManagerRegistry;
3032
use Doctrine\Common\Persistence\ObjectManager;
@@ -267,6 +269,68 @@ public function testGetSubSubresourceItem()
267269
$this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 1]], $context));
268270
}
269271

272+
public function testGetSubresourceOneToOneRelation()
273+
{
274+
// RelatedOwningDummy OneToOne RelatedOwnedDummy
275+
$managerRegistryProphecy = $this->prophesize(ManagerRegistry::class);
276+
$identifiers = ['id'];
277+
278+
// First manager (RelatedOwningDummy)
279+
// Generated QueryBuilder
280+
$qb = $this->prophesize(QueryBuilder::class);
281+
$qb->select('IDENTITY(owningDummy_a1.owningDummy)')->shouldBeCalled()->willReturn($qb);
282+
$qb->from(RelatedOwningDummy::class, 'owningDummy_a1')->shouldBeCalled()->willReturn($qb);
283+
$qb->andWhere('owningDummy_a1.id = :id_p1')->shouldBeCalled()->willReturn($qb);
284+
285+
// RelatedOwningDummy classMetaData
286+
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
287+
$classMetadataProphecy->hasAssociation('ownedDummy')->willReturn(true)->shouldBeCalled();
288+
$classMetadataProphecy->getAssociationMapping('ownedDummy')->shouldBeCalled()->willReturn(['type' => ClassMetadata::ONE_TO_ONE]);
289+
$classMetadataProphecy->getTypeOfField('id')->willReturn(DBALType::INTEGER)->shouldBeCalled();
290+
291+
// RelatedOwningDummy Manager
292+
$relatedOwningDummyManagerProphecy = $this->prophesize(EntityManager::class);
293+
$relatedOwningDummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal());
294+
$relatedOwningDummyManagerProphecy->getClassMetadata(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal());
295+
296+
$managerRegistryProphecy->getManagerForClass(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($relatedOwningDummyManagerProphecy->reveal());
297+
298+
// Result Query
299+
$result = new \stdClass();
300+
$queryProphecy = $this->prophesize(AbstractQuery::class);
301+
$queryProphecy->getOneOrNullResult()->shouldBeCalled()->willReturn($result);
302+
303+
// Second manager (RelatedOwnedDummy)
304+
// RelatedOwnedDummy classMetaData
305+
$classMetadataOwnedProphecy = $this->prophesize(ClassMetadata::class);
306+
$classMetadataOwnedProphecy->hasAssociation('owningDummy')->willReturn(true)->shouldBeCalled();
307+
$classMetadataOwnedProphecy->getAssociationMapping('owningDummy')->shouldBeCalled()->willReturn(['type' => ClassMetadata::ONE_TO_ONE]);
308+
$classMetadataOwnedProphecy->getTypeOfField('id')->willReturn(DBALType::INTEGER)->shouldBeCalled();
309+
310+
$queryBuilder = $this->prophesize(QueryBuilder::class);
311+
$queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal());
312+
$queryBuilder->setParameter('id_p1', 1, DBALType::INTEGER)->shouldBeCalled()->willReturn($queryBuilder);
313+
314+
$repositoryProphecy = $this->prophesize(EntityRepository::class);
315+
$repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal());
316+
317+
$ownedDummyManagerProphecy = $this->prophesize(EntityManager::class);
318+
$ownedDummyManagerProphecy->getClassMetaData(RelatedOwnedDummy::class)->willReturn($classMetadataOwnedProphecy->reveal());
319+
$ownedDummyManagerProphecy->getRepository(RelatedOwnedDummy::class)->willReturn($repositoryProphecy->reveal());
320+
321+
$managerRegistryProphecy->getManagerForClass(RelatedOwnedDummy::class)->shouldBeCalled()->willReturn($ownedDummyManagerProphecy->reveal());
322+
323+
list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies([RelatedOwnedDummy::class => $identifiers, RelatedOwningDummy::class => $identifiers]);
324+
325+
$dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory);
326+
327+
$context = ['property' => 'ownedDummy', 'identifiers' => [['id', RelatedOwningDummy::class], ['ownedDummy', RelatedOwnedDummy::class]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true];
328+
329+
330+
331+
$this->assertEquals($result, $dataProvider->getSubresource(RelatedOwnedDummy::class, ['id' => ['id' => 1], 'ownedDummy' => ['id' => 1]], $context));
332+
}
333+
270334
public function testQueryResultExtension()
271335
{
272336
$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';

0 commit comments

Comments
 (0)