Skip to content

Commit 87e1ac6

Browse files
committed
changes
1 parent 17c12d0 commit 87e1ac6

File tree

6 files changed

+169
-7
lines changed

6 files changed

+169
-7
lines changed

src/DoctrineIdentityExtractor.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ public function __construct(EntityManagerInterface $em)
2020
/**
2121
* @return mixed[]
2222
*/
23-
public function extractIdentities(object $entity): array
23+
public function extractIdentities(object $entity, bool $flat = false): array
2424
{
25-
return $this->em->getClassMetadata(get_class($entity))->getIdentifierValues($entity);
25+
$identities = $this->em->getClassMetadata(get_class($entity))->getIdentifierValues($entity);
26+
27+
return $flat ? $this->flatIdentity($identities) : $identities;
2628
}
2729

2830
/**
@@ -117,4 +119,15 @@ private function checkType(object $entity, string $type): void
117119
}
118120
}
119121

122+
private function flatIdentity(array $identity): array
123+
{
124+
foreach ($identity as $key => $value) {
125+
if (is_object($value)) {
126+
$identity[$key] = $this->extractIdentity($value);
127+
}
128+
}
129+
130+
return $identity;
131+
}
132+
120133
}

src/Insertion/Insertion.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Utilitte\Doctrine\Insertion;
4+
5+
use Doctrine\DBAL\ParameterType;
6+
use Doctrine\ORM\EntityManagerInterface;
7+
8+
final class Insertion
9+
{
10+
11+
public function __construct(
12+
private EntityManagerInterface $em,
13+
)
14+
{
15+
}
16+
17+
public function insertOneIgnore(string $entity, array $values, array $columns = []): bool
18+
{
19+
return $this->insertArray($entity, [$values], $columns, true) === 1;
20+
}
21+
22+
public function insertArray(string $entity, array $values, array $columns = [], bool $ignore = false): ?int
23+
{
24+
$insert = $this->sqlValues($values);
25+
$metadata = $this->em->getClassMetadata($entity);
26+
$table = $metadata->getTableName();
27+
28+
if (!$insert) {
29+
return null;
30+
}
31+
32+
if ($columns) {
33+
$columns = implode(
34+
', ',
35+
array_map(
36+
function (string $column) use ($metadata): string
37+
{
38+
if (isset($metadata->fieldMappings[$column])) {
39+
return $metadata->getColumnName($column);
40+
}
41+
42+
return $metadata->getSingleAssociationJoinColumnName($column);
43+
},
44+
$columns
45+
)
46+
);
47+
48+
$columns = ' (' . $columns . ')';
49+
} else {
50+
$columns = '';
51+
}
52+
53+
$sql = sprintf('INSERT%s INTO %s%s %s', $ignore ? ' IGNORE' : '', $table, $columns, $insert);
54+
55+
return $this->em->getConnection()->executeStatement($sql);
56+
}
57+
58+
private function sqlValues(array $values): ?string
59+
{
60+
$sql = '';
61+
62+
foreach ($values as $items) {
63+
$sql .= sprintf(
64+
'(%s), ',
65+
implode(',', array_map(fn (mixed $value) => $this->escape($value), $items))
66+
);
67+
}
68+
69+
return $sql ? 'VALUES ' . substr($sql, 0, -2) : null;
70+
}
71+
72+
private function escape(mixed $value): mixed
73+
{
74+
$type = ParameterType::STRING;
75+
76+
if (is_int($value)) {
77+
$type = ParameterType::INTEGER;
78+
} else if (is_bool($type)) {
79+
$type = ParameterType::BOOLEAN;
80+
}
81+
82+
return $this->em->getConnection()->quote($value, $type);
83+
}
84+
85+
}

src/Query/BuiltInFunctions.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Doctrine\ORM\Query\ResultSetMappingBuilder;
66
use InvalidArgumentException;
77
use Utilitte\Doctrine\Query\ValueObject\Alias;
8+
use Utilitte\Doctrine\Query\ValueObject\Config;
89
use Utilitte\Doctrine\QueryMetadataExtractor;
910

1011
final class BuiltInFunctions
@@ -14,10 +15,13 @@ final class BuiltInFunctions
1415

1516
private ResultSetMappingBuilder $rsmBuilder;
1617

17-
public function __construct(QueryMetadataExtractor $queryMetadataExtractor, ResultSetMappingBuilder $rsmBuilder)
18+
private Config $config;
19+
20+
public function __construct(QueryMetadataExtractor $queryMetadataExtractor, ResultSetMappingBuilder $rsmBuilder, Config $config)
1821
{
1922
$this->queryMetadataExtractor = $queryMetadataExtractor;
2023
$this->rsmBuilder = $rsmBuilder;
24+
$this->config = $config;
2125
}
2226

2327
/**
@@ -32,6 +36,11 @@ public function call(array $aliases, string $name, string ...$args)
3236
return $this->$name($aliases, ...$args);
3337
}
3438

39+
private function join(array $aliases, string $alias): string
40+
{
41+
return $this->config->getJoin($alias);
42+
}
43+
3544
private function select(): string
3645
{
3746
return $this->rsmBuilder->generateSelectClause();

src/Query/RawQueryFactory.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@ public function __construct(QueryMetadataExtractor $queryMetadataExtractor)
1818
$this->functions = new RawQueryFunctions($queryMetadataExtractor);
1919
}
2020

21-
public function prepare(string $sql): RawQueryStatement
21+
public function prepare(string $sql, string ...$subSqls): RawQueryStatement
2222
{
23+
if ($subSqls) {
24+
$sql = preg_replace_callback('#\?([0-9]+)#', function (array $matches) use ($subSqls) {
25+
return $subSqls[$matches[1] - 1];
26+
}, $sql);
27+
}
28+
2329
return new RawQueryStatement($this->queryMetadataExtractor, $sql);
2430
}
2531

src/Query/RawQueryStatement.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use InvalidArgumentException;
99
use Nette\Utils\Strings;
1010
use Utilitte\Doctrine\Query\ValueObject\Alias;
11+
use Utilitte\Doctrine\Query\ValueObject\Config;
1112
use Utilitte\Doctrine\QueryMetadataExtractor;
1213

1314
final class RawQueryStatement
@@ -24,6 +25,8 @@ final class RawQueryStatement
2425
/** @var Alias[] */
2526
private array $aliases = [];
2627

