[TASK] Make DataMapper not a singleton 87/58287/21
authorTymoteusz Motylewski <t.motylewski@gmail.com>
Sat, 15 Sep 2018 19:16:28 +0000 (21:16 +0200)
committerMarkus Klein <markus.klein@typo3.org>
Thu, 20 Sep 2018 17:41:22 +0000 (19:41 +0200)
DataMapper is not a singleton any more. Thanks to that, a further
refactoring can be done to pass aggregate root query configuration
to the DataMapper, which will allow to fix inconsistencies
in Extbase language handling.

The runtime cache of data maps is moved to DataMapFactory.

Resolves: #86268
Releases: master
Change-Id: I003451c4d07855ff25d695578c9ec7b443f630bc
Reviewed-on: https://review.typo3.org/58287
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
16 files changed:
typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php
typo3/sysext/extbase/Classes/Persistence/Generic/LazyLoadingProxy.php
typo3/sysext/extbase/Classes/Persistence/Generic/LazyObjectStorage.php
typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapFactory.php
typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapper.php
typo3/sysext/extbase/Classes/Persistence/Generic/Query.php
typo3/sysext/extbase/Classes/Persistence/Generic/QueryFactory.php
typo3/sysext/extbase/Classes/Persistence/Generic/QueryResult.php
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
typo3/sysext/extbase/Tests/Unit/Persistence/Generic/BackendTest.php
typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php
typo3/sysext/extbase/Tests/Unit/Persistence/Generic/QueryFactoryTest.php
typo3/sysext/extbase/Tests/Unit/Persistence/Generic/QueryTest.php
typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbBackendTest.php
typo3/sysext/extensionmanager/Classes/Domain/Repository/ExtensionRepository.php

index f3f6035..f3d479f 100644 (file)
@@ -14,8 +14,11 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
+use TYPO3\CMS\Extbase\Object\ObjectManager;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap;
+use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
 use TYPO3\CMS\Extbase\Persistence\ObjectMonitoringInterface;
 
 /**
@@ -70,9 +73,9 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
     protected $storageBackend;
 
     /**
-     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
+     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
-    protected $dataMapper;
+    protected $dataMapFactory;
 
     /**
      * The TYPO3 reference index object
@@ -124,11 +127,11 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
     }
 
     /**
-     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
+     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory
      */
