Completed
Push — master ( c341b6...280bd5 )
by Rafael
04:24
created

NodeFilter::applyFilter()   B

Complexity

Conditions 11
Paths 45

Size

Total Lines 38
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 11.0908

Importance

Changes 0
Metric Value
eloc 29
dl 0
loc 38
ccs 20
cts 22
cp 0.9091
rs 7.3166
c 0
b 0
f 0
cc 11
nc 45
nop 5
crap 11.0908

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
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Filter\Common;
12
13
use Doctrine\ORM\Mapping\ClassMetadataInfo;
14
use Doctrine\ORM\QueryBuilder;
15
use Ynlo\GraphQLBundle\Filter\FilterContext;
16
use Ynlo\GraphQLBundle\Filter\FilterInterface;
17
use Ynlo\GraphQLBundle\Model\Filter\NodeComparisonExpression;
18
use Ynlo\GraphQLBundle\Model\NodeInterface;
19
use Ynlo\GraphQLBundle\Type\NodeComparisonOperatorType;
20
21
/**
22
 * Node filter to filter by related nodes
23
 */
24
class NodeFilter implements FilterInterface
25
{
26
    /**
27
     * @inheritDoc
28
     */
29 7
    public function __invoke(FilterContext $context, QueryBuilder $qb, $condition)
30
    {
31 7
        if (!$condition instanceof NodeComparisonExpression) {
32 1
            throw new \RuntimeException('Invalid filter condition');
33
        }
34
35 6
        if (!$context->getField() || !$context->getField()->getName()) {
36 1
            throw new \RuntimeException('There are not valid field related to this filter.');
37
        }
38
39 5
        $entity = $context->getNode()->getClass();
0 ignored issues
show
Bug introduced by
The method getClass() does not exist on Ynlo\GraphQLBundle\Defin...wareDefinitionInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Ynlo\GraphQLBundle\Definition\ImplementorInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

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

39
        $entity = $context->getNode()->/** @scrutinizer ignore-call */ getClass();
Loading history...
40 5
        $metadata = $qb->getEntityManager()->getClassMetadata($entity);
41 5
        $column = $context->getField()->getOriginName();
42 5
        if ($context->getField()->getOriginType() === 'ReflectionMethod') {
43
            $column = $context->getField()->getName();
44
        }
45
46 5
        if (!$metadata->hasAssociation($column)) {
47 1
            throw new \RuntimeException(sprintf('There are not valid association in %s called %s.', $entity, $column));
48
        }
49
50 4
        $association = $metadata->getAssociationMapping($column);
51
52 4
        $alias = $qb->getRootAliases()[0];
53
54 4
        $this->applyFilter($qb, $association['type'], $alias, $column, $condition);
55 4
    }
56
57
    /**
58
     * @param QueryBuilder             $qb
59
     * @param string                   $assocType
60
     * @param string                   $alias
61
     * @param string                   $column
62
     * @param NodeComparisonExpression $condition
63
     */
64 4
    protected function applyFilter(QueryBuilder $qb, $assocType, $alias, $column, NodeComparisonExpression $condition): void
65
    {
66 4
        $ids = [];
67 4
        foreach ($condition->getNodes() as $node) {
68 4
            if ($node instanceof NodeInterface) {
69 4
                $ids[] = $node->getId();
70
            }
71
        }
72 4
        $ids = array_filter($ids);
73
74 4
        switch ($assocType) {
75
            case ClassMetadataInfo::MANY_TO_ONE:
76
            case ClassMetadataInfo::ONE_TO_ONE:
77
            case ClassMetadataInfo::ONE_TO_MANY:
78 2
                if ($condition->getOp() === NodeComparisonOperatorType::IN) {
79 1
                    if (empty($ids)) {
80
                        $qb->andWhere($qb->expr()->isNull("{$alias}.{$column}"));
81
                    } else {
82 1
                        $qb->andWhere($qb->expr()->in("{$alias}.{$column}", $ids));
83
                    }
84
                } else {
85 1
                    if (empty($ids)) {
86
                        $qb->andWhere($qb->expr()->isNotNull("{$alias}.{$column}"));
87
                    } else {
88 1
                        $qb->andWhere($qb->expr()->notIn("{$alias}.{$column}", $ids));
89
                    }
90
                }
91 2
                break;
92
            case ClassMetadataInfo::MANY_TO_MANY:
93 2
                $paramName = sprintf('%s_ids_%s', $column, mt_rand());
94 2
                if ($condition->getOp() === NodeComparisonOperatorType::IN) {
95 1
                    $qb->andWhere(sprintf(':%s MEMBER OF %s.%s', $paramName, $alias, $column))
96 1
                       ->setParameter($paramName, $ids);
97
                } else {
98 1
                    $qb->andWhere(sprintf(':%s NOT MEMBER OF %s.%s', $paramName, $alias, $column))
99 1
                       ->setParameter($paramName, $ids);
100
                }
101 2
                break;
102
        }
103 4
    }
104
}
105