2 namespace TYPO3\CMS\Extbase\Persistence\Generic;
150 $this->referenceIndex = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ReferenceIndex::class);
151 $this->aggregateRootObjects = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
152 $this->deletedEntities = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
153 $this->changedEntities = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
213 return $this->storageBackend->getObjectCountByQuery($query);
226 $result = $this->storageBackend->getObjectDataByQuery($query);
227 $result = $this->emitafterGettingObjectDataSignal($query, $result);
239 $signalArguments = $this->signalSlotDispatcher->dispatch(__CLASS__,
'beforeGettingObjectData', array($query));
240 return $signalArguments[0];
252 $signalArguments = $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterGettingObjectData', array($query, $result));
253 return $signalArguments[1];
265 if ($object instanceof \TYPO3\CMS\Extbase\Persistence\Generic\
LazyLoadingProxy) {
266 $object = $object->_loadRealInstance();
267 if (!is_object($object)) {
271 return $this->session->getIdentifierByObject($object);
284 if ($this->session->hasIdentifier($identifier, $className)) {
285 return $this->session->getObjectByIdentifier($identifier, $className);
287 $query = $this->persistenceManager->createQueryForType($className);
288 $query->getQuerySettings()->setRespectStoragePage(
false);
289 $query->getQuerySettings()->setRespectSysLanguage(
false);
290 return $query->matching($query->equals(
'uid', $identifier))->execute()->getFirst();
313 $this->aggregateRootObjects = $objects;
324 $this->changedEntities = $entities;
335 $this->deletedEntities = $entities;
345 $this->persistObjects();
354 protected function persistObjects()
356 $this->visitedDuringPersistence = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
357 foreach ($this->aggregateRootObjects as $object) {
359 if ($object->_isNew()) {
364 foreach ($this->changedEntities as $object) {
377 if (isset($this->visitedDuringPersistence[$object])) {
382 $dataMap = $this->dataMapper->getDataMap(get_class($object));
383 $properties = $object->_getProperties();
384 foreach ($properties as $propertyName => $propertyValue) {
388 $columnMap = $dataMap->getColumnMap($propertyName);
389 if ($propertyValue instanceof \TYPO3\CMS\Extbase\Persistence\
ObjectStorage) {
390 $cleanProperty = $object->_getCleanProperty($propertyName);
394 if ($object->_isNew() || $propertyValue->_isDirty() || ($propertyValue->count() === 0 && $cleanProperty && $cleanProperty->count() > 0)) {
395 $this->persistObjectStorage($propertyValue, $object, $propertyName, $row);
396 $propertyValue->_memorizeCleanState();
398 foreach ($propertyValue as $containedObject) {
400 $queue[] = $containedObject;
405 if ($object->_isDirty($propertyName)) {
406 if ($propertyValue->_isNew()) {
407 $this->
insertObject($propertyValue, $object, $propertyName);
410 $row[$columnMap->getColumnName()] = $propertyValue !== null
411 ? $this->dataMapper->getPlainValue($propertyValue)
414 $queue[] = $propertyValue;
415 }
elseif ($object->_isNew() || $object->_isDirty($propertyName)) {
416 $row[$columnMap->getColumnName()] = $this->dataMapper->getPlainValue($propertyValue, $columnMap);
421 $object->_memorizeCleanState();
423 $this->visitedDuringPersistence[$object] = $object->getUid();
424 foreach ($queue as $queuedObject) {
438 if ($propertyValue instanceof \TYPO3\CMS\Extbase\Persistence\Generic\
LazyLoadingProxy) {
441 if ($propertyValue instanceof \TYPO3\CMS\Extbase\Persistence\Generic\
LazyObjectStorage) {
442 if ($propertyValue->isInitialized() ===
false) {
460 protected function persistObjectStorage(\TYPO3\CMS\Extbase\Persistence\
ObjectStorage $objectStorage, \TYPO3\CMS\Extbase\DomainObject\
DomainObjectInterface $parentObject, $propertyName, array &$row)
462 $className = get_class($parentObject);
463 $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName);
464 $propertyMetaData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName);
467 if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY && $propertyMetaData[
'cascade'] ===
'remove') {
472 $currentUids = array();
473 $sortingPosition = 1;
474 $updateSortingOfFollowing =
false;
476 foreach ($objectStorage as $object) {
478 if (empty($currentUids)) {
479 $sortingPosition = 1;
483 $cleanProperty = $parentObject->_getCleanProperty($propertyName);
484 if ($object->_isNew()) {
488 $updateSortingOfFollowing =
true;
489 }
elseif ($cleanProperty === null || $cleanProperty->getPosition($object) === null) {
493 $updateSortingOfFollowing =
true;
494 }
elseif ($objectStorage->isRelationDirty($object) || $cleanProperty->getPosition($object) !== $objectStorage->getPosition($object)) {
496 $updateSortingOfFollowing =
true;
497 }
elseif ($updateSortingOfFollowing) {
498 if ($sortingPosition > $objectStorage->getPosition($object)) {
501 $sortingPosition = $objectStorage->getPosition($object);
504 $currentUids[] = $object->getUid();
507 if ($columnMap->getParentKeyFieldName() === null) {
508 $row[$columnMap->getColumnName()] = implode(
',', $currentUids);
510 $row[$columnMap->getColumnName()] = $this->dataMapper->countRelated($parentObject, $propertyName);
524 $removedObjects = array();
525 $cleanPropertyValue = $object->_getCleanProperty($propertyName);
526 if (is_array($cleanPropertyValue) || $cleanPropertyValue instanceof \Iterator) {
527 $propertyValue = $object->_getProperty($propertyName);
528 foreach ($cleanPropertyValue as $containedObject) {
529 if (!$propertyValue->contains($containedObject)) {
530 $removedObjects[] = $containedObject;
534 return $removedObjects;
548 $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
549 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
550 if ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
552 }
elseif ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
568 $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
569 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
570 if ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
572 }
elseif ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
589 $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
590 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
591 if ($parentColumnMap->getTypeOfRelation() !== \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
592 throw new \TYPO3\CMS\Extbase\Persistence\Exception\IllegalRelationTypeException(
593 'Parent column relation type is ' . $parentColumnMap->getTypeOfRelation() .
594 ' but should be ' . \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY,
599 $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName();
600 if ($parentKeyFieldName !== null) {
601 $row[$parentKeyFieldName] = $parentObject->getUid();
602 $parentTableFieldName = $parentColumnMap->getParentTableFieldName();
603 if ($parentTableFieldName !== null) {
604 $row[$parentTableFieldName] = $parentDataMap->getTableName();
606 $relationTableMatchFields = $parentColumnMap->getRelationTableMatchFields();
607 if (is_array($relationTableMatchFields)) {
608 $row = array_merge($relationTableMatchFields, $row);
611 $childSortByFieldName = $parentColumnMap->getChildSortByFieldName();
612 if (!empty($childSortByFieldName)) {
613 $row[$childSortByFieldName] = $sortingPosition;
630 $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
631 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
632 if ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
634 $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName();
635 if ($parentKeyFieldName !== null) {
636 $row[$parentKeyFieldName] = 0;
637 $parentTableFieldName = $parentColumnMap->getParentTableFieldName();
638 if ($parentTableFieldName !== null) {
639 $row[$parentTableFieldName] =
'';
641 $relationTableMatchFields = $parentColumnMap->getRelationTableMatchFields();
642 if (is_array($relationTableMatchFields) && !empty($relationTableMatchFields)) {
643 $row = array_merge(array_fill_keys(array_keys($relationTableMatchFields),
''), $row);
646 $childSortByFieldName = $parentColumnMap->getChildSortByFieldName();
647 if (!empty($childSortByFieldName)) {
648 $row[$childSortByFieldName] = 0;
653 }
elseif ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
668 if ($object instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject) {
670 if ($result !==
false) {
671 $object->_setProperty(
'uid', (
int)$result);
675 $dataMap = $this->dataMapper->getDataMap(get_class($object));
677 $properties = $object->_getProperties();
678 foreach ($properties as $propertyName => $propertyValue) {
682 $columnMap = $dataMap->getColumnMap($propertyName);
684 $row[$columnMap->getColumnName()] = 0;
686 if ($columnMap->getParentKeyFieldName() === null) {
688 $row[$columnMap->getColumnName()] =
'';
691 $row[$columnMap->getColumnName()] = 0;
693 }
elseif ($propertyValue !== null) {
694 $row[$columnMap->getColumnName()] = $this->dataMapper->getPlainValue($propertyValue);
698 if ($dataMap->getLanguageIdColumnName() !== null && $object->_getProperty(
'_languageUid') === null) {
699 $row[$dataMap->getLanguageIdColumnName()] = 0;
700 $object->_setProperty(
'_languageUid', 0);
702 if ($dataMap->getTranslationOriginColumnName() !== null) {
703 $row[$dataMap->getTranslationOriginColumnName()] = 0;
705 if ($dataMap->getTranslationOriginDiffSourceName() !== null) {
706 $row[$dataMap->getTranslationOriginDiffSourceName()] =
'';
708 if ($parentObject !== null && $parentPropertyName) {
709 $parentColumnDataMap = $this->dataMapper->getDataMap(get_class($parentObject))->getColumnMap($parentPropertyName);
710 $relationTableMatchFields = $parentColumnDataMap->getRelationTableMatchFields();
711 if (is_array($relationTableMatchFields)) {
712 $row = array_merge($relationTableMatchFields, $row);
714 if ($parentColumnDataMap->getParentKeyFieldName() !== null) {
715 $row[$parentColumnDataMap->getParentKeyFieldName()] = (int)$parentObject->getUid();
718 $uid = $this->storageBackend->addRow($dataMap->getTableName(), $row);
719 $object->_setProperty(
'uid', (
int)$uid);
720 $object->setPid((
int)$row[
'pid']);
721 if ((
int)$uid >= 1) {
724 $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
725 if ($frameworkConfiguration[
'persistence'][
'updateReferenceIndex'] ===
'1') {
726 $this->referenceIndex->updateRefIndexTable($dataMap->getTableName(), $uid);
728 $this->session->registerObject($object, $uid);
729 if ((
int)$uid >= 1) {
741 $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterInsertObject', array($object));
752 $this->signalSlotDispatcher->dispatch(__CLASS__,
'endInsertObject', array($object));
763 return $this->storageBackend->getUidOfAlreadyPersistedValueObject($object);
777 $dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
778 $columnMap = $dataMap->getColumnMap($propertyName);
780 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
781 $columnMap->getChildKeyFieldName() => (int)$object->getUid(),
782 $columnMap->getChildSortByFieldName() => !is_null($sortingPosition) ? (int)$sortingPosition : 0
784 $relationTableName = $columnMap->getRelationTableName();
785 if ($columnMap->getRelationTablePageIdColumnName() !== null) {
788 $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
789 if (is_array($relationTableMatchFields)) {
790 $row = array_merge($relationTableMatchFields, $row);
792 $relationTableInsertFields = $columnMap->getRelationTableInsertFields();
793 if (is_array($relationTableInsertFields)) {
794 $row = array_merge($relationTableInsertFields, $row);
796 $res = $this->storageBackend->addRow($relationTableName, $row,
true);
811 $dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
812 $columnMap = $dataMap->getColumnMap($propertyName);
814 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
815 $columnMap->getChildKeyFieldName() => (int)$object->getUid(),
816 $columnMap->getChildSortByFieldName() => (int)$sortingPosition
818 $relationTableName = $columnMap->getRelationTableName();
819 $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
820 if (is_array($relationTableMatchFields)) {
821 $row = array_merge($relationTableMatchFields, $row);
823 $res = $this->storageBackend->updateRelationTableRow(
838 $dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
839 $columnMap = $dataMap->getColumnMap($parentPropertyName);
840 $relationTableName = $columnMap->getRelationTableName();
841 $relationMatchFields = array(
842 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid()
844 $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
845 if (is_array($relationTableMatchFields)) {
846 $relationMatchFields = array_merge($relationTableMatchFields, $relationMatchFields);
848 $res = $this->storageBackend->removeRow($relationTableName, $relationMatchFields,
false);
862 $dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
863 $columnMap = $dataMap->getColumnMap($parentPropertyName);
864 $relationTableName = $columnMap->getRelationTableName();
865 $relationMatchFields = array(
866 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
867 $columnMap->getChildKeyFieldName() => (int)$relatedObject->getUid()
869 $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
870 if (is_array($relationTableMatchFields)) {
871 $relationMatchFields = array_merge($relationTableMatchFields, $relationMatchFields);
873 $res = $this->storageBackend->removeRow($relationTableName, $relationMatchFields,
false);
887 $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
888 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
889 if ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
890 $tableName = $parentColumnMap->getChildTableName();
891 $sortByFieldName = $parentColumnMap->getChildSortByFieldName();
893 if (empty($sortByFieldName)) {
896 $matchFields = array();
897 $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName();
898 if ($parentKeyFieldName !== null) {
899 $matchFields[$parentKeyFieldName] = $parentObject->getUid();
900 $parentTableFieldName = $parentColumnMap->getParentTableFieldName();
901 if ($parentTableFieldName !== null) {
902 $matchFields[$parentTableFieldName] = $parentDataMap->getTableName();
906 if (empty($matchFields)) {
909 }
elseif ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
910 $tableName = $parentColumnMap->getRelationTableName();
911 $sortByFieldName = $parentColumnMap->getChildSortByFieldName();
913 $matchFields = array(
914 $parentColumnMap->getParentKeyFieldName() => (int)$parentObject->getUid()
917 $relationTableMatchFields = $parentColumnMap->getRelationTableMatchFields();
918 if (is_array($relationTableMatchFields)) {
919 $matchFields = array_merge($relationTableMatchFields, $matchFields);
922 throw new \TYPO3\CMS\Extbase\Persistence\Exception\IllegalRelationTypeException(
'Unexpected parent column relation type:' . $parentColumnMap->getTypeOfRelation(), 1345368106);
925 $result = $this->storageBackend->getMaxValueFromTable(
941 $dataMap = $this->dataMapper->getDataMap(get_class($object));
943 $row[
'uid'] = $object->getUid();
944 if ($dataMap->getLanguageIdColumnName() !== null) {
945 $row[$dataMap->getLanguageIdColumnName()] = (int)$object->_getProperty(
'_languageUid');
946 if ($object->_getProperty(
'_localizedUid') !== null) {
947 $row[
'uid'] = $object->_getProperty(
'_localizedUid');
950 $res = $this->storageBackend->updateRow($dataMap->getTableName(), $row);
954 $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
955 if ($frameworkConfiguration[
'persistence'][
'updateReferenceIndex'] ===
'1') {
956 $this->referenceIndex->updateRefIndexTable($dataMap->getTableName(), $row[
'uid']);
968 $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterUpdateObject', array($object));
978 $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterPersistObject', array($object));
990 $dataMap = $this->dataMapper->getDataMap(get_class($object));
992 if ($dataMap->getRecordTypeColumnName() !== null && $dataMap->getRecordType() !== null) {
993 $row[$dataMap->getRecordTypeColumnName()] = $dataMap->getRecordType();
995 if ($object->_isNew() && !isset($row[
'pid'])) {
1009 $dataMap = $this->dataMapper->getDataMap(get_class($object));
1010 if ($object->_isNew() && $dataMap->getCreationDateColumnName() !== null) {
1011 $row[$dataMap->getCreationDateColumnName()] =
$GLOBALS[
'EXEC_TIME'];
1013 if ($dataMap->getModificationDateColumnName() !== null) {
1014 $row[$dataMap->getModificationDateColumnName()] =
$GLOBALS[
'EXEC_TIME'];
1025 foreach ($this->deletedEntities as $entity) {
1026 if ($this->session->hasObject($entity)) {
1028 $this->session->unregisterReconstitutedEntity($entity);
1029 $this->session->unregisterObject($entity);
1032 $this->deletedEntities = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
1044 $dataMap = $this->dataMapper->getDataMap(get_class($object));
1045 $tableName = $dataMap->getTableName();
1046 if ($markAsDeleted ===
true && $dataMap->getDeletedFlagColumnName() !== null) {
1047 $deletedColumnName = $dataMap->getDeletedFlagColumnName();
1049 'uid' => $object->getUid(),
1050 $deletedColumnName => 1
1053 $res = $this->storageBackend->updateRow($tableName, $row);
1055 $res = $this->storageBackend->removeRow($tableName, array(
'uid' => $object->getUid()));
1057 if ($res ===
true) {
1061 $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
1062 if ($frameworkConfiguration[
'persistence'][
'updateReferenceIndex'] ===
'1') {
1063 $this->referenceIndex->updateRefIndexTable($tableName, $object->getUid());
1074 $this->signalSlotDispatcher->dispatch(__CLASS__,
'afterRemoveObject', array($object));
1085 $className = get_class($object);
1086 $dataMap = $this->dataMapper->getDataMap($className);
1087 $classSchema = $this->reflectionService->getClassSchema($className);
1088 $properties = $object->_getProperties();
1089 foreach ($properties as $propertyName => $propertyValue) {
1090 $columnMap = $dataMap->getColumnMap($propertyName);
1091 $propertyMetaData = $classSchema->getProperty($propertyName);
1092 if ($propertyMetaData[
'cascade'] ===
'remove') {
1093 if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
1094 foreach ($propertyValue as $containedObject) {
1117 $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
1118 if ($object !== null) {
1119 if (\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($object,
'pid')) {
1120 $pid = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($object,
'pid');
1125 $className = get_class($object);
1126 if (isset($frameworkConfiguration[
'persistence'][
'classes'][$className]) && !empty($frameworkConfiguration[
'persistence'][
'classes'][$className][
'newRecordStoragePid'])) {
1127 return (
int)$frameworkConfiguration[
'persistence'][
'classes'][$className][
'newRecordStoragePid'];
1130 $storagePidList = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(
',', $frameworkConfiguration[
'persistence'][
'storagePid']);
1131 return (
int)$storagePidList[0];