-    public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
+    public function injectDataMapFactory(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory)
     {
-        $this->dataMapper = $dataMapper;
+        $this->dataMapFactory = $dataMapFactory;
     }
 
     /**
@@ -173,16 +176,6 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
     }
 
     /**
-     * Returns the Data Mapper
-     *
-     * @return \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
-     */
-    public function getDataMapper()
-    {
-        return $this->dataMapper;
-    }
-
-    /**
      * Returns the current QOM factory
      *
      * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelFactory
@@ -371,7 +364,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
         }
         $row = [];
         $queue = [];
-        $dataMap = $this->dataMapper->getDataMap(get_class($object));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
         $properties = $object->_getProperties();
         foreach ($properties as $propertyName => $propertyValue) {
             if (!$dataMap->isPersistableProperty($propertyName) || $this->propertyValueIsLazyLoaded($propertyValue)) {
@@ -449,7 +442,9 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
     protected function persistObjectStorage(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $objectStorage, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, array &$row)
     {
         $className = get_class($parentObject);
-        $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName);
+        $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
+        $dataMapper = $objectManager->get(DataMapper::class);
+        $columnMap = $this->dataMapFactory->buildDataMap($className)->getColumnMap($propertyName);
         $propertyMetaData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName);
         foreach ($this->getRemovedChildObjects($parentObject, $propertyName) as $removedObject) {
             $this->detachObjectFromParentObject($removedObject, $parentObject, $propertyName);
@@ -496,7 +491,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
         if ($columnMap->getParentKeyFieldName() === null) {
             $row[$columnMap->getColumnName()] = implode(',', $currentUids);
         } else {
-            $row[$columnMap->getColumnName()] = $this->dataMapper->countRelated($parentObject, $propertyName);
+            $row[$columnMap->getColumnName()] = $dataMapper->countRelated($parentObject, $propertyName);
         }
     }
 
@@ -533,7 +528,8 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function attachObjectToParentObject(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $parentPropertyName, $sortingPosition = 0)
     {
-        $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+        $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
+
         $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
         if ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
             $this->attachObjectToParentObjectRelationHasMany($object, $parentObject, $parentPropertyName, $sortingPosition);
@@ -552,7 +548,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function updateRelationOfObjectToParentObject(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, \TYPO3\CMS\Extbase\DomainObject\AbstractEntity $parentObject, $parentPropertyName, $sortingPosition = 0)
     {
-        $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+        $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
         $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
         if ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
             $this->attachObjectToParentObjectRelationHasMany($object, $parentObject, $parentPropertyName, $sortingPosition);
@@ -572,7 +568,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function attachObjectToParentObjectRelationHasMany(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, \TYPO3\CMS\Extbase\DomainObject\AbstractEntity $parentObject, $parentPropertyName, $sortingPosition = 0)
     {
-        $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+        $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
         $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
         if ($parentColumnMap->getTypeOfRelation() !== \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
             throw new \TYPO3\CMS\Extbase\Persistence\Exception\IllegalRelationTypeException(
@@ -612,7 +608,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function detachObjectFromParentObject(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $parentPropertyName)
     {
-        $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+        $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
         $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
         if ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
             $row = [];
@@ -656,7 +652,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
                 return;
             }
         }
-        $dataMap = $this->dataMapper->getDataMap(get_class($object));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
         $row = [];
         $properties = $object->_getProperties();
         foreach ($properties as $propertyName => $propertyValue) {
@@ -690,7 +686,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
             $row[$dataMap->getTranslationOriginDiffSourceName()] = '';
         }
         if ($parentObject !== null && $parentPropertyName) {
-            $parentColumnDataMap = $this->dataMapper->getDataMap(get_class($parentObject))->getColumnMap($parentPropertyName);
+            $parentColumnDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject))->getColumnMap($parentPropertyName);
             $relationTableMatchFields = $parentColumnDataMap->getRelationTableMatchFields();
             if (is_array($relationTableMatchFields)) {
                 $row = array_merge($relationTableMatchFields, $row);
@@ -758,7 +754,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function insertRelationInRelationtable(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $sortingPosition = null)
     {
-        $dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
         $columnMap = $dataMap->getColumnMap($propertyName);
         $parentUid = $parentObject->getUid();
         if ($parentObject->_getProperty('_localizedUid') !== null) {
@@ -796,7 +792,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function updateRelationInRelationTable(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $sortingPosition = 0)
     {
-        $dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
         $columnMap = $dataMap->getColumnMap($propertyName);
         $row = [
             $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
@@ -824,7 +820,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function deleteAllRelationsFromRelationtable(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $parentPropertyName)
     {
-        $dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
         $columnMap = $dataMap->getColumnMap($parentPropertyName);
         $relationTableName = $columnMap->getRelationTableName();
         $relationMatchFields = [
@@ -848,7 +844,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function deleteRelationFromRelationtable(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $relatedObject, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $parentPropertyName)
     {
-        $dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
         $columnMap = $dataMap->getColumnMap($parentPropertyName);
         $relationTableName = $columnMap->getRelationTableName();
         $relationMatchFields = [
@@ -873,7 +869,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function fetchMaxSortingFromParentTable(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $parentPropertyName)
     {
-        $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+        $parentDataMap = $this->dataMapFactory->buildDataMap(get_class($parentObject));
         $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
         if ($parentColumnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
             $tableName = $parentColumnMap->getChildTableName();
@@ -928,7 +924,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function updateObject(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, array $row)
     {
-        $dataMap = $this->dataMapper->getDataMap(get_class($object));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
         $this->addCommonFieldsToRow($object, $row);
         $row['uid'] = $object->getUid();
         if ($dataMap->getLanguageIdColumnName() !== null) {
@@ -976,7 +972,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function addCommonFieldsToRow(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, array &$row)
     {
-        $dataMap = $this->dataMapper->getDataMap(get_class($object));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
         $this->addCommonDateFieldsToRow($object, $row);
         if ($dataMap->getRecordTypeColumnName() !== null && $dataMap->getRecordType() !== null) {
             $row[$dataMap->getRecordTypeColumnName()] = $dataMap->getRecordType();
@@ -994,7 +990,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function addCommonDateFieldsToRow(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, array &$row)
     {
-        $dataMap = $this->dataMapper->getDataMap(get_class($object));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
         if ($object->_isNew() && $dataMap->getCreationDateColumnName() !== null) {
             $row[$dataMap->getCreationDateColumnName()] = $GLOBALS['EXEC_TIME'];
         }
@@ -1026,7 +1022,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function removeEntity(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, $markAsDeleted = true)
     {
-        $dataMap = $this->dataMapper->getDataMap(get_class($object));
+        $dataMap = $this->dataMapFactory->buildDataMap(get_class($object));
         $tableName = $dataMap->getTableName();
         if ($markAsDeleted === true && $dataMap->getDeletedFlagColumnName() !== null) {
             $deletedColumnName = $dataMap->getDeletedFlagColumnName();
@@ -1067,7 +1063,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
     protected function removeRelatedObjects(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object)
     {
         $className = get_class($object);
-        $dataMap = $this->dataMapper->getDataMap($className);
+        $dataMap = $this->dataMapFactory->buildDataMap($className);
         $classSchema = $this->reflectionService->getClassSchema($className);
         $properties = $object->_getProperties();
         foreach ($properties as $propertyName => $propertyValue) {
@@ -1134,8 +1130,10 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
      */
     protected function getPlainValue($input, ColumnMap $columnMap = null)
     {
+        $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
+        $dataMapper = $objectManager->get(DataMapper::class);
         return $input !== null
-            ? $this->dataMapper->getPlainValue($input, $columnMap)
+            ? $dataMapper->getPlainValue($input, $columnMap)
             : null;
     }
 }
