Passed
Pull Request — 1.x (#321)
by Akihito
02:42
created

OptionsMethodRequest::paramDefault()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 5
nc 6
nop 2
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource\Options;
6
7
use ReflectionException;
8
use ReflectionMethod;
9
use ReflectionNamedType;
10
use ReflectionParameter;
11
12
use function assert;
13
use function is_array;
14
use function is_string;
15
use function method_exists;
16
17
/** @psalm-import-type OptionMethodMeta from InputParamMetaInterface */
18
final class OptionsMethodRequest
19
{
20
    /**
21
     * Parameter #2 $paramMetas of method BEAR\Resource\OptionsMethodRequest::ignoreAnnotatedPrameter() expects array('parameters' => array<string, array('type' =>
22
     *
23
     * @param array<string, array{type: string, description?: string}> $paramDoc
24
     * @param array<string, string>                                    $ins
25
     *
26
     * @return OptionMethodMeta
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\Options\OptionMethodMeta was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
     */
28
    public function __invoke(ReflectionMethod $method, array $paramDoc, array $ins): array
29
    {
30
        return $this->getParamMetas($method->getParameters(), $paramDoc, $ins);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getParamMe...ers(), $paramDoc, $ins) returns the type array which is incompatible with the documented return type BEAR\Resource\Options\OptionMethodMeta.
Loading history...
31
    }
32
33
    /**
34
     * @param array<string, array{type?: string, description?: string}> $paramDoc
35
     *
36
     * @psalm-suppress RedundantCondition for BC
37
     */
38
    private function getParameterType(ReflectionParameter $parameter, array $paramDoc, string $name): string|null
39
    {
40
        $hasType = method_exists($parameter, 'getType') && $parameter->getType();
41
        if ($hasType) {
42
            return $this->getType($parameter);
43
        }
44
45
        return $paramDoc[$name]['type'] ?? null;
46
    }
47
48
    /**
49
     * @param array<ReflectionParameter>                               $parameters
50
     * @param array<string, array{type: string, description?: string}> $paramDoc
51
     * @param array<string, string>                                    $ins
52
     *
53
     * @return OptionMethodMeta
54
     */
55
    private function getParamMetas(array $parameters, array $paramDoc, array $ins): array
56
    {
57
        foreach ($parameters as $parameter) {
58
            $name = $parameter->name;
59
            if (isset($ins[$name])) {
60
                $paramDoc[$name]['in'] = $ins[$parameter->name];
61
            }
62
63
            if (! isset($paramDoc[$parameter->name])) {
64
                $paramDoc[$name] = [];
65
            }
66
67
            $paramDoc = $this->paramType($paramDoc, $parameter);
68
            $paramDoc = $this->paramDefault($paramDoc, $parameter);
69
        }
70
71
        $required = $this->getRequired($parameters);
72
73
        return $this->setParamMetas($paramDoc, $required);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->setParamMetas($paramDoc, $required) returns the type array which is incompatible with the documented return type BEAR\Resource\Options\OptionMethodMeta.
Loading history...
74
    }
75
76
    /**
77
     * @param array<ReflectionParameter> $parameters
78
     *
79
     * @return string[]
80
     * @psalm-return list<string>
81
     */
82
    private function getRequired(array $parameters): array
83
    {
84
        $required = [];
85
        foreach ($parameters as $parameter) {
86
            if ($parameter->isOptional()) {
87
                continue;
88
            }
89
90
            $required[] = $parameter->name;
91
        }
92
93
        return $required;
94
    }
95
96
    /**
97
     * @param array<string, array{type?: string, description?: string}> $paramDoc
98
     *
99
     * @return array<string, array{type?: string, description?: string, default?: string}>
100
     *
101
     * @throws ReflectionException
102
     */
103
    private function paramDefault(array $paramDoc, ReflectionParameter $parameter): array
104
    {
105
        $hasDefault = $parameter->isDefaultValueAvailable() && $parameter->getDefaultValue() !== null;
106
        if ($hasDefault) {
107
            /** @psalm-suppress MixedAssignment */
108
            $default = $parameter->getDefaultValue();
109
            $paramDoc[$parameter->name]['default'] = is_array($default) ? '[]' : (string) $parameter->getDefaultValue(); // @phpstan-ignore-lines
110
        }
111
112
        return $paramDoc;
113
    }
114
115
    /**
116
     * @param array<string, array{type?: string, description?: string, default?: string, in?: string}> $paramDoc
117
     *
118
     * @return array<string, array{type?: string, description?: string, default?: string, in?: string}>
119
     */
120
    private function paramType(array $paramDoc, ReflectionParameter $parameter): array
121
    {
122
        $type = $this->getParameterType($parameter, $paramDoc, $parameter->name);
123
        if (is_string($type)) {
124
            $paramDoc[$parameter->name]['type'] = $type; // override type parameter by reflection over phpdoc param type
125
        }
126
127
        return $paramDoc;
128
    }
129
130
    private function getType(ReflectionParameter $parameter): string
131
    {
132
        $namedType = $parameter->getType();
133
        assert($namedType instanceof ReflectionNamedType);
134
        $type = $namedType->getName();
135
        if ($type === 'int') {
136
            $type = 'integer';
137
        }
138
139
        return $type;
140
    }
141
142
    /**
143
     * @param array<string, array{type?: string}> $paramDoc
144
     * @param list<string>                        $required
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\Options\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
145
     *
146
     * @return OptionMethodMeta
147
     */
148
    private function setParamMetas(array $paramDoc, array $required): array
149
    {
150
        $paramMetas = [];
151
        if ((bool) $paramDoc) {
152
            $paramMetas['parameters'] = $paramDoc;
153
        }
154
155
        if ((bool) $required) {
156
            $paramMetas['required'] = $required;
157
        }
158
159
        return $paramMetas;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $paramMetas returns the type array which is incompatible with the documented return type BEAR\Resource\Options\OptionMethodMeta.
Loading history...
160
    }
161
}
162