summaryrefslogtreecommitdiff
path: root/vendor/doctrine/orm/src/Persisters/Entity/SingleTablePersister.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/doctrine/orm/src/Persisters/Entity/SingleTablePersister.php')
-rw-r--r--vendor/doctrine/orm/src/Persisters/Entity/SingleTablePersister.php166
1 files changed, 166 insertions, 0 deletions
diff --git a/vendor/doctrine/orm/src/Persisters/Entity/SingleTablePersister.php b/vendor/doctrine/orm/src/Persisters/Entity/SingleTablePersister.php
new file mode 100644
index 0000000..4a4d999
--- /dev/null
+++ b/vendor/doctrine/orm/src/Persisters/Entity/SingleTablePersister.php
@@ -0,0 +1,166 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\ORM\Persisters\Entity;
6
7use Doctrine\Common\Collections\Criteria;
8use Doctrine\ORM\Internal\SQLResultCasing;
9use Doctrine\ORM\Mapping\AssociationMapping;
10use Doctrine\ORM\Mapping\ClassMetadata;
11use Doctrine\ORM\Utility\PersisterHelper;
12
13use function array_flip;
14use function array_intersect;
15use function array_map;
16use function array_unshift;
17use function implode;
18use function strval;
19
20/**
21 * Persister for entities that participate in a hierarchy mapped with the
22 * SINGLE_TABLE strategy.
23 *
24 * @link https://martinfowler.com/eaaCatalog/singleTableInheritance.html
25 */
26class SingleTablePersister extends AbstractEntityInheritancePersister
27{
28 use SQLResultCasing;
29
30 protected function getDiscriminatorColumnTableName(): string
31 {
32 return $this->class->getTableName();
33 }
34
35 protected function getSelectColumnsSQL(): string
36 {
37 $columnList = [];
38 if ($this->currentPersisterContext->selectColumnListSql !== null) {
39 return $this->currentPersisterContext->selectColumnListSql;
40 }
41
42 $columnList[] = parent::getSelectColumnsSQL();
43
44 $rootClass = $this->em->getClassMetadata($this->class->rootEntityName);
45 $tableAlias = $this->getSQLTableAlias($rootClass->name);
46
47 // Append discriminator column
48 $discrColumn = $this->class->getDiscriminatorColumn();
49 $discrColumnName = $discrColumn->name;
50 $discrColumnType = $discrColumn->type;
51
52 $columnList[] = $tableAlias . '.' . $discrColumnName;
53
54 $resultColumnName = $this->getSQLResultCasing($this->platform, $discrColumnName);
55
56 $this->currentPersisterContext->rsm->setDiscriminatorColumn('r', $resultColumnName);
57 $this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumnName, false, $discrColumnType);
58
59 // Append subclass columns
60 foreach ($this->class->subClasses as $subClassName) {
61 $subClass = $this->em->getClassMetadata($subClassName);
62
63 // Regular columns
64 foreach ($subClass->fieldMappings as $fieldName => $mapping) {
65 if (isset($mapping->inherited)) {
66 continue;
67 }
68
69 $columnList[] = $this->getSelectColumnSQL($fieldName, $subClass);
70 }
71
72 // Foreign key columns
73 foreach ($subClass->associationMappings as $assoc) {
74 if (! $assoc->isToOneOwningSide() || isset($assoc->inherited)) {
75 continue;
76 }
77
78 $targetClass = $this->em->getClassMetadata($assoc->targetEntity);
79
80 foreach ($assoc->joinColumns as $joinColumn) {
81 $columnList[] = $this->getSelectJoinColumnSQL(
82 $tableAlias,
83 $joinColumn->name,
84 $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform),
85 PersisterHelper::getTypeOfColumn($joinColumn->referencedColumnName, $targetClass, $this->em),
86 );
87 }
88 }
89 }
90
91 $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList);
92
93 return $this->currentPersisterContext->selectColumnListSql;
94 }
95
96 /**
97 * {@inheritDoc}
98 */
99 protected function getInsertColumnList(): array
100 {
101 $columns = parent::getInsertColumnList();
102
103 // Add discriminator column to the INSERT SQL
104 $columns[] = $this->class->getDiscriminatorColumn()->name;
105
106 return $columns;
107 }
108
109 protected function getSQLTableAlias(string $className, string $assocName = ''): string
110 {
111 return parent::getSQLTableAlias($this->class->rootEntityName, $assocName);
112 }
113
114 /**
115 * {@inheritDoc}
116 */
117 protected function getSelectConditionSQL(array $criteria, AssociationMapping|null $assoc = null): string
118 {
119 $conditionSql = parent::getSelectConditionSQL($criteria, $assoc);
120
121 if ($conditionSql) {
122 $conditionSql .= ' AND ';
123 }
124
125 return $conditionSql . $this->getSelectConditionDiscriminatorValueSQL();
126 }
127
128 protected function getSelectConditionCriteriaSQL(Criteria $criteria): string
129 {
130 $conditionSql = parent::getSelectConditionCriteriaSQL($criteria);
131
132 if ($conditionSql) {
133 $conditionSql .= ' AND ';
134 }
135
136 return $conditionSql . $this->getSelectConditionDiscriminatorValueSQL();
137 }
138
139 protected function getSelectConditionDiscriminatorValueSQL(): string
140 {
141 $values = array_map($this->conn->quote(...), array_map(
142 strval(...),
143 array_flip(array_intersect($this->class->discriminatorMap, $this->class->subClasses)),
144 ));
145
146 if ($this->class->discriminatorValue !== null) { // discriminators can be 0
147 array_unshift($values, $this->conn->quote((string) $this->class->discriminatorValue));
148 }
149
150 $discColumnName = $this->class->getDiscriminatorColumn()->name;
151
152 $values = implode(', ', $values);
153 $tableAlias = $this->getSQLTableAlias($this->class->name);
154
155 return $tableAlias . '.' . $discColumnName . ' IN (' . $values . ')';
156 }
157
158 protected function generateFilterConditionSQL(ClassMetadata $targetEntity, string $targetTableAlias): string
159 {
160 // Ensure that the filters are applied to the root entity of the inheritance tree
161 $targetEntity = $this->em->getClassMetadata($targetEntity->rootEntityName);
162 // we don't care about the $targetTableAlias, in a STI there is only one table.
163
164 return parent::generateFilterConditionSQL($targetEntity, $targetTableAlias);
165 }
166}