28+
private Config $config;
29+
2730
public function __construct(QueryMetadataExtractor $queryMetadataExtractor, string $sql)
2831
{
2932
$this->queryMetadataExtractor = $queryMetadataExtractor;
@@ -33,12 +36,13 @@ public function __construct(QueryMetadataExtractor $queryMetadataExtractor, stri
3336
$queryMetadataExtractor->getEntityManager(),
3437
ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT
3538
);
36-
$this->functions = new BuiltInFunctions($queryMetadataExtractor, $this->rsmBuilder);
39+
$this->config = new Config();
40+
$this->functions = new BuiltInFunctions($queryMetadataExtractor, $this->rsmBuilder, $this->config);
3741
}
3842

39-
public function addScalarResult(string $column, string $alias, string $type = 'string'): self
43+
public function addScalarResult(string $column, ?string $alias = null, string $type = 'string'): self
4044
{
41-
$this->rsmBuilder->addScalarResult($column, $alias, $type);
45+
$this->rsmBuilder->addScalarResult($column, $alias ?? $column, $type);
4246

4347
return $this;
4448
}
@@ -52,6 +56,28 @@ public function addRootEntity(string $class, string $alias): self
5256
return $this;
5357
}
5458

59+
public function addJoin(string $sourceAlias, string $field, string $alias): self
60+
{
61+
$class = $this->aliases[$sourceAlias]->getClass();
62+
$metadata = $this->queryMetadataExtractor->getClassMetadata($class);
63+
$assocClass = $metadata->getAssociationTargetClass($field);
64+
$assocMetadata = $this->queryMetadataExtractor->getClassMetadata($assocClass);
65+
66+
$this->config->addJoin($alias, sprintf(
67+
'%s AS %s ON %s.%s = %s.%s',
68+
$assocMetadata->getTableName(),
69+
$alias,
70+
$sourceAlias,
71+
$metadata->getSingleAssociationJoinColumnName($field),
72+
$alias,
73+
$metadata->getSingleAssociationReferencedJoinColumnName($field)
74+
));
75+
76+
$this->addEntity($assocClass, $alias);
77+
78+
return $this;
79+
}
80+
5581
public function addEntity(string $class, string $alias): self
5682
{
5783
$this->aliases[$alias] = new Alias($class, $alias);

src/Query/ValueObject/Config.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Utilitte\Doctrine\Query\ValueObject;
4+
5+
final class Config
6+
{
7+
8+
/** @var mixed[] */
9+
private array $joins = [];
10+
11+
public function addJoin(string $alias, string $join): self
12+
{
13+
$this->joins[$alias] = $join;
14+
15+
return $this;
16+
}
17+
18+
public function getJoin(string $alias): string
19+
{
20+
return $this->joins[$alias];
21+
}
22+
23+
}

0 commit comments

Comments
 (0)