Completed
Push — 1.x ( 7efb78...079849 )
by Akihito
04:35 queued 02:43
created

OptionsMethods::getType()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
rs 9.6666
ccs 5
cts 5
cp 1
cc 2
eloc 5
nc 2
nop 1
crap 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 phpDocumentor\Reflection\DocBlockFactory;
12
use Ray\Di\Di\Assisted;
13
14
final class OptionsMethods
15
{
16
    private $reader;
17
18 84
    public function __construct(Reader $reader)
19
    {
20 84
        $this->reader = $reader;
21 84
    }
22
23
    /**
24
     * @param ResourceObject $ro
25
     * @param string         $requestMethod
26
     *
27
     * @return array
28
     */
29 4
    public function __invoke(ResourceObject $ro, $requestMethod)
30
    {
31 4
        $method = new \ReflectionMethod($ro, 'on' . $requestMethod);
32 4
        $docComment = $method->getDocComment();
33 4
        $doc = $paramDoc = [];
34 4
        if ($docComment) {
35 4
            list($doc, $paramDoc) = $this->docBlock($docComment);
36
        }
37 4
        $parameters = $method->getParameters();
38 4
        list($paramDoc, $required) = $this->getParameterMetas($parameters, $paramDoc);
39 4
        $paramMetas = [];
40 4
        if ((bool) $paramDoc) {
41 2
            $paramMetas['parameters'] = $paramDoc;
42
        }
43 4
        if ((bool) $required) {
44 4
            $paramMetas['required'] = $required;
45
        }
46 4
        $paramMetas = $this->ignoreAnnotatedPrameter($method, $paramMetas);
47
48 4
        return $doc + $paramMetas;
49
    }
50
51
    /**
52
     * @param string $docComment
53
     *
54
     * @return array [$docs, $params]
55
     */
56 4
    private function docBlock($docComment)
57
    {
58 4
        $factory = DocBlockFactory::createInstance();
59 4
        $docblock = $factory->create($docComment);
60 4
        $summary = $docblock->getSummary();
61 4
        $docs = $params = [];
62 4
        if ($summary) {
63 1
            $docs['summary'] = $summary;
64
        }
65 4
        $description = (string) $docblock->getDescription();
66 4
        if ($description) {
67 1
            $docs['description'] = $description;
68
        }
69 4
        $tags = $docblock->getTagsByName('param');
70 4
        $params = $this->docBlogTags($tags, $params);
71
72 4
        return [$docs, $params];
73
    }
74
75
    /**
76
     * @param \ReflectionParameter $parameter
77
     * @param array                $paramDoc
78
     * @param string               $name
79
     *
80
     * @return string|null
81
     */
82 4
    private function getParameterType(\ReflectionParameter $parameter, array $paramDoc, $name)
83
    {
84 4
        $hasType = method_exists($parameter, 'getType') && $parameter->getType();
85 4
        if ($hasType) {
86 1
            return $this->getType($parameter);
87
        }
88 4
        if (isset($paramDoc[$name]['type'])) {
89 2
            return $paramDoc[$name]['type'];
90
        }
91 2
    }
92
93
    /**
94
     * @param \ReflectionParameter[] $parameters
95
     * @param array                  $paramDoc
96
     *
97
     * @return array [$paramDoc, $required]
98
     */
99 4
    private function getParameterMetas(array $parameters, array $paramDoc)
100
    {
101 4
        $required = [];
102 4
        foreach ($parameters as $parameter) {
103 4
            $paramDoc = $this->paramType($paramDoc, $parameter);
104 4
            if (! $parameter->isOptional()) {
105 4
                $required[] = $parameter->name;
106
            }
107 4
            $paramDoc = $this->paramDefault($paramDoc, $parameter);
108
        }
109
110 4
        return [$paramDoc, $required];
111
    }
112
113
    /**
114
     * @return array
115
     */
116 4
    private function paramDefault(array $paramDoc, \ReflectionParameter $parameter)
117
    {
118 4
        $hasDefault = $parameter->isDefaultValueAvailable() && $parameter->getDefaultValue() !== null;
119 4
        if ($hasDefault) {
120 1
            $paramDoc[$parameter->name]['default'] = (string) $parameter->getDefaultValue();
121
        }
122
123 4
        return $paramDoc;
124
    }
125
126
    /**
127
     * @return array
128
     */
129 4
    private function paramType(array $paramDoc, \ReflectionParameter $parameter)
130
    {
131 4
        $type = $this->getParameterType($parameter, $paramDoc, $parameter->name);
132 4
        if (is_string($type)) {
133 2
            $paramDoc[$parameter->name]['type'] = $type;
134
        }
135
136 4
        return $paramDoc;
137
    }
138
139
    /**
140
     * @param \ReflectionParameter $parameter
141
     *
142
     * @return string
143
     */
144 1
    private function getType(\ReflectionParameter $parameter)
145
    {
146 1
        $type = (string) $parameter->getType();
147 1
        if ($type === 'int') {
148 1
            $type = 'integer';
149
        }
150
151 1
        return $type;
152
    }
153
154
    /**
155
     * @return array
156
     */
157 4
    private function docBlogTags(array $tags, array $params)
158
    {
159 4
        foreach ($tags as $tag) {
160
            /* @var $tag \phpDocumentor\Reflection\DocBlock\Tags\Param */
161 2
            $varName = $tag->getVariableName();
162 2
            $tagType = (string) $tag->getType();
163 2
            $type = $tagType === 'int' ? 'integer' : $tagType;
164 2
            $params[$varName] = [
165 2
                'type' => $type
166
            ];
167 2
            $description = (string) $tag->getDescription();
168 2
            if ($description) {
169 2
                $params[$varName]['description'] = $description;
170
            }
171
        }
172
173 4
        return $params;
174
    }
175
176
    /**
177
     * Ignore @ Assisted @ ResourceParam parameter
178
     *
179
     * @return array
180
     */
181 4
    private function ignoreAnnotatedPrameter(\ReflectionMethod $method, array $paramMetas)
182
    {
183 4
        $annotations = $this->reader->getMethodAnnotations($method);
184 4
        foreach ($annotations as $annotation) {
185 2
            if ($annotation instanceof ResourceParam) {
186 1
                unset($paramMetas['parameters'][$annotation->param]);
187 1
                $paramMetas['required'] = array_values(array_diff($paramMetas['required'], [$annotation->param]));
188
            }
189 2
            if ($annotation instanceof Assisted) {
190 1
                $paramMetas = $this->ignorreAssisted($paramMetas, $annotation);
191
            }
192
        }
193
194 4
        return $paramMetas;
195
    }
196
197
    /**
198
     * Ignore @ Assisted parameter
199
     *
200
     * @return array
201
     */
202 1
    private function ignorreAssisted(array $paramMetas, Assisted $annotation)
203
    {
204 1
        $paramMetas['required'] = array_values(array_diff($paramMetas['required'], $annotation->values));
205 1
        foreach ($annotation->values as $varName) {
206 1
            unset($paramMetas['parameters'][$varName]);
207
        }
208
209 1
        return $paramMetas;
210
    }
211
}
212