Issues (114)

src/OptionsMethodRequest.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
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 7
use function method_exists;
16
17 7
/**
18 7
 * @psalm-import-type OptionsResponse from Types
19
 * @psalm-import-type InsMap from Types
20 7
 */
21
final class OptionsMethodRequest
22 7
{
23
    /**
24 7
     * Parameter #2 $paramMetas of method BEAR\Resource\OptionsMethodRequest::ignoreAnnotatedPrameter() expects array('parameters' => array<string, array('type' =>
25
     *
26
     * @param array<array-key, array{type: string, description?: string}> $paramDoc
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, array{t... description?: string}> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, array{type: string, description?: string}>.
Loading history...
27
     * @param InsMap                                                      $ins
28
     *
29
     * @return OptionsResponse
30 7
     */
31
    public function __invoke(ReflectionMethod $method, array $paramDoc, array $ins): array
32 7
    {
33 7
        return $this->getParamMetas($method->getParameters(), $paramDoc, $ins);
34 7
    }
35
36 3
    /**
37 2
     * @param array<string, array{type?: string, description?: string}> $paramDoc
38
     *
39 1
     * @psalm-suppress RedundantCondition for BC
40
     */
41 7
    private function getParameterType(ReflectionParameter $parameter, array $paramDoc, string $name): string|null
42
    {
43 7
        $hasType = method_exists($parameter, 'getType') && $parameter->getType();
44 7
        if ($hasType) {
45 2
            return $this->getType($parameter);
46
        }
47 7
48 4
        return $paramDoc[$name]['type'] ?? null;
49
    }
50 7
51 7
    /**
52
     * @param array<ReflectionParameter>                               $parameters
53 7
     * @param array<string, array{type: string, description?: string}> $paramDoc
54
     * @param InsMap                                                   $ins
55 7
     *
56
     * @return OptionsResponse
57
     */
58
    private function getParamMetas(array $parameters, array $paramDoc, array $ins): array
59
    {
60
        foreach ($parameters as $parameter) {
61 7
            $name = (string) $parameter->name;
62
            if (isset($ins[$name])) {
63 7
                $paramDoc[$name]['in'] = $ins[$parameter->name];
64 7
            }
65 7
66 7
            if (! isset($paramDoc[$parameter->name])) {
67
                $paramDoc[$name] = [];
68
            }
69
70 7
            $paramDoc = $this->paramType($paramDoc, $parameter);
71
            $paramDoc = $this->paramDefault($paramDoc, $parameter);
72
        }
73 7
74
        $required = $this->getRequired($parameters);
75 7
76 7
        return $this->setParamMetas($paramDoc, $required);
77 2
    }
78
79
    /**
80 7
     * @param array<ReflectionParameter> $parameters
81
     *
82
     * @return string[]
83 7
     * @psalm-return list<string>
84
     */
85 7
    private function getRequired(array $parameters): array
86 7
    {
87 7
        $required = [];
88
        foreach ($parameters as $parameter) {
89
            if ($parameter->isOptional()) {
90 7
                continue;
91
            }
92
93 7
            $required[] = $parameter->name;
94
        }
95 7
96 7
        return $required;
97 4
    }
98
99
    /**
100 7
     * @param array<string, array{type?: string, description?: string}> $paramDoc
101
     *
102
     * @return array<string, array{type?: string, description?: string, default?: string}>
103
     *
104
     * @throws ReflectionException
105
     */
106 7
    private function paramDefault(array $paramDoc, ReflectionParameter $parameter): array
107
    {
108 7
        $hasDefault = $parameter->isDefaultValueAvailable() && $parameter->getDefaultValue() !== null;
109 7
        if ($hasDefault) {
110 5
            $default = $parameter->getDefaultValue();
111 1
            $paramDoc[(string) $parameter->name]['default'] = is_array($default) ? '[]' : (string) $parameter->getDefaultValue(); // @phpstan-ignore-lines
112 1
        }
113
114 5
        return $paramDoc;
115 5
    }
116
117
    /**
118
     * @param array<string, array{type?: string, description?: string, default?: string, in?: string}> $paramDoc
119 7
     *
120
     * @return array<string, array{type?: string, description?: string, default?: string, in?: string}>
121
     */
122
    private function paramType(array $paramDoc, ReflectionParameter $parameter): array
123
    {
124
        $type = $this->getParameterType($parameter, $paramDoc, $parameter->name);
125 1
        if (is_string($type)) {
126
            $paramDoc[(string) $parameter->name]['type'] = $type; // override type parameter by reflection over phpdoc param type
127 1
        }
128 1
129 1
        return $paramDoc;
130
    }
131
132 1
    private function getType(ReflectionParameter $parameter): string
133
    {
134
        $namedType = $parameter->getType();
135 7
        assert($namedType instanceof ReflectionNamedType);
136
        $type = $namedType->getName();
137 7
        if ($type === 'int') {
138 7
            $type = 'integer';
139 7
        }
140
141 7
        return $type;
142 7
    }
143
144
    /**
145 7
     * @param array<string, array{type?: string}> $paramDoc
146
     * @param list<string>                        $required
147
     *
148
     * @return OptionsResponse
149
     */
150
    private function setParamMetas(array $paramDoc, array $required): array
151
    {
152
        $paramMetas = [];
153
        if ((bool) $paramDoc) {
154
            $paramMetas['parameters'] = $paramDoc;
155
        }
156
157
        if ((bool) $required) {
158
            $paramMetas['required'] = $required;
159
        }
160
161
        return $paramMetas;
162
    }
163
}
164