[+TASK] Extbase (DomainObject): Added a "private" property _localizationParentUid...
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Persistence / Repository.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
6 * All rights reserved
7 *
8 * This class is a backport of the corresponding class of FLOW3.
9 * All credits go to the v5 team.
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 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * The base repository - will usually be extended by a more concrete repository.
30 *
31 * @package Extbase
32 * @subpackage Persistence
33 * @version $ID:$
34 * @api
35 */
36 class Tx_Extbase_Persistence_Repository implements Tx_Extbase_Persistence_RepositoryInterface, t3lib_Singleton {
37
38 /**
39 * @var Tx_Extbase_Persistence_IdentityMap
40 **/
41 protected $identityMap;
42
43 /**
44 * Objects of this repository
45 *
46 * @var Tx_Extbase_Persistence_ObjectStorage
47 */
48 protected $addedObjects;
49
50 /**
51 * Objects removed but not found in $this->addedObjects at removal time
52 *
53 * @var Tx_Extbase_Persistence_ObjectStorage
54 */
55 protected $removedObjects;
56
57 /**
58 * @var Tx_Extbase_Persistence_QueryFactoryInterface
59 */
60 protected $queryFactory;
61
62 /**
63 * @var Tx_Extbase_Persistence_ManagerInterface
64 */
65 protected $persistenceManager;
66
67 /**
68 * @var string
69 */
70 protected $objectType;
71
72 /**
73 * Constructs a new Repository
74 *
75 */
76 public function __construct() {
77 $this->identityMap = t3lib_div::makeInstance('Tx_Extbase_Persistence_IdentityMap');
78 $this->addedObjects = new Tx_Extbase_Persistence_ObjectStorage();
79 $this->removedObjects = new Tx_Extbase_Persistence_ObjectStorage();
80 $this->queryFactory = t3lib_div::makeInstance('Tx_Extbase_Persistence_QueryFactory'); // singleton
81 $this->persistenceManager = Tx_Extbase_Dispatcher::getPersistenceManager();
82 $this->persistenceManager->registerRepositoryClassName(get_class($this));
83 $this->objectType = str_replace(array('_Repository_', 'Repository'), array('_Model_', ''), $this->getRepositoryClassName());
84 }
85
86 /**
87 * Adds an object to this repository
88 *
89 * @param object $object The object to add
90 * @return void
91 * @api
92 */
93 public function add($object) {
94 if (!($object instanceof $this->objectType)) {
95 throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The object given to add() was not of the type (' . $this->objectType . ') this repository manages.', 1248363335);
96 }
97
98 $this->addedObjects->attach($object);
99 $this->removedObjects->detach($object);
100 }
101
102 /**
103 * Removes an object from this repository.
104 *
105 * @param object $object The object to remove
106 * @return void
107 * @api
108 */
109 public function remove($object) {
110 if (!($object instanceof $this->objectType)) {
111 throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The object given to remove() was not of the type (' . $this->objectType . ') this repository manages.', 1248363335);
112 }
113
114 if ($this->addedObjects->contains($object)) {
115 $this->addedObjects->detach($object);
116 } else {
117 $this->removedObjects->attach($object);
118 }
119 }
120
121 /**
122 * Replaces an object by another.
123 *
124 * @param object $existingObject The existing object
125 * @param object $newObject The new object
126 * return void
127 * @api
128 */
129 public function replace($existingObject, $newObject) {
130 if (!($existingObject instanceof $this->objectType)) {
131 throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The existing object given to replace was not of the type (' . $this->objectType . ') this repository manages.', 1248363434);
132 }
133 if (!($newObject instanceof $this->objectType)) {
134 throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The new object given to replace was not of the type (' . $this->objectType . ') this repository manages.', 1248363439);
135 }
136
137 $backend = $this->persistenceManager->getBackend();
138 $session = $this->persistenceManager->getSession();
139 $uuid = $backend->getIdentifierByObject($existingObject);
140 if ($uuid !== NULL) {
141 $backend->replaceObject($existingObject, $newObject);
142 $session->unregisterReconstitutedObject($existingObject);
143 $session->registerReconstitutedObject($newObject);
144
145 if ($this->removedObjects->contains($existingObject)) {
146 $this->removedObjects->detach($existingObject);
147 $this->removedObjects->attach($newObject);
148 }
149 } elseif ($this->addedObjects->contains($existingObject)) {
150 $this->addedObjects->detach($existingObject);
151 $this->addedObjects->attach($newObject);
152 } else {
153 throw new Tx_Extbase_Persistence_Exception_UnknownObject('The "existing object" is unknown to the persistence backend.', 1238068475);
154 }
155
156 }
157
158 /**
159 * Replaces an existing object with the same identifier by the given object
160 *
161 * @param object $modifiedObject The modified object
162 * @api
163 */
164 public function update($modifiedObject) {
165 if (!($modifiedObject instanceof $this->objectType)) {
166 throw new Tx_Extbase_Persistence_Exception_IllegalObjectType('The modified object given to update() was not of the type (' . $this->objectType . ') this repository manages.', 1249479625);
167 }
168
169 $uid = $modifiedObject->getUid();
170 if ($uid !== NULL) {
171 $existingObject = $this->findByUid($uid);
172 $this->replace($existingObject, $modifiedObject);
173 } else {
174 throw new Tx_Extbase_Persistence_Exception_UnknownObject('The "modified object" is does not have an existing counterpart in this repository.', 1249479819);
175 }
176 }
177
178 /**
179 * Returns all addedObjects that have been added to this repository with add().
180 *
181 * This is a service method for the persistence manager to get all addedObjects
182 * added to the repository. Those are only objects *added*, not objects
183 * fetched from the underlying storage.
184 *
185 * @return Tx_Extbase_Persistence_ObjectStorage the objects
186 */
187 public function getAddedObjects() {
188 return $this->addedObjects;
189 }
190
191 /**
192 * Returns an Tx_Extbase_Persistence_ObjectStorage with objects remove()d from the repository
193 * that had been persisted to the storage layer before.
194 *
195 * @return Tx_Extbase_Persistence_ObjectStorage the objects
196 */
197 public function getRemovedObjects() {
198 return $this->removedObjects;
199 }
200
201 /**
202 * Returns all objects of this repository
203 *
204 * @return array An array of objects, empty if no objects found
205 * @api
206 */
207 public function findAll() {
208 $result = $this->createQuery()->execute();
209 return $result;
210 }
211
212 /**
213 * Removes all objects of this repository as if remove() was called for
214 * all of them.
215 *
216 * @return void
217 * @api
218 */
219 public function removeAll() {
220 $this->addedObjects = new Tx_Extbase_Persistence_ObjectStorage();
221 foreach ($this->findAll() as $object) {
222 $this->remove($object);
223 }
224 }
225
226 /**
227 * Finds an object matching the given identifier.
228 *
229 * @param int $uid The identifier of the object to find
230 * @return object The matching object if found, otherwise NULL
231 * @api
232 */
233 public function findByUid($uid) {
234 if (!is_int($uid) || $uid < 0) throw new InvalidArgumentException('The uid must be a positive integer', 1245071889);
235 if ($this->identityMap->hasIdentifier($uid, $this->objectType)) {
236 $object = $this->identityMap->getObjectByIdentifier($uid, $this->objectType);
237 } else {
238 $query = $this->createQuery();
239 $query->getQuerySettings()->setRespectSysLanguage(FALSE);
240 $result = $query->matching($query->withUid($uid))->execute();
241 $object = NULL;
242 if (count($result) > 0) {
243 $object = current($result);
244 }
245 $this->identityMap->registerObject($object, $uid);
246 }
247 return $object;
248 }
249
250 /**
251 * Returns a query for objects of this repository
252 *
253 * @param boolean $useStoragePageId If FALSE, will NOT add pid=... to the query. TRUE by default. Only change if you know what you are doing.
254 * @return Tx_Extbase_Persistence_QueryInterface
255 * @api
256 */
257 public function createQuery() {
258 return $this->queryFactory->create($this->objectType);
259 }
260
261 /**
262 * Dispatches magic methods (findBy[Property]())
263 *
264 * @param string $methodName The name of the magic method
265 * @param string $arguments The arguments of the magic method
266 * @throws Tx_Extbase_Persistence_Exception_UnsupportedMethod
267 * @return void
268 * @api
269 */
270 public function __call($methodName, $arguments) {
271 if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
272 $propertyName = strtolower(substr(substr($methodName, 6), 0, 1) ) . substr(substr($methodName, 6), 1);
273 $query = $this->createQuery();
274 $result = $query->matching($query->equals($propertyName, $arguments[0]))
275 ->execute();
276 return $result;
277 } elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
278 $propertyName = strtolower(substr(substr($methodName, 9), 0, 1) ) . substr(substr($methodName, 9), 1);
279 $query = $this->createQuery();
280 $result = $query->matching($query->equals($propertyName, $arguments[0]))
281 ->setLimit(1)
282 ->execute();
283 $object = NULL;
284 if (count($result) > 0) {
285 $object = current($result);
286 }
287 return $object;
288 }
289 throw new Tx_Extbase_Persistence_Exception_UnsupportedMethod('The method "' . $methodName . '" is not supported by the repository.', 1233180480);
290 }
291
292 /**
293 * Returns the class name of this class.
294 *
295 * @return string Class name of the repository.
296 */
297 protected function getRepositoryClassName() {
298 return get_class($this);
299 }
300
301 }
302 ?>