Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / orm / lib / Doctrine / ORM / Query / ResultSetMappingBuilder.php
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 MIT license. For more information, see
17  * <http://www.doctrine-project.org>.
18  */
19
20 namespace Doctrine\ORM\Query;
21
22 use Doctrine\ORM\EntityManager;
23 use Doctrine\ORM\Mapping\ClassMetadataInfo;
24
25 /**
26  * A ResultSetMappingBuilder uses the EntityManager to automatically populate entity fields
27  *
28  * @author Michael Ridgway <mcridgway@gmail.com>
29  * @since 2.1
30  */
31 class ResultSetMappingBuilder extends ResultSetMapping
32 {
33     /**
34      * @var EntityManager
35      */
36     private $em;
37
38     /**
39      * @param EntityManager
40      */
41     public function __construct(EntityManager $em)
42     {
43         $this->em = $em;
44     }
45
46     /**
47      * Adds a root entity and all of its fields to the result set.
48      *
49      * @param string $class The class name of the root entity.
50      * @param string $alias The unique alias to use for the root entity.
51      * @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName)
52      */
53     public function addRootEntityFromClassMetadata($class, $alias, $renamedColumns = array())
54     {
55         $this->addEntityResult($class, $alias);
56         $this->addAllClassFields($class, $alias, $renamedColumns);
57     }
58
59     /**
60      * Adds a joined entity and all of its fields to the result set.
61      *
62      * @param string $class The class name of the joined entity.
63      * @param string $alias The unique alias to use for the joined entity.
64      * @param string $parentAlias The alias of the entity result that is the parent of this joined result.
65      * @param object $relation The association field that connects the parent entity result with the joined entity result.
66      * @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName)
67      */
68     public function addJoinedEntityFromClassMetadata($class, $alias, $parentAlias, $relation, $renamedColumns = array())
69     {
70         $this->addJoinedEntityResult($class, $alias, $parentAlias, $relation);
71         $this->addAllClassFields($class, $alias, $renamedColumns);
72     }
73
74     /**
75      * Adds all fields of the given class to the result set mapping (columns and meta fields)
76      */
77     protected function addAllClassFields($class, $alias, $renamedColumns = array())
78     {
79         $classMetadata = $this->em->getClassMetadata($class);
80         if ($classMetadata->isInheritanceTypeSingleTable() || $classMetadata->isInheritanceTypeJoined()) {
81             throw new \InvalidArgumentException('ResultSetMapping builder does not currently support inheritance.');
82         }
83         $platform = $this->em->getConnection()->getDatabasePlatform();
84         foreach ($classMetadata->getColumnNames() as $columnName) {
85             $propertyName = $classMetadata->getFieldName($columnName);
86             if (isset($renamedColumns[$columnName])) {
87                 $columnName = $renamedColumns[$columnName];
88             }
89             $columnName = $platform->getSQLResultCasing($columnName);
90             if (isset($this->fieldMappings[$columnName])) {
91                 throw new \InvalidArgumentException("The column '$columnName' conflicts with another column in the mapper.");
92             }
93             $this->addFieldResult($alias, $columnName, $propertyName);
94         }
95         foreach ($classMetadata->associationMappings as $associationMapping) {
96             if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
97                 foreach ($associationMapping['joinColumns'] as $joinColumn) {
98                     $columnName = $joinColumn['name'];
99                     $renamedColumnName = isset($renamedColumns[$columnName]) ? $renamedColumns[$columnName] : $columnName;
100                     $renamedColumnName = $platform->getSQLResultCasing($renamedColumnName);
101                     if (isset($this->metaMappings[$renamedColumnName])) {
102                         throw new \InvalidArgumentException("The column '$renamedColumnName' conflicts with another column in the mapper.");
103                     }
104                     $this->addMetaResult($alias, $renamedColumnName, $columnName);
105                 }
106             }
107         }
108     }
109
110
111     /**
112      * Adds the mappings of the results of native SQL queries to the result set.
113      *
114      * @param   ClassMetadataInfo $class
115      * @param   array $queryMapping
116      * @return  ResultSetMappingBuilder
117      */
118     public function addNamedNativeQueryMapping(ClassMetadataInfo $class, array $queryMapping)
119     {
120         if (isset($queryMapping['resultClass'])) {
121             return $this->addNamedNativeQueryResultClassMapping($class, $queryMapping['resultClass']);
122         }
123
124         return $this->addNamedNativeQueryResultSetMapping($class, $queryMapping['resultSetMapping']);
125     }
126
127     /**
128      * Adds the class mapping of the results of native SQL queries to the result set.
129      *
130      * @param   ClassMetadataInfo $class
131      * @param   string $resultClassName
132      * @return  ResultSetMappingBuilder
133      */
134     public function addNamedNativeQueryResultClassMapping(ClassMetadataInfo $class, $resultClassName)
135     {
136
137         $classMetadata  = $this->em->getClassMetadata($resultClassName);
138         $shortName      = $classMetadata->reflClass->getShortName();
139         $alias          = strtolower($shortName[0]).'0';
140
141         $this->addEntityResult($class->name, $alias);
142
143         if ($classMetadata->discriminatorColumn) {
144             $discriminatorColumn = $classMetadata->discriminatorColumn;
145             $this->setDiscriminatorColumn($alias, $discriminatorColumn['name']);
146             $this->addMetaResult($alias, $discriminatorColumn['name'], $discriminatorColumn['fieldName']);
147         }
148
149         foreach ($classMetadata->getColumnNames() as $key => $columnName) {
150             $propertyName   = $classMetadata->getFieldName($columnName);
151             $this->addFieldResult($alias, $columnName, $propertyName);
152         }
153
154         foreach ($classMetadata->associationMappings as $associationMapping) {
155             if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
156                 foreach ($associationMapping['joinColumns'] as $joinColumn) {
157                     $columnName = $joinColumn['name'];
158                     $this->addMetaResult($alias, $columnName, $columnName, $classMetadata->isIdentifier($columnName));
159                 }
160             }
161         }
162
163         return $this;
164     }
165
166     /**
167      * Adds the result set mapping of the results of native SQL queries to the result set.
168      *
169      * @param   ClassMetadataInfo $class
170      * @param   string $resultSetMappingName
171      * @return  ResultSetMappingBuilder
172      */
173     public function addNamedNativeQueryResultSetMapping(ClassMetadataInfo $class, $resultSetMappingName)
174     {
175         $counter        = 0;
176         $resultMapping  = $class->getSqlResultSetMapping($resultSetMappingName);
177         $rooShortName   = $class->reflClass->getShortName();
178         $rootAlias      = strtolower($rooShortName[0]) . $counter;
179
180
181         if (isset($resultMapping['entities'])) {
182             foreach ($resultMapping['entities'] as $key => $entityMapping) {
183                 $classMetadata  = $this->em->getClassMetadata($entityMapping['entityClass']);
184
185                 if ($class->reflClass->name == $classMetadata->reflClass->name) {
186                     $this->addEntityResult($classMetadata->name, $rootAlias);
187                     $this->addNamedNativeQueryEntityResultMapping($classMetadata, $entityMapping, $rootAlias);
188                 } else {
189                     $shortName      = $classMetadata->reflClass->getShortName();
190                     $joinAlias      = strtolower($shortName[0]) . ++ $counter;
191                     $associations   = $class->getAssociationsByTargetClass($classMetadata->name);
192
193                     foreach ($associations as $relation => $mapping) {
194                         $this->addJoinedEntityResult($mapping['targetEntity'], $joinAlias, $rootAlias, $relation);
195                         $this->addNamedNativeQueryEntityResultMapping($classMetadata, $entityMapping, $joinAlias);
196                     }
197                 }
198
199             }
200         }
201
202         if (isset($resultMapping['columns'])) {
203             foreach ($resultMapping['columns'] as $entityMapping) {
204                 $this->addScalarResult($entityMapping['name'], $entityMapping['name']);
205             }
206         }
207
208         return $this;
209     }
210
211     /**
212      * Adds the entity result mapping of the results of native SQL queries to the result set.
213      * 
214      * @param ClassMetadataInfo $classMetadata
215      * @param array $entityMapping
216      * @param string $alias
217      * @return ResultSetMappingBuilder
218      */
219     public function addNamedNativeQueryEntityResultMapping(ClassMetadataInfo $classMetadata, array $entityMapping, $alias)
220     {
221         if (isset($entityMapping['discriminatorColumn']) && $entityMapping['discriminatorColumn']) {
222             $discriminatorColumn = $entityMapping['discriminatorColumn'];
223             $this->setDiscriminatorColumn($alias, $discriminatorColumn);
224             $this->addMetaResult($alias, $discriminatorColumn, $discriminatorColumn);
225         }
226
227         if (isset($entityMapping['fields']) && !empty($entityMapping['fields'])) {
228             foreach ($entityMapping['fields'] as $field) {
229                 $fieldName = $field['name'];
230                 $relation  = null;
231
232                 if(strpos($fieldName, '.')){
233                     list($relation, $fieldName) = explode('.', $fieldName);
234                 }
235
236                 if (isset($classMetadata->associationMappings[$relation])) {
237                     if($relation) {
238                         $associationMapping = $classMetadata->associationMappings[$relation];
239                         $joinAlias          = $alias.$relation;
240                         $parentAlias        = $alias;
241
242                         $this->addJoinedEntityResult($associationMapping['targetEntity'], $joinAlias, $parentAlias, $relation);
243                         $this->addFieldResult($joinAlias, $field['column'], $fieldName);
244                     }else {
245                         $this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name);
246                     }
247                 } else {
248                     if(!isset($classMetadata->fieldMappings[$fieldName])) {
249                         throw new \InvalidArgumentException("Entity '".$classMetadata->name."' has no field '".$fieldName."'. ");
250                     }
251                     $this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name);
252                 }
253             }
254
255         } else {
256             foreach ($classMetadata->getColumnNames() as $columnName) {
257                 $propertyName   = $classMetadata->getFieldName($columnName);
258                 $this->addFieldResult($alias, $columnName, $propertyName);
259             }
260         }
261
262         return $this;
263     }
264 }