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

CRUDAnnotationParser::parse()   F

Complexity

Conditions 16
Paths 1460

Size

Total Lines 83
Code Lines 48

Duplication

Lines 47
Ratio 56.63 %

Code Coverage

Tests 31
CRAP Score 20.5988

Importance

Changes 0
Metric Value
cc 16
eloc 48
nc 1460
nop 3
dl 47
loc 83
ccs 31
cts 42
cp 0.7381
crap 20.5988
rs 2.0134
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\Loader\Annotation;
12
13
use Doctrine\Common\Util\Inflector;
14
use Ynlo\GraphQLBundle\Annotation;
15
use Ynlo\GraphQLBundle\Definition\DefinitionInterface;
16
use Ynlo\GraphQLBundle\Definition\ObjectDefinitionInterface;
17
use Ynlo\GraphQLBundle\Definition\Registry\Endpoint;
18
use Ynlo\GraphQLBundle\Form\Node\NodeDeleteInput;
19
use Ynlo\GraphQLBundle\Model\AddNodePayload;
20
use Ynlo\GraphQLBundle\Model\DeleteNodePayload;
21
use Ynlo\GraphQLBundle\Model\NodeInterface;
22
use Ynlo\GraphQLBundle\Model\UpdateNodePayload;
23
use Ynlo\GraphQLBundle\Mutation\AddNodeMutation;
24
use Ynlo\GraphQLBundle\Mutation\DeleteNodeMutation;
25
use Ynlo\GraphQLBundle\Mutation\UpdateNodeMutation;
26
use Ynlo\GraphQLBundle\Query\Node\AllNodesWithPagination;
27
use Ynlo\GraphQLBundle\Query\Node\Node;
28
use Ynlo\GraphQLBundle\Query\Node\Nodes;
29
use Ynlo\GraphQLBundle\Util\ClassUtils;
30
31
/**
32
 * CRUDAnnotationParser
33
 */
