|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de> 00006 * All rights reserved 00007 * 00008 * This class is a backport of the corresponding class of FLOW3. 00009 * All credits go to the v5 team. 00010 * 00011 * This script is part of the TYPO3 project. The TYPO3 project is 00012 * free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU General Public License as published by 00014 * the Free Software Foundation; either version 2 of the License, or 00015 * (at your option) any later version. 00016 * 00017 * The GNU General Public License can be found at 00018 * http://www.gnu.org/copyleft/gpl.html. 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00027 00028 /** 00029 * A persistence backend. This backend maps objects to the relational model of the storage backend. 00030 * It persists all added, removed and changed objects. 00031 * 00032 * @package Extbase 00033 * @subpackage Persistence 00034 * @version $Id: Backend.php 2292 2010-05-25 11:11:04Z jocrau $ 00035 */ 00036 class Tx_Extbase_Persistence_Backend implements Tx_Extbase_Persistence_BackendInterface, t3lib_Singleton { 00037 00038 /** 00039 * @var Tx_Extbase_Persistence_Session 00040 */ 00041 protected $session; 00042 00043 /** 00044 * @var Tx_Extbase_Persistence_ObjectStorage 00045 */ 00046 protected $aggregateRootObjects; 00047 00048 /** 00049 * @var Tx_Extbase_Persistence_ObjectStorage 00050 */ 00051 protected $visitedDuringPersistence; 00052 00053 /** 00054 * @var Tx_Extbase_Persistence_IdentityMap 00055 **/ 00056 protected $identityMap; 00057 00058 /** 00059 * @var Tx_Extbase_Reflection_Service 00060 */ 00061 protected $reflectionService; 00062 00063 /** 00064 * @var Tx_Extbase_Persistence_QueryFactoryInterface 00065 */ 00066 protected $queryFactory; 00067 00068 /** 00069 * @var Tx_Extbase_Persistence_QOM_QueryObjectModelFactory 00070 */ 00071 protected $qomFactory; 00072 00073 /** 00074 * @var Tx_Extbase_Persistence_Storage_BackendInterface 00075 */ 00076 protected $storageBackend; 00077 00078 /** 00079 * @var Tx_Extbase_Persistence_DataMapper 00080 */ 00081 protected $dataMapper; 00082 00083 /** 00084 * The TYPO3 reference index object 00085 * 00086 * @var t3lib_refindex 00087 **/ 00088 protected $referenceIndex; 00089 00090 /** 00091 * @var Tx_Extbase_Configuration_ConfigurationManagerInterface 00092 */ 00093 protected $configurationManager; 00094 00095 /** 00096 * Constructs the backend 00097 * 00098 * @return void 00099 */ 00100 public function __construct(Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager) { 00101 $this->configurationManager = $configurationManager; 00102 $frameworkConfiguration = $configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); 00103 if ($frameworkConfiguration['persistence']['updateReferenceIndex'] === '1') { 00104 $this->referenceIndex = t3lib_div::makeInstance('t3lib_refindex'); 00105 } 00106 } 00107 00108 /** 00109 * @param Tx_Extbase_Persistence_Session $session 00110 * @return void 00111 */ 00112 public function injectSession(Tx_Extbase_Persistence_Session $session) { 00113 $this->session = $session; 00114 } 00115 00116 /** 00117 * @param Tx_Extbase_Persistence_Storage_BackendInterface $storageBackend 00118 * @return void 00119 */ 00120 public function injectStorageBackend(Tx_Extbase_Persistence_Storage_BackendInterface $storageBackend) { 00121 $this->storageBackend = $storageBackend; 00122 } 00123 00124 /** 00125 * Injects the DataMapper to map nodes to objects 00126 * 00127 * @param Tx_Extbase_Persistence_Mapper_DataMapper $dataMapper 00128 * @return void 00129 */ 00130 public function injectDataMapper(Tx_Extbase_Persistence_Mapper_DataMapper $dataMapper) { 00131 $this->dataMapper = $dataMapper; 00132 } 00133 00134 /** 00135 * Injects the identity map 00136 * 00137 * @param Tx_Extbase_Persistence_IdentityMap $identityMap 00138 * @return void 00139 */ 00140 public function injectIdentityMap(Tx_Extbase_Persistence_IdentityMap $identityMap) { 00141 $this->identityMap = $identityMap; 00142 } 00143 00144 /** 00145 * Injects the Reflection Service 00146 * 00147 * @param Tx_Extbase_Reflection_Service 00148 * @return void 00149 */ 00150 public function injectReflectionService(Tx_Extbase_Reflection_Service $reflectionService) { 00151 $this->reflectionService = $reflectionService; 00152 } 00153 00154 /** 00155 * Injects the QueryFactory 00156 * 00157 * @param Tx_Extbase_Persistence_QueryFactoryInterface $queryFactory 00158 * @return void 00159 */ 00160 public function injectQueryFactory(Tx_Extbase_Persistence_QueryFactoryInterface $queryFactory) { 00161 $this->queryFactory = $queryFactory; 00162 } 00163 00164 /** 00165 * Injects the QueryObjectModelFactory 00166 * 00167 * @param Tx_Extbase_Persistence_QOM_QueryObjectModelFactory $qomFactory 00168 * @return void 00169 */ 00170 public function injectQomFactory(Tx_Extbase_Persistence_QOM_QueryObjectModelFactory $qomFactory) { 00171 $this->qomFactory = $qomFactory; 00172 } 00173 00174 /** 00175 * Returns the repository session 00176 * 00177 * @return Tx_Extbase_Persistence_Session 00178 */ 00179 public function getSession() { 00180 return $this->session; 00181 } 00182 00183 /** 00184 * Returns the Data Mapper 00185 * 00186 * @return Tx_Extbase_Persistence_Mapper_DataMapper 00187 */ 00188 public function getDataMapper() { 00189 return $this->dataMapper; 00190 } 00191 00192 /** 00193 * Returns the current QOM factory 00194 * 00195 * @return Tx_Extbase_Persistence_QOM_QueryObjectModelFactory 00196 */ 00197 public function getQomFactory() { 00198 return $this->qomFactory; 00199 } 00200 00201 /** 00202 * Returns the current identityMap 00203 * 00204 * @return Tx_Extbase_Persistence_IdentityMap 00205 */ 00206 public function getIdentityMap() { 00207 return $this->identityMap; 00208 } 00209 00210 /** 00211 * Returns the reflection service 00212 * 00213 * @return Tx_Extbase_Reflection_Service 00214 */ 00215 public function getReflectionService() { 00216 return $this->reflectionService; 00217 } 00218 00219 /** 00220 * Returns the number of records matching the query. 00221 * 00222 * @param Tx_Extbase_Persistence_QueryInterface $query 00223 * @return integer 00224 * @api 00225 */ 00226 public function getObjectCountByQuery(Tx_Extbase_Persistence_QueryInterface $query) { 00227 return $this->storageBackend->getObjectCountByQuery($query); 00228 } 00229 00230 /** 00231 * Returns the object data matching the $query. 00232 * 00233 * @param Tx_Extbase_Persistence_QueryInterface $query 00234 * @return array 00235 * @api 00236 */ 00237 public function getObjectDataByQuery(Tx_Extbase_Persistence_QueryInterface $query) { 00238 return $this->storageBackend->getObjectDataByQuery($query); 00239 } 00240 00241 /** 00242 * Returns the (internal) identifier for the object, if it is known to the 00243 * backend. Otherwise NULL is returned. 00244 * 00245 * @param object $object 00246 * @return string The identifier for the object if it is known, or NULL 00247 */ 00248 public function getIdentifierByObject($object) { 00249 if ($object instanceof Tx_Extbase_Persistence_LazyLoadingProxy) { 00250 $object = $object->_loadRealInstance(); 00251 if (!is_object($object)) { 00252 return NULL; 00253 } 00254 } 00255 if ($this->identityMap->hasObject($object)) { 00256 return $this->identityMap->getIdentifierByObject($object); 00257 } else { 00258 return NULL; 00259 } 00260 } 00261 00262 /** 00263 * Returns the object with the (internal) identifier, if it is known to the 00264 * backend. Otherwise NULL is returned. 00265 * 00266 * @param string $identifier 00267 * @param string $className 00268 * @return object The object for the identifier if it is known, or NULL 00269 */ 00270 public function getObjectByIdentifier($identifier, $className) { 00271 if ($this->identityMap->hasIdentifier($identifier, $className)) { 00272 return $this->identityMap->getObjectByIdentifier($identifier, $className); 00273 } else { 00274 $query = $this->queryFactory->create($className); 00275 return $query->matching( 00276 $query->withUid($identifier)) 00277 ->execute() 00278 ->getFirst(); 00279 } 00280 } 00281 00282 /** 00283 * Checks if the given object has ever been persisted. 00284 * 00285 * @param object $object The object to check 00286 * @return boolean TRUE if the object is new, FALSE if the object exists in the repository 00287 */ 00288 public function isNewObject($object) { 00289 return ($this->getIdentifierByObject($object) === NULL); 00290 } 00291 00292 /** 00293 * Replaces the given object by the second object. 00294 * 00295 * This method will unregister the existing object at the identity map and 00296 * register the new object instead. The existing object must therefore 00297 * already be registered at the identity map which is the case for all 00298 * reconstituted objects. 00299 * 00300 * The new object will be identified by the uid which formerly belonged 00301 * to the existing object. The existing object looses its uid. 00302 * 00303 * @param object $existingObject The existing object 00304 * @param object $newObject The new object 00305 * @return void 00306 */ 00307 public function replaceObject($existingObject, $newObject) { 00308 $existingUid = $this->getIdentifierByObject($existingObject); 00309 if ($existingUid === NULL) throw new Tx_Extbase_Persistence_Exception_UnknownObject('The given object is unknown to this persistence backend.', 1238070163); 00310 00311 $this->identityMap->unregisterObject($existingObject); 00312 $this->identityMap->registerObject($newObject, $existingUid); 00313 } 00314 00315 /** 00316 * Sets the aggregate root objects 00317 * 00318 * @param Tx_Extbase_Persistence_ObjectStorage $objects 00319 * @return void 00320 */ 00321 public function setAggregateRootObjects(Tx_Extbase_Persistence_ObjectStorage $objects) { 00322 $this->aggregateRootObjects = $objects; 00323 } 00324 00325 /** 00326 * Sets the deleted objects 00327 * 00328 * @param Tx_Extbase_Persistence_ObjectStorage $objects 00329 * @return void 00330 */ 00331 public function setDeletedObjects(Tx_Extbase_Persistence_ObjectStorage $objects) { 00332 $this->deletedObjects = $objects; 00333 } 00334 00335 /** 00336 * Commits the current persistence session. 00337 * 00338 * @return void 00339 */ 00340 public function commit() { 00341 $this->persistObjects(); 00342 $this->processDeletedObjects(); 00343 } 00344 00345 /** 00346 * Traverse and persist all aggregate roots and their object graph. 00347 * 00348 * @return void 00349 */ 00350 protected function persistObjects() { 00351 $this->visitedDuringPersistence = new Tx_Extbase_Persistence_ObjectStorage(); 00352 foreach ($this->aggregateRootObjects as $object) { 00353 if (!$this->identityMap->hasObject($object)) { 00354 $this->insertObject($object); 00355 } 00356 } 00357 foreach ($this->aggregateRootObjects as $object) { 00358 $this->persistObject($object); 00359 } 00360 } 00361 00362 /** 00363 * Persists the given object. 00364 * 00365 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object to be inserted 00366 * @return void 00367 */ 00368 protected function persistObject(Tx_Extbase_DomainObject_DomainObjectInterface $object) { 00369 if (isset($this->visitedDuringPersistence[$object])) { 00370 return; 00371 } 00372 $row = array(); 00373 $queue = array(); 00374 $dataMap = $this->dataMapper->getDataMap(get_class($object)); 00375 $properties = $object->_getProperties(); 00376 foreach ($properties as $propertyName => $propertyValue) { 00377 if (!$dataMap->isPersistableProperty($propertyName) || $this->propertyValueIsLazyLoaded($propertyValue)) continue; 00378 $columnMap = $dataMap->getColumnMap($propertyName); 00379 if ($propertyValue instanceof Tx_Extbase_Persistence_ObjectStorage) { 00380 if ($object->_isNew() || $propertyValue->_isDirty()) { 00381 $this->persistObjectStorage($propertyValue, $object, $propertyName, $row); 00382 } 00383 foreach ($propertyValue as $containedObject) { 00384 if ($containedObject instanceof Tx_Extbase_DomainObject_DomainObjectInterface) { 00385 $queue[] = $containedObject; 00386 } 00387 } 00388 } elseif ($propertyValue instanceof Tx_Extbase_DomainObject_DomainObjectInterface) { 00389 if ($object->_isDirty($propertyName)) { 00390 if ($propertyValue->_isNew()) { 00391 $this->insertObject($propertyValue); 00392 } 00393 $row[$columnMap->getColumnName()] = $this->getPlainValue($propertyValue); 00394 } 00395 $queue[] = $propertyValue; 00396 } elseif ($object->_isNew() || $object->_isDirty($propertyName)) { 00397 $row[$columnMap->getColumnName()] = $this->getPlainValue($propertyValue); 00398 } 00399 } 00400 if (count($row) > 0) { 00401 $this->updateObject($object, $row); 00402 $object->_memorizeCleanState(); 00403 } 00404 $this->visitedDuringPersistence[$object] = $object->getUid(); 00405 foreach ($queue as $queuedObject) { 00406 $this->persistObject($queuedObject); 00407 } 00408 } 00409 00410 /** 00411 * Checks, if the property value is lazy loaded and was not initialized 00412 * 00413 * @param mixed $propertyValue The property value 00414 * @return bool 00415 */ 00416 protected function propertyValueIsLazyLoaded($propertyValue) { 00417 if ($propertyValue instanceof Tx_Extbase_Persistence_LazyLoadingProxy) return TRUE; 00418 if ($propertyValue instanceof Tx_Extbase_Persistence_LazyObjectStorage) { 00419 if ($propertyValue->isInitialized() === FALSE) { 00420 return TRUE; 00421 } 00422 } 00423 return FALSE; 00424 } 00425 00426 /** 00427 * Persists a an object storage. Objects of a 1:n or m:n relation are queued and processed with the parent object. A 1:1 relation 00428 * gets persisted immediately. Objects which were removed from the property were detached from the parent object. They will not be 00429 * deleted by default. You have to annotate the property with "@cascade remove" if you want them to be deleted as well. 00430 * 00431 * @param Tx_Extbase_Persistence_ObjectStorage $objectStorage The object storage to be persisted. 00432 * @param Tx_Extbase_DomainObject_DomainObjectInterface $parentObject The parent object. One of the properties holds the object storage. 00433 * @param string $propertyName The name of the property holding the object storage. 00434 * @param array $row The row array of the parent object to be persisted. It's passed by reference and gets filled with either a comma separated list of uids (csv) or the number of contained objects. 00435 * @return void 00436 */ 00437 protected function persistObjectStorage(Tx_Extbase_Persistence_ObjectStorage $objectStorage, Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $propertyName, array &$row) { 00438 $className = get_class($parentObject); 00439 $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName); 00440 $columnName = $columnMap->getColumnName(); 00441 $propertyMetaData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName); 00442 00443 foreach ($this->getRemovedChildObjects($parentObject, $propertyName) as $removedObject) { 00444 if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY && $propertyMetaData['cascade'] === 'remove') { 00445 $this->removeObject($removedObject); 00446 } else { 00447 $this->detachObjectFromParentObject($removedObject, $parentObject, $propertyName); 00448 } 00449 } 00450 00451 if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { 00452 $this->deleteAllRelationsFromRelationtable($parentObject, $propertyName); 00453 } 00454 00455 $currentUids = array(); 00456 $sortingPosition = 1; 00457 foreach ($objectStorage as $object) { 00458 if ($object->_isNew()) { 00459 $this->insertObject($object); 00460 } 00461 $currentUids[] = $object->getUid(); 00462 $this->attachObjectToParentObject($object, $parentObject, $propertyName, $sortingPosition); 00463 $sortingPosition++; 00464 } 00465 00466 if ($columnMap->getParentKeyFieldName() === NULL) { 00467 $row[$columnMap->getColumnName()] = implode(',', $currentUids); 00468 } else { 00469 $row[$columnMap->getColumnName()] = $this->dataMapper->countRelated($parentObject, $propertyName); 00470 } 00471 } 00472 00473 /** 00474 * Returns the current field value of the given object property from the storage backend. 00475 * 00476 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object 00477 * @param string $propertyName The property name 00478 * @return mixed The field value 00479 */ 00480 protected function getCurrentFieldValue(Tx_Extbase_DomainObject_DomainObjectInterface $object, $propertyName) { 00481 $className = get_class($object); 00482 $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName); 00483 $query = $this->queryFactory->create($className); 00484 $query->getQuerySettings()->setReturnRawQueryResult(TRUE); 00485 $currentRow = $query->matching( 00486 $query->withUid($object->getUid())) 00487 ->execute() 00488 ->getFirst(); 00489 $fieldValue = $currentRow[$columnMap->getColumnName()]; 00490 return $fieldValue; 00491 } 00492 00493 /** 00494 * Returns the removed objects determined by a comparison of the clean property value 00495 * with the actual property value. 00496 * 00497 * @param Tx_Extbase_DomainObject_AbstractEntity $object The object 00498 * @param string $parentPropertyName The name of the property 00499 * @return array An array of removed objects 00500 */ 00501 protected function getRemovedChildObjects(Tx_Extbase_DomainObject_AbstractEntity $object, $propertyName) { 00502 $removedObjects = array(); 00503 $cleanPropertyValue = $object->_getCleanProperty($propertyName); 00504 if (is_array($cleanPropertyValue) || $cleanPropertyValue instanceof Iterator) { 00505 $propertyValue = $object->_getProperty($propertyName); 00506 foreach ($cleanPropertyValue as $containedObject) { 00507 if (!$propertyValue->contains($containedObject)) { 00508 $removedObjects[] = $containedObject; 00509 } 00510 } 00511 } 00512 return $removedObjects; 00513 } 00514 00515 /** 00516 * Updates the fields defining the relation between the object and the parent object. 00517 * 00518 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object 00519 * @param Tx_Extbase_DomainObject_AbstractEntity $parentObject 00520 * @param string $parentPropertyName 00521 * @return void 00522 */ 00523 protected function attachObjectToParentObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, Tx_Extbase_DomainObject_AbstractEntity $parentObject, $parentPropertyName, $sortingPosition = 0) { 00524 $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject)); 00525 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName); 00526 if ($parentColumnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) { 00527 $row = array(); 00528 $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName(); 00529 if ($parentKeyFieldName !== NULL) { 00530 $row[$parentKeyFieldName] = $parentObject->getUid(); 00531 $parentTableFieldName = $parentColumnMap->getParentTableFieldName(); 00532 if ($parentTableFieldName !== NULL) { 00533 $row[$parentTableFieldName] = $parentDataMap->getTableName(); 00534 } 00535 } 00536 $childSortByFieldName = $parentColumnMap->getChildSortByFieldName(); 00537 if (!empty($childSortByFieldName)) { 00538 $row[$childSortByFieldName] = $sortingPosition; 00539 } 00540 if (count($row) > 0) { 00541 $this->updateObject($object, $row); 00542 } 00543 } elseif ($parentColumnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { 00544 $this->insertRelationInRelationtable($object, $parentObject, $parentPropertyName, $sortingPosition); 00545 } 00546 } 00547 00548 /** 00549 * Updates the fields defining the relation between the object and the parent object. 00550 * 00551 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object 00552 * @param Tx_Extbase_DomainObject_AbstractEntity $parentObject 00553 * @param string $parentPropertyName 00554 * @return void 00555 */ 00556 protected function detachObjectFromParentObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, Tx_Extbase_DomainObject_AbstractEntity $parentObject, $parentPropertyName) { 00557 $parentDataMap = $this->dataMapper->getDataMap(get_class($parentObject)); 00558 $parentColumnMap = $parentDataMap->getColumnMap($parentPropertyName); 00559 if ($parentColumnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) { 00560 $row = array(); 00561 $parentKeyFieldName = $parentColumnMap->getParentKeyFieldName(); 00562 if ($parentKeyFieldName !== NULL) { 00563 $row[$parentKeyFieldName] = ''; 00564 $parentTableFieldName = $parentColumnMap->getParentTableFieldName(); 00565 if ($parentTableFieldName !== NULL) { 00566 $row[$parentTableFieldName] = ''; 00567 } 00568 } 00569 $childSortByFieldName = $parentColumnMap->getChildSortByFieldName(); 00570 if (!empty($childSortByFieldName)) { 00571 $row[$childSortByFieldName] = 0; 00572 } 00573 if (count($row) > 0) { 00574 $this->updateObject($object, $row); 00575 } 00576 } elseif ($parentColumnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { 00577 $this->deleteRelationFromRelationtable($object, $parentObject, $parentPropertyName); 00578 } 00579 } 00580 00581 /** 00582 * Inserts an object in the storage backend 00583 * 00584 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object to be insterted in the storage 00585 * @return void 00586 */ 00587 protected function insertObject(Tx_Extbase_DomainObject_DomainObjectInterface $object) { 00588 if ($object instanceof Tx_Extbase_DomainObject_AbstractValueObject) { 00589 $result = $this->getUidOfAlreadyPersistedValueObject($object); 00590 if ($result !== FALSE) { 00591 $object->_setProperty('uid', (int)$result); 00592 return; 00593 } 00594 } 00595 00596 $dataMap = $this->dataMapper->getDataMap(get_class($object)); 00597 $row = array(); 00598 $this->addCommonFieldsToRow($object, $row); 00599 if($dataMap->getLanguageIdColumnName() !== NULL) { 00600 $row[$dataMap->getLanguageIdColumnName()] = -1; 00601 } 00602 $uid = $this->storageBackend->addRow( 00603 $dataMap->getTableName(), 00604 $row 00605 ); 00606 $object->_setProperty('uid', (int)$uid); 00607 $frameworkConfiguration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); 00608 if ($frameworkConfiguration['persistence']['updateReferenceIndex'] === '1') { 00609 $this->referenceIndex->updateRefIndexTable($dataMap->getTableName(), $uid); 00610 } 00611 $this->identityMap->registerObject($object, $uid); 00612 } 00613 00614 /** 00615 * Tests, if the given Value Object already exists in the storage backend and if so, it returns the uid. 00616 * 00617 * @param Tx_Extbase_DomainObject_AbstractValueObject $object The object to be tested 00618 */ 00619 protected function getUidOfAlreadyPersistedValueObject(Tx_Extbase_DomainObject_AbstractValueObject $object) { 00620 return $this->storageBackend->getUidOfAlreadyPersistedValueObject($object); 00621 } 00622 00623 /** 00624 * Inserts mm-relation into a relation table 00625 * 00626 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The related object 00627 * @param Tx_Extbase_DomainObject_DomainObjectInterface $parentObject The parent object 00628 * @param string $propertyName The name of the parent object's property where the related objects are stored in 00629 * @return void 00630 */ 00631 protected function insertRelationInRelationtable(Tx_Extbase_DomainObject_DomainObjectInterface $object, Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $propertyName, $sortingPosition = NULL) { 00632 $dataMap = $this->dataMapper->getDataMap(get_class($parentObject)); 00633 $columnMap = $dataMap->getColumnMap($propertyName); 00634 $row = array( 00635 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(), 00636 $columnMap->getChildKeyFieldName() => (int)$object->getUid(), 00637 $columnMap->getChildSortByFieldName() => !is_null($sortingPosition) ? (int)$sortingPosition : 0 00638 ); 00639 $relationTableName = $columnMap->getRelationTableName(); 00640 // FIXME Reenable support for tablenames 00641 // $childTableName = $columnMap->getChildTableName(); 00642 // if (isset($childTableName)) { 00643 // $row['tablenames'] = $childTableName; 00644 // } 00645 if ($columnMap->getRelationTablePageIdColumnName() !== NULL) { 00646 $row[$columnMap->getRelationTablePageIdColumnName()] = $this->determineStoragePageIdForNewRecord(); 00647 } 00648 00649 $relationTableInsertFields = $columnMap->getRelationTableInsertFields(); 00650 if (count($relationTableInsertFields)) { 00651 foreach($relationTableInsertFields as $insertField => $insertValue) { 00652 $row[$insertField] = $insertValue; 00653 } 00654 } 00655 00656 $res = $this->storageBackend->addRow( 00657 $relationTableName, 00658 $row, 00659 TRUE); 00660 return $res; 00661 } 00662 00663 /** 00664 * Delete all mm-relations of a parent from a relation table 00665 * 00666 * @param Tx_Extbase_DomainObject_DomainObjectInterface $parentObject The parent object 00667 * @param string $parentPropertyName The name of the parent object's property where the related objects are stored in 00668 * @return void 00669 */ 00670 protected function deleteAllRelationsFromRelationtable(Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $parentPropertyName) { 00671 $dataMap = $this->dataMapper->getDataMap(get_class($parentObject)); 00672 $columnMap = $dataMap->getColumnMap($parentPropertyName); 00673 $relationTableName = $columnMap->getRelationTableName(); 00674 00675 $relationMatchFields = array( 00676 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid() 00677 ); 00678 00679 $relationTableMatchFields = $columnMap->getRelationTableMatchFields(); 00680 if (is_array($relationTableMatchFields) && count($relationTableMatchFields) > 0) { 00681 $relationMatchFields = array_merge($relationTableMatchFields,$relationMatchFields); 00682 } 00683 00684 $res = $this->storageBackend->removeRow( 00685 $relationTableName, 00686 $relationMatchFields, 00687 FALSE); 00688 return $res; 00689 } 00690 00691 /** 00692 * Delete an mm-relation from a relation table 00693 * 00694 * @param Tx_Extbase_DomainObject_DomainObjectInterface $relatedObject The related object 00695 * @param Tx_Extbase_DomainObject_DomainObjectInterface $parentObject The parent object 00696 * @param string $parentPropertyName The name of the parent object's property where the related objects are stored in 00697 * @return void 00698 */ 00699 protected function deleteRelationFromRelationtable(Tx_Extbase_DomainObject_DomainObjectInterface $relatedObject, Tx_Extbase_DomainObject_DomainObjectInterface $parentObject, $parentPropertyName) { 00700 $dataMap = $this->dataMapper->getDataMap(get_class($parentObject)); 00701 $columnMap = $dataMap->getColumnMap($parentPropertyName); 00702 $relationTableName = $columnMap->getRelationTableName(); 00703 $res = $this->storageBackend->removeRow( 00704 $relationTableName, 00705 array( 00706 $columnMap->getParentKeyFieldName() => (int)$parentObject->getUid(), 00707 $columnMap->getChildKeyFieldName() => (int)$relatedObject->getUid(), 00708 ), 00709 FALSE); 00710 return $res; 00711 } 00712 00713 /** 00714 * Updates a given object in the storage 00715 * 00716 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object to be insterted in the storage 00717 * @param Tx_Extbase_DomainObject_AbstractEntity|NULL $parentObject The parent object (if any) 00718 * @param string|NULL $parentPropertyName The name of the property 00719 * @param array $row The $row 00720 */ 00721 protected function updateObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, array $row) { 00722 $dataMap = $this->dataMapper->getDataMap(get_class($object)); 00723 $this->addCommonFieldsToRow($object, $row); 00724 $row['uid'] = $object->getUid(); 00725 if($dataMap->getLanguageIdColumnName() !== NULL) { 00726 $row[$dataMap->getLanguageIdColumnName()] = $object->_getProperty('_languageUid'); 00727 if ($object->_getProperty('_localizedUid') !== NULL) { 00728 $row['uid'] = $object->_getProperty('_localizedUid'); 00729 } 00730 } 00731 $res = $this->storageBackend->updateRow( 00732 $dataMap->getTableName(), 00733 $row 00734 ); 00735 $frameworkConfiguration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); 00736 if ($frameworkConfiguration['persistence']['updateReferenceIndex'] === '1') { 00737 $this->referenceIndex->updateRefIndexTable($dataMap->getTableName(), $row['uid']); 00738 } 00739 return $res; 00740 } 00741 00742 /** 00743 * Returns a table row to be inserted or updated in the database 00744 * 00745 * @param Tx_Extbase_Persistence_Mapper_DataMap $dataMap The appropriate data map representing a database table 00746 * @param array $properties The properties of the object 00747 * @return array A single row to be inserted in the database 00748 */ 00749 protected function addCommonFieldsToRow(Tx_Extbase_DomainObject_DomainObjectInterface $object, array &$row) { 00750 $className = get_class($object); 00751 $dataMap = $this->dataMapper->getDataMap($className); 00752 if ($object->_isNew() && ($dataMap->getCreationDateColumnName() !== NULL)) { 00753 $row[$dataMap->getCreationDateColumnName()] = $GLOBALS['EXEC_TIME']; 00754 } 00755 if ($dataMap->getModificationDateColumnName() !== NULL) { 00756 $row[$dataMap->getModificationDateColumnName()] = $GLOBALS['EXEC_TIME']; 00757 } 00758 if ($dataMap->getRecordTypeColumnName() !== NULL && $dataMap->getRecordType() !== NULL) { 00759 $row[$dataMap->getRecordTypeColumnName()] = $dataMap->getRecordType(); 00760 } 00761 if ($object->_isNew() && !isset($row['pid'])) { 00762 $row['pid'] = $this->determineStoragePageIdForNewRecord($object); 00763 } 00764 } 00765 00766 /** 00767 * Iterate over deleted aggregate root objects and process them 00768 * 00769 * @return void 00770 */ 00771 protected function processDeletedObjects() { 00772 foreach ($this->deletedObjects as $object) { 00773 $this->removeObject($object); 00774 $this->identityMap->unregisterObject($object); 00775 } 00776 $this->deletedObjects = new Tx_Extbase_Persistence_ObjectStorage(); 00777 } 00778 00779 /** 00780 * Deletes an object 00781 * 00782 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object to be insterted in the storage 00783 * @param Tx_Extbase_DomainObject_AbstractEntity|NULL $parentObject The parent object (if any) 00784 * @param string|NULL $parentPropertyName The name of the property 00785 * @param bool $markAsDeleted Shold we only mark the row as deleted instead of deleting (TRUE by default)? 00786 * @return void 00787 */ 00788 protected function removeObject(Tx_Extbase_DomainObject_DomainObjectInterface $object, $markAsDeleted = TRUE) { 00789 $dataMap = $this->dataMapper->getDataMap(get_class($object)); 00790 $tableName = $dataMap->getTableName(); 00791 if (($markAsDeleted === TRUE) && ($dataMap->getDeletedFlagColumnName() !== NULL)) { 00792 $deletedColumnName = $dataMap->getDeletedFlagColumnName(); 00793 $res = $this->storageBackend->updateRow( 00794 $tableName, 00795 array( 00796 'uid' => $object->getUid(), 00797 $deletedColumnName => 1 00798 ) 00799 ); 00800 } else { 00801 $res = $this->storageBackend->removeRow( 00802 $tableName, 00803 array('uid' => $object->getUid()) 00804 ); 00805 } 00806 $this->removeRelatedObjects($object); 00807 $frameworkConfiguration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); 00808 if ($frameworkConfiguration['persistence']['updateReferenceIndex'] === '1') { 00809 $this->referenceIndex->updateRefIndexTable($tableName, $object->getUid()); 00810 } 00811 } 00812 00813 /** 00814 * Remove related objects 00815 * 00816 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object to scanned for related objects 00817 * @return void 00818 */ 00819 protected function removeRelatedObjects(Tx_Extbase_DomainObject_DomainObjectInterface $object) { 00820 $className = get_class($object); 00821 $dataMap = $this->dataMapper->getDataMap($className); 00822 $classSchema = $this->reflectionService->getClassSchema($className); 00823 00824 $properties = $object->_getProperties(); 00825 foreach ($properties as $propertyName => $propertyValue) { 00826 $columnMap = $dataMap->getColumnMap($propertyName); 00827 $propertyMetaData = $classSchema->getProperty($propertyName); 00828 if ($propertyMetaData['cascade'] === 'remove') { 00829 if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) { 00830 foreach ($propertyValue as $containedObject) { 00831 $this->removeObject($containedObject); 00832 } 00833 } elseif ($propertyValue instanceof Tx_Extbase_DomainObject_DomainObjectInterface) { 00834 $this->removeObject($propertyValue); 00835 } 00836 } 00837 } 00838 } 00839 00840 /** 00841 * Determine the storage page ID for a given NEW record 00842 * 00843 * This does the following: 00844 * - If there is a TypoScript configuration "classes.CLASSNAME.newRecordStoragePid", that is used to store new records. 00845 * - If there is no such TypoScript configuration, it uses the first value of The "storagePid" taken for reading records. 00846 * 00847 * @param Tx_Extbase_DomainObject_DomainObjectInterface $object 00848 * @return int the storage Page ID where the object should be stored 00849 */ 00850 protected function determineStoragePageIdForNewRecord(Tx_Extbase_DomainObject_DomainObjectInterface $object = NULL) { 00851 $frameworkConfiguration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); 00852 if ($object !== NULL) { 00853 $className = get_class($object); 00854 if (isset($frameworkConfiguration['persistence']['classes'][$className]) && !empty($frameworkConfiguration['persistence']['classes'][$className]['newRecordStoragePid'])) { 00855 return (int)$frameworkConfiguration['persistence']['classes'][$className]['newRecordStoragePid']; 00856 } 00857 } 00858 $storagePidList = t3lib_div::intExplode(',', $frameworkConfiguration['persistence']['storagePid']); 00859 return (int) $storagePidList[0]; 00860 } 00861 00862 /** 00863 * Returns a plain value, i.e. objects are flattened out if possible. 00864 * 00865 * @param mixed $input 00866 * @return mixed 00867 */ 00868 protected function getPlainValue($input) { 00869 if ($input instanceof DateTime) { 00870 return $input->format('U'); 00871 } elseif ($input instanceof Tx_Extbase_DomainObject_DomainObjectInterface) { 00872 return $input->getUid(); 00873 } elseif (is_bool($input)) { 00874 return $input === TRUE ? 1 : 0; 00875 } else { 00876 return $input; 00877 } 00878 } 00879 00880 } 00881 00882 ?>
1.8.0