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

ORMQueryBuilderLoader::getEntitiesByIds()   C

Complexity

Conditions 12
Paths 12

Size

Total Lines 69
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 156

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 39
c 1
b 0
f 0
nc 12
nop 2
dl 0
loc 69
ccs 0
cts 40
cp 0
crap 156
rs 6.9666

How to fix   Long Method    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\DBAL\Connection;
0 ignored issues
show
Bug introduced by
The type Doctrine\DBAL\Connection 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 Doctrine\DBAL\Types\ConversionException;
0 ignored issues
show
Bug introduced by
The type Doctrine\DBAL\Types\ConversionException 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...
22
use Doctrine\DBAL\Types\Type;
0 ignored issues
show
Bug introduced by
The type Doctrine\DBAL\Types\Type 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...
23
use Doctrine\ORM\QueryBuilder;
0 ignored issues
show
Bug introduced by
The type Doctrine\ORM\QueryBuilder 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...
24
use Symfony\Component\Form\Exception\TransformationFailedException;
25
26
/**
27
 * Loads entities using a {@link QueryBuilder} instance.
28
 *
29
 * @author Benjamin Eberlei <[email protected]>
30
 * @author Bernhard Schussek <[email protected]>
31
 */
32
class ORMQueryBuilderLoader implements EntityLoaderInterface
33
{
34
    /**
35
     * Contains the query builder that builds the query for fetching the
36
     * entities.
37
     *
38
     * This property should only be accessed through queryBuilder.
39
     */
40
    private $queryBuilder;
41
42
    public function __construct(QueryBuilder $queryBuilder)
43
    {
44
        $this->queryBuilder = $queryBuilder;
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50
    public function getEntities(): array
51
    {
52
        return $this->queryBuilder->getQuery()->execute();
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function getEntitiesByIds(string $identifier, array $values): array
59
    {
60
        if (null !== $this->queryBuilder->getMaxResults() || 0 < (int) $this->queryBuilder->getFirstResult()) {
61
            // an offset or a limit would apply on results including the where clause with submitted id values
62
            // that could make invalid choices valid
63
            $choices = [];
64
            $metadata = $this->queryBuilder->getEntityManager()->getClassMetadata(\current($this->queryBuilder->getRootEntities()));
65
66
            foreach ($this->getEntities() as $entity) {
67
                if (\in_array((string) \current($metadata->getIdentifierValues($entity)), $values, true)) {
68
                    $choices[] = $entity;
69
                }
70
            }
71
72
            return $choices;
73
        }
74
75
        $qb = clone $this->queryBuilder;
76
        $alias = \current($qb->getRootAliases());
77
        $parameter = 'ORMQueryBuilderLoader_getEntitiesByIds_' . $identifier;
78
        $parameter = \str_replace('.', '_', $parameter);
79
        $where = $qb->expr()->in($alias . '.' . $identifier, ':' . $parameter);
80
81
        // Guess type
82
        $entity = \current($qb->getRootEntities());
83
        $metadata = $qb->getEntityManager()->getClassMetadata($entity);
84
85
        if (\in_array($type = $metadata->getTypeOfField($identifier), ['integer', 'bigint', 'smallint'])) {
86
            $parameterType = Connection::PARAM_INT_ARRAY;
87
88
            // Filter out non-integer values (e.g. ""). If we don't, some
89
            // databases such as PostgreSQL fail.
90
            $values = \array_values(\array_filter($values, function ($v) {
91
                return (string) $v === (string) (int) $v || \ctype_digit($v);
92
            }));
93
        } elseif (\in_array($type, ['ulid', 'uuid', 'guid'])) {
94
            $parameterType = Connection::PARAM_STR_ARRAY;
95
96
            // Like above, but we just filter out empty strings.
97
            $values = \array_values(\array_filter($values, function ($v) {
98
                return '' !== (string) $v;
99
            }));
100
101
            // Convert values into right type
102
            if (Type::hasType($type)) {
103
                $doctrineType = Type::getType($type);
104
                $platform = $qb->getEntityManager()->getConnection()->getDatabasePlatform();
105
106
                foreach ($values as &$value) {
107
                    try {
108
                        $value = $doctrineType->convertToDatabaseValue($value, $platform);
109
                    } catch (ConversionException $e) {
110
                        throw new TransformationFailedException(\sprintf('Failed to transform "%s" into "%s".', $value, $type), 0, $e);
111
                    }
112
                }
113
                unset($value);
114
            }
115
        } else {
116
            $parameterType = Connection::PARAM_STR_ARRAY;
117
        }
118
119
        if (!$values) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $values of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
120
            return [];
121
        }
122
123
        return $qb->andWhere($where)
124
                  ->getQuery()
125
                  ->setParameter($parameter, $values, $parameterType)
126
                  ->getResult();
127
    }
128
}
129