[CLEANUP] Remove redundant code in Persistence 76/28576/21
authorAlexander Stehlik <alexander.stehlik@gmail.com>
Mon, 24 Mar 2014 10:35:48 +0000 (11:35 +0100)
committerMarkus Klein <klein.t3@mfc-linz.at>
Sun, 29 Jun 2014 15:42:46 +0000 (17:42 +0200)
The getPlainValue method is consolidated in the DataMapper.

Resolves: #57255
Releases: 6.3
Change-Id: Ic35fd2768a1431f260c99d6faf8ad4e0a1754ea3
Reviewed-on: https://review.typo3.org/28576
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
Reviewed-by: Markus Klein
Tested-by: Markus Klein
typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php
typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapper.php
typo3/sysext/extbase/Classes/Persistence/Generic/Query.php
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
typo3/sysext/extbase/Classes/Utility/TypeHandlingUtility.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/Storage/Typo3DbBackendTest.php
typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php

index 88c761f..f8e673c 100644 (file)
@@ -376,11 +376,14 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
                                        if ($propertyValue->_isNew()) {
                                                $this->insertObject($propertyValue, $object, $propertyName);
                                        }
                                        if ($propertyValue->_isNew()) {
                                                $this->insertObject($propertyValue, $object, $propertyName);
                                        }
-                                       $row[$columnMap->getColumnName()] = $this->getPlainValue($propertyValue);
+                                       // Check explicitly for NULL, as getPlainValue would convert this to 'NULL'
+                                       $row[$columnMap->getColumnName()] = $propertyValue !== NULL
+                                               ? $this->dataMapper->getPlainValue($propertyValue)
+                                               : NULL;
                                }
                                $queue[] = $propertyValue;
                        } elseif ($object->_isNew() || $object->_isDirty($propertyName)) {
                                }
                                $queue[] = $propertyValue;
                        } elseif ($object->_isNew() || $object->_isDirty($propertyName)) {
-                               $row[$columnMap->getColumnName()] = $this->getPlainValue($propertyValue, $columnMap);
+                               $row[$columnMap->getColumnName()] = $this->dataMapper->getPlainValue($propertyValue, $columnMap);
                        }
                }
                if (count($row) > 0) {
                        }
                }
                if (count($row) > 0) {
@@ -1020,35 +1023,4 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
                $storagePidList = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $frameworkConfiguration['persistence']['storagePid']);
                return (int)$storagePidList[0];
        }
                $storagePidList = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $frameworkConfiguration['persistence']['storagePid']);
                return (int)$storagePidList[0];
        }
-
-       /**
-        * Returns a plain value, i.e. objects are flattened out if possible.
-        *
-        * @param mixed $input
-        * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap $columnMap
-        * @return mixed
-        */
-       protected function getPlainValue($input, $columnMap = NULL) {
-               if ($input instanceof \DateTime) {
-                       if (!is_null($columnMap) && !is_null($columnMap->getDateTimeStorageFormat())) {
-                               if ($columnMap->getDateTimeStorageFormat() == 'datetime') {
-                                       return $input->format('Y-m-d H:i:s');
-                               }
-                               if ($columnMap->getDateTimeStorageFormat() == 'date') {
-                                       return $input->format('Y-m-d');
-                               }
-                       } else {
-                               return $input->format('U');
-                       }
-               } elseif ($input instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) {
-                       return $input->getUid();
-               } elseif ($input instanceof \TYPO3\CMS\Core\Type\TypeInterface) {
-                       return (string) $input;
-               } elseif (is_bool($input)) {
-                       return $input === TRUE ? 1 : 0;
-               } else {
-                       return $input;
-               }
-               return NULL;
-       }
 }
 }