index 102eedb..677001e 100644 (file)
@@ -15,6 +15,8 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic;
  */
 
 use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
+use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
+use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
 
 /**
  * A proxy that can replace any object and replaces itself in it's parent on
@@ -23,7 +25,7 @@ use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
 class LazyLoadingProxy implements \Iterator, \TYPO3\CMS\Extbase\Persistence\Generic\LoadingStrategyInterface
 {
     /**
-     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
+     * @var DataMapper
      */
     protected $dataMapper;
 
@@ -49,11 +51,16 @@ class LazyLoadingProxy implements \Iterator, \TYPO3\CMS\Extbase\Persistence\Gene
     private $fieldValue;
 
     /**
-     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
+     * @var ObjectManagerInterface
      */
-    public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
+    protected $objectManager;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     */
+    public function injectObjectManager(ObjectManagerInterface $objectManager)
     {
-        $this->dataMapper = $dataMapper;
+        $this->objectManager = $objectManager;
     }
 
     /**
@@ -71,6 +78,14 @@ class LazyLoadingProxy implements \Iterator, \TYPO3\CMS\Extbase\Persistence\Gene
     }
 
     /**
+     * Object initialization called when object is created with ObjectManager, after constructor
+     */
+    public function initializeObject()
+    {
+        $this->dataMapper = $this->objectManager->get(DataMapper::class);
+    }
+
+    /**
      * Populate this proxy by asking the $population closure.
      *
      * @return object The instance (hopefully) returned
index 1a0287d..f367995 100644 (file)
@@ -15,6 +15,8 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic;
  */
 
 use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
+use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
+use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
 
 /**
  * A proxy that can replace any object and replaces itself in it's parent on
@@ -64,11 +66,16 @@ class LazyObjectStorage extends \TYPO3\CMS\Extbase\Persistence\ObjectStorage imp
     protected $isInitialized = false;
 
     /**
-     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
+     * @var ObjectManagerInterface
      */
