[TASK] Streamline phpdoc annotations in EXT:extbase
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Persistence / Generic / LazyLoadingProxy.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\AbstractDomainObject;
18 use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
19 use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
20 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
21
22 /**
23 * A proxy that can replace any object and replaces itself in it's parent on
24 * first access (call, get, set, isset, unset).
25 * @internal only to be used within Extbase, not part of TYPO3 Core API.
26 */
27 class LazyLoadingProxy implements \Iterator, LoadingStrategyInterface
28 {
29 /**
30 * @var ?DataMapper
31 */
32 protected $dataMapper;
33
34 /**
35 * The object this property is contained in.
36 *
37 * @var DomainObjectInterface
38 */
39 private $parentObject;
40
41 /**
42 * The name of the property represented by this proxy.
43 *
44 * @var string
45 */
46 private $propertyName;
47
48 /**
49 * The raw field value.
50 *
51 * @var mixed
52 */
53 private $fieldValue;
54
55 /**
56 * @var ObjectManagerInterface
57 */
58 protected $objectManager;
59
60 /**
61 * @param ObjectManagerInterface $objectManager
62 */
63 public function injectObjectManager(ObjectManagerInterface $objectManager)
64 {
65 $this->objectManager = $objectManager;
66 }
67
68 /**
69 * Constructs this proxy instance.
70 *
71 * @param DomainObjectInterface $parentObject The object instance this proxy is part of
72 * @param string $propertyName The name of the proxied property in it's parent
73 * @param mixed $fieldValue The raw field value.
74 * @param ?DataMapper $dataMapper
75 */
76 public function __construct($parentObject, $propertyName, $fieldValue, ?DataMapper $dataMapper = null)
77 {
78 $this->parentObject = $parentObject;
79 $this->propertyName = $propertyName;
80 $this->fieldValue = $fieldValue;
81 $this->dataMapper = $dataMapper;
82 }
83
84 /**
85 * Object initialization called when object is created with ObjectManager, after constructor
86 */
87 public function initializeObject()
88 {
89 if (!$this->dataMapper) {
90 $this->dataMapper = $this->objectManager->get(DataMapper::class);
91 }
92 }
93
94 /**
95 * Populate this proxy by asking the $population closure.
96 *
97 * @return object The instance (hopefully) returned
98 */
99 public function _loadRealInstance()
100 {
101 // this check safeguards against a proxy being activated multiple times
102 // usually that does not happen, but if the proxy is held from outside
103 // its parent ... the result would be weird.
104 if ($this->parentObject instanceof AbstractDomainObject
105 && $this->parentObject->_getProperty($this->propertyName) instanceof LazyLoadingProxy
106 && $this->dataMapper
107 ) {
108 $objects = $this->dataMapper->fetchRelated($this->parentObject, $this->propertyName, $this->fieldValue, false);
109 $propertyValue = $this->dataMapper->mapResultToPropertyValue($this->parentObject, $this->propertyName, $objects);
110 $this->parentObject->_setProperty($this->propertyName, $propertyValue);
111 $this->parentObject->_memorizeCleanState($this->propertyName);
112 return $propertyValue;
113 }
114 return $this->parentObject->_getProperty($this->propertyName);
115 }
116
117 /**
118 * @return string
119 */
120 public function _getTypeAndUidString()
121 {
122 $type = $this->dataMapper->getType(get_class($this->parentObject), $this->propertyName);
123 return $type . ':' . $this->fieldValue;
124 }
125
126 /**
127 * Magic method call implementation.
128 *
129 * @param string $methodName The name of the property to get
130 * @param array $arguments The arguments given to the call
131 * @return mixed
132 */
133 public function __call($methodName, $arguments)
134 {
135 $realInstance = $this->_loadRealInstance();
136 if (!is_object($realInstance)) {
137 return null;
138 }
139 return call_user_func_array([$realInstance, $methodName], $arguments);
140 }
141
142 /**
143 * Magic get call implementation.
144 *
145 * @param string $propertyName The name of the property to get
146 * @return mixed
147 */
148 public function __get($propertyName)
149 {
150 $realInstance = $this->_loadRealInstance();
151 return $realInstance->{$propertyName};
152 }
153
154 /**
155 * Magic set call implementation.
156 *
157 * @param string $propertyName The name of the property to set
158 * @param mixed $value The value for the property to set
159 */
160 public function __set($propertyName, $value)
161 {
162 $realInstance = $this->_loadRealInstance();
163 $realInstance->{$propertyName} = $value;
164 }
165
166 /**
167 * Magic isset call implementation.
168 *
169 * @param string $propertyName The name of the property to check
170 * @return bool
171 */
172 public function __isset($propertyName)
173 {
174 $realInstance = $this->_loadRealInstance();
175 return isset($realInstance->{$propertyName});
176 }
177
178 /**
179 * Magic unset call implementation.
180 *
181 * @param string $propertyName The name of the property to unset
182 */
183 public function __unset($propertyName)
184 {
185 $realInstance = $this->_loadRealInstance();
186 unset($realInstance->{$propertyName});
187 }
188
189 /**
190 * Magic toString call implementation.
191 *
192 * @return string
193 */
194 public function __toString()
195 {
196 $realInstance = $this->_loadRealInstance();
197 return $realInstance->__toString();
198 }
199
200 /**
201 * Returns the current value of the storage array
202 *
203 * @return mixed
204 */
205 public function current()
206 {
207 $realInstance = $this->_loadRealInstance();
208 return current($realInstance);
209 }
210
211 /**
212 * Returns the current key storage array
213 *
214 * @return int
215 */
216 public function key()
217 {
218 $realInstance = $this->_loadRealInstance();
219 return key($realInstance);
220 }
221
222 /**
223 * Returns the next position of the storage array
224 */
225 public function next()
226 {
227 $realInstance = $this->_loadRealInstance();
228 next($realInstance);
229 }
230
231 /**
232 * Resets the array pointer of the storage
233 */
234 public function rewind()
235 {
236 $realInstance = $this->_loadRealInstance();
237 reset($realInstance);
238 }
239
240 /**
241 * Checks if the array pointer of the storage points to a valid position
242 *
243 * @return bool
244 */
245 public function valid()
246 {
247 return $this->current() !== false;
248 }
249 }