2 namespace TYPO3\CMS\Extbase\Persistence
;
4 /***************************************************************
7 * This class is a backport of the corresponding class of TYPO3 Flow.
8 * All credits go to the TYPO3 Flow team.
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
31 * The base repository - will usually be extended by a more concrete repository.
35 class Repository
implements \TYPO3\CMS\Extbase\Persistence\RepositoryInterface
, \TYPO3\CMS\Core\SingletonInterface
{
38 * @var \TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap
40 protected $identityMap;
43 * Objects of this repository
45 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage
47 protected $addedObjects;
50 * Objects removed but not found in $this->addedObjects at removal time
52 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage
54 protected $removedObjects;
57 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface
59 protected $queryFactory;
62 * @var \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
67 * @var \TYPO3\CMS\Extbase\Persistence\Generic\Session
72 * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
74 protected $persistenceManager;
77 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
79 protected $objectManager;
84 protected $objectType;
89 protected $defaultOrderings = array();
92 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
94 protected $defaultQuerySettings = NULL;
97 * Constructs a new Repository
99 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
100 * @deprecated since Extbase 6.0.0; will be removed in Extbase 6.2 - Use objectManager to instantiate repository objects instead of GeneralUtility::makeInstance
102 public function __construct(\TYPO3\CMS\Extbase\
Object\ObjectManagerInterface
$objectManager = NULL) {
103 $this->addedObjects
= new \TYPO3\CMS\Extbase\Persistence\
ObjectStorage();
104 $this->removedObjects
= new \TYPO3\CMS\Extbase\Persistence\
ObjectStorage();
105 $nsSeparator = strpos($this->getRepositoryClassName(), '\\') !== FALSE ?
'\\\\' : '_';
106 $this->objectType
= preg_replace(array('/' . $nsSeparator . 'Repository' . $nsSeparator . '(?!.*' . $nsSeparator . 'Repository' . $nsSeparator . ')/', '/Repository$/'), array($nsSeparator . 'Model' . $nsSeparator, ''), $this->getRepositoryClassName());
107 if ($objectManager === NULL) {
108 // Legacy creation, in case the object manager is NOT injected
109 // If ObjectManager IS there, then all properties are automatically injected
110 // @deprecated since Extbase 6.0.0, will be removed in Extbase 6.2
111 \TYPO3\CMS\Core\Utility\GeneralUtility
::logDeprecatedFunction();
113 $this->objectManager
= \TYPO3\CMS\Core\Utility\GeneralUtility
::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
114 $this->injectIdentityMap($this->objectManager
->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\IdentityMap'));
115 $this->injectQueryFactory($this->objectManager
->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\QueryFactory'));
116 $this->injectPersistenceManager($this->objectManager
->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager'));
117 $this->injectBackend($this->objectManager
->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\BackendInterface'));
118 $this->injectSession($this->objectManager
->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Session'));
120 $this->objectManager
= $objectManager;
125 * @param \TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap $identityMap
128 public function injectIdentityMap(\TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap
$identityMap) {
129 $this->identityMap
= $identityMap;
133 * Injects the Persistence Backend
135 * @param \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface $backend The persistence backend
138 public function injectBackend(\TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
$backend) {
139 $this->backend
= $backend;
144 * Injects the Persistence Session
146 * @param \TYPO3\CMS\Extbase\Persistence\Generic\Session $session The persistence session
149 public function injectSession(\TYPO3\CMS\Extbase\Persistence\Generic\Session
$session) {
150 $this->session
= $session;
154 * @param \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory $queryFactory
157 public function injectQueryFactory(\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory
$queryFactory) {
158 $this->queryFactory
= $queryFactory;
162 * @param \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager
165 public function injectPersistenceManager(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
$persistenceManager) {
166 $this->persistenceManager
= $persistenceManager;
167 $this->persistenceManager
->registerRepositoryClassName($this->getRepositoryClassName());
171 * Adds an object to this repository
173 * @param object $object The object to add
174 * @throws Exception\IllegalObjectTypeException
178 public function add($object) {
179 if (!$object instanceof $this->objectType
) {
180 throw new \TYPO3\CMS\Extbase\Persistence\Exception\
IllegalObjectTypeException('The object given to add() was not of the type (' . $this->objectType
. ') this repository manages.', 1248363335);
182 $this->addedObjects
->attach($object);
183 if ($this->removedObjects
->contains($object)) {
184 $this->removedObjects
->detach($object);
189 * Removes an object from this repository.
191 * @param object $object The object to remove
192 * @throws Exception\IllegalObjectTypeException
196 public function remove($object) {
197 if (!$object instanceof $this->objectType
) {
198 throw new \TYPO3\CMS\Extbase\Persistence\Exception\
IllegalObjectTypeException('The object given to remove() was not of the type (' . $this->objectType
. ') this repository manages.', 1248363335);
200 if ($this->addedObjects
->contains($object)) {
201 $this->addedObjects
->detach($object);
203 if (!$object->_isNew()) {
204 $this->removedObjects
->attach($object);
209 * Replaces an object by another.
211 * @param object $existingObject The existing object
212 * @param object $newObject The new object
213 * @throws Exception\UnknownObjectException
214 * @throws Exception\IllegalObjectTypeException
218 public function replace($existingObject, $newObject) {
219 if (!$existingObject instanceof $this->objectType
) {
220 throw new \TYPO3\CMS\Extbase\Persistence\Exception\
IllegalObjectTypeException('The existing object given to replace was not of the type (' . $this->objectType
. ') this repository manages.', 1248363434);
222 if (!$newObject instanceof $this->objectType
) {
223 throw new \TYPO3\CMS\Extbase\Persistence\Exception\
IllegalObjectTypeException('The new object given to replace was not of the type (' . $this->objectType
. ') this repository manages.', 1248363439);
225 $uuid = $this->persistenceManager
->getIdentifierByObject($existingObject);
226 if ($uuid !== NULL) {
227 $this->backend
->replaceObject($existingObject, $newObject);
228 $this->session
->unregisterReconstitutedObject($existingObject);
229 $this->session
->registerReconstitutedObject($newObject);
230 if ($this->removedObjects
->contains($existingObject)) {
231 $this->removedObjects
->detach($existingObject);
232 $this->removedObjects
->attach($newObject);
233 } elseif ($this->addedObjects
->contains($existingObject)) {
234 $this->addedObjects
->detach($existingObject);
235 $this->addedObjects
->attach($newObject);
237 } elseif ($this->addedObjects
->contains($existingObject)) {
238 $this->addedObjects
->detach($existingObject);
239 $this->addedObjects
->attach($newObject);
241 throw new \TYPO3\CMS\Extbase\Persistence\Exception\
UnknownObjectException('The "existing object" is unknown to the persistence backend.', 1238068475);
246 * Replaces an existing object with the same identifier by the given object
248 * @param object $modifiedObject The modified object
249 * @throws Exception\UnknownObjectException
250 * @throws Exception\IllegalObjectTypeException
254 public function update($modifiedObject) {
255 if (!$modifiedObject instanceof $this->objectType
) {
256 throw new \TYPO3\CMS\Extbase\Persistence\Exception\
IllegalObjectTypeException('The modified object given to update() was not of the type (' . $this->objectType
. ') this repository manages.', 1249479625);
258 $uid = $modifiedObject->getUid();
260 $existingObject = $this->findByUid($uid);
261 $this->replace($existingObject, $modifiedObject);
263 throw new \TYPO3\CMS\Extbase\Persistence\Exception\
UnknownObjectException('The "modified object" is does not have an existing counterpart in this repository.', 1249479819);
268 * Returns all addedObjects that have been added to this repository with add().
270 * This is a service method for the persistence manager to get all addedObjects
271 * added to the repository. Those are only objects *added*, not objects
272 * fetched from the underlying storage.
274 * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage the objects
276 public function getAddedObjects() {
277 return $this->addedObjects
;
281 * Returns an \TYPO3\CMS\Extbase\Persistence\ObjectStorage with objects remove()d from the repository
282 * that had been persisted to the storage layer before.
284 * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage the objects
286 public function getRemovedObjects() {
287 return $this->removedObjects
;
291 * Returns all objects of this repository.
293 * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array
296 public function findAll() {
297 $result = $this->createQuery()->execute();
302 * Returns the total number objects of this repository.
304 * @return integer The object count
307 public function countAll() {
308 return $this->createQuery()->execute()->count();
312 * Removes all objects of this repository as if remove() was called for
318 public function removeAll() {
319 $this->addedObjects
= new \TYPO3\CMS\Extbase\Persistence\
ObjectStorage();
320 foreach ($this->findAll() as $object) {
321 $this->remove($object);
326 * Finds an object matching the given identifier.
328 * @param integer $uid The identifier of the object to find
329 * @return object The matching object if found, otherwise NULL
332 public function findByUid($uid) {
333 if ($this->identityMap
->hasIdentifier($uid, $this->objectType
)) {
334 $object = $this->identityMap
->getObjectByIdentifier($uid, $this->objectType
);
336 $query = $this->createQuery();
337 $query->getQuerySettings()->setRespectSysLanguage(FALSE);
338 $query->getQuerySettings()->setRespectStoragePage(FALSE);
339 $object = $query->matching($query->equals('uid', $uid))->execute()->getFirst();
345 * Sets the property names to order the result by per default.
346 * Expected like this:
348 * 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
349 * 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
352 * @param array $defaultOrderings The property names to order by
356 public function setDefaultOrderings(array $defaultOrderings) {
357 $this->defaultOrderings
= $defaultOrderings;
361 * Sets the default query settings to be used in this repository
363 * @param \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
367 public function setDefaultQuerySettings(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
$defaultQuerySettings) {
368 $this->defaultQuerySettings
= $defaultQuerySettings;
372 * Returns a query for objects of this repository
374 * @return \TYPO3\CMS\Extbase\Persistence\QueryInterface
377 public function createQuery() {
378 $query = $this->queryFactory
->create($this->objectType
);
379 if ($this->defaultOrderings
!== array()) {
380 $query->setOrderings($this->defaultOrderings
);
382 if ($this->defaultQuerySettings
!== NULL) {
383 $query->setQuerySettings(clone $this->defaultQuerySettings
);
389 * Dispatches magic methods (findBy[Property]())
391 * @param string $methodName The name of the magic method
392 * @param string $arguments The arguments of the magic method
393 * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedMethodException
397 public function __call($methodName, $arguments) {
398 if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
399 $propertyName = lcfirst(substr($methodName, 6));
400 $query = $this->createQuery();
401 $result = $query->matching($query->equals($propertyName, $arguments[0]))->execute();
403 } elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
404 $propertyName = lcfirst(substr($methodName, 9));
405 $query = $this->createQuery();
407 $result = $query->matching($query->equals($propertyName, $arguments[0]))->setLimit(1)->execute();
408 if ($result instanceof \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
) {
409 return $result->getFirst();
410 } elseif (is_array($result)) {
411 return isset($result[0]) ?
$result[0] : NULL;
414 } elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
415 $propertyName = lcfirst(substr($methodName, 7));
416 $query = $this->createQuery();
417 $result = $query->matching($query->equals($propertyName, $arguments[0]))->execute()->count();
420 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\
UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1233180480);
424 * Returns the class name of this class.
426 * @return string Class name of the repository.
428 protected function getRepositoryClassName() {
429 return get_class($this);