-    public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
+    protected $objectManager;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     */
+    public function injectObjectManager(ObjectManagerInterface $objectManager)
     {
-        $this->dataMapper = $dataMapper;
+        $this->objectManager = $objectManager;
     }
 
     /**
@@ -97,6 +104,14 @@ class LazyObjectStorage extends \TYPO3\CMS\Extbase\Persistence\ObjectStorage imp
     }
 
     /**
+     * Object initialization called when object is created with ObjectManager, after constructor
+     */
+    public function initializeObject()
+    {
+        $this->dataMapper = $this->objectManager->get(DataMapper::class);
+    }
+
+    /**
      * This is a function lazy load implementation.
      */
     protected function initialize()
index 8f465a5..90cb1cf 100644 (file)
@@ -47,6 +47,13 @@ class DataMapFactory implements \TYPO3\CMS\Core\SingletonInterface
     protected $dataMapCache;
 
     /**
+     * Runtime cache for data maps, to reduce number of calls to cache backend.
+     *
+     * @var array
+     */
+    protected $dataMaps = [];
+
+    /**
      * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService
      */
     public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService)
@@ -96,11 +103,15 @@ class DataMapFactory implements \TYPO3\CMS\Core\SingletonInterface
      */
     public function buildDataMap($className)
     {
+        if (isset($this->dataMaps[$className])) {
+            return $this->dataMaps[$className];
+        }
         $dataMap = $this->dataMapCache->get(str_replace('\\', '%', $className));
         if ($dataMap === false) {
             $dataMap = $this->buildDataMapInternal($className);
             $this->dataMapCache->set(str_replace('\\', '%', $className), $dataMap);
         }
+        $this->dataMaps[$className] = $dataMap;
         return $dataMap;
     }
 
index 1334208..cb0f7d1 100644 (file)
@@ -24,7 +24,7 @@ use TYPO3\CMS\Extbase\Utility\TypeHandlingUtility;
 /**
  * A mapper to map database tables configured in $TCA on domain objects.
  */
