eec0f742c321f228f28b3fc2606f62efc268a354
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Persistence / Generic / LazyObjectStorage.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Persistence\Generic;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
18
19 /**
20 * A proxy that can replace any object and replaces itself in it's parent on
21 * first access (call, get, set, isset, unset).
22 */
23 class LazyObjectStorage extends \TYPO3\CMS\Extbase\Persistence\ObjectStorage implements \TYPO3\CMS\Extbase\Persistence\Generic\LoadingStrategyInterface
24 {
25 /**
26 * This field is only needed to make debugging easier:
27 * If you call current() on a class that implements Iterator, PHP will return the first field of the object
28 * instead of calling the current() method of the interface.
29 * We use this unusual behavior of PHP to return the warning below in this case.
30 *
31 * @var string
32 */
33 private $warning = 'You should never see this warning. If you do, you probably used PHP array functions like current() on the TYPO3\\CMS\\Extbase\\Persistence\\Generic\\LazyObjectStorage. To retrieve the first result, you can use the rewind() and current() methods.';
34
35 /**
36 * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
37 */
38 protected $dataMapper;
39
40 /**
41 * The object this property is contained in.
42 *
43 * @var \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface
44 */
45 protected $parentObject;
46
47 /**
48 * The name of the property represented by this proxy.
49 *
50 * @var string
51 */
52 protected $propertyName;
53
54 /**
55 * The raw field value.
56 *
57 * @var mixed
58 */
59 protected $fieldValue;
60
61 /**
62 * @var bool
63 */
64 protected $isInitialized = false;
65
66 /**
67 * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
68 */
69 public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
70 {
71 $this->dataMapper = $dataMapper;
72 }
73
74 /**
75 * Returns the state of the initialization
76 *
77 * @return bool
78 */
79 public function isInitialized()
80 {
81 return $this->isInitialized;
82 }
83
84 /**
85 * Constructs this proxy instance.
86 *
87 * @param DomainObjectInterface $parentObject The object instance this proxy is part of
88 * @param string $propertyName The name of the proxied property in it's parent
89 * @param mixed $fieldValue The raw field value.
90 */
91 public function __construct($parentObject, $propertyName, $fieldValue)
92 {
93 $this->parentObject = $parentObject;
94 $this->propertyName = $propertyName;
95 $this->fieldValue = $fieldValue;
96 reset($this->storage);
97 }
98
99 /**
100 * This is a function lazy load implementation.
101 */
102 protected function initialize()
103 {
104 if (!$this->isInitialized) {
105 $this->isInitialized = true;
106 $objects = $this->dataMapper->fetchRelated($this->parentObject, $this->propertyName, $this->fieldValue, false);
107 foreach ($objects as $object) {
108 parent::attach($object);
109 }
110 $this->_memorizeCleanState();
111 if (!$this->isStorageAlreadyMemorizedInParentCleanState()) {
112 $this->parentObject->_memorizeCleanState($this->propertyName);
113 }
114 }
115 }
116
117 /**
118 * @return bool
119 */
120 protected function isStorageAlreadyMemorizedInParentCleanState()
121 {
122 return $this->parentObject->_getCleanProperty($this->propertyName) === $this;
123 }
124
125 // Delegation to the ObjectStorage methods below
126 /**
127 * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $storage
128 *
129 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::addAll
130 */
131 public function addAll(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $storage)
132 {
133 $this->initialize();
134 parent::addAll($storage);
135 }
136
137 /**
138 * @param object $object The object to add.
139 * @param mixed $data The data to associate with the object.
140 *
141 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::attach
142 */
143 public function attach($object, $data = null)
144 {
145 $this->initialize();
146 parent::attach($object, $data);
147 }
148
149 /**
150 * @param object $object The object to look for.
151 * @return bool
152 *
153 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::contains
154 */
155 public function contains($object)
156 {
157 $this->initialize();
158 return parent::contains($object);
159 }
160
161 /**
162 * Counts the elements in the storage array
163 *
164 * @throws Exception
165 * @return int The number of elements in the ObjectStorage
166 */
167 public function count()
168 {
169 $columnMap = $this->dataMapper->getDataMap(get_class($this->parentObject))->getColumnMap($this->propertyName);
170 $numberOfElements = null;
171 if (!$this->isInitialized && $columnMap->getTypeOfRelation() === Mapper\ColumnMap::RELATION_HAS_MANY) {
172 $numberOfElements = $this->dataMapper->countRelated($this->parentObject, $this->propertyName, $this->fieldValue);
173 } else {
174 $this->initialize();
175 $numberOfElements = count($this->storage);
176 }
177 if (is_null($numberOfElements)) {
178 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('The number of elements could not be determined.', 1252514486);
179 }
180 return $numberOfElements;
181 }
182
183 /**
184 * @return object The object at the current iterator position.
185 *
186 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::current
187 */
188 public function current()
189 {
190 $this->initialize();
191 return parent::current();
192 }
193
194 /**
195 * @param object $object The object to remove.
196 *
197 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::detach
198 */
199 public function detach($object)
200 {
201 $this->initialize();
202 parent::detach($object);
203 }
204
205 /**
206 * @return string The index corresponding to the position of the iterator.
207 *
208 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::key
209 */
210 public function key()
211 {
212 $this->initialize();
213 return parent::key();
214 }
215
216 /**
217 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::next
218 */
219 public function next()
220 {
221 $this->initialize();
222 parent::next();
223 }
224
225 /**
226 * @param object $object The object to look for.
227 * @return bool
228 *
229 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::offsetExists
230 */
231 public function offsetExists($object)
232 {
233 $this->initialize();
234 return parent::offsetExists($object);
235 }
236
237 /**
238 * @param object $object The object to look for.
239 * @return mixed
240 *
241 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::offsetGet
242 */
243 public function offsetGet($object)
244 {
245 $this->initialize();
246 return parent::offsetGet($object);
247 }
248
249 /**
250 * @param object $object The object to add.
251 * @param mixed $info The data to associate with the object.
252 *
253 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::offsetSet
254 */
255 public function offsetSet($object, $info)
256 {
257 $this->initialize();
258 parent::offsetSet($object, $info);
259 }
260
261 /**
262 * @param object $object The object to remove.
263 *
264 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::offsetUnset
265 */
266 public function offsetUnset($object)
267 {
268 $this->initialize();
269 parent::offsetUnset($object);
270 }
271
272 /**
273 * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $storage The storage containing the elements to remove.
274 *
275 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::removeAll
276 */
277 public function removeAll(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $storage)
278 {
279 $this->initialize();
280 parent::removeAll($storage);
281 }
282
283 /**
284 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::rewind
285 */
286 public function rewind()
287 {
288 $this->initialize();
289 parent::rewind();
290 }
291
292 /**
293 * @return bool
294 *
295 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::valid
296 */
297 public function valid()
298 {
299 $this->initialize();
300 return parent::valid();
301 }
302
303 /**
304 * @return array
305 *
306 * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::toArray
307 */
308 public function toArray()
309 {
310 $this->initialize();
311 return parent::toArray();
312 }
313
314 /**
315 * @param mixed $object
316 * @return int|NULL
317 */
318 public function getPosition($object)
319 {
320 $this->initialize();
321 return parent::getPosition($object);
322 }
323 }