Passed
Push — master ( f2e1d1...eea237 )
by Divine Niiquaye
03:30
created

DoctrineChoiceLoader::doLoadChoicesForValues()   C

Complexity

Conditions 12
Paths 22

Size

Total Lines 38
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 156

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 17
c 1
b 0
f 0
nc 22
nop 2
dl 0
loc 38
ccs 0
cts 18
cp 0
crap 156
rs 6.9666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of DivineNii opensource projects.
7
 *
8
 * PHP version 7.4 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 DivineNii (https://divinenii.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Rade\Database\Doctrine\Form\ChoiceList;
19
20
use Doctrine\Persistence\ObjectManager;
0 ignored issues
show
Bug introduced by
The type Doctrine\Persistence\ObjectManager 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...
21
use Symfony\Component\Form\ChoiceList\Loader\AbstractChoiceLoader;
22
use Symfony\Component\Form\Exception\LogicException;
23
24
/**
25
 * Loads choices using a Doctrine object manager.
26
 *
27
 * @author Bernhard Schussek <[email protected]>
28
 */
29
class DoctrineChoiceLoader extends AbstractChoiceLoader
30
{
31
    private ObjectManager $manager;
32
    private string $class;
33
    private ?IdReader $idReader;
34
    private ?EntityLoaderInterface $objectLoader;
35
36
    /**
37
     * Creates a new choice loader.
38
     *
39
     * Optionally, an implementation of {@link EntityLoaderInterface} can be
40
     * passed which optimizes the object loading for one of the Doctrine
41
     * mapper implementations.
42
     *
43
     * @param string $class The class name of the loaded objects
44
     */
45
    public function __construct(ObjectManager $manager, string $class, IdReader $idReader = null, EntityLoaderInterface $objectLoader = null)
46
    {
47
        $classMetadata = $manager->getClassMetadata($class);
48
49
        if ($idReader && !$idReader->isSingleId()) {
50
            throw new \InvalidArgumentException(\sprintf('The second argument `$idReader` of "%s" must be null when the query cannot be optimized because of composite id fields.', __METHOD__));
51
        }
52
53
        $this->manager = $manager;
54
        $this->class = $classMetadata->getName();
55
        $this->idReader = $idReader;
56
        $this->objectLoader = $objectLoader;
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62
    protected function loadChoices(): iterable
63
    {
64
        return $this->objectLoader
65
            ? $this->objectLoader->getEntities()
66
            : $this->manager->getRepository($this->class)->findAll();
67
    }
68
69
    /**
70
     * @internal to be remove in Symfony 6
71
     */
72
    protected function doLoadValuesForChoices(array $choices): array
73
    {
74
        // Optimize performance for single-field identifiers. We already
75
        // know that the IDs are used as values
76
        // Attention: This optimization does not check choices for existence
77
        if ($this->idReader) {
78
            throw new LogicException('Not defining the IdReader explicitly as a value callback when the query can be optimized is not supported.');
79
        }
80
81
        return parent::doLoadValuesForChoices($choices);
82
    }
83
84
    protected function doLoadChoicesForValues(array $values, ?callable $value): array
85
    {
86
        if ($this->idReader && null === $value) {
87
            throw new LogicException('Not defining the IdReader explicitly as a value callback when the query can be optimized is not supported.');
88
        }
89
90
        $idReader = null;
91
92
        if (\is_array($value) && $value[0] instanceof IdReader) {
93
            $idReader = $value[0];
94
        } elseif ($value instanceof \Closure && ($rThis = (new \ReflectionFunction($value))->getClosureThis()) instanceof IdReader) {
95
            $idReader = $rThis;
96
        }
97
98
        // Optimize performance in case we have an object loader and
99
        // a single-field identifier
100
        if ($idReader && $this->objectLoader) {
101
            $objects = [];
102
            $objectsById = [];
103
104
            // Maintain order and indices from the given $values
105
            // An alternative approach to the following loop is to add the
106
            // "INDEX BY" clause to the Doctrine query in the loader,
107
            // but I'm not sure whether that's doable in a generic fashion.
108
            foreach ($this->objectLoader->getEntitiesByIds($idReader->getIdField(), $values) as $object) {
109
                $objectsById[$idReader->getIdValue($object)] = $object;
110
            }
111
112
            foreach ($values as $i => $id) {
113
                if (isset($objectsById[$id])) {
114
                    $objects[$i] = $objectsById[$id];
115
                }
116
            }
117
118
            return $objects;
119
        }
120
121
        return parent::doLoadChoicesForValues($values, $value);
122
    }
123
}
124