a832d92b78c6026dc0b38af8baf7d69c3f5b05ad
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Persistence / Generic / Mapper / DataMapper.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Persistence\Generic\Mapper;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2013 Extbase Team (http://forge.typo3.org/projects/typo3v4-mvc)
8 * Extbase is a backport of TYPO3 Flow. All credits go to the TYPO3 Flow team.
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30 /**
31 * A mapper to map database tables configured in $TCA on domain objects.
32 */
33 class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
34
35 /**
36 * @var \TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap
37 */
38 protected $identityMap;
39
40 /**
41 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
42 */
43 protected $reflectionService;
44
45 /**
46 * @var \TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelFactory
47 */
48 protected $qomFactory;
49
50 /**
51 * @var \TYPO3\CMS\Extbase\Persistence\Generic\Session
52 */
53 protected $persistenceSession;
54
55 /**
56 * A reference to the page select object providing methods to perform language and work space overlays
57 *
58 * @var \TYPO3\CMS\Frontend\Page\PageRepository
59 */
60 protected $pageSelectObject;
61
62 /**
63 * Cached data maps
64 *
65 * @var array
66 */
67 protected $dataMaps = array();
68
69 /**
70 * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
71 */
72 protected $dataMapFactory;
73
74 /**
75 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface
76 */
77 protected $queryFactory;
78
79 /**
80 * The TYPO3 reference index object
81 *
82 * @var \TYPO3\CMS\Core\Database\ReferenceIndex
83 */
84 protected $referenceIndex;
85
86 /**
87 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
88 */
89 protected $objectManager;
90
91 /**
92 * Injects the identity map
93 *
94 * @param \TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap $identityMap
95 * @return void
96 */
97 public function injectIdentityMap(\TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap $identityMap) {
98 $this->identityMap = $identityMap;
99 }
100
101 /**
102 * Injects the persistence session
103 *
104 * @param \TYPO3\CMS\Extbase\Persistence\Generic\Session $persistenceSession
105 * @return void
106 */
107 public function injectSession(\TYPO3\CMS\Extbase\Persistence\Generic\Session $persistenceSession) {
108 $this->persistenceSession = $persistenceSession;
109 }
110
111 /**
112 * Injects the Reflection Service
113 *
114 * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService
115 * @return void
116 */
117 public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService) {
118 $this->reflectionService = $reflectionService;
119 }
120
121 /**
122 * Injects the DataMap Factory
123 *
124 * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory
125 * @return void
126 */
127 public function injectDataMapFactory(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory) {
128 $this->dataMapFactory = $dataMapFactory;
129 }
130
131 /**
132 * Injects the Query Factory
133 *
134 * @param \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface $queryFactory
135 */
136 public function injectQueryFactory(\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface $queryFactory) {
137 $this->queryFactory = $queryFactory;
138 }
139
140 /**
141 * Sets the query object model factory
142 *
143 * @param \TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelFactory $qomFactory
144 * @return void
145 */
146 public function injectQomFactory(\TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelFactory $qomFactory) {
147 $this->qomFactory = $qomFactory;
148 }
149
150 /**
151 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
152 * @return void
153 */
154 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) {
155 $this->objectManager = $objectManager;
156 }
157
158 /**
159 * Maps the given rows on objects
160 *
161 * @param string $className The name of the class
162 * @param array $rows An array of arrays with field_name => value pairs
163 * @return array An array of objects of the given class
164 */
165 public function map($className, array $rows) {
166 $objects = array();
167 foreach ($rows as $row) {
168 $objects[] = $this->mapSingleRow($this->getTargetType($className, $row), $row);
169 }
170 return $objects;
171 }
172
173 /**
174 * Returns the target type for the given row.
175 *
176 * @param string $className The name of the class
177 * @param array $row A single array with field_name => value pairs
178 * @return string The target type (a class name)
179 */
180 public function getTargetType($className, array $row) {
181 $dataMap = $this->getDataMap($className);
182 $targetType = $className;
183 if ($dataMap->getRecordTypeColumnName() !== NULL) {
184 foreach ($dataMap->getSubclasses() as $subclassName) {
185 $recordSubtype = $this->getDataMap($subclassName)->getRecordType();
186 if ($row[$dataMap->getRecordTypeColumnName()] === $recordSubtype) {
187 $targetType = $subclassName;
188 break;
189 }
190 }
191 }
192 return $targetType;
193 }
194
195 /**
196 * Maps a single row on an object of the given class
197 *
198 * @param string $className The name of the target class
199 * @param array $row A single array with field_name => value pairs
200 * @return object An object of the given class
201 */
202 protected function mapSingleRow($className, array $row) {
203 if ($this->identityMap->hasIdentifier($row['uid'], $className)) {
204 $object = $this->identityMap->getObjectByIdentifier($row['uid'], $className);
205 } else {
206 $object = $this->createEmptyObject($className);
207 $this->identityMap->registerObject($object, $row['uid']);
208 $this->thawProperties($object, $row);
209 $object->_memorizeCleanState();
210 $this->persistenceSession->registerReconstitutedEntity($object);
211 }
212 return $object;
213 }
214
215 /**
216 * Creates a skeleton of the specified object
217 *
218 * @param string $className Name of the class to create a skeleton for
219 * @throws \TYPO3\CMS\Extbase\Object\Exception\CannotReconstituteObjectException
220 * @return object The object skeleton
221 */
222 protected function createEmptyObject($className) {
223 // Note: The class_implements() function also invokes autoload to assure that the interfaces
224 // and the class are loaded. Would end up with __PHP_Incomplete_Class without it.
225 if (!in_array('TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface', class_implements($className))) {
226 throw new \TYPO3\CMS\Extbase\Object\Exception\CannotReconstituteObjectException('Cannot create empty instance of the class "' . $className . '" because it does not implement the TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface.', 1234386924);
227 }
228 $object = $this->objectManager->getEmptyObject($className);
229 return $object;
230 }
231
232 /**
233 * Sets the given properties on the object.
234 *
235 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object The object to set properties on
236 * @param array $row
237 * @return void
238 */
239 protected function thawProperties(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, array $row) {
240 $className = get_class($object);
241 $dataMap = $this->getDataMap($className);
242 $object->_setProperty('uid', intval($row['uid']));
243 $object->_setProperty('pid', intval($row['pid']));
244 $object->_setProperty('_localizedUid', intval($row['uid']));
245 if ($dataMap->getLanguageIdColumnName() !== NULL) {
246 $object->_setProperty('_languageUid', intval($row[$dataMap->getLanguageIdColumnName()]));
247 if (isset($row['_LOCALIZED_UID'])) {
248 $object->_setProperty('_localizedUid', intval($row['_LOCALIZED_UID']));
249 }
250 }
251 $properties = $object->_getProperties();
252 foreach ($properties as $propertyName => $propertyValue) {
253 if (!$dataMap->isPersistableProperty($propertyName)) {
254 continue;
255 }
256 $columnMap = $dataMap->getColumnMap($propertyName);
257 $columnName = $columnMap->getColumnName();
258 $propertyData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName);
259 $propertyValue = NULL;
260 if ($row[$columnName] !== NULL) {
261 switch ($propertyData['type']) {
262 case 'integer':
263 $propertyValue = (integer) $row[$columnName];
264 break;
265 case 'float':
266 $propertyValue = (double) $row[$columnName];
267 break;
268 case 'boolean':
269 $propertyValue = (boolean) $row[$columnName];
270 break;
271 case 'string':
272 $propertyValue = (string) $row[$columnName];
273 break;
274 case 'array':
275 // $propertyValue = $this->mapArray($row[$columnName]); // Not supported, yet!
276 break;
277 case 'SplObjectStorage':
278 case 'Tx_Extbase_Persistence_ObjectStorage':
279 case 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage':
280 $propertyValue = $this->mapResultToPropertyValue($object, $propertyName, $this->fetchRelated($object, $propertyName, $row[$columnName]));
281 break;
282 default:
283 if ($propertyData['type'] === 'DateTime' || in_array('DateTime', class_parents($propertyData['type']))) {
284 $propertyValue = $this->mapDateTime($row[$columnName], $columnMap->getDateTimeStorageFormat());
285 } else {
286 $propertyValue = $this->mapResultToPropertyValue($object, $propertyName, $this->fetchRelated($object, $propertyName, $row[$columnName]));
287 }
288 }
289 }
290 if ($propertyValue !== NULL) {
291 $object->_setProperty($propertyName, $propertyValue);
292 }
293 }
294 }
295
296 /**
297 * Creates a DateTime from an unix timestamp or date/datetime value.
298 * If the input is empty, NULL is returned.
299 *
300 * @param integer|string $value Unix timestamp or date/datetime value
301 * @param NULL|string $storageFormat Storage format for native date/datetime fields
302 * @return \DateTime
303 */
304 protected function mapDateTime($value, $storageFormat = NULL) {
305 if (empty($value) || $value === '0000-00-00' || $value === '0000-00-00 00:00:00') {
306 // 0 -> NULL !!!
307 return NULL;
308 } elseif ($storageFormat === 'date' || $storageFormat === 'datetime') {
309 // native date/datetime values are stored in UTC
310 $utcTimeZone = new \DateTimeZone('UTC');
311 $utcDateTime = new \DateTime($value, $utcTimeZone);
312 $currentTimeZone = new \DateTimeZone(date_default_timezone_get());
313 return $utcDateTime->setTimezone($currentTimeZone);
314 } else {
315 return new \DateTime(date('c', $value));
316 }
317 }
318
319 /**
320 * Fetches a collection of objects related to a property of a parent object
321 *
322 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject The object instance this proxy is part of
323 * @param string $propertyName The name of the proxied property in it's parent
324 * @param mixed $fieldValue The raw field value.
325 * @param boolean $enableLazyLoading A flag indication if the related objects should be lazy loaded
326 * @return \TYPO3\CMS\Extbase\Persistence\Generic\LazyObjectStorage|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface The result
327 */
328 public function fetchRelated(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $enableLazyLoading = TRUE) {
329 $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
330 if ($enableLazyLoading === TRUE && $propertyMetaData['lazy']) {
331 if (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
332 $result = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\LazyObjectStorage', $parentObject, $propertyName, $fieldValue);
333 } else {
334 if (empty($fieldValue)) {
335 $result = NULL;
336 } else {
337 $result = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\LazyLoadingProxy', $parentObject, $propertyName, $fieldValue);
338 }
339 }
340 } else {
341 $result = $this->fetchRelatedEager($parentObject, $propertyName, $fieldValue);
342 }
343 return $result;
344 }
345
346 /**
347 * Fetches the related objects from the storage backend.
348 *
349 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject The object instance this proxy is part of
350 * @param string $propertyName The name of the proxied property in it's parent
351 * @param mixed $fieldValue The raw field value.
352 * @return mixed
353 */
354 protected function fetchRelatedEager(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
355 return $fieldValue === '' ? $this->getEmptyRelationValue($parentObject, $propertyName) : $this->getNonEmptyRelationValue($parentObject, $propertyName, $fieldValue);
356 }
357
358 /**
359 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
360 * @param string $propertyName
361 * @return array|NULL
362 */
363 protected function getEmptyRelationValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName) {
364 $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
365 $relatesToOne = $columnMap->getTypeOfRelation() == \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE;
366 return $relatesToOne ? NULL : array();
367 }
368
369 /**
370 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
371 * @param string $propertyName
372 * @param string $fieldValue
373 * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
374 */
375 protected function getNonEmptyRelationValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue) {
376 $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
377 return $query->execute();
378 }
379
380 /**
381 * Builds and returns the prepared query, ready to be executed.
382 *
383 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
384 * @param string $propertyName
385 * @param string $fieldValue
386 * @return \TYPO3\CMS\Extbase\Persistence\QueryInterface
387 */
388 protected function getPreparedQuery(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
389 $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
390 $type = $this->getType(get_class($parentObject), $propertyName);
391 $query = $this->queryFactory->create($type);
392 $query->getQuerySettings()->setRespectStoragePage(FALSE);
393 $query->getQuerySettings()->setRespectSysLanguage(FALSE);
394 if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
395 if ($columnMap->getChildSortByFieldName() !== NULL) {
396 $query->setOrderings(array($columnMap->getChildSortByFieldName() => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));
397 }
398 } elseif ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
399 $query->setSource($this->getSource($parentObject, $propertyName));
400 if ($columnMap->getChildSortByFieldName() !== NULL) {
401 $query->setOrderings(array($columnMap->getChildSortByFieldName() => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));
402 }
403 }
404 $query->matching($this->getConstraint($query, $parentObject, $propertyName, $fieldValue, $columnMap->getRelationTableMatchFields()));
405 return $query;
406 }
407
408 /**
409 * Builds and returns the constraint for multi value properties.
410 *
411 * @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
412 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
413 * @param string $propertyName
414 * @param string $fieldValue
415 * @param array $relationTableMatchFields
416 * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface $constraint
417 */
418 protected function getConstraint(\TYPO3\CMS\Extbase\Persistence\QueryInterface $query, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $relationTableMatchFields = array()) {
419 $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
420 if ($columnMap->getParentKeyFieldName() !== NULL) {
421 $constraint = $query->equals($columnMap->getParentKeyFieldName(), $parentObject);
422 if ($columnMap->getParentTableFieldName() !== NULL) {
423 $constraint = $query->logicalAnd($constraint, $query->equals($columnMap->getParentTableFieldName(), $this->getDataMap(get_class($parentObject))->getTableName()));
424 }
425 } else {
426 $constraint = $query->in('uid', \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $fieldValue));
427 }
428 if (count($relationTableMatchFields) > 0) {
429 foreach ($relationTableMatchFields as $relationTableMatchFieldName => $relationTableMatchFieldValue) {
430 $constraint = $query->logicalAnd($constraint, $query->equals($relationTableMatchFieldName, $relationTableMatchFieldValue));
431 }
432 }
433 return $constraint;
434 }
435
436 /**
437 * Builds and returns the source to build a join for a m:n relation.
438 *
439 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
440 * @param string $propertyName
441 * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source
442 */
443 protected function getSource(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName) {
444 $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
445 $left = $this->qomFactory->selector(NULL, $columnMap->getRelationTableName());
446 $childClassName = $this->getType(get_class($parentObject), $propertyName);
447 $right = $this->qomFactory->selector($childClassName, $columnMap->getChildTableName());
448 $joinCondition = $this->qomFactory->equiJoinCondition($columnMap->getRelationTableName(), $columnMap->getChildKeyFieldName(), $columnMap->getChildTableName(), 'uid');
449 $source = $this->qomFactory->join($left, $right, \TYPO3\CMS\Extbase\Persistence\Generic\Query::JCR_JOIN_TYPE_INNER, $joinCondition);
450 return $source;
451 }
452
453 /**
454 * Returns the given result as property value of the specified property type.
455 *
456 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
457 * @param string $propertyName
458 * @param mixed $result The result
459 * @return mixed
460 */
461 public function mapResultToPropertyValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $result) {
462 if ($result instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LoadingStrategyInterface) {
463 $propertyValue = $result;
464 } else {
465 $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
466 if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'SplObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage', 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage'), TRUE)) {
467 $objects = array();
468 foreach ($result as $value) {
469 $objects[] = $value;
470 }
471 if ($propertyMetaData['type'] === 'ArrayObject') {
472 $propertyValue = new \ArrayObject($objects);
473 } elseif (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
474 $propertyValue = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
475 foreach ($objects as $object) {
476 $propertyValue->attach($object);
477 }
478 $propertyValue->_memorizeCleanState();
479 } else {
480 $propertyValue = $objects;
481 }
482 } elseif (strpbrk($propertyMetaData['type'], '_\\') !== FALSE) {
483 if (is_object($result) && $result instanceof \TYPO3\CMS\Extbase\Persistence\QueryResultInterface) {
484 $propertyValue = $result->getFirst();
485 } else {
486 $propertyValue = $result;
487 }
488 }
489 }
490 return $propertyValue;
491 }
492
493 /**
494 * Counts the number of related objects assigned to a property of a parent object
495 *
496 * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject The object instance this proxy is part of
497 * @param string $propertyName The name of the proxied property in it's parent
498 * @param mixed $fieldValue The raw field value.
499 * @return integer
500 */
501 public function countRelated(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
502 $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
503 return $query->execute()->count();
504 }
505
506 /**
507 * Delegates the call to the Data Map.
508 * Returns TRUE if the property is persistable (configured in $TCA)
509 *
510 * @param string $className The property name
511 * @param string $propertyName The property name
512 * @return boolean TRUE if the property is persistable (configured in $TCA)
513 */
514 public function isPersistableProperty($className, $propertyName) {
515 $dataMap = $this->getDataMap($className);
516 return $dataMap->isPersistableProperty($propertyName);
517 }
518
519 /**
520 * Returns a data map for a given class name
521 *
522 * @param string $className The class name you want to fetch the Data Map for
523 * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception
524 * @return \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap The data map
525 */
526 public function getDataMap($className) {
527 if (!is_string($className) || strlen($className) === 0) {
528 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('No class name was given to retrieve the Data Map for.', 1251315965);
529 }
530 if (!isset($this->dataMaps[$className])) {
531 $this->dataMaps[$className] = $this->dataMapFactory->buildDataMap($className);
532 }
533 return $this->dataMaps[$className];
534 }
535
536 /**
537 * Returns the selector (table) name for a given class name.
538 *
539 * @param string $className
540 * @return string The selector name
541 */
542 public function convertClassNameToTableName($className = NULL) {
543 if ($className !== NULL) {
544 $tableName = $this->getDataMap($className)->getTableName();
545 } else {
546 $tableName = strtolower($className);
547 }
548 return $tableName;
549 }
550
551 /**
552 * Returns the column name for a given property name of the specified class.
553 *
554 * @param string $propertyName
555 * @param string $className
556 * @return string The column name
557 */
558 public function convertPropertyNameToColumnName($propertyName, $className = NULL) {
559 if (!empty($className)) {
560 $dataMap = $this->getDataMap($className);
561 if ($dataMap !== NULL) {
562 $columnMap = $dataMap->getColumnMap($propertyName);
563 if ($columnMap !== NULL) {
564 return $columnMap->getColumnName();
565 }
566 }
567 }
568 return \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($propertyName);
569 }
570
571 /**
572 * Returns the type of a child object.
573 *
574 * @param string $parentClassName The class name of the object this proxy is part of
575 * @param string $propertyName The name of the proxied property in it's parent
576 * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException
577 * @return string The class name of the child object
578 */
579 public function getType($parentClassName, $propertyName) {
580 $propertyMetaData = $this->reflectionService->getClassSchema($parentClassName)->getProperty($propertyName);
581 if (!empty($propertyMetaData['elementType'])) {
582 $type = $propertyMetaData['elementType'];
583 } elseif (!empty($propertyMetaData['type'])) {
584 $type = $propertyMetaData['type'];
585 } else {
586 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('Could not determine the child object type.', 1251315967);
587 }
588 return $type;
589 }
590 }
591
592 ?>