Skip to content

Commit

Permalink
Fix Doctrine ORM alias resolver to support multiple select clauses in…
Browse files Browse the repository at this point in the history
… the single "select()" or "addSelect()" method call
  • Loading branch information
Kreyu committed Jul 24, 2024
1 parent 9099719 commit 246608a
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 6 deletions.
8 changes: 5 additions & 3 deletions src/Bridge/Doctrine/Orm/Query/AliasResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ private function isResolvable(string $path, QueryBuilder $queryBuilder): bool
}

foreach ($queryBuilder->getDQLPart('select') ?? [] as $select) {
$parts = preg_split('/ as( hidden)? /i', $select->getParts()[0]);
foreach ($select->getParts() as $clause) {
preg_match_all('/([^,]+)\s+AS\s+(HIDDEN\s+)?([^,]+)?/i', $clause, $matches);

if ($path === ($parts[1] ?? $parts[0])) {
return false;
if (in_array($path, $matches[3])) {
return false;
}
}
}

Expand Down
80 changes: 77 additions & 3 deletions tests/Unit/Bridge/Doctrine/Orm/Query/AliasResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,96 @@ public static function provideResolveCases(): iterable
'category.name',
];

yield 'With query path present in SELECT part' => [
yield 'With query path present in SELECT clause' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) AS product_name')
->from(Product::class, 'product'),
'product_name',
'product_name',
];

yield 'With query path present in SELECT clause, marked as HIDDEN' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) AS HIDDEN product_name')
->from(Product::class, 'product'),
'product_name',
'product_name',
];

yield 'With multiple selects in single call, first match' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) AS product_name', 'category.name AS HIDDEN category_name')
->from(Product::class, 'product')
->leftJoin('product.category', 'category'),
'product_name',
'product_name',
];

yield 'With query path present in SELECT part marked as HIDDEN' => [
yield 'With multiple selects in single call, second match' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) AS HIDDEN product_name')
->addSelect('UPPER(product.name) AS product_name', 'category.name AS HIDDEN category_name')
->from(Product::class, 'product')
->leftJoin('product.category', 'category'),
'category_name',
'category_name',
];

yield 'With multiple selects in single clause, first match' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) AS product_name, category.name AS HIDDEN category_name')
->from(Product::class, 'product')
->leftJoin('product.category', 'category'),
'product_name',
'product_name',
];

yield 'With multiple selects in single clause, second match' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) AS product_name, category.name AS HIDDEN category_name')
->from(Product::class, 'product')
->leftJoin('product.category', 'category'),
'category_name',
'category_name',
];

yield 'With lowercase AS' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) as product_name')
->from(Product::class, 'product'),
'product_name',
'product_name',
];

yield 'With lowercase AS HIDDEN' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) as hidden product_name')
->from(Product::class, 'product'),
'product_name',
'product_name',
];

yield 'With mixed case AS' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) As product_name')
->from(Product::class, 'product'),
'product_name',
'product_name',
];

yield 'With mixed case AS HIDDEN' => [
TestEntityManagerFactory::create()
->createQueryBuilder()
->addSelect('UPPER(product.name) aS HIDdeN product_name')
->from(Product::class, 'product'),
'product_name',
'product_name',
];
Expand Down

0 comments on commit 246608a

Please sign in to comment.