Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/Bridge/Doctrine/Orm/Util/QueryBuilderHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ private function __construct()
*/
public static function addJoinOnce(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $association, string $joinType = null, string $conditionType = null, string $condition = null, string $originAlias = null, string $newAlias = null): string
{
$join = self::getExistingJoin($queryBuilder, $alias, $association, $originAlias);
$joinType = $joinType ?? Join::INNER_JOIN;
$join = self::getExistingJoin($queryBuilder, $alias, $association, $originAlias, $joinType);

if (null !== $join) {
return $join->getAlias();
Expand All @@ -42,7 +43,7 @@ public static function addJoinOnce(QueryBuilder $queryBuilder, QueryNameGenerato
$associationAlias = $newAlias ?? $queryNameGenerator->generateJoinAlias($association);
$query = "$alias.$association";

if (Join::LEFT_JOIN === $joinType || QueryChecker::hasLeftJoin($queryBuilder)) {
if (Join::LEFT_JOIN === $joinType) {
$queryBuilder->leftJoin($query, $associationAlias, $conditionType, $condition);
} else {
$queryBuilder->innerJoin($query, $associationAlias, $conditionType, $condition);
Expand Down Expand Up @@ -160,7 +161,7 @@ public static function traverseJoins(string $alias, QueryBuilder $queryBuilder,
/**
* Gets the existing join from QueryBuilder DQL parts.
*/
private static function getExistingJoin(QueryBuilder $queryBuilder, string $alias, string $association, string $originAlias = null): ?Join
private static function getExistingJoin(QueryBuilder $queryBuilder, string $alias, string $association, ?string $originAlias, string $joinType): ?Join
{
$parts = $queryBuilder->getDQLPart('join');
$rootAlias = $originAlias ?? $queryBuilder->getRootAliases()[0];
Expand All @@ -171,7 +172,7 @@ private static function getExistingJoin(QueryBuilder $queryBuilder, string $alia

foreach ($parts[$rootAlias] as $join) {
/** @var Join $join */
if (sprintf('%s.%s', $alias, $association) === $join->getJoin()) {
if (sprintf('%s.%s', $alias, $association) === $join->getJoin() && $join->getJoinType() === $joinType) {
return $join;
}
}
Expand Down
17 changes: 0 additions & 17 deletions src/Bridge/Doctrine/Orm/Util/QueryChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;

/**
Expand Down Expand Up @@ -162,22 +161,6 @@ public static function hasOrderByOnToManyJoin(QueryBuilder $queryBuilder, Manage
return self::hasOrderByOnFetchJoinedToManyAssociation($queryBuilder, $managerRegistry);
}

/**
* Determines whether the QueryBuilder already has a left join.
*/
public static function hasLeftJoin(QueryBuilder $queryBuilder): bool
{
foreach ($queryBuilder->getDQLPart('join') as $joins) {
foreach ($joins as $join) {
if (Join::LEFT_JOIN === $join->getJoinType()) {
return true;
}
}
}

return false;
}

/**
* Determines whether the QueryBuilder has a joined to-many association.
*/
Expand Down
71 changes: 70 additions & 1 deletion tests/Bridge/Doctrine/Orm/Util/QueryBuilderHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
Expand Down Expand Up @@ -55,8 +56,49 @@ public function testAddJoinOnce(?string $originAliasForJoinOnce, string $expecte
}

/**
* @dataProvider provideAddJoinOnce
* @dataProvider provideAddJoinOnceWithMixedJoinTypes
*/
public function testAddJoinOnceWithMixedJoinTypes(
string $originAliasForJoinOnce,
string $newAlias,
string $joinType,
string $expectedAlias,
string $expectedJoinType
): void {
$queryBuilder = new QueryBuilder($this->prophesize(EntityManagerInterface::class)->reveal());
$queryBuilder->from('foo', 'f');
$queryBuilder->from('foo', 'f2');
$queryBuilder->join('f.bar', 'b');
$queryBuilder->join('f2.bar', 'b2');
$queryBuilder->leftJoin('f2.bar', 'bl2');

$queryNameGenerator = $this->prophesize(QueryNameGeneratorInterface::class);

$alias = QueryBuilderHelper::addJoinOnce(
$queryBuilder,
$queryNameGenerator->reveal(),
$originAliasForJoinOnce,
'bar',
$joinType,
null,
null,
$originAliasForJoinOnce,
$newAlias
);

/** @var Join $join */
foreach ($queryBuilder->getDQLPart('join')[$originAliasForJoinOnce] as $join) {
if ($join->getAlias() === $alias) {
$addedJoinType = $join->getJoinType();
}
}

$this->assertEqualsCanonicalizing(
[$expectedAlias, $expectedJoinType],
[$alias, $addedJoinType ?? null]
);
}

public function testAddJoinOnceWithSpecifiedNewAlias()
{
$queryBuilder = new QueryBuilder($this->prophesize(EntityManagerInterface::class)->reveal());
Expand Down Expand Up @@ -140,4 +182,31 @@ public function provideAddJoinOnce(): array
],
];
}

public function provideAddJoinOnceWithMixedJoinTypes(): array
{
return [
'Adding new join for already joined association but with different type' => [
'f',
'bl',
Join::LEFT_JOIN,
'bl',
Join::LEFT_JOIN,
],
'Adding already existing join with type left' => [
'f2',
'bl8',
Join::LEFT_JOIN,
'bl2',
Join::LEFT_JOIN,
],
'Adding already existing join with type inner' => [
'f2',
'b8',
Join::INNER_JOIN,
'b2',
Join::INNER_JOIN,
],
];
}
}