154 $this->referenceIndex = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\
TYPO3\CMS\Core\Database\ReferenceIndex::class);
155 $this->referenceIndex->enableRuntimeCache();
156 $this->aggregateRootObjects = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
157 $this->deletedEntities = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
158 $this->changedEntities = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
207 return $this->storageBackend->getObjectCountByQuery($query);
219 $result = $this->storageBackend->getObjectDataByQuery($query);
232 $signalArguments = $this->signalSlotDispatcher->dispatch(__CLASS__,
'beforeGettingObjectData', [$query]);
233 return $signalArguments[0];
245 $signalArguments = $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterGettingObjectData', [$query, $result]);
246 return $signalArguments[1];
259 $object = $object->_loadRealInstance();
260 if (!is_object($object)) {
264 return $this->session->getIdentifierByObject($object);
277 if ($this->session->hasIdentifier($identifier, $className)) {
278 return $this->session->getObjectByIdentifier($identifier, $className);
280 $query = $this->persistenceManager->createQueryForType($className);
281 $query->getQuerySettings()->setRespectStoragePage(
false);
282 $query->getQuerySettings()->setRespectSysLanguage(
false);
283 $query->getQuerySettings()->setLanguageOverlayMode(
true);
284 return $query->matching($query->equals(
'uid', $identifier))->execute()->getFirst();
305 $this->aggregateRootObjects = $objects;
315 $this->changedEntities = $entities;
325 $this->deletedEntities = $entities;
342 $this->visitedDuringPersistence = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
343 foreach ($this->aggregateRootObjects as $object) {
345 if ($object->_isNew()) {
350 foreach ($this->changedEntities as $object) {
362 if (isset($this->visitedDuringPersistence[$object])) {
367 $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
368 $properties = $object->_getProperties();
369 foreach ($properties as $propertyName => $propertyValue) {
370 if (!$dataMap->isPersistableProperty($propertyName) || $this->propertyValueIsLazyLoaded($propertyValue)) {
373 $columnMap = $dataMap->getColumnMap($propertyName);
374 if ($propertyValue instanceof \
TYPO3\CMS\
Extbase\Persistence\ObjectStorage) {
375 $cleanProperty = $object->_getCleanProperty($propertyName);
379 if ($object->_isNew() || $propertyValue->_isDirty() || ($propertyValue->count() === 0 && $cleanProperty && $cleanProperty->count() > 0)) {
381 $propertyValue->_memorizeCleanState();
383 foreach ($propertyValue as $containedObject) {
384 if ($containedObject instanceof \
TYPO3\CMS\
Extbase\DomainObject\DomainObjectInterface) {
385 $queue[] = $containedObject;
388 } elseif ($propertyValue instanceof \
TYPO3\CMS\
Extbase\DomainObject\DomainObjectInterface
389 && $object instanceof ObjectMonitoringInterface) {
390 if ($object->_isDirty($propertyName)) {
391 if ($propertyValue->_isNew()) {
392 $this->
insertObject($propertyValue, $object, $propertyName);
394 $row[$columnMap->getColumnName()] = $this->
getPlainValue($propertyValue);
396 $queue[] = $propertyValue;
397 } elseif ($object->_isNew() || $object->_isDirty($propertyName)) {
398 $row[$columnMap->getColumnName()] = $this->
getPlainValue($propertyValue, $columnMap);
403 $object->_memorizeCleanState();
405 $this->visitedDuringPersistence[$object] = $object->getUid();
406 foreach ($queue as $queuedObject) {
420 if ($propertyValue instanceof \
TYPO3\CMS\
Extbase\Persistence\Generic\LazyLoadingProxy) {
423 if ($propertyValue instanceof \
TYPO3\CMS\
Extbase\Persistence\Generic\LazyObjectStorage) {
424 if ($propertyValue->isInitialized() ===
false) {
444 $className = get_class($parentObject);
445 $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
446 $dataMapper = $objectManager->get(DataMapper::class);
447 $columnMap = $this->dataMapFactory->buildDataMap($className)->getColumnMap($propertyName);
448 $propertyMetaData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName);
457 $sortingPosition = 1;
458 $updateSortingOfFollowing =
false;
460 foreach ($objectStorage as $object) {
462 if (empty($currentUids)) {
463 $sortingPosition = 1;
467 $cleanProperty = $parentObject->_getCleanProperty($propertyName);
468 if ($object->_isNew()) {
472 $updateSortingOfFollowing =
true;
473 } elseif ($cleanProperty ===
null || $cleanProperty->getPosition($object) ===
null) {
477 $updateSortingOfFollowing =
true;
478 } elseif ($objectStorage->isRelationDirty($object) || $cleanProperty->getPosition($object) !== $objectStorage->getPosition($object)) {
480 $updateSortingOfFollowing =
true;
481 } elseif ($updateSortingOfFollowing) {
482 if ($sortingPosition > $objectStorage->getPosition($object)) {
485 $sortingPosition = $objectStorage->getPosition($object);
488 $currentUids[] = $object->getUid();
491 if ($columnMap->getParentKeyFieldName() ===
null) {
492 $row[$columnMap->getColumnName()] = implode(
',', $currentUids);
494 $row[$columnMap->getColumnName()] = $dataMapper->countRelated($parentObject, $propertyName);
508 $removedObjects = [];
509 $cleanPropertyValue = $object->_getCleanProperty($propertyName);
510 if (is_array($cleanPropertyValue) || $cleanPropertyValue instanceof \Iterator) {
511 $propertyValue = $object->_getProperty($propertyName);
512 foreach ($cleanPropertyValue as $containedObject) {
513 if (!$propertyValue->contains($containedObject)) {
514 $removedObjects[] = $containedObject;
518 return $removedObjects;
531 $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
533 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
551 $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
552 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
571 $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
572 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
574 throw new \TYPO3\CMS\Extbase\Persistence\Exception\IllegalRelationTypeException(
575 'Parent column relation type is ' . $parentColumnMap->getTypeOfRelation() .
581 $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName();
582 if ($parentKeyFieldName !==
null) {
583 $row[$parentKeyFieldName] = $parentObject->_getProperty(
'_localizedUid') ?: $parentObject->getUid();
584 $parentTableFieldName = $parentColumnMap->getParentTableFieldName();
585 if ($parentTableFieldName !==
null) {
586 $row[$parentTableFieldName] = $parentDataMap->getTableName();
588 $relationTableMatchFields = $parentColumnMap->getRelationTableMatchFields();
589 if (is_array($relationTableMatchFields)) {
590 $row = array_merge($relationTableMatchFields, $row);
593 $childSortByFieldName = $parentColumnMap->getChildSortByFieldName();
594 if (!empty($childSortByFieldName)) {
595 $row[$childSortByFieldName] = $sortingPosition;
611 $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
612 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
615 $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName();
616 if ($parentKeyFieldName !==
null) {
617 $row[$parentKeyFieldName] = 0;
618 $parentTableFieldName = $parentColumnMap->getParentTableFieldName();
619 if ($parentTableFieldName !==
null) {
620 $row[$parentTableFieldName] =
'';
622 $relationTableMatchFields = $parentColumnMap->getRelationTableMatchFields();
623 if (is_array($relationTableMatchFields) && !empty($relationTableMatchFields)) {
624 $row = array_merge(array_fill_keys(array_keys($relationTableMatchFields),
''), $row);
627 $childSortByFieldName = $parentColumnMap->getChildSortByFieldName();
628 if (!empty($childSortByFieldName)) {
629 $row[$childSortByFieldName] = 0;
646 protected function insertObject(\
TYPO3\CMS\
Extbase\DomainObject\DomainObjectInterface $object, \
TYPO3\CMS\
Extbase\DomainObject\DomainObjectInterface $parentObject =
null, $parentPropertyName =
'')
648 if ($object instanceof \
TYPO3\CMS\
Extbase\DomainObject\AbstractValueObject) {
650 if ($result !==
false) {
651 $object->_setProperty(
'uid', (
int)$result);
655 $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
657 $properties = $object->_getProperties();
658 foreach ($properties as $propertyName => $propertyValue) {
659 if (!$dataMap->isPersistableProperty($propertyName) || $this->propertyValueIsLazyLoaded($propertyValue)) {
662 $columnMap = $dataMap->getColumnMap($propertyName);
664 $row[$columnMap->getColumnName()] = 0;
666 if ($columnMap->getParentKeyFieldName() ===
null) {
668 $row[$columnMap->getColumnName()] =
'';
671 $row[$columnMap->getColumnName()] = 0;
673 } elseif ($propertyValue !==
null) {
674 $row[$columnMap->getColumnName()] = $this->
getPlainValue($propertyValue, $columnMap);
678 if ($dataMap->getLanguageIdColumnName() !==
null && $object->_getProperty(
'_languageUid') ===
null) {
679 $row[$dataMap->getLanguageIdColumnName()] = 0;
680 $object->_setProperty(
'_languageUid', 0);
682 if ($dataMap->getTranslationOriginColumnName() !==
null) {
683 $row[$dataMap->getTranslationOriginColumnName()] = 0;
685 if ($dataMap->getTranslationOriginDiffSourceName() !==
null) {
686 $row[$dataMap->getTranslationOriginDiffSourceName()] =
'';
688 if ($parentObject !==
null && $parentPropertyName) {
689 $parentColumnDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject))->getColumnMap($parentPropertyName);
690 $relationTableMatchFields = $parentColumnDataMap->getRelationTableMatchFields();
691 if (is_array($relationTableMatchFields)) {
692 $row = array_merge($relationTableMatchFields, $row);
694 if ($parentColumnDataMap->getParentKeyFieldName() !==
null) {
695 $row[$parentColumnDataMap->getParentKeyFieldName()] = (int)$parentObject->getUid();
698 $uid = $this->storageBackend->addRow($dataMap->getTableName(), $row);
699 $object->_setProperty(
'uid', (
int)$uid);
700 $object->setPid((
int)$row[
'pid']);
701 if ((
int)$uid >= 1) {
705 if ($frameworkConfiguration[
'persistence'][
'updateReferenceIndex'] ===
'1') {
706 $this->referenceIndex->updateRefIndexTable($dataMap->getTableName(), $uid);
708 $this->session->registerObject($object, $uid);
709 if ((
int)$uid >= 1) {
721 $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterInsertObject', [$object]);
732 $this->signalSlotDispatcher->dispatch(__CLASS__,
'endInsertObject', [$object]);
743 return $this->storageBackend->getUidOfAlreadyPersistedValueObject($object);
757 $dataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
758 $columnMap = $dataMap->getColumnMap($propertyName);
759 $parentUid = $parentObject->getUid();
760 if ($parentObject->_getProperty(
'_localizedUid') !==
null) {
761 $parentUid = $parentObject->_getProperty(
'_localizedUid');
764 $columnMap->getParentKeyFieldName() => (int)$parentUid,
765 $columnMap->getChildKeyFieldName() => (int)$object->getUid(),
766 $columnMap->getChildSortByFieldName() => $sortingPosition !==
null ? (int)$sortingPosition : 0
768 $relationTableName = $columnMap->getRelationTableName();
769 if ($columnMap->getRelationTablePageIdColumnName() !==
null) {
772 $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
773 if (is_array($relationTableMatchFields)) {
774 $row = array_merge($relationTableMatchFields, $row);
776 $relationTableInsertFields = $columnMap->getRelationTableInsertFields();
777 if (is_array($relationTableInsertFields)) {
778 $row = array_merge($relationTableInsertFields, $row);
780 $res = $this->storageBackend->addRow($relationTableName, $row,
true);
795 $dataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
796 $columnMap = $dataMap->getColumnMap($propertyName);
798 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
799 $columnMap->getChildKeyFieldName() => (int)$object->getUid(),
800 $columnMap->getChildSortByFieldName() => (int)$sortingPosition
802 $relationTableName = $columnMap->getRelationTableName();
803 $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
804 if (is_array($relationTableMatchFields)) {
805 $row = array_merge($relationTableMatchFields, $row);
807 $res = $this->storageBackend->updateRelationTableRow(
823 $dataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
824 $columnMap = $dataMap->getColumnMap($parentPropertyName);
825 $relationTableName = $columnMap->getRelationTableName();
826 $relationMatchFields = [
827 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid()
829 $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
830 if (is_array($relationTableMatchFields)) {
831 $relationMatchFields = array_merge($relationTableMatchFields, $relationMatchFields);
833 $res = $this->storageBackend->removeRow($relationTableName, $relationMatchFields,
false);
847 $dataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
848 $columnMap = $dataMap->getColumnMap($parentPropertyName);
849 $relationTableName = $columnMap->getRelationTableName();
850 $relationMatchFields = [
851 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
852 $columnMap->getChildKeyFieldName() => (int)$relatedObject->getUid()
854 $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
855 if (is_array($relationTableMatchFields)) {
856 $relationMatchFields = array_merge($relationTableMatchFields, $relationMatchFields);
858 $res = $this->storageBackend->removeRow($relationTableName, $relationMatchFields,
false);
872 $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
873 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
875 $tableName = $parentColumnMap->getChildTableName();
876 $sortByFieldName = $parentColumnMap->getChildSortByFieldName();
878 if (empty($sortByFieldName)) {
882 $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName();
883 if ($parentKeyFieldName !==
null) {
884 $matchFields[$parentKeyFieldName] = $parentObject->getUid();
885 $parentTableFieldName = $parentColumnMap->getParentTableFieldName();
886 if ($parentTableFieldName !==
null) {
887 $matchFields[$parentTableFieldName] = $parentDataMap->getTableName();
891 if (empty($matchFields)) {
895 $tableName = $parentColumnMap->getRelationTableName();
896 $sortByFieldName = $parentColumnMap->getChildSortByFieldName();
899 $parentColumnMap->getParentKeyFieldName() => (int)$parentObject->getUid()
902 $relationTableMatchFields = $parentColumnMap->getRelationTableMatchFields();
903 if (is_array($relationTableMatchFields)) {
904 $matchFields = array_merge($relationTableMatchFields, $matchFields);
907 throw new \TYPO3\CMS\Extbase\Persistence\Exception\IllegalRelationTypeException(
'Unexpected parent column relation type: ' . $parentColumnMap->getTypeOfRelation(), 1345368106);
910 $result = $this->storageBackend->getMaxValueFromTable(
927 $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
929 $row[
'uid'] = $object->getUid();
930 if ($dataMap->getLanguageIdColumnName() !==
null) {
931 $row[$dataMap->getLanguageIdColumnName()] = (int)$object->_getProperty(
'_languageUid');
932 if ($object->_getProperty(
'_localizedUid') !==
null) {
933 $row[
'uid'] = $object->_getProperty(
'_localizedUid');
936 $res = $this->storageBackend->updateRow($dataMap->getTableName(), $row);
941 if ($frameworkConfiguration[
'persistence'][
'updateReferenceIndex'] ===
'1') {
942 $this->referenceIndex->updateRefIndexTable($dataMap->getTableName(), $row[
'uid']);
954 $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterUpdateObject', [$object]);
964 $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterPersistObject', [$object]);
975 $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
977 if ($dataMap->getRecordTypeColumnName() !==
null && $dataMap->getRecordType() !==
null) {
978 $row[$dataMap->getRecordTypeColumnName()] = $dataMap->getRecordType();
980 if ($object->_isNew() && !isset($row[
'pid'])) {
993 $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
994 if ($object->_isNew() && $dataMap->getCreationDateColumnName() !==
null) {
995 $row[$dataMap->getCreationDateColumnName()] =
$GLOBALS[
'EXEC_TIME'];
997 if ($dataMap->getModificationDateColumnName() !==
null) {
998 $row[$dataMap->getModificationDateColumnName()] =
$GLOBALS[
'EXEC_TIME'];
1007 foreach ($this->deletedEntities as $entity) {
1008 if ($this->session->hasObject($entity)) {
1010 $this->session->unregisterReconstitutedEntity($entity);
1011 $this->session->unregisterObject($entity);
1014 $this->deletedEntities = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
1025 $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
1026 $tableName = $dataMap->getTableName();
1027 if ($markAsDeleted ===
true && $dataMap->getDeletedFlagColumnName() !==
null) {
1028 $deletedColumnName = $dataMap->getDeletedFlagColumnName();
1030 'uid' => $object->getUid(),
1031 $deletedColumnName => 1
1034 $res = $this->storageBackend->updateRow($tableName, $row);
1036 $res = $this->storageBackend->removeRow($tableName, [
'uid' => $object->getUid()]);
1038 if ($res ===
true) {
1043 if ($frameworkConfiguration[
'persistence'][
'updateReferenceIndex'] ===
'1') {
1044 $this->referenceIndex->updateRefIndexTable($tableName, $object->getUid());
1055 $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterRemoveObject', [$object]);
1065 $className = get_class($object);
1066 $dataMap = $this->dataMapFactory->buildDataMap($className);
1067 $classSchema = $this->reflectionService->getClassSchema($className);
1068 $properties = $object->_getProperties();
1069 foreach ($properties as $propertyName => $propertyValue) {
1070 $columnMap = $dataMap->getColumnMap($propertyName);
1071 if ($columnMap ===
null) {
1074 $propertyMetaData = $classSchema->getProperty($propertyName);
1075 if ($propertyMetaData[
'annotations'][
'cascade'] ===
'remove') {
1077 foreach ($propertyValue as $containedObject) {
1080 } elseif ($propertyValue instanceof \
TYPO3\CMS\
Extbase\DomainObject\DomainObjectInterface) {
1083 } elseif ($dataMap->getDeletedFlagColumnName() ===
null
1105 if ($object !==
null) {
1106 if (\
TYPO3\CMS\
Extbase\Reflection\ObjectAccess::isPropertyGettable($object,
'pid')) {
1112 $className = get_class($object);
1113 if (isset($frameworkConfiguration[
'persistence'][
'classes'][$className]) && !empty($frameworkConfiguration[
'persistence'][
'classes'][$className][
'newRecordStoragePid'])) {
1114 return (
int)$frameworkConfiguration[
'persistence'][
'classes'][$className][
'newRecordStoragePid'];
1117 $storagePidList = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(
',', $frameworkConfiguration[
'persistence'][
'storagePid']);
1118 return (
int)$storagePidList[0];
1133 $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
1134 $dataMapper = $objectManager->get(DataMapper::class);
1135 return $input !==
null
1136 ? $dataMapper->getPlainValue($input, $columnMap)