OptionsMethods   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 63
dl 0
loc 150
ccs 29
cts 29
cp 1
rs 10
c 3
b 0
f 0
wmc 26

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getMethodExtras() 0 17 4
A getJsonSchema() 0 13 3
A getInsFromParameterAttributes() 0 18 4
B getInsFromMethodAnnotations() 0 17 8
A __invoke() 0 20 4
A getInMap() 0 14 2
A __construct() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use BEAR\Resource\Annotation\Embed;
8
use BEAR\Resource\Annotation\JsonSchema;
9
use BEAR\Resource\Annotation\Link;
10
use Ray\Aop\ReflectionMethod;
11
use Ray\Di\Di\Named;
12
use Ray\WebContextParam\Annotation\AbstractWebContextParam;
13
use Ray\WebContextParam\Annotation\CookieParam;
14
use Ray\WebContextParam\Annotation\EnvParam;
15
use Ray\WebContextParam\Annotation\FilesParam;
16
use Ray\WebContextParam\Annotation\FormParam;
17
use Ray\WebContextParam\Annotation\QueryParam;
18
use Ray\WebContextParam\Annotation\ServerParam;
19
20
use function assert;
21
use function class_exists;
22
use function file_exists;
23
use function file_get_contents;
24
use function json_decode;
25
26
use const JSON_THROW_ON_ERROR;
27
28
/**
29
 * @psalm-import-type InsMap from Types
30
 * @psalm-import-type OptionsMethodsResponse from Types
31
 * @psalm-import-type OptionsResponse from Types
32
 */
33
final class OptionsMethods
34
{
35
    /**
36
     * Constants for annotation name and "in" name
37
     */
38
    private const WEB_CONTEXT_NAME = [
39
        CookieParam::class => 'cookie',
40
        EnvParam::class => 'env',
41
        FormParam::class => 'formData',
42 99
        QueryParam::class => 'query',
43
        ServerParam::class => 'server',
44 99
        FilesParam::class => 'files',
45 99
    ];
46 99
47
    public function __construct(
48 7
        #[Named('json_schema_dir')]
49
        private readonly string $schemaDir = '',
50 7
    ) {
51 7
    }
52 7
53 7
    /** @return OptionsMethodsResponse */
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\OptionsMethodsResponse 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...
54 7
    public function __invoke(ResourceObject $ro, string $requestMethod): array
55 7
    {
56 7
        $method = new ReflectionMethod($ro::class, 'on' . $requestMethod);
57 1
        $ins = $this->getInMap($method);
58
        [$doc, $paramDoc] = (new OptionsMethodDocBolck())($method);
59
        $methodOption = $doc;
60 6
        $paramMetas = (new OptionsMethodRequest())($method, $paramDoc, $ins);
61
        $schema = $this->getJsonSchema($method);
62
        $request = ! empty($paramMetas) ? ['request' => $paramMetas] : [];
63 7
        $methodOption += $request;
64
        if (! empty($schema)) {
65 7
            $methodOption += ['schema' => $schema];
66 7
        }
67 7
68 5
        $extras = $this->getMethodExtras($method);
69 5
        if (! empty($extras)) {
70
            $methodOption += $extras;
71
        }
72
73 7
        return $methodOption; // @phpstan-ignore-line
74
    }
75
76 7
    /**
77
     * @return (Embed|Link)[][]
78 7
     * @psalm-return array{links?: non-empty-list<Link>, embed?: non-empty-list<Embed>}
79 7
     * @phpstan-return (Embed|Link)[][]
80 5
     */
81
    private function getMethodExtras(ReflectionMethod $method): array
82 2
    {
83 2
        $extras = [];
84 1
        $annotations = $method->getAnnotations();
85
        foreach ($annotations as $annotation) {
86
            if ($annotation instanceof Link) {
87 1
                $extras['links'][] = $annotation;
88
            }
89
90
            if (! ($annotation instanceof Embed)) {
91
                continue;
92
            }
93
94
            $extras['embed'][] = $annotation;
95
        }
96
97
        return $extras;
98
    }
99
100
    /** @return InsMap */
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\InsMap 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...
101
    private function getInMap(ReflectionMethod $method): array
102
    {
103
        $ins = [];
104
        bc_for_annotation: {
105
            // @codeCoverageIgnoreStart
106
            $annotations = $method->getAnnotations();
107
            $ins = $this->getInsFromMethodAnnotations($annotations, $ins);
108
        if ($ins) {
109
            return $ins;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ins returns the type array which is incompatible with the documented return type BEAR\Resource\InsMap.
Loading history...
110
        }
111
            // @codeCoverageIgnoreEnd
112
        }
113
114
        return $this->getInsFromParameterAttributes($method, $ins);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getInsFrom...tributes($method, $ins) returns the type array which is incompatible with the documented return type BEAR\Resource\InsMap.
Loading history...
115
    }
116
117
    /** @return array<array-key, mixed> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, mixed> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, mixed>.
Loading history...
118
    private function getJsonSchema(ReflectionMethod $method): array
119
    {
120
        $schema = $method->getAnnotation(JsonSchema::class);
121
        if (! $schema instanceof JsonSchema) {
122
            return [];
123
        }
124
125
        $schemaFile = $this->schemaDir . '/' . $schema->schema;
126
        if (! file_exists($schemaFile)) {
127
            return [];
128
        }
129
130
        return (array) json_decode((string) file_get_contents($schemaFile), null, 512, JSON_THROW_ON_ERROR);
131
    }
132
133
    /**
134
     * @param array<object> $annotations
135
     * @param InsMap        $ins
136
     *
137
     * @return InsMap
138
     *
139
     * @codeCoverageIgnore BC for annotation
140
     */
141
    public function getInsFromMethodAnnotations(array $annotations, array $ins): array
142
    {
143
        foreach ($annotations as $annotation) {
144
            if (! ($annotation instanceof AbstractWebContextParam)) {
145
                continue;
146
            }
147
148
            $class = $annotation::class;
149
            assert(class_exists($class));
150
            /** @var array-key $webKey */
151
            assert($class === CookieParam::class || $class === EnvParam::class || $class === FormParam::class || $class === QueryParam::class || $class === ServerParam::class || $class === FilesParam::class);
152
            $webKey = self::WEB_CONTEXT_NAME[$class];
153
154
            $ins[$annotation->param] = $webKey;
155
        }
156
157
        return $ins;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ins returns the type array which is incompatible with the documented return type BEAR\Resource\InsMap.
Loading history...
158
    }
159
160
    /**
161
     * @param InsMap $ins
162
     *
163
     * @return InsMap
164
     */
165
    public function getInsFromParameterAttributes(ReflectionMethod $method, array $ins): array
166
    {
167
        $parameters = $method->getParameters();
168
        foreach ($parameters as $parameter) {
169
            $attributes = $parameter->getAttributes();
170
            foreach ($attributes as $attribute) {
171
                $instance = $attribute->newInstance();
172
                if (! ($instance instanceof AbstractWebContextParam)) {
173
                    continue;
174
                }
175
176
                /** @var array-key $class */
177
                $class = $instance::class;
178
                $ins[$parameter->name] = self::WEB_CONTEXT_NAME[$class];
179
            }
180
        }
181
182
        return $ins;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ins returns the type array which is incompatible with the documented return type BEAR\Resource\InsMap.
Loading history...
183
    }
184
}
185