[+FEATURE] Extbase (Persistence): Implemented a second Lazy Loading strategy called...
authorJochen Rau <j.rau@web.de>
Mon, 14 Sep 2009 09:37:35 +0000 (09:37 +0000)
committerJochen Rau <j.rau@web.de>
Mon, 14 Sep 2009 09:37:35 +0000 (09:37 +0000)
[+BUGFIX] Extbase (Persistence): It is now possible to pass an object as operand of a comparison.

12 files changed:
typo3/sysext/extbase/Classes/Persistence/Backend.php
typo3/sysext/extbase/Classes/Persistence/LazyLoadingProxy.php
typo3/sysext/extbase/Classes/Persistence/LazyObjectStorage.php [new file with mode: 0644]
typo3/sysext/extbase/Classes/Persistence/LoadingStrategyInterface.php [new file with mode: 0644]
typo3/sysext/extbase/Classes/Persistence/Mapper/ColumnMap.php
typo3/sysext/extbase/Classes/Persistence/Mapper/DataMap.php
typo3/sysext/extbase/Classes/Persistence/Mapper/DataMapper.php
typo3/sysext/extbase/Classes/Persistence/ObjectStorage.php
typo3/sysext/extbase/Classes/Persistence/Query.php
typo3/sysext/extbase/Classes/Property/Mapper.php
typo3/sysext/extbase/Classes/Reflection/ClassSchema.php
typo3/sysext/extbase/Classes/Utility/Extension.php

index f188169..8e4a8ba 100644 (file)
@@ -109,7 +109,6 @@ class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendIn
         *
         * @param Tx_Extbase_Persistence_IdentityMap $identityMap
         * @return void
-
         */
        public function injectIdentityMap(Tx_Extbase_Persistence_IdentityMap $identityMap) {
                $this->identityMap = $identityMap;
@@ -381,10 +380,10 @@ class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendIn
                                        foreach ($propertyValue as $relatedObject) {
                                                $queuedObjects[$propertyName][] = $relatedObject;
                                        }
-                                       $row[$columnName] = count($propertyValue); // Will be overwritten if the related objects are referenced by a comma separated list
                                        foreach ($this->getDeletedChildObjects($object, $propertyName) as $deletedObject) {
                                                $this->deleteObject($deletedObject, $object, $propertyName, TRUE, FALSE);
                                        }
+                                       $row[$columnName] = count($propertyValue); // Will be overwritten if the related objects are referenced by a comma separated list
                                }
                        } elseif ($propertyValue instanceof Tx_Extbase_DomainObject_DomainObjectInterface) {
                                // TODO Handle Value Objects different
@@ -435,7 +434,6 @@ class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendIn
                $className = get_class($object);
                $dataMap = $this->dataMapper->getDataMap($className);
                foreach ($queuedChildObjects as $propertyName => $childObjects) {
-                       $childPidArray = array();
                        $columnMap = $dataMap->getColumnMap($propertyName);
                        foreach($childObjects as $childObject) {
                                $this->persistObject($childObject, $object, $propertyName);
@@ -444,7 +442,11 @@ class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendIn
                                }
                        }
                        if ($columnMap->getParentKeyFieldName() === NULL) { // TRUE: We have to generate a comma separated list stored in the field
-                               $row[$propertyName] = implode(',', $childPidArray);
+                               if (count($childPidArray) > 0) {
+                                       $row[$propertyName] = implode(',', $childPidArray);
+                               } else {
+                                       $row[$propertyName] = NULL;
+                               }
                                $objectHasToBeUpdated = TRUE;
                        }
                }
@@ -653,4 +655,4 @@ class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendIn
 
 }
 
-?>
\ No newline at end of file
+?>
index 6703ccd..c54839c 100644 (file)
@@ -33,8 +33,7 @@
  * @subpackage Persistence
  * @version $Id: LazyLoadingProxy.php 2591 2009-06-09 19:23:47Z k-fish $
  */
