//$extutil = new Tx_Extbase_Utility_Extension;
//$extutil->createAutoloadRegistryForExtension('extbase', t3lib_extMgm::extPath('extbase'));
//$extutil->createAutoloadRegistryForExtension('fluid', t3lib_extMgm::extPath('fluid'));
-
+
+ $GLOBALS['TT']->push('Extbase is called.','');
+ $GLOBALS['TT']->push('Extbase gets initialized.','');
if (!is_array($configuration)) {
t3lib_div::sysLog('Extbase was not able to dispatch the request. No configuration.', 'extbase', t3lib_div::SYSLOG_SEVERITY_ERROR);
return $content;
$requestHashService->verifyRequest($request);
$persistenceManager = self::getPersistenceManager();
+ $GLOBALS['TT']->pull();
+ $GLOBALS['TT']->push('Extbase dispatches request.','');
$dispatchLoopCount = 0;
while (!$request->isDispatched()) {
if ($dispatchLoopCount++ > 99) throw new Tx_Extbase_MVC_Exception_InfiniteLoop('Could not ultimately dispatch the request after ' . $dispatchLoopCount . ' iterations.', 1217839467);
} catch (Tx_Extbase_MVC_Exception_StopAction $ignoredException) {
}
}
+ $GLOBALS['TT']->pull();
+ $GLOBALS['TT']->push('Extbase persists all changes.','');
$flashMessages = t3lib_div::makeInstance('Tx_Extbase_MVC_Controller_FlashMessages'); // singleton
- $flashMessages->persist();
-
+ $flashMessages->persist();
$persistenceManager->persistAll();
+ $GLOBALS['TT']->pull();
+
self::$reflectionService->shutdown();
if (count($response->getAdditionalHeaderData()) > 0) {
$GLOBALS['TSFE']->additionalHeaderData[$request->getControllerExtensionName()] = implode("\n", $response->getAdditionalHeaderData());
}
$response->sendHeaders();
+ $GLOBALS['TT']->pull();
return $response->getContent();
}
*/
public static function getPersistenceManager() {
if (self::$persistenceManager === NULL) {
+ $identityMap = t3lib_div::makeInstance('Tx_Extbase_Persistence_IdentityMap');
+
$dataMapper = t3lib_div::makeInstance('Tx_Extbase_Persistence_Mapper_DataMapper'); // singleton
+ $dataMapper->injectIdentityMap($identityMap);
$dataMapper->injectReflectionService(self::$reflectionService);
-
+
$storageBackend = t3lib_div::makeInstance('Tx_Extbase_Persistence_Storage_Typo3DbBackend', $GLOBALS['TYPO3_DB']); // singleton
$storageBackend->injectDataMapper($dataMapper);
$persistenceBackend = t3lib_div::makeInstance('Tx_Extbase_Persistence_Backend', $persistenceSession, $storageBackend); // singleton
$persistenceBackend->injectDataMapper($dataMapper);
- $persistenceBackend->injectIdentityMap(t3lib_div::makeInstance('Tx_Extbase_Persistence_IdentityMap'));
+ $persistenceBackend->injectIdentityMap($identityMap);
+ $persistenceBackend->injectReflectionService(self::$reflectionService);
$persistenceBackend->injectQueryFactory(t3lib_div::makeInstance('Tx_Extbase_Persistence_QueryFactory'));
$persistenceBackend->injectQOMFactory($qomFactory);
$persistenceBackend->injectValueFactory(t3lib_div::makeInstance('Tx_Extbase_Persistence_ValueFactory'));
* @return void
* @api
*/
- public function setLastLogin($lastLogin) {
+ public function setLastLogin(DateTime $lastLogin) {
$this->lastLogin = $lastLogin;
}
abstract class Tx_Extbase_DomainObject_AbstractDomainObject implements Tx_Extbase_DomainObject_DomainObjectInterface {
/**
- * @var string The uid
+ * @var int The uid
*/
protected $uid;
*/
public function _memorizeCleanState() {
}
-
- /**
- * Returns a hash map of dirty properties and $values. This is always the empty array for ValueObjects, because ValueObjects never change.
- *
- * @return array
- */
- public function _getDirtyProperties() {
- return array();
- }
-
+
/**
* Returns TRUE if the properties were modified after reconstitution. However, value objects can be never updated.
*
/**
* @var An array holding the clean property values. Set right after reconstitution of the object
*/
- private $_cleanProperties = NULL;
+ private $_cleanProperties = array();
/**
* Register an object's clean state, e.g. after it has been reconstituted
*/
public function _memorizePropertyCleanState($propertyName) {
$propertyValue = $this->$propertyName;
- if (!is_array($this->_cleanProperties)) {
- $this->_cleanProperties = array();
- }
if (is_object($propertyValue)) {
$this->_cleanProperties[$propertyName] = clone($propertyValue);
* @return array
*/
public function _getCleanProperties() {
- 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 calling _isDirty().', 1233309106);
return $this->_cleanProperties;
}
/**
- * Returns a hash map of dirty properties and $values
+ * Returns the clean value of the given property. The returned value will be NULL if the clean state was not memorized before, or
+ * if the clean value is NULL.
*
- * @return array
+ * @param string $propertyName The name of the property to be memorized. If omittet all persistable properties are memorized.
+ * @return mixed The clean property value or NULL
*/
- public function _getDirtyProperties() {
- 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);
- $dirtyProperties = array();
- 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) {
- $dirtyProperties[$propertyName] = $this->$propertyName;
- }
- } else {
- if ($this->$propertyName !== $propertyValue) {
- $dirtyProperties[$propertyName] = $this->$propertyName;
- }
- }
+ public function _getCleanProperty($propertyName) {
+ if (is_array($this->_cleanProperties)) {
+ return isset($this->_cleanProperties[$propertyName]) ? $this->_cleanProperties[$propertyName] : NULL;
+ } else {
+ return NULL;
}
- return $dirtyProperties;
}
-
+
/**
* Returns TRUE if the properties were modified after reconstitution
*
* @return boolean
*/
public function _isDirty($propertyName = NULL) {
- 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 (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);
$result = FALSE;
if ($propertyName !== NULL) {
*/
public function _getProperties();
- /**
- * Returns a hash map of dirty properties and $values
- *
- * @return boolean
- */
- public function _getDirtyProperties();
-
}
?>
\ No newline at end of file
**/
protected $identityMap;
+ /**
+ * @var Tx_Extbase_Reflection_Service
+ */
+ protected $reflectionService;
+
/**
* @var Tx_Extbase_Persistence_QueryFactoryInterface
*/
**/
protected $referenceIndex;
+ /**
+ * @var array
+ **/
+ protected $extbaseSettings;
+
/**
* Constructs the backend
*
public function __construct(Tx_Extbase_Persistence_Session $session, Tx_Extbase_Persistence_Storage_BackendInterface $storageBackend) {
$this->session = $session;
$this->storageBackend = $storageBackend;
- $this->referenceIndex = t3lib_div::makeInstance('t3lib_refindex');
+ $this->extbaseSettings = Tx_Extbase_Dispatcher::getExtbaseFrameworkConfiguration();
+ if ($this->extbaseSettings['persistence']['updateReferenceIndex'] === '1') {
+ $this->referenceIndex = t3lib_div::makeInstance('t3lib_refindex');
+ }
$this->aggregateRootObjects = new Tx_Extbase_Persistence_ObjectStorage();
}
$this->identityMap = $identityMap;
}
+ /**
+ * Injects the Reflection Service
+ *
+ * @param Tx_Extbase_Reflection_Service
+ * @return void
+ */
+ public function injectReflectionService(Tx_Extbase_Reflection_Service $reflectionService) {
+ $this->reflectionService = $reflectionService;
+ }
+
/**
* Injects the QueryFactory
*
* @return void
*/
protected function persistObjects() {
+ foreach ($this->aggregateRootObjects as $object) {
+ // if (!$this->identityMap->hasObject($object)) { // TODO Must be enabled to allow other identity properties than $uid
+ if ($object->_isNew()) {
+ $this->insertObject($object);
+ }
+ }
+
foreach ($this->aggregateRootObjects as $object) {
$this->persistObject($object);
}
* @param string $parentPropertyName The name of the property the object is stored in
* @return void
*/
- protected function persistObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, $parentObject = NULL, $parentPropertyName = NULL) {
+ protected function persistObject(Tx_Extbase_DomainObject_DomainObjectInterface $object) {
$row = array();
- $queuedObjects = array();
+ $queue = array();
$className = get_class($object);
$dataMap = $this->dataMapper->getDataMap($className);
-
- if ($object instanceof Tx_Extbase_DomainObject_AbstractValueObject) {
- $this->mapAlreadyPersistedValueObject($object);
- }
-
+ $classSchema = $this->reflectionService->getClassSchema($className);
+
$properties = $object->_getProperties();
- // Fill up $row[$columnName] array with changed values which need to be stored
foreach ($properties as $propertyName => $propertyValue) {
- if (!$dataMap->isPersistableProperty($propertyName) || ($propertyValue instanceof Tx_Extbase_Persistence_LazyLoadingProxy)) {
+ if (!$dataMap->isPersistableProperty($propertyName)) continue;
+ if (($propertyValue instanceof Tx_Extbase_Persistence_LazyLoadingProxy) || ((get_class($propertyValue) === 'Tx_Extbase_Persistence_LazyObjectStorage') && ($propertyValue->isInitialized() === FALSE))) {
continue;
}
$columnMap = $dataMap->getColumnMap($propertyName);
- if ($object->_isNew() || $object->_isDirty($propertyName)) {
- if ($columnMap->isRelation()) {
- $this->persistRelations($object, $propertyName, $propertyValue, $columnMap, $queuedObjects, $row);
+ $propertyMetaData = $classSchema->getProperty($propertyName);
+ $propertyType = $propertyMetaData['type'];
+ // FIXME enable property-type check
+ // $this->checkPropertyType($propertyType, $propertyValue);
+ if ($propertyType === 'Tx_Extbase_Persistence_ObjectStorage') {
+ if ($object->_isDirty($propertyName)) {
+ $row[$columnMap->getColumnName()] = $this->persistObjectStorage($propertyValue, $object, $propertyName, $queue);
} else {
- // We have not a relation, this means it is a scalar (like a string or interger value) or an object
+ foreach ($propertyValue as $containedObject) {
+ $queue[] = $containedObject;
+ }
+ }
+ } elseif ($propertyValue instanceof Tx_Extbase_DomainObject_DomainObjectInterface) {
+ if ($object->_isDirty($propertyName)) {
+ if ($propertyValue->_isNew()) {
+ if ($propertyValue instanceof Tx_Extbase_DomainObject_AbstractEntity) {
+ $this->insertObject($propertyValue, $object, $propertyName);
+ $queue[] = $propertyValue;
+ } else {
+ $this->persistValueObject($propertyValue, $object, $propertyName);
+ }
+ }
$row[$columnMap->getColumnName()] = $dataMap->convertPropertyValueToFieldValue($propertyValue);
}
+ } elseif ($object instanceof Tx_Extbase_DomainObject_AbstractValueObject || $object->_isNew() || $object->_isDirty($propertyName)) {
+ $row[$columnMap->getColumnName()] = $dataMap->convertPropertyValueToFieldValue($propertyValue);
}
- } // end property iteration for loop
-
- // The state of the Object has to be stored in a local variable because $object->_isNew() will return FALSE after
- // the object was inserted. We need the initial state here.
- $objectIsNew = $object->_isNew();
- if ($objectIsNew === TRUE) {
- $this->insertObject($object, $parentObject, $parentPropertyName, $row);
- } elseif ($object->_isDirty()) {
- $this->updateObject($object, $parentObject, $parentPropertyName, $row);
+ }
+
+ if (count($row) > 0) {
+ $this->updateObject($object, $row);
+ }
+
+ if ($object instanceof Tx_Extbase_DomainObject_AbstractEntity) {
+ $object->_memorizeCleanState();
}
- $objectHasToBeUpdated = $this->processQueuedChildObjects($object, $queuedObjects, $row);
- if ($objectHasToBeUpdated === TRUE) {
- // TODO Check if this can be merged with the first update
- $this->updateObject($object, $parentObject, $parentPropertyName, $row);
+ foreach ($queue as $object) {
+ $this->persistObject($object);
}
+
+ }
- // SK: I need to check the code below more thoroughly
- if ($parentObject instanceof Tx_Extbase_DomainObject_DomainObjectInterface && !empty($parentPropertyName)) {
- $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
- $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
- if (($parentColumnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY)) {
- $this->insertRelationInRelationtable($object, $parentObject, $parentPropertyName);
- }
+ /**
+ * Checks a value given against the expected type. If not matching, an
+ * UnexpectedTypeException is thrown. NULL is always considered valid.
+ *
+ * @param string $expectedType The expected type
+ * @param mixed $value The value to check
+ * @return void
+ * @throws Tx_Extbase_Persistence_Exception_UnexpectedType
+ */
+ protected function checkPropertyType($expectedType, $value) {
+ if ($value === NULL) {
+ return;
}
- // TODO: We should only register the object if it was really updated.
- $this->identityMap->registerObject($object, $object->getUid());
- $object->_memorizeCleanState();
+ if (is_object($value)) {
+ if (!($value instanceof $expectedType)) {
+ throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('Expected property of type ' . $expectedType . ', but got ' . get_class($value), 1244465558);
+ }
+ } elseif ($expectedType !== gettype($value)) {
+ throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('Expected property of type ' . $expectedType . ', but got ' . gettype($value), 1244465558);
+ }
}
+
+ /**
+ * Persists the given value object.
+ *
+ * @return void
+ */
+ protected function persistValueObject(Tx_Extbase_DomainObject_AbstractValueObject $object, Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $parentPropertyName, $sortingPosition = 1) {
+ $result = $this->getUidOfAlreadyPersistedValueObject($object);
+ if ($result !== FALSE) {
+ $object->_setProperty('uid', (int)$result);
+ if($this->dataMapper->getDataMap(get_class($parentObject))->getColumnMap($parentPropertyName)->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
+ $this->insertRelationInRelationtable($object, $parentObject, $parentPropertyName, $sortingPosition);
+ }
+ } else {
+ $row = array();
+ $className = get_class($object);
+ $dataMap = $this->dataMapper->getDataMap($className);
+ $classSchema = $this->reflectionService->getClassSchema($className);
+
+ $properties = $object->_getProperties();
+ foreach ($properties as $propertyName => $propertyValue) {
+ if (!$dataMap->isPersistableProperty($propertyName) || $this->isLazyValue($propertyValue)) {
+ continue;
+ }
+ $columnMap = $dataMap->getColumnMap($propertyName);
+ $propertyMetaData = $classSchema->getProperty($propertyName);
+ $propertyType = $propertyMetaData['type'];
+ // FIXME enable property-type check
+ // $this->checkPropertyType($propertyType, $propertyValue);
+ $row[$columnMap->getColumnName()] = $dataMap->convertPropertyValueToFieldValue($propertyValue);
+ }
+ $this->insertObject($object, $parentObject, $parentPropertyName, $sortingPosition, $row);
+ }
+ }
+
+ /**
+ * Tests, if the given Value Object already exists in the storage backend. If so, it maps the uid
+ * to the given object.
+ *
+ * @param Tx_Extbase_DomainObject_AbstractValueObject $object The object to be tested
+ */
+ protected function getUidOfAlreadyPersistedValueObject(Tx_Extbase_DomainObject_AbstractValueObject $object) {
+ return $this->storageBackend->getUidOfAlreadyPersistedValueObject($object);
+ }
+
/**
* Persists a relation. Objects of a 1:n or m:n relation are queued and processed with the parent object. A 1:1 relation
- * gets persisted immediately. Objects which were removed from the property were deleted immediately, too.
+ * gets persisted immediately. Objects which were removed from the property were detached from the parent object. They will not be
+ * deleted by default. You have to annotate the property with "@cascade remove" if you want them to be deleted as well.
*
* @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object
* @param string $propertyName The name of the property the related objects are stored in
- * @param mixed $propertyValue The property value (an array of Domain Objects, ObjectStorage holding Domain Objects or a Domain Object itself)
+ * @param mixed $propertyValue The property value
* @return void
*/
- protected function persistRelations(Tx_Extbase_DomainObject_DomainObjectInterface $object, $propertyName, $propertyValue, Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, &$queuedObjects, &$row) {
- $columnName = $columnMap->getColumnName();
- if (($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) || ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY)) {
- if (is_array($propertyValue) || $propertyValue instanceof ArrayAccess) {
- foreach ($propertyValue as $relatedObject) {
- $queuedObjects[$propertyName][] = $relatedObject;
- }
- foreach ($this->getRemovedChildObjects($object, $propertyName) as $removedObject) {
- // TODO The removed object should only be deleted automatically if it is not managed by a Repository
- if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
- $this->deleteObject($removedObject, $object, $propertyName);
- } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
- $this->deleteRelationFromRelationtable($removedObject, $object, $propertyName);
- }
- }
- $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
- if ($propertyValue->_isNew() || $propertyValue->_isDirty()) {
- $this->persistObject($propertyValue);
+ protected function persistObjectStorage(Tx_Extbase_Persistence_ObjectStorage $objectStorage, Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $propertyName, &$queue) {
+ $className = get_class($parentObject);
+ $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName);
+ $columnName = $columnMap->getColumnName();
+ $propertyMetaData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName);
+
+ foreach ($this->getRemovedChildObjects($parentObject, $propertyName) as $removedObject) {
+ if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY && $propertyMetaData['cascade'] === 'remove') {
+ $this->removeObject($removedObject);
+ } else {
+ $this->detachObjectFromParentObject($removedObject, $parentObject, $propertyName);
+ }
+ }
+
+ $childPidArray = array();
+ $sortingPosition = 1;
+ foreach ($objectStorage as $object) {
+ if ($object->_isNew()) {
+ if ($object instanceof Tx_Extbase_DomainObject_AbstractEntity) {
+ $this->insertObject($object, $parentObject, $propertyName, $sortingPosition);
+ $queue[] = $object;
+ } else {
+ $this->persistValueObject($object, $parentObject, $propertyName, $sortingPosition);
}
- $row[$columnName] = $propertyValue->getUid();
}
+ $childPidArray[] = $object->getUid(); // FIXME This won't work for partly loaded storages
+ $sortingPosition++;
+ }
+
+ if ($columnMap->getParentKeyFieldName() === NULL) {
+ $newParentPropertyValue = implode(',', $childPidArray);
+ } else {
+ $newParentPropertyValue = count($objectStorage); // TODO check for limited queries
+ }
+
+ return $newParentPropertyValue;
}
-
+
/**
* Returns the removed objects determined by a comparison of the clean property value
* with the actual property value.
*/
protected function getRemovedChildObjects(Tx_Extbase_DomainObject_AbstractEntity $object, $propertyName) {
$removedObjects = array();
- if (!$object->_isNew()) {
- $cleanProperties = $object->_getCleanProperties();
- $cleanPropertyValue = $cleanProperties[$propertyName];
- $propertyValue = $object->_getProperty($propertyName);
- if ($cleanPropertyValue instanceof Tx_Extbase_Persistence_ObjectStorage) {
- $cleanPropertyValue = $cleanPropertyValue->toArray();
- }
- if ($propertyValue instanceof Tx_Extbase_Persistence_ObjectStorage) {
- $propertyValue = $propertyValue->toArray();
- }
- foreach ($cleanPropertyValue as $item) {
- if (!in_array($item, $propertyValue)) {
- $removedObjects[] = $item;
- }
+ $cleanPropertyValue = $object->_getCleanProperty($propertyName);
+ $propertyValue = $object->_getProperty($propertyName);
+ if ($cleanPropertyValue instanceof Tx_Extbase_Persistence_ObjectStorage) {
+ $cleanPropertyValue = $cleanPropertyValue->toArray();
+ }
+ if ($propertyValue instanceof Tx_Extbase_Persistence_ObjectStorage) {
+ $propertyValue = $propertyValue->toArray();
+ }
+ foreach ($cleanPropertyValue as $hash => $item) {
+ if (!array_key_exists($hash, $propertyValue)) {
+ $removedObjects[] = $item;
}
}
return $removedObjects;
}
-
+
/**
- * This function processes the queued child objects to be persisted. The queue is build while looping over the
- * collection of Domain Objects stored in a object property.
+ * Updates the fields defining the relation between the object and the parent object.
*
- * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object holding the collection
- * @param array $queuedObjects The queued child objects
- * @param array $row The row to be inseted or updated in the database. Passed as reference.
- * @return boolean TRUE if the object holding the collection has to be updated; otherwise FALSE
+ * @param Tx_Extbase_DomainObject_DomainObjectInterface $object
+ * @param Tx_Extbase_DomainObject_AbstractEntity $parentObject
+ * @param string $parentPropertyName
+ * @return void
*/
- protected function processQueuedChildObjects(Tx_Extbase_DomainObject_DomainObjectInterface $object, array $queuedChildObjects, array &$row) {
- $objectHasToBeUpdated = FALSE;
- $className = get_class($object);
- $dataMap = $this->dataMapper->getDataMap($className);
- foreach ($queuedChildObjects as $propertyName => $childObjects) {
- $columnMap = $dataMap->getColumnMap($propertyName);
- $childPidArray = array();
- foreach($childObjects as $childObject) {
- $this->persistObject($childObject, $object, $propertyName);
- if ($childObject instanceof Tx_Extbase_DomainObject_DomainObjectInterface) {
- $childPidArray[] = (int)$childObject->getUid();
+ protected function detachObjectFromParentObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, Tx_Extbase_DomainObject_AbstractEntity $parentObject, $parentPropertyName) {
+ $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
+ $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
+ if ($parentColumnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
+ $row = array();
+ $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName();
+ if ($parentKeyFieldName !== NULL) {
+ $row[$parentKeyFieldName] = '';
+ $parentTableFieldName = $parentColumnMap->getParentTableFieldName();
+ if ($parentTableFieldName !== NULL) {
+ $row[$parentTableFieldName] = '';
}
}
- if ($columnMap->getParentKeyFieldName() === NULL) { // TRUE: We have to generate a comma separated list stored in the field
- if (count($childPidArray) > 0) {
- $row[$propertyName] = implode(',', $childPidArray);
- } else {
- $row[$propertyName] = NULL;
- }
- $objectHasToBeUpdated = TRUE;
+ if (count($row) > 0) {
+ $this->updateObject($object, $row);
}
- }
- return $objectHasToBeUpdated;
- }
-
- /**
- * Tests, if the given Value Object already exists in the storage backend. If so, it maps the uid
- * to the given object.
- *
- * @param Tx_Extbase_DomainObject_AbstractValueObject $object The object to be tested
- */
- protected function mapAlreadyPersistedValueObject(Tx_Extbase_DomainObject_AbstractValueObject $object) {
- $dataMap = $this->dataMapper->getDataMap(get_class($object));
- $properties = $object->_getProperties();
- $result = $this->storageBackend->hasValueObject($properties, $dataMap);
- if ($result !== FALSE) {
- $object->_setProperty('uid', $result);
- }
+ } elseif ($parentColumnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
+ $this->deleteRelationFromRelationtable($object, $parentObject, $parentPropertyName);
+ }
}
-
+
/**
* Inserts an object in the storage
*
* @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object to be insterted in the storage
- * @param Tx_Extbase_DomainObject_AbstractEntity|NULL $parentObject The parent object (if any)
- * @param string|NULL $parentPropertyName The name of the property
- * @param array $row The $row
+ * @param array $row The tuple to be inserted
+ * @param Tx_Extbase_DomainObject_AbstractEntity $parentObject The parent object (if any)
+ * @param string $parentPropertyName The name of the property
*/
- protected function insertObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, Tx_Extbase_DomainObject_AbstractEntity $parentObject = NULL, $parentPropertyName = NULL, array &$row) {
- $className = get_class($object);
- $dataMap = $this->dataMapper->getDataMap($className);
- $tableName = $dataMap->getTableName();
- $this->addCommonFieldsToRow($object, $parentObject, $parentPropertyName, $row);
- $uid = $this->storageBackend->addRow(
- $tableName,
- $row
- );
- $object->_setProperty('uid', $uid);
- $this->referenceIndex->updateRefIndexTable($tableName, $uid);
+ protected function insertObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, Tx_Extbase_DomainObject_AbstractEntity $parentObject = NULL, $propertyName = NULL, $sortingPosition = NULL, array $row = array()) {
+ $tableName = $this->dataMapper->getDataMap(get_class($object))->getTableName();
+ $this->addCommonFieldsToRow($object, $row);
+ if ($parentObject !== NULL) {
+ $parentColumnMap = $this->dataMapper->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
+ if ($parentColumnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY && $parentColumnMap->getParentKeyFieldName() !== NULL) {
+ $row[$parentColumnMap->getParentKeyFieldName()] = $parentObject->getUid();
+ }
+ }
+ if ($object->_isNew()) {
+ $uid = $this->storageBackend->addRow(
+ $tableName,
+ $row
+ );
+ $object->_setProperty('uid', (int)$uid);
+ }
+ if ($parentObject !== NULL) {
+ if($parentColumnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
+ $this->insertRelationInRelationtable($object, $parentObject, $propertyName, $sortingPosition);
+ }
+ }
+ if ($this->extbaseSettings['persistence']['updateReferenceIndex'] === '1') {
+ $this->referenceIndex->updateRefIndexTable($tableName, $uid);
+ }
+ $this->identityMap->registerObject($object, $uid);
}
-
+
/**
* Inserts mm-relation into a relation table
*
- * @param Tx_Extbase_DomainObject_DomainObjectInterface $relatedObject The related object
+ * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The related object
* @param Tx_Extbase_DomainObject_DomainObjectInterface $parentObject The parent object
- * @param string $parentPropertyName The name of the parent object's property where the related objects are stored in
+ * @param string $propertyName The name of the parent object's property where the related objects are stored in
* @return void
*/
- protected function insertRelationInRelationtable(Tx_Extbase_DomainObject_DomainObjectInterface $relatedObject, Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $parentPropertyName) {
+ protected function insertRelationInRelationtable(Tx_Extbase_DomainObject_DomainObjectInterface $object, Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $propertyName, $sortingPosition = NULL) {
$dataMap = $this->dataMapper->getDataMap(get_class($parentObject));
- $columnMap = $dataMap->getColumnMap($parentPropertyName);
+ $columnMap = $dataMap->getColumnMap($propertyName);
$row = array(
$columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(),
- $columnMap->getChildKeyFieldName() => (int)$relatedObject->getUid(),
- 'sorting' => 9999 // TODO sorting of mm table items
+ $columnMap->getChildKeyFieldName() => (int)$object->getUid(),
+ $columnMap->getChildSortByFieldName() => !is_null($sortingPosition) ? (int)$sortingPosition : 0
);
$relationTableName = $columnMap->getRelationTableName();
// FIXME Reenable support for tablenames
* @param string|NULL $parentPropertyName The name of the property
* @param array $row The $row
*/
- protected function updateObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, $parentObject = NULL, $parentPropertyName = NULL, array &$row) {
- $className = get_class($object);
- $dataMap = $this->dataMapper->getDataMap($className);
- $tableName = $dataMap->getTableName();
- $this->addCommonFieldsToRow($object, $parentObject, $parentPropertyName, $row);
+ protected function updateObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, array &$row) {
+ $tableName = $this->dataMapper->getDataMap(get_class($object))->getTableName();
+ $this->addCommonFieldsToRow($object, $row);
$uid = $object->getUid();
$row['uid'] = $uid;
$res = $this->storageBackend->updateRow(
$tableName,
$row
);
- $this->referenceIndex->updateRefIndexTable($tableName, $uid);
+ if ($this->extbaseSettings['persistence']['updateReferenceIndex'] === '1') {
+ $this->referenceIndex->updateRefIndexTable($tableName, $uid);
+ }
+ if ($object instanceof Tx_Extbase_DomainObject_AbstractEntity) {
+ $object->_memorizeCleanState();
+ }
return $res;
}
* @param array $properties The properties of the object
* @return array A single row to be inserted in the database
*/
- protected function addCommonFieldsToRow(Tx_Extbase_DomainObject_DomainObjectInterface $object, $parentObject = NULL, $parentPropertyName = NULL, array &$row) {
+ protected function addCommonFieldsToRow(Tx_Extbase_DomainObject_DomainObjectInterface $object, array &$row) {
$className = get_class($object);
$dataMap = $this->dataMapper->getDataMap($className);
if ($dataMap->hasCreationDateColumn() && $object->_isNew()) {
if ($dataMap->hasTimestampColumn()) {
$row[$dataMap->getTimestampColumnName()] = $GLOBALS['EXEC_TIME'];
}
-
if ($object->_isNew() && $dataMap->hasPidColumn() && !isset($row['pid'])) {
$row['pid'] = $this->determineStoragePageIdForNewRecord($object);
}
-
- if ($parentObject instanceof Tx_Extbase_DomainObject_DomainObjectInterface && !empty($parentPropertyName)) {
- $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject));
- $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName);
- // FIXME This is a hacky solution
- if ($parentColumnMap->getTypeOfRelation() !== Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
- $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName();
- if ($parentKeyFieldName !== NULL) {
- $row[$parentKeyFieldName] = $parentObject->getUid();
- }
- $parentTableFieldName = $parentColumnMap->getParentTableFieldName();
- if ($parentTableFieldName !== NULL) {
- $row[$parentTableFieldName] = $parentDataMap->getTableName();
- }
- }
- }
- }
-
- /**
- * Determine the storage page ID for a given NEW record
- *
- * This does the following:
- * - If there is a TypoScript configuration "classes.CLASSNAME.newRecordStoragePid", that is used to store new records.
- * - If there is no such TypoScript configuration, it uses the first value of The "storagePid" taken for reading records.
- *
- * @param Tx_Extbase_DomainObject_DomainObjectInterface $object
- * @return int the storage Page ID where the object should be stored
- */
- protected function determineStoragePageIdForNewRecord(Tx_Extbase_DomainObject_DomainObjectInterface $object) {
- $className = get_class($object);
- $extbaseSettings = Tx_Extbase_Dispatcher::getExtbaseFrameworkConfiguration();
-
- if (isset($extbaseSettings['persistence']['classes'][$className]) && !empty($extbaseSettings['persistence']['classes'][$className]['newRecordStoragePid'])) {
- return (int)$extbaseSettings['persistence']['classes'][$className]['newRecordStoragePid'];
- } else {
- $storagePidList = t3lib_div::intExplode(',', $extbaseSettings['persistence']['storagePid']);
- return (int) $storagePidList[0];
- }
}
/**
*/
protected function processDeletedObjects() {
foreach ($this->deletedObjects as $object) {
- $this->deleteObject($object);
+ $this->removeObject($object);
$this->identityMap->unregisterObject($object);
}
$this->deletedObjects = new Tx_Extbase_Persistence_ObjectStorage();
}
/**
- * Deletes an object, it's 1:n related objects, and the m:n relations in relation tables (but not the m:n related objects!)
+ * Deletes an object
*
* @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object to be insterted in the storage
* @param Tx_Extbase_DomainObject_AbstractEntity|NULL $parentObject The parent object (if any)
* @param bool $markAsDeleted Shold we only mark the row as deleted instead of deleting (TRUE by default)?
* @return void
*/
- protected function deleteObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, $parentObject = NULL, $parentPropertyName = NULL, $markAsDeleted = TRUE) {
- // TODO Implement recursive deletions
+ protected function removeObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, $markAsDeleted = TRUE) {
$dataMap = $this->dataMapper->getDataMap(get_class($object));
$tableName = $dataMap->getTableName();
if (($markAsDeleted === TRUE) && $dataMap->hasDeletedColumn()) {
array('uid' => $object->getUid())
);
}
- $this->referenceIndex->updateRefIndexTable($tableName, $uid);
+ $this->removeRelatedObjects($object);
+ if ($this->extbaseSettings['persistence']['updateReferenceIndex'] === '1') {
+ $this->referenceIndex->updateRefIndexTable($tableName, $object->getUid());
+ }
+ }
+
+ /**
+ * Remove related objects
+ *
+ * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object to scanned for related objects
+ * @return void
+ */
+ protected function removeRelatedObjects(Tx_Extbase_DomainObject_DomainObjectInterface $object) {
+ $className = get_class($object);
+ $dataMap = $this->dataMapper->getDataMap($className);
+ $classSchema = $this->reflectionService->getClassSchema($className);
+
+ $properties = $object->_getProperties();
+ foreach ($properties as $propertyName => $propertyValue) {
+ $columnMap = $dataMap->getColumnMap($propertyName);
+ $propertyMetaData = $classSchema->getProperty($propertyName);
+ if ($propertyMetaData['cascade'] === 'remove') {
+ if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
+ foreach ($propertyValue as $containedObject) {
+ $this->removeObject($containedObject);
+ }
+ } elseif ($propertyValue instanceof Tx_Extbase_DomainObject_DomainObjectInterface) {
+ $this->removeObject($propertyValue);
+ }
+ }
+ }
}
/**
$dataMap = $this->dataMapper->getDataMap($className);
return $dataMap->isPersistableProperty($propertyName);
}
+
+ /**
+ * Determine the storage page ID for a given NEW record
+ *
+ * This does the following:
+ * - If there is a TypoScript configuration "classes.CLASSNAME.newRecordStoragePid", that is used to store new records.
+ * - If there is no such TypoScript configuration, it uses the first value of The "storagePid" taken for reading records.
+ *
+ * @param Tx_Extbase_DomainObject_DomainObjectInterface $object
+ * @return int the storage Page ID where the object should be stored
+ */
+ protected function determineStoragePageIdForNewRecord(Tx_Extbase_DomainObject_DomainObjectInterface $object) {
+ $className = get_class($object);
+ $extbaseSettings = Tx_Extbase_Dispatcher::getExtbaseFrameworkConfiguration();
+
+ if (isset($extbaseSettings['persistence']['classes'][$className]) && !empty($extbaseSettings['persistence']['classes'][$className]['newRecordStoragePid'])) {
+ return (int)$extbaseSettings['persistence']['classes'][$className]['newRecordStoragePid'];
+ } else {
+ $storagePidList = t3lib_div::intExplode(',', $extbaseSettings['persistence']['storagePid']);
+ return (int) $storagePidList[0];
+ }
+ }
}
--- /dev/null
+<?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 "Unexpected Type" exception.
+ *
+ * @package Extbase
+ * @subpackage Persistence\Exception
+ * @version $ID:$
+ */
+class Tx_Extbase_Persistence_Exception_UnexpectedTypeException extends Tx_Extbase_Persistence_Exception {
+}
+
+?>
\ No newline at end of file
*/
class Tx_Extbase_Persistence_LazyLoadingProxy implements Iterator, Tx_Extbase_Persistence_LoadingStrategyInterface {
- /**
- * @var Tx_Extbase_Persistence_QueryFactoryInterface
- */
- protected $queryFactory;
-
/**
* The object this property is contained in.
*
*/
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');
+ public function __construct($parentObject, $propertyName, $fieldValue) {
$this->parentObject = $parentObject;
$this->propertyName = $propertyName;
$this->fieldValue = $fieldValue;
- $this->columnMap = $columnMap;
}
/**
// 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();
- $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);
+ $objects = $dataMapper->fetchRelated($this->parentObject, $this->propertyName, $this->fieldValue, FALSE);
+ $propertyValue = $dataMapper->mapResultToPropertyValue($this->parentObject, $this->propertyName, $objects);
+ $this->parentObject->_setProperty($this->propertyName, $propertyValue);
$this->parentObject->_memorizeCleanState($this->propertyName);
- return $realInstance;
+ return $propertyValue;
} else {
return $this->parentObject->_getProperty($this->propertyName);
}
*/
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;
+ protected $parentObject;
/**
* The name of the property represented by this proxy.
*
* @var string
*/
- private $propertyName;
+ protected $propertyName;
/**
* The raw field value.
*
* @var mixed
*/
- private $fieldValue;
+ protected $fieldValue;
/**
*
- * @var Tx_Extbase_Persistence_Mapper_ColumnMap
+ * @var bool
*/
- private $columnMap;
+ protected $isInitialized = FALSE;
/**
* 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');
+ public function __construct($parentObject, $propertyName, $fieldValue) {
$this->parentObject = $parentObject;
$this->propertyName = $propertyName;
$this->fieldValue = $fieldValue;
- $this->columnMap = $columnMap;
- $this->storage = NULL; // TODO
}
/**
* @return void
*/
protected function initializeStorage() {
- if (is_null($this->storage)) {
+ if (!$this->isInitialized) {
$dataMapper = Tx_Extbase_Dispatcher::getPersistenceManager()->getBackend()->getDataMapper();
- $objects = $dataMapper->fetchRelatedObjects($this->parentObject, $this->propertyName, $this->fieldValue, $this->columnMap);
+ $objects = $dataMapper->fetchRelated($this->parentObject, $this->propertyName, $this->fieldValue, FALSE);
$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
+ $this->isInitialized = TRUE;
}
}
* @return void
*/
public function count() {
+ $dataMapper = Tx_Extbase_Dispatcher::getPersistenceManager()->getBackend()->getDataMapper();
+ $columnMap = $dataMapper->getDataMap(get_class($this->parentObject))->getColumnMap($this->propertyName);
$numberOfElements = NULL;
- if ($this->columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
- $parentKeyFieldName = $this->columnMap->getParentKeyFieldName();
- if (!empty($parentKeyFieldName)) {
- $numberOfElements = $this->fieldValue; // The field value in TYPO3 normally contains the number of related elements
- } else {
- $this->initializeStorage();
- $numberOfElements = count($this->storage);
- // FIXME Count on comma separated lists does not respect hidden objects
- // 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;
+ if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
+ $parentKeyFieldName = $columnMap->getParentKeyFieldName();
+ $dataMapper = Tx_Extbase_Dispatcher::getPersistenceManager()->getBackend()->getDataMapper();
+ $numberOfElements = $dataMapper->countRelated($this->parentObject, $this->propertyName, $this->fieldValue);
} else {
$this->initializeStorage();
$numberOfElements = count($this->storage);
switch ($loadingStrategy) {
case self::STRATEGY_LAZY_PROXY;
case self::STRATEGY_LAZY_STORAGE;
+ case self::STRATEGY_EAGER;
$this->loadingStrategy = $loadingStrategy;
break;
- default:
- $this->loadingStrategy = self::STRATEGY_EAGER;
- break;
}
}
* This method tries to determine the type of type of relation to other tables and sets it based on
* the $TCA column configuration
*
- * @param string $columnMap The column map
+ * @param Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap The column map
* @param string $columnConfiguration The column configuration from $TCA
* @return void
*/
}
break;
case (Tx_Extbase_Persistence_PropertyType::REFERENCE):
- if (!is_null($row->getValue($columnName))) {
- $propertyValue = $this->mapRelatedObjects($object, $propertyName, $row, $columnMap);
- } else {
+ if (is_null($row->getValue($columnName))) {
$propertyValue = NULL;
+ } else {
+ $fieldValue = $row->getValue($columnMap->getColumnName());
+ $result = $this->fetchRelated($object, $propertyName, $fieldValue);
+ $propertyValue = $this->mapResultToPropertyValue($object, $propertyName, $result);
}
break;
- // FIXME we have an object to handle... -> exception
default:
- // SK: We should throw an exception as this point as there was an undefined propertyType we can not handle.
- if ($row->hasValue($columnName)) {
- $property = $row->getValue($columnName);
- if (is_object($property)) {
- $propertyValue = $this->mapObject($property);
- // SK: THIS case can not happen I think. At least $this->mapObject() is not available.
- } else {
- // SK: This case does not make sense either. $this-mapSingleRow has a different signature
- $propertyValue = $this->mapSingleRow($className, $property);
- }
- }
+ // FIXME throw exception
break;
}
-
$object->_setProperty($propertyName, $propertyValue);
}
}
/**
- * Maps related objects to an ObjectStorage
+ * Fetches a collection of objects related to a property of a parent object
*
- * @param object $parentObject The parent object for the mapping result
- * @param string $propertyName The target property name for the mapping result
- * @param Tx_Extbase_Persistence_RowInterface $row The actual database row
- * @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
+ * @param Tx_Extbase_DomainObject_AbstractEntity $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
+ * @return mixed The result
*/
- 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);
- $targetClassSchema = $this->reflectionService->getClassSchema(get_class($parentObject));
- $propertyMetaData = $targetClassSchema->getProperty($propertyName);
- $fieldValue = $row->getValue($columnMap->getColumnName());
- if ($columnMap->getLoadingStrategy() === Tx_Extbase_Persistence_Mapper_ColumnMap::STRATEGY_LAZY_PROXY) {
- $result = t3lib_div::makeInstance('Tx_Extbase_Persistence_LazyLoadingProxy', $parentObject, $propertyName, $fieldValue, $columnMap);
- } else {
- $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) || ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY)) {
- if ($propertyMetaData['lazy'] === TRUE || $columnMap->getLoadingStrategy() === Tx_Extbase_Persistence_Mapper_ColumnMap::STRATEGY_LAZY_STORAGE) {
- $result = new Tx_Extbase_Persistence_LazyObjectStorage($parentObject, $propertyName, $fieldValue, $columnMap);
- } else {
- $objects = $this->fetchRelatedObjects($parentObject, $propertyName, $fieldValue, $columnMap);
- if ($propertyMetaData['type'] === 'ArrayObject') {
- $result = new ArrayObject($objects);
- } elseif ($propertyMetaData['type'] === 'Tx_Extbase_Persistence_ObjectStorage' || $propertyMetaData['type'] === 'Tx_Extbase_Persistence_LazyObjectStorage') {
- $result = new Tx_Extbase_Persistence_ObjectStorage();
- foreach ($objects as $object) {
- $result->attach($object);
- }
- } else {
- $result = $objects;
- }
- }
+ public function fetchRelated(Tx_Extbase_DomainObject_AbstractEntity $parentObject, $propertyName, $fieldValue, $enableLazyLoading = TRUE) {
+ $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
+ $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
+ if ($enableLazyLoading === TRUE && ($propertyMetaData['lazy'] || ($columnMap->getLoadingStrategy() !== Tx_Extbase_Persistence_Mapper_ColumnMap::STRATEGY_EAGER))) {
+ if (($propertyMetaData['type'] === 'Tx_Extbase_Persistence_ObjectStorage') || ($columnMap->getLoadingStrategy() === Tx_Extbase_Persistence_Mapper_ColumnMap::STRATEGY_LAZY_STORAGE)) {
+ $result = t3lib_div::makeInstance('Tx_Extbase_Persistence_LazyObjectStorage', $parentObject, $propertyName, $fieldValue);
+ } else {
+ $result = t3lib_div::makeInstance('Tx_Extbase_Persistence_LazyLoadingProxy', $parentObject, $propertyName, $fieldValue);
}
+ } else {
+ $result = $this->fetchRelatedEager($parentObject, $propertyName, $fieldValue);
}
return $result;
}
-
+
/**
- * Fetches a collection of objects related to a property of a parent object
+ * Fetches the related objects from the storage backend.
*
* @param Tx_Extbase_DomainObject_AbstractEntity $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
- * @return Tx_Extbase_Persistence_ObjectStorage An Object Storage containing the related objects
+ * @return void
*/
- public function fetchRelatedObjects(Tx_Extbase_DomainObject_AbstractEntity $parentObject, $propertyName, $fieldValue, Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap) {
+ protected function fetchRelatedEager(Tx_Extbase_DomainObject_AbstractEntity $parentObject, $propertyName, $fieldValue) {
+ $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
+ return $query->execute();
+ }
+
+ /**
+ * Builds and returns the prepared query, ready to be executed.
+ *
+ * @param Tx_Extbase_DomainObject_AbstractEntity $parentObject
+ * @param string $propertyName
+ * @param string $fieldValue
+ * @return void
+ */
+ protected function getPreparedQuery(Tx_Extbase_DomainObject_AbstractEntity $parentObject, $propertyName, $fieldValue) {
+ $columnMap = $this->getDataMap(get_class($parentObject))->getColumnMap($propertyName);
$queryFactory = t3lib_div::makeInstance('Tx_Extbase_Persistence_QueryFactory');
- $objects = NULL;
- $childSortByFieldName = $columnMap->getChildSortByFieldName();
+ $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);
$parentKeyFieldName = $columnMap->getParentKeyFieldName();
- if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
- $query = $queryFactory->create($columnMap->getChildClassName());
+ $childSortByFieldName = $columnMap->getChildSortByFieldName();
+ if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE) {
+ $result = $query->matching($query->withUid(intval($fieldValue)));
+ } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
if (!empty($childSortByFieldName)) {
$query->setOrderings(array($childSortByFieldName => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING));
}
- $parentKeyFieldName = $columnMap->getParentKeyFieldName();
if (isset($parentKeyFieldName)) {
- $objects = $query->matching($query->equals($parentKeyFieldName, $parentObject->getUid()))->execute();
+ $result = $query->matching($query->equals($parentKeyFieldName, $parentObject->getUid()));
} else {
- $uidArray = t3lib_div::intExplode(',', $fieldValue);
- $objects = $query->matching($query->equals('uid', $uidArray))->execute();
+ $result = $query->matching($query->equals('uid', t3lib_div::intExplode(',', $fieldValue)));
}
} elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
$relationTableName = $columnMap->getRelationTableName();
Tx_Extbase_Persistence_QOM_QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_INNER,
$joinCondition
);
- $query = $queryFactory->create($columnMap->getChildClassName());
$query->setSource($source);
if (!empty($childSortByFieldName)) {
$query->setOrderings(array($childSortByFieldName => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING));
}
- // 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);
- $objects = $query->matching($query->equals($parentKeyFieldName, $parentObject->getUid()))->execute();
+ $result = $query->matching($query->equals($parentKeyFieldName, $parentObject->getUid()));
} else {
throw new Tx_Extbase_Persistence_Exception('Could not determine type of relation.', 1252502725);
}
- return $objects;
+ return $query;
+ }
+
+ /**
+ * Returns the given result as property value of the specified property type.
+ *
+ * @param mixed $result The result could be an object or an ObjectStorage
+ * @param array $propertyMetaData The property meta data
+ * @return void
+ */
+ public function mapResultToPropertyValue(Tx_Extbase_DomainObject_AbstractEntity $parentObject, $propertyName, $result) {
+ $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName);
+ if ($result instanceof Tx_Extbase_Persistence_LoadingStrategyInterface) {
+ $propertyValue = $result;
+ } else {
+ if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'Tx_Extbase_Persistence_ObjectStorage')) && strpos($propertyMetaData['elementType'], '_') !== FALSE) {
+ $objects = array();
+ foreach ($result as $value) {
+ $objects[] = $value;
+ }
+
+ if ($propertyMetaData['type'] === 'ArrayObject') {
+ $propertyValue = new ArrayObject($objects);
+ } elseif ($propertyMetaData['type'] === 'Tx_Extbase_Persistence_ObjectStorage') {
+ $propertyValue = new Tx_Extbase_Persistence_ObjectStorage();
+ foreach ($objects as $object) {
+ $propertyValue->attach($object);
+ }
+ } else {
+ $propertyValue = $objects;
+ }
+ } elseif (strpos($propertyMetaData['type'], '_') !== FALSE) {
+ $propertyValue = current($result);
+ }
+ }
+ return $propertyValue;
+ }
+
+ /**
+ * Counts the number of related objects assigned to a property of a parent object
+ *
+ * @param Tx_Extbase_DomainObject_AbstractEntity $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.
+ */
+ public function countRelated(Tx_Extbase_DomainObject_AbstractEntity $parentObject, $propertyName, $fieldValue) {
+ $query = $this->getPreparedQuery($parentObject, $propertyName, $fieldValue);
+ return $query->count();
}
/**
*/
protected $storage = array();
+ /**
+ *
+ * @var bool
+ */
+ protected $isInitialized = TRUE;
+
/**
* This is a template function to be overwritten by a concrete implementation. It enables you to implement
* a lazy load implementation.
protected function initializeStorage() {
}
+ /**
+ * Returns the state of the initialization
+ *
+ * @return void
+ */
+ public function isInitialized() {
+ return $this->isInitialized;
+ }
+
/**
* Resets the array pointer of the storage
*
*/
public function execute() {
$result = $this->getPreparedQueryObjectModel()->execute();
- return $this->dataMapper->map($this->className, $result->getRows());
+ if ($this->getQuerySettings()->getReturnRawQueryResult() === TRUE) {
+ return $result;
+ } else {
+ return $this->dataMapper->map($this->className, $result->getRows());
+ }
}
/**
*/
protected $pageSelectObject;
+ /**
+ * The TypoScript Configuration of the page
+ *
+ * @var array
+ */
+ protected $pageTSConfig;
+
+ /**
+ * Caches information about tables (esp. the existing column names)
+ *
+ * @var array
+ */
+ protected $tableInformationCache = array();
+
/**
* Constructs this Storage Backend instance
*
$sqlString = 'INSERT INTO ' . $tableName . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')';
$this->replacePlaceholders($sqlString, $parameters);
+ // debug($sqlString,2);
$this->databaseHandle->sql_query($sqlString);
$this->checkSqlErrors();
$uid = $this->databaseHandle->sql_insert_id();
if (!$isRelation) {
$this->clearPageCache($tableName, $uid);
}
- return $uid;
+ return (int)$uid;
}
/**
$sqlString = 'UPDATE ' . $tableName . ' SET ' . implode(', ', $fields) . ' WHERE uid=?';
$this->replacePlaceholders($sqlString, $parameters);
-
+ // debug($sqlString,2);
$returnValue = $this->databaseHandle->sql_query($sqlString);
$this->checkSqlErrors();
if (!$isRelation) {
return $returnValue;
}
+ /**
+ * Fetches row data from the database
+ *
+ * @param string $identifier The Identifier of the row to fetch
+ * @param Tx_Extbase_Persistence_Mapper_DataMap $dataMap The Data Map
+ * @return array|FALSE
+ */
+ public function getRowByIdentifier($identifier, Tx_Extbase_Persistence_Mapper_DataMap $dataMap) {
+ $tableName = $dataMap->getTableName();
+ $statement = 'SELECT * FROM ' . $tableName . ' WHERE uid=?';
+ $this->replacePlaceholders($statement, array($identifier));
+ // debug($statement,-2);
+ $res = $this->databaseHandle->sql_query($statement);
+ $this->checkSqlErrors();
+ $row = $this->databaseHandle->sql_fetch_assoc($res);
+ if ($row !== FALSE) {
+ return $row;
+ } else {
+ return FALSE;
+ }
+ }
+
/**
* Returns an array with tuples matching the query.
*
*/
public function countRows(Tx_Extbase_Persistence_QOM_QueryObjectModelInterface $query) {
$constraint = $query->getConstraint();
- if($constraint instanceof Tx_Extbase_Persistence_QOM_StatementInterface) throw new Tx_Extbase_Persistence_Storage_Exception_BadConstraint('Could not execute count on queries with aconstraint of type Tx_Extbase_Persistence_QOM_StatementInterface', 1256661045);
+ if($constraint instanceof Tx_Extbase_Persistence_QOM_StatementInterface) throw new Tx_Extbase_Persistence_Storage_Exception_BadConstraint('Could not execute count on queries with a constraint of type Tx_Extbase_Persistence_QOM_StatementInterface', 1256661045);
$parameters = array();
$statementParts = $this->parseQuery($query, $parameters);
$statementParts['fields'] = array('COUNT(*)');
/**
* Checks if a Value Object equal to the given Object exists in the data base
*
- * @param array $properties The properties of the Value Object
- * @param Tx_Extbase_Persistence_Mapper_DataMap $dataMap The Data Map
+ * @param Tx_Extbase_DomainObject_AbstractValueObject $object The Value Object
* @return array The matching uid
*/
- public function hasValueObject(array $properties, Tx_Extbase_Persistence_Mapper_DataMap $dataMap) {
+ public function getUidOfAlreadyPersistedValueObject(Tx_Extbase_DomainObject_AbstractValueObject $object) {
$fields = array();
$parameters = array();
+ $dataMap = $this->dataMapper->getDataMap(get_class($object));
+ $properties = $object->_getProperties();
foreach ($properties as $propertyName => $propertyValue) {
// FIXME We couple the Backend to the Entity implementation (uid, isClone); changes there breaks this method
if ($dataMap->isPersistableProperty($propertyName) && ($propertyName !== 'uid') && ($propertyName !== 'pid') && ($propertyName !== 'isClone')) {
$statement .= ' AND ' . implode(' AND ', $sql['additionalWhereClause']);
}
$this->replacePlaceholders($statement, $parameters);
+ // debug($statement,-2);
$res = $this->databaseHandle->sql_query($statement);
$this->checkSqlErrors();
$row = $this->databaseHandle->sql_fetch_assoc($res);
if ($row !== FALSE) {
- return $row['uid'];
+ return (int)$row['uid'];
} else {
return FALSE;
}
* @return string The query part with replaced placeholders
*/
protected function replacePlaceholders(&$sqlString, array $parameters) {
+ // TODO profile this method again
if (substr_count($sqlString, '?') !== count($parameters)) throw new Tx_Extbase_Persistence_Exception('The number of question marks to replace must be equal to the number of parameters.', 1242816074);
$offset = 0;
foreach ($parameters as $parameter) {
* @return void
*/
protected function addPageIdStatement($tableName, array &$sql) {
- $columns = $this->databaseHandle->admin_get_fields($tableName);
- if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('pid', $columns)) {
+ if (empty($this->tableInformationCache[$tableName]['columnNames'])) {
+ $this->tableInformationCache[$tableName]['columnNames'] = $this->databaseHandle->admin_get_fields($tableName);
+ }
+ if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('pid', $this->tableInformationCache[$tableName]['columnNames'])) {
$extbaseFrameworkConfiguration = Tx_Extbase_Dispatcher::getExtbaseFrameworkConfiguration();
$sql['additionalWhereClause'][] = $tableName . '.pid IN (' . implode(', ', t3lib_div::intExplode(',', $extbaseFrameworkConfiguration['persistence']['storagePid'])) . ')';
}
// if disabled, return
return;
}
-
+
$pageIdsToClear = array();
$storagePage = NULL;
$pageIdsToClear[] = $storagePage;
}
-
if ($storagePage === NULL) {
return;
}
- $pageTSConfig = t3lib_BEfunc::getPagesTSconfig($storagePage);
- if (isset($pageTSConfig['TCEMAIN.']['clearCacheCmd'])) {
- $clearCacheCommands = t3lib_div::trimExplode(',',strtolower($pageTSConfig['TCEMAIN.']['clearCacheCmd']),1);
+ if (empty($this->pageTSConfig)) {
+ $this->pageTSConfig = t3lib_BEfunc::getPagesTSconfig($storagePage);
+ }
+ if (isset($this->pageTSConfig['TCEMAIN.']['clearCacheCmd'])) {
+ $clearCacheCommands = t3lib_div::trimExplode(',',strtolower($this->pageTSConfig['TCEMAIN.']['clearCacheCmd']),1);
$clearCacheCommands = array_unique($clearCacheCommands);
foreach ($clearCacheCommands as $clearCacheCommand) {
if (t3lib_div::testInt($clearCacheCommand)) {
}
}
}
-
+
+ // TODO check if we can hand this over to the Dispatcher to clear the page only once
Tx_Extbase_Utility_Cache::clearPageCache($pageIdsToClear);
}
}
*/
protected $respectEnableFields = TRUE;
+ /**
+ * Flag if the the query result should be returned as raw QueryResult.
+ * @var boolean
+ */
+ protected $returnRawQueryResult = FALSE;
+
/**
* Sets the flag if the storage page should be respected for the query.
*
public function getRespectEnableFields() {
return $this->respectEnableFields;
}
+
+ /**
+ * Sets the state, if the QueryResult should be returned unmapped.
+ *
+ * @var boolean $returnRawQueryResult TRUE, if the QueryResult should be returned unmapped; otherwise FALSE.
+ * @return void
+ */
+ public function setReturnRawQueryResult($returnRawQueryResult) {
+ $this->returnRawQueryResult = $returnRawQueryResult;
+ }
+
+ /**
+ * Returns the state, if the QueryResult should be returned unmapped.
+ *
+ * @return boolean TRUE, if the QueryResult should be returned unmapped; otherwise FALSE.
+ */
+ public function getReturnRawQueryResult() {
+ return $this->returnRawQueryResult;
+ }
}
?>
\ No newline at end of file
*/
public function setRespectEnableFields($respectEnableFields);
+ /**
+ * Sets the state, if the QueryResult should be returned unmapped.
+ *
+ * @return boolean TRUE, if the QueryResult should be returned unmapped; otherwise FALSE.
+ */
+ public function setReturnRawQueryResult($returnRawQueryResult);
+
+ /**
+ * Returns the state, if the QueryResult should be returned unmapped.
+ *
+ * @return boolean TRUE, if the QueryResult should be returned unmapped; otherwise FALSE.
+ */
+ public function getReturnRawQueryResult();
+
}
?>
\ No newline at end of file
if ($targetClassSchema !== NULL && $targetClassSchema->hasProperty($propertyName)) {
$propertyMetaData = $targetClassSchema->getProperty($propertyName);
- if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'Tx_Extbase_Persistence_ObjectStorage', 'Tx_Extbase_Persistence_LazyObjectStorage')) && strpos($propertyMetaData['elementType'], '_') !== FALSE) {
+ if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'Tx_Extbase_Persistence_ObjectStorage')) && strpos($propertyMetaData['elementType'], '_') !== FALSE) {
$objects = array();
foreach ($propertyValue as $value) {
$objects[] = $this->transformToObject($value, $propertyMetaData['elementType'], $propertyName);
// make sure we hand out what is expected
if ($propertyMetaData['type'] === 'ArrayObject') {
$propertyValue = new ArrayObject($objects);
- } elseif ($propertyMetaData['type'] === 'Tx_Extbase_Persistence_ObjectStorage' || $propertyMetaData['type'] === 'Tx_Extbase_Persistence_LazyObjectStorage') {
+ } elseif ($propertyMetaData['type'] === 'Tx_Extbase_Persistence_ObjectStorage') {
$propertyValue = new Tx_Extbase_Persistence_ObjectStorage();
foreach ($objects as $object) {
$propertyValue->attach($object);
* @param string $name Name of the property
* @param string $type Type of the property (see ALLOWED_TYPES_PATTERN)
* @param boolean $lazy Whether the property should be lazy-loaded when reconstituting
+ * @param string $cascade Strategy to cascade the object graph.
* @return void
* @author Robert Lemke <robert@typo3.org>
* @author Karsten Dambekalns <karsten@typo3.org>
*/
- public function addProperty($name, $type, $lazy = FALSE) {
+ public function addProperty($name, $type, $lazy = FALSE, $cascade = '') {
$matches = array();
if (preg_match(self::ALLOWED_TYPES_PATTERN, $type, $matches)) {
$type = ($matches['type'] === 'int') ? 'integer' : $matches['type'];
$this->properties[$name] = array(
'type' => $type,
'elementType' => $elementType,
- 'lazy' => $lazy
+ 'lazy' => $lazy,
+ 'cascade' => $cascade
);
} else {
throw new Tx_Extbase_Reflection_Exception_InvalidPropertyType('Invalid property type encountered: ' . $type, 1220387528);
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function getProperty($propertyName) {
- return $this->properties[$propertyName];
+ return is_array($this->properties[$propertyName]) ? $this->properties[$propertyName] : array();
}
/**
* @param string $className Name of the class containing the property
* @param string $propertyName Name of the tagged property
* @param string $tag Tag to return the values of
- if (!isset($this->propertyTagsValues[$className])) return array();
* @return array An array of values or an empty array if the tag was not found
* @author Robert Lemke <robert@typo3.org>
* @api
foreach ($this->getClassPropertyNames($className) as $propertyName) {
if (!$this->isPropertyTaggedWith($className, $propertyName, 'transient') && $this->isPropertyTaggedWith($className, $propertyName, 'var')) {
- $classSchema->addProperty($propertyName, implode(' ', $this->getPropertyTagValues($className, $propertyName, 'var')), $this->isPropertyTaggedWith($className, $propertyName, 'lazy'));
+ $cascadeTagValues = $this->getPropertyTagValues($className, $propertyName, 'cascade');
+ $classSchema->addProperty($propertyName, implode(' ', $this->getPropertyTagValues($className, $propertyName, 'var')), $this->isPropertyTaggedWith($className, $propertyName, 'lazy'), $cascadeTagValues[0]);
}
if ($this->isPropertyTaggedWith($className, $propertyName, 'uuid')) {
$classSchema->setUUIDPropertyName($propertyName);
* Tries to load the reflection data from this service's cache.
*
* @return void
-
*/
protected function loadFromCache() {
$cacheKey = $this->getCacheKey();
* Exports the internal reflection data into the ReflectionData cache.
*
* @return void
-
*/
protected function saveToCache() {
if (!is_object($this->cache)) {
}
persistence {
storagePid =
- enableAutomaticCacheClearing = 1
classes {
}
}
$domainObject->_memorizePropertyCleanState('bar');
$domainObject->bar = 'Now it is sunny.';
$this->assertTrue($domainObject->_isDirty());
-
- // We can check here that _getDirtyProperties returns the correct values as well.
- $this->assertSame(array('bar' => 'Now it is sunny.'), $domainObject->_getDirtyProperties());
}
/**
$this->assertFalse($domainObject->_isDirty());
}
- /**
- * @test
- */
- public function getDirtyPropertiesReturnsNoPropertiesIfObjectWithObjectPropertiesIsClean() {
- $domainObjectName = uniqid('DomainObject_');
- eval('class ' . $domainObjectName . ' extends Tx_Extbase_DomainObject_AbstractEntity {
- public $foo;
- public $bar;
- }');
- $domainObject = new $domainObjectName();
- $domainObject->foo = new DateTime();
- $domainObject->bar = 'It is raining outside';
- $domainObject->_memorizePropertyCleanState('foo');
- $domainObject->_memorizePropertyCleanState('bar');
- $this->assertEquals(array(), $domainObject->_getDirtyProperties());
- }
-
/**
* @test
*/
public function _setProperty($propertyName, $propertyValue) {}
public function _getProperty($propertyName) {}
public function _getProperties() {}
- public function _getDirtyProperties() {}
public function getUid() { return 123; }
}');
}
config.tx_extbase {
persistence{
+ enableAutomaticCacheClearing = 1
+ updateReferenceIndex = 0
classes {
Tx_Extbase_Domain_Model_FrontendUser {
mapping {