Passed
Push — master ( c39fb6...9e9a0d )
by Rafael
04:42
created

AllNodesWithPagination::__invoke()   C

Complexity

Conditions 9
Paths 20

Size

Total Lines 51
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 13.5293

Importance

Changes 0
Metric Value
cc 9
eloc 33
nc 20
nop 1
dl 0
loc 51
ccs 21
cts 34
cp 0.6176
crap 13.5293
rs 6.2727
c 0
b 0
f 0

How to fix   Long Method   

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\Query\Node;
12
13
use Doctrine\ORM\QueryBuilder;
14
use GraphQL\Error\Error;
15
use Ynlo\GraphQLBundle\Definition\Extension\PaginationDefinitionExtension;
16
use Ynlo\GraphQLBundle\Extension\ExtensionManager;
17
use Ynlo\GraphQLBundle\Model\ConnectionInterface;
18
use Ynlo\GraphQLBundle\Model\NodeConnection;
19
use Ynlo\GraphQLBundle\Model\NodeInterface;
20
use Ynlo\GraphQLBundle\Pagination\DoctrineCursorPaginatorInterface;
21
use Ynlo\GraphQLBundle\Pagination\DoctrineOffsetCursorPaginator;
22
use Ynlo\GraphQLBundle\Pagination\PaginationRequest;
23
24
/**
25
 * Base class to fetch nodes
26
 */
27
class AllNodesWithPagination extends AllNodes
28
{
29
    /**
30
     * @param array[] $args
31
     *
32
     * @return mixed
33
     *
34
     * @throws Error
35
     */
36 10
    public function __invoke($args = [])
37
    {
38 10
        $orderBy = $args['orderBy'] ?? [];
39 10
        $first = $args['first'] ?? null;
40 10
        $last = $args['last'] ?? null;
41 10
        $before = $args['before'] ?? null;
42 10
        $after = $args['after'] ?? null;
43
44 10
        $this->initialize();
45
46 10
        $qb = $this->createQuery();
47 10
        $this->applyOrderBy($qb, $orderBy);
48
49 10
        if ($this->getContext()->getRoot()) {
50 3
            $this->applyFilterByParent($qb, $this->getContext()->getRoot());
51
        }
52
53 10
        $this->configureQuery($qb);
54 10
        foreach ($this->container->get(ExtensionManager::class)->getExtensions() as $extension) {
55
            $extension->configureQuery($qb, $this, $this->context);
56
        }
57
58 10
        if (!$first && !$last) {
59
            $error = sprintf('You must provide a `first` or `last` value to properly paginate records in "%s" connection.', $this->queryDefinition->getName());
60
            throw new Error($error);
61
        }
62
63 10
        if ($this->queryDefinition->hasMeta('pagination')) {
64 10
            $limitAllowed = $this->queryDefinition->getMeta('pagination')['limit'];
65
66 10
            if ($first > $limitAllowed || $last > $limitAllowed) {
67
                $current = $first ?? $last;
68
                $where = $first ? 'first' : 'last';
69
                $error = sprintf(
70
                    'Requesting %s records for `%s` exceeds the `%s` limit of %s records for "%s" connection',
71
                    $current,
72
                    $this->queryDefinition->getName(),
73
                    $where,
74
                    $limitAllowed,
75
                    $this->queryDefinition->getName()
76
                );
77
                throw new Error($error);
78
            }
79
        }
80
81 10
        $paginator = $this->createPaginator();
82
83 10
        $connection = $this->createConnection();
84 10
        $paginator->paginate($qb, new PaginationRequest($first, $last, $after, $before), $connection);
85
86 10
        return $connection;
87
    }
88
89
    /**
90
     * @return ConnectionInterface
91
     */
92 10
    protected function createConnection(): ConnectionInterface
93
    {
94 10
        return new NodeConnection();
95
    }
96
97
    /**
98
     * @return DoctrineCursorPaginatorInterface
99
     */
100 10
    protected function createPaginator(): DoctrineCursorPaginatorInterface
101
    {
102 10
        return new DoctrineOffsetCursorPaginator();
103
    }
104
105
    /**
106
     * @param QueryBuilder  $qb
107
     * @param NodeInterface $root
108
     */
109 3
    protected function applyFilterByParent(QueryBuilder $qb, NodeInterface $root)
110
    {
111 3
        $parentField = null;
112 3
        if ($this->queryDefinition->hasMeta('pagination')) {
113 3
            $parentField = $this->queryDefinition->getMeta('pagination')['parent_field'] ?? null;
114
        }
115 3
        if (!$parentField) {
116
            throw new \RuntimeException(
117
                sprintf(
118
                    'Missing parent field to filter "%s" by given parent.
119
             The "parent_field" should be specified.',
120
                    $this->queryDefinition->getName()
121
                )
122
            );
123
        }
124
125 3
        if ($this->objectDefinition->hasField($parentField)) {
126 3
            $parentField = $this->objectDefinition->getField($parentField)->getOriginName();
127
        }
128
129 3
        $paramName = 'root'.mt_rand();
0 ignored issues
show
Bug introduced by
The call to mt_rand() has too few arguments starting with min. ( Ignorable by Annotation )

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

129
        $paramName = 'root'./** @scrutinizer ignore-call */ mt_rand();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
130 3
        if ($this->queryDefinition->getMeta('pagination')['parent_relation'] === PaginationDefinitionExtension::MANY_TO_MANY) {
131 2
            $qb->andWhere(sprintf(':%s MEMBER OF %s.%s', $paramName, $this->queryAlias, $parentField))
132 2
               ->setParameter($paramName, $root);
133
        } else {
134 1
            $qb->andWhere(sprintf('%s.%s = :%s', $this->queryAlias, $parentField, $paramName))
135 1
               ->setParameter($paramName, $root);
136
        }
137 3
    }
138
}
139