Skip to content

Commit

Permalink
fix api-platform/#360 QueryChecker with class join
Browse files Browse the repository at this point in the history
  • Loading branch information
abluchet committed Aug 7, 2017
1 parent e0c8465 commit b0b0089
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 13 deletions.
34 changes: 29 additions & 5 deletions src/Bridge/Doctrine/Orm/Util/QueryChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,44 @@ public static function hasOrderByOnToManyJoin(QueryBuilder $queryBuilder, Manage
}
}

if (empty($orderByAliases)) {
return false;
}

if (!empty($orderByAliases)) {
foreach ($joinParts as $joins) {
foreach ($joins as $join) {
$alias = QueryJoinParser::getJoinAlias($join);

if (isset($orderByAliases[$alias])) {
$relationship = QueryJoinParser::getJoinRelationship($join);
list($parentAlias, $association) = explode('.', $relationship);
if (!isset($orderByAliases[$alias])) {
continue;
}

$parentMetadata = QueryJoinParser::getClassMetadataFromJoinAlias($parentAlias, $queryBuilder, $managerRegistry);
$relationship = QueryJoinParser::getJoinRelationship($join);

if ($parentMetadata->isCollectionValuedAssociation($association)) {
if (false !== strpos($relationship, '.')) {
$metadata = QueryJoinParser::getClassMetadataFromJoinAlias($alias, $queryBuilder, $managerRegistry);
if ($metadata->isCollectionValuedAssociation($relationship)) {
return true;
}
} else {
$parentMetadata = $managerRegistry->getManagerForClass($relationship)->getClassMetadata($relationship);

foreach ($queryBuilder->getRootEntities() as $rootEntity) {
$rootMetadata = $managerRegistry
->getManagerForClass($rootEntity)
->getClassMetadata($rootEntity);

if (!($rootMetadata instanceof ClassMetadata)) {
continue;
}

foreach ($rootMetadata->getAssociationsByTargetClass($relationship) as $association => $mapping) {
if ($parentMetadata->isCollectionValuedAssociation($association)) {
return true;
}
}
}
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions src/Bridge/Doctrine/Orm/Util/QueryJoinParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@ public static function getClassMetadataFromJoinAlias(string $alias, QueryBuilder

$pos = strpos($relationship, '.');

$aliasMap[$alias] = [
'parentAlias' => substr($relationship, 0, $pos),
'association' => substr($relationship, $pos + 1),
];
if (false !== $pos) {
$aliasMap[$alias] = [
'parentAlias' => substr($relationship, 0, $pos),
'association' => substr($relationship, $pos + 1),
];
}
}
}

Expand Down
22 changes: 22 additions & 0 deletions tests/Bridge/Doctrine/Orm/Util/QueryCheckerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Orm\Util;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryChecker;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\Mapping\ClassMetadata;
Expand Down Expand Up @@ -153,4 +154,25 @@ public function testHasOrderByOnToManyJoinWithoutJoinAndWithoutOrderBy()

$this->assertFalse(QueryChecker::hasOrderByOnToManyJoin($queryBuilder->reveal(), $managerRegistry->reveal()));
}

public function testHasOrderByOnToManyJoinWithClassLeftJoin()
{
$queryBuilder = $this->prophesize(QueryBuilder::class);
$queryBuilder->getRootEntities()->willReturn(['Dummy']);
$queryBuilder->getRootAliases()->willReturn(['d']);
$queryBuilder->getDQLPart('join')->willReturn(['a_1' => [new Join('LEFT_JOIN', RelatedDummy::class, 'a_1', null, 'a_1.name = d.name')]]);
$queryBuilder->getDQLPart('orderBy')->willReturn(['a_1.name' => new OrderBy('a_1.name', 'asc')]);
$classMetadata = $this->prophesize(ClassMetadata::class);
$classMetadata->getAssociationsByTargetClass(RelatedDummy::class)->willReturn(['relatedDummy' => ['targetEntity' => RelatedDummy::class]]);
$relatedClassMetadata = $this->prophesize(ClassMetadata::class);
$relatedClassMetadata->isCollectionValuedAssociation('relatedDummy')->willReturn(true);
$objectManager = $this->prophesize(ObjectManager::class);
$objectManager->getClassMetadata('Dummy')->willReturn($classMetadata->reveal());
$objectManager->getClassMetadata(RelatedDummy::class)->willReturn($relatedClassMetadata->reveal());
$managerRegistry = $this->prophesize(ManagerRegistry::class);
$managerRegistry->getManagerForClass('Dummy')->willReturn($objectManager->reveal());
$managerRegistry->getManagerForClass(RelatedDummy::class)->willReturn($objectManager->reveal());

$this->assertTrue(QueryChecker::hasOrderByOnToManyJoin($queryBuilder->reveal(), $managerRegistry->reveal()));
}
}
21 changes: 17 additions & 4 deletions tests/Bridge/Doctrine/Orm/Util/QueryJoinParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Orm\Util;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryJoinParser;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\Mapping\ClassMetadata;
Expand Down Expand Up @@ -43,16 +44,22 @@ public function testGetClassMetadataFromJoinAlias()

public function testGetJoinRelationshipWithJoin()
{
$join = new Join('INNER_JOIN', 'relatedDummy', 'a_1', null, 'a_1.name = r.name');
$this->assertEquals('relatedDummy', QueryJoinParser::getJoinRelationship($join));
$join = new Join('INNER_JOIN', 'a_1.relatedDummy', 'a_1', null, 'a_1.name = r.name');
$this->assertEquals('a_1.relatedDummy', QueryJoinParser::getJoinRelationship($join));
}

public function testGetJoinRelationshipWithClassJoin()
{
$join = new Join('INNER_JOIN', RelatedDummy::class, 'a_1', null, 'a_1.name = r.name');
$this->assertEquals(RelatedDummy::class, QueryJoinParser::getJoinRelationship($join));
}

public function testGetJoinRelationshipWithReflection()
{
$methodExist = $this->getFunctionMock('ApiPlatform\Core\Bridge\Doctrine\Orm\Util', 'method_exists');
$methodExist->expects($this->any())->with(Join::class, 'getJoin')->willReturn('false');
$join = new Join('INNER_JOIN', 'relatedDummy', 'a_1', null, 'a_1.name = r.name');
$this->assertEquals('relatedDummy', QueryJoinParser::getJoinRelationship($join));
$join = new Join('INNER_JOIN', 'a_1.relatedDummy', 'a_1', null, 'a_1.name = r.name');
$this->assertEquals('a_1.relatedDummy', QueryJoinParser::getJoinRelationship($join));
}

public function testGetJoinAliasWithJoin()
Expand All @@ -61,6 +68,12 @@ public function testGetJoinAliasWithJoin()
$this->assertEquals('a_1', QueryJoinParser::getJoinAlias($join));
}

public function testGetJoinAliasWithClassJoin()
{
$join = new Join('LEFT_JOIN', RelatedDummy::class, 'a_1', null, 'a_1.name = r.name');
$this->assertEquals('a_1', QueryJoinParser::getJoinAlias($join));
}

public function testGetJoinAliasWithReflection()
{
$methodExist = $this->getFunctionMock('ApiPlatform\Core\Bridge\Doctrine\Orm\Util', 'method_exists');
Expand Down

0 comments on commit b0b0089

Please sign in to comment.