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