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