-class DataMapper implements \TYPO3\CMS\Core\SingletonInterface
+class DataMapper
 {
     /**
      * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
@@ -49,13 +49,6 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface
     protected $pageSelectObject;
 
     /**
-     * Cached data maps
-     *
-     * @var array
-     */
-    protected $dataMaps = [];
-
-    /**
      * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
     protected $dataMapFactory;
@@ -616,10 +609,7 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface
         if (!is_string($className) || $className === '') {
             throw new Persistence\Generic\Exception('No class name was given to retrieve the Data Map for.', 1251315965);
         }
-        if (!isset($this->dataMaps[$className])) {
-            $this->dataMaps[$className] = $this->dataMapFactory->buildDataMap($className);
-        }
-        return $this->dataMaps[$className];
+        return $this->dataMapFactory->buildDataMap($className);
     }
 
     /**
index 3b839be..3d7b91d 100644 (file)
@@ -54,9 +54,9 @@ class Query implements QueryInterface
     protected $objectManager;
 
     /**
-     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
+     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
-    protected $dataMapper;
+    protected $dataMapFactory;
 
     /**
      * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
@@ -114,11 +114,11 @@ class Query implements QueryInterface
     }
 
     /**
-     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
+     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory
      */
-    public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
+    public function injectDataMapFactory(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory)
     {
-        $this->dataMapper = $dataMapper;
+        $this->dataMapFactory = $dataMapFactory;
     }
 
     /**
@@ -218,7 +218,7 @@ class Query implements QueryInterface
     public function getSource()
     {
         if ($this->source === null) {
-            $this->source = $this->qomFactory->selector($this->getType(), $this->dataMapper->convertClassNameToTableName($this->getType()));
+            $this->source = $this->qomFactory->selector($this->getType(), $this->dataMapFactory->buildDataMap($this->getType())->getTableName());
         }
         return $this->source;
     }
@@ -609,7 +609,7 @@ class Query implements QueryInterface
     {
         $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
         $this->persistenceManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface::class);
-        $this->dataMapper = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);
+        $this->dataMapFactory = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory::class);
         $this->qomFactory = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelFactory::class);
     }
 
index 2946da8..c6f1b9b 100644 (file)
@@ -30,9 +30,9 @@ class QueryFactory implements QueryFactoryInterface, \TYPO3\CMS\Core\SingletonIn
     protected $configurationManager;
 
     /**
-     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
+     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
-    protected $dataMapper;
+    protected $dataMapFactory;
 
     /**
      * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
@@ -51,11 +51,11 @@ class QueryFactory implements QueryFactoryInterface, \TYPO3\CMS\Core\SingletonIn
     }
 
     /**
-     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
+     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory
      */
-    public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
+    public function injectDataMapFactory(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory)
     {
-        $this->dataMapper = $dataMapper;
+        $this->dataMapFactory = $dataMapFactory;
     }
 
     /**
@@ -70,7 +70,7 @@ class QueryFactory implements QueryFactoryInterface, \TYPO3\CMS\Core\SingletonIn
         $query = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class, $className);
         $querySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class);
 
-        $dataMap = $this->dataMapper->getDataMap($className);
+        $dataMap = $this->dataMapFactory->buildDataMap($className);
         if ($dataMap->getIsStatic() || $dataMap->getRootLevel()) {
             $querySettings->setRespectStoragePage(false);
         }
index 2953267..dcd66da 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
+use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
 use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
 
 /**
@@ -49,11 +51,16 @@ class QueryResult implements QueryResultInterface
     protected $queryResult;
 
     /**
-     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
+     * @var ObjectManagerInterface
      */
-    public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
+    protected $objectManager;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     */
+    public function injectObjectManager(ObjectManagerInterface $objectManager)
     {
-        $this->dataMapper = $dataMapper;
+        $this->objectManager = $objectManager;
     }
 
     /**
@@ -75,6 +82,14 @@ class QueryResult implements QueryResultInterface
     }
 
     /**
+     * Object initialization called when object is created with ObjectManager, after constructor
+     */
+    public function initializeObject()
+    {
+        $this->dataMapper = $this->objectManager->get(DataMapper::class);
+    }
+
+    /**
      * Loads the objects this QueryResult is supposed to hold
      */
     protected function initialize()
@@ -254,7 +269,6 @@ class QueryResult implements QueryResultInterface
     {
         $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
         $this->persistenceManager = $objectManager->get(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface::class);
-        $this->dataMapper = $objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);
     }
 
     /**
index 692e014..654d222 100644 (file)
@@ -50,11 +50,6 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
     protected $connectionPool;
 
     /**
-     * @var DataMapper
-     */
-    protected $dataMapper;
-
-    /**
      * @var ConfigurationManagerInterface
      */
     protected $configurationManager;
@@ -83,14 +78,6 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
     protected $hasPidColumn = [];
 
     /**
-     * @param DataMapper $dataMapper
-     */
-    public function injectDataMapper(DataMapper $dataMapper)
-    {
-        $this->dataMapper = $dataMapper;
-    }
-
-    /**
      * @param ConfigurationManagerInterface $configurationManager
      */
     public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
@@ -497,7 +484,8 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
      */
     public function getUidOfAlreadyPersistedValueObject(AbstractValueObject $object)
     {
-        $dataMap = $this->dataMapper->getDataMap(get_class($object));
+        $dataMapper = $this->objectManager->get(DataMapper::class);
+        $dataMap = $dataMapper->getDataMap(get_class($object));
         $tableName = $dataMap->getTableName();
         $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
         if ($this->environmentService->isEnvironmentInFrontendMode()) {
@@ -513,7 +501,7 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
                 if ($propertyValue === null) {
                     $whereClause[] = $queryBuilder->expr()->isNull($fieldName);
                 } else {
-                    $whereClause[] = $queryBuilder->expr()->eq($fieldName, $queryBuilder->createNamedParameter($this->dataMapper->getPlainValue($propertyValue)));
+                    $whereClause[] = $queryBuilder->expr()->eq($fieldName, $queryBuilder->createNamedParameter($dataMapper->getPlainValue($propertyValue)));
                 }
             }
         }
index cfe449a..7cd508c 100644 (file)
@@ -22,6 +22,7 @@ use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
 use TYPO3\CMS\Extbase\Persistence\Generic\Exception;
 use TYPO3\CMS\Extbase\Persistence\Generic\Exception\InconsistentQuerySettingsException;
 use TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException;
