165 public function map($className, array $rows)
168 foreach ($rows as $row) {
184 $targetType = $className;
185 if ($dataMap->getRecordTypeColumnName() !==
null) {
186 foreach ($dataMap->getSubclasses() as $subclassName) {
188 if ((
string)$row[$dataMap->getRecordTypeColumnName()] === (
string)$recordSubtype) {
189 $targetType = $subclassName;
206 if ($this->persistenceSession->hasIdentifier($row[
'uid'], $className)) {
207 $object = $this->persistenceSession->getObjectByIdentifier($row[
'uid'], $className);
210 $this->persistenceSession->registerObject($object, $row[
'uid']);
213 $object->_memorizeCleanState();
214 $this->persistenceSession->registerReconstitutedEntity($object);
226 $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterMappingSingleRow', [$object]);
240 if (!in_array(\
TYPO3\CMS\
Extbase\DomainObject\DomainObjectInterface::class, class_implements($className))) {
242 .
'" because it does not implement the TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface.', 1234386924);
244 $object = $this->objectManager->getEmptyObject($className);
258 $className = get_class($object);
259 $classSchema = $this->reflectionService->getClassSchema($className);
265 if ($dataMap->getLanguageIdColumnName() !==
null) {
266 $object->
_setProperty(
'_languageUid', (
int)$row[$dataMap->getLanguageIdColumnName()]);
267 if (isset($row[
'_LOCALIZED_UID'])) {
268 $object->
_setProperty(
'_localizedUid', (
int)$row[
'_LOCALIZED_UID']);
271 if (!empty($row[
'_ORIG_uid']) && !empty(
$GLOBALS[
'TCA'][$dataMap->getTableName()][
'ctrl'][
'versioningWS'])) {
272 $object->
_setProperty(
'_versionedUid', (
int)$row[
'_ORIG_uid']);
275 foreach ($properties as $propertyName => $propertyValue) {
276 if (!$dataMap->isPersistableProperty($propertyName)) {
279 $columnMap = $dataMap->getColumnMap($propertyName);
280 $columnName = $columnMap->getColumnName();
282 $property = $classSchema->getProperty($propertyName);
283 if (empty($property)) {
284 throw new Exception\NonExistentPropertyException(
285 'The type of property ' . $className .
'::' . $propertyName .
' could not be identified, ' .
286 'as property ' . $propertyName .
' is unknown to the ' . ClassSchema::class .
' instance of class ' .
287 $className .
'. Please make sure said property exists and that you cleared all caches to trigger ' .
288 'a new build of said ' . ClassSchema::class .
' instance.',
293 $propertyType = $property[
'type'] ??
null;
294 if ($propertyType ===
null) {
295 throw new Exception\UnknownPropertyTypeException(
296 'The type of property ' . $className .
'::' . $propertyName .
' could not be identified, therefore the desired value (' .
297 var_export($propertyValue,
true) .
') cannot be mapped onto it. The type of a class property is usually defined via php doc blocks. ' .
298 'Make sure the property has a valid @var tag set which defines the type.',
302 $propertyValue =
null;
303 if (isset($row[$columnName])) {
304 switch ($propertyType) {
306 $propertyValue = (int)$row[$columnName];
309 $propertyValue = (double)$row[$columnName];
312 $propertyValue = (bool)$row[$columnName];
315 $propertyValue = (string)$row[$columnName];
320 case 'SplObjectStorage':
321 case Persistence\ObjectStorage::class:
325 $this->
fetchRelated($object, $propertyName, $row[$columnName])
329 if (is_subclass_of($propertyType, \DateTimeInterface::class)) {
332 $columnMap->getDateTimeStorageFormat(),
336 $propertyValue = $this->
mapCoreType($propertyType, $row[$columnName]);
347 if ($propertyValue !==
null) {
362 return new $type($value);
374 protected function mapDateTime($value, $storageFormat =
null, $targetType = \DateTime::class)
378 if (empty($value) || $value ===
'0000-00-00' || $value ===
'0000-00-00 00:00:00' || $value ===
'00:00:00') {
382 if (in_array($storageFormat, $dateTimeTypes,
true)) {
384 $utcTimeZone = new \DateTimeZone(
'UTC');
385 $utcDateTime = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($targetType, $value, $utcTimeZone);
386 $currentTimeZone = new \DateTimeZone(date_default_timezone_get());
387 return $utcDateTime->setTimezone($currentTimeZone);
390 return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($targetType, date(
'c', (
int)$value));
404 $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
405 if ($enableLazyLoading ===
true && $propertyMetaData[
'annotations'][
'lazy']) {
406 if ($propertyMetaData[
'type'] === Persistence\ObjectStorage::class) {
407 $result = $this->objectManager->get(\
TYPO3\CMS\
Extbase\Persistence\Generic\LazyObjectStorage::class, $parentObject, $propertyName, $fieldValue, $this);
409 if (empty($fieldValue)) {
412 $result = $this->objectManager->get(\
TYPO3\CMS\
Extbase\Persistence\Generic\LazyLoadingProxy::class, $parentObject, $propertyName, $fieldValue, $this);
443 return $relatesToOne ? null : [];
468 $dataMap = $this->
getDataMap(get_class($parentObject));
469 $columnMap = $dataMap->getColumnMap($propertyName);
470 $type = $this->
getType(get_class($parentObject), $propertyName);
471 $query = $this->queryFactory->create($type);
472 if ($this->query &&
$query instanceof Persistence\Generic\
Query) {
473 $query->setParentQuery($this->query);
478 if ($this->configurationManager->isFeatureEnabled(
'consistentTranslationOverlayHandling')) {
484 if ($dataMap->getLanguageIdColumnName() !==
null && !$this->query->getQuerySettings()->getRespectSysLanguage()) {
488 $languageUid = (int)$parentObject->
_getProperty(
'_languageUid');
495 if ($columnMap->getChildSortByFieldName() !==
null) {
500 if ($columnMap->getChildSortByFieldName() !==
null) {
518 protected function getConstraint(Persistence\QueryInterface
$query, DomainObjectInterface $parentObject, $propertyName, $fieldValue =
'', $relationTableMatchFields = [])
521 if ($columnMap->getParentKeyFieldName() !==
null) {
522 $constraint =
$query->
equals($columnMap->getParentKeyFieldName(), $parentObject);
523 if ($columnMap->getParentTableFieldName() !==
null) {
526 $query->
equals($columnMap->getParentTableFieldName(), $this->getDataMap(get_class($parentObject))->getTableName())
530 $constraint =
$query->
in(
'uid', \
TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(
',', $fieldValue));
532 if (!empty($relationTableMatchFields)) {
533 foreach ($relationTableMatchFields as $relationTableMatchFieldName => $relationTableMatchFieldValue) {
550 $left = $this->qomFactory->selector(
null, $columnMap->getRelationTableName());
551 $childClassName = $this->
getType(get_class($parentObject), $propertyName);
552 $right = $this->qomFactory->selector($childClassName, $columnMap->getChildTableName());
553 $joinCondition = $this->qomFactory->equiJoinCondition($columnMap->getRelationTableName(), $columnMap->getChildKeyFieldName(), $columnMap->getChildTableName(),
'uid');
576 $result = $this->
fetchRelated($parentObject, $propertyName, $fieldValue);
579 if ($fieldValue ===
'') {
582 $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
583 if ($this->persistenceSession->hasIdentifier($fieldValue, $propertyMetaData[
'type'])) {
584 $propertyValue = $this->persistenceSession->getObjectByIdentifier($fieldValue, $propertyMetaData[
'type']);
586 $result = $this->
fetchRelated($parentObject, $propertyName, $fieldValue);
592 return $propertyValue;
618 $propertyValue =
null;
620 $propertyValue = $result;
622 $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
623 if (in_array($propertyMetaData[
'type'], [
'array',
'ArrayObject',
'SplObjectStorage', Persistence\ObjectStorage::class],
true)) {
625 foreach ($result as $value) {
628 if ($propertyMetaData[
'type'] ===
'ArrayObject') {
629 $propertyValue = new \ArrayObject($objects);
630 } elseif ($propertyMetaData[
'type'] === Persistence\ObjectStorage::class) {
632 foreach ($objects as $object) {
633 $propertyValue->attach($object);
635 $propertyValue->_memorizeCleanState();
637 $propertyValue = $objects;
639 } elseif (strpbrk($propertyMetaData[
'type'],
'_\\') !==
false) {
640 if (is_object($result) && $result instanceof Persistence\QueryResultInterface) {
641 $propertyValue = $result->getFirst();
643 $propertyValue = $result;
647 return $propertyValue;
675 return $dataMap->isPersistableProperty($propertyName);
687 if (!is_string($className) || $className ===
'') {
690 return $this->dataMapFactory->buildDataMap($className);
713 if (!empty($className)) {
715 if ($dataMap !==
null) {
716 $columnMap = $dataMap->getColumnMap($propertyName);
717 if ($columnMap !==
null) {
718 return $columnMap->getColumnName();
722 return \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($propertyName);
733 public function getType($parentClassName, $propertyName)
735 $propertyMetaData = $this->reflectionService->getClassSchema($parentClassName)->getProperty($propertyName);
736 if (!empty($propertyMetaData[
'elementType'])) {
737 $type = $propertyMetaData[
'elementType'];
738 } elseif (!empty($propertyMetaData[
'type'])) {
739 $type = $propertyMetaData[
'type'];
741 throw new UnexpectedTypeException(
'Could not determine the child object type.', 1251315967);
758 if ($input ===
null) {
761 if ($input instanceof Persistence\Generic\LazyLoadingProxy) {
762 $input = $input->_loadRealInstance();
765 if (is_bool($input)) {
766 $parameter = (int)$input;
767 } elseif (is_int($input)) {
769 } elseif ($input instanceof \DateTimeInterface) {
770 if ($columnMap !==
null && $columnMap->getDateTimeStorageFormat() !==
null) {
771 $storageFormat = $columnMap->getDateTimeStorageFormat();
772 $timeZoneToStore = clone $input;
774 $timeZoneToStore->setTimezone(
new \DateTimeZone(
'UTC'));
775 switch ($storageFormat) {
777 $parameter = $timeZoneToStore->format(
'Y-m-d H:i:s');
780 $parameter = $timeZoneToStore->format(
'Y-m-d');
783 $parameter = $timeZoneToStore->format(
'H:i');
786 throw new \InvalidArgumentException(
'Column map DateTime format "' . $storageFormat .
'" is unknown. Allowed values are date, datetime or time.', 1395353470);
789 $parameter = $input->format(
'U');
791 } elseif ($input instanceof DomainObjectInterface) {
792 $parameter = (int)$input->getUid();
794 $plainValueArray = [];
795 foreach ($input as $inputElement) {
796 $plainValueArray[] = $this->
getPlainValue($inputElement, $columnMap);
798 $parameter = implode(
',', $plainValueArray);
799 } elseif (is_object($input)) {
801 $parameter = (string)$input;
803 throw new UnexpectedTypeException(
'An object of class "' . get_class($input) .
'" could not be converted to a plain value.', 1274799934);
806 $parameter = (string)$input;