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

PaginationDefinitionExtension::configure()   D

Complexity

Conditions 10
Paths 50

Size

Total Lines 113
Code Lines 85

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 81
CRAP Score 10.0104

Importance

Changes 0
Metric Value
cc 10
eloc 85
nc 50
nop 3
dl 0
loc 113
ccs 81
cts 85
cp 0.9529
crap 10.0104
rs 4.8196
c 0
b 0
f 0

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 1
    public function __construct(Reader $reader, $config = [])
51
    {
52 1
        $this->reader = $reader;
53 1
        $this->limit = $config['limit'] ?? 100;
54 1
    }
55
56
    /**
57
     * {@inheritDoc}
58
     */
59 1
    public function buildConfig(ArrayNodeDefinition $root)
60
    {
61
        $config = $root
62 1
            ->info('Enable pagination in queries or sub-fields')
63 1
            ->canBeEnabled()
64 1
            ->children();
65
66
        /** @var NodeBuilder $rootNode */
67 1
        $config->scalarNode('target')
68 1
               ->info('Target node to properly paginate. If is possible will be auto-resolved using naming conventions')
69 1
               ->isRequired();
70 1
        $config->integerNode('limit')->info('Max number of records allowed for first & last')->defaultValue($this->limit);
71 1
        $config->scalarNode('parent_field')
72 1
               ->info('When is used in sub-fields should be the field to filter by parent instance');
73 1
        $config->enumNode('parent_relation')
74 1
               ->info('When is used in sub-fields should be the type of relation with the parent field')
75 1
               ->defaultValue(self::ONE_TO_MANY)
76 1
               ->values([self::ONE_TO_MANY, self::MANY_TO_MANY]);
77 1
    }
78
79
    /**
80
     * {@inheritDoc}
81
     */
82 1
    public function normalizeConfig(DefinitionInterface $definition, $config): array
83
    {
84 1
        if (true === $config && $definition instanceof ExecutableDefinitionInterface) {
85 1
            $config = [];
86
        }
87
88 1
        if (is_array($config) && !isset($config['target'])) {
89 1
            $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 1
        if (false === $config) {
93
            $config = [];
94
        }
95
96 1
        return $config;
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102 1
    public function configure(DefinitionInterface $definition, Endpoint $endpoint, array $config)
103
    {
104 1
        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 1
            return;
106
        }
107
108 1
        if (!$definition instanceof QueryDefinition && !$definition instanceof FieldDefinition) {
109
            return;
110
        }
111
112 1
        $first = new ArgumentDefinition();
113 1
        $first->setName('first');
114 1
        $first->setType('int');
115 1
        $first->setNonNull(false);
116 1
        $first->setDescription('Returns the first *n* elements from the list.');
117 1
        $definition->addArgument($first);
118
119 1
        $last = new ArgumentDefinition();
120 1
        $last->setName('last');
121 1
        $last->setType('int');
122 1
        $last->setNonNull(false);
123 1
        $last->setDescription('Returns the last *n* elements from the list.');
124 1
        $definition->addArgument($last);
125
126 1
        $after = new ArgumentDefinition();
127 1
        $after->setName('after');
128 1
        $after->setType('string');
129 1
        $after->setNonNull(false);
130 1
        $after->setDescription('Returns the last *n* elements from the list.');
131 1
        $definition->addArgument($after);
132
133 1
        $before = new ArgumentDefinition();
134 1
        $before->setName('before');
135 1
        $before->setType('string');
136 1
        $before->setNonNull(false);
137 1
        $before->setDescription('Returns the last *n* elements from the list.');
138 1
        $definition->addArgument($before);
139
140 1
        if (!$definition->hasArgument('orderBy')) {
141 1
            $orderBy = new ArgumentDefinition();
142 1
            $orderBy->setName('orderBy');
143 1
            $orderBy->setType(OrderBy::class);
144 1
            $orderBy->setNonNull(false);
145 1
            $orderBy->setList(true);
146 1
            $orderBy->setDescription('Ordering options for this list.');
147 1
            $definition->addArgument($orderBy);
148
        } else {
149
            //if exist move to the end
150
            $orderBy = $definition->getArgument('orderBy');
151
            $definition->removeArgument('orderBy');
152
            $definition->addArgument($orderBy);
153
        }
154
155 1
        $target = null;
156 1
        if ($definition instanceof FieldDefinition) {
157 1
            $target = $definition->getType();
158
        }
159
160 1
        $target = $config['target'] ?? $target;
161 1
        if ($endpoint->hasTypeForClass($target)) {
162 1
            $target = $endpoint->getTypeForClass($target);
163
        }
164
165 1
        $connection = new ObjectDefinition();
166 1
        $connection->setName(ucfirst($target).'Connection');
167
168 1
        if (!$endpoint->hasType($connection->getName())) {
169 1
            $endpoint->addType($connection);
170
171 1
            $totalCount = new FieldDefinition();
172 1
            $totalCount->setName('totalCount');
173 1
            $totalCount->setType('Int');
174 1
            $totalCount->setNonNull(true);
175 1
            $connection->addField($totalCount);
176
177 1
            $pageInfo = new FieldDefinition();
178 1
            $pageInfo->setName('pageInfo');
179 1
            $pageInfo->setType('PageInfo');
180 1
            $pageInfo->setNonNull(true);
181 1
            $connection->addField($pageInfo);
182
183 1
            $edgeObject = new ObjectDefinition();
184 1
            $edgeObject->setName(ucfirst($target).'Edge');
185 1
            if (!$endpoint->hasType($edgeObject->getName())) {
186 1
                $endpoint->addType($edgeObject);
187
188 1
                $node = new FieldDefinition();
189 1
                $node->setName('node');
190 1
                $node->setType($target);
191 1
                $node->setNonNull(true);
192 1
                $edgeObject->addField($node);
193
194 1
                $cursor = new FieldDefinition();
195 1
                $cursor->setName('cursor');
196 1
                $cursor->setType('string');
197 1
                $cursor->setNonNull(true);
198 1
                $edgeObject->addField($cursor);
199
            }
200
201 1
            $edges = new FieldDefinition();
202 1
            $edges->setName('edges');
203 1
            $edges->setType($edgeObject->getName());
204 1
            $edges->setList(true);
205 1
            $connection->addField($edges);
206
        }
207
208 1
        $definition->setType($connection->getName());
209 1
        $definition->setList(false);
210 1
        $definition->setMeta('node', $target);
211 1
        $definition->setMeta('pagination', $config);
212
213 1
        if (!$definition->getResolver()) {
214 1
            $definition->setResolver(AllNodesWithPagination::class);
215
        }
216 1
    }
217
}
218