@@ -102,11 +103,24 @@ class Typo3DbQueryParser
     protected $suggestDistinctQuery = false;
 
     /**
-     * @param DataMapper $dataMapper
+     * @var ObjectManagerInterface
      */
-    public function injectDataMapper(DataMapper $dataMapper)
+    protected $objectManager;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     */
+    public function injectObjectManager(ObjectManagerInterface $objectManager)
+    {
+        $this->objectManager = $objectManager;
+    }
+
+    /**
+     * Object initialization called when object is created with ObjectManager, after constructor
+     */
+    public function initializeObject()
     {
-        $this->dataMapper = $dataMapper;
+        $this->dataMapper = $this->objectManager->get(DataMapper::class);
     }
 
     /**
index b650a7d..36142a6 100644 (file)
@@ -22,7 +22,7 @@ use TYPO3\CMS\Extbase\Persistence\Generic\Backend;
 use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap;
-use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
+use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory;
 use TYPO3\CMS\Extbase\Persistence\Generic\Storage\BackendInterface;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
@@ -39,7 +39,7 @@ class BackendTest extends UnitTestCase
         /* \TYPO3\CMS\Extbase\Persistence\Generic\Backend|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface */
         $fixture = $this->getAccessibleMock(Backend::class, ['dummy'], [], '', false);
         /* \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper|\PHPUnit_Framework_MockObject_MockObject */
-        $dataMapper = $this->createMock(DataMapper::class);
+        $dataMapFactory = $this->createMock(DataMapFactory::class);
         /* \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap|\PHPUnit_Framework_MockObject_MockObject */
         $dataMap = $this->createMock(DataMap::class);
         /* \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap|\PHPUnit_Framework_MockObject_MockObject */
@@ -70,16 +70,16 @@ class BackendTest extends UnitTestCase
             ->expects($this->any())
             ->method('getColumnMap')
             ->will($this->returnValue($columnMap));
-        $dataMapper
+        $dataMapFactory
             ->expects($this->any())
-            ->method('getDataMap')
+            ->method('buildDataMap')
             ->will($this->returnValue($dataMap));
         $storageBackend
             ->expects($this->once())
             ->method('addRow')
             ->with(null, $expectedRow, true);
 
-        $fixture->_set('dataMapper', $dataMapper);
+        $fixture->_set('dataMapFactory', $dataMapFactory);
         $fixture->_set('storageBackend', $storageBackend);
         $fixture->_call('insertRelationInRelationtable', $domainObject, $domainObject, '');
     }
@@ -119,7 +119,7 @@ class BackendTest extends UnitTestCase
         $parentObject = new \stdClass();
         $proxy = $this->getMockBuilder(LazyLoadingProxy::class)
             ->setMethods(['_loadRealInstance'])
-            ->setConstructorArgs([$parentObject, 'y', 'z'])
+            ->disableOriginalConstructor()
             ->disableProxyingToOriginalMethods()
             ->getMock();
         $session = $this->getMockBuilder('stdClass')
index 3b42ade..87cb6d7 100644 (file)
@@ -91,9 +91,11 @@ class DataMapperTest extends UnitTestCase
             ->setMethods(['getClassSchema'])
             ->getMock();
         $mockReflectionService->expects($this->any())->method('getClassSchema')->will($this->returnValue($classSchema));
+        $dataMapFactory = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory::class, ['dummy']);
+        $dataMapFactory->_set('dataMaps', $dataMaps);
         $dataMapper = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class, ['dummy']);
-        $dataMapper->_set('dataMaps', $dataMaps);
         $dataMapper->_set('reflectionService', $mockReflectionService);
+        $dataMapper->_set('dataMapFactory', $dataMapFactory);
         $dataMapper->_call('thawProperties', $object, $row);
         $this->assertAttributeEquals('firstValue', 'firstProperty', $object);
         $this->assertAttributeEquals(1234, 'secondProperty', $object);
