‪TYPO3CMS  ‪main
DataMapper.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Doctrine\Instantiator\InstantiatorInterface;
21 use Psr\EventDispatcher\EventDispatcherInterface;
22 use Symfony\Component\PropertyInfo\Type;
53 
59 {
63  protected ‪$query;
64 
65  public function ‪__construct(
66  private readonly ‪ReflectionService $reflectionService,
67  private readonly ‪QueryObjectModelFactory $qomFactory,
68  private readonly ‪Session $persistenceSession,
69  private readonly ‪DataMapFactory $dataMapFactory,
70  private readonly ‪QueryFactoryInterface $queryFactory,
71  private readonly EventDispatcherInterface $eventDispatcher,
72  private readonly InstantiatorInterface $instantiator,
73  ) {}
74 
75  public function ‪setQuery(‪QueryInterface ‪$query): void
76  {
77  $this->query = ‪$query;
78  }
79 
90  public function ‪map($className, array $rows)
91  {
92  $objects = [];
93  foreach ($rows as $row) {
94  $objects[] = $this->‪mapSingleRow($this->‪getTargetType($className, $row), $row);
95  }
96  return $objects;
97  }
98 
108  public function ‪getTargetType($className, array $row)
109  {
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 ((string)$row[$dataMap->getRecordTypeColumnName()] === (string)$recordSubtype) {
116  $targetType = $subclassName;
117  break;
118  }
119  }
120  }
121  return $targetType;
122  }
123 
134  protected function ‪mapSingleRow($className, array $row)
135  {
136  // @todo: this also needs to contain the query's languageAspect with its configuration
137  // which should be changed along with https://review.typo3.org/c/Packages/TYPO3.CMS/+/75093
138  ‪$identifier = $row['uid'] . (isset($row['_LOCALIZED_UID']) ? '_' . $row['_LOCALIZED_UID'] : '');
139  if ($this->persistenceSession->hasIdentifier(‪$identifier, $className)) {
140  $object = $this->persistenceSession->getObjectByIdentifier(‪$identifier, $className);
141  } else {
142  $object = $this->‪createEmptyObject($className);
143  $this->persistenceSession->registerObject($object, ‪$identifier);
144  $this->‪thawProperties($object, $row);
145  $event = new AfterObjectThawedEvent($object, $row);
146  $this->eventDispatcher->dispatch($event);
147  $object->_memorizeCleanState();
148  $this->persistenceSession->registerReconstitutedEntity($object);
149  }
150  return $object;
151  }
152 
165  protected function ‪createEmptyObject(string $className): DomainObjectInterface
166  {
167  // Note: The class_implements() function also invokes autoload to assure that the interfaces
168  // and the class are loaded. Would end up with __PHP_Incomplete_Class without it.
169  if (!in_array(DomainObjectInterface::class, class_implements($className) ?: [])) {
170  throw new InvalidClassException('Cannot create empty instance of the class "' . $className
171  . '" because it does not implement the TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface.', 1234386924);
172  }
173  // Use GU::getClassName() to obey class implementation overrides.
174  $object = $this->instantiator->instantiate(GeneralUtility::getClassName($className));
175  if (is_callable($callable = [$object, 'initializeObject'])) {
176  $callable();
177  }
178  return $object;
179  }
180 
188  protected function ‪thawProperties(DomainObjectInterface $object, array $row)
189  {
190  $className = get_class($object);
191  $classSchema = $this->reflectionService->getClassSchema($className);
192  $dataMap = $this->‪getDataMap($className);
193  $object->_setProperty(‪AbstractDomainObject::PROPERTY_UID, (int)$row['uid']);
194  $object->_setProperty(‪AbstractDomainObject::PROPERTY_PID, (int)($row['pid'] ?? 0));
195  $object->_setProperty(‪AbstractDomainObject::PROPERTY_LOCALIZED_UID, (int)$row['uid']);
196  $object->_setProperty(‪AbstractDomainObject::PROPERTY_VERSIONED_UID, (int)$row['uid']);
197  if ($dataMap->getLanguageIdColumnName() !== null) {
198  $object->_setProperty(‪AbstractDomainObject::PROPERTY_LANGUAGE_UID, (int)($row[$dataMap->getLanguageIdColumnName()] ?? 0));
199  if (isset($row['_LOCALIZED_UID'])) {
200  $object->_setProperty(‪AbstractDomainObject::PROPERTY_LOCALIZED_UID, (int)$row['_LOCALIZED_UID']);
201  }
202  }
203  if (!empty($row['_ORIG_uid']) && !empty(‪$GLOBALS['TCA'][$dataMap->getTableName()]['ctrl']['versioningWS'])) {
204  $object->_setProperty(‪AbstractDomainObject::PROPERTY_VERSIONED_UID, (int)$row['_ORIG_uid']);
205  }
206  foreach ($classSchema->getDomainObjectProperties() as $property) {
207  $propertyName = $property->getName();
208  if (!$dataMap->isPersistableProperty($propertyName)) {
209  continue;
210  }
211  $columnMap = $dataMap->getColumnMap($propertyName);
212  if (!$columnMap instanceof ColumnMap) {
213  continue;
214  }
215 
216  $columnName = $columnMap->‪getColumnName();
217  if (!isset($row[$columnName])) {
218  continue;
219  }
220 
221  $propertyValue = $row[$columnName];
222 
223  $nonProxyPropertyTypes = $property->getFilteredTypes([$property, 'filterLazyLoadingProxyAndLazyObjectStorage']);
224  if ($nonProxyPropertyTypes === []) {
225  throw new UnknownPropertyTypeException(
226  'The type of property ' . $className . '::' . $propertyName . ' could not be identified, therefore the desired value (' .
227  var_export($propertyValue, true) . ') cannot be mapped onto it. The type of a class property is usually defined via property types or php doc blocks. ' .
228  'Make sure the property has a property type or valid @var tag set which defines the type.',
229  1579965021
230  );
231  }
232 
233  if (count($nonProxyPropertyTypes) > 1) {
234  throw new UnknownPropertyTypeException(
235  'The type of property ' . $className . '::' . $propertyName . ' could not be identified because the property is defined as union or intersection type, therefore the desired value (' .
236  var_export($propertyValue, true) . ') cannot be mapped onto it. Make sure to use only a single type.',
237  1660215701
238  );
239  }
240 
241  $primaryType = $nonProxyPropertyTypes[0];
242 
243  $propertyType = $primaryType->getBuiltinType();
244  $propertyClassName = $primaryType->getClassName();
245 
246  $propertyValue = match ($propertyType) {
247  'int', 'integer' => (int)$propertyValue,
248  'bool', 'boolean' => (bool)$propertyValue,
249  'float' => (float)$propertyValue,
250  'string' => (string)$propertyValue,
251  'array' => null, // $this->mapArray($propertyValue); // Not supported, yet!
252  'object' => $this->‪thawObjectProperty($property, $columnMap, $object, $propertyName, $propertyValue, $propertyClassName),
253  default => null,
254  };
255 
256  if ($propertyValue !== null || $property->isNullable()) {
257  $object->_setProperty($propertyName, $propertyValue);
258  }
259  }
260  }
261 
266  private function ‪thawObjectProperty(
267  Property $propertySchema,
268  ColumnMap $columnMap,
269  DomainObjectInterface $parent,
270  string $propertyName,
271  mixed $propertyValue,
272  ?string $targetClassName
273  ): ?object {
274  if ($targetClassName === null) {
275  return null;
276  }
277 
278  if (is_subclass_of($targetClassName, \BackedEnum::class)) {
279  return $propertySchema->isNullable()
280  ? $targetClassName::tryFrom($propertyValue)
281  : $targetClassName::from($propertyValue);
282  }
283 
284  if (in_array($targetClassName, [\SplObjectStorage::class, ObjectStorage::class], true)) {
285  return $this->‪mapResultToPropertyValue(
286  $parent,
287  $propertyName,
288  $this->‪fetchRelated($parent, $propertyName, $propertyValue)
289  );
290  }
291 
292  if (is_subclass_of($targetClassName, \DateTimeInterface::class)) {
293  return $this->‪mapDateTime(
294  $propertyValue,
295  $columnMap->getDateTimeStorageFormat(),
296  $targetClassName
297  );
298  }
299 
300  if (‪TypeHandlingUtility::isCoreType($targetClassName)) {
301  return $this->‪mapCoreType($targetClassName, $propertyValue);
302  }
303 
304  return $this->‪mapObjectToClassProperty(
305  $parent,
306  $propertyName,
307  $propertyValue
308  );
309  }
310 
318  protected function ‪mapCoreType($type, $value)
319  {
320  return new $type($value);
321  }
322 
332  protected function ‪mapDateTime($value, $storageFormat = null, $targetType = \DateTime::class)
333  {
334  $dateTimeTypes = ‪QueryHelper::getDateTimeTypes();
335 
336  // Invalid values are converted to NULL
337  if (empty($value) || $value === '0000-00-00' || $value === '0000-00-00 00:00:00' || $value === '00:00:00') {
338  return null;
339  }
340  if (!in_array($storageFormat, $dateTimeTypes, true)) {
341  // Integer timestamps are also stored "as is" in the database, but are UTC by definition,
342  // so we convert the timestamp to an ISO representation.
343  $value = date('c', (int)$value);
344  }
345  // All date/datetime/time values are stored in the database "as is", independent of any time zone information.
346  // It is therefore only important to use the same time zone in PHP when storing and retrieving the values.
347  return GeneralUtility::makeInstance($targetType, $value);
348  }
349 
359  public function ‪fetchRelated(DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $enableLazyLoading = true)
360  {
361  $property = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
362  if ($enableLazyLoading && $property->isLazy()) {
363  if ($property->isObjectStorageType()) {
364  $result = GeneralUtility::makeInstance(LazyObjectStorage::class, $parentObject, $propertyName, $fieldValue, $this);
365  } elseif (empty($fieldValue)) {
366  $result = null;
367  } else {
368  $result = GeneralUtility::makeInstance(LazyLoadingProxy::class, $parentObject, $propertyName, $fieldValue, $this);
369  }
370  } else {
371  $result = $this->‪fetchRelatedEager($parentObject, $propertyName, $fieldValue);
372  }
373  return $result;
374  }
375 
384  protected function ‪fetchRelatedEager(DomainObjectInterface $parentObject, $propertyName, $fieldValue = '')
385  {
386  return $fieldValue === '' ? $this->‪getEmptyRelationValue($parentObject, $propertyName) : $this->‪getNonEmptyRelationValue($parentObject, $propertyName, $fieldValue);
387  }
388 
393  protected function ‪getEmptyRelationValue(DomainObjectInterface $parentObject, $propertyName)
394  {
395  $columnMap = $this->‪getDataMap(get_class($parentObject))->‪getColumnMap($propertyName);
396  $relatesToOne = $columnMap->‪getTypeOfRelation() == Relation::HAS_ONE;
397  return $relatesToOne ? null : [];
398  }
399 
405  protected function ‪getNonEmptyRelationValue(DomainObjectInterface $parentObject, $propertyName, $fieldValue)
406  {
407  ‪$query = $this->‪getPreparedQuery($parentObject, $propertyName, $fieldValue);
408  return ‪$query->‪execute();
409  }
410 
418  protected function ‪getPreparedQuery(DomainObjectInterface $parentObject, $propertyName, $fieldValue = '')
419  {
420  $dataMap = $this->‪getDataMap(get_class($parentObject));
421  $columnMap = $dataMap->getColumnMap($propertyName);
422  $type = $this->‪getType(get_class($parentObject), $propertyName);
423  ‪$query = $this->queryFactory->create($type);
424  if ($this->query && ‪$query instanceof Query) {
425  ‪$query->setParentQuery($this->query);
426  }
429 
430  $languageAspect = ‪$query->‪getQuerySettings()->‪getLanguageAspect();
431  $languageUid = $languageAspect->getContentId();
432  if ($this->query) {
433  $languageAspect = $this->query->getQuerySettings()->getLanguageAspect();
434  $languageUid = $languageAspect->getContentId();
435  if ($dataMap->getLanguageIdColumnName() !== null && !$this->query->getQuerySettings()->getRespectSysLanguage()) {
436  //pass language of parent record to child objects, so they can be overlaid correctly in case
437  //e.g. findByUid is used.
438  //the languageUid is used for getRecordOverlay later on, despite RespectSysLanguage being false
439  $parentLanguageUid = (int)$parentObject->_getProperty(‪AbstractDomainObject::PROPERTY_LANGUAGE_UID);
440  // do not override the language when the parent language uid is set to all languages (-1)
441  if ($parentLanguageUid !== -1) {
442  $languageUid = $parentLanguageUid;
443  }
444  }
445  }
446 
447  // we always want to overlay relations as most of the time they are stored in db using default language uids
448  $languageAspect = new LanguageAspect(
449  $languageUid,
450  $languageUid,
451  $languageAspect->getOverlayType() === ‪LanguageAspect::OVERLAYS_OFF ? ‪LanguageAspect::OVERLAYS_MIXED : $languageAspect->getOverlayType()
452  );
454 
455  if ($columnMap->getTypeOfRelation() === Relation::HAS_MANY) {
456  if (null !== ‪$orderings = $this->getOrderingsForColumnMap($columnMap)) {
458  }
459  } elseif ($columnMap->getTypeOfRelation() === Relation::HAS_AND_BELONGS_TO_MANY) {
460  ‪$query->‪setSource($this->‪getSource($parentObject, $propertyName));
461  if ($columnMap->getChildSortByFieldName() !== null) {
462  ‪$query->‪setOrderings([$columnMap->getChildSortByFieldName() => ‪QueryInterface::ORDER_ASCENDING]);
463  }
464  }
465  ‪$query->‪matching($this->‪getConstraint(‪$query, $parentObject, $propertyName, $fieldValue, (array)$columnMap->getRelationTableMatchFields()));
466  return ‪$query;
467  }
468 
475  public function getOrderingsForColumnMap(ColumnMap $columnMap): array|null
476  {
477  if ($columnMap->getChildSortByFieldName() !== null) {
478  return [$columnMap->getChildSortByFieldName() => ‪QueryInterface::ORDER_ASCENDING];
479  }
480 
481  if ($columnMap->getChildTableDefaultSortings() === null) {
482  return null;
483  }
484 
486  ‪$fields = ‪QueryHelper::parseOrderBy($columnMap->getChildTableDefaultSortings());
487  foreach (‪$fields as $field) {
488  $fieldName = $field[0] ?? null;
489  if ($fieldName === null) {
490  continue;
491  }
492 
493  if (($fieldOrdering = $field[1] ?? null) === null) {
495  continue;
496  }
497 
498  $fieldOrdering = strtoupper($fieldOrdering);
499  if (!in_array($fieldOrdering, [‪QueryInterface::ORDER_ASCENDING, ‪QueryInterface::ORDER_DESCENDING], true)) {
501  continue;
502  }
503 
504  ‪$orderings[$fieldName] = $fieldOrdering;
505  }
506  return ‪$orderings !== [] ? ‪$orderings : null;
507  }
508 
517  protected function ‪getConstraint(‪QueryInterface ‪$query, ‪DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $relationTableMatchFields = [])
518  {
519  $dataMap = $this->‪getDataMap(get_class($parentObject));
520  $columnMap = $dataMap->getColumnMap($propertyName);
521  $workspaceId = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'id');
522  if ($columnMap && $workspaceId > 0) {
523  $resolvedRelationIds = $this->‪resolveRelationValuesOfField($dataMap, $columnMap, $parentObject, $fieldValue, $workspaceId);
524  } else {
525  $resolvedRelationIds = [];
526  }
527  // Work with the UIDs directly in a workspace
528  if (!empty($resolvedRelationIds)) {
529  if (‪$query->‪getSource() instanceof Persistence\Generic\Qom\JoinInterface) {
530  $constraint = ‪$query->‪in(‪$query->‪getSource()->getJoinCondition()->getProperty1Name(), $resolvedRelationIds);
531  // When querying MM relations directly, Typo3DbQueryParser uses enableFields and thus, filters
532  // out versioned records by default. However, we directly query versioned UIDs here, so we want
533  // to include the versioned records explicitly.
534  if ($columnMap->getTypeOfRelation() === Relation::HAS_AND_BELONGS_TO_MANY) {
537  }
538  } else {
539  $constraint = ‪$query->‪in('uid', $resolvedRelationIds);
540  }
541  if ($columnMap->getParentTableFieldName() !== null) {
542  $constraint = ‪$query->‪logicalAnd(
543  $constraint,
544  ‪$query->‪equals($columnMap->getParentTableFieldName(), $dataMap->getTableName())
545  );
546  }
547  } elseif ($columnMap->getParentKeyFieldName() !== null) {
548  $value = $parentObject;
549  // If this a MM relation, and MM relations do not know about workspaces, the MM relations always point to the
550  // versioned record, so this must be taken into account here and the versioned record's UID must be used.
551  if ($columnMap->getTypeOfRelation() === Relation::HAS_AND_BELONGS_TO_MANY) {
552  // The versioned UID is used ideally the version ID of a translated record, so this takes precedence over the localized UID
553  if ($value->_hasProperty(‪AbstractDomainObject::PROPERTY_VERSIONED_UID) && $value->_getProperty(‪AbstractDomainObject::PROPERTY_VERSIONED_UID) > 0 && $value->_getProperty(‪AbstractDomainObject::PROPERTY_VERSIONED_UID) !== $value->getUid()) {
555  }
556  }
557  $constraint = ‪$query->‪equals($columnMap->getParentKeyFieldName(), $value);
558  if ($columnMap->getParentTableFieldName() !== null) {
559  $constraint = ‪$query->‪logicalAnd(
560  $constraint,
561  ‪$query->‪equals($columnMap->getParentTableFieldName(), $dataMap->getTableName())
562  );
563  }
564  } else {
565  // Note: $fieldValue is annotated as a string, but this cannot be trusted as the callers do not ensure this.
566  $constraint = ‪$query->‪in('uid', ‪GeneralUtility::intExplode(',', (string)$fieldValue));
567  }
568  if (!empty($relationTableMatchFields)) {
569  foreach ($relationTableMatchFields as $relationTableMatchFieldName => $relationTableMatchFieldValue) {
570  $constraint = ‪$query->‪logicalAnd($constraint, ‪$query->‪equals($relationTableMatchFieldName, $relationTableMatchFieldValue));
571  }
572  }
573  return $constraint;
574  }
575 
593  protected function ‪resolveRelationValuesOfField(DataMap $dataMap, ColumnMap $columnMap, DomainObjectInterface $parentObject, $fieldValue, int $workspaceId)
594  {
595  $parentId = $parentObject->getUid();
596  // versionedUid in a multi-language setup is the overlaid versioned AND translated ID
597  if ($parentObject->_hasProperty(‪AbstractDomainObject::PROPERTY_VERSIONED_UID) && $parentObject->_getProperty(‪AbstractDomainObject::PROPERTY_VERSIONED_UID) > 0 && $parentObject->_getProperty(‪AbstractDomainObject::PROPERTY_VERSIONED_UID) !== $parentId) {
598  $parentId = $parentObject->_getProperty(‪AbstractDomainObject::PROPERTY_VERSIONED_UID);
599  } elseif ($parentObject->_hasProperty(‪AbstractDomainObject::PROPERTY_LANGUAGE_UID) && $parentObject->_getProperty(‪AbstractDomainObject::PROPERTY_LANGUAGE_UID) > 0) {
600  $parentId = $parentObject->_getProperty(‪AbstractDomainObject::PROPERTY_LOCALIZED_UID);
601  }
602  $relationHandler = GeneralUtility::makeInstance(RelationHandler::class);
603  $relationHandler->setWorkspaceId($workspaceId);
604  $relationHandler->setUseLiveReferenceIds(true);
605  $relationHandler->setUseLiveParentIds(true);
606  $tableName = $dataMap->getTableName();
607  $fieldName = $columnMap->getColumnName();
608  $fieldConfiguration = ‪$GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'] ?? null;
609  if (!is_array($fieldConfiguration)) {
610  return [];
611  }
612  $relationHandler->start(
613  $fieldValue,
614  $fieldConfiguration['allowed'] ?? $fieldConfiguration['foreign_table'] ?? '',
615  $fieldConfiguration['MM'] ?? '',
616  $parentId,
617  $tableName,
618  $fieldConfiguration
619  );
620  $relationHandler->processDeletePlaceholder();
621  $relatedUids = [];
622  if (!empty($relationHandler->tableArray)) {
623  $relatedUids = reset($relationHandler->tableArray);
624  }
625  return $relatedUids;
626  }
627 
634  protected function ‪getSource(DomainObjectInterface $parentObject, $propertyName)
635  {
636  $columnMap = $this->‪getDataMap(get_class($parentObject))->‪getColumnMap($propertyName);
637  $left = $this->qomFactory->selector(null, $columnMap->getRelationTableName());
638  $childClassName = $this->‪getType(get_class($parentObject), $propertyName);
639  $right = $this->qomFactory->selector($childClassName, $columnMap->getChildTableName());
640  $joinCondition = $this->qomFactory->equiJoinCondition($columnMap->getRelationTableName(), $columnMap->getChildKeyFieldName(), $columnMap->getChildTableName(), 'uid');
641  $source = $this->qomFactory->join($left, $right, ‪Query::JCR_JOIN_TYPE_INNER, $joinCondition);
642  return $source;
643  }
644 
660  protected function ‪mapObjectToClassProperty(DomainObjectInterface $parentObject, $propertyName, $fieldValue)
661  {
662  if ($this->‪propertyMapsByForeignKey($parentObject, $propertyName)) {
663  $result = $this->‪fetchRelated($parentObject, $propertyName, $fieldValue);
664  return $this->‪mapResultToPropertyValue($parentObject, $propertyName, $result);
665  }
666 
667  if (empty($fieldValue)) {
668  return $this->‪getEmptyRelationValue($parentObject, $propertyName);
669  }
670 
671  $primaryType = $this->reflectionService
672  ->getClassSchema(get_class($parentObject))
673  ->getProperty($propertyName)
674  ->getPrimaryType();
675 
676  if ($primaryType === null) {
677  throw ‪NoPropertyTypesException::create($parentObject::class, $propertyName);
678  }
679 
680  $className = $primaryType->getClassName();
681  if (!is_string($className)) {
682  throw new \LogicException(
683  sprintf('Evaluated type of class property %s::%s is not a class name. Check the type declaration of the property to use a valid class name.', $parentObject::class, $propertyName),
684  1660217846
685  );
686  }
687 
688  if ($this->persistenceSession->hasIdentifier((string)$fieldValue, $className)) {
689  return $this->persistenceSession->getObjectByIdentifier((string)$fieldValue, $className);
690  }
691 
692  $result = $this->‪fetchRelated($parentObject, $propertyName, $fieldValue);
693  return $this->‪mapResultToPropertyValue($parentObject, $propertyName, $result);
694  }
695 
702  protected function ‪propertyMapsByForeignKey(DomainObjectInterface $parentObject, $propertyName)
703  {
704  $columnMap = $this->‪getDataMap(get_class($parentObject))->‪getColumnMap($propertyName);
705  return $columnMap->‪getParentKeyFieldName() !== null;
706  }
707 
715  public function ‪mapResultToPropertyValue(DomainObjectInterface $parentObject, $propertyName, $result)
716  {
717  $propertyValue = null;
718  if ($result instanceof LoadingStrategyInterface) {
719  $propertyValue = $result;
720  } else {
721  $property = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
722  $primaryType = $property->getPrimaryType();
723 
724  if ($primaryType === null) {
725  throw ‪NoPropertyTypesException::create($parentObject::class, $propertyName);
726  }
727 
728  if ($primaryType->getBuiltinType() === 'array' || in_array($primaryType->getClassName(), [\ArrayObject::class, \SplObjectStorage::class, ObjectStorage::class], true)) {
729  $objects = [];
730  foreach ($result as $value) {
731  $objects[] = $value;
732  }
733  if ($primaryType->getClassName() === \ArrayObject::class) {
734  $propertyValue = new \ArrayObject($objects);
735  } elseif ($primaryType->getClassName() === ObjectStorage::class) {
736  $propertyValue = new ObjectStorage();
737  foreach ($objects as $object) {
738  $propertyValue->attach($object);
739  }
740  $propertyValue->_memorizeCleanState();
741  } else {
742  $propertyValue = $objects;
743  }
744  } elseif (strpbrk((string)$primaryType->getClassName(), '_\\') !== false) {
745  // @todo: check the strpbrk function call. Seems to be a check for Tx_Foo_Bar style class names
746  if ($result instanceof QueryResultInterface) {
747  $propertyValue = $result->getFirst();
748  } else {
749  $propertyValue = $result;
750  }
751  }
752  }
753  return $propertyValue;
754  }
755 
764  public function ‪countRelated(DomainObjectInterface $parentObject, $propertyName, $fieldValue = '')
765  {
766  ‪$query = $this->‪getPreparedQuery($parentObject, $propertyName, $fieldValue);
767  return ‪$query->‪execute()->count();
768  }
769 
777  public function ‪getDataMap($className)
778  {
779  if (!is_string($className) || $className === '') {
780  throw new Exception('No class name was given to retrieve the Data Map for.', 1251315965);
781  }
782  return $this->dataMapFactory->buildDataMap($className);
783  }
784 
791  public function ‪convertClassNameToTableName($className)
792  {
793  return $this->‪getDataMap($className)->‪getTableName();
794  }
795 
803  public function ‪convertPropertyNameToColumnName($propertyName, $className = null)
804  {
805  if (!empty($className)) {
806  $dataMap = $this->‪getDataMap($className);
807  if ($dataMap !== null) {
808  $columnMap = $dataMap->getColumnMap($propertyName);
809  if ($columnMap !== null) {
810  return $columnMap->getColumnName();
811  }
812  }
813  }
815  }
816 
825  public function ‪getType($parentClassName, $propertyName)
826  {
827  try {
828  $primaryType = $this->reflectionService
829  ->getClassSchema($parentClassName)
830  ->getProperty($propertyName)
831  ->getPrimaryType();
832 
833  if ($primaryType === null) {
834  throw ‪NoPropertyTypesException::create($parentClassName, $propertyName);
835  }
836 
837  if ($primaryType->isCollection() && $primaryType->getCollectionValueTypes() !== []) {
838  $primaryCollectionValueType = $primaryType->getCollectionValueTypes()[0];
839  return $primaryCollectionValueType->getClassName()
840  ?? $primaryCollectionValueType->getBuiltinType();
841  }
842 
843  return $primaryType->getClassName()
844  ?? $primaryType->getBuiltinType();
845  } catch (NoSuchPropertyException|NoPropertyTypesException $e) {
846  }
847 
848  throw new UnexpectedTypeException('Could not determine the child object type.', 1251315967);
849  }
850 
861  public function ‪getPlainValue(mixed $input, ?ColumnMap $columnMap = null): int|string
862  {
863  if ($input === null) {
864  return 'NULL';
865  }
866 
867  if ($input instanceof \BackedEnum) {
868  return $input->value;
869  }
870 
871  if ($input instanceof LazyLoadingProxy) {
872  $input = $input->_loadRealInstance();
873  }
874 
875  if (is_bool($input)) {
876  return (int)$input;
877  }
878 
879  if (is_int($input)) {
880  return $input;
881  }
882 
883  if ($input instanceof \DateTimeInterface) {
884  if ($columnMap !== null && $columnMap->getDateTimeStorageFormat() !== null) {
885  $storageFormat = $columnMap->getDateTimeStorageFormat();
886  return match ($storageFormat) {
887  'datetime' => $input->format('Y-m-d H:i:s'),
888  'date' => $input->format('Y-m-d'),
889  'time' => $input->format('H:i'),
890  default => throw new \InvalidArgumentException('Column map DateTime format "' . $storageFormat . '" is unknown. Allowed values are date, datetime or time.', 1395353470),
891  };
892  }
893 
894  return $input->format('U');
895  }
896 
897  if ($input instanceof DomainObjectInterface) {
898  return (int)$input->getUid();
899  }
900 
902  $plainValueArray = [];
903  foreach ($input as $inputElement) {
904  $plainValueArray[] = $this->‪getPlainValue($inputElement, $columnMap);
905  }
906  return implode(',', $plainValueArray);
907  }
908 
909  if (is_object($input)) {
910  if (‪TypeHandlingUtility::isCoreType($input) || $input instanceof \Stringable) {
911  return (string)$input;
912  }
913 
914  throw new UnexpectedTypeException('An object of class "' . get_class($input) . '" could not be converted to a plain value.', 1274799934);
915  }
916 
917  return (string)$input;
918  }
919 }
‪TYPO3\CMS\Extbase\Reflection\ClassSchema\Exception\NoSuchPropertyException
Definition: NoSuchPropertyException.php:24
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:44
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\map
‪array map($className, array $rows)
Definition: DataMapper.php:89
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\mapDateTime
‪DateTimeInterface mapDateTime($value, $storageFormat=null, $targetType=\DateTime::class)
Definition: DataMapper.php:331
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getDateTimeStorageFormat
‪getDateTimeStorageFormat()
Definition: ColumnMap.php:222
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\mapResultToPropertyValue
‪mixed mapResultToPropertyValue(DomainObjectInterface $parentObject, $propertyName, $result)
Definition: DataMapper.php:714
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getLanguageAspect
‪getLanguageAspect()
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getParentKeyFieldName
‪getParentKeyFieldName()
Definition: ColumnMap.php:192
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap\getColumnMap
‪ColumnMap null getColumnMap($propertyName)
Definition: DataMap.php:224
‪TYPO3\CMS\Extbase\Persistence\Generic\LoadingStrategyInterface
Definition: LoadingStrategyInterface.php:21
‪TYPO3\CMS\Core\Context\LanguageAspect\OVERLAYS_MIXED
‪const OVERLAYS_MIXED
Definition: LanguageAspect.php:75
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\createEmptyObject
‪createEmptyObject(string $className)
Definition: DataMapper.php:164
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\getConstraint
‪TYPO3 CMS Extbase Persistence Generic Qom ConstraintInterface getConstraint(QueryInterface $query, DomainObjectInterface $parentObject, $propertyName, $fieldValue='', $relationTableMatchFields=[])
Definition: DataMapper.php:516
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap
Definition: DataMap.php:25
‪TYPO3\CMS\Extbase\Persistence\QueryInterface
Definition: QueryInterface.php:30
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\equals
‪TYPO3 CMS Extbase Persistence Generic Qom ComparisonInterface equals($propertyName, $operand, $caseSensitive=true)
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\logicalAnd
‪logicalAnd(ConstraintInterface ... $constraints)
‪TYPO3\CMS\Core\Database\RelationHandler
Definition: RelationHandler.php:36
‪TYPO3\CMS\Extbase\Utility\TypeHandlingUtility\isCoreType
‪static isCoreType($type)
Definition: TypeHandlingUtility.php:117
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap\getTableName
‪string getTableName()
Definition: DataMap.php:163
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\setIgnoreEnableFields
‪$this setIgnoreEnableFields(bool $ignoreEnableFields)
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap\getRecordType
‪string null getRecordType()
Definition: DataMap.php:183
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\getPlainValue
‪int string getPlainValue(mixed $input, ?ColumnMap $columnMap=null)
Definition: DataMapper.php:860
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\getType
‪string getType($parentClassName, $propertyName)
Definition: DataMapper.php:824
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap
Definition: ColumnMap.php:27
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\Exception\UnknownPropertyTypeException
Definition: UnknownPropertyTypeException.php:22
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\setLanguageAspect
‪$this setLanguageAspect(LanguageAspect $languageAspect)
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\ORDER_DESCENDING
‪const ORDER_DESCENDING
Definition: QueryInterface.php:100
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getRelationTableName
‪getRelationTableName()
Definition: ColumnMap.php:172
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\convertPropertyNameToColumnName
‪string convertPropertyNameToColumnName($propertyName, $className=null)
Definition: DataMapper.php:802
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\setOrderings
‪TYPO3 CMS Extbase Persistence QueryInterface setOrderings(array $orderings)
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject\PROPERTY_PID
‪const PROPERTY_PID
Definition: AbstractDomainObject.php:33
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelFactory
Definition: QueryObjectModelFactory.php:30
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\execute
‪TYPO3 CMS Extbase Persistence QueryResultInterface object[] execute($returnRawQueryResult=false)
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getChildTableDefaultSortings
‪getChildTableDefaultSortings()
Definition: ColumnMap.php:152
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getChildTableName
‪getChildTableName()
Definition: ColumnMap.php:142
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\getEmptyRelationValue
‪array null getEmptyRelationValue(DomainObjectInterface $parentObject, $propertyName)
Definition: DataMapper.php:392
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\mapObjectToClassProperty
‪mixed mapObjectToClassProperty(DomainObjectInterface $parentObject, $propertyName, $fieldValue)
Definition: DataMapper.php:659
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getQuerySettings
‪QuerySettingsInterface getQuerySettings()
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\getTargetType
‪string getTargetType($className, array $row)
Definition: DataMapper.php:107
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
Definition: DataMapper.php:59
‪TYPO3\CMS\Core\Utility\GeneralUtility\camelCaseToLowerCaseUnderscored
‪static string camelCaseToLowerCaseUnderscored($string)
Definition: GeneralUtility.php:678
‪TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface\_getProperty
‪_getProperty(string $propertyName)
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject\PROPERTY_LOCALIZED_UID
‪const PROPERTY_LOCALIZED_UID
Definition: AbstractDomainObject.php:34
‪TYPO3\CMS\Extbase\Reflection\ClassSchema\Exception\NoPropertyTypesException
Definition: NoPropertyTypesException.php:24
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\propertyMapsByForeignKey
‪bool propertyMapsByForeignKey(DomainObjectInterface $parentObject, $propertyName)
Definition: DataMapper.php:701
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidClassException
Definition: InvalidClassException.php:25
‪TYPO3\CMS\Extbase\Persistence\ObjectStorage
Definition: ObjectStorage.php:34
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
Definition: DataMapFactory.php:34
‪TYPO3\CMS\Extbase\Reflection\ReflectionService
Definition: ReflectionService.php:28
‪TYPO3\CMS\Extbase\Event\Persistence\AfterObjectThawedEvent
Definition: AfterObjectThawedEvent.php:26
‪TYPO3\CMS\Extbase\Persistence
Definition: ClassesConfiguration.php:18
‪TYPO3\CMS\Extbase\Exception
Definition: Exception.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\$fields
‪$fields
Definition: DataMapper.php:485
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\in
‪ComparisonInterface in($propertyName, $operand)
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\mapSingleRow
‪object mapSingleRow($className, array $row)
Definition: DataMapper.php:133
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getColumnName
‪getColumnName()
Definition: ColumnMap.php:132
‪TYPO3\CMS\Extbase\Reflection\ClassSchema\Property
Definition: Property.php:30
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\$orderings
‪foreach($fields as $field) return $orderings
Definition: DataMapper.php:505
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getSource
‪TYPO3 CMS Extbase Persistence Generic Qom SourceInterface getSource()
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\ORDER_ASCENDING
‪const ORDER_ASCENDING
Definition: QueryInterface.php:99
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\thawProperties
‪thawProperties(DomainObjectInterface $object, array $row)
Definition: DataMapper.php:187
‪TYPO3\CMS\Extbase\Utility\TypeHandlingUtility
Definition: TypeHandlingUtility.php:29
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getTypeOfRelation
‪getTypeOfRelation()
Definition: ColumnMap.php:127
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Extbase\Persistence\Generic\Query\JCR_JOIN_TYPE_INNER
‪const JCR_JOIN_TYPE_INNER
Definition: Query.php:45
‪TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface
Definition: QueryFactoryInterface.php:22
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getChildSortByFieldName
‪getChildSortByFieldName()
Definition: ColumnMap.php:162
‪TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface
Definition: DomainObjectInterface.php:33
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\fetchRelatedEager
‪mixed fetchRelatedEager(DomainObjectInterface $parentObject, $propertyName, $fieldValue='')
Definition: DataMapper.php:383
‪TYPO3\CMS\Core\Database\Query\QueryHelper\getDateTimeTypes
‪static array getDateTimeTypes()
Definition: QueryHelper.php:211
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject
Definition: AbstractDomainObject.php:31
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\matching
‪TYPO3 CMS Extbase Persistence QueryInterface matching($constraint)
‪TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface\getUid
‪getUid()
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\setSource
‪setSource(SourceInterface $source)
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\$orderings
‪if($columnMap->getChildTableDefaultSortings()===null) $orderings
Definition: DataMapper.php:484
‪TYPO3\CMS\Extbase\Persistence\Generic\Session
Definition: Session.php:27
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getParentTableFieldName
‪getParentTableFieldName()
Definition: ColumnMap.php:202
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject\PROPERTY_LANGUAGE_UID
‪const PROPERTY_LANGUAGE_UID
Definition: AbstractDomainObject.php:35
‪TYPO3\CMS\Extbase\Persistence\QueryResultInterface
Definition: QueryResultInterface.php:26
‪TYPO3\CMS\Extbase\Persistence\Generic\Exception
Definition: InconsistentQuerySettingsException.php:18
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject\PROPERTY_VERSIONED_UID
‪const PROPERTY_VERSIONED_UID
Definition: AbstractDomainObject.php:36
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\convertClassNameToTableName
‪string convertClassNameToTableName($className)
Definition: DataMapper.php:790
‪TYPO3\CMS\Core\Context\LanguageAspect
Definition: LanguageAspect.php:57
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\countRelated
‪int countRelated(DomainObjectInterface $parentObject, $propertyName, $fieldValue='')
Definition: DataMapper.php:763
‪TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface\_setProperty
‪_setProperty(string $propertyName, mixed $value)
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\fetchRelated
‪TYPO3 CMS Extbase Persistence Generic LazyObjectStorage Persistence QueryResultInterface fetchRelated(DomainObjectInterface $parentObject, $propertyName, $fieldValue='', $enableLazyLoading=true)
Definition: DataMapper.php:358
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getChildKeyFieldName
‪getChildKeyFieldName()
Definition: ColumnMap.php:212
‪TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException
Definition: UnexpectedTypeException.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\thawObjectProperty
‪thawObjectProperty(Property $propertySchema, ColumnMap $columnMap, DomainObjectInterface $parent, string $propertyName, mixed $propertyValue, ?string $targetClassName)
Definition: DataMapper.php:265
‪TYPO3\CMS\Extbase\Utility\TypeHandlingUtility\isValidTypeForMultiValueComparison
‪static isValidTypeForMultiValueComparison($value)
Definition: TypeHandlingUtility.php:147
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\Exception\NonExistentPropertyException
Definition: NonExistentPropertyException.php:22
‪TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy
Definition: LazyLoadingProxy.php:30
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\getNonEmptyRelationValue
‪Persistence QueryResultInterface getNonEmptyRelationValue(DomainObjectInterface $parentObject, $propertyName, $fieldValue)
Definition: DataMapper.php:404
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\resolveRelationValuesOfField
‪array false mixed resolveRelationValuesOfField(DataMap $dataMap, ColumnMap $columnMap, DomainObjectInterface $parentObject, $fieldValue, int $workspaceId)
Definition: DataMapper.php:592
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\$query
‪QueryInterface null $query
Definition: DataMapper.php:62
‪TYPO3\CMS\Extbase\Reflection\ClassSchema\Exception\NoPropertyTypesException\create
‪static create(string $className, string $propertyName)
Definition: NoPropertyTypesException.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Query
Definition: Query.php:41
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\setEnableFieldsToBeIgnored
‪$this setEnableFieldsToBeIgnored(array $enableFieldsToBeIgnored)
‪TYPO3\CMS\Core\Context\LanguageAspect\OVERLAYS_OFF
‪const OVERLAYS_OFF
Definition: LanguageAspect.php:74
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\setRespectStoragePage
‪$this setRespectStoragePage(bool $respectStoragePage)
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\getPreparedQuery
‪Persistence QueryInterface getPreparedQuery(DomainObjectInterface $parentObject, $propertyName, $fieldValue='')
Definition: DataMapper.php:417
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject\PROPERTY_UID
‪const PROPERTY_UID
Definition: AbstractDomainObject.php:32
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper
‪TYPO3\CMS\Extbase\Persistence\Generic\LazyObjectStorage
Definition: LazyObjectStorage.php:36
‪TYPO3\CMS\Extbase\Reflection\ClassSchema\Property\isNullable
‪isNullable()
Definition: Property.php:143
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static list< int > intExplode(string $delimiter, string $string, bool $removeEmptyValues=false)
Definition: GeneralUtility.php:751
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\setRespectSysLanguage
‪$this setRespectSysLanguage(bool $respectSysLanguage)
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\getSource
‪TYPO3 CMS Extbase Persistence Generic Qom SourceInterface getSource(DomainObjectInterface $parentObject, $propertyName)
Definition: DataMapper.php:633
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\setQuery
‪setQuery(QueryInterface $query)
Definition: DataMapper.php:74
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\getDataMap
‪DataMap getDataMap($className)
Definition: DataMapper.php:776
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\__construct
‪__construct(private readonly ReflectionService $reflectionService, private readonly QueryObjectModelFactory $qomFactory, private readonly Session $persistenceSession, private readonly DataMapFactory $dataMapFactory, private readonly QueryFactoryInterface $queryFactory, private readonly EventDispatcherInterface $eventDispatcher, private readonly InstantiatorInterface $instantiator,)
Definition: DataMapper.php:64
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\Relation
‪Relation
Definition: Relation.php:24
‪TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface\_hasProperty
‪_hasProperty(string $propertyName)
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper\mapCoreType
‪TYPO3 CMS Core Type TypeInterface mapCoreType($type, $value)
Definition: DataMapper.php:317