|
1 <?php |
|
2 /* |
|
3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
14 * |
|
15 * This software consists of voluntary contributions made by many individuals |
|
16 * and is licensed under the LGPL. For more information, see |
|
17 * <http://www.doctrine-project.org>. |
|
18 */ |
|
19 |
|
20 namespace Doctrine\ORM\Persisters; |
|
21 |
|
22 use Doctrine\ORM\Mapping\ClassMetadata; |
|
23 |
|
24 /** |
|
25 * Persister for entities that participate in a hierarchy mapped with the |
|
26 * SINGLE_TABLE strategy. |
|
27 * |
|
28 * @author Roman Borschel <roman@code-factory.org> |
|
29 * @author Benjamin Eberlei <kontakt@beberlei.de> |
|
30 * @since 2.0 |
|
31 * @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html |
|
32 */ |
|
33 class SingleTablePersister extends AbstractEntityInheritancePersister |
|
34 { |
|
35 /** {@inheritdoc} */ |
|
36 protected function _getDiscriminatorColumnTableName() |
|
37 { |
|
38 return $this->_class->table['name']; |
|
39 } |
|
40 |
|
41 /** {@inheritdoc} */ |
|
42 protected function _getSelectColumnListSQL() |
|
43 { |
|
44 $columnList = parent::_getSelectColumnListSQL(); |
|
45 |
|
46 // Append discriminator column |
|
47 $discrColumn = $this->_class->discriminatorColumn['name']; |
|
48 $columnList .= ", $discrColumn"; |
|
49 $rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName); |
|
50 $tableAlias = $this->_getSQLTableAlias($rootClass->name); |
|
51 $resultColumnName = $this->_platform->getSQLResultCasing($discrColumn); |
|
52 $this->_rsm->setDiscriminatorColumn('r', $resultColumnName); |
|
53 $this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn); |
|
54 |
|
55 // Append subclass columns |
|
56 foreach ($this->_class->subClasses as $subClassName) { |
|
57 $subClass = $this->_em->getClassMetadata($subClassName); |
|
58 // Regular columns |
|
59 foreach ($subClass->fieldMappings as $fieldName => $mapping) { |
|
60 if ( ! isset($mapping['inherited'])) { |
|
61 $columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass); |
|
62 } |
|
63 } |
|
64 // Foreign key columns |
|
65 foreach ($subClass->associationMappings as $assoc) { |
|
66 if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE && ! isset($assoc['inherited'])) { |
|
67 foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) { |
|
68 if ($columnList != '') $columnList .= ', '; |
|
69 $columnList .= $this->getSelectJoinColumnSQL($tableAlias, $srcColumn, |
|
70 isset($assoc['inherited']) ? $assoc['inherited'] : $this->_class->name |
|
71 ); |
|
72 } |
|
73 } |
|
74 } |
|
75 } |
|
76 |
|
77 return $columnList; |
|
78 } |
|
79 |
|
80 /** {@inheritdoc} */ |
|
81 protected function _getInsertColumnList() |
|
82 { |
|
83 $columns = parent::_getInsertColumnList(); |
|
84 // Add discriminator column to the INSERT SQL |
|
85 $columns[] = $this->_class->discriminatorColumn['name']; |
|
86 |
|
87 return $columns; |
|
88 } |
|
89 |
|
90 /** {@inheritdoc} */ |
|
91 protected function _getSQLTableAlias($className, $assocName = '') |
|
92 { |
|
93 return parent::_getSQLTableAlias($this->_class->rootEntityName, $assocName); |
|
94 } |
|
95 |
|
96 /** {@inheritdoc} */ |
|
97 protected function _getSelectConditionSQL(array $criteria, $assoc = null) |
|
98 { |
|
99 $conditionSql = parent::_getSelectConditionSQL($criteria, $assoc); |
|
100 |
|
101 // Append discriminator condition |
|
102 if ($conditionSql) $conditionSql .= ' AND '; |
|
103 $values = array(); |
|
104 if ($this->_class->discriminatorValue !== null) { // discriminators can be 0 |
|
105 $values[] = $this->_conn->quote($this->_class->discriminatorValue); |
|
106 } |
|
107 |
|
108 $discrValues = array_flip($this->_class->discriminatorMap); |
|
109 foreach ($this->_class->subClasses as $subclassName) { |
|
110 $values[] = $this->_conn->quote($discrValues[$subclassName]); |
|
111 } |
|
112 $conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.' |
|
113 . $this->_class->discriminatorColumn['name'] |
|
114 . ' IN (' . implode(', ', $values) . ')'; |
|
115 |
|
116 return $conditionSql; |
|
117 } |
|
118 } |