index df24445..66f0eae 100644 (file)
@@ -30,9 +30,9 @@ class QueryFactoryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
     protected $queryFactory;
 
     /**
-     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper|\PHPUnit_Framework_MockObject_MockObject
+     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $dataMapper;
+    protected $dataMapFactory;
 
     /**
      * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap|\PHPUnit_Framework_MockObject_MockObject
@@ -52,11 +52,11 @@ class QueryFactoryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             $this->createMock(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::class)
         );
 
-        $this->dataMapper = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class)
-            ->setMethods(['getDataMap', 'convertClassNameToTableName'])
+        $this->dataMapFactory = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory::class)
+            ->setMethods(['buildDataMap', 'convertClassNameToTableName'])
             ->getMock();
-        $this->dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($this->dataMap));
-        $this->queryFactory->_set('dataMapper', $this->dataMapper);
+        $this->dataMapFactory->expects($this->any())->method('buildDataMap')->will($this->returnValue($this->dataMap));
+        $this->queryFactory->_set('dataMapFactory', $this->dataMapFactory);
     }
 
     public function getStaticAndRootLevelAndExpectedResult()
index d472640..ae88a1b 100644 (file)
@@ -20,7 +20,7 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic;
 class QueryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
 {
     /**
-     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Query
+     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Query|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface
      */
     protected $query;
 
@@ -35,22 +35,22 @@ class QueryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
     protected $persistenceManager;
 
     /**
-     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
+     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
-    protected $dataMapper;
+    protected $dataMapFactory;
 
     /**
      * Sets up this test case
      */
     protected function setUp()
     {
-        $this->query = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Query::class, ['dummy'], ['someType']);
+        $this->query = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Query::class, ['getSelectorName'], ['someType']);
         $this->querySettings = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class);
         $this->query->_set('querySettings', $this->querySettings);
         $this->persistenceManager = $this->createMock(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface::class);
         $this->query->_set('persistenceManager', $this->persistenceManager);
-        $this->dataMapper = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);
-        $this->query->_set('dataMapper', $this->dataMapper);
+        $this->dataMapFactory = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory::class);
+        $this->query->_set('dataMapFactory', $this->dataMapFactory);
     }
 
     /**
@@ -151,6 +151,7 @@ class QueryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
         $qomFactory = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelFactory::class, ['comparison']);
         $qomFactory->_set('objectManager', $objectManager);
         $qomFactory->expects($this->once())->method('comparison')->with($this->anything(), $this->anything(), $expectedOperand);
+        $this->query->expects($this->any())->method('getSelectorName')->will($this->returnValue('someSelector'));
         $this->query->_set('qomFactory', $qomFactory);
         $this->query->equals($propertyName, $operand, false);
     }
index af158ea..05f32d5 100644 (file)
@@ -119,6 +119,13 @@ class Typo3DbBackendTest extends UnitTestCase
             '',
             false
         );
+        $mockObjectManager = $this->getAccessibleMock(ObjectManager::class, ['get']);
+        $mockObjectManager->expects($this->any())
+            ->method('get')
+            ->with(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class)
+            ->will($this->returnValue($mockDataMapper));
+
+        $mockTypo3DbBackend->_set('objectManager', $mockObjectManager);
         $mockTypo3DbBackend->_set('dataMapper', $mockDataMapper);
         $mockTypo3DbBackend->_set('connectionPool', $connectionPoolProphet->reveal());
         $mockTypo3DbBackend->_set('environmentService', $environmentServiceProphet->reveal());
index c668115..0b8dc3e 100644 (file)
@@ -30,19 +30,6 @@ class ExtensionRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
     const TABLE_NAME = 'tx_extensionmanager_domain_model_extension';
 
     /**
-     * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
-     */
-    protected $dataMapper;
-
-    /**
-     * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
-     */
-    public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
-    {
-        $this->dataMapper = $dataMapper;
-    }
-
-    /**
      * Do not include pid in queries
      */
     public function initializeObject()
@@ -195,7 +182,8 @@ class ExtensionRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
             ->execute()
             ->fetchAll();
 
-        return $this->dataMapper->map(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, $result);
+        $dataMapper = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);
+        return $dataMapper->map(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, $result);
     }
 
     /**