Completed
Push — 1.x ( 1f4201...9079df )
by Akihito
05:22
created

NamedParameter::handleParams()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 17
cts 17
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 17
nc 6
nop 2
crap 7
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 BEAR\Resource\Exception\ParameterException;
11
use Doctrine\Common\Annotations\Reader;
12
use Doctrine\Common\Cache\Cache;
13
use Ray\Di\Di\Assisted;
14
use Ray\Di\InjectorInterface;
15
16
final class NamedParameter implements NamedParameterInterface
17
{
18
    /**
19
     * @var Cache
20
     */
21
    private $cache;
22
23
    /**
24
     * @var Reader
25
     */
26
    private $reader;
27
28
    /**
29
     * @var InjectorInterface
30
     */
31
    private $injector;
32
33 87
    public function __construct(Cache $cache, Reader $reader, InjectorInterface $injector)
34
    {
35 87
        $this->cache = $cache;
36 87
        $this->reader = $reader;
37 87
        $this->injector = $injector;
38 87
    }
39
40
    /**
41
     * {@inheritdoc}
42
     */
43 55
    public function getParameters(array $callable, array $query)
44
    {
45 55
        $id = __CLASS__ . get_class($callable[0]) . $callable[1];
46 55
        $names = $this->cache->fetch($id);
47 55
        if (! $names) {
48 54
            $names = $this->getNamedParamMetas($callable);
49 54
            $this->cache->save($id, $names);
50
        }
51 55
        $parameters = $this->handleParams($query, $names);
52
53 50
        return $parameters;
54
    }
55
56
    /**
57
     * Return named parameter information
58
     *
59
     * @param array $callable
60
     *
61
     * @return array
62
     */
63 54
    private function getNamedParamMetas(array $callable)
64
    {
65 54
        $method = new \ReflectionMethod($callable[0], $callable[1]);
66 54
        $parameters = $method->getParameters();
67 54
        $names = [];
68 54
        foreach ($parameters as $parameter) {
69 46
            $default = $parameter->isDefaultValueAvailable() === true ? $parameter->getDefaultValue() : new Param(get_class($callable[0]), $callable[1], $parameter->name);
70 46
            $names[$parameter->name] = $default;
71
        }
72 54
        $annotations = $this->reader->getMethodAnnotations($method);
73 54
        foreach ($annotations as $annotation) {
74 22
            if ($annotation instanceof ResourceParam) {
75 3
                $names[$annotation->param] = $annotation;
76
            }
77 22
            if ($annotation instanceof Assisted) {
78
                /* @var $annotation Assisted */
79 1
                foreach ($annotation->values as $assistedParam) {
80 1
                    $names[$assistedParam] = $annotation;
81
                }
82
            }
83
        }
84
85 54
        return $names;
86
    }
87
88
    /**
89
     * @param string[] $query caller value
90
     * @param string[] $names default value ['param-name' => 'param-type|param-value']
91
     *
92
     * @return array
93
     */
94 55
    private function handleParams(array $query, array $names)
95
    {
96 55
        $parameters = [];
97 55
        foreach ($names as $name => $param) {
98
            // @ResourceParam value
99 47
            if ($param instanceof ResourceParam) {
100 3
                $parameters[] = $this->getResourceParam($param, $query);
101 3
                continue;
102
            }
103
            // @Assisted (method injection) value
104 47
            if ($param instanceof Assisted) {
105 1
                $parameters[] = null;
106 1
                continue;
107
            }
108
            // query value
109 46
            if (isset($query[$name])) {
110 36
                $parameters[] = $query[$name];
111 36
                continue;
112
            }
113
            // default value
114 14
            if (is_scalar($param) || $param === null) {
115 9
                $parameters[] = $param;
116 9
                continue;
117
            }
118 5
            throw new ParameterException($name);
119
        }
120
121 50
        return $parameters;
122
    }
123
124
    /**
125
     * @param ResourceParam $resourceParam
126
     * @param array         $query
127
     *
128
     * @return mixed
129
     */
130 3
    private function getResourceParam(ResourceParam $resourceParam, array $query)
131
    {
132 3
        $uri = $resourceParam->templated === true ? uri_template($resourceParam->uri, $query) : $resourceParam->uri;
133 3
        $resource = $this->injector->getInstance(ResourceInterface::class);
134 3
        $resourceResult = $resource->get->uri($uri)->eager->request();
135 3
        $fragment = parse_url($uri, PHP_URL_FRAGMENT);
136
137 3
        return $resourceResult[$fragment];
138
    }
139
}
140