Passed
Push — master ( 1bf4f0...5a65ca )
by Rafael
09:05
created

PaginationDefinitionExtension::configure()   D

Complexity

Conditions 10
Paths 50

Size

Total Lines 120
Code Lines 91

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 87
CRAP Score 10.0085

Importance

Changes 0
Metric Value
dl 0
loc 120
ccs 87
cts 91
cp 0.956
rs 4.8196
c 0
b 0
f 0
cc 10
eloc 91
nc 50
nop 3
crap 10.0085

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
 *  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\Definition\Extension;
12
13
use Doctrine\Common\Annotations\Reader;
14
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
15
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
16
use Ynlo\GraphQLBundle\Definition\ArgumentDefinition;
17
use Ynlo\GraphQLBundle\Definition\DefinitionInterface;
18
use Ynlo\GraphQLBundle\Definition\ExecutableDefinitionInterface;
19
use Ynlo\GraphQLBundle\Definition\FieldDefinition;
20
use Ynlo\GraphQLBundle\Definition\ObjectDefinition;
21
use Ynlo\GraphQLBundle\Definition\QueryDefinition;
22
use Ynlo\GraphQLBundle\Definition\Registry\Endpoint;
23
use Ynlo\GraphQLBundle\Model\OrderBy;
24
use Ynlo\GraphQLBundle\Query\Node\AllNodesWithPagination;
25
26
/**
27
 * Convert a simple return of nodes into a paginated collection with edges
28
 */
