Raised Extbase version to 1.2.0RC2
authorBenni Mack <benni.mack@typo3.org>
Sun, 20 Jun 2010 15:00:52 +0000 (15:00 +0000)
committerBenni Mack <benni.mack@typo3.org>
Sun, 20 Jun 2010 15:00:52 +0000 (15:00 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@7992 709f56b5-9817-0410-a4d7-c38de5d9e867

19 files changed:
ChangeLog
NEWS.txt
typo3/sysext/extbase/Classes/DomainObject/AbstractDomainObject.php
typo3/sysext/extbase/Classes/DomainObject/AbstractEntity.php
typo3/sysext/extbase/Classes/DomainObject/DomainObjectInterface.php
typo3/sysext/extbase/Classes/MVC/Web/Routing/UriBuilder.php
typo3/sysext/extbase/Classes/Persistence/Backend.php
typo3/sysext/extbase/Classes/Persistence/LazyObjectStorage.php
typo3/sysext/extbase/Classes/Persistence/Mapper/DataMapFactory.php
typo3/sysext/extbase/Classes/Persistence/Mapper/DataMapper.php
typo3/sysext/extbase/Classes/Persistence/ObjectMonitoringInterface.php [new file with mode: 0644]
typo3/sysext/extbase/Classes/Persistence/ObjectStorage.php
typo3/sysext/extbase/Classes/Persistence/QOM/QueryObjectModelFactory.php
typo3/sysext/extbase/Classes/Persistence/QOM/Statement.php
typo3/sysext/extbase/Classes/Persistence/Storage/Typo3DbBackend.php
typo3/sysext/extbase/Tests/DomainObject/AbstractEntity_testcase.php
typo3/sysext/extbase/Tests/MVC/Web/Routing/UriBuilder_testcase.php
typo3/sysext/extbase/Tests/Persistence/Mapper/DataMapFactory_testcase.php
typo3/sysext/extbase/ext_autoload.php

index 6f51857..97ec5b9 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,7 @@
 
 2010-06-20  Benjamin Mack  <benni@typo3.org>
 
+       * Raised Extbase version to 1.2.0RC2
        * Fixed bug #14722: Remove info icon from CEs in page module (Thanks to Steffen Gebert)
        * Followup to #14733: Improvements to Backend skin - Added styling to missing parts of the Backend - TCEforms without tabs, TCEforms with Flexforms, TCEforms with IRRE, TSconfig help, help styling improvements
        * Followup to #13379: Sprite Icon API - Removed unneeded checks in ext_tables.php for t3skin (Thanks to Steffen Ritter)
index 0186eef..4db76fe 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -84,6 +84,8 @@ Compatibility
 
        * Extbase: has been updated to support "Single Table Inheritance" which is a breaking change.  In TYPO3 4.3, Extbase made a "best guess" for the table name if it was not the lowercased class name (simply by crawling the class hierarchy upwards trying to find a mapping rule or table). This "magic" was removed because It was very hard to understand what was happening; especially if there was an error. This behaviour is now changed and you define the recordType and the tableName through TypoScript now. See the typo3.projecty.typo3v4mvc mailing list for more details on this topic.
 
+       * Extbase: Template filenames are expected to be UpperCamelCased from now on. Before, they were expected to be all lowercase. For a grace period there is still a fallback mechanism, so that your old template filenames will still work. But you should rename your templates from "myaction.html" to "MyAction.html" to make sure, that it still works in upcoming versions of Fluid!  A message to the deprecation log is generated in case an "old" template name is found.
+
        * Support for GDlib 1.x was completely dropped, only GDlib 2.x is supported, which is bundled with most PHP installations.
 
        * Versioning: "Page" and "Branch" versioning has been disabled for all installations, because it is deprecated since TYPO3 4.2. If you still use one of these versioning types, make sure to set $TYPO3_CONF_VARS['BE']['elementVersioningOnly'] = FALSE in your localconf.php. Please be aware that this option will vanish with TYPO3 4.6 and that "Page" and "Branch" versioning is neither supported nor maintained any longer.
index 2a5f020..ef8ef87 100644 (file)
@@ -31,7 +31,7 @@
  * @subpackage DomainObject
  * @version $ID:$
  */
-abstract class Tx_Extbase_DomainObject_AbstractDomainObject implements Tx_Extbase_DomainObject_DomainObjectInterface {
+abstract class Tx_Extbase_DomainObject_AbstractDomainObject implements Tx_Extbase_DomainObject_DomainObjectInterface, Tx_Extbase_Persistence_ObjectMonitoringInterface {
 
        /**
         * @var int The uid
index 69d57d4..04909bf 100644 (file)
@@ -35,7 +35,7 @@ abstract class Tx_Extbase_DomainObject_AbstractEntity extends Tx_Extbase_DomainO
        /**
         * @var An array holding the clean property values. Set right after reconstitution of the object
         */
-       private $_cleanProperties = array();
+       private $_cleanProperties;
 
        /**
         * Register an object's clean state, e.g. after it has been reconstituted
@@ -66,6 +66,9 @@ abstract class Tx_Extbase_DomainObject_AbstractEntity extends Tx_Extbase_DomainO
         */
        public function _memorizePropertyCleanState($propertyName) {
                $propertyValue = $this->$propertyName;
+               if (!is_array($this->_cleanProperties)) {
+                       $this->_cleanProperties = array();
+               }
                if (is_object($propertyValue)) {
                        $this->_cleanProperties[$propertyName] = clone($propertyValue);
 
@@ -114,35 +117,40 @@ abstract class Tx_Extbase_DomainObject_AbstractEntity extends Tx_Extbase_DomainO
         * @return boolean
         */
        public function _isDirty($propertyName = NULL) {
-               if (empty($this->_cleanProperties)) return TRUE;
-               // if (!is_array($this->_cleanProperties)) throw new Tx_Extbase_Persistence_Exception_CleanStateNotMemorized('The clean state of the object "' . get_class($this) . '" has not been memorized before asking _isDirty().', 1233309106);
-               if ($this->uid !== NULL && $this->uid != $this->_cleanProperties['uid']) throw new Tx_Extbase_Persistence_Exception_TooDirty('The uid "' . $this->uid . '" has been modified, that is simply too much.', 1222871239);
+               if ($this->uid !== NULL && is_array($this->_cleanProperties) && $this->uid != $this->_getCleanProperty('uid')) throw new Tx_Extbase_Persistence_Exception_TooDirty('The uid "' . $this->uid . '" has been modified, that is simply too much.', 1222871239);
+               if ($propertyName === NULL) {
+                       foreach ($this->_getCleanProperties() as $propertyName => $cleanPropertyValue) {
+                               if ($this->isPropertyDirty($cleanPropertyValue, $this->$propertyName) === TRUE) return TRUE;
+                       }
+               } else {
+                       if ($this->isPropertyDirty($this->_getCleanProperty($propertyName), $this->$propertyName) === TRUE) return TRUE;
+               }
+               return FALSE;
+       }
+
+       /**
+        * Checks the $value against the $cleanState.
+        *
+        * @param mixed $previousValue
+        * @param mixed $currentValue
+        * @return boolan
+        */
+       protected function isPropertyDirty($previousValue, $currentValue) {
                $result = FALSE;
-               if ($propertyName !== NULL) {
-                       if (is_object($this->$propertyName)) {
-                               // In case it is an object, we do a simple comparison (!=) as we want cloned objects to return the same values.
-                               $result = $this->_cleanProperties[$propertyName] != $this->$propertyName;
+               // In case it is an object and it implements the ObjectMonitoringInterface, we call _isDirty() instead of a simple comparison of objects.
+               // We do this, because if the object itself contains a lazy loaded property, the comparison of the objects might fail even if the object didn't change
+               if (is_object($currentValue)) {
+                       if ($currentValue instanceof Tx_Extbase_Persistence_ObjectMonitoringInterface) {
+                               $result = !is_object($previousValue) || $currentValue->_isDirty() || (get_class($previousValue) !== get_class($currentValue));
                        } else {
-                               $result = $this->_cleanProperties[$propertyName] !== $this->$propertyName;
+                               // For all other objects we do only a simple comparison (!=) as we want cloned objects to return the same values.
+                               $result = ($previousValue != $currentValue);
                        }
                } else {
-                       foreach ($this->_cleanProperties as $propertyName => $propertyValue) {
-                               if (is_object($this->$propertyName)) {
-                                       // In case it is an object, we do a simple comparison (!=) as we want cloned objects to return the same values.
-                                       if ($this->$propertyName != $propertyValue) {
-                                               $result = TRUE;
-                                               break;
-                                       }
-                               } else {
-                                       if ($this->$propertyName !== $propertyValue) {
-                                               $result = TRUE;
-                                               break;
-                                       }
-                               }
-                       }
+                       $result = ($previousValue !== $currentValue);
                }
                return $result;
        }
-
+       
 }
 ?>
\ No newline at end of file
index a104723..34c43dc 100644 (file)
@@ -44,14 +44,6 @@ interface Tx_Extbase_DomainObject_DomainObjectInterface {
        public function getUid();
 
        /**
-        * Register an object's clean state, e.g. after it has been reconstituted
-        * from the database
-        *
-        * @return void
-        */
-       public function _memorizeCleanState();
-
-       /**
         * Returns TRUE if the object is new (the uid was not set, yet). Only for internal use
         *
         * @return boolean
@@ -59,13 +51,6 @@ interface Tx_Extbase_DomainObject_DomainObjectInterface {
        public function _isNew();
 
        /**
-        * Returns TRUE if the properties were modified after reconstitution
-        *
-        * @return boolean
-        */
-       public function _isDirty();
-
-       /**
         * Reconstitutes a property. Only for internal use.
         *
         * @param string $propertyName
index 951de95..54a673b 100644 (file)
@@ -482,11 +482,11 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
        public function buildFrontendUri() {
                $typolinkConfiguration = $this->buildTypolinkConfiguration();
 
-               $uri = $this->contentObject->typoLink_URL($typolinkConfiguration);
-               $uri = ltrim($uri, '/');
                if ($this->createAbsoluteUri === TRUE) {
-                       $uri = $this->request->getBaseURI() . $uri;
+                       $typolinkConfiguration['forceAbsoluteUrl'] = TRUE;
                }
+
+               $uri = $this->contentObject->typoLink_URL($typolinkConfiguration);
                return $uri;
        }
 
index 1d6e99c..cb444b8 100644 (file)
@@ -46,6 +46,11 @@ class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendIn
        protected $aggregateRootObjects;
 
        /**
+        * @var Tx_Extbase_Persistence_ObjectStorage
+        */
+       protected $visitedDuringPersistence;
+
+       /**
         * @var Tx_Extbase_Persistence_IdentityMap
         **/
        protected $identityMap;
@@ -335,6 +340,7 @@ class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendIn
         * @return void
         */
        protected function persistObjects() {
+               $this->visitedDuringPersistence = new Tx_Extbase_Persistence_ObjectStorage();
                foreach ($this->aggregateRootObjects as $object) {
                        if (!$this->identityMap->hasObject($object)) {
                                $this->insertObject($object);
@@ -354,6 +360,12 @@ class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendIn
         * @return void
         */
        protected function persistObject(Tx_Extbase_DomainObject_DomainObjectInterface $object) {
+               if (isset($this->visitedDuringPersistence[$object])) {
+                       return $this->visitedDuringPersistence[$object];
+               } else {
+                       $this->visitedDuringPersistence[$object] = $object->getUid();
+               }
+
                $row = array();
                $queue = array();
                $className = get_class($object);
@@ -383,12 +395,12 @@ class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendIn
                                        if ($propertyValue->_isNew()) {
                                                if ($propertyValue instanceof Tx_Extbase_DomainObject_AbstractEntity) {
                                                        $this->insertObject($propertyValue);
-                                                       $queue[] = $propertyValue;
                                                } else {
                                                        $this->persistValueObject($propertyValue);
                                                }
                                        }
                                        $row[$columnMap->getColumnName()] = $this->getPlainValue($propertyValue);
+                                       $queue[] = $propertyValue;
                                }
                        } elseif ($object instanceof Tx_Extbase_DomainObject_AbstractValueObject || $object->_isNew() || $object->_isDirty($propertyName)) {
                                $row[$columnMap->getColumnName()] = $this->getPlainValue($propertyValue);
index 470bb45..b38e678 100644 (file)
@@ -97,6 +97,7 @@ class Tx_Extbase_Persistence_LazyObjectStorage extends Tx_Extbase_Persistence_Ob
                        foreach ($objects as $object) {
                                parent::attach($object);
                        }
+                       $this->_memorizeCleanState();
                        $this->parentObject->_memorizeCleanState($this->propertyName);
                }
        }
index ca13337..48c9164 100644 (file)
@@ -177,18 +177,14 @@ class Tx_Extbase_Persistence_Mapper_DataMapFactory {
         */
        protected function setRelations(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration, $propertyMetaData) {
                if (isset($columnConfiguration)) {
-                       if (isset($propertyMetaData['elementType'])) {
-                               if (isset($columnConfiguration['MM']) || isset($columnConfiguration['foreign_selector'])) {
-                                       $columnMap = $this->setManyToManyRelation($columnMap, $columnConfiguration);
-                               } else {
-                                       $columnMap = $this->setOneToManyRelation($columnMap, $columnConfiguration);
-                               }
+                       if (isset($columnConfiguration['MM']) || isset($columnConfiguration['foreign_selector'])) {
+                               $columnMap = $this->setManyToManyRelation($columnMap, $columnConfiguration);
+                       } elseif (isset($propertyMetaData['elementType'])) {
+                               $columnMap = $this->setOneToManyRelation($columnMap, $columnConfiguration);
+                       } elseif (isset($propertyMetaData['type']) && strpos($propertyMetaData['type'], '_') !== FALSE) {
+                               $columnMap = $this->setOneToOneRelation($columnMap, $columnConfiguration);
                        } else {
-                               if (isset($propertyMetaData['type']) && strpos($propertyMetaData['type'], '_') !== FALSE) {
-                                       $columnMap = $this->setOneToOneRelation($columnMap, $columnConfiguration);
-                               } else {
                                        $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_NONE);
-                               }
                        }
                } else {
                        $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_NONE);
index 0f8aab1..aef0994 100644 (file)
@@ -256,6 +256,7 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
                                        case 'SplObjectStorage':
                                        case 'Tx_Extbase_Persistence_ObjectStorage':
                                                $propertyValue = $this->mapResultToPropertyValue($object, $propertyName, $this->fetchRelated($object, $propertyName, $row[$columnName]));
+                                               $propertyValue->_memorizeCleanState();
                                        break;
                                        default:
                                                if (($propertyData['type'] === 'DateTime') || in_array('DateTime', class_parents($propertyData['type']))) {
@@ -344,16 +345,17 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
        protected function getPreparedQuery(Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $propertyName, $fieldValue = '') {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                $queryFactory = t3lib_div::makeInstance('Tx_Extbase_Persistence_QueryFactory');
+               $type = $this->getType(get_class($parentObject), $propertyName);
                if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE) {
-                       $query = $queryFactory->create($this->getType(get_class($parentObject), $propertyName));
+                       $query = $queryFactory->create($type);
                } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
-                       $query = $queryFactory->create($this->getElementType(get_class($parentObject), $propertyName));
+                       $query = $queryFactory->create($type);
                        $query->getQuerySettings()->setRespectStoragePage(FALSE);
                        if ($columnMap->getChildSortByFieldName() !== NULL) {
                                $query->setOrderings(array($columnMap->getChildSortByFieldName() => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING));
                        }
                } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
-                       $query = $queryFactory->create($this->getElementType(get_class($parentObject), $propertyName));
+                       $query = $queryFactory->create($type);
                        $query->getQuerySettings()->setRespectStoragePage(FALSE);
                        $query->setSource($this->getSource($parentObject, $propertyName));
                        if ($columnMap->getChildSortByFieldName() !== NULL) {
@@ -407,7 +409,7 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
        protected function getSource(Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $propertyName) {
                $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                $left = $this->qomFactory->selector(NULL, $columnMap->getRelationTableName());
-               $childClassName = $this->getElementType(get_class($parentObject), $propertyName);
+               $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(
@@ -434,7 +436,7 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
                        $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
                        $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
                        if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'SplObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'))) {
-                               $elementType = $this->getElementType(get_class($parentObject), $propertyName);
+                               $elementType = $this->getType(get_class($parentObject), $propertyName);
                                $objects = array();
                                foreach ($result as $value) {
                                        $objects[] = $value;
@@ -544,7 +546,9 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
         */
        public function getType($parentClassName, $propertyName) {
                $propertyMetaData = $this->reflectionService->getClassSchema($parentClassName)->getProperty($propertyName);
-               if (!empty($propertyMetaData['type'])) {
+               if (!empty($propertyMetaData['elementType'])) {
+                       $type = $propertyMetaData['elementType'];
+               } elseif (!empty($propertyMetaData['type'])) {
                        $type = $propertyMetaData['type'];
                } else {
                        throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('Could not determine the child object type.', 1251315967);
@@ -552,22 +556,5 @@ class Tx_Extbase_Persistence_Mapper_DataMapper implements t3lib_Singleton {
                return $type;
        }
 
-       /**
-        * Returns the type of the elements inside an ObjectStorage or array.
-        *
-        * @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
-        * @return string The class name of the elements inside an ObjectStorage
-        */
-       public function getElementType($parentClassName, $propertyName) {
-               $propertyMetaData = $this->reflectionService->getClassSchema($parentClassName)->getProperty($propertyName);
-               if (!empty($propertyMetaData['elementType'])) {
-                       $elementType = $propertyMetaData['elementType'];
-               } else {
-                       throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('Could not determine the type of the contained objects.', 1251315966);
-               }
-               return $elementType;            
-       }
-
 }
 ?>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Classes/Persistence/ObjectMonitoringInterface.php b/typo3/sysext/extbase/Classes/Persistence/ObjectMonitoringInterface.php
new file mode 100644 (file)
index 0000000..9320216
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
+*  All rights reserved
+*
+*  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 how to monitor changes on an object and its properties. All domain objects which should be persisted need to implement the below interface.
+ *
+ * @see Tx_Extbase_DomainObject_AbstractEntity
+ * @see Tx_Extbase_DomainObject_AbstractValueObject
+ *
+ * @package Extbase
+ * @subpackage Persistence
+ * @version $ID:$
+ */
+interface Tx_Extbase_Persistence_ObjectMonitoringInterface {
+
+       /**
+        * Register an object's clean state, e.g. after it has been reconstituted
+        * from the database
+        *
+        * @return void
+        */
+       public function _memorizeCleanState();
+
+       /**
+        * Returns TRUE if the properties were modified after reconstitution
+        *
+        * @return boolean
+        */
+       public function _isDirty();
+       
+}
+?>
\ No newline at end of file
index 4a9dfb6..4280a42 100644 (file)
@@ -32,7 +32,7 @@
  * @subpackage Persistence
  * @version $ID:$
  */
-class Tx_Extbase_Persistence_ObjectStorage implements Countable, Iterator, ArrayAccess {
+class Tx_Extbase_Persistence_ObjectStorage implements Countable, Iterator, ArrayAccess, Tx_Extbase_Persistence_ObjectMonitoringInterface {
 
        /**
         * An array holding the objects and the stored information. The key of the array items ist the 
@@ -51,6 +51,12 @@ class Tx_Extbase_Persistence_ObjectStorage implements Countable, Iterator, Array
        protected $storage = array();
 
        /**
+        * A flag indication if the object storage was modified after reconstitution (eg. by adding a new object)
+        * @var bool
+        */
+       protected $isModified = FALSE;
+               
+       /**
         * Rewind the iterator to the first storage element.
         *
         * @return void
@@ -114,6 +120,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Countable, Iterator, Array
         * @return void
         */
        public function offsetSet($object, $information) {
+               $this->isModified = TRUE;
                $this->storage[spl_object_hash($object)] = array('obj' => $object, 'inf' => $information);
        }
 
@@ -134,6 +141,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Countable, Iterator, Array
         * @return void
         */
        public function offsetUnset($object) {
+               $this->isModified = TRUE;
                unset($this->storage[spl_object_hash($object)]);
        }
 
@@ -189,6 +197,7 @@ class Tx_Extbase_Persistence_ObjectStorage implements Countable, Iterator, Array
        }
        
        public function setInfo($data) {
+               $this->isModified = TRUE;
                $key = key($this->storage);
                $this->storage[$key]['inf']  = $data;
        }
@@ -238,6 +247,25 @@ class Tx_Extbase_Persistence_ObjectStorage implements Countable, Iterator, Array
                throw new RuntimeException('A ObjectStorage instance cannot be unserialized.', 1267700870);
        }
        
+       /**
+        * Register an object's clean state, e.g. after it has been reconstituted
+        * from the database
+        *
+        * @return void
+        */
+       public function _memorizeCleanState() {
+               $this->isModified = FALSE;
+       }
+
+       /**
+        * Returns TRUE if the properties were modified after reconstitution
+        *
+        * @return boolean
+        */
+       public function _isDirty() {
+               return $this->isModified;
+       }
+       
 }
 
 ?>
\ No newline at end of file
index b07eca5..ec6c450 100644 (file)
@@ -92,10 +92,11 @@ class Tx_Extbase_Persistence_QOM_QueryObjectModelFactory implements Tx_Extbase_P
         * Sets a statement as constraint. This is not part of the JCR 2.0 Specification!
         *
         * @param string $statement The statement
-        * @param object $language The language of the statement. Must be a supported languanguage defined as Tx_Extbase_Persistence_QOM_QueryObjectModelInterface::JCR_* or Tx_Extbase_Persistence_QOM_QueryObjectModelInterface::TYPO3_* or 
+        * @param array $boundVariables An array of variables to bind to the statement
+        * @param object $language The language of the statement. Must be a supported languanguage defined as Tx_Extbase_Persistence_QOM_QueryObjectModelFactory::TYPO3_*
         * @return Tx_Extbase_Persistence_QOM_StatementInterface
         */
-       public function statement($statement, $boundVariables, $language) {
+       public function statement($statement, array $boundVariables = array(), $language = Tx_Extbase_Persistence_QOM_Statement::TYPO3_SQL_MYSQL) {
                return t3lib_div::makeInstance('Tx_Extbase_Persistence_QOM_Statement', $statement, $boundVariables, $language);
        }
 
index ce1b3c1..312ff07 100644 (file)
@@ -60,7 +60,7 @@ class Tx_Extbase_Persistence_QOM_Statement {
         *
         * @param string $statement The statement
         * @param array $boundVariables An array of variables to bind to the statement
-        * @param string $language 
+        * @param string $language The query language. One of the above constants.
         */
        public function __construct($statement, array $boundVariables = array(), $language = self::TYPO3_SQL_MYSQL) {
                $this->statement = $statement;
index 1a879dd..bea0a5a 100644 (file)
@@ -648,12 +648,12 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                                $onStatement .= ' OR ' . $tableName . '.' . $columnName . ' LIKE CONCAT(' . $childTableName . '.uid,\',%\'))';
                                $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $onStatement;
                        }
-                       $className = $this->dataMapper->getElementType($className, $propertyName);
+                       $className = $this->dataMapper->getType($className, $propertyName);
                } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
                        $relationTableName = $columnMap->getRelationTableName();
                        $sql['unions'][$relationTableName] = 'LEFT JOIN ' . $relationTableName . ' ON ' . $tableName . '.uid=' . $relationTableName . '.uid_local';
                        $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $relationTableName . '.uid_foreign=' . $childTableName . '.uid';
-                       $className = $this->dataMapper->getElementType($className, $propertyName);
+                       $className = $this->dataMapper->getType($className, $propertyName);
                } else {
                        throw new Tx_Extbase_Persistence_Exception('Could not determine type of relation.', 1252502725);
                }
index f43d2aa..b2ac697 100644 (file)
@@ -36,9 +36,8 @@ class Tx_Extbase_DomainObject_AbstractEntity_testcase extends Tx_Extbase_BaseTes
                $domainObject = new $domainObjectName();
                $domainObject->foo = 'Test';
                $domainObject->bar = 'It is raining outside';
+               $domainObject->_memorizeCleanState();
                
-               $domainObject->_memorizePropertyCleanState('foo');
-               $domainObject->_memorizePropertyCleanState('bar');
                $this->assertFalse($domainObject->_isDirty());
        }
 
@@ -55,9 +54,9 @@ class Tx_Extbase_DomainObject_AbstractEntity_testcase extends Tx_Extbase_BaseTes
                $domainObject->foo = 'Test';
                $domainObject->bar = 'It is raining outside';
 
-               $domainObject->_memorizePropertyCleanState('foo');
-               $domainObject->_memorizePropertyCleanState('bar');
+               $domainObject->_memorizeCleanState();
                $domainObject->bar = 'Now it is sunny.';
+
                $this->assertTrue($domainObject->_isDirty());
        }
 
@@ -73,9 +72,8 @@ class Tx_Extbase_DomainObject_AbstractEntity_testcase extends Tx_Extbase_BaseTes
                $domainObject = new $domainObjectName();
                $domainObject->foo = new DateTime();
                $domainObject->bar = 'It is raining outside';
+               $domainObject->_memorizeCleanState();
 
-               $domainObject->_memorizePropertyCleanState('foo');
-               $domainObject->_memorizePropertyCleanState('bar');
                $this->assertFalse($domainObject->_isDirty());
        }
 
@@ -94,13 +92,15 @@ class Tx_Extbase_DomainObject_AbstractEntity_testcase extends Tx_Extbase_BaseTes
                        public $foo;
                        public $bar;
                }');
+               $secondDomainObject = new $secondDomainObjectName;
+               $secondDomainObject->_memorizeCleanState();
+               
 
                $domainObject = new $domainObjectName();
-               $domainObject->foo = new $secondDomainObjectName;
+               $domainObject->foo = $secondDomainObject;
                $domainObject->bar = 'It is raining outside';
+               $domainObject->_memorizeCleanState();
 
-               $domainObject->_memorizePropertyCleanState('foo');
-               $domainObject->_memorizePropertyCleanState('bar');
                $this->assertFalse($domainObject->_isDirty());
        }
 }
index 8eef2af..27d9184 100644 (file)
@@ -299,10 +299,10 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder_testcase extends Tx_Extbase_BaseTest
        /**
         * @test
         */
-       public function buildFrontendUriStripsLeadingSlashesFromRelativeUris() {
+       public function buildFrontendUriDoesNotStripLeadingSlashesFromRelativeUris() {
                $this->contentObject->expects($this->once())->method('typoLink_URL')->will($this->returnValue('/relative/uri'));
 
-               $expectedResult = 'relative/uri';
+               $expectedResult = '/relative/uri';
                $actualResult = $this->uriBuilder->buildFrontendUri();
 
                $this->assertSame($expectedResult, $actualResult);
@@ -312,12 +312,14 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder_testcase extends Tx_Extbase_BaseTest
         * @test
         */
        public function buildFrontendUriCreatesAbsoluteUrisIfSpecified() {
-               $this->request->expects($this->any())->method('getBaseURI')->will($this->returnValue('http://baseuri/'));
-               $this->contentObject->expects($this->once())->method('typoLink_URL')->will($this->returnValue('relative/uri'));
-               $this->uriBuilder->setCreateAbsoluteUri(TRUE);
+               $uriBuilder = $this->getMock('Tx_Extbase_MVC_Web_Routing_UriBuilder', array('buildTypolinkConfiguration'), array($this->contentObject));
+               $uriBuilder->expects($this->once())->method('buildTypolinkConfiguration')->will($this->returnValue(array('foo' => 'bar')));
+
+               $this->contentObject->expects($this->once())->method('typoLink_URL')->with(array('foo' => 'bar', 'forceAbsoluteUrl' => TRUE))->will($this->returnValue('http://baseuri/relative/uri'));
+               $uriBuilder->setCreateAbsoluteUri(TRUE);
 
                $expectedResult = 'http://baseuri/relative/uri';
-               $actualResult = $this->uriBuilder->buildFrontendUri();
+               $actualResult = $uriBuilder->buildFrontendUri();
                $this->assertSame($expectedResult, $actualResult);
        }
 
index a3442c3..1308ff9 100644 (file)
@@ -53,6 +53,27 @@ class Tx_Extbase_Persistence_Mapper_DataMapFactory_testcase extends Tx_Extbase_B
        /**
         * @test
         */
+       public function setRelationsDetectsOneToOneRelationWithIntermediateTable() {
+               $mockColumnMap = $this->getMock('Tx_Extbase_Persistence_Mapper_ColumnMap', array(), array(), '', FALSE);
+           $columnConfiguration = array(
+                       'type' => 'select',
+                       'foreign_table' => 'tx_myextension_bar',
+                       'MM' => 'tx_myextension_mm'
+                       );
+               $propertyMetaData = array(
+                       'type' => 'Tx_Myext_Domain_Model_Foo',
+                       'elementType' => NULL
+                       );
+               $mockDataMapFactory = $this->getMock($this->buildAccessibleProxy('Tx_Extbase_Persistence_Mapper_DataMapFactory'), array('setOneToOneRelation', 'setOneToManyRelation', 'setManyToManyRelation'), array(), '', FALSE);
+               $mockDataMapFactory->expects($this->never())->method('setOneToOneRelation');
+               $mockDataMapFactory->expects($this->never())->method('setOneToManyRelation');
+               $mockDataMapFactory->expects($this->once())->method('setManyToManyRelation');
+               $mockDataMapFactory->_callRef('setRelations', $mockColumnMap, $columnConfiguration, $propertyMetaData);
+       }
+       
+       /**
+        * @test
+        */
        public function setRelationsDetectsOneToManyRelation() {
                $mockColumnMap = $this->getMock('Tx_Extbase_Persistence_Mapper_ColumnMap', array(), array(), '', FALSE);
            $columnConfiguration = array(
index 9a99fbb..e8d2032 100644 (file)
@@ -91,6 +91,7 @@ return array(
        'tx_extbase_persistence_lazyloadingproxy' => $extensionClassesPath . 'Persistence/LazyLoadingProxy.php',
        'tx_extbase_persistence_lazyobjectstorage' => $extensionClassesPath . 'Persistence/LazyObjectStorage.php',
        'tx_extbase_persistence_loadingstrategyinterface' => $extensionClassesPath . 'Persistence/LoadingStrategyInterface.php',
+       'tx_extbase_persistence_objectmonitoringinterface' => $extensionClassesPath . 'Persistence/ObjectMonitoringInterface.php',
        'tx_extbase_persistence_manager' => $extensionClassesPath . 'Persistence/Manager.php',
        'tx_extbase_persistence_managerinterface' => $extensionClassesPath . 'Persistence/ManagerInterface.php',
        'tx_extbase_persistence_objectstorage' => $extensionClassesPath . 'Persistence/ObjectStorage.php',