[CLEANUP] Adjust code to coding guidelines
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Persistence / Repository.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Persistence;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * This class is a backport of the corresponding class of TYPO3 Flow.
8 * All credits go to the TYPO3 Flow team.
9 * All rights reserved.
10 *
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.
16 *
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.
21 *
22 *
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.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30 /**
31 * The base repository - will usually be extended by a more concrete repository.
32 *
33 * @api
34 */
35 class Repository implements \TYPO3\CMS\Extbase\Persistence\RepositoryInterface, \TYPO3\CMS\Core\SingletonInterface {
36
37 /**
38 * @var \TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap
39 */
40 protected $identityMap;
41
42 /**
43 * Objects of this repository
44 *
45 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage
46 */
47 protected $addedObjects;
48
49 /**
50 * Objects removed but not found in $this->addedObjects at removal time
51 *
52 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage
53 */
54 protected $removedObjects;
55
56 /**
57 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface
58 */
59 protected $queryFactory;
60
61 /**
62 * @var \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
63 */
64 protected $backend;
65
66 /**
67 * @var \TYPO3\CMS\Extbase\Persistence\Generic\Session
68 */
69 protected $session;
70
71 /**
72 * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
73 */
74 protected $persistenceManager;
75
76 /**
77 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
78 */
79 protected $objectManager;
80
81 /**
82 * @var string
83 */
84 protected $objectType;
85
86 /**
87 * @var array
88 */
89 protected $defaultOrderings = array();
90
91 /**
92 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
93 */
94 protected $defaultQuerySettings = NULL;
95
96 /**
97 * Constructs a new Repository
98 *
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
101 */
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();
112
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'));
119 } else {
120 $this->objectManager = $objectManager;
121 }
122 }
123
124 /**
125 * @param \TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap $identityMap
126 * @return void
127 */
128 public function injectIdentityMap(\TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap $identityMap) {
129 $this->identityMap = $identityMap;
130 }
131
132 /**
133 * Injects the Persistence Backend
134 *
135 * @param \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface $backend The persistence backend
136 * @return void
137 */
138 public function injectBackend(\TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface $backend) {
139 $this->backend = $backend;
140 }
141
142 /**
143 *
144 * Injects the Persistence Session
145 *
146 * @param \TYPO3\CMS\Extbase\Persistence\Generic\Session $session The persistence session
147 * @return void
148 */
149 public function injectSession(\TYPO3\CMS\Extbase\Persistence\Generic\Session $session) {
150 $this->session = $session;
151 }
152
153 /**
154 * @param \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory $queryFactory
155 * @return void
156 */
157 public function injectQueryFactory(\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory $queryFactory) {
158 $this->queryFactory = $queryFactory;
159 }
160
161 /**
162 * @param \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager
163 * @return void
164 */
165 public function injectPersistenceManager(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager) {
166 $this->persistenceManager = $persistenceManager;
167 $this->persistenceManager->registerRepositoryClassName($this->getRepositoryClassName());
168 }
169
170 /**
171 * Adds an object to this repository
172 *
173 * @param object $object The object to add
174 * @throws Exception\IllegalObjectTypeException
175 * @return void
176 * @api
177 */
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);
181 }
182 $this->addedObjects->attach($object);
183 if ($this->removedObjects->contains($object)) {
184 $this->removedObjects->detach($object);
185 }
186 }
187
188 /**
189 * Removes an object from this repository.
190 *
191 * @param object $object The object to remove
192 * @throws Exception\IllegalObjectTypeException
193 * @return void
194 * @api
195 */
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);
199 }
200 if ($this->addedObjects->contains($object)) {
201 $this->addedObjects->detach($object);
202 }
203 if (!$object->_isNew()) {
204 $this->removedObjects->attach($object);
205 }
206 }
207
208 /**
209 * Replaces an object by another.
210 *
211 * @param object $existingObject The existing object
212 * @param object $newObject The new object
213 * @throws Exception\UnknownObjectException
214 * @throws Exception\IllegalObjectTypeException
215 * @return void
216 * @api
217 */
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);
221 }
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);
224 }
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);
236 }
237 } elseif ($this->addedObjects->contains($existingObject)) {
238 $this->addedObjects->detach($existingObject);
239 $this->addedObjects->attach($newObject);
240 } else {
241 throw new \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException('The "existing object" is unknown to the persistence backend.', 1238068475);
242 }
243 }
244
245 /**
246 * Replaces an existing object with the same identifier by the given object
247 *
248 * @param object $modifiedObject The modified object
249 * @throws Exception\UnknownObjectException
250 * @throws Exception\IllegalObjectTypeException
251 * @return void
252 * @api
253 */
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);
257 }
258 $uid = $modifiedObject->getUid();
259 if ($uid !== NULL) {
260 $existingObject = $this->findByUid($uid);
261 $this->replace($existingObject, $modifiedObject);
262 } else {
263 throw new \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException('The "modified object" is does not have an existing counterpart in this repository.', 1249479819);
264 }
265 }
266
267 /**
268 * Returns all addedObjects that have been added to this repository with add().
269 *
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.
273 *
274 * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage the objects
275 */
276 public function getAddedObjects() {
277 return $this->addedObjects;
278 }
279
280 /**
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.
283 *
284 * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage the objects
285 */
286 public function getRemovedObjects() {
287 return $this->removedObjects;
288 }
289
290 /**
291 * Returns all objects of this repository.
292 *
293 * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array
294 * @api
295 */
296 public function findAll() {
297 $result = $this->createQuery()->execute();
298 return $result;
299 }
300
301 /**
302 * Returns the total number objects of this repository.
303 *
304 * @return integer The object count
305 * @api
306 */
307 public function countAll() {
308 return $this->createQuery()->execute()->count();
309 }
310
311 /**
312 * Removes all objects of this repository as if remove() was called for
313 * all of them.
314 *
315 * @return void
316 * @api
317 */
318 public function removeAll() {
319 $this->addedObjects = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
320 foreach ($this->findAll() as $object) {
321 $this->remove($object);
322 }
323 }
324
325 /**
326 * Finds an object matching the given identifier.
327 *
328 * @param integer $uid The identifier of the object to find
329 * @return object The matching object if found, otherwise NULL
330 * @api
331 */
332 public function findByUid($uid) {
333 if ($this->identityMap->hasIdentifier($uid, $this->objectType)) {
334 $object = $this->identityMap->getObjectByIdentifier($uid, $this->objectType);
335 } else {
336 $query = $this->createQuery();
337 $query->getQuerySettings()->setRespectSysLanguage(FALSE);
338 $query->getQuerySettings()->setRespectStoragePage(FALSE);
339 $object = $query->matching($query->equals('uid', $uid))->execute()->getFirst();
340 }
341 return $object;
342 }
343
344 /**
345 * Sets the property names to order the result by per default.
346 * Expected like this:
347 * array(
348 * 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
349 * 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
350 * )
351 *
352 * @param array $defaultOrderings The property names to order by
353 * @return void
354 * @api
355 */
356 public function setDefaultOrderings(array $defaultOrderings) {
357 $this->defaultOrderings = $defaultOrderings;
358 }
359
360 /**
361 * Sets the default query settings to be used in this repository
362 *
363 * @param \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
364 * @return void
365 * @api
366 */
367 public function setDefaultQuerySettings(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings) {
368 $this->defaultQuerySettings = $defaultQuerySettings;
369 }
370
371 /**
372 * Returns a query for objects of this repository
373 *
374 * @return \TYPO3\CMS\Extbase\Persistence\QueryInterface
375 * @api
376 */
377 public function createQuery() {
378 $query = $this->queryFactory->create($this->objectType);
379 if ($this->defaultOrderings !== array()) {
380 $query->setOrderings($this->defaultOrderings);
381 }
382 if ($this->defaultQuerySettings !== NULL) {
383 $query->setQuerySettings(clone $this->defaultQuerySettings);
384 }
385 return $query;
386 }
387
388 /**
389 * Dispatches magic methods (findBy[Property]())
390 *
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
394 * @return mixed
395 * @api
396 */
397 public function __call($methodName, $arguments) {
398 if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
399 $propertyName = strtolower(substr(substr($methodName, 6), 0, 1)) . substr(substr($methodName, 6), 1);
400 $query = $this->createQuery();
401 $result = $query->matching($query->equals($propertyName, $arguments[0]))->execute();
402 return $result;
403 } elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
404 $propertyName = strtolower(substr(substr($methodName, 9), 0, 1)) . substr(substr($methodName, 9), 1);
405 $query = $this->createQuery();
406 $object = $query->matching($query->equals($propertyName, $arguments[0]))->setLimit(1)->execute()->getFirst();
407 return $object;
408 } elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
409 $propertyName = strtolower(substr(substr($methodName, 7), 0, 1)) . substr(substr($methodName, 7), 1);
410 $query = $this->createQuery();
411 $result = $query->matching($query->equals($propertyName, $arguments[0]))->execute()->count();
412 return $result;
413 }
414 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1233180480);
415 }
416
417 /**
418 * Returns the class name of this class.
419 *
420 * @return string Class name of the repository.
421 */
422 protected function getRepositoryClassName() {
423 return get_class($this);
424 }
425 }
426
427 ?>