29
class PaginationDefinitionExtension extends AbstractDefinitionExtension
30
{
31
    public const ONE_TO_MANY = 'ONE_TO_MANY';
32
    public const MANY_TO_MANY = 'MANY_TO_MANY';
33
34
    /**
35
     * @var Reader
36
     */
37
    protected $reader;
38
39
    /**
40
     * @var int
41
     */
42
    protected $limit;
43
44
    /**
45
     * PaginationDefinitionExtension constructor.
46
     *
47
     * @param Reader $reader
48
     * @param array  $config
49
     */
50 21
    public function __construct(Reader $reader, $config = [])
51
    {
52 21
        $this->reader = $reader;
53 21
        $this->limit = $config['limit'] ?? 100;
54 21
    }
55
56
    /**
57
     * {@inheritDoc}
58
     */
59 21
    public function buildConfig(ArrayNodeDefinition $root)
60
    {
61
        $config = $root
62 21
            ->info('Enable pagination in queries or sub-fields')
63 21
            ->canBeEnabled()
64 21
            ->children();
65
66
        /** @var NodeBuilder $rootNode */
67 21
        $config->scalarNode('target')
68 21
               ->info('Target node to properly paginate. If is possible will be auto-resolved using naming conventions')
69 21
               ->isRequired();
70 21
        $config->integerNode('limit')->info('Max number of records allowed for first & last')->defaultValue($this->limit);
71 21
        $config->scalarNode('parent_field')
72 21
               ->info('When is used in sub-fields should be the field to filter by parent instance');
73 21
        $config->enumNode('parent_relation')
74 21
               ->info('When is used in sub-fields should be the type of relation with the parent field')
75 21
               ->defaultValue(self::ONE_TO_MANY)
76 21
               ->values([self::ONE_TO_MANY, self::MANY_TO_MANY]);
77 21
    }
78
79
    /**
80
     * {@inheritDoc}
81
     */
82 21
    public function normalizeConfig(DefinitionInterface $definition, $config): array
83
    {
84 21
        if (true === $config && $definition instanceof ExecutableDefinitionInterface) {
85 21
            $config = [];
86
        }
87
88 21
        if (is_array($config) && !isset($config['target'])) {
89 21
            $config['target'] = $definition->getType();
0 ignored issues
show
Bug introduced by
The method getType() does not exist on Ynlo\GraphQLBundle\Definition\DefinitionInterface. It seems like you code against a sub-type of Ynlo\GraphQLBundle\Definition\DefinitionInterface such as Ynlo\GraphQLBundle\Definition\ArgumentDefinition or Ynlo\GraphQLBundle\Defin...ableDefinitionInterface. ( Ignorable by Annotation )

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

89
            /** @scrutinizer ignore-call */ 
90
            $config['target'] = $definition->getType();
Loading history...
90
        }
91
92 21
        if (false === $config) {
93
            $config = [];
94
        }
95
96 21
        return $config;
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102 21
    public function configure(DefinitionInterface $definition, Endpoint $endpoint, array $config)
103
    {
104 21
        if (!$config) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $config 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...
105 21
            return;
106
        }
107
108 21
        if (!$definition instanceof QueryDefinition && !$definition instanceof FieldDefinition) {
109
            return;
110
        }
111
112 21
        $search = new ArgumentDefinition();
113 21
        $search->setName('search');
114 21
        $search->setType('string');
115 21
        $search->setNonNull(false);
116 21
        $search->setDescription('Search in current list by given string');
117 21
        $definition->addArgument($search);
118
119 21
        $first = new ArgumentDefinition();
120 21
        $first->setName('first');
121 21
        $first->setType('int');
122 21
        $first->setNonNull(false);
123 21
        $first->setDescription('Returns the first *n* elements from the list.');
124 21
        $definition->addArgument($first);
125
126 21
        $last = new ArgumentDefinition();
127 21
        $last->setName('last');
128 21
        $last->setType('int');
129 21
        $last->setNonNull(false);
130 21
        $last->setDescription('Returns the last *n* elements from the list.');
131 21
        $definition->addArgument($last);
132
133 21
        $after = new ArgumentDefinition();
134 21
        $after->setName('after');
135 21
        $after->setType('string');
136 21
        $after->setNonNull(false);
137 21
        $after->setDescription('Returns the last *n* elements from the list.');
138 21
        $definition->addArgument($after);
139
140 21
        $before = new ArgumentDefinition();
141 21
        $before->setName('before');
142 21
        $before->setType('string');
143 21
        $before->setNonNull(false);
144 21
        $before->setDescription('Returns the last *n* elements from the list.');
145 21
        $definition->addArgument($before);
146
147 21
        if (!$definition->hasArgument('orderBy')) {
148 21
            $orderBy = new ArgumentDefinition();
149 21
            $orderBy->setName('orderBy');
150 21
            $orderBy->setType(OrderBy::class);
151 21
            $orderBy->setNonNull(false);
152 21
            $orderBy->setList(true);
153 21
            $orderBy->setDescription('Ordering options for this list.');
154 21
            $definition->addArgument($orderBy);
155
        } else {
156
            //if exist move to the end
157
            $orderBy = $definition->getArgument('orderBy');
158
            $definition->removeArgument('orderBy');
159
            $definition->addArgument($orderBy);
160
        }
161
162 21
        $target = null;
163 21
        if ($definition instanceof FieldDefinition) {
164 21
            $target = $definition->getType();
165
        }
166
167 21
        $target = $config['target'] ?? $target;
168 21
        if ($endpoint->hasTypeForClass($target)) {
169 21
            $target = $endpoint->getTypeForClass($target);
170
        }
171
172 21
        $connection = new ObjectDefinition();
173 21
        $connection->setName(ucfirst($target).'Connection');
174
175 21
        if (!$endpoint->hasType($connection->getName())) {
176 21
            $endpoint->addType($connection);
177
178 21
            $totalCount = new FieldDefinition();
179 21
            $totalCount->setName('totalCount');
180 21
            $totalCount->setType('Int');
181 21
            $totalCount->setNonNull(true);
182 21
            $connection->addField($totalCount);
183
184 21
            $pageInfo = new FieldDefinition();
185 21
            $pageInfo->setName('pageInfo');
186 21
            $pageInfo->setType('PageInfo');
187 21
            $pageInfo->setNonNull(true);
188 21
            $connection->addField($pageInfo);
189
190 21
            $edgeObject = new ObjectDefinition();
191 21
            $edgeObject->setName(ucfirst($target).'Edge');
192 21
            if (!$endpoint->hasType($edgeObject->getName())) {
193 21
                $endpoint->addType($edgeObject);
194
195 21
                $node = new FieldDefinition();
196 21
                $node->setName('node');
197 21
                $node->setType($target);
198 21
                $node->setNonNull(true);
199 21
                $edgeObject->addField($node);
200
201 21
                $cursor = new FieldDefinition();
202 21
                $cursor->setName('cursor');
203 21
                $cursor->setType('string');
204 21
                $cursor->setNonNull(true);
205 21
                $edgeObject->addField($cursor);
206
            }
207
208 21
            $edges = new FieldDefinition();
209 21
            $edges->setName('edges');
210 21
            $edges->setType($edgeObject->getName());
211 21
            $edges->setList(true);
212 21
            $connection->addField($edges);
213
        }
214
215 21
        $definition->setType($connection->getName());
216 21
        $definition->setList(false);
217 21
        $definition->setMeta('node', $target);
218 21
        $definition->setMeta('pagination', $config);
219
220 21
        if (!$definition->getResolver()) {
221 21
            $definition->setResolver(AllNodesWithPagination::class);
222
        }
223 21
    }
224
}
225