Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#360)
by
unknown
10:54
created

AnnotationParser::formatRelay()   B

Complexity

Conditions 8
Paths 24

Size

Total Lines 46

Duplication

Lines 6
Ratio 13.04 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
dl 6
loc 46
c 0
b 0
f 0
ccs 0
cts 39
cp 0
rs 7.9337
cc 8
nc 24
nop 4
crap 72
1
<?php
2
3
namespace Overblog\GraphQLBundle\Config\Parser;
4
5
use Symfony\Component\Config\Resource\FileResource;
6
use Symfony\Component\DependencyInjection\ContainerBuilder;
7
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
8
use Zend\Code\Reflection\PropertyReflection;
9
10
class AnnotationParser implements ParserInterface
11
{
12
    public static function getAnnotationReader()
13
    {
14
        if (!class_exists('\\Doctrine\\Common\\Annotations\\AnnotationReader') ||
15
            !class_exists('\\Doctrine\\Common\\Annotations\\AnnotationRegistry')
16
        ) {
17
            throw new \Exception('In order to use annotation, you need to require doctrine ORM');
18
        }
19
20
        $loader = require __DIR__.'/../../../../autoload.php';
21
22
        \Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\Common\Annotati...istry::registerLoader() has been deprecated with message: this method is deprecated and will be removed in doctrine/annotations 2.0 autoloading should be deferred to the globally registered autoloader by then. For now, use @example AnnotationRegistry::registerLoader('class_exists')

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
23
        \Doctrine\Common\Annotations\AnnotationRegistry::registerFile(__DIR__.'/../../Annotation/GraphQLAnnotation.php');
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\Common\Annotati...egistry::registerFile() has been deprecated with message: this method is deprecated and will be removed in doctrine/annotations 2.0 autoloading should be deferred to the globally registered autoloader by then. For now, use @example AnnotationRegistry::registerLoader('class_exists')

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
24
        $reader = new \Doctrine\Common\Annotations\AnnotationReader();
25
26
        return $reader;
27
    }
28
29
    /**
30
     * {@inheritdoc}
31
     *
32
     * @throws \ReflectionException
33
     * @throws InvalidArgumentException
34
     */
35
    public static function parse(\SplFileInfo $file, ContainerBuilder $container)
36
    {
37
        $reader = self::getAnnotationReader();
38
        $container->addResource(new FileResource($file->getRealPath()));
39
        try {
40
            $fileContent = file_get_contents($file->getRealPath());
41
42
            $entityName = substr($file->getFilename(), 0, -4);
43
            if (preg_match('#namespace (.+);#', $fileContent, $namespace)) {
44
                $className = $namespace[1].'\\'.$entityName;
45
            } else {
46
                $className = $entityName;
47
            }
48
49
            $reflexionEntity = new \ReflectionClass($className);
50
51
            $annotations = $reader->getClassAnnotations($reflexionEntity);
52
            $annotations = self::parseAnnotation($annotations);
53
54
            $alias = self::getGraphQLAlias($annotations) ?: $entityName;
55
            $type = self::getGraphQLType($annotations);
56
57
            switch ($type) {
58
                case 'relay-connection':
59
                    return self::formatRelay($type, $alias, $annotations, $reflexionEntity->getProperties());
0 ignored issues
show
Documentation introduced by
$reflexionEntity->getProperties() is of type array<integer,object<ReflectionProperty>>, but the function expects a array<integer,object<Zen...on\PropertyReflection>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
60
                case 'enum':
61
                    return self::formatEnumType($alias, $entityName, $reflexionEntity->getProperties());
62
                case 'custom-scalar':
63
                    return self::formatCustomScalarType($alias, $type, $className, $annotations);
64
                default:
65
                    return self::formatScalarType($alias, $type, $entityName, $reflexionEntity->getProperties());
66
            }
67
        } catch (\InvalidArgumentException $e) {
68
            throw new InvalidArgumentException(sprintf('Unable to parse file "%s".', $file), $e->getCode(), $e);
69
        }
70
    }
71
72
    /**
73
     * Get the graphQL alias.
74
     *
75
     * @param $annotation
76
     *
77
     * @return string|null
78
     */
79
    protected static function getGraphQLAlias($annotation)
80
    {
81
        if (array_key_exists('GraphQLAlias', $annotation) && !empty($annotation['GraphQLAlias']['name'])) {
82
            return $annotation['GraphQLAlias']['name'];
83
        }
84
85
        return null;
86
    }
87
88
    /**
89
     * Get the graphQL type.
90
     *
91
     * @param $annotation
92
     *
93
     * @return string
94
     */
95
    protected static function getGraphQLType($annotation)
96
    {
97
        if (array_key_exists('GraphQLType', $annotation) && !empty($annotation['GraphQLType']['type'])) {
98
            return $annotation['GraphQLType']['type'];
99
        }
100
101
        if (array_key_exists('GraphQLScalarType', $annotation) && !empty($annotation['GraphQLScalarType']['type'])) {
102
            return 'custom-scalar';
103
        }
104
105
        return 'object';
106
    }
107
108
    /**
109
     * @param string               $type
110
     * @param string               $alias
111
     * @param array                $classAnnotations
112
     * @param PropertyReflection[] $properties
113
     *
114
     * @return array
115
     *
116
     * @throws \Exception
117
     */
118
    protected static function formatRelay($type, $alias, $classAnnotations, $properties)
119
    {
120
        $reader = self::getAnnotationReader();
121
122
        $typesConfig = [
123
            $alias => [
124
                'type' => $type,
125
                'config' => [],
126
            ],
127
        ];
128
129
        if (!empty($classAnnotations['GraphQLNode'])) {
130
            $typesConfig[$alias]['config']['nodeType'] = $classAnnotations['GraphQLNode']['type'];
131
            $typesConfig[$alias]['config']['resolveNode'] = $classAnnotations['GraphQLNode']['resolve'];
132
        }
133
134
        foreach ($properties as $property) {
135
            $propertyName = $property->getName();
136
            $propertyAnnotation = $reader->getPropertyAnnotations($property);
137
            $propertyAnnotation = self::parseAnnotation($propertyAnnotation);
138
139
            if (!empty($propertyAnnotation['GraphQLEdgeFields'])) {
140 View Code Duplication
                if (empty($typesConfig[$alias]['config']['edgeFields'])) {
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...
141
                    $typesConfig[$alias]['config']['edgeFields'] = [];
142
                }
143
144
                $typesConfig[$alias]['config']['edgeFields'][$propertyName] = [
145
                    'type' => $propertyAnnotation['GraphQLEdgeFields']['type'],
146
                    'resolve' => $propertyAnnotation['GraphQLEdgeFields']['resolve'],
147
                ];
148
            } elseif (!empty($propertyAnnotation['GraphQLConnectionFields'])) {
149 View Code Duplication
                if (empty($typesConfig[$alias]['config']['connectionFields'])) {
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...
150
                    $typesConfig[$alias]['config']['connectionFields'] = [];
151
                }
152
153
                $typesConfig[$alias]['config']['connectionFields'][$propertyName] = [
154
                    'type' => $propertyAnnotation['GraphQLConnectionFields']['type'],
155
                    'resolve' => $propertyAnnotation['GraphQLConnectionFields']['resolve'],
156
                ];
157
            }
158
        }
159
160
        return empty($typesConfig[$alias]['config'])
161
            ? []
162
            : $typesConfig;
163
    }
164
165
    /**
166
     * Format enum type.
167
     *
168
     * @param string                $alias
169
     * @param string                $entityName
170
     * @param \ReflectionProperty[] $properties
171
     *
172
     * @return array
173
     */
174
    protected static function formatEnumType($alias, $entityName, $properties)
175
    {
176
        $reader = self::getAnnotationReader();
177
178
        $typesConfig = [
179
            $alias => [
180
                'type' => 'enum',
181
                'config' => [
182
                    'description' => $entityName.' type',
183
                ],
184
            ],
185
        ];
186
187
        $values = [];
188
        /** @var \ReflectionProperty $property */
189
        foreach ($properties as $property) {
190
            $propertyName = $property->getName();
191
192
            $propertyAnnotation = $reader->getPropertyAnnotations($property);
193
            $propertyAnnotation = self::parseAnnotation($propertyAnnotation);
194
195
            $values[$propertyName] = [
196
                'value' => $propertyAnnotation,
197
            ];
198
199
            if (array_key_exists('GraphQLDescription', $propertyAnnotation) && !empty($test['GraphQLDescription']['description'])) {
200
                $values[$propertyName]['description'] = $test['GraphQLDescription']['description'];
201
            }
202
        }
203
204
        $typesConfig[$alias]['config']['values'] = $values;
205
206
        return $typesConfig;
207
    }
208
209
    /**
210
     * Format custom scalar type.
211
     *
212
     * @param string $alias
213
     * @param string $type
214
     * @param string $className
215
     * @param array  $annotations
216
     *
217
     * @return array
218
     */
219
    protected static function formatCustomScalarType($alias, $type, $className, $annotations)
220
    {
221
        if (array_key_exists('GraphQLScalarType', $annotations) && !empty($annotations['GraphQLScalarType']['type'])) {
222
            return [
223
                $alias => [
224
                    'type' => $type,
225
                    'config' => [
226
                        'scalarType' => $annotations['GraphQLScalarType']['type'],
227
                    ],
228
                ],
229
            ];
230
        }
231
232
        $config = [
233
            'serialize' => [$className, 'serialize'],
234
            'parseValue' => [$className, 'parseValue'],
235
            'parseLiteral' => [$className, 'parseLiteral'],
236
        ];
237
238
        return [
239
            $alias => [
240
                'type' => $type,
241
                'config' => $config,
242
            ],
243
        ];
244
    }
245
246
    /**
247
     * Format scalar type.
248
     *
249
     * @param string                $alias
250
     * @param string                $type
251
     * @param string                $entityName
252
     * @param \ReflectionProperty[] $properties
253
     *
254
     * @return array
255
     */
256
    protected static function formatScalarType($alias, $type, $entityName, $properties)
257
    {
258
        $reader = self::getAnnotationReader();
259
260
        $typesConfig = [
261
            $alias => [
262
                'type' => $type,
263
                'config' => [
264
                    'description' => $entityName.' type',
265
                    'fields' => [],
266
                ],
267
            ],
268
        ];
269
270
        foreach ($properties as $property) {
271
            $propertyName = $property->getName();
272
            $propertyAnnotation = $reader->getPropertyAnnotations($property);
273
            $propertyAnnotation = self::parseAnnotation($propertyAnnotation);
274
275
            if (!$graphQlType = self::getGraphQLFieldType($propertyName, $propertyAnnotation)) {
276
                continue;
277
            }
278
279
            if ($graphQlAccessControl = self::getGraphQLAccessControl($propertyAnnotation)) {
280
                $graphQlType['access'] = $graphQlAccessControl;
281
            }
282
283
            if ($graphQlPublicControl = self::getGraphQLPublicControl($propertyAnnotation)) {
284
                $graphQlType['public'] = $graphQlPublicControl;
285
            }
286
287
            $typesConfig[$alias]['config']['fields'][$propertyName] = $graphQlType;
288
        }
289
290
        return empty($typesConfig[$alias]['config']['fields'])
291
            ? []
292
            : $typesConfig;
293
    }
294
295
    /**
296
     * Return the graphQL type for the named field.
297
     *
298
     * @param string $name
299
     * @param array  $annotation
300
     *
301
     * @return array|null
302
     */
303
    protected static function getGraphQLFieldType($name, $annotation)
304
    {
305
        if (!$type = self::getGraphQLScalarFieldType($name, $annotation)) {
306
            if (!$type = self::getGraphQLQueryField($annotation)) {
307
                if (!$type = self::getGraphQLMutationField($annotation)) {
308
                    return null;
309
                }
310
            }
311
        }
312
313
        return $type;
314
    }
315
316
    /**
317
     * Return the common field type, like ID, Int, String, and other user-created type.
318
     *
319
     * @param string $name
320
     * @param array  $annotation
321
     *
322
     * @return array|null
323
     */
324
    protected static function getGraphQLScalarFieldType($name, $annotation)
325
    {
326
        // Get the current type, depending on current annotation
327
        $type = $graphQLType = null;
0 ignored issues
show
Unused Code introduced by
$graphQLType is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
328
        $nullable = $isMultiple = false;
329
        if (array_key_exists('GraphQLColumn', $annotation) && array_key_exists('type', $annotation['GraphQLColumn'])) {
330
            $annotation = $annotation['GraphQLColumn'];
331
            $type = $annotation['type'];
332 View Code Duplication
        } elseif (array_key_exists('GraphQLToMany', $annotation) && array_key_exists('target', $annotation['GraphQLToMany'])) {
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...
333
            $annotation = $annotation['GraphQLToMany'];
334
            $type = $annotation['target'];
335
            $isMultiple = $nullable = true;
336
        } elseif (array_key_exists('GraphQLToOne', $annotation) && array_key_exists('target', $annotation['GraphQLToOne'])) {
337
            $annotation = $annotation['GraphQLToOne'];
338
            $type = $annotation['target'];
339
            $nullable = true;
340 View Code Duplication
        } elseif (array_key_exists('OneToMany', $annotation) && array_key_exists('targetEntity', $annotation['OneToMany'])) {
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...
341
            $annotation = $annotation['OneToMany'];
342
            $type = $annotation['targetEntity'];
343
            $isMultiple = $nullable = true;
344
        } elseif (array_key_exists('OneToOne', $annotation) && array_key_exists('targetEntity', $annotation['OneToOne'])) {
345
            $annotation = $annotation['OneToOne'];
346
            $type = $annotation['targetEntity'];
347
            $nullable = true;
348 View Code Duplication
        } elseif (array_key_exists('ManyToMany', $annotation) && array_key_exists('targetEntity', $annotation['ManyToMany'])) {
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...
349
            $annotation = $annotation['ManyToMany'];
350
            $type = $annotation['targetEntity'];
351
            $isMultiple = $nullable = true;
352
        } elseif (array_key_exists('ManyToOne', $annotation) && array_key_exists('targetEntity', $annotation['ManyToOne'])) {
353
            $annotation = $annotation['ManyToOne'];
354
            $type = $annotation['targetEntity'];
355
            $nullable = true;
356
        } elseif (array_key_exists('Column', $annotation) && array_key_exists('type', $annotation['Column'])) {
357
            $annotation = $annotation['Column'];
358
            $type = $annotation['type'];
359
        }
360
361
        if (!$type) {
362
            return null;
363
        }
364
365
        if (array_key_exists('nullable', $annotation)) {
366
            $nullable = 'true' == $annotation['nullable']
367
                ? true
368
                : false;
369
        }
370
371
        $type = explode('\\', $type);
372
        $type = $type[count($type) - 1];
373
374
        // Get the graphQL type representation
375
        // Specific case for ID and relation
376
        if ('id' === $name && 'integer' === $type) {
377
            $graphQLType = 'ID';
378
        } else {
379
            // Make the relation between doctrine Column type and graphQL type
380
            switch ($type) {
381
                case 'integer':
382
                    $graphQLType = 'Int';
383
                    break;
384
                case 'string':
385
                case 'text':
386
                    $graphQLType = 'String';
387
                    break;
388
                case 'bool':
389
                case 'boolean':
390
                    $graphQLType = 'Boolean';
391
                    break;
392
                case 'float':
393
                case 'decimal':
394
                    $graphQLType = 'Float';
395
                    break;
396
                default:
397
                    // No maching: considering is custom-scalar graphQL type
398
                    $graphQLType = $type;
399
            }
400
        }
401
402
        if ($isMultiple) {
403
            $graphQLType = '['.$graphQLType.']';
404
        }
405
406
        if (!$nullable) {
407
            $graphQLType .= '!';
408
        }
409
410
        return ['type' => $graphQLType];
411
    }
412
413
    /**
414
     * Get the graphql query formatted field.
415
     *
416
     * @param array $annotation
417
     *
418
     * @return array|null
419
     */
420
    protected static function getGraphQLQueryField($annotation)
421
    {
422
        if (!array_key_exists('GraphQLQuery', $annotation)) {
423
            return null;
424
        }
425
426
        $annotationQuery = $annotation['GraphQLQuery'];
427
428
        $ret = [
429
            'type' => $annotationQuery['type'],
430
        ];
431
432
        $method = $annotationQuery['method'];
433
        $args = $queryArgs = [];
434
        if (!empty($annotationQuery['input'])) {
435
            $annotationArgs = $annotationQuery['input'];
436
            if (!array_key_exists(0, $annotationArgs)) {
437
                $annotationArgs = [$annotationArgs];
438
            }
439
440
            foreach ($annotationArgs as $arg) {
441
                if (!empty($arg['name'])) {
442
                    $args[$arg['name']] = [
443
                        'type' => $arg['type'],
444
                    ];
445
446
                    if (!empty($arg['description'])) {
447
                        $args[$arg['name']]['description'] = $arg['description'];
448
                    }
449
                }
450
451
                $queryArgs[] = $arg['target'];
452
            }
453
454
            if (!empty($args)) {
455
                $ret['args'] = $args;
456
            }
457
        }
458
459
        if (!empty($queryArgs)) {
460
            $query = "'".$method."', [".implode(', ', $queryArgs).']';
461
        } else {
462
            $query = "'".$method."'";
463
        }
464
465
        $ret['resolve'] = '@=resolver('.$query.')';
466
467
        if (!empty($annotationQuery['argsBuilder'])) {
468
            $ret['argsBuilder'] = $annotationQuery['argsBuilder'];
469
        }
470
471
        return $ret;
472
    }
473
474
    /**
475
     * Get the formatted graphQL mutation field.
476
     *
477
     * @param array $annotation
478
     *
479
     * @return array
480
     */
481
    protected static function getGraphQLMutationField($annotation)
482
    {
483
        if (!array_key_exists('GraphQLMutation', $annotation)) {
484
            return self::getGraphQLRelayMutationField($annotation);
485
        }
486
487
        $annotation = $annotation['GraphQLMutation'];
488 View Code Duplication
        if (array_key_exists('args', $annotation)) {
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...
489
            $mutate = "@=mutation('".$annotation['method']."', [".implode(', ', $annotation['args']).'])';
490
        } else {
491
            $mutate = "'".$annotation['method']."'";
492
        }
493
494
        return [
495
            'type' => $annotation['payload'],
496
            'resolve' => $mutate,
497
            'args' => $annotation['input'],
498
        ];
499
    }
500
501
    /**
502
     * Get the formatted graphQL relay mutation field.
503
     *
504
     * @param array $annotation
505
     *
506
     * @return array|null
507
     */
508
    protected static function getGraphQLRelayMutationField($annotation)
509
    {
510
        if (!array_key_exists('GraphQLRelayMutation', $annotation)) {
511
            return null;
512
        }
513
514
        $annotation = $annotation['GraphQLRelayMutation'];
515 View Code Duplication
        if (array_key_exists('args', $annotation)) {
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...
516
            $mutate = "'".$annotation['method']."', [".implode(', ', $annotation['args']).']';
517
        } else {
518
            $mutate = "'".$annotation['method']."'";
519
        }
520
521
        return [
522
            'builder' => 'Relay::Mutation',
523
            'builderConfig' => [
524
                'inputType' => $annotation['input'][0],
525
                'payloadType' => $annotation['payload'],
526
                'mutateAndGetPayload' => '@=mutation('.$mutate.')',
527
            ],
528
        ];
529
    }
530
531
    /**
532
     * Get graphql access control annotation.
533
     *
534
     * @param $annotation
535
     *
536
     * @return null|string
537
     */
538 View Code Duplication
    protected static function getGraphQLAccessControl($annotation)
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...
539
    {
540
        if (array_key_exists('GraphQLAccessControl', $annotation) && array_key_exists('method', $annotation['GraphQLAccessControl'])) {
541
            return '@='.$annotation['GraphQLAccessControl']['method'];
542
        }
543
544
        return null;
545
    }
546
547
    /**
548
     * Get graphql public control.
549
     *
550
     * @param $annotation
551
     *
552
     * @return null|string
553
     */
554 View Code Duplication
    protected static function getGraphQLPublicControl($annotation)
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...
555
    {
556
        if (array_key_exists('GraphQLPublicControl', $annotation) && array_key_exists('method', $annotation['GraphQLPublicControl'])) {
557
            return '@='.$annotation['GraphQLPublicControl']['method'];
558
        }
559
560
        return null;
561
    }
562
563
    /**
564
     * Parse annotation.
565
     *
566
     * @param mixed $annotation
0 ignored issues
show
Documentation introduced by
There is no parameter named $annotation. Did you maybe mean $annotations?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
567
     *
568
     * @return array
569
     */
570
    protected static function parseAnnotation($annotations)
571
    {
572
        $returnAnnotation = [];
573
        foreach ($annotations as $index => $annotation) {
574
            if (!is_array($annotation)) {
575
                $index = explode('\\', get_class($annotation));
576
                $index = $index[count($index) - 1];
577
            }
578
579
            $returnAnnotation[$index] = [];
580
581
            foreach ($annotation as $indexAnnotation => $value) {
582
                $returnAnnotation[$index][$indexAnnotation] = $value;
583
            }
584
        }
585
586
        return $returnAnnotation;
587
    }
588
}
589