LazyObjectStorage   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 293
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 28
eloc 65
dl 0
loc 293
rs 10
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
A key() 0 4 1
A initialize() 0 11 4
A __construct() 0 11 2
A attach() 0 4 1
A addAll() 0 4 1
A rewind() 0 4 1
A next() 0 4 1
A offsetSet() 0 4 1
A isInitialized() 0 3 1
A isStorageAlreadyMemorizedInParentCleanState() 0 3 1
A toArray() 0 4 1
A offsetExists() 0 4 1
A count() 0 13 4
A valid() 0 4 1
A removeAll() 0 4 1
A contains() 0 4 1
A detach() 0 4 1
A current() 0 4 1
A offsetGet() 0 4 1
A getPosition() 0 4 1
A offsetUnset() 0 4 1
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 Symfony\Component\VarDumper\Cloner\Data;
19
use TYPO3\CMS\Core\Utility\GeneralUtility;
20
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap;
21
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
22
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
23
24
/**
25
 * A proxy that can replace any object and replaces itself in it's parent on
26
 * first access (call, get, set, isset, unset).
27
 * @internal only to be used within Extbase, not part of TYPO3 Core API.
28
 *
29
 * @template TEntity
30
 * @extends ObjectStorage<TEntity>
31
 */
32
class LazyObjectStorage extends ObjectStorage implements LoadingStrategyInterface
33
{
34
    /**
35
     * This field is only needed to make debugging easier:
36
     * If you call current() on a class that implements Iterator, PHP will return the first field of the object
37
     * instead of calling the current() method of the interface.
38
     * We use this unusual behavior of PHP to return the warning below in this case.
39
     *
40
     * @var string
41
     */
42
    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.';
0 ignored issues
show
introduced by
The private property $warning is not used, and could be removed.
Loading history...
43
44
    protected DataMapper $dataMapper;
45
46
    /**
47
     * The object this property is contained in.
48
     *
49
     * @var \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface
50
     */
51
    protected $parentObject;
52
53
    /**
54
     * The name of the property represented by this proxy.
55
     *
56
     * @var string
57
     */
58
    protected $propertyName;
59
60
    /**
61
     * The raw field value.
62
     *
63
     * @var mixed
64
     */
65
    protected $fieldValue;
66
67
    /**
68
     * @var bool
69
     */
70
    protected $isInitialized = false;
71
72
    /**
73
     * Returns the state of the initialization
74
     *
75
     * @return bool
76
     */
77
    public function isInitialized()
78
    {
79
        return $this->isInitialized;
80
    }
81
82
    /**
83
     * Constructs this proxy instance.
84
     *
85
     * @param TEntity $parentObject The object instance this proxy is part of
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Persistence\Generic\TEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
86
     * @param string $propertyName The name of the proxied property in it's parent
87
     * @param mixed $fieldValue The raw field value.
88
     * @param ?DataMapper $dataMapper
89
     */
90
    public function __construct($parentObject, $propertyName, $fieldValue, ?DataMapper $dataMapper = null)
91
    {
92
        $this->parentObject = $parentObject;
93
        $this->propertyName = $propertyName;
94
        $this->fieldValue = $fieldValue;
95
        reset($this->storage);
96
        if ($dataMapper === null) {
97
            $dataMapper = GeneralUtility::makeInstance(DataMapper::class);
98
        }
99
        /** @var DataMapper $dataMapper */
100
        $this->dataMapper = $dataMapper;
101
    }
102
103
    /**
104
     * This is a function lazy load implementation.
105
     */
106
    protected function initialize()
107
    {
108
        if (!$this->isInitialized) {
109
            $this->isInitialized = true;
110
            $objects = $this->dataMapper->fetchRelated($this->parentObject, $this->propertyName, $this->fieldValue, false);
111
            foreach ($objects as $object) {
112
                parent::attach($object);
113
            }
114
            $this->_memorizeCleanState();
115
            if (!$this->isStorageAlreadyMemorizedInParentCleanState()) {
116
                $this->parentObject->_memorizeCleanState($this->propertyName);
0 ignored issues
show
Bug introduced by
The method _memorizeCleanState() does not exist on TYPO3\CMS\Extbase\Domain...t\DomainObjectInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to TYPO3\CMS\Extbase\Domain...t\DomainObjectInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

116
                $this->parentObject->/** @scrutinizer ignore-call */ 
117
                                     _memorizeCleanState($this->propertyName);
Loading history...
117
            }
118
        }
119
    }
120
121
    /**
122
     * @return bool
123
     */
124
    protected function isStorageAlreadyMemorizedInParentCleanState()
125
    {
126
        return $this->parentObject->_getCleanProperty($this->propertyName) === $this;
127
    }
128
129
    // Delegation to the ObjectStorage methods below
130
    /**
131
     * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $storage
132
     *
133
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::addAll
134
     */
135
    public function addAll(ObjectStorage $storage)
136
    {
137
        $this->initialize();
138
        parent::addAll($storage);
139
    }
140
141
    /**
142
     * @param TEntity $object The object to add.
143
     * @param mixed $data The data to associate with the object.
144
     *
145
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::attach
146
     */
147
    public function attach($object, $data = null)
148
    {
149
        $this->initialize();
150
        parent::attach($object, $data);
151
    }
152
153
    /**
154
     * @param TEntity $object The object to look for.
155
     * @return bool
156
     *
157
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::contains
158
     */
159
    public function contains($object)
160
    {
161
        $this->initialize();
162
        return parent::contains($object);
163
    }
164
165
    /**
166
     * Counts the elements in the storage array
167
     *
168
     * @throws Exception
169
     * @return int The number of elements in the ObjectStorage
170
     */
171
    public function count()
172
    {
173
        $columnMap = $this->dataMapper->getDataMap(get_class($this->parentObject))->getColumnMap($this->propertyName);
174
        if (!$this->isInitialized && $columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) {
175
            $numberOfElements = $this->dataMapper->countRelated($this->parentObject, $this->propertyName, $this->fieldValue);
176
        } else {
177
            $this->initialize();
178
            $numberOfElements = count($this->storage);
179
        }
180
        if ($numberOfElements === null) {
181
            throw new Exception('The number of elements could not be determined.', 1252514486);
182
        }
183
        return $numberOfElements;
184
    }
185
186
    /**
187
     * @return TEntity The object at the current iterator position.
188
     *
189
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::current
190
     */
191
    public function current()
192
    {
193
        $this->initialize();
194
        return parent::current();
195
    }
196
197
    /**
198
     * @param TEntity $object The object to remove.
199
     *
200
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::detach
201
     */
202
    public function detach($object)
203
    {
204
        $this->initialize();
205
        parent::detach($object);
206
    }
207
208
    /**
209
     * @return string The index corresponding to the position of the iterator.
210
     *
211
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::key
212
     */
213
    public function key()
214
    {
215
        $this->initialize();
216
        return parent::key();
217
    }
218
219
    /**
220
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::next
221
     */
222
    public function next()
223
    {
224
        $this->initialize();
225
        parent::next();
226
    }
227
228
    /**
229
     * @param TEntity $value The object to look for, or the key in the storage.
230
     * @return bool
231
     *
232
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::offsetExists
233
     */
234
    public function offsetExists($value)
235
    {
236
        $this->initialize();
237
        return parent::offsetExists($value);
238
    }
239
240
    /**
241
     * @param TEntity $value The object to look for, or its key in the storage.
242
     * @return mixed
243
     *
244
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::offsetGet
245
     */
246
    public function offsetGet($value)
247
    {
248
        $this->initialize();
249
        return parent::offsetGet($value);
250
    }
251
252
    /**
253
     * @param TEntity $object The object to add.
254
     * @param mixed $info The data to associate with the object.
255
     *
256
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::offsetSet
257
     */
258
    public function offsetSet($object, $info)
259
    {
260
        $this->initialize();
261
        parent::offsetSet($object, $info);
262
    }
263
264
    /**
265
     * @param TEntity $value The object to remove, or its key in the storage.
266
     *
267
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::offsetUnset
268
     */
269
    public function offsetUnset($value)
270
    {
271
        $this->initialize();
272
        parent::offsetUnset($value);
273
    }
274
275
    /**
276
     * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $storage The storage containing the elements to remove.
277
     *
278
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::removeAll
279
     */
280
    public function removeAll(ObjectStorage $storage)
281
    {
282
        $this->initialize();
283
        parent::removeAll($storage);
284
    }
285
286
    /**
287
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::rewind
288
     */
289
    public function rewind()
290
    {
291
        $this->initialize();
292
        parent::rewind();
293
    }
294
295
    /**
296
     * @return bool
297
     *
298
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::valid
299
     */
300
    public function valid()
301
    {
302
        $this->initialize();
303
        return parent::valid();
304
    }
305
306
    /**
307
     * @return array
308
     *
309
     * @see \TYPO3\CMS\Extbase\Persistence\ObjectStorage::toArray
310
     */
311
    public function toArray()
312
    {
313
        $this->initialize();
314
        return parent::toArray();
315
    }
316
317
    /**
318
     * @param mixed $object
319
     * @return int|null
320
     */
321
    public function getPosition($object)
322
    {
323
        $this->initialize();
324
        return parent::getPosition($object);
325
    }
326
}
327