b3bbfc518a7e1cc1313c5adb2232d00fa8a74aba
[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 * @deprecated since 6.1 will be removed two versions later, use the persistence session instead
40 */
41 protected $identityMap;
42
43 /**
44 * @var \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
45 * @deprecated since 6.1, will be removed two versions later, use the persistence manager instead
46 */
47 protected $backend;
48
49 /**
50 * @var \TYPO3\CMS\Extbase\Persistence\Generic\Session
51 * @deprecated since 6.1 will be removed two versions later, use the persistence manager instead
52 */
53 protected $session;
54
55 /**
56 * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
57 */
58 protected $persistenceManager;
59
60 /**
61 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
62 */
63 protected $objectManager;
64
65 /**
66 * @var string
67 */
68 protected $objectType;
69
70 /**
71 * @var array
72 */
73 protected $defaultOrderings = array();
74
75 /**
76 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
77 */
78 protected $defaultQuerySettings = NULL;
79
80 /**
81 * Constructs a new Repository
82 *
83 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
84 * @deprecated since Extbase 6.0.0; will be removed in Extbase 6.2 - Use objectManager to instantiate repository objects instead of GeneralUtility::makeInstance
85 */
86 public function __construct(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager = NULL) {
87 $nsSeparator = strpos($this->getRepositoryClassName(), '\\') !== FALSE ? '\\\\' : '_';
88 $this->objectType = preg_replace(array('/' . $nsSeparator . 'Repository' . $nsSeparator . '(?!.*' . $nsSeparator . 'Repository' . $nsSeparator . ')/', '/Repository$/'), array($nsSeparator . 'Model' . $nsSeparator, ''), $this->getRepositoryClassName());
89 if ($objectManager === NULL) {
90 // Legacy creation, in case the object manager is NOT injected
91 // If ObjectManager IS there, then all properties are automatically injected
92 // @deprecated since Extbase 6.0.0, will be removed in Extbase 6.2
93 \TYPO3\CMS\Core\Utility\GeneralUtility::logDeprecatedFunction();
94
95 $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
96 $this->injectIdentityMap($this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\IdentityMap'));
97 $this->injectPersistenceManager($this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager'));
98 $this->injectBackend($this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\BackendInterface'));
99 $this->injectSession($this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Session'));
100 } else {
101 $this->objectManager = $objectManager;
102 }
103 }
104
105 /**
106 * @param \TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap $identityMap
107 * @return void
108 * @deprecated since 6.1, will be removed two versions later
109 */
110 public function injectIdentityMap(\TYPO3\CMS\Extbase\Persistence\Generic\IdentityMap $identityMap) {
111 $this->identityMap = $identityMap;
112 }
113
114 /**
115 * Injects the Persistence Backend
116 *
117 * @param \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface $backend The persistence backend
118 * @return void
119 * @deprecated since 6.1, will be removed two versions later
120 */
121 public function injectBackend(\TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface $backend) {
122 $this->backend = $backend;
123 }
124
125 /**
126 * Injects the Persistence Session
127 *
128 * @param \TYPO3\CMS\Extbase\Persistence\Generic\Session $session The persistence session
129 * @return void
130 * @deprecated since 6.1, will be removed two versions later
131 */
132 public function injectSession(\TYPO3\CMS\Extbase\Persistence\Generic\Session $session) {
133 $this->session = $session;
134 }
135
136 /**
137 * @param \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager
138 * @return void
139 */
140 public function injectPersistenceManager(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager) {
141 $this->persistenceManager = $persistenceManager;
142 }
143
144 /**
145 * Adds an object to this repository
146 *
147 * @param object $object The object to add
148 * @throws Exception\IllegalObjectTypeException
149 * @return void
150 * @api
151 */
152 public function add($object) {
153 if (!$object instanceof $this->objectType) {
154 throw new \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException('The object given to add() was not of the type (' . $this->objectType . ') this repository manages.', 1248363335);
155 }
156 $this->persistenceManager->add($object);
157 }
158
159 /**
160 * Removes an object from this repository.
161 *
162 * @param object $object The object to remove
163 * @throws Exception\IllegalObjectTypeException
164 * @return void
165 * @api
166 */
167 public function remove($object) {
168 if (!$object instanceof $this->objectType) {
169 throw new \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException('The object given to remove() was not of the type (' . $this->objectType . ') this repository manages.', 1248363335);
170 }
171 $this->persistenceManager->remove($object);
172 }
173
174 /**
175 * Replaces an object by another.
176 *
177 * @param object $existingObject The existing object
178 * @param object $newObject The new object
179 * @deprecated since 6.1, will be removed two versions later
180 */
181 public function replace($existingObject, $newObject) {
182 // Does nothing here as explicit update replaces objects in persistence session already
183 }
184
185 /**
186 * Replaces an existing object with the same identifier by the given object
187 *
188 * @param object $modifiedObject The modified object
189 * @throws Exception\UnknownObjectException
190 * @throws Exception\IllegalObjectTypeException
191 * @return void
192 * @api
193 */
194 public function update($modifiedObject) {
195 if (!$modifiedObject instanceof $this->objectType) {
196 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);
197 }
198 $this->persistenceManager->update($modifiedObject);
199 }
200
201 /**
202 * Returns all objects of this repository.
203 *
204 * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array
205 * @api
206 */
207 public function findAll() {
208 return $this->createQuery()->execute();
209 }
210
211 /**
212 * Returns the total number objects of this repository.
213 *
214 * @return integer The object count
215 * @api
216 */
217 public function countAll() {
218 return $this->createQuery()->execute()->count();
219 }
220
221 /**
222 * Removes all objects of this repository as if remove() was called for
223 * all of them.
224 *
225 * @return void
226 * @api
227 */
228 public function removeAll() {
229 foreach ($this->findAll() AS $object) {
230 $this->remove($object);
231 }
232 }
233
234 /**
235 * Finds an object matching the given identifier.
236 *
237 * @param integer $uid The identifier of the object to find
238 * @return object The matching object if found, otherwise NULL
239 * @api
240 */
241 public function findByUid($uid) {
242 return $this->findByIdentifier($uid);
243 }
244
245 /**
246 * Finds an object matching the given identifier.
247 *
248 * @param mixed $identifier The identifier of the object to find
249 * @return object The matching object if found, otherwise NULL
250 * @api
251 */
252 public function findByIdentifier($identifier) {
253 /**
254 * @todo: This method must be changed again in 6.2 + 1
255 * This is marked @deprecated to be found in cleanup sessions.
256 *
257 * The repository should directly talk to the backend which
258 * does not respect query settings of the repository as
259 * findByIdentifier is strictly defined by finding an
260 * undeleted object by its identifier regardless if it
261 * is hidden/visible or a versioning/translation overlay.
262 *
263 * As a consequence users will be forced to overwrite this method
264 * and mimic this behaviour to be able to find objects by identifier
265 * respecting their query settings from 6.1 + 1 on.
266 */
267 if ($this->session->hasIdentifier($identifier, $this->objectType)) {
268 $object = $this->session->getObjectByIdentifier($identifier, $this->objectType);
269 } else {
270 $query = $this->createQuery();
271 $query->getQuerySettings()->setRespectStoragePage(FALSE);
272 $query->getQuerySettings()->setRespectSysLanguage(FALSE);
273 $object = $query->matching($query->equals('uid', $identifier))->execute()->getFirst();
274 }
275
276 return $object;
277 }
278
279 /**
280 * Sets the property names to order the result by per default.
281 * Expected like this:
282 * array(
283 * 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
284 * 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
285 * )
286 *
287 * @param array $defaultOrderings The property names to order by
288 * @return void
289 * @api
290 */
291 public function setDefaultOrderings(array $defaultOrderings) {
292 $this->defaultOrderings = $defaultOrderings;
293 }
294
295 /**
296 * Sets the default query settings to be used in this repository
297 *
298 * @param \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
299 * @return void
300 * @api
301 */
302 public function setDefaultQuerySettings(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings) {
303 $this->defaultQuerySettings = $defaultQuerySettings;
304 }
305
306 /**
307 * Returns a query for objects of this repository
308 *
309 * @return \TYPO3\CMS\Extbase\Persistence\QueryInterface
310 * @api
311 */
312 public function createQuery() {
313 $query = $this->persistenceManager->createQueryForType($this->objectType);
314 if ($this->defaultOrderings !== array()) {
315 $query->setOrderings($this->defaultOrderings);
316 }
317 if ($this->defaultQuerySettings !== NULL) {
318 $query->setQuerySettings(clone $this->defaultQuerySettings);
319 }
320 return $query;
321 }
322
323 /**
324 * Dispatches magic methods (findBy[Property]())
325 *
326 * @param string $methodName The name of the magic method
327 * @param string $arguments The arguments of the magic method
328 * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedMethodException
329 * @return mixed
330 * @api
331 */
332 public function __call($methodName, $arguments) {
333 if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
334 $propertyName = lcfirst(substr($methodName, 6));
335 $query = $this->createQuery();
336 $result = $query->matching($query->equals($propertyName, $arguments[0]))->execute();
337 return $result;
338 } elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
339 $propertyName = lcfirst(substr($methodName, 9));
340 $query = $this->createQuery();
341
342 $result = $query->matching($query->equals($propertyName, $arguments[0]))->setLimit(1)->execute();
343 if ($result instanceof \TYPO3\CMS\Extbase\Persistence\QueryResultInterface) {
344 return $result->getFirst();
345 } elseif (is_array($result)) {
346 return isset($result[0]) ? $result[0] : NULL;
347 }
348
349 } elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
350 $propertyName = lcfirst(substr($methodName, 7));
351 $query = $this->createQuery();
352 $result = $query->matching($query->equals($propertyName, $arguments[0]))->execute()->count();
353 return $result;
354 }
355 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1233180480);
356 }
357
358 /**
359 * Returns the class name of this class.
360 *
361 * @return string Class name of the repository.
362 */
363 protected function getRepositoryClassName() {
364 return get_class($this);
365 }
366 }
367
368 ?>