34
class CRUDAnnotationParser implements AnnotationParserInterface
35
{
36
    use AnnotationReaderAwareTrait;
37
38
    /**
39
     * @var QueryAnnotationParser
40
     */
41
    protected $queryParser;
42
43
    /**
44
     * @var MutationAnnotationParser
45
     */
46
    protected $mutationParser;
47
48
    /**
49
     * CRUDAnnotationParser constructor.
50
     *
51
     * @param QueryAnnotationParser    $queryParser
52
     * @param MutationAnnotationParser $mutationParser
53
     */
54 1
    public function __construct(QueryAnnotationParser $queryParser, MutationAnnotationParser $mutationParser)
55
    {
56 1
        $this->queryParser = $queryParser;
57 1
        $this->mutationParser = $mutationParser;
58 1
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 1
    public function supports($annotation): bool
64
    {
65 1
        return $annotation instanceof Annotation\CRUDOperations;
66
    }
67
68
    /**
69
     * {@inheritDoc}
70
     */
71 1
    public function parse($annotation, \ReflectionClass $refClass, Endpoint $endpoint)
72
    {
73 1
        if (!$endpoint->hasTypeForClass($refClass->getName())) {
74
            throw new \Exception(sprintf('Can`t apply CRUD operations to "%s", CRUD operations can only be applied to valid GraphQL object types.', $refClass->getName()));
75
        }
76
77 1
        if (!$refClass->implementsInterface(NodeInterface::class)) {
78
            throw new \Exception(
79
                sprintf(
80
                    'Can`t apply CRUD operations to "%s", CRUD operations can only be applied to nodes.
81
             You are implementing NodeInterface in this class?',
82
                    $refClass->getName()
83
                )
84
            );
85
        }
86
87
        /** @var Annotation\CRUDOperations $annotation */
88 1
        if ($annotation->exclude) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $annotation->exclude 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...
89 1
            $annotation->include = array_diff($annotation->include, $annotation->exclude);
90
        }
91
92 1
        $definition = $endpoint->getType($endpoint->getTypeForClass($refClass->getName()));
93
94 1
        $bundleNamespace = ClassUtils::relatedBundleNamespace($refClass->getName());
95
96
        //All query
97 1 View Code Duplication
        if (in_array('all', $annotation->include)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
98 1
            if ($annotation->all) {
99
                $query = $annotation->all;
100
            } else {
101 1
                $query = new Annotation\Query();
102
            }
103 1
            $this->createAllOperation($definition, $query, $endpoint, $bundleNamespace);
104
        }
105
106
        //Get query
107 1 View Code Duplication
        if (in_array('get', $annotation->include)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
108 1
            if ($annotation->get) {
109
                $query = $annotation->get;
110
            } else {
111 1
                $query = new Annotation\Query();
112
            }
113 1
            $this->createGetOperation($definition, $query, $endpoint, $bundleNamespace);
114
        }
115
116
        //Gets query
117 1 View Code Duplication
        if (in_array('gets', $annotation->include)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
118 1
            if ($annotation->gets) {
119
                $query = $annotation->gets;
120
            } else {
121 1
                $query = new Annotation\Query();
122
            }
123 1
            $this->createGetsOperation($definition, $query, $endpoint, $bundleNamespace);
124
        }
125
126
        //Add mutation
127 1 View Code Duplication
        if (in_array('add', $annotation->include)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
128 1
            if ($annotation->add) {
129
                $mutation = $annotation->add;
130
            } else {
131 1
                $mutation = new Annotation\Mutation();
132
            }
133 1
            $this->createAddOperation($definition, $mutation, $endpoint, $bundleNamespace);
134
        }
135
136
        //Update mutation
137 1 View Code Duplication
        if (in_array('update', $annotation->include)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
138 1
            if ($annotation->update) {
139
                $mutation = $annotation->update;
140
            } else {
141 1
                $mutation = new Annotation\Mutation();
142
            }
143 1
            $this->createUpdateOperation($definition, $mutation, $endpoint, $bundleNamespace);
144
        }
145
146
        //Delete mutation
147 1 View Code Duplication
        if (in_array('delete', $annotation->include)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
148 1
            if ($annotation->delete) {
149
                $mutation = $annotation->delete;
150
            } else {
151 1
                $mutation = new Annotation\Mutation();
152
            }
153 1
            $this->createDeleteOperation($definition, $mutation, $endpoint, $bundleNamespace);
154
        }
155 1
    }
156
157
    /**
158
     * @param ObjectDefinitionInterface $definition
159
     * @param Annotation\Query          $query
160
     * @param Endpoint                  $endpoint
161
     * @param string                    $bundleNamespace
162
     */
163 1 View Code Duplication
    protected function createGetsOperation(ObjectDefinitionInterface $definition, Annotation\Query $query, Endpoint $endpoint, $bundleNamespace)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
    {
165 1
        $query->name = $query->name ?? Inflector::pluralize(lcfirst($definition->getName()));
166 1
        $query->node = $query->node ?? $definition->getName();
167 1
        $query->list = true;
168 1
        $resolverReflection = new \ReflectionClass(Nodes::class);
169
170 1
        $resolver = ClassUtils::applyNamingConvention($bundleNamespace, 'Query', $definition->getName(), $query->name);
171 1
        if (class_exists($resolver)) {
172
            $query->resolver = $resolver;
173
        }
174
175 1
        $this->queryParser->parse($query, $resolverReflection, $endpoint);
176 1
    }
177
178
    /**
179
     * @param ObjectDefinitionInterface $definition
180
     * @param Annotation\Query          $query
181
     * @param Endpoint                  $endpoint
182
     * @param string                    $bundleNamespace
183
     */
184 1 View Code Duplication
    protected function createGetOperation(ObjectDefinitionInterface $definition, Annotation\Query $query, Endpoint $endpoint, $bundleNamespace)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185
    {
186 1
        $query->name = $query->name ?? Inflector::singularize(lcfirst($definition->getName()));
187 1
        $query->node = $query->node ?? $definition->getName();
188 1
        $resolverReflection = new \ReflectionClass(Node::class);
189
190 1
        $resolver = ClassUtils::applyNamingConvention($bundleNamespace, 'Query', $definition->getName(), $query->name);
191 1
        if (class_exists($resolver)) {
192
            $query->resolver = $resolver;
193
        }
194
195 1
        $this->queryParser->parse($query, $resolverReflection, $endpoint);
196 1
    }
197
198
    /**
199
     * @param ObjectDefinitionInterface $definition
200
     * @param Annotation\Query          $query
201
     * @param Endpoint                  $endpoint
202
     * @param string                    $bundleNamespace
203
     */
204 1
    protected function createAllOperation(ObjectDefinitionInterface $definition, Annotation\Query $query, Endpoint $endpoint, $bundleNamespace)
205
    {
206 1
        $query->name = $query->name ?? 'all'.Inflector::pluralize(ucfirst($definition->getName()));
207 1
        $query->node = $query->node ?? $definition->getName();
208 1
        $query->options = array_merge(['pagination' => true], $query->options);
209 1
        $resolverReflection = new \ReflectionClass(AllNodesWithPagination::class);
210
211 1
        $resolver = ClassUtils::applyNamingConvention($bundleNamespace, 'Query', $definition->getName(), $query->name);
212 1
        if (class_exists($resolver)) {
213
            $query->resolver = $resolver;
214
        }
215
216 1
        $this->queryParser->parse($query, $resolverReflection, $endpoint);
217 1
    }
218
219
    /**
220
     * @param ObjectDefinitionInterface $definition
221
     * @param Annotation\Mutation       $mutation
222
     * @param Endpoint                  $endpoint
223
     * @param string                    $bundleNamespace
224
     */
225 1 View Code Duplication
    protected function createAddOperation(ObjectDefinitionInterface $definition, Annotation\Mutation $mutation, Endpoint $endpoint, $bundleNamespace)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
226
    {
227 1
        $mutation->name = $mutation->name ?? 'add'.ucfirst($definition->getName());
228 1
        $mutation->payload = $mutation->payload ?? null;
229 1
        if (!$mutation->payload) {
230
            //deep cloning
231
            /** @var ObjectDefinitionInterface $payload */
232 1
            $payload = unserialize(serialize($endpoint->getType(AddNodePayload::class)), [DefinitionInterface::class]);
233 1
            $payload->setName(ucfirst($mutation->name.'Payload'));
234
235 1
            if (!$endpoint->hasType($payload->getName())) {
236 1
                $payload->getField('node')->setType($definition->getName());
237 1
                $endpoint->add($payload);
238
            }
239
240 1
            $mutation->payload = $payload->getName();
241
        }
242 1
        $mutation->node = $mutation->node ?? $definition->getName();
243 1
        $mutation->options = array_merge(['form' => ['type' => true]], $mutation->options);
244 1
        $resolverReflection = new \ReflectionClass(AddNodeMutation::class);
245
246 1
        $resolver = ClassUtils::applyNamingConvention($bundleNamespace, 'Mutation', $definition->getName(), $mutation->name);
247 1
        if (class_exists($resolver)) {
248
            $mutation->resolver = $resolver;
249
        }
250
251 1
        $this->mutationParser->parse($mutation, $resolverReflection, $endpoint);
252 1
    }
253
254
    /**
255
     * @param ObjectDefinitionInterface $definition
256
     * @param Annotation\Mutation       $mutation
257
     * @param Endpoint                  $endpoint
258
     * @param string                    $bundleNamespace
259
     */
260 1 View Code Duplication
    protected function createUpdateOperation(ObjectDefinitionInterface $definition, Annotation\Mutation $mutation, Endpoint $endpoint, $bundleNamespace)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
261
    {
262 1
        $mutation->name = $mutation->name ?? 'update'.ucfirst($definition->getName());
263 1
        $mutation->payload = $mutation->payload ?? null;
264 1
        if (!$mutation->payload) {
265
            //deep cloning
266
            /** @var ObjectDefinitionInterface $payload */
267 1
            $payload = unserialize(serialize($endpoint->getType(UpdateNodePayload::class)), [DefinitionInterface::class]);
268 1
            $payload->setName(ucfirst($mutation->name.'Payload'));
269
270 1
            if (!$endpoint->hasType($payload->getName())) {
271 1
                $payload->getField('node')->setType($definition->getName());
272 1
                $endpoint->add($payload);
273
            }
274
275 1
            $mutation->payload = $payload->getName();
276
        }
277 1
        $mutation->node = $mutation->node ?? $definition->getName();
278 1
        $mutation->options = array_merge(['form' => ['type' => true]], $mutation->options);
279 1
        $resolverReflection = new \ReflectionClass(UpdateNodeMutation::class);
280
281 1
        $resolver = ClassUtils::applyNamingConvention($bundleNamespace, 'Mutation', $definition->getName(), $mutation->name);
282 1
        if (class_exists($resolver)) {
283
            $mutation->resolver = $resolver;
284
        }
285
286 1
        $this->mutationParser->parse($mutation, $resolverReflection, $endpoint);
287 1
    }
288
289
    /**
290
     * @param ObjectDefinitionInterface $definition
291
     * @param Annotation\Mutation       $mutation
292
     * @param Endpoint                  $endpoint
293
     * @param string                    $bundleNamespace
294
     */
295 1
    protected function createDeleteOperation(ObjectDefinitionInterface $definition, Annotation\Mutation $mutation, Endpoint $endpoint, $bundleNamespace)
296
    {
297 1
        $mutation->name = $mutation->name ?? 'delete'.ucfirst($definition->getName());
298 1
        $mutation->payload = $mutation->payload ?? null;
299 1
        if (!$mutation->payload) {
300 1
            $mutation->payload = DeleteNodePayload::class;
301
        }
302 1
        $mutation->node = $mutation->node ?? $definition->getName();
303 1
        $mutation->options = array_merge(['form' => ['type' => NodeDeleteInput::class]], $mutation->options);
304 1
        $resolverReflection = new \ReflectionClass(DeleteNodeMutation::class);
305
306 1
        $resolver = ClassUtils::applyNamingConvention($bundleNamespace, 'Mutation', $definition->getName(), $mutation->name);
307 1
        if (class_exists($resolver)) {
308
            $mutation->resolver = $resolver;
309
        }
310
311 1
        $this->mutationParser->parse($mutation, $resolverReflection, $endpoint);
312 1
    }
313
}
314