Completed
Pull Request — master (#1331)
by Maciej
10:31
created

HydratorFactory   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 429
Duplicated Lines 13.05 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 83.64%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 45
lcom 1
cbo 8
dl 56
loc 429
ccs 138
cts 165
cp 0.8364
rs 8.3673
c 3
b 1
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 3
A setUnitOfWork() 0 4 1
C getHydratorFor() 0 36 8
D generateHydratorClass() 47 228 20
D hydrate() 9 40 10
A generateHydratorClasses() 0 10 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like HydratorFactory often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use HydratorFactory, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ODM\MongoDB\Hydrator;
21
22
use Doctrine\Common\EventManager;
23
use Doctrine\ODM\MongoDB\DocumentManager;
24
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
25
use Doctrine\ODM\MongoDB\Event\PreLoadEventArgs;
26
use Doctrine\ODM\MongoDB\Events;
27
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
28
use Doctrine\ODM\MongoDB\Proxy\Proxy;
29
use Doctrine\ODM\MongoDB\Types\Type;
30
use Doctrine\ODM\MongoDB\UnitOfWork;
31
use Doctrine\ODM\MongoDB\Configuration;
32
33
/**
34
 * The HydratorFactory class is responsible for instantiating a correct hydrator
35
 * type based on document's ClassMetadata
36
 *
37
 * @since       1.0
38
 * @author      Jonathan H. Wage <[email protected]>
39
 */
40
class HydratorFactory
41
{
42
    /**
43
     * The DocumentManager this factory is bound to.
44
     *
45
     * @var \Doctrine\ODM\MongoDB\DocumentManager
46
     */
47
    private $dm;
48
49
    /**
50
     * The UnitOfWork used to coordinate object-level transactions.
51
     *
52
     * @var \Doctrine\ODM\MongoDB\UnitOfWork
53
     */
54
    private $unitOfWork;
55
56
    /**
57
     * The EventManager associated with this Hydrator
58
     *
59
     * @var \Doctrine\Common\EventManager
60
     */
61
    private $evm;
62
63
    /**
64
     * Which algorithm to use to automatically (re)generate hydrator classes.
65
     *
66
     * @var integer
67
     */
68
    private $autoGenerate;
69
70
    /**
71
     * The namespace that contains all hydrator classes.
72
     *
73
     * @var string
74
     */
75
    private $hydratorNamespace;
76
77
    /**
78
     * The directory that contains all hydrator classes.
79
     *
80
     * @var string
81
     */
82
    private $hydratorDir;
83
84
    /**
85
     * Array of instantiated document hydrators.
86
     *
87
     * @var array
88
     */
89
    private $hydrators = array();
90
91
    /**
92
     * @param DocumentManager $dm
93
     * @param EventManager $evm
94
     * @param string $hydratorDir
95
     * @param string $hydratorNs
96
     * @param integer $autoGenerate
97
     * @throws HydratorException
98
     */
99 931
    public function __construct(DocumentManager $dm, EventManager $evm, $hydratorDir, $hydratorNs, $autoGenerate)
100
    {
101 931
        if ( ! $hydratorDir) {
102
            throw HydratorException::hydratorDirectoryRequired();
103
        }
104 931
        if ( ! $hydratorNs) {
105
            throw HydratorException::hydratorNamespaceRequired();
106
        }
107 931
        $this->dm = $dm;
108 931
        $this->evm = $evm;
109 931
        $this->hydratorDir = $hydratorDir;
110 931
        $this->hydratorNamespace = $hydratorNs;
111 931
        $this->autoGenerate = $autoGenerate;
112 931
    }
113
114
    /**
115
     * Sets the UnitOfWork instance.
116
     *
117
     * @param UnitOfWork $uow
118
     */
119 931
    public function setUnitOfWork(UnitOfWork $uow)
120
    {
121 931
        $this->unitOfWork = $uow;
122 931
    }
123
124
    /**
125
     * Gets the hydrator object for the given document class.
126
     *
127
     * @param string $className
128
     * @return \Doctrine\ODM\MongoDB\Hydrator\HydratorInterface $hydrator
129
     */
130 345
    public function getHydratorFor($className)
131
    {
132 345
        if (isset($this->hydrators[$className])) {
133 99
            return $this->hydrators[$className];
134
        }
135 345
        $hydratorClassName = str_replace('\\', '', $className) . 'Hydrator';
136 345
        $fqn = $this->hydratorNamespace . '\\' . $hydratorClassName;
137 345
        $class = $this->dm->getClassMetadata($className);
138
139 345
        if ( ! class_exists($fqn, false)) {
140 158
            $fileName = $this->hydratorDir . DIRECTORY_SEPARATOR . $hydratorClassName . '.php';
141 158
            switch ($this->autoGenerate) {
142 158
                case Configuration::AUTOGENERATE_NEVER:
143
                    require $fileName;
144
                    break;
145
                    
146 158
                case Configuration::AUTOGENERATE_ALWAYS:
147 158
                    $this->generateHydratorClass($class, $hydratorClassName, $fileName);
148 158
                    require $fileName;
149 158
                    break;
150
                    
151
                case Configuration::AUTOGENERATE_FILE_NOT_EXISTS:
152
                    if (!file_exists($fileName)) {
153
                        $this->generateHydratorClass($class, $hydratorClassName, $fileName);
154
                    }
155
                    require $fileName;
156
                    break;
157
                    
158
                case Configuration::AUTOGENERATE_EVAL:
159
                    $this->generateHydratorClass($class, $hydratorClassName, false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
160
                    break;
161 158
            }
162 158
        }
163 345
        $this->hydrators[$className] = new $fqn($this->dm, $this->unitOfWork, $class);
164 345
        return $this->hydrators[$className];
165
    }
166
167
    /**
168
     * Generates hydrator classes for all given classes.
169
     *
170
     * @param array $classes The classes (ClassMetadata instances) for which to generate hydrators.
171
     * @param string $toDir The target directory of the hydrator classes. If not specified, the
172
     *                      directory configured on the Configuration of the DocumentManager used
173
     *                      by this factory is used.
174
     */
175 1
    public function generateHydratorClasses(array $classes, $toDir = null)
176 1
    {
177
        $hydratorDir = $toDir ?: $this->hydratorDir;
178
        $hydratorDir = rtrim($hydratorDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
179
        foreach ($classes as $class) {
180
            $hydratorClassName = str_replace('\\', '', $class->name) . 'Hydrator';
181
            $hydratorFileName = $hydratorDir . $hydratorClassName . '.php';
182
            $this->generateHydratorClass($class, $hydratorClassName, $hydratorFileName);
183
        }
184
    }
185
186
    /**
187
     * @param ClassMetadata $class
188
     * @param string $hydratorClassName
189
     * @param string $fileName
190
     */
191 158
    private function generateHydratorClass(ClassMetadata $class, $hydratorClassName, $fileName)
192
    {
193 158
        $code = '';
194
195 158
        foreach ($class->fieldMappings as $fieldName => $mapping) {
196 158
            if (isset($mapping['alsoLoadFields'])) {
197 4
                foreach ($mapping['alsoLoadFields'] as $name) {
198 4
                    $code .= sprintf(<<<EOF
199
200
        /** @AlsoLoad("$name") */
201 4
        if (!array_key_exists('%1\$s', \$data) && array_key_exists('$name', \$data)) {
202 4
            \$data['%1\$s'] = \$data['$name'];
203
        }
204
205
EOF
206 4
                        ,
207 4
                        $mapping['name']
208 4
                    );
209 4
                }
210 4
            }
211
212 158
            if ($mapping['type'] === 'date') {
213 8
                $code .= sprintf(<<<EOF
214
215
        /** @Field(type="date") */
216
        if (isset(\$data['%1\$s'])) {
217
            \$value = \$data['%1\$s'];
218
            %3\$s
219
            \$this->class->reflFields['%2\$s']->setValue(\$document, clone \$return);
220
            \$hydratedData['%2\$s'] = \$return;
221
        }
222
223
EOF
224 8
                    ,
225 8
                    $mapping['name'],
226 8
                    $mapping['fieldName'],
227 8
                    Type::getType($mapping['type'])->closureToPHP()
228 8
                );
229
230
231 158
            } elseif ( ! isset($mapping['association'])) {
232 158
                $code .= sprintf(<<<EOF
233
234 158
        /** @Field(type="{$mapping['type']}") */
235
        if (isset(\$data['%1\$s'])) {
236
            \$value = \$data['%1\$s'];
237
            %3\$s
238
            \$this->class->reflFields['%2\$s']->setValue(\$document, \$return);
239
            \$hydratedData['%2\$s'] = \$return;
240
        }
241
242
EOF
243 158
                    ,
244 158
                    $mapping['name'],
245 158
                    $mapping['fieldName'],
246 158
                    Type::getType($mapping['type'])->closureToPHP()
247 158
                );
248 158 View Code Duplication
            } elseif ($mapping['association'] === ClassMetadata::REFERENCE_ONE && $mapping['isOwningSide']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
249 42
                $code .= sprintf(<<<EOF
250
251
        /** @ReferenceOne */
252
        if (isset(\$data['%1\$s'])) {
253
            \$reference = \$data['%1\$s'];
254
            if (isset(\$this->class->fieldMappings['%2\$s']['simple']) && \$this->class->fieldMappings['%2\$s']['simple']) {
255
                \$className = \$this->class->fieldMappings['%2\$s']['targetDocument'];
256
                \$mongoId = \$reference;
257
            } else {
258
                \$className = \$this->unitOfWork->getClassNameForAssociation(\$this->class->fieldMappings['%2\$s'], \$reference);
259
                \$mongoId = \$reference['\$id'];
260
            }
261
            \$targetMetadata = \$this->dm->getClassMetadata(\$className);
262
            \$id = \$targetMetadata->getPHPIdentifierValue(\$mongoId);
263
            \$return = \$this->dm->getReference(\$className, \$id);
264
            \$this->class->reflFields['%2\$s']->setValue(\$document, \$return);
265
            \$hydratedData['%2\$s'] = \$return;
266
        }
267
268
EOF
269 42
                    ,
270 42
                    $mapping['name'],
271 42
                    $mapping['fieldName']
272 42
                );
273 104
            } elseif ($mapping['association'] === ClassMetadata::REFERENCE_ONE && $mapping['isInverseSide']) {
274 5
                if (isset($mapping['repositoryMethod']) && $mapping['repositoryMethod']) {
275 1
                    $code .= sprintf(<<<EOF
276
277
        \$className = \$this->class->fieldMappings['%2\$s']['targetDocument'];
278
        \$return = \$this->dm->getRepository(\$className)->%3\$s(\$document);
279
        \$this->class->reflFields['%2\$s']->setValue(\$document, \$return);
280
        \$hydratedData['%2\$s'] = \$return;
281
282
EOF
283 1
                        ,
284 1
                        $mapping['name'],
285 1
                        $mapping['fieldName'],
286 1
                        $mapping['repositoryMethod']
287 1
                    );
288 1
                } else {
289 5
                    $code .= sprintf(<<<EOF
290
291
        \$mapping = \$this->class->fieldMappings['%2\$s'];
292
        \$className = \$mapping['targetDocument'];
293
        \$targetClass = \$this->dm->getClassMetadata(\$mapping['targetDocument']);
294
        \$mappedByMapping = \$targetClass->fieldMappings[\$mapping['mappedBy']];
295
        \$mappedByFieldName = isset(\$mappedByMapping['simple']) && \$mappedByMapping['simple'] ? \$mapping['mappedBy'] : \$mapping['mappedBy'].'.\$id';
296
        \$criteria = array_merge(
297
            array(\$mappedByFieldName => \$data['_id']),
298
            isset(\$this->class->fieldMappings['%2\$s']['criteria']) ? \$this->class->fieldMappings['%2\$s']['criteria'] : array()
299
        );
300
        \$sort = isset(\$this->class->fieldMappings['%2\$s']['sort']) ? \$this->class->fieldMappings['%2\$s']['sort'] : array();
301
        \$return = \$this->unitOfWork->getDocumentPersister(\$className)->load(\$criteria, null, array(), 0, \$sort);
302
        \$this->class->reflFields['%2\$s']->setValue(\$document, \$return);
303
        \$hydratedData['%2\$s'] = \$return;
304
305
EOF
306 5
                        ,
307 5
                        $mapping['name'],
308 5
                        $mapping['fieldName']
309 5
                    );
310
                }
311 85 View Code Duplication
            } elseif ($mapping['association'] === ClassMetadata::REFERENCE_MANY || $mapping['association'] === ClassMetadata::EMBED_MANY) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
312 66
                $code .= sprintf(<<<EOF
313
314
        /** @Many */
315
        \$mongoData = isset(\$data['%1\$s']) ? \$data['%1\$s'] : null;
316
        \$return = new \Doctrine\ODM\MongoDB\PersistentCollection(new \Doctrine\Common\Collections\ArrayCollection(), \$this->dm, \$this->unitOfWork);
317
        \$return->setHints(\$hints);
318
        \$return->setOwner(\$document, \$this->class->fieldMappings['%2\$s']);
319
        \$return->setInitialized(false);
320
        if (\$mongoData) {
321
            \$return->setMongoData(\$mongoData);
322
        }
323
        \$this->class->reflFields['%2\$s']->setValue(\$document, \$return);
324
        \$hydratedData['%2\$s'] = \$return;
325
326
EOF
327 66
                    ,
328 66
                    $mapping['name'],
329 66
                    $mapping['fieldName']
330 66
                );
331 84
            } elseif ($mapping['association'] === ClassMetadata::EMBED_ONE) {
332 35
                $code .= sprintf(<<<EOF
333
334
        /** @EmbedOne */
335
        if (isset(\$data['%1\$s'])) {
336
            \$embeddedDocument = \$data['%1\$s'];
337
            \$className = \$this->unitOfWork->getClassNameForAssociation(\$this->class->fieldMappings['%2\$s'], \$embeddedDocument);
338
            \$embeddedMetadata = \$this->dm->getClassMetadata(\$className);
339
            \$return = \$embeddedMetadata->newInstance();
340
341
            \$this->unitOfWork->setParentAssociation(\$return, \$this->class->fieldMappings['%2\$s'], \$document, '%1\$s');
342
343
            \$embeddedData = \$this->dm->getHydratorFactory()->hydrate(\$return, \$embeddedDocument, \$hints);
344
            \$embeddedId = \$embeddedMetadata->identifier && isset(\$embeddedData[\$embeddedMetadata->identifier]) ? \$embeddedData[\$embeddedMetadata->identifier] : null;
345
346
            \$this->unitOfWork->registerManaged(\$return, \$embeddedId, \$embeddedData);
347
348
            \$this->class->reflFields['%2\$s']->setValue(\$document, \$return);
349
            \$hydratedData['%2\$s'] = \$return;
350
        }
351
352
EOF
353 35
                    ,
354 35
                    $mapping['name'],
355 35
                    $mapping['fieldName']
356 35
                );
357 35
            }
358 158
        }
359
360 158
        $namespace = $this->hydratorNamespace;
361 158
        $code = sprintf(<<<EOF
362
<?php
363
364
namespace $namespace;
365
366
use Doctrine\ODM\MongoDB\DocumentManager;
367
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
368
use Doctrine\ODM\MongoDB\Hydrator\HydratorInterface;
369
use Doctrine\ODM\MongoDB\UnitOfWork;
370
371
/**
372
 * THIS CLASS WAS GENERATED BY THE DOCTRINE ODM. DO NOT EDIT THIS FILE.
373
 */
374 158
class $hydratorClassName implements HydratorInterface
375
{
376
    private \$dm;
377
    private \$unitOfWork;
378
    private \$class;
379
380
    public function __construct(DocumentManager \$dm, UnitOfWork \$uow, ClassMetadata \$class)
381
    {
382
        \$this->dm = \$dm;
383
        \$this->unitOfWork = \$uow;
384
        \$this->class = \$class;
385
    }
386
387
    public function hydrate(\$document, \$data, array \$hints = array())
388
    {
389
        \$hydratedData = array();
390
%s        return \$hydratedData;
391
    }
392 158
}
393
EOF
394 158
            ,
395
            $code
396 158
        );
397
398 158
        if ($fileName === false) {
399
            if ( ! class_exists($namespace . '\\' . $hydratorClassName)) {
400
                eval(substr($code, 5));
401
            }
402
        } else {
403 158
            $parentDirectory = dirname($fileName);
404
405 158
            if ( ! is_dir($parentDirectory) && (false === @mkdir($parentDirectory, 0775, true))) {
406
                throw HydratorException::hydratorDirectoryNotWritable();
407
            }
408
409 158
            if ( ! is_writable($parentDirectory)) {
410
                throw HydratorException::hydratorDirectoryNotWritable();
411
            }
412
413 158
            $tmpFileName = $fileName . '.' . uniqid('', true);
414 158
            file_put_contents($tmpFileName, $code);
415 158
            rename($tmpFileName, $fileName);
416 158
            chmod($fileName, 0664);
417
        }
418 158
    }
419
420
    /**
421
     * Hydrate array of MongoDB document data into the given document object.
422
     *
423
     * @param object $document  The document object to hydrate the data into.
424
     * @param array $data The array of document data.
425
     * @param array $hints Any hints to account for during reconstitution/lookup of the document.
426
     * @return array $values The array of hydrated values.
427
     */
428 345
    public function hydrate($document, $data, array $hints = array())
429
    {
430 345
        $metadata = $this->dm->getClassMetadata(get_class($document));
431
        // Invoke preLoad lifecycle events and listeners
432 345
        if ( ! empty($metadata->lifecycleCallbacks[Events::preLoad])) {
433 10
            $args = array(new PreLoadEventArgs($document, $this->dm, $data));
434 10
            $metadata->invokeLifecycleCallbacks(Events::preLoad, $document, $args);
435 10
        }
436 345 View Code Duplication
        if ($this->evm->hasListeners(Events::preLoad)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
437 2
            $this->evm->dispatchEvent(Events::preLoad, new PreLoadEventArgs($document, $this->dm, $data));
438 2
        }
439
440
        // alsoLoadMethods may transform the document before hydration
441 345
        if ( ! empty($metadata->alsoLoadMethods)) {
442 12
            foreach ($metadata->alsoLoadMethods as $method => $fieldNames) {
443 12
                foreach ($fieldNames as $fieldName) {
444
                    // Invoke the method only once for the first field we find
445 12
                    if (array_key_exists($fieldName, $data)) {
446 8
                        $document->$method($data[$fieldName]);
447 8
                        continue 2;
448
                    }
449 10
                }
450 12
            }
451 12
        }
452
453 345
        $data = $this->getHydratorFor($metadata->name)->hydrate($document, $data, $hints);
454 345
        if ($document instanceof Proxy) {
455 56
            $document->__isInitialized__ = true;
0 ignored issues
show
Bug introduced by
Accessing __isInitialized__ on the interface Doctrine\ODM\MongoDB\Proxy\Proxy suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
456 56
        }
457
458
        // Invoke the postLoad lifecycle callbacks and listeners
459 345 View Code Duplication
        if ( ! empty($metadata->lifecycleCallbacks[Events::postLoad])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
460 9
            $metadata->invokeLifecycleCallbacks(Events::postLoad, $document, array(new LifecycleEventArgs($document, $this->dm)));
461 9
        }
462 345 View Code Duplication
        if ($this->evm->hasListeners(Events::postLoad)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
463 3
            $this->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($document, $this->dm));
464 3
        }
465
466 345
        return $data;
467
    }
468
}
469