Passed
Push — master ( 797014...bcb509 )
by
unknown
19:02
created

LazyLoadingProxy::injectObjectManager()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Extbase\Persistence\Generic;
17
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
use TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject;
20
use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
21
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
22
23
/**
24
 * A proxy that can replace any object and replaces itself in it's parent on
25
 * first access (call, get, set, isset, unset).
26
 * @internal only to be used within Extbase, not part of TYPO3 Core API.
27
 */
28
class LazyLoadingProxy implements \Iterator, LoadingStrategyInterface
29
{
30
    protected DataMapper $dataMapper;
31
32
    /**
33
     * The object this property is contained in.
34
     *
35
     * @var DomainObjectInterface
36
     */
37
    private $parentObject;
38
39
    /**
40
     * The name of the property represented by this proxy.
41
     *
42
     * @var string
43
     */
44
    private $propertyName;
45
46
    /**
47
     * The raw field value.
48
     *
49
     * @var mixed
50
     */
51
    private $fieldValue;
52
53
    /**
54
     * Constructs this proxy instance.
55
     *
56
     * @param DomainObjectInterface $parentObject The object instance this proxy is part of
57
     * @param string $propertyName The name of the proxied property in it's parent
58
     * @param mixed $fieldValue The raw field value.
59
     * @param ?DataMapper $dataMapper
60
     */
61
    public function __construct($parentObject, $propertyName, $fieldValue, ?DataMapper $dataMapper = null)
62
    {
63
        $this->parentObject = $parentObject;
64
        $this->propertyName = $propertyName;
65
        $this->fieldValue = $fieldValue;
66
        if ($dataMapper === null) {
67
            $dataMapper = GeneralUtility::makeInstance(DataMapper::class);
68
        }
69
        /** @var DataMapper $dataMapper */
70
        $this->dataMapper = $dataMapper;
71
    }
72
73
    /**
74
     * Populate this proxy by asking the $population closure.
75
     *
76
     * @return object The instance (hopefully) returned
77
     */
78
    public function _loadRealInstance()
79
    {
80
        // this check safeguards against a proxy being activated multiple times
81
        // usually that does not happen, but if the proxy is held from outside
82
        // its parent ... the result would be weird.
83
        if ($this->parentObject instanceof AbstractDomainObject
84
            && $this->parentObject->_getProperty($this->propertyName) instanceof LazyLoadingProxy
85
            && $this->dataMapper
86
        ) {
87
            $objects = $this->dataMapper->fetchRelated($this->parentObject, $this->propertyName, $this->fieldValue, false);
88
            $propertyValue = $this->dataMapper->mapResultToPropertyValue($this->parentObject, $this->propertyName, $objects);
89
            $this->parentObject->_setProperty($this->propertyName, $propertyValue);
90
            $this->parentObject->_memorizeCleanState($this->propertyName);
91
            return $propertyValue;
92
        }
93
        return $this->parentObject->_getProperty($this->propertyName);
94
    }
95
96
    /**
97
     * @return string
98
     */
99
    public function _getTypeAndUidString()
100
    {
101
        $type = $this->dataMapper->getType(get_class($this->parentObject), $this->propertyName);
102
        return $type . ':' . $this->fieldValue;
103
    }
104
105
    /**
106
     * @return int
107
     */
108
    public function getUid(): int
109
    {
110
        return (int)$this->fieldValue;
111
    }
112
113
    /**
114
     * Magic method call implementation.
115
     *
116
     * @param string $methodName The name of the property to get
117
     * @param array $arguments The arguments given to the call
118
     * @return mixed
119
     */
120
    public function __call($methodName, $arguments)
121
    {
122
        $realInstance = $this->_loadRealInstance();
123
        if (!is_object($realInstance)) {
124
            return null;
125
        }
126
        /** @var callable $callable */
127
        $callable = [$realInstance, $methodName];
128
        return $callable(...$arguments);
129
    }
130
131
    /**
132
     * Magic get call implementation.
133
     *
134
     * @param string $propertyName The name of the property to get
135
     * @return mixed
136
     */
137
    public function __get($propertyName)
138
    {
139
        $realInstance = $this->_loadRealInstance();
140
        return $realInstance->{$propertyName};
141
    }
142
143
    /**
144
     * Magic set call implementation.
145
     *
146
     * @param string $propertyName The name of the property to set
147
     * @param mixed $value The value for the property to set
148
     */
149
    public function __set($propertyName, $value)
150
    {
151
        $realInstance = $this->_loadRealInstance();
152
        $realInstance->{$propertyName} = $value;
153
    }
154
155
    /**
156
     * Magic isset call implementation.
157
     *
158
     * @param string $propertyName The name of the property to check
159
     * @return bool
160
     */
161
    public function __isset($propertyName)
162
    {
163
        $realInstance = $this->_loadRealInstance();
164
        return isset($realInstance->{$propertyName});
165
    }
166
167
    /**
168
     * Magic unset call implementation.
169
     *
170
     * @param string $propertyName The name of the property to unset
171
     */
172
    public function __unset($propertyName)
173
    {
174
        $realInstance = $this->_loadRealInstance();
175
        unset($realInstance->{$propertyName});
176
    }
177
178
    /**
179
     * Magic toString call implementation.
180
     *
181
     * @return string
182
     */
183
    public function __toString()
184
    {
185
        $realInstance = $this->_loadRealInstance();
186
        return $realInstance->__toString();
187
    }
188
189
    /**
190
     * Returns the current value of the storage array
191
     *
192
     * @return mixed
193
     */
194
    public function current()
195
    {
196
        // todo: make sure current() can be performed on $realInstance
197
        $realInstance = $this->_loadRealInstance();
198
        return current($realInstance);
199
    }
200
201
    /**
202
     * Returns the current key storage array
203
     *
204
     * @return int
205
     */
206
    public function key()
207
    {
208
        // todo: make sure key() can be performed on $realInstance
209
        $realInstance = $this->_loadRealInstance();
210
        return key($realInstance);
0 ignored issues
show
Bug Best Practice introduced by
The expression return key($realInstance) also could return the type null|string which is incompatible with the documented return type integer.
Loading history...
211
    }
212
213
    /**
214
     * Returns the next position of the storage array
215
     */
216
    public function next()
217
    {
218
        // todo: make sure next() can be performed on $realInstance
219
        $realInstance = $this->_loadRealInstance();
220
        next($realInstance);
221
    }
222
223
    /**
224
     * Resets the array pointer of the storage
225
     */
226
    public function rewind()
227
    {
228
        // todo: make sure reset() can be performed on $realInstance
229
        $realInstance = $this->_loadRealInstance();
230
        reset($realInstance);
231
    }
232
233
    /**
234
     * Checks if the array pointer of the storage points to a valid position
235
     *
236
     * @return bool
237
     */
238
    public function valid()
239
    {
240
        return $this->current() !== false;
241
    }
242
}
243