-// TODO Implement support for CountableInterface
-class Tx_Extbase_Persistence_LazyLoadingProxy {
+class Tx_Extbase_Persistence_LazyLoadingProxy implements Tx_Extbase_Persistence_LoadingStrategyInterface {
 
        /**
         * @var Tx_Extbase_Persistence_QueryFactoryInterface
@@ -95,7 +94,11 @@ class Tx_Extbase_Persistence_LazyLoadingProxy {
                // it's parent... the result would be weird.
                if ($this->parentObject->_getProperty($this->propertyName) instanceof Tx_Extbase_Persistence_LazyLoadingProxy) {
                        $dataMapper = Tx_Extbase_Dispatcher::getPersistenceManager()->getBackend()->getDataMapper();
-                       $realInstance = $dataMapper->fetchRelatedObjects($this->parentObject, $this->propertyName, $this->fieldValue, $this->columnMap);
+                       $objects = $dataMapper->fetchRelatedObjects($this->parentObject, $this->propertyName, $this->fieldValue, $this->columnMap);
+                       $realInstance = new Tx_Extbase_Persistence_ObjectStorage();
+                       foreach ($objects as $object) {
+                               $realInstance->attach($object);
+                       }
                        $this->parentObject->_setProperty($this->propertyName, $realInstance);
                        $this->parentObject->_memorizeCleanState($this->propertyName);
                        return $realInstance;
@@ -161,4 +164,4 @@ class Tx_Extbase_Persistence_LazyLoadingProxy {
                unset($realInstance->$propertyName);
        }
 }
-?>
\ No newline at end of file
+?>
diff --git a/typo3/sysext/extbase/Classes/Persistence/LazyObjectStorage.php b/typo3/sysext/extbase/Classes/Persistence/LazyObjectStorage.php
new file mode 100644 (file)
index 0000000..b424564
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
+ *  All rights reserved
+ *
+ *  This class is a backport of the corresponding class of FLOW3.
+ *  All credits go to the v5 team.
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * A proxy that can replace any object and replaces itself in it's parent on
+ * first access (call, get, set, isset, unset).
+ *
+ * @package Extbase
+ * @subpackage Persistence
+ * @version $Id: LazyLoadingProxy.php 2591 2009-06-09 19:23:47Z k-fish $
+ */
+class Tx_Extbase_Persistence_LazyObjectStorage extends Tx_Extbase_Persistence_ObjectStorage implements Tx_Extbase_Persistence_LoadingStrategyInterface {
+
+       /**
+        * @var Tx_Extbase_Persistence_QueryFactoryInterface
+        */
+       protected $queryFactory;
+
+       /**
+        * The object this property is contained in.
+        *
+        * @var object
+        */
+       private $parentObject;
+
+       /**
+        * The name of the property represented by this proxy.
+        *
+        * @var string
+        */
+       private $propertyName;
+
+       /**
+        * The raw field value.
+        *
+        * @var mixed
+        */
+       private $fieldValue;
+
+       /**
+        *
+        * @var Tx_Extbase_Persistence_Mapper_ColumnMap
+        */
+       private $columnMap;
+
+       /**
+        * Constructs this proxy instance.
+        *
+        * @param object $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 Tx_Extbase_Persistence_Mapper_DataMap $dataMap The corresponding Data Map of the property
+        */
+       public function __construct($parentObject, $propertyName, $fieldValue, Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap) {
+               $this->queryFactory = t3lib_div::makeInstance('Tx_Extbase_Persistence_QueryFactory');
+               $this->parentObject = $parentObject;
+               $this->propertyName = $propertyName;
+               $this->fieldValue = $fieldValue;
+               $this->columnMap = $columnMap;
+               $this->storage = NULL; // TODO
+       }
+       
+       /**
+        * This is a function lazy load implementation. 
+        *
+        * @return void
+        */
+       protected function initializeStorage() {
+               if (is_null($this->storage)) {
+                       $dataMapper = Tx_Extbase_Dispatcher::getPersistenceManager()->getBackend()->getDataMapper();
+                       $objects = $dataMapper->fetchRelatedObjects($this->parentObject, $this->propertyName, $this->fieldValue, $this->columnMap);
+                       $storage = array();
+                       foreach ($objects as $object) {
+                               $storage[spl_object_hash($object)] = $object;
+                       }
+                       $this->storage = $storage;
+                       $this->parentObject->_memorizeCleanState($this->propertyName);
+               }
+               if (!is_array($this->storage)) {
+                       throw new Tx_Extbase_Persistence_Exception('The storage could not be initialized.', 1252393014); // TODO
+               }
+       }
+       
+       /**
+        * Counts the elements in the storage array
+        *
+        * @return void
+        */
+       public function count() {
+               $numberOfElements = NULL;
+               if ($this->columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
+                       if (isset($parentKeyFieldName)) {
+                               $numberOfElements = $this->fieldValue;
+                       } else {
+                               if (empty($this->fieldValue)) {
+                                       $numberOfElements = 0;
+                               }
+                               $numberOfElements = count(explode(',', $this->fieldValue));
+                       }
+               } elseif ($this->columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
+                       $numberOfElements = $this->fieldValue;                  
+               } else {
+                       $this->initializeStorage();
+                       $numberOfElements = count($this->storage);                      
+               }
+               if (is_null($numberOfElements)) {
+                       throw new Tx_Extbase_Persistence_Exception('The number of elements could not be determined.', 1252514486);
+               }
+               return $numberOfElements;
+       }
+
+
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Classes/Persistence/LoadingStrategyInterface.php b/typo3/sysext/extbase/Classes/Persistence/LoadingStrategyInterface.php
new file mode 100644 (file)
index 0000000..535e07a
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
+ *  All rights reserved
+ *
+ *  This class is a backport of the corresponding class of FLOW3.
+ *  All credits go to the v5 team.
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * An interface for the lazy loading strategies.
+ *
+ * @package Extbase
+ * @subpackage Persistence
+ * @version $Id: LazyLoadingProxy.php 2591 2009-06-09 19:23:47Z k-fish $
+ */
+interface Tx_Extbase_Persistence_LoadingStrategyInterface {
+
+}
+?>
\ No newline at end of file
index b9bb37b..8f091a4 100644 (file)
@@ -44,8 +44,9 @@ class Tx_Extbase_Persistence_Mapper_ColumnMap {
         * Constants reflecting the loading strategy
         */
        const STRATEGY_EAGER = 'eager';
-       const STRATEGY_PROXY = 'proxy';
-
+       const STRATEGY_LAZY_PROXY = 'proxy';
+       const STRATEGY_LAZY_STORAGE = 'storage';
+       
        /**
         * The property name corresponding to the table name
         *
@@ -210,8 +211,8 @@ class Tx_Extbase_Persistence_Mapper_ColumnMap {
 
        public function setLoadingStrategy($loadingStrategy) {
                switch ($loadingStrategy) {
-                       case self::STRATEGY_PROXY;
-                       // Add more to check for allowed strategies, or-even better-use an interface
+                       case self::STRATEGY_LAZY_PROXY;
+                       case self::STRATEGY_LAZY_STORAGE;
                                $this->loadingStrategy = $loadingStrategy;
                                break;
                        default:
@@ -329,4 +330,4 @@ class Tx_Extbase_Persistence_Mapper_ColumnMap {
        }
 
 }
-?>
\ No newline at end of file
+?>
index bf4a1ee..6be84e7 100644 (file)
@@ -126,7 +126,6 @@ class Tx_Extbase_Persistence_Mapper_DataMap {
                                }
                                $columnMap = new Tx_Extbase_Persistence_Mapper_ColumnMap($columnName, $propertyName);
                                $this->setPropertyType($columnMap, $columnConfiguration);
-                               // TODO Check support for IRRE
                                $this->setRelations($columnMap, $columnConfiguration);
                                $this->addColumnMap($columnMap);
                        }
@@ -570,4 +569,4 @@ class Tx_Extbase_Persistence_Mapper_DataMap {
                return $convertedValue;
        }
 
-}
\ No newline at end of file
+}
index d727f3a..218651a 100644 (file)
@@ -140,7 +140,6 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
         *
         * @param string $className Name of the class to create a skeleton for
         * @return object The object skeleton
-
         */
        protected function createEmptyObject($className) {
                // Note: The class_implements() function also invokes autoload to assure that the interfaces
@@ -215,18 +214,33 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
         * @param int $loadingStrategy The loading strategy; one of Tx_Extbase_Persistence_Mapper_ColumnMap::STRATEGY_*
         * @return array|Tx_Extbase_Persistence_ObjectStorage|Tx_Extbase_Persistence_LazyLoadingProxy|another implementation of a loading strategy
         */
-       // FIXME There is a recursion problem with post1 -> post2 and post2 -> post1
        protected function mapRelatedObjects(Tx_Extbase_DomainObject_AbstractEntity $parentObject, $propertyName, Tx_Extbase_Persistence_RowInterface $row, Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap) {
                $dataMap = $this->getDataMap(get_class($parentObject));
                $columnMap = $dataMap->getColumnMap($propertyName);
                $fieldValue = $row[$columnMap->getColumnName()];
-               if ($columnMap->getLoadingStrategy() === Tx_Extbase_Persistence_Mapper_ColumnMap::STRATEGY_PROXY) {
-                       // TODO Remove dependency to the loading strategy implementation
+               if ($columnMap->getLoadingStrategy() === Tx_Extbase_Persistence_Mapper_ColumnMap::STRATEGY_LAZY_PROXY) {
                        $result = t3lib_div::makeInstance('Tx_Extbase_Persistence_LazyLoadingProxy', $parentObject, $propertyName, $fieldValue, $columnMap);
                } else {
-                       $result = $this->fetchRelatedObjects($parentObject, $propertyName, $fieldValue, $columnMap);
+                       $queryFactory = t3lib_div::makeInstance('Tx_Extbase_Persistence_QueryFactory');
+                       if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE) {
+                               $query = $queryFactory->create($columnMap->getChildClassName());
+                               // TODO: This is an ugly hack, just ignoring the storage page state from here. Actually, the query settings would have to be passed into the DataMapper, so we can respect
+                               // enableFields and storage page settings.
+                               $query->getQuerySettings()->setRespectStoragePage(FALSE);
+                               $result = current($query->matching($query->withUid((int)$fieldValue))->execute());
+                       } else {
+                               if ($columnMap->getLoadingStrategy() === Tx_Extbase_Persistence_Mapper_ColumnMap::STRATEGY_LAZY_STORAGE) {
+                                       $objectStorage = new Tx_Extbase_Persistence_LazyObjectStorage($parentObject, $propertyName, $fieldValue, $columnMap);
+                               } else {
+                                       $objects = $this->fetchRelatedObjects($parentObject, $propertyName, $fieldValue, $columnMap);
+                                       $objectStorage = new Tx_Extbase_Persistence_ObjectStorage();
+                                       foreach ($objects as $object) {
+                                               $objectStorage->attach($object);
+                                       }
+                               }
+                               $result = $objectStorage;
+                       }
                }
-
                return $result;
        }
 
@@ -237,33 +251,20 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
         * @param string $propertyName The name of the proxied property in it's parent
         * @param mixed $fieldValue The raw field value.
         * @param Tx_Extbase_Persistence_Mapper_DataMap $dataMap The corresponding Data Map of the property
+        * @return Tx_Extbase_Persistence_ObjectStorage An Object Storage containing the related objects 
         */
        public function fetchRelatedObjects(Tx_Extbase_DomainObject_AbstractEntity $parentObject, $propertyName, $fieldValue, Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap) {
                $queryFactory = t3lib_div::makeInstance('Tx_Extbase_Persistence_QueryFactory');
-               if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE) {
-                       $query = $queryFactory->create($columnMap->getChildClassName());
-                       // TODO: This is an ugly hack, just ignoring the storage page state from here. Actually, the query settings would have to be passed into the DataMapper, so we can respect
-                       // enableFields and storage page settings.
-                       $query->getQuerySettings()->setRespectStoragePage(FALSE);
-                       $result = current($query->matching($query->withUid((int)$fieldValue))->execute());
-               } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
-                       $objectStorage = new Tx_Extbase_Persistence_ObjectStorage();
+               if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
                        $query = $queryFactory->create($columnMap->getChildClassName());
                        $parentKeyFieldName = $columnMap->getParentKeyFieldName();
                        if (isset($parentKeyFieldName)) {
                                $objects = $query->matching($query->equals($columnMap->getParentKeyFieldName(), $parentObject->getUid()))->execute();
                        } else {
-                               $uidArray = t3lib_div::intExplode(',', $fieldValue);
-                               $uids = implode(',', $uidArray);
                                // FIXME Using statement() is only a preliminary solution
-                               $objects = $query->statement('SELECT * FROM ' . $columnMap->getChildTableName() . ' WHERE uid IN (' . $uids . ')')->execute();
-                       }
-                       foreach ($objects as $object) {
-                               $objectStorage->attach($object);
+                               $objects = $query->statement('SELECT * FROM ' . $columnMap->getChildTableName() . ' WHERE uid IN (' . $fieldValue . ')')->execute();
                        }
-                       $result = $objectStorage;
                } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
-                       $objectStorage = new Tx_Extbase_Persistence_ObjectStorage();
                        $relationTableName = $columnMap->getRelationTableName();
                        $left = $this->QOMFactory->selector(NULL, $relationTableName);
                        $childClassName = $columnMap->getChildClassName();
@@ -279,13 +280,10 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
                        $query = $queryFactory->create($columnMap->getChildClassName());
                        $query->setSource($source);
                        $objects = $query->matching($query->equals($columnMap->getParentKeyFieldName(), $parentObject->getUid()))->execute();
-                       foreach ($objects as $object) {
-                               $objectStorage->attach($object);
-                       }
-                       $result = $objectStorage;
+               } else {
+                       throw new Tx_Extbase_Persistence_Exception('Could not determine type of relation.', 1252502725);
                }
-
-               return $result;
+               return $objects;
        }
 
        /**
@@ -309,27 +307,36 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
        public function getDataMap($className) {
                if (!is_string($className) || strlen($className) === 0) throw new Tx_Extbase_Persistence_Exception('No class name was given to retrieve the Data Map for.', 1251315965);
                if (empty($this->dataMaps[$className])) {
-                       // FIXME This is a costy for table name aliases -> implement a DataMapBuilder (knowing the aliases defined in $TCA)
-                       $mapping = array();
+                       // FIXME This is too expensive for table name aliases -> implement a DataMapBuilder (knowing the aliases defined in $TCA)
+                       $columnMapping = array();
                        $extbaseSettings = Tx_Extbase_Dispatcher::getExtbaseFrameworkConfiguration();
-                       if (isset($extbaseSettings['persistence']['classes'][$className]) && !empty($extbaseSettings['persistence']['classes'][$className]['mapping']['tableName'])) {
-                               $tableName = $extbaseSettings['persistence']['classes'][$className]['mapping']['tableName'];
+                       if (is_array($extbaseSettings['persistence']['classes'][$className])) {
+                               $persistenceSettings = $extbaseSettings['persistence']['classes'][$className];
+                               if (is_string($persistenceSettings['mapping']['tableName']) && strlen($persistenceSettings['mapping']['tableName']) > 0) {
+                                       $tableName = $persistenceSettings['mapping']['tableName'];
+                               }
+                               if (is_array($persistenceSettings['mapping']['columns'])) {
+                                       $columnMapping = $persistenceSettings['mapping']['columns'];
+                               }
                        } else {
                                foreach (class_parents($className) as $parentClassName) {
-                                       if (isset($extbaseSettings['persistence']['classes'][$parentClassName]) && !empty($extbaseSettings['persistence']['classes'][$parentClassName]['mapping']['tableName'])) {
-                                               $tableName = $extbaseSettings['persistence']['classes'][$parentClassName]['mapping']['tableName'];
-                                               break;
+                                       $persistenceSettings = $extbaseSettings['persistence']['classes'][$parentClassName];
+                                       if (is_array($persistenceSettings)) {
+                                               if (is_string($persistenceSettings['mapping']['tableName']) && strlen($persistenceSettings['mapping']['tableName']) > 0) {
+                                                       $tableName = $persistenceSettings['mapping']['tableName'];
+                                               }
+                                               if (is_array($persistenceSettings['mapping']['columns'])) {
+                                                       $columnMapping = $persistenceSettings['mapping']['columns'];
+                                               }
                                        }
+                                       break;
                                }
                        }
-                       if (is_array($extbaseSettings['persistence']['classes'][$parentClassName]['mapping']['columns'])) {
-                               $mapping = $extbaseSettings['persistence']['classes'][$parentClassName]['mapping']['columns'];
-                       }
 
-                       $dataMap = new Tx_Extbase_Persistence_Mapper_DataMap($className, $tableName, $mapping);
+                       $dataMap = new Tx_Extbase_Persistence_Mapper_DataMap($className, $tableName, $columnMapping);
                        $this->dataMaps[$className] = $dataMap;
                }
-               return $this->dataMaps[$className];
+               return $this->dataMaps[$className];
        }
 
        /**
index 80b20f1..94a2119 100644 (file)
@@ -37,14 +37,24 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         *
         * @var array
         */
-       private $storage = array();
+       protected $storage = array();
 
        /**
+        * This is a template function to be overwritten by a concrete implementation. It enables you to implement
+        * a lazy load implementation. 
+        *
+        * @return void
+        */
+       protected function initializeStorage() {
+       }
+       
+       /**
         * Resets the array pointer of the storage
         *
         * @return void
         */
        public function rewind() {
+               $this->initializeStorage();
                reset($this->storage);
        }
 
@@ -54,6 +64,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         * @return void
         */
        public function valid() {
+               $this->initializeStorage();
                return $this->current() !== FALSE;
        }
 
@@ -63,6 +74,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         * @return void
         */
        public function key() {
+               $this->initializeStorage();
                return key($this->storage);
        }
 
@@ -72,6 +84,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         * @return void
         */
        public function current() {
+               $this->initializeStorage();
                return current($this->storage);
        }
 
@@ -81,6 +94,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         * @return void
         */
        public function next() {
+               $this->initializeStorage();
                next($this->storage);
        }
 
@@ -90,6 +104,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         * @return void
         */
        public function count() {
+               $this->initializeStorage();
                return count($this->storage);
        }
 
@@ -102,8 +117,10 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         */
        public function offsetSet($offset, $value) {
                if (!is_object($offset)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Expected parameter 1 to be object, ' . gettype($offset) . ' given');
+               // TODO Check implementation again
                // if (!is_object($obj)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Expected parameter 2 to be object, ' . gettype($offset) . ' given');
                // if (!($offset === $obj)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Parameter 1 and parameter 2 must be a reference to the same object.');
+               $this->initializeStorage();
                if (!$this->contains($offset)) {
                        $this->storage[spl_object_hash($offset)] = $value;
                }
@@ -117,6 +134,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         */
        public function offsetExists($offset) {
                if (!is_object($offset)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Expected parameter to be an object, ' . gettype($offset) . ' given');
+               $this->initializeStorage();
                return isset($this->storage[spl_object_hash($offset)]);
        }
 
@@ -128,6 +146,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         */
        public function offsetUnset($offset) {
                if (!is_object($offset)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Expected parameter to be an object, ' . gettype($offset) . ' given');
+               $this->initializeStorage();
                unset($this->storage[spl_object_hash($offset)]);
        }
 
@@ -139,6 +158,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         */
        public function offsetGet($offset) {
                if (!is_object($offset)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Expected parameter to be an object, ' . gettype($offset) . ' given');
+               $this->initializeStorage();
                return isset($this->storage[spl_object_hash($offset)]) ? $this->storage[spl_object_hash($offset)] : NULL;
        }
 
@@ -150,6 +170,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         */
        public function contains($object) {
                if (!is_object($object)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Expected parameter to be an object, ' . gettype($object) . ' given');
+               $this->initializeStorage();
                return array_key_exists(spl_object_hash($object), $this->storage);
        }
 
@@ -161,6 +182,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         */
        public function attach($object, $value = NULL) {
                if (!is_object($object)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Expected parameter to be an object, ' . gettype($object) . ' given');
+               $this->initializeStorage();
                if (!$this->contains($object)) {
                        if ($value === NULL) {
                                $value = $object;
@@ -178,6 +200,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         */
        public function detach($object) {
                if (!is_object($object)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Expected parameter to be an object, ' . gettype($object) . ' given');
+               $this->initializeStorage();
                unset($this->storage[spl_object_hash($object)]);
        }
 
@@ -189,6 +212,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         */
        public function addAll($objects) {
                if (is_array($objects) || ($objects instanceof Tx_Extbase_Persistence_ObjectStorage)) {
+                       $this->initializeStorage();
                        foreach ($objects as $object) {
                                $this->attach($object);
                        }
@@ -205,6 +229,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         */
        public function removeAll($objects) {
                if (!is_array($object)) throw new Tx_Extbase_MVC_Exception_InvalidArgumentType('Expected parameter to be an array, ' . gettype($object) . ' given');
+               $this->initializeStorage();
                foreach ($objects as $object) {
                        $this->detach($object);
                }
@@ -216,9 +241,10 @@ class Tx_Extbase_Persistence_ObjectStorage implements Iterator, Countable, Array
         * @return array The object storage
         */
        public function toArray() {
+               $this->initializeStorage();
                return $this->storage;
        }
 
 }
 
-?>
\ No newline at end of file
+?>
index c8faa0d..7752a76 100644 (file)
@@ -371,50 +371,28 @@ class Tx_Extbase_Persistence_Query implements Tx_Extbase_Persistence_QueryInterf
        public function equals($propertyName, $operand, $caseSensitive = TRUE) {
                $uniqueVariableName = uniqid($propertyName);
                if (is_object($operand) && !($operand instanceof DateTime)) {
-                       // FIXME This branch of if-then-else is not fully backported and non functional by now
                        $operand = $this->persistenceManager->getBackend()->getIdentifierByObject($operand);
-                       $left = $source;
-                       $columnMap = $this->dataMapper->getDataMap($this->className)->getColumnMap($propertyName);
-                       $childTableName = $columnMap->getChildTableName();
-                       $right = $this->QOMFactory->selector($childClassName);
-                       $joinCondition = $this->QOMFactory->childNodeJoinCondition($childTableName, $parentTableName);
-
-                       $this->source = $this->QOMFactory->join(
-                               $left,
-                               $right,
-                               Tx_Extbase_Persistence_QOM_QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_INNER,
-                               $joinCondition
+               }
+               if ($caseSensitive) {
+                       $comparison = $this->QOMFactory->comparison(
+                               $this->QOMFactory->propertyValue($propertyName, $this->getSelectorName()),
+                               Tx_Extbase_Persistence_QOM_QueryObjectModelConstantsInterface::JCR_OPERATOR_EQUAL_TO,
+                               $this->QOMFactory->bindVariable($uniqueVariableName)
                                );
-
+               } else {
                        $comparison = $this->QOMFactory->comparison(
-                               $this->QOMFactory->propertyValue($propertyName, $sourceSelectorName),
+                               $this->QOMFactory->lowerCase(
+                                       $this->QOMFactory->propertyValue($propertyName, $this->getSelectorName())
+                               ),
                                Tx_Extbase_Persistence_QOM_QueryObjectModelConstantsInterface::JCR_OPERATOR_EQUAL_TO,
                                $this->QOMFactory->bindVariable($uniqueVariableName)
                                );
-                               
+               }
+
+               if ($caseSensitive) {
                        $this->operands[$uniqueVariableName] = $operand;
                } else {
-                       if ($caseSensitive) {
-                               $comparison = $this->QOMFactory->comparison(
-                                       $this->QOMFactory->propertyValue($propertyName, $this->getSelectorName()),
-                                       Tx_Extbase_Persistence_QOM_QueryObjectModelConstantsInterface::JCR_OPERATOR_EQUAL_TO,
-                                       $this->QOMFactory->bindVariable($uniqueVariableName)
-                                       );
-                       } else {
-                               $comparison = $this->QOMFactory->comparison(
-                                       $this->QOMFactory->lowerCase(
-                                               $this->QOMFactory->propertyValue($propertyName, $this->getSelectorName())
-                                       ),
-                                       Tx_Extbase_Persistence_QOM_QueryObjectModelConstantsInterface::JCR_OPERATOR_EQUAL_TO,
-                                       $this->QOMFactory->bindVariable($uniqueVariableName)
-                                       );
-                       }
-
-                       if ($caseSensitive) {
-                               $this->operands[$uniqueVariableName] = $operand;
-                       } else {
-                               $this->operands[$uniqueVariableName] = strtolower($operand);
-                       }
+                       $this->operands[$uniqueVariableName] = strtolower($operand);
                }
 
                return $comparison;
index 2251eef..db164d7 100644 (file)
@@ -266,7 +266,7 @@ class Tx_Extbase_Property_Mapper {
                                }
                        }
                } else {
-                       throw new InvalidArgumentException('transformToObject() accepts only strings and arrays.', 1251814355);
+                       throw new InvalidArgumentException('transformToObject() accepts only numeric values and arrays.', 1251814355);
                }
 
                return $propertyValue;
index aefbb56..09078c1 100644 (file)
@@ -121,7 +121,7 @@ class Tx_Extbase_Reflection_ClassSchema {
                        $type = ($matches['type'] === 'int') ? 'integer' : $matches['type'];
                        $elementType = isset($matches['elementType']) ? $matches['elementType'] : NULL;
 
-                       if ($elementType !== NULL && !in_array($type, array('array', 'ArrayObject', 'SplObjectStorage'))) {
+                       if ($elementType !== NULL && !in_array($type, array('array', 'ArrayObject', 'Tx_Extbase_Persistence_ObjectStorage', 'Tx_Extbase_Persistence_LazyObjectStorage'))) {
                                throw new Tx_Extbase_Reflection_Exception_InvalidPropertyType('Property  of type "' . $type . '" must not have an element type hint (' . $elementType . ').', 1248103053);
                        }
 
@@ -269,4 +269,4 @@ class Tx_Extbase_Reflection_ClassSchema {
        }
 
 }
-?>
\ No newline at end of file
+?>
index c38ef1c..b54ff58 100644 (file)
@@ -284,8 +284,8 @@ tt_content.list.20.' . $pluginSignature . ' {
                        $config['labels'] = '';
                        $config['extRelPath'] = $relPath;
                }
-                               
-               if ((strlen($main) > 0) && !isset($GLOBALS['TBE_MODULES'][$main])) {
+
+               if ((strlen($main) > 0) && !array_key_exists($main, $GLOBALS['TBE_MODULES'])) {
                        $main = $extensionName . self::convertLowerUnderscoreToUpperCamelCase($main);
                } else {
                        $main = (strlen($main) > 0) ? $main : 'web'; // TODO By now, $main must default to 'web'
@@ -487,4 +487,4 @@ tt_content.list.20.' . $pluginSignature . ' {
        }
        
 }
-?>
\ No newline at end of file
+?>