Completed
Push — master ( 2975e7...46c3ee )
by Rafael
07:49
created

NodeFilter   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 55
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 13
dl 0
loc 55
ccs 33
cts 33
cp 1
rs 10
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
C __invoke() 0 50 13
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();
40 5
        $metadata = $qb->getEntityManager()->getClassMetadata($entity);
41 5
        $column = $context->getField()->getOriginName();
42
43 5
        if (!$metadata->hasAssociation($column)) {
44 1
            throw new \RuntimeException(sprintf('There are not valid association in %s called %s.', $entity, $column));
45
        }
46
47 4
        $association = $metadata->getAssociationMapping($column);
48
49 4
        $ids = [];
50 4
        foreach ($condition->getNodes() as $node) {
51 4
            if ($node instanceof NodeInterface) {
52 4
                $ids[] = $node->getId();
53
            }
54
        }
55 4
        $ids = array_filter($ids);
56
57 4
        $alias = $qb->getRootAliases()[0];
58
59 4
        switch ($association['type']) {
60 4
            case ClassMetadataInfo::MANY_TO_ONE:
61 2
            case ClassMetadataInfo::ONE_TO_ONE:
62 2
            case ClassMetadataInfo::ONE_TO_MANY:
63 2
                if ($condition->getOp() === NodeComparisonOperatorType::IN) {
64 1
                    $qb->andWhere($qb->expr()->in("{$alias}.{$column}", $ids));
65
                } else {
66 1
                    $qb->andWhere($qb->expr()->notIn("{$alias}.{$column}", $ids));
67
                }
68 2
                break;
69 2
            case ClassMetadataInfo::MANY_TO_MANY:
70 2
                $paramName = sprintf('%s_ids_%s', $column, mt_rand());
71 2
                if ($condition->getOp() === NodeComparisonOperatorType::IN) {
72 1
                    $qb->andWhere(sprintf(':%s MEMBER OF %s.%s', $paramName, $alias, $column))
73 1
                       ->setParameter($paramName, $ids);
74
                } else {
75 1
                    $qb->andWhere(sprintf(':%s NOT MEMBER OF %s.%s', $paramName, $alias, $column))
76 1
                       ->setParameter($paramName, $ids);
77
                }
78 2
                break;
79
        }
80 4
    }
81
}
82