TYPO3 CMS  TYPO3_6-2
DataMapper.php
Go to the documentation of this file.
1 <?php
3 
18 
23 
28  protected $identityMap;
29 
34  protected $reflectionService;
35 
40  protected $qomFactory;
41 
47 
53  protected $pageSelectObject;
54 
60  protected $dataMaps = array();
61 
66  protected $dataMapFactory;
67 
72  protected $queryFactory;
73 
79  protected $referenceIndex;
80 
85  protected $objectManager;
86 
94  public function map($className, array $rows) {
95  $objects = array();
96  foreach ($rows as $row) {
97  $objects[] = $this->mapSingleRow($this->getTargetType($className, $row), $row);
98  }
99  return $objects;
100  }
101 
109  public function getTargetType($className, array $row) {
110  $dataMap = $this->getDataMap($className);
111  $targetType = $className;
112  if ($dataMap->getRecordTypeColumnName() !== NULL) {
113  foreach ($dataMap->getSubclasses() as $subclassName) {
114  $recordSubtype = $this->getDataMap($subclassName)->getRecordType();
115  if ($row[$dataMap->getRecordTypeColumnName()] === $recordSubtype) {
116  $targetType = $subclassName;
117  break;
118  }
119  }
120  }
121  return $targetType;
122  }
123 
131  protected function mapSingleRow($className, array $row) {
132  if ($this->identityMap->hasIdentifier($row['uid'], $className)) {
133  $object = $this->identityMap->getObjectByIdentifier($row['uid'], $className);
134  } else {
135  $object = $this->createEmptyObject($className);
136  $this->identityMap->registerObject($object, $row['uid']);
137  $this->thawProperties($object, $row);
138  $object->_memorizeCleanState();
139  $this->persistenceSession->registerReconstitutedEntity($object);
140  }
141  return $object;
142  }
143 
151  protected function createEmptyObject($className) {
152  // Note: The class_implements() function also invokes autoload to assure that the interfaces
153  // and the class are loaded. Would end up with __PHP_Incomplete_Class without it.
154  if (!in_array('TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface', class_implements($className))) {
155  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);
156  }
157  $object = $this->objectManager->getEmptyObject($className);
158  return $object;
159  }
160 
168  protected function thawProperties(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, array $row) {
169  $className = get_class($object);
170  $classSchema = $this->reflectionService->getClassSchema($className);
171  $dataMap = $this->getDataMap($className);
172  $object->_setProperty('uid', (int)$row['uid']);
173  $object->_setProperty('pid', (int)$row['pid']);
174  $object->_setProperty('_localizedUid', (int)$row['uid']);
175  $object->_setProperty('_versionedUid', (int)$row['uid']);
176  if ($dataMap->getLanguageIdColumnName() !== NULL) {
177  $object->_setProperty('_languageUid', (int)$row[$dataMap->getLanguageIdColumnName()]);
178  if (isset($row['_LOCALIZED_UID'])) {
179  $object->_setProperty('_localizedUid', (int)$row['_LOCALIZED_UID']);
180  }
181  }
182  if (!empty($row['_ORIG_uid']) && !empty($GLOBALS['TCA'][$dataMap->getTableName()]['ctrl']['versioningWS'])) {
183  $object->_setProperty('_versionedUid', (int)$row['_ORIG_uid']);
184  }
185  $properties = $object->_getProperties();
186  foreach ($properties as $propertyName => $propertyValue) {
187  if (!$dataMap->isPersistableProperty($propertyName)) {
188  continue;
189  }
190  $columnMap = $dataMap->getColumnMap($propertyName);
191  $columnName = $columnMap->getColumnName();
192  $propertyData = $classSchema->getProperty($propertyName);
193  $propertyValue = NULL;
194  if ($row[$columnName] !== NULL) {
195  switch ($propertyData['type']) {
196  case 'integer':
197  $propertyValue = (int)$row[$columnName];
198  break;
199  case 'float':
200  $propertyValue = (double)$row[$columnName];
201  break;
202  case 'boolean':
203  $propertyValue = (bool)$row[$columnName];
204  break;
205  case 'string':
206  $propertyValue = (string)$row[$columnName];
207  break;
208  case 'array':
209  // $propertyValue = $this->mapArray($row[$columnName]); // Not supported, yet!
210  break;
211  case 'SplObjectStorage':
212  case 'Tx_Extbase_Persistence_ObjectStorage':
213  case 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage':
214  $propertyValue = $this->mapResultToPropertyValue(
215  $object,
216  $propertyName,
217  $this->fetchRelated($object, $propertyName, $row[$columnName])
218  );
219  break;
220  default:
221  if ($propertyData['type'] === 'DateTime' || in_array('DateTime', class_parents($propertyData['type']))) {
222  $propertyValue = $this->mapDateTime($row[$columnName], $columnMap->getDateTimeStorageFormat(), $propertyData['type']);
223  } elseif (TypeHandlingUtility::isCoreType($propertyData['type'])) {
224  $propertyValue = $this->mapCoreType($propertyData['type'], $row[$columnName]);
225  } else {
226  $propertyValue = $this->mapObjectToClassProperty(
227  $object,
228  $propertyName,
229  $row[$columnName]
230  );
231  }
232 
233  }
234  }
235  if ($propertyValue !== NULL) {
236  $object->_setProperty($propertyName, $propertyValue);
237  }
238  }
239  }
240 
248  protected function mapCoreType($type, $value) {
249  return new $type($value);
250  }
251 
261  protected function mapDateTime($value, $storageFormat = NULL, $targetType = 'DateTime') {
262  if (empty($value) || $value === '0000-00-00' || $value === '0000-00-00 00:00:00') {
263  // 0 -> NULL !!!
264  return NULL;
265  } elseif ($storageFormat === 'date' || $storageFormat === 'datetime') {
266  // native date/datetime values are stored in UTC
267  $utcTimeZone = new \DateTimeZone('UTC');
268  $utcDateTime = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($targetType, $value, $utcTimeZone);
269  $currentTimeZone = new \DateTimeZone(date_default_timezone_get());
270  return $utcDateTime->setTimezone($currentTimeZone);
271  } else {
272  return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($targetType, date('c', $value));
273  }
274  }
275 
285  public function fetchRelated(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $enableLazyLoading = TRUE) {
286  $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
287  if ($enableLazyLoading === TRUE && $propertyMetaData['lazy']) {
288  if (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
289  $result = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\LazyObjectStorage', $parentObject, $propertyName, $fieldValue);
290  } else {
291  if (empty($fieldValue)) {
292  $result = NULL;
293  } else {
294  $result = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\LazyLoadingProxy', $parentObject, $propertyName, $fieldValue);
295  }
296  }
297  } else {
298  $result = $this->fetchRelatedEager($parentObject, $propertyName, $fieldValue);
299  }
300  return $result;
301  }
302 
311  protected function fetchRelatedEager(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
312  return $fieldValue === '' ? $this->getEmptyRelationValue($parentObject, $propertyName) : $this->getNonEmptyRelationValue($parentObject, $propertyName, $fieldValue);
313  }
314 
320  protected function getEmptyRelationValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName) {
321  $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
322  $relatesToOne = $columnMap->getTypeOfRelation() == \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE;
323  return $relatesToOne ? NULL : array();
324  }
325 
332  protected function getNonEmptyRelationValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue) {
333  $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
334  return $query->execute();
335  }
336 
345  protected function getPreparedQuery(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
346  $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
347  $type = $this->getType(get_class($parentObject), $propertyName);
348  $query = $this->queryFactory->create($type);
349  $query->getQuerySettings()->setRespectStoragePage(FALSE);
350  $query->getQuerySettings()->setRespectSysLanguage(FALSE);
351  if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
352  if ($columnMap->getChildSortByFieldName() !== NULL) {
353  $query->setOrderings(array($columnMap->getChildSortByFieldName() => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));
354  }
356  $query->setSource($this->getSource($parentObject, $propertyName));
357  if ($columnMap->getChildSortByFieldName() !== NULL) {
358  $query->setOrderings(array($columnMap->getChildSortByFieldName() => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));
359  }
360  }
361  $query->matching($this->getConstraint($query, $parentObject, $propertyName, $fieldValue, $columnMap->getRelationTableMatchFields()));
362  return $query;
363  }
364 
375  protected function getConstraint(\TYPO3\CMS\Extbase\Persistence\QueryInterface $query, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $relationTableMatchFields = array()) {
376  $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
377  if ($columnMap->getParentKeyFieldName() !== NULL) {
378  $constraint = $query->equals($columnMap->getParentKeyFieldName(), $parentObject);
379  if ($columnMap->getParentTableFieldName() !== NULL) {
380  $constraint = $query->logicalAnd($constraint, $query->equals($columnMap->getParentTableFieldName(), $this->getDataMap(get_class($parentObject))->getTableName()));
381  }
382  } else {
383  $constraint = $query->in('uid', \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $fieldValue));
384  }
385  if (count($relationTableMatchFields) > 0) {
386  foreach ($relationTableMatchFields as $relationTableMatchFieldName => $relationTableMatchFieldValue) {
387  $constraint = $query->logicalAnd($constraint, $query->equals($relationTableMatchFieldName, $relationTableMatchFieldValue));
388  }
389  }
390  return $constraint;
391  }
392 
400  protected function getSource(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName) {
401  $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
402  $left = $this->qomFactory->selector(NULL, $columnMap->getRelationTableName());
403  $childClassName = $this->getType(get_class($parentObject), $propertyName);
404  $right = $this->qomFactory->selector($childClassName, $columnMap->getChildTableName());
405  $joinCondition = $this->qomFactory->equiJoinCondition($columnMap->getRelationTableName(), $columnMap->getChildKeyFieldName(), $columnMap->getChildTableName(), 'uid');
406  $source = $this->qomFactory->join($left, $right, \TYPO3\CMS\Extbase\Persistence\Generic\Query::JCR_JOIN_TYPE_INNER, $joinCondition);
407  return $source;
408  }
409 
425  protected function mapObjectToClassProperty(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue) {
426  if ($this->propertyMapsByForeignKey($parentObject, $propertyName)) {
427  $result = $this->fetchRelated($parentObject, $propertyName, $fieldValue);
428  $propertyValue = $this->mapResultToPropertyValue($parentObject, $propertyName, $result);
429  } else {
430  if ($fieldValue === '') {
431  $propertyValue = $this->getEmptyRelationValue($parentObject, $propertyName);
432  } else {
433  $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
434  if ($this->persistenceSession->hasIdentifier($fieldValue, $propertyMetaData['type'])) {
435  $propertyValue = $this->persistenceSession->getObjectByIdentifier($fieldValue, $propertyMetaData['type']);
436  } else {
437  $result = $this->fetchRelated($parentObject, $propertyName, $fieldValue);
438  $propertyValue = $this->mapResultToPropertyValue($parentObject, $propertyName, $result);
439  }
440  }
441  }
442 
443  return $propertyValue;
444  }
445 
453  protected function propertyMapsByForeignKey(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName) {
454  $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
455  return ($columnMap->getParentKeyFieldName() !== NULL);
456  }
457 
466  public function mapResultToPropertyValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $result) {
467  $propertyValue = NULL;
468  if ($result instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LoadingStrategyInterface) {
469  $propertyValue = $result;
470  } else {
471  $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
472  if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'SplObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage', 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage'), TRUE)) {
473  $objects = array();
474  foreach ($result as $value) {
475  $objects[] = $value;
476  }
477  if ($propertyMetaData['type'] === 'ArrayObject') {
478  $propertyValue = new \ArrayObject($objects);
479  } elseif (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
480  $propertyValue = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
481  foreach ($objects as $object) {
482  $propertyValue->attach($object);
483  }
484  $propertyValue->_memorizeCleanState();
485  } else {
486  $propertyValue = $objects;
487  }
488  } elseif (strpbrk($propertyMetaData['type'], '_\\') !== FALSE) {
489  if (is_object($result) && $result instanceof \TYPO3\CMS\Extbase\Persistence\QueryResultInterface) {
490  $propertyValue = $result->getFirst();
491  } else {
492  $propertyValue = $result;
493  }
494  }
495  }
496  return $propertyValue;
497  }
498 
507  public function countRelated(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
508  $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
509  return $query->execute()->count();
510  }
511 
520  public function isPersistableProperty($className, $propertyName) {
521  $dataMap = $this->getDataMap($className);
522  return $dataMap->isPersistableProperty($propertyName);
523  }
524 
532  public function getDataMap($className) {
533  if (!is_string($className) || strlen($className) === 0) {
534  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('No class name was given to retrieve the Data Map for.', 1251315965);
535  }
536  if (!isset($this->dataMaps[$className])) {
537  $this->dataMaps[$className] = $this->dataMapFactory->buildDataMap($className);
538  }
539  return $this->dataMaps[$className];
540  }
541 
548  public function convertClassNameToTableName($className = NULL) {
549  if ($className !== NULL) {
550  $tableName = $this->getDataMap($className)->getTableName();
551  } else {
552  $tableName = strtolower($className);
553  }
554  return $tableName;
555  }
556 
564  public function convertPropertyNameToColumnName($propertyName, $className = NULL) {
565  if (!empty($className)) {
566  $dataMap = $this->getDataMap($className);
567  if ($dataMap !== NULL) {
568  $columnMap = $dataMap->getColumnMap($propertyName);
569  if ($columnMap !== NULL) {
570  return $columnMap->getColumnName();
571  }
572  }
573  }
574  return \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($propertyName);
575  }
576 
585  public function getType($parentClassName, $propertyName) {
586  $propertyMetaData = $this->reflectionService->getClassSchema($parentClassName)->getProperty($propertyName);
587  if (!empty($propertyMetaData['elementType'])) {
588  $type = $propertyMetaData['elementType'];
589  } elseif (!empty($propertyMetaData['type'])) {
590  $type = $propertyMetaData['type'];
591  } else {
592  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('Could not determine the child object type.', 1251315967);
593  }
594  return $type;
595  }
596 }
getSource(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName)
Definition: DataMapper.php:400
getNonEmptyRelationValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue)
Definition: DataMapper.php:332
static intExplode($delimiter, $string, $removeEmptyValues=FALSE, $limit=0)
thawProperties(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, array $row)
Definition: DataMapper.php:168
getEmptyRelationValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName)
Definition: DataMapper.php:320
fetchRelatedEager(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue='')
Definition: DataMapper.php:311
mapResultToPropertyValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $result)
Definition: DataMapper.php:466
mapObjectToClassProperty(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue)
Definition: DataMapper.php:425
countRelated(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue='')
Definition: DataMapper.php:507
propertyMapsByForeignKey(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName)
Definition: DataMapper.php:453
convertPropertyNameToColumnName($propertyName, $className=NULL)
Definition: DataMapper.php:564
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
mapDateTime($value, $storageFormat=NULL, $targetType='DateTime')
Definition: DataMapper.php:261
fetchRelated(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue='', $enableLazyLoading=TRUE)
Definition: DataMapper.php:285
getConstraint(\TYPO3\CMS\Extbase\Persistence\QueryInterface $query, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue='', $relationTableMatchFields=array())
Definition: DataMapper.php:375
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
getPreparedQuery(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue='')
Definition: DataMapper.php:345