TYPO3 API  SVNRelease
Repository.php
Go to the documentation of this file.
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  * The base repository - will usually be extended by a more concrete repository.
00030  *
00031  * @package Extbase
00032  * @subpackage Persistence
00033  * @version $ID:$
00034  * @api
00035  */
00036 class Tx_Extbase_Persistence_Repository implements Tx_Extbase_Persistence_RepositoryInterface, t3lib_Singleton {
00037 
00038     /**
00039      * @var Tx_Extbase_Persistence_IdentityMap
00040      **/
00041     protected $identityMap;
00042 
00043     /**
00044      * Objects of this repository
00045      *
00046      * @var Tx_Extbase_Persistence_ObjectStorage
00047      */
00048     protected $addedObjects;
00049 
00050     /**
00051      * Objects removed but not found in $this->addedObjects at removal time
00052      *
00053      * @var Tx_Extbase_Persistence_ObjectStorage
00054      */
00055     protected $removedObjects;
00056 
00057     /**
00058      * @var Tx_Extbase_Persistence_QueryFactoryInterface
00059      */
00060     protected $queryFactory;
00061 
00062     /**
00063      * @var Tx_Extbase_Persistence_ManagerInterface
00064      */
00065     protected $persistenceManager;
00066 
00067     /**
00068      * @var Tx_Extbase_Object_ObjectManagerInterface
00069      */
00070     protected $objectManager;
00071 
00072     /**
00073      * @var string
00074      */
00075     protected $objectType;
00076 
00077     /**
00078      * @var array
00079      */
00080     protected $defaultOrderings = array();
00081 
00082     /**
00083      * @var Tx_Extbase_Persistence_QuerySettingsInterface
00084      */
00085     protected $defaultQuerySettings = NULL;
00086 
00087     /**
00088      * Constructs a new Repository
00089      *
00090      * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
00091      */
00092     public function __construct(Tx_Extbase_Object_ObjectManagerInterface $objectManager = NULL) {
00093         $this->addedObjects = new Tx_Extbase_Persistence_ObjectStorage();
00094         $this->removedObjects = new Tx_Extbase_Persistence_ObjectStorage();
00095         $this->objectType = str_replace(array('_Repository_', 'Repository'), array('_Model_', ''), $this->getRepositoryClassName());
00096 
00097         if ($objectManager === NULL) {
00098             // Legacy creation, in case the object manager is NOT injected
00099             // If ObjectManager IS there, then all properties are automatically injected
00100             $this->objectManager = t3lib_div::makeInstance('Tx_Extbase_Object_ObjectManager');
00101             $this->injectIdentityMap($this->objectManager->get('Tx_Extbase_Persistence_IdentityMap'));
00102             $this->injectQueryFactory($this->objectManager->get('Tx_Extbase_Persistence_QueryFactory'));
00103             $this->injectPersistenceManager($this->objectManager->get('Tx_Extbase_Persistence_Manager'));
00104         } else {
00105             $this->objectManager = $objectManager;
00106         }
00107     }
00108 
00109     /**
00110      * @param Tx_Extbase_Persistence_IdentityMap $identityMap
00111      * @return void
00112      */
00113     public function injectIdentityMap(Tx_Extbase_Persistence_IdentityMap $identityMap) {
00114         $this->identityMap = $identityMap;
00115     }
00116 
00117     /**
00118      * @param Tx_Extbase_Persistence_QueryFactory $queryFactory
00119      * @return void
00120      */
00121     public function injectQueryFactory(Tx_Extbase_Persistence_QueryFactory $queryFactory) {
00122         $this->queryFactory = $queryFactory;
00123     }
00124 
00125     /**
00126      * @param Tx_Extbase_Persistence_ManagerInterface $persistenceManager
00127      * @return void
00128      */
00129     public function injectPersistenceManager(Tx_Extbase_Persistence_ManagerInterface $persistenceManager) {
00130         $this->persistenceManager = $persistenceManager;
00131         $this->persistenceManager->registerRepositoryClassName($this->getRepositoryClassName());
00132     }
00133 
00134     /**
00135      * Adds an object to this repository
00136      *
00137      * @param object $object The object to add
00138      * @return void
00139      * @api
00140      */
00141     public function add($object) {
00142         if (!($object instanceof $this->objectType)) {
00143             throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The object given to add() was not of the type (' . $this->objectType . ') this repository manages.', 1248363335);
00144         }
00145 
00146         $this->addedObjects->attach($object);
00147 
00148         if ($this->removedObjects->contains($object)) {
00149             $this->removedObjects->detach($object);
00150         }
00151     }
00152 
00153     /**
00154      * Removes an object from this repository.
00155      *
00156      * @param object $object The object to remove
00157      * @return void
00158      * @api
00159      */
00160     public function remove($object) {
00161         if (!($object instanceof $this->objectType)) {
00162             throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The object given to remove() was not of the type (' . $this->objectType . ') this repository manages.', 1248363335);
00163         }
00164 
00165         if ($this->addedObjects->contains($object)) {
00166             $this->addedObjects->detach($object);
00167         }
00168 
00169         if (!$object->_isNew()) {
00170             $this->removedObjects->attach($object);
00171         }
00172     }
00173 
00174     /**
00175      * Replaces an object by another.
00176      *
00177      * @param object $existingObject The existing object
00178      * @param object $newObject The new object
00179      * @return void
00180      * @api
00181      */
00182     public function replace($existingObject, $newObject) {
00183         if (!($existingObject instanceof $this->objectType)) {
00184             throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The existing object given to replace was not of the type (' . $this->objectType . ') this repository manages.', 1248363434);
00185         }
00186         if (!($newObject instanceof $this->objectType)) {
00187             throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The new object given to replace was not of the type (' . $this->objectType . ') this repository manages.', 1248363439);
00188         }
00189 
00190         $backend = $this->persistenceManager->getBackend();
00191         $session = $this->persistenceManager->getSession();
00192         $uuid = $backend->getIdentifierByObject($existingObject);
00193         if ($uuid !== NULL) {
00194             $backend->replaceObject($existingObject, $newObject);
00195             $session->unregisterReconstitutedObject($existingObject);
00196             $session->registerReconstitutedObject($newObject);
00197 
00198             if ($this->removedObjects->contains($existingObject)) {
00199                 $this->removedObjects->detach($existingObject);
00200                 $this->removedObjects->attach($newObject);
00201             }
00202         } elseif ($this->addedObjects->contains($existingObject)) {
00203             $this->addedObjects->detach($existingObject);
00204             $this->addedObjects->attach($newObject);
00205         } else {
00206             throw new Tx_Extbase_Persistence_Exception_UnknownObject('The "existing object" is unknown to the persistence backend.', 1238068475);
00207         }
00208 
00209     }
00210 
00211     /**
00212      * Replaces an existing object with the same identifier by the given object
00213      *
00214      * @param object $modifiedObject The modified object
00215      * @api
00216      */
00217     public function update($modifiedObject) {
00218         if (!($modifiedObject instanceof $this->objectType)) {
00219             throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The modified object given to update() was not of the type (' . $this->objectType . ') this repository manages.', 1249479625);
00220         }
00221 
00222         $uid = $modifiedObject->getUid();
00223         if ($uid !== NULL) {
00224             $existingObject = $this->findByUid($uid);
00225             $this->replace($existingObject, $modifiedObject);
00226         } else {
00227             throw new Tx_Extbase_Persistence_Exception_UnknownObject('The "modified object" is does not have an existing counterpart in this repository.', 1249479819);
00228         }
00229     }
00230 
00231     /**
00232      * Returns all addedObjects that have been added to this repository with add().
00233      *
00234      * This is a service method for the persistence manager to get all addedObjects
00235      * added to the repository. Those are only objects *added*, not objects
00236      * fetched from the underlying storage.
00237      *
00238      * @return Tx_Extbase_Persistence_ObjectStorage the objects
00239      */
00240     public function getAddedObjects() {
00241         return $this->addedObjects;
00242     }
00243 
00244     /**
00245      * Returns an Tx_Extbase_Persistence_ObjectStorage with objects remove()d from the repository
00246      * that had been persisted to the storage layer before.
00247      *
00248      * @return Tx_Extbase_Persistence_ObjectStorage the objects
00249      */
00250     public function getRemovedObjects() {
00251         return $this->removedObjects;
00252     }
00253 
00254     /**
00255      * Returns all objects of this repository
00256      *
00257      * @return array An array of objects, empty if no objects found
00258      * @api
00259      */
00260     public function findAll() {
00261         $result = $this->createQuery()->execute();
00262         return $result;
00263     }
00264 
00265     /**
00266      * Returns the total number objects of this repository.
00267      *
00268      * @return integer The object count
00269      * @api
00270      */
00271     public function countAll() {
00272         return $this->createQuery()->execute()->count();
00273     }
00274 
00275     /**
00276      * Removes all objects of this repository as if remove() was called for
00277      * all of them.
00278      *
00279      * @return void
00280      * @api
00281      */
00282     public function removeAll() {
00283         $this->addedObjects = new Tx_Extbase_Persistence_ObjectStorage();
00284         foreach ($this->findAll() as $object) {
00285             $this->remove($object);
00286         }
00287     }
00288 
00289     /**
00290      * Finds an object matching the given identifier.
00291      *
00292      * @param int $uid The identifier of the object to find
00293      * @return object The matching object if found, otherwise NULL
00294      * @api
00295      */
00296     public function findByUid($uid) {
00297         if ($this->identityMap->hasIdentifier($uid, $this->objectType)) {
00298             $object = $this->identityMap->getObjectByIdentifier($uid, $this->objectType);
00299         } else {
00300             $query = $this->createQuery();
00301             $query->getQuerySettings()->setRespectSysLanguage(FALSE);
00302             $query->getQuerySettings()->setRespectStoragePage(FALSE);
00303             $object = $query
00304                     ->matching(
00305                         $query->equals('uid', $uid)
00306                     )
00307                     ->execute()
00308                     ->getFirst();
00309             if ($object !== NULL) {
00310                 $this->identityMap->registerObject($object, $uid);
00311             }
00312         }
00313         return $object;
00314     }
00315 
00316     /**
00317      * Sets the property names to order the result by per default.
00318      * Expected like this:
00319      * array(
00320      *  'foo' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING,
00321      *  'bar' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING
00322      * )
00323      *
00324      * @param array $defaultOrderings The property names to order by
00325      * @return void
00326      * @api
00327      */
00328     public function setDefaultOrderings(array $defaultOrderings) {
00329         $this->defaultOrderings = $defaultOrderings;
00330     }
00331 
00332     /**
00333      * Sets the default query settings to be used in this repository
00334      *
00335      * @param Tx_Extbase_Persistence_QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
00336      * @return void
00337      * @api
00338      */
00339     public function setDefaultQuerySettings(Tx_Extbase_Persistence_QuerySettingsInterface $defaultQuerySettings) {
00340         $this->defaultQuerySettings = $defaultQuerySettings;
00341     }
00342 
00343     /**
00344      * Returns a query for objects of this repository
00345      *
00346      * @return Tx_Extbase_Persistence_QueryInterface
00347      * @api
00348      */
00349     public function createQuery() {
00350         $query = $this->queryFactory->create($this->objectType);
00351         if ($this->defaultOrderings !== array()) {
00352             $query->setOrderings($this->defaultOrderings);
00353         }
00354         if ($this->defaultQuerySettings !== NULL) {
00355             $query->setQuerySettings($this->defaultQuerySettings);
00356         }
00357         return $query;
00358     }
00359 
00360     /**
00361      * Dispatches magic methods (findBy[Property]())
00362      *
00363      * @param string $methodName The name of the magic method
00364      * @param string $arguments The arguments of the magic method
00365      * @throws Tx_Extbase_Persistence_Exception_UnsupportedMethod
00366      * @return void
00367      * @api
00368      */
00369     public function __call($methodName, $arguments) {
00370         if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
00371             $propertyName = strtolower(substr(substr($methodName, 6), 0, 1) ) . substr(substr($methodName, 6), 1);
00372             $query = $this->createQuery();
00373             $result = $query->matching($query->equals($propertyName, $arguments[0]))
00374                 ->execute();
00375             return $result;
00376         } elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
00377             $propertyName = strtolower(substr(substr($methodName, 9), 0, 1) ) . substr(substr($methodName, 9), 1);
00378             $query = $this->createQuery();
00379             $object = $query->matching($query->equals($propertyName, $arguments[0]))
00380                 ->setLimit(1)
00381                 ->execute()
00382                 ->getFirst();
00383             return $object;
00384         } elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
00385             $propertyName = strtolower(substr(substr($methodName, 7), 0, 1) ) . substr(substr($methodName, 7), 1);
00386             $query = $this->createQuery();
00387             $result = $query->matching($query->equals($propertyName, $arguments[0]))
00388                 ->execute()
00389                 ->count();
00390             return $result;
00391         }
00392         throw new Tx_Extbase_Persistence_Exception_UnsupportedMethod('The method "' . $methodName . '" is not supported by the repository.', 1233180480);
00393     }
00394 
00395     /**
00396      * Returns the class name of this class.
00397      *
00398      * @return string Class name of the repository.
00399      */
00400     protected function getRepositoryClassName() {
00401         return get_class($this);
00402     }
00403 
00404 }
00405 ?>