index c8bcc53..1bde9db 100644 (file)
@@ -14,6 +14,10 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic\Mapper;
  * The TYPO3 project - inspiring people to share!
  */
 
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Extbase\Object\Exception\CannotReconstituteObjectException;
+use TYPO3\CMS\Extbase\Persistence;
+use TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException;
+use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
 use TYPO3\CMS\Extbase\Utility\TypeHandlingUtility;
 
 /**
 use TYPO3\CMS\Extbase\Utility\TypeHandlingUtility;
 
 /**
@@ -145,14 +149,15 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
         * Creates a skeleton of the specified object
         *
         * @param string $className Name of the class to create a skeleton for
         * Creates a skeleton of the specified object
         *
         * @param string $className Name of the class to create a skeleton for
-        * @throws \TYPO3\CMS\Extbase\Object\Exception\CannotReconstituteObjectException
+        * @throws CannotReconstituteObjectException
         * @return object The object skeleton
         */
        protected function createEmptyObject($className) {
                // Note: The class_implements() function also invokes autoload to assure that the interfaces
                // and the class are loaded. Would end up with __PHP_Incomplete_Class without it.
                if (!in_array('TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface', class_implements($className))) {
         * @return object The object skeleton
         */
        protected function createEmptyObject($className) {
                // Note: The class_implements() function also invokes autoload to assure that the interfaces
                // and the class are loaded. Would end up with __PHP_Incomplete_Class without it.
                if (!in_array('TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface', class_implements($className))) {
-                       throw new \TYPO3\CMS\Extbase\Object\Exception\CannotReconstituteObjectException('Cannot create empty instance of the class "' . $className . '" because it does not implement the TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface.', 1234386924);
+                       throw new CannotReconstituteObjectException('Cannot create empty instance of the class "' . $className
+                               . '" because it does not implement the TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface.', 1234386924);
                }
                $object = $this->objectManager->getEmptyObject($className);
                return $object;
                }
                $object = $this->objectManager->getEmptyObject($className);
                return $object;
@@ -161,11 +166,11 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * Sets the given properties on the object.
         *
        /**
         * Sets the given properties on the object.
         *
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object The object to set properties on
+        * @param DomainObjectInterface $object The object to set properties on
         * @param array $row
         * @return void
         */
         * @param array $row
         * @return void
         */
-       protected function thawProperties(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, array $row) {
+       protected function thawProperties(DomainObjectInterface $object, array $row) {
                $className = get_class($object);
                $classSchema = $this->reflectionService->getClassSchema($className);
                $dataMap = $this->getDataMap($className);
                $className = get_class($object);
                $classSchema = $this->reflectionService->getClassSchema($className);
                $dataMap = $this->getDataMap($className);
@@ -271,13 +276,13 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * Fetches a collection of objects related to a property of a parent object
         *
        /**
         * Fetches a collection of objects related to a property of a parent object
         *
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject The object instance this proxy is part of
+        * @param DomainObjectInterface $parentObject The object instance this proxy is part of
         * @param string $propertyName The name of the proxied property in it's parent
         * @param mixed $fieldValue The raw field value.
         * @param boolean $enableLazyLoading A flag indication if the related objects should be lazy loaded
         * @param string $propertyName The name of the proxied property in it's parent
         * @param mixed $fieldValue The raw field value.
         * @param boolean $enableLazyLoading A flag indication if the related objects should be lazy loaded
-        * @return \TYPO3\CMS\Extbase\Persistence\Generic\LazyObjectStorage|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface The result
+        * @return \TYPO3\CMS\Extbase\Persistence\Generic\LazyObjectStorage|Persistence\QueryResultInterface The result
         */
         */
-       public function fetchRelated(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $enableLazyLoading = TRUE) {
+       public function fetchRelated(DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $enableLazyLoading = TRUE) {
                $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
                if ($enableLazyLoading === TRUE && $propertyMetaData['lazy']) {
                        if (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
                $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
                if ($enableLazyLoading === TRUE && $propertyMetaData['lazy']) {
                        if (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
@@ -298,33 +303,33 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * Fetches the related objects from the storage backend.
         *
        /**
         * Fetches the related objects from the storage backend.
         *
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject The object instance this proxy is part of
+        * @param DomainObjectInterface $parentObject The object instance this proxy is part of
         * @param string $propertyName The name of the proxied property in it's parent
         * @param mixed $fieldValue The raw field value.
         * @return mixed
         */
         * @param string $propertyName The name of the proxied property in it's parent
         * @param mixed $fieldValue The raw field value.
         * @return mixed
         */
-       protected function fetchRelatedEager(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
+       protected function fetchRelatedEager(DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
                return $fieldValue === '' ? $this->getEmptyRelationValue($parentObject, $propertyName) : $this->getNonEmptyRelationValue($parentObject, $propertyName, $fieldValue);
        }
 
        /**
                return $fieldValue === '' ? $this->getEmptyRelationValue($parentObject, $propertyName) : $this->getNonEmptyRelationValue($parentObject, $propertyName, $fieldValue);
        }
 
        /**
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
+        * @param DomainObjectInterface $parentObject
         * @param string $propertyName
         * @return array|NULL
         */
         * @param string $propertyName
         * @return array|NULL
         */
-       protected function getEmptyRelationValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName) {
+       protected function getEmptyRelationValue(DomainObjectInterface $parentObject, $propertyName) {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
-               $relatesToOne = $columnMap->getTypeOfRelation() == \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE;
+               $relatesToOne = $columnMap->getTypeOfRelation() == ColumnMap::RELATION_HAS_ONE;
                return $relatesToOne ? NULL : array();
        }
 
        /**
                return $relatesToOne ? NULL : array();
        }
 
        /**
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
+        * @param DomainObjectInterface $parentObject
         * @param string $propertyName
         * @param string $fieldValue
         * @param string $propertyName
         * @param string $fieldValue
-        * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
+        * @return Persistence\QueryResultInterface
         */
         */
-       protected function getNonEmptyRelationValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue) {
+       protected function getNonEmptyRelationValue(DomainObjectInterface $parentObject, $propertyName, $fieldValue) {
                $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
                return $query->execute();
        }
                $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
                return $query->execute();
        }
@@ -332,25 +337,25 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * Builds and returns the prepared query, ready to be executed.
         *
        /**
         * Builds and returns the prepared query, ready to be executed.
         *
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
+        * @param DomainObjectInterface $parentObject
         * @param string $propertyName
         * @param string $fieldValue
         * @param string $propertyName
         * @param string $fieldValue
-        * @return \TYPO3\CMS\Extbase\Persistence\QueryInterface
+        * @return Persistence\QueryInterface
         */
         */
-       protected function getPreparedQuery(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
+       protected function getPreparedQuery(DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                $type = $this->getType(get_class($parentObject), $propertyName);
                $query = $this->queryFactory->create($type);
                $query->getQuerySettings()->setRespectStoragePage(FALSE);
                $query->getQuerySettings()->setRespectSysLanguage(FALSE);
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                $type = $this->getType(get_class($parentObject), $propertyName);
                $query = $this->queryFactory->create($type);
                $query->getQuerySettings()->setRespectStoragePage(FALSE);
                $query->getQuerySettings()->setRespectSysLanguage(FALSE);
-               if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
+               if ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) {
                        if ($columnMap->getChildSortByFieldName() !== NULL) {
                        if ($columnMap->getChildSortByFieldName() !== NULL) {
-                               $query->setOrderings(array($columnMap->getChildSortByFieldName() => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));
+                               $query->setOrderings(array($columnMap->getChildSortByFieldName() => Persistence\QueryInterface::ORDER_ASCENDING));
                        }
                        }
-               } elseif ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
+               } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
                        $query->setSource($this->getSource($parentObject, $propertyName));
                        if ($columnMap->getChildSortByFieldName() !== NULL) {
                        $query->setSource($this->getSource($parentObject, $propertyName));
                        if ($columnMap->getChildSortByFieldName() !== NULL) {
-                               $query->setOrderings(array($columnMap->getChildSortByFieldName() => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));
+                               $query->setOrderings(array($columnMap->getChildSortByFieldName() => Persistence\QueryInterface::ORDER_ASCENDING));
                        }
                }
                $query->matching($this->getConstraint($query, $parentObject, $propertyName, $fieldValue, $columnMap->getRelationTableMatchFields()));
                        }
                }
                $query->matching($this->getConstraint($query, $parentObject, $propertyName, $fieldValue, $columnMap->getRelationTableMatchFields()));
@@ -360,19 +365,22 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * Builds and returns the constraint for multi value properties.
         *
        /**
         * Builds and returns the constraint for multi value properties.
         *
-        * @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
+        * @param Persistence\QueryInterface $query
+        * @param DomainObjectInterface $parentObject
         * @param string $propertyName
         * @param string $fieldValue
         * @param array $relationTableMatchFields
         * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface $constraint
         */
         * @param string $propertyName
         * @param string $fieldValue
         * @param array $relationTableMatchFields
         * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface $constraint
         */
-       protected function getConstraint(\TYPO3\CMS\Extbase\Persistence\QueryInterface $query, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $relationTableMatchFields = array()) {
+       protected function getConstraint(Persistence\QueryInterface $query, DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $relationTableMatchFields = array()) {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                if ($columnMap->getParentKeyFieldName() !== NULL) {
                        $constraint = $query->equals($columnMap->getParentKeyFieldName(), $parentObject);
                        if ($columnMap->getParentTableFieldName() !== NULL) {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                if ($columnMap->getParentKeyFieldName() !== NULL) {
                        $constraint = $query->equals($columnMap->getParentKeyFieldName(), $parentObject);
                        if ($columnMap->getParentTableFieldName() !== NULL) {
-                               $constraint = $query->logicalAnd($constraint, $query->equals($columnMap->getParentTableFieldName(), $this->getDataMap(get_class($parentObject))->getTableName()));
+                               $constraint = $query->logicalAnd(
+                                       $constraint,
+                                       $query->equals($columnMap->getParentTableFieldName(), $this->getDataMap(get_class($parentObject))->getTableName())
+                               );
                        }
                } else {
                        $constraint = $query->in('uid', \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $fieldValue));
                        }
                } else {
                        $constraint = $query->in('uid', \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $fieldValue));
@@ -388,17 +396,17 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * Builds and returns the source to build a join for a m:n relation.
         *
        /**
         * Builds and returns the source to build a join for a m:n relation.
         *
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
+        * @param DomainObjectInterface $parentObject
         * @param string $propertyName
         * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source
         */
         * @param string $propertyName
         * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source
         */
-       protected function getSource(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName) {
+       protected function getSource(DomainObjectInterface $parentObject, $propertyName) {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                $left = $this->qomFactory->selector(NULL, $columnMap->getRelationTableName());
                $childClassName = $this->getType(get_class($parentObject), $propertyName);
                $right = $this->qomFactory->selector($childClassName, $columnMap->getChildTableName());
                $joinCondition = $this->qomFactory->equiJoinCondition($columnMap->getRelationTableName(), $columnMap->getChildKeyFieldName(), $columnMap->getChildTableName(), 'uid');
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                $left = $this->qomFactory->selector(NULL, $columnMap->getRelationTableName());
                $childClassName = $this->getType(get_class($parentObject), $propertyName);
                $right = $this->qomFactory->selector($childClassName, $columnMap->getChildTableName());
                $joinCondition = $this->qomFactory->equiJoinCondition($columnMap->getRelationTableName(), $columnMap->getChildKeyFieldName(), $columnMap->getChildTableName(), 'uid');
-               $source = $this->qomFactory->join($left, $right, \TYPO3\CMS\Extbase\Persistence\Generic\Query::JCR_JOIN_TYPE_INNER, $joinCondition);
+               $source = $this->qomFactory->join($left, $right, Persistence\Generic\Query::JCR_JOIN_TYPE_INNER, $joinCondition);
                return $source;
        }
 
                return $source;
        }
 
@@ -411,13 +419,13 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
         * the correct type and identity (fieldValue), this function returns that object.
         * Otherwise, it proceeds with mapResultToPropertyValue().
         *
         * the correct type and identity (fieldValue), this function returns that object.
         * Otherwise, it proceeds with mapResultToPropertyValue().
         *
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
+        * @param DomainObjectInterface $parentObject
         * @param string $propertyName
         * @param mixed $fieldValue the raw field value
         * @return mixed
         * @see mapResultToPropertyValue()
         */
         * @param string $propertyName
         * @param mixed $fieldValue the raw field value
         * @return mixed
         * @see mapResultToPropertyValue()
         */
-       protected function mapObjectToClassProperty(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue) {
+       protected function mapObjectToClassProperty(DomainObjectInterface $parentObject, $propertyName, $fieldValue) {
                if ($this->propertyMapsByForeignKey($parentObject, $propertyName)) {
                                $result = $this->fetchRelated($parentObject, $propertyName, $fieldValue);
                                $propertyValue = $this->mapResultToPropertyValue($parentObject, $propertyName, $result);
                if ($this->propertyMapsByForeignKey($parentObject, $propertyName)) {
                                $result = $this->fetchRelated($parentObject, $propertyName, $fieldValue);
                                $propertyValue = $this->mapResultToPropertyValue($parentObject, $propertyName, $result);
@@ -441,11 +449,11 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * Checks if the relation is based on a foreign key.
         *
        /**
         * Checks if the relation is based on a foreign key.
         *
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
+        * @param DomainObjectInterface $parentObject
         * @param string $propertyName
         * @return boolean TRUE if the property is mapped
         */
         * @param string $propertyName
         * @return boolean TRUE if the property is mapped
         */
-       protected function propertyMapsByForeignKey(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName) {
+       protected function propertyMapsByForeignKey(DomainObjectInterface $parentObject, $propertyName) {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                return ($columnMap->getParentKeyFieldName() !== NULL);
        }
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                return ($columnMap->getParentKeyFieldName() !== NULL);
        }
@@ -453,14 +461,14 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * Returns the given result as property value of the specified property type.
         *
        /**
         * Returns the given result as property value of the specified property type.
         *
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject
+        * @param DomainObjectInterface $parentObject
         * @param string $propertyName
         * @param mixed $result The result
         * @return mixed
         */
         * @param string $propertyName
         * @param mixed $result The result
         * @return mixed
         */
-       public function mapResultToPropertyValue(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $result) {
+       public function mapResultToPropertyValue(DomainObjectInterface $parentObject, $propertyName, $result) {
                $propertyValue = NULL;
                $propertyValue = NULL;
-               if ($result instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LoadingStrategyInterface) {
+               if ($result instanceof Persistence\Generic\LoadingStrategyInterface) {
                        $propertyValue = $result;
                } else {
                        $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
                        $propertyValue = $result;
                } else {
                        $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
@@ -472,7 +480,7 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
                                if ($propertyMetaData['type'] === 'ArrayObject') {
                                        $propertyValue = new \ArrayObject($objects);
                                } elseif (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
                                if ($propertyMetaData['type'] === 'ArrayObject') {
                                        $propertyValue = new \ArrayObject($objects);
                                } elseif (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
-                                       $propertyValue = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+                                       $propertyValue = new Persistence\ObjectStorage();
                                        foreach ($objects as $object) {
                                                $propertyValue->attach($object);
                                        }
                                        foreach ($objects as $object) {
                                                $propertyValue->attach($object);
                                        }
@@ -481,7 +489,7 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
                                        $propertyValue = $objects;
                                }
                        } elseif (strpbrk($propertyMetaData['type'], '_\\') !== FALSE) {
                                        $propertyValue = $objects;
                                }
                        } elseif (strpbrk($propertyMetaData['type'], '_\\') !== FALSE) {
-                               if (is_object($result) && $result instanceof \TYPO3\CMS\Extbase\Persistence\QueryResultInterface) {
+                               if (is_object($result) && $result instanceof Persistence\QueryResultInterface) {
                                        $propertyValue = $result->getFirst();
                                } else {
                                        $propertyValue = $result;
                                        $propertyValue = $result->getFirst();
                                } else {
                                        $propertyValue = $result;
@@ -494,12 +502,12 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * Counts the number of related objects assigned to a property of a parent object
         *
        /**
         * Counts the number of related objects assigned to a property of a parent object
         *
-        * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject The object instance this proxy is part of
+        * @param DomainObjectInterface $parentObject The object instance this proxy is part of
         * @param string $propertyName The name of the proxied property in it's parent
         * @param mixed $fieldValue The raw field value.
         * @return integer
         */
         * @param string $propertyName The name of the proxied property in it's parent
         * @param mixed $fieldValue The raw field value.
         * @return integer
         */
-       public function countRelated(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
+       public function countRelated(DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
                $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
                return $query->execute()->count();
        }
                $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
                return $query->execute()->count();
        }
@@ -521,12 +529,12 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
         * Returns a data map for a given class name
         *
         * @param string $className The class name you want to fetch the Data Map for
         * Returns a data map for a given class name
         *
         * @param string $className The class name you want to fetch the Data Map for
-        * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception
-        * @return \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap The data map
+        * @throws Persistence\Generic\Exception
+        * @return DataMap The data map
         */
        public function getDataMap($className) {
                if (!is_string($className) || strlen($className) === 0) {
         */
        public function getDataMap($className) {
                if (!is_string($className) || strlen($className) === 0) {
-                       throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('No class name was given to retrieve the Data Map for.', 1251315965);
+                       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);
                }
                if (!isset($this->dataMaps[$className])) {
                        $this->dataMaps[$className] = $this->dataMapFactory->buildDataMap($className);
@@ -574,7 +582,7 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
         *
         * @param string $parentClassName The class name of the object this proxy is part of
         * @param string $propertyName The name of the proxied property in it's parent
         *
         * @param string $parentClassName The class name of the object this proxy is part of
         * @param string $propertyName The name of the proxied property in it's parent
-        * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException
+        * @throws UnexpectedTypeException
         * @return string The class name of the child object
         */
        public function getType($parentClassName, $propertyName) {
         * @return string The class name of the child object
         */
        public function getType($parentClassName, $propertyName) {
@@ -584,8 +592,80 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface {
                } elseif (!empty($propertyMetaData['type'])) {
                        $type = $propertyMetaData['type'];
                } else {
                } elseif (!empty($propertyMetaData['type'])) {
                        $type = $propertyMetaData['type'];
                } else {
-                       throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('Could not determine the child object type.', 1251315967);
+                       throw new UnexpectedTypeException('Could not determine the child object type.', 1251315967);
                }
                return $type;
        }
                }
                return $type;
        }
+
+       /**
+        * Returns a plain value, i.e. objects are flattened out if possible.
+        * Multi value objects or arrays will be converted to a comma-separated list for use in IN SQL queries.
+        *
+        * @param mixed $input The value that will be converted.
+        * @param ColumnMap $columnMap Optional column map for retrieving the date storage format.
+        * @param callable $parseStringValueCallback Optional callback method that will be called for string values. Can be used to do database quotation.
+        * @param array $parseStringValueCallbackParameters Additional parameters that will be passed to the callabck as second parameter.
+        * @throws \InvalidArgumentException
+        * @throws UnexpectedTypeException
+        * @return int|string
+        */
+       public function getPlainValue($input, $columnMap = NULL, $parseStringValueCallback = NULL, array $parseStringValueCallbackParameters = array()) {
+               if ($input === NULL) {
+                       return 'NULL';
+               }
+               if ($input instanceof Persistence\Generic\LazyLoadingProxy) {
+                       $input = $input->_loadRealInstance();
+               }
+
+               if (is_bool($input)) {
+                       $parameter = (int)$input;
+               } elseif ($input instanceof \DateTime) {
+                       if (!is_null($columnMap) && !is_null($columnMap->getDateTimeStorageFormat())) {
+                               $storageFormat = $columnMap->getDateTimeStorageFormat();
+                               switch ($storageFormat) {
+                                       case 'datetime':
+                                               $parameter = $input->format('Y-m-d H:i:s');
+                                               break;
+                                       case 'date':
+                                               $parameter = $input->format('Y-m-d');
+                                               break;
+                                       default:
+                                               throw new \InvalidArgumentException('Column map DateTime format "' . $storageFormat . '" is unknown. Allowed values are datetime or date.', 1395353470);
+                               }
+                       } else {
+                               $parameter = $input->format('U');
+                       }
+               } elseif (TypeHandlingUtility::isValidTypeForMultiValueComparison($input)) {
+                       $plainValueArray = array();
+                       foreach ($input as $inputElement) {
+                               $plainValueArray[] = $this->getPlainValue($inputElement, $columnMap, $parseStringValueCallback, $parseStringValueCallbackParameters);
+                       }
+                       $parameter = implode(',', $plainValueArray);
+               } elseif ($input instanceof DomainObjectInterface) {
+                       $parameter = (int)$input->getUid();
+               } elseif (TypeHandlingUtility::isCoreType($input)) {
+                       $parameter = $this->getPlainStringValue($input, $parseStringValueCallback, $parseStringValueCallbackParameters);
+               } elseif (is_object($input)) {
+                       throw new UnexpectedTypeException('An object of class "' . get_class($input) . '" could not be converted to a plain value.', 1274799934);
+               } else {
+                       $parameter = $this->getPlainStringValue($input, $parseStringValueCallback, $parseStringValueCallbackParameters);
+               }
+               return $parameter;
+       }
+
+       /**
+        * If the given callback is set the value will be passed on the the callback function.
+        * The value will be converted to a string.
+        *
+        * @param string $value The string value that should be processed. Will be passed to the callback as first parameter.
+        * @param callable $callback The data passed to call_user_func().
+        * @param array $additionalParameters Optional additional parameters passed to the callback as second argument.
+        * @return string
+        */
+       protected function getPlainStringValue($value, $callback = NULL , array $additionalParameters = array()) {
+               if (is_callable($callback)) {
+                       $value = call_user_func($callback, $value, $additionalParameters);
+               }
+               return (string)$value;
+       }
 }
 }
index 2bab23f..4547fda 100644 (file)
@@ -472,7 +472,7 @@ class Query implements QueryInterface {
         * @api
         */
        public function in($propertyName, $operand) {
         * @api
         */
        public function in($propertyName, $operand) {
-               if (!is_array($operand) && !$operand instanceof \ArrayAccess && !$operand instanceof \Traversable) {
+               if (!\TYPO3\CMS\Extbase\Utility\TypeHandlingUtility::isValidTypeForMultiValueComparison($operand)) {
                        throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('The "in" operator must be given a multivalued operand (array, ArrayAccess, Traversable).', 1264678095);
                }
                return $this->qomFactory->comparison($this->qomFactory->propertyValue($propertyName, $this->getSelectorName()), QueryInterface::OPERATOR_IN, $operand);
                        throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('The "in" operator must be given a multivalued operand (array, ArrayAccess, Traversable).', 1264678095);
                }
                return $this->qomFactory->comparison($this->qomFactory->propertyValue($propertyName, $this->getSelectorName()), QueryInterface::OPERATOR_IN, $operand);
index aff77a4..849aa43 100644 (file)
@@ -15,7 +15,7 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic\Storage;
  */
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
  */
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Extbase\Persistence\Generic\Qom\Statement;
+use TYPO3\CMS\Extbase\Persistence\Generic\Qom;
 use TYPO3\CMS\Extbase\Persistence\QueryInterface;
 
 /**
 use TYPO3\CMS\Extbase\Persistence\QueryInterface;
 
 /**
@@ -282,7 +282,7 @@ class Typo3DbBackend implements BackendInterface, \TYPO3\CMS\Core\SingletonInter
         */
        public function getObjectDataByQuery(QueryInterface $query) {
                $statement = $query->getStatement();
         */
        public function getObjectDataByQuery(QueryInterface $query) {
                $statement = $query->getStatement();
-               if ($statement instanceof Statement) {
+               if ($statement instanceof Qom\Statement) {
                        $rows = $this->getObjectDataByRawQuery($statement);
                } else {
                        $rows = $this->getRowsByStatementParts($query);
                        $rows = $this->getObjectDataByRawQuery($statement);
                } else {
                        $rows = $this->getRowsByStatementParts($query);
@@ -381,10 +381,10 @@ class Typo3DbBackend implements BackendInterface, \TYPO3\CMS\Core\SingletonInter
        /**
         * Returns the object data using a custom statement
         *
        /**
         * Returns the object data using a custom statement
         *
-        * @param Statement $statement
+        * @param Qom\Statement $statement
         * @return array
         */
         * @return array
         */
-       protected function getObjectDataByRawQuery(Statement $statement) {
+       protected function getObjectDataByRawQuery(Qom\Statement $statement) {
                $realStatement = $statement->getStatement();
                $parameters = $statement->getBoundVariables();
 
                $realStatement = $statement->getStatement();
                $parameters = $statement->getBoundVariables();
 
@@ -425,7 +425,7 @@ class Typo3DbBackend implements BackendInterface, \TYPO3\CMS\Core\SingletonInter
         * @return integer The number of matching tuples
         */
        public function getObjectCountByQuery(QueryInterface $query) {
         * @return integer The number of matching tuples
         */
        public function getObjectCountByQuery(QueryInterface $query) {
-               if ($query->getConstraint() instanceof Statement) {
+               if ($query->getConstraint() instanceof Qom\Statement) {
                        throw new \TYPO3\CMS\Extbase\Persistence\Generic\Storage\Exception\BadConstraintException('Could not execute count on queries with a constraint of type TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Qom\\Statement', 1256661045);
                }
 
                        throw new \TYPO3\CMS\Extbase\Persistence\Generic\Storage\Exception\BadConstraintException('Could not execute count on queries with a constraint of type TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Qom\\Statement', 1256661045);
                }
 
@@ -510,31 +510,10 @@ class Typo3DbBackend implements BackendInterface, \TYPO3\CMS\Core\SingletonInter
         * @return array
         */
        protected function resolveParameterPlaceholders(array $statementParts, array $parameters) {
         * @return array
         */
        protected function resolveParameterPlaceholders(array $statementParts, array $parameters) {
-               $tableNameForEscape = (reset($statementParts['tables']) ?: 'foo');
+               $tableName = reset($statementParts['tables']) ?: 'foo';
 
                foreach ($parameters as $parameterPlaceholder => $parameter) {
 
                foreach ($parameters as $parameterPlaceholder => $parameter) {
-                       if ($parameter instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) {
-                               $parameter = $parameter->_loadRealInstance();
-                       }
-
-                       if ($parameter instanceof \DateTime) {
-                               $parameter = $parameter->format('U');
-                       } elseif ($parameter instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) {
-                               $parameter = (int)$parameter->getUid();
-                       } elseif (is_array($parameter)) {
-                               $subParameters = array();
-                               foreach ($parameter as $subParameter) {
-                                       $subParameters[] = $this->databaseHandle->fullQuoteStr($subParameter, $tableNameForEscape);
-                               }
-                               $parameter = implode(',', $subParameters);
-                       } elseif ($parameter === NULL) {
-                               $parameter = 'NULL';
-                       } elseif (is_bool($parameter)) {
-                               $parameter = (int)$parameter;
-                       } else {
-                               $parameter = $this->databaseHandle->fullQuoteStr((string)$parameter, $tableNameForEscape);
-                       }
-
+                       $parameter = $this->dataMapper->getPlainValue($parameter, NULL, array($this, 'quoteTextValueCallback'), array('tablename' => $tableName));
                        $statementParts['where'] = str_replace($parameterPlaceholder, $parameter, $statementParts['where']);
                }
 
                        $statementParts['where'] = str_replace($parameterPlaceholder, $parameter, $statementParts['where']);
                }
 
@@ -542,6 +521,17 @@ class Typo3DbBackend implements BackendInterface, \TYPO3\CMS\Core\SingletonInter
        }
 
        /**
        }
 
        /**
+        * Will be called by the data mapper to quote string values.
+        *
+        * @param string $value The value to be quoted.
+        * @param array $parameters Additional parameters array currently containing the "tablename" key.
+        * @return string The quoted string.
+        */
+       public function quoteTextValueCallback($value, $parameters) {
+               return $this->databaseHandle->fullQuoteStr($value, $parameters['tablename']);
+       }
+
+       /**
         * Checks if a Value Object equal to the given Object exists in the data base
         *
         * @param \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject $object The Value Object
         * Checks if a Value Object equal to the given Object exists in the data base
         *
         * @param \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject $object The Value Object
@@ -560,7 +550,7 @@ class Typo3DbBackend implements BackendInterface, \TYPO3\CMS\Core\SingletonInter
                                        $fields[] = $dataMap->getColumnMap($propertyName)->getColumnName() . ' IS NULL';
                                } else {
                                        $fields[] = $dataMap->getColumnMap($propertyName)->getColumnName() . '=?';
                                        $fields[] = $dataMap->getColumnMap($propertyName)->getColumnName() . ' IS NULL';
                                } else {
                                        $fields[] = $dataMap->getColumnMap($propertyName)->getColumnName() . '=?';
-                                       $parameters[] = $this->getPlainValue($propertyValue);
+                                       $parameters[] = $this->dataMapper->getPlainValue($propertyValue);
                                }
                        }
                }
                                }
                        }
                }
@@ -586,40 +576,6 @@ class Typo3DbBackend implements BackendInterface, \TYPO3\CMS\Core\SingletonInter
        }
 
        /**
        }
 
        /**
-        * Returns a plain value, i.e. objects are flattened out if possible.
-        *
-        * @param mixed $input
-        * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException
-        * @return mixed
-        * @todo remove after getUidOfAlreadyPersistedValueObject is adjusted, this was moved to queryParser
-        */
-       protected function getPlainValue($input) {
-               if (is_array($input)) {
-                       throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('An array could not be converted to a plain value.', 1274799932);
-               }
-               if ($input instanceof \DateTime) {
-                       return $input->format('U');
-               } elseif ($input instanceof \TYPO3\CMS\Core\Type\TypeInterface) {
-                       return (string) $input;
-               } elseif (is_object($input)) {
-                       if ($input instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) {
-                               $realInput = $input->_loadRealInstance();
-                       } else {
-                               $realInput = $input;
-                       }
-                       if ($realInput instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) {
-                               return $realInput->getUid();
-                       } else {
-                               throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('An object of class "' . get_class($realInput) . '" could not be converted to a plain value.', 1274799934);
-                       }
-               } elseif (is_bool($input)) {
-                       return (int)$input;
-               } else {
-                       return $input;
-               }
-       }
-
-       /**
         * Replace query placeholders in a query part by the given
         * parameters.
         *
         * Replace query placeholders in a query part by the given
         * parameters.
         *
@@ -737,16 +693,16 @@ class Typo3DbBackend implements BackendInterface, \TYPO3\CMS\Core\SingletonInter
         * Performs workspace and language overlay on the given row array. The language and workspace id is automatically
         * detected (depending on FE or BE context). You can also explicitly set the language/workspace id.
         *
         * Performs workspace and language overlay on the given row array. The language and workspace id is automatically
         * detected (depending on FE or BE context). You can also explicitly set the language/workspace id.
         *
-        * @param \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source The source (selector od join)
+        * @param Qom\SourceInterface $source The source (selector od join)
         * @param array $rows
         * @param \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
         * @param null|integer $workspaceUid
         * @return array
         */
         * @param array $rows
         * @param \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
         * @param null|integer $workspaceUid
         * @return array
         */
-       protected function doLanguageAndWorkspaceOverlay(\TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source, array $rows, \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $querySettings, $workspaceUid = NULL) {
-               if ($source instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SelectorInterface) {
+       protected function doLanguageAndWorkspaceOverlay(Qom\SourceInterface $source, array $rows, \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $querySettings, $workspaceUid = NULL) {
+               if ($source instanceof Qom\SelectorInterface) {
                        $tableName = $source->getSelectorName();
                        $tableName = $source->getSelectorName();
-               } elseif ($source instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Qom\JoinInterface) {
+               } elseif ($source instanceof Qom\JoinInterface) {
                        $tableName = $source->getRight()->getSelectorName();
                } else {
                        // No proper source, so we do not have a table name here
                        $tableName = $source->getRight()->getSelectorName();
                } else {
                        // No proper source, so we do not have a table name here
index ff4167a..ffe3252 100644 (file)
@@ -136,7 +136,7 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
                        if ($operator === QueryInterface::OPERATOR_IN) {
                                $items = array();
                                foreach ($operand2 as $value) {
                        if ($operator === QueryInterface::OPERATOR_IN) {
                                $items = array();
                                foreach ($operand2 as $value) {
-                                       $value = $this->getPlainValue($value);
+                                       $value = $this->dataMapper->getPlainValue($value);
                                        if ($value !== NULL) {
                                                $items[] = $value;
                                        }
                                        if ($value !== NULL) {
                                                $items[] = $value;
                                        }
@@ -343,7 +343,7 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
                if ($operator === QueryInterface::OPERATOR_IN) {
                        $hasValue = FALSE;
                        foreach ($operand2 as $value) {
                if ($operator === QueryInterface::OPERATOR_IN) {
                        $hasValue = FALSE;
                        foreach ($operand2 as $value) {
-                               $value = $this->getPlainValue($value);
+                               $value = $this->dataMapper->getPlainValue($value);
                                if ($value !== NULL) {
                                        $parameters[] = $value;
                                        $hasValue = TRUE;
                                if ($value !== NULL) {
                                        $parameters[] = $value;
                                        $hasValue = TRUE;
@@ -696,40 +696,6 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
        }
 
        /**
        }
 
        /**
-        * Returns a plain value, i.e. objects are flattened out if possible.
-        *
-        * @param mixed $input
-        * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException
-        * @return mixed
-        */
-       protected function getPlainValue($input) {
-               if (is_array($input)) {
-                       throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('An array could not be converted to a plain value.', 1274799932);
-               }
-               if ($input instanceof \DateTime) {
-                       return $input->format('U');
-               } elseif (TypeHandlingUtility::isCoreType($input)) {
-                       return (string) $input;
-               } elseif (is_object($input)) {
-                       if ($input instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) {
-                               $realInput = $input->_loadRealInstance();
-                       } else {
-                               $realInput = $input;
-                       }
-                       if ($realInput instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) {
-                               return $realInput->getUid();
-                       } else {
-                               throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('An object of class "' . get_class($realInput) . '" could not be converted to a plain value.', 1274799934);
-                       }
-               } elseif (is_bool($input)) {
-                       return $input === TRUE ? 1 : 0;
-               } else {
-                       return $input;
-               }
-       }
-
-
-       /**
         * adds a union statement to the query, mostly for tables referenced in the where condition.
         *
         * @param string &$className
         * adds a union statement to the query, mostly for tables referenced in the where condition.
         *
         * @param string &$className
index a6a0217..9845062 100644 (file)
@@ -106,8 +106,8 @@ class TypeHandlingUtility {
        /**
         * Returns TRUE if the $type is a CMS core type object.
         *
        /**
         * Returns TRUE if the $type is a CMS core type object.
         *
-        * @param string $type
-        * @return boolean
+        * @param string|object $type
+        * @return bool
         */
        static public function isCoreType($type) {
                return is_subclass_of($type, 'TYPO3\\CMS\\Core\\Type\\TypeInterface');
         */
        static public function isCoreType($type) {
                return is_subclass_of($type, 'TYPO3\\CMS\\Core\\Type\\TypeInterface');
@@ -136,6 +136,16 @@ class TypeHandlingUtility {
        }
 
        /**
        }
 
        /**
+        * Returns TRUE when the given value can be used in an "in" comparison in a query.
+        *
+        * @param mixed $value
+        * @return bool
+        */
+       static public function isValidTypeForMultiValueComparison($value) {
+               return is_array($value) || $value instanceof \Traversable;
+       }
+
+       /**
         * Converts a hex encoded string into binary data
         *
         * @param string $hexadecimalData A hex encoded string of data
         * Converts a hex encoded string into binary data
         *
         * @param string $hexadecimalData A hex encoded string of data
index b891074..a1b0cf3 100644 (file)
@@ -74,20 +74,6 @@ class BackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
        /**
         * @test
         */
        /**
         * @test
         */
-       public function getPlainValueReturnsCorrectDateTimeFormat() {
-               $fixture = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Backend', array('dummy'), array(), '', FALSE);
-               $columnMap = new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('column_name', 'propertyName');
-               $columnMap->setDateTimeStorageFormat('datetime');
-               $datetimeAsString = '2013-04-15 09:30:00';
-               $input = new \DateTime($datetimeAsString);
-               $this->assertEquals('2013-04-15 09:30:00', $fixture->_call('getPlainValue', $input, $columnMap));
-               $columnMap->setDateTimeStorageFormat('date');
-               $this->assertEquals('2013-04-15', $fixture->_call('getPlainValue', $input, $columnMap));
-       }
-
-       /**
-        * @test
-        */
        public function getIdentifierByObjectReturnsIdentifierForNonlazyObject() {
                $fakeUuid = 'fakeUuid';
                $configurationManager = $this->getMock('TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManagerInterface');
        public function getIdentifierByObjectReturnsIdentifierForNonlazyObject() {
                $fakeUuid = 'fakeUuid';
                $configurationManager = $this->getMock('TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManagerInterface');
index 109e6f7..bcb6c24 100644 (file)
@@ -13,6 +13,9 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Mapper;
  *
  * The TYPO3 project - inspiring people to share!
  */
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
+use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap;
+use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
 
 /**
  * Test case
 
 /**
  * Test case
@@ -25,6 +28,7 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
        public function mapMapsArrayToObjectByCallingmapToObject() {
                $rows = array(array('uid' => '1234'));
                $object = new \stdClass();
        public function mapMapsArrayToObjectByCallingmapToObject() {
                $rows = array(array('uid' => '1234'));
                $object = new \stdClass();
+               /** @var DataMapper|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject $dataMapper */
                $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('mapSingleRow', 'getTargetType'));
                $dataMapper->expects($this->any())->method('getTargetType')->will($this->returnArgument(1));
                $dataMapFactory = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapFactory');
                $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('mapSingleRow', 'getTargetType'));
                $dataMapper->expects($this->any())->method('getTargetType')->will($this->returnArgument(1));
                $dataMapFactory = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapFactory');
@@ -53,7 +57,10 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
        public function thawPropertiesSetsPropertyValues() {
                $className = 'Class' . md5(uniqid(mt_rand(), TRUE));
                $classNameWithNS = __NAMESPACE__ . '\\' . $className;
        public function thawPropertiesSetsPropertyValues() {
                $className = 'Class' . md5(uniqid(mt_rand(), TRUE));
                $classNameWithNS = __NAMESPACE__ . '\\' . $className;
-               eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity { public $firstProperty; public $secondProperty; public $thirdProperty; public $fourthProperty; }');
+               eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity {
+                public $firstProperty; public $secondProperty; public $thirdProperty; public $fourthProperty;
+                }'
+               );
                $object = new $classNameWithNS();
                $row = array(
                        'uid' => '1234',
                $object = new $classNameWithNS();
                $row = array(
                        'uid' => '1234',
@@ -63,18 +70,18 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                        'fourthProperty' => FALSE
                );
                $columnMaps = array(
                        'fourthProperty' => FALSE
                );
                $columnMaps = array(
-                       'uid' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('uid', 'uid'),
-                       'pid' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('pid', 'pid'),
-                       'firstProperty' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('firstProperty', 'firstProperty'),
-                       'secondProperty' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('secondProperty', 'secondProperty'),
-                       'thirdProperty' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('thirdProperty', 'thirdProperty')
+                       'uid' => new ColumnMap('uid', 'uid'),
+                       'pid' => new ColumnMap('pid', 'pid'),
+                       'firstProperty' => new ColumnMap('firstProperty', 'firstProperty'),
+                       'secondProperty' => new ColumnMap('secondProperty', 'secondProperty'),
+                       'thirdProperty' => new ColumnMap('thirdProperty', 'thirdProperty')
                );
                $dataMap = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('dummy'), array($className, $className));
                $dataMap->_set('columnMaps', $columnMaps);
                $dataMaps = array(
                        $classNameWithNS => $dataMap
                );
                );
                $dataMap = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('dummy'), array($className, $className));
                $dataMap->_set('columnMaps', $columnMaps);
                $dataMaps = array(
                        $classNameWithNS => $dataMap
                );
-               /** @var \TYPO3\CMS\Core\Tests\AccessibleObjectInterface|\TYPO3\CMS\Extbase\Reflection\ClassSchema $classSchema */
+               /** @var AccessibleObjectInterface|\TYPO3\CMS\Extbase\Reflection\ClassSchema $classSchema */
                $classSchema = $this->getAccessibleMock('TYPO3\CMS\Extbase\Reflection\ClassSchema', array('dummy'), array($classNameWithNS));
                $classSchema->_set('typeHandlingService', new \TYPO3\CMS\Extbase\Service\TypeHandlingService());
                $classSchema->addProperty('pid', 'integer');
                $classSchema = $this->getAccessibleMock('TYPO3\CMS\Extbase\Reflection\ClassSchema', array('dummy'), array($classNameWithNS));
                $classSchema->_set('typeHandlingService', new \TYPO3\CMS\Extbase\Service\TypeHandlingService());
                $classSchema->addProperty('pid', 'integer');
@@ -101,8 +108,8 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @test
         */
        public function fetchRelatedEagerReturnsNullForEmptyRelationHasOne() {
         * @test
         */
        public function fetchRelatedEagerReturnsNullForEmptyRelationHasOne() {
-               $columnMap = new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('columnName', 'propertyName');
-               $columnMap->setTypeOfRelation(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE);
+               $columnMap = new ColumnMap('columnName', 'propertyName');
+               $columnMap->setTypeOfRelation(ColumnMap::RELATION_HAS_ONE);
                $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
                $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
                $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap'));
                $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
                $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
                $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap'));
@@ -117,8 +124,8 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @test
         */
        public function fetchRelatedEagerReturnsEmptyArrayForEmptyRelationNotHasOne() {
         * @test
         */
        public function fetchRelatedEagerReturnsEmptyArrayForEmptyRelationNotHasOne() {
-               $columnMap = new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('columnName', 'propertyName');
-               $columnMap->setTypeOfRelation(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_BELONGS_TO_MANY);
+               $columnMap = new ColumnMap('columnName', 'propertyName');
+               $columnMap->setTypeOfRelation(ColumnMap::RELATION_BELONGS_TO_MANY);
                $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
                $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
                $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap'));
                $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
                $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
                $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap'));
@@ -134,8 +141,8 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @test
         */
        public function mapObjectToClassPropertyReturnsNullForEmptyRelationHasOne() {
         * @test
         */
        public function mapObjectToClassPropertyReturnsNullForEmptyRelationHasOne() {
-               $columnMap = new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('columnName', 'propertyName');
-               $columnMap->setTypeOfRelation(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE);
+               $columnMap = new ColumnMap('columnName', 'propertyName');
+               $columnMap->setTypeOfRelation(ColumnMap::RELATION_HAS_ONE);
                $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
                $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
                $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap', 'fetchRelated'));
                $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
                $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
                $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap', 'fetchRelated'));
@@ -153,16 +160,14 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @test
         */
        public function mapObjectToClassPropertyReturnsExistingObjectWithoutCallingFetchRelated() {
         * @test
         */
        public function mapObjectToClassPropertyReturnsExistingObjectWithoutCallingFetchRelated() {
-               $columnMap = new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('columnName', 'propertyName');
-               $columnMap->setTypeOfRelation(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE);
+               $columnMap = new ColumnMap('columnName', 'propertyName');
+               $columnMap->setTypeOfRelation(ColumnMap::RELATION_HAS_ONE);
                $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
 
                $className = 'Class1' . md5(uniqid(mt_rand(), TRUE));
                $classNameWithNS = __NAMESPACE__ . '\\' . $className;
                eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity { public $relationProperty; }');
                $object = new $classNameWithNS();
                $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
 
                $className = 'Class1' . md5(uniqid(mt_rand(), TRUE));
                $classNameWithNS = __NAMESPACE__ . '\\' . $className;
                eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity { public $relationProperty; }');
                $object = new $classNameWithNS();
-               $classSchema1 = $this->getAccessibleMock('TYPO3\CMS\Extbase\Reflection\ClassSchema', array('dummy'), array($classNameWithNS));
-               $classSchema1->_set('typeHandlingService', new \TYPO3\CMS\Extbase\Service\TypeHandlingService());
 
                $className2 = 'Class2' . md5(uniqid(mt_rand(), TRUE));
                $className2WithNS = __NAMESPACE__ . '\\' . $className2;
 
                $className2 = 'Class2' . md5(uniqid(mt_rand(), TRUE));
                $className2WithNS = __NAMESPACE__ . '\\' . $className2;
@@ -171,6 +176,9 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $classSchema2 = $this->getAccessibleMock('TYPO3\CMS\Extbase\Reflection\ClassSchema', array('dummy'), array($className2WithNS));
                $classSchema2->_set('typeHandlingService', new \TYPO3\CMS\Extbase\Service\TypeHandlingService());
 
                $classSchema2 = $this->getAccessibleMock('TYPO3\CMS\Extbase\Reflection\ClassSchema', array('dummy'), array($className2WithNS));
                $classSchema2->_set('typeHandlingService', new \TYPO3\CMS\Extbase\Service\TypeHandlingService());
 
+               /** @var \TYPO3\CMS\Extbase\Reflection\ClassSchema|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject $classSchema1 */
+               $classSchema1 = $this->getAccessibleMock('TYPO3\CMS\Extbase\Reflection\ClassSchema', array('dummy'), array($classNameWithNS));
+               $classSchema1->_set('typeHandlingService', new \TYPO3\CMS\Extbase\Service\TypeHandlingService());
                $classSchema1->addProperty('relationProperty', $className2WithNS);
                $identifier = 1;
 
                $classSchema1->addProperty('relationProperty', $className2WithNS);
                $identifier = 1;
 
@@ -218,6 +226,8 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         */
        public function mapDateTimeHandlesDifferentFieldEvaluations($value, $storageFormat, $expectedValue) {
                $accessibleClassName = $this->buildAccessibleProxy('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper');
         */
        public function mapDateTimeHandlesDifferentFieldEvaluations($value, $storageFormat, $expectedValue) {
                $accessibleClassName = $this->buildAccessibleProxy('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper');
+
+               /** @var DataMapper|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject $accessibleDataMapFactory */
                $accessibleDataMapFactory = new $accessibleClassName();
 
                /** @var $dateTime NULL|\DateTime */
                $accessibleDataMapFactory = new $accessibleClassName();
 
                /** @var $dateTime NULL|\DateTime */
@@ -229,4 +239,75 @@ class DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                        $this->assertEquals($expectedValue, $dateTime->format('c'));
                }
        }
                        $this->assertEquals($expectedValue, $dateTime->format('c'));
                }
        }
-}
+
+       /**
+        * @test
+        */
+       public function getPlainValueReturnsCorrectDateTimeFormat() {
+               $subject = new DataMapper();
+               $columnMap = new ColumnMap('column_name', 'propertyName');
+               $columnMap->setDateTimeStorageFormat('datetime');
+               $datetimeAsString = '2013-04-15 09:30:00';
+               $input = new \DateTime($datetimeAsString);
+               $this->assertEquals('2013-04-15 09:30:00', $subject->getPlainValue($input, $columnMap));
+               $columnMap->setDateTimeStorageFormat('date');
+               $this->assertEquals('2013-04-15', $subject->getPlainValue($input, $columnMap));
+       }
+
+       /**
+        * @test
+        * @dataProvider getPlainValueReturnsExpectedValuesDataProvider
+        */
+       public function getPlainValueReturnsExpectedValues($expectedValue, $input) {
+               $dataMapper = new DataMapper();
+               $this->assertSame($expectedValue, $dataMapper->getPlainValue($input));
+       }
+
+       /**
+        * @return array
+        */
+       public function getPlainValueReturnsExpectedValuesDataProvider() {
+               return array(
+                       'datetime to timestamp' => array('1365866253', new \DateTime('@1365866253')),
+                       'boolean true to 1' => array(1, TRUE),
+                       'boolean false to 0' => array(0, FALSE),
+                       'NULL is handled' => array('NULL', NULL),
+                       'plain value is returned unchanged' => array('RANDOM string', 'RANDOM string'),
+                       'array is flattened' => array('a,b,c', array('a', 'b', 'c')),
+                       'deep array is flattened' => array('a,b,c', array(array('a', 'b'), 'c')),
+               );
+       }
+
+       /**
+        * @test
+        * @expectedException \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException
+        */
+       public function getPlainValueCallsGetRealInstanceOnInputIfInputIsInstanceOfLazyLoadingProxy() {
+               $dataMapper = new DataMapper();
+               $input = $this->getMock(
+                       'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\LazyLoadingProxy',
+                       array(),
+                       array(),
+                       '',
+                       FALSE
+               );
+               $input->expects($this->once())->method('_loadRealInstance')->will($this->returnValue($dataMapper));
+               $dataMapper->getPlainValue($input);
+       }
+
+       /**
+        * @test
+        */
+       public function getPlainValueCallsGetUidOnDomainObjectInterfaceInput() {
+               $dataMapper = new DataMapper();
+               $input = $this->getMock(
+                       'TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface',
+                       array(),
+                       array(),
+                       '',
+                       FALSE
+               );
+               $input->expects($this->once())->method('getUid')->will($this->returnValue(23));
+               $this->assertSame(23, $dataMapper->getPlainValue($input));
+       }
+}
\ No newline at end of file
index 97d0168..5c71bd0 100644 (file)
@@ -13,6 +13,7 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Storage;
  *
  * The TYPO3 project - inspiring people to share!
  */
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
 
 /**
  * Test case
 
 /**
  * Test case
@@ -20,6 +21,18 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Storage;
 class Typo3DbBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        /**
 class Typo3DbBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
        /**
+        * @var DataMapper
+        */
+       protected static $dataMapper;
+
+       /**
+        * Setup DataMapper
+        */
+       public static function setUpBeforeClass() {
+               self::$dataMapper = new DataMapper();
+       }
+
+       /**
         * @test
         */
        public function uidOfAlreadyPersistedValueObjectIsDeterminedCorrectly() {
         * @test
         */
        public function uidOfAlreadyPersistedValueObjectIsDeterminedCorrectly() {
@@ -32,16 +45,16 @@ class Typo3DbBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $mockDataMap->expects($this->any())->method('isPersistableProperty')->will($this->returnValue(TRUE));
                $mockDataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($mockColumnMap));
                $mockDataMap->expects($this->any())->method('getTableName')->will($this->returnValue($tableName));
                $mockDataMap->expects($this->any())->method('isPersistableProperty')->will($this->returnValue(TRUE));
                $mockDataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($mockColumnMap));
                $mockDataMap->expects($this->any())->method('getTableName')->will($this->returnValue($tableName));
-               $mockDataMapper = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap'), array(), '', FALSE);
+               $mockDataMapper = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap', 'getPlainValue'), array(), '', FALSE);
                $mockDataMapper->expects($this->once())->method('getDataMap')->will($this->returnValue($mockDataMap));
                $mockDataMapper->expects($this->once())->method('getDataMap')->will($this->returnValue($mockDataMap));
+               $mockDataMapper->expects($this->once())->method('getPlainValue')->will($this->returnValue('plainPropertyValue'));
                $expectedStatement = 'SELECT * FROM tx_foo_table WHERE column_name=?';
                $expectedParameters = array('plainPropertyValue');
                $expectedUid = 52;
                $mockDataBaseHandle = $this->getMock('TYPO3\CMS\Core\Database\DatabaseConnection', array('sql_query', 'sql_fetch_assoc'), array(), '', FALSE);
                $mockDataBaseHandle->expects($this->once())->method('sql_query')->will($this->returnValue('resource'));
                $mockDataBaseHandle->expects($this->any())->method('sql_fetch_assoc')->with('resource')->will($this->returnValue(array('uid' => $expectedUid)));
                $expectedStatement = 'SELECT * FROM tx_foo_table WHERE column_name=?';
                $expectedParameters = array('plainPropertyValue');
                $expectedUid = 52;
                $mockDataBaseHandle = $this->getMock('TYPO3\CMS\Core\Database\DatabaseConnection', array('sql_query', 'sql_fetch_assoc'), array(), '', FALSE);
                $mockDataBaseHandle->expects($this->once())->method('sql_query')->will($this->returnValue('resource'));
                $mockDataBaseHandle->expects($this->any())->method('sql_fetch_assoc')->with('resource')->will($this->returnValue(array('uid' => $expectedUid)));
-               $mockTypo3DbBackend = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbBackend', array('getPlainValue', 'checkSqlErrors', 'replacePlaceholders', 'addVisibilityConstraintStatement'), array(), '', FALSE);
-               $mockTypo3DbBackend->expects($this->once())->method('getPlainValue')->will($this->returnValue('plainPropertyValue'));
+               $mockTypo3DbBackend = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbBackend', array('checkSqlErrors', 'replacePlaceholders', 'addVisibilityConstraintStatement'), array(), '', FALSE);
                $mockTypo3DbBackend->expects($this->once())->method('addVisibilityConstraintStatement')->with($this->isInstanceOf('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\QuerySettingsInterface'), $tableName, $this->isType('array'));
                $mockTypo3DbBackend->expects($this->once())->method('replacePlaceholders')->with($expectedStatement, $expectedParameters);
                $mockTypo3DbBackend->_set('dataMapper', $mockDataMapper);
                $mockTypo3DbBackend->expects($this->once())->method('addVisibilityConstraintStatement')->with($this->isInstanceOf('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\QuerySettingsInterface'), $tableName, $this->isType('array'));
                $mockTypo3DbBackend->expects($this->once())->method('replacePlaceholders')->with($expectedStatement, $expectedParameters);
                $mockTypo3DbBackend->_set('dataMapper', $mockDataMapper);
@@ -81,4 +94,31 @@ class Typo3DbBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $mockTypo3DbBackend->_set('pageRepository', $pageRepositoryMock);
                $this->assertSame(array($comparisonRow), $mockTypo3DbBackend->_call('doLanguageAndWorkspaceOverlay', $sourceMock, array($row), $mockQuerySettings, $workspaceUid));
        }
                $mockTypo3DbBackend->_set('pageRepository', $pageRepositoryMock);
                $this->assertSame(array($comparisonRow), $mockTypo3DbBackend->_call('doLanguageAndWorkspaceOverlay', $sourceMock, array($row), $mockQuerySettings, $workspaceUid));
        }
-}
+
+       /**
+        * @return array
+        */
+       public function resolveParameterPlaceholdersReplacesValuesDataProvider() {
+               return array(
+                       'string' => array('bar', '123', '123'),
+                       'array' => array('bar', array(1,2,3), '1,2,3'),
+               );
+       }
+
+       /**
+        * @param $parameter
+        * @param $value
+        * @param $expected
+        * @test
+        * @dataProvider resolveParameterPlaceholdersReplacesValuesDataProvider
+        */
+       public function resolveParameterPlaceholdersReplacesValues($parameter, $value, $expected) {
+               $mock = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbBackend', array('quoteTextValueCallback'));
+               $mock->expects($this->any())->method('quoteTextValueCallback')->will($this->returnArgument(0));
+               $mock->_set('dataMapper', self::$dataMapper);
+               $stmtParts = array('tables' => array('foo'), 'where' => $parameter);
+               $parameters = array($parameter => $value);
+               $result = $mock->_call('resolveParameterPlaceholders', $stmtParts, $parameters);
+               $this->assertSame($expected, $result['where']);
+       }
+}
\ No newline at end of file
index 53d022f..dc4552e 100644 (file)
@@ -386,128 +386,4 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
                $this->assertSame($expectedSql, $sql);
        }
 
                $this->assertSame($expectedSql, $sql);
        }
-
-       /**
-        * @test
-        * @expectedException \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException
-        */
-       public function getPlainValueThrowsExceptionIfInputIsArray() {
-               $mockTypo3DbQueryParser = $this->getAccessibleMock(
-                       'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser',
-                       array('dummy'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $mockTypo3DbQueryParser->_call('getPlainValue', array());
-       }
-
-       /**
-        * @test
-        */
-       public function getPlainValueReturnsTimestampIfDateTimeObjectIsGiven() {
-               $mockTypo3DbQueryParser = $this->getAccessibleMock(
-                       'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser',
-                       array('dummy'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $input = new \DateTime('@1365866253');
-               $this->assertSame('1365866253', $mockTypo3DbQueryParser->_call('getPlainValue', $input));
-       }
-
-       /**
-        * @test
-        */
-       public function getPlainValueReturnsIntegerOneIfValueIsBooleanTrue() {
-               $mockTypo3DbQueryParser = $this->getAccessibleMock(
-                       'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser',
-                       array('dummy'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $this->assertSame(1, $mockTypo3DbQueryParser->_call('getPlainValue', TRUE));
-       }
-
-       /**
-        * @test
-        */
-       public function getPlainValueReturnsIntegerZeroIfValueIsBooleanFalse() {
-               $mockTypo3DbQueryParser = $this->getAccessibleMock(
-                       'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser',
-                       array('dummy'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $this->assertSame(0, $mockTypo3DbQueryParser->_call('getPlainValue', FALSE));
-       }
-
-       /**
-        * @test
-        * @expectedException \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException
-        */
-       public function getPlainValueCallsGetRealInstanceOnInputIfInputIsInstanceOfLazyLoadingProxy() {
-               $mockTypo3DbQueryParser = $this->getAccessibleMock(
-                       'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser',
-                       array('dummy'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $input = $this->getMock(
-                       'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\LazyLoadingProxy',
-                       array(),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $input
-                       ->expects($this->once())
-                       ->method('_loadRealInstance');
-               $mockTypo3DbQueryParser->_call('getPlainValue', $input);
-       }
-
-       /**
-        * @test
-        */
-       public function getPlainValueCallsGetUidOnDomainObjectInterfaceInput() {
-               $mockTypo3DbQueryParser = $this->getAccessibleMock(
-                       'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser',
-                       array('dummy'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $input = $this->getMock(
-                       'TYPO3\\CMS\\Extbase\\DomainObject\\DomainObjectInterface',
-                       array(),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $input
-                       ->expects($this->once())
-                       ->method('getUid')
-                       ->will($this->returnValue(23));
-               $this->assertSame(23, $mockTypo3DbQueryParser->_call('getPlainValue', $input));
-       }
-
-       /**
-        * @test
-        */
-       public function getPlainValueReturnsSimpleType() {
-               $mockTypo3DbQueryParser = $this->getAccessibleMock(
-                       'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser',
-                       array('dummy'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $value = uniqid('foo_');
-               $this->assertSame($value, $mockTypo3DbQueryParser->_call('getPlainValue', $value));
-       }
-
 }
 }