Skip to content

Commit 3e22316

Browse files
committed
add RawQueryFunctions
1 parent bdda1c6 commit 3e22316

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed

src/Query/RawQueryFactory.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ final class RawQueryFactory
1010
{
1111

1212
private QueryMetadataExtractor $queryMetadataExtractor;
13+
private RawQueryFunctions $functions;
1314

1415
public function __construct(QueryMetadataExtractor $queryMetadataExtractor)
1516
{
1617
$this->queryMetadataExtractor = $queryMetadataExtractor;
18+
$this->functions = new RawQueryFunctions($queryMetadataExtractor);
1719
}
1820

1921
/**
@@ -34,6 +36,9 @@ public function create(string $sql, array $aliases): string
3436
*/
3537
private function replace(array $matches, array $aliases): string
3638
{
39+
if ($matches[1] === 'fn') {
40+
return $this->replaceFunctions($matches, $aliases);
41+
}
3742
if (!isset($aliases[$matches[1]])) {
3843
throw new InvalidArgumentException(sprintf('Alias %s not set', $matches[1]));
3944
}
@@ -44,14 +49,33 @@ private function replace(array $matches, array $aliases): string
4449
$this->queryMetadataExtractor->getTableName($aliases[$matches[1]]);
4550
}
4651

52+
/**
53+
* @param mixed[] $matches
54+
* @param string[] $aliases
55+
*/
56+
private function replaceFunctions(array $matches, array $aliases): string
57+
{
58+
if (count($matches) !== 4) {
59+
throw new InvalidArgumentException('Raw query function must have method');
60+
}
61+
62+
$name = $matches[2];
63+
$args = array_map('trim', explode(',', $matches[3]));
64+
65+
return $this->functions->call($aliases, $name, ...$args);
66+
}
67+
4768
/**
4869
* @param string[] $aliases
4970
*/
5071
private function buildRegex(array $aliases): string
5172
{
73+
$aliases[] = 'fn';
5274
$group = implode('|', array_map(fn (string $alias) => preg_quote($alias, '#'), $aliases));
5375

54-
return '#%(' . $group . ')(?:\.(\w+))?#';
76+
$args = '(?:\((.*?)\))?';
77+
78+
return '#%(' . $group . ')(?:\.(\w+)' . $args . ')?#';
5579
}
5680

5781
}

src/Query/RawQueryFunctions.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Utilitte\Doctrine\Query;
4+
5+
use InvalidArgumentException;
6+
use Utilitte\Doctrine\QueryMetadataExtractor;
7+
8+
final class RawQueryFunctions
9+
{
10+
11+
private QueryMetadataExtractor $queryMetadataExtractor;
12+
13+
public function __construct(QueryMetadataExtractor $queryMetadataExtractor)
14+
{
15+
$this->queryMetadataExtractor = $queryMetadataExtractor;
16+
}
17+
18+
public function call(array $aliases, string $name, string ...$args)
19+
{
20+
if ($name === 'call' || !method_exists($this, $name)) {
21+
throw new InvalidArgumentException(sprintf('Raw query function %s not exists', $name));
22+
}
23+
24+
return $this->$name($aliases, ...$args);
25+
}
26+
27+
public function join(array $aliases, string $field, ?string $alias = null, ?string $sourceAlias = null): string
28+
{
29+
[$table, $column] = explode('.' , $field);
30+
$alias = $alias ? ' ' . $alias : '';
31+
32+
$metadata = $this->queryMetadataExtractor->getClassMetadata($aliases[$table]);
33+
$tableName = $this->queryMetadataExtractor->getTableName($metadata->getAssociationMapping($column)['targetEntity']);
34+
35+
return sprintf(
36+
'%s%s ON %s%s = %s',
37+
$tableName,
38+
$alias,
39+
$sourceAlias ? $sourceAlias . '.' : '',
40+
$metadata->getSingleAssociationJoinColumnName($column),
41+
$metadata->getSingleAssociationReferencedJoinColumnName($column)
42+
);
43+
}
44+
45+
public function joinTable(array $aliases, string $field): string
46+
{
47+
[$table, $column] = explode('.' , $field);
48+
49+
$metadata = $this->queryMetadataExtractor->getClassMetadata($aliases[$table]);
50+
51+
return $this->queryMetadataExtractor->getTableName($metadata->getAssociationMapping($column)['targetEntity']);
52+
}
53+
54+
public function joinSource(array $aliases, string $field): string
55+
{
56+
[$table, $column] = explode('.' , $field);
57+
58+
$metadata = $this->queryMetadataExtractor->getClassMetadata($aliases[$table]);
59+
60+
return $metadata->getSingleAssociationJoinColumnName($column);
61+
}
62+
63+
public function joinTarget(array $aliases, string $field): string
64+
{
65+
[$table, $column] = explode('.' , $field);
66+
67+
$metadata = $this->queryMetadataExtractor->getClassMetadata($aliases[$table]);
68+
69+
return $metadata->getSingleAssociationReferencedJoinColumnName($column);
70+
}
71+
72+
}

0 commit comments

Comments
 (0)