Completed
Push — code201 ( 677523...68154a )
by Akihito
05:57
created

OptionsMethodRequest::setParamMetas()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 4
nop 2
1
<?php
2
/**
3
 * This file is part of the BEAR.Resource package.
4
 *
5
 * @license http://opensource.org/licenses/MIT MIT
6
 */
7
namespace BEAR\Resource;
8
9
use BEAR\Resource\Annotation\ResourceParam;
10
use Doctrine\Common\Annotations\Reader;
11
use Ray\Di\Di\Assisted;
12
13
final class OptionsMethodRequest
14
{
15
    private $reader;
16
17
    public function __construct(Reader $reader)
18
    {
19
        $this->reader = $reader;
20
    }
21
22
    public function __invoke(\ReflectionMethod $method, array $paramDoc, array $ins) : array
23
    {
24
        $paramMetas = $this->getParamMetas($method->getParameters(), $paramDoc, $ins);
25
        $paramMetas = $this->ignoreAnnotatedPrameter($method, $paramMetas);
26
27
        return $paramMetas;
28
    }
29
30
    /**
31
     * @param \ReflectionParameter $parameter
32
     * @param array                $paramDoc
33
     * @param string               $name
34
     *
35
     * @return string|null
36
     */
37
    private function getParameterType(\ReflectionParameter $parameter, array $paramDoc, string $name)
38
    {
39
        $hasType = method_exists($parameter, 'getType') && $parameter->getType();
40
        if ($hasType) {
41
            return $this->getType($parameter);
42
        }
43
        if (isset($paramDoc[$name]['type'])) {
44
            return $paramDoc[$name]['type'];
45
        }
46
    }
47
48
    private function getParamMetas(array $parameters, array $paramDoc, array $ins) : array
49
    {
50
        foreach ($parameters as $parameter) {
51
            if (isset($ins[$parameter->name])) {
52
                $paramDoc[$parameter->name]['in'] = $ins[$parameter->name];
53
            }
54
            if (! isset($paramDoc[$parameter->name])) {
55
                $paramDoc[$parameter->name] = [];
56
            }
57
            $paramDoc = $this->paramType($paramDoc, $parameter);
58
            $paramDoc = $this->paramDefault($paramDoc, $parameter);
59
        }
60
        $required = $this->getRequired($parameters);
61
        $paramMetas = $this->setParamMetas($paramDoc, $required);
62
63
        return $paramMetas;
64
    }
65
66
    /**
67
     * @param \ReflectionParameter[] $parameters
68
     */
69
    private function getRequired(array $parameters) : array
70
    {
71
        $required = [];
72
        foreach ($parameters as $parameter) {
73
            if (! $parameter->isOptional()) {
74
                $required[] = $parameter->name;
75
            }
76
        }
77
78
        return $required;
79
    }
80
81
    private function paramDefault(array $paramDoc, \ReflectionParameter $parameter) : array
82
    {
83
        $hasDefault = $parameter->isDefaultValueAvailable() && $parameter->getDefaultValue() !== null;
84
        if ($hasDefault) {
85
            $paramDoc[$parameter->name]['default'] = (string) $parameter->getDefaultValue();
86
        }
87
88
        return $paramDoc;
89
    }
90
91
    private function paramType(array $paramDoc, \ReflectionParameter $parameter) : array
92
    {
93
        $type = $this->getParameterType($parameter, $paramDoc, $parameter->name);
94
        if (is_string($type)) {
95
            $paramDoc[$parameter->name]['type'] = $type;
96
        }
97
98
        return $paramDoc;
99
    }
100
101
    /**
102
     * @param \ReflectionParameter $parameter
103
     */
104
    private function getType(\ReflectionParameter $parameter) : string
105
    {
106
        $type = (string) $parameter->getType();
107
        if ($type === 'int') {
108
            $type = 'integer';
109
        }
110
111
        return $type;
112
    }
113
114
    /**
115
     * Ignore @ Assisted @ ResourceParam parameter
116
     */
117
    private function ignoreAnnotatedPrameter(\ReflectionMethod $method, array $paramMetas) : array
118
    {
119
        $annotations = $this->reader->getMethodAnnotations($method);
120
        foreach ($annotations as $annotation) {
121
            if ($annotation instanceof ResourceParam) {
122
                unset($paramMetas['parameters'][$annotation->param]);
123
                $paramMetas['required'] = array_values(array_diff($paramMetas['required'], [$annotation->param]));
124
            }
125
            if ($annotation instanceof Assisted) {
126
                $paramMetas = $this->ignorreAssisted($paramMetas, $annotation);
127
            }
128
        }
129
130
        return $paramMetas;
131
    }
132
133
    /**
134
     * Ignore @ Assisted parameter
135
     */
136
    private function ignorreAssisted(array $paramMetas, Assisted $annotation) : array
137
    {
138
        $paramMetas['required'] = array_values(array_diff($paramMetas['required'], $annotation->values));
139
        foreach ($annotation->values as $varName) {
140
            unset($paramMetas['parameters'][$varName]);
141
        }
142
143
        return $paramMetas;
144
    }
145
146
    private function setParamMetas(array $paramDoc, array $required) : array
147
    {
148
        $paramMetas = [];
149
        if ((bool) $paramDoc) {
150
            $paramMetas['parameters'] = $paramDoc;
151
        }
152
        if ((bool) $required) {
153
            $paramMetas['required'] = $required;
154
        }
155
156
        return $paramMetas;
157
    }
158
}
159