Completed
Push — code201 ( 677523...68154a )
by Akihito
08:44 queued 05:59
created

NamedParameter::getParam()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
eloc 2
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 Doctrine\Common\Cache\Cache;
12
use Ray\Di\Di\Assisted;
13
use Ray\Di\InjectorInterface;
14
use Ray\WebContextParam\Annotation\AbstractWebContextParam;
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
    /**
34
     * @var array
35
     */
36
    private $globals;
37
38 102
    public function __construct(Cache $cache, Reader $reader, InjectorInterface $injector, array $globals = [])
39
    {
40 102
        $this->cache = $cache;
41 102
        $this->reader = $reader;
42 102
        $this->injector = $injector;
43 102
        $this->globals = $globals;
44 102
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49 67
    public function getParameters(array $callable, array $query)
50
    {
51 67
        $cacheId = __CLASS__ . get_class($callable[0]) . $callable[1];
52 67
        $names = $this->cache->fetch($cacheId);
53 67
        if (! $names) {
54 64
            $names = $this->getNamedParamMetas($callable);
55 64
            $this->cache->save($cacheId, $names);
56
        }
57 67
        $parameters = $this->evaluateParams($query, $names);
58
59 60
        return $parameters;
60
    }
61
62
    /**
63
     * Return evaluated parameters
64
     *
65
     * @param array            $query caller value
66
     * @param ParamInterface[] $names Param object[] ['varName' => ParamInterface]
67
     */
68 67
    private function evaluateParams(array $query, array $names) : array
69
    {
70 67
        $parameters = [];
71 67
        foreach ($names as $varName => $param) {
72
            /* @var $param ParamInterface */
73 59
            $parameters[] = $param($varName, $query, $this->injector);
74
        }
75
76 60
        return $parameters;
77
    }
78
79
    /**
80
     * Return named parameter metas
81
     */
82 64
    private function getNamedParamMetas(callable $callable) : array
83
    {
84 64
        $method = new \ReflectionMethod($callable[0], $callable[1]);
85 64
        $parameters = $method->getParameters();
86 64
        $annotations = $this->reader->getMethodAnnotations($method);
87 64
        $assistedNames = $this->getAssistedNames($annotations);
88 64
        $webContext = $this->getWebContext($annotations);
89 64
        $namedParamMetas = $this->addNamedParams($parameters, $assistedNames, $webContext);
90
91 64
        return $namedParamMetas;
92
    }
93
94 64
    private function getAssistedNames(array $annotations) : array
95
    {
96 64
        $names = [];
97 64
        foreach ($annotations as $annotation) {
98 31
            if ($annotation instanceof ResourceParam) {
99 3
                $names[$annotation->param] = new AssistedResourceParam($annotation);
100
            }
101 31
            if ($annotation instanceof Assisted) {
102 31
                $names = $this->setAssistedAnnotation($names, $annotation);
103
            }
104
        }
105
106 64
        return $names;
107
    }
108
109 64
    private function getWebContext(array $annotations) : array
110
    {
111 64
        $webcontext = [];
112 64
        foreach ($annotations as $annotation) {
113 31
            if ($annotation instanceof AbstractWebContextParam) {
114 31
                $webcontext[$annotation->param] = $annotation;
115
            }
116
        }
117
118 64
        return $webcontext;
119
    }
120
121 1
    private function setAssistedAnnotation(array $names, Assisted $assisted) : array
122
    {
123
        /* @var $annotation Assisted */
124 1
        foreach ($assisted->values as $assistedParam) {
125 1
            $names[$assistedParam] = new AssistedParam;
126
        }
127
128 1
        return $names;
129
    }
130
131
    /**
132
     * @param \ReflectionParameter[] $parameters
133
     * @param array                  $assistedNames
134
     * @param array                  $webcontext
135
     *
136
     * @return ParamInterface[]
137
     */
138 64
    private function addNamedParams(array $parameters, array $assistedNames, array $webcontext) : array
139
    {
140 64
        $names = [];
141 64
        foreach ($parameters as $parameter) {
142 55
            if (isset($assistedNames[$parameter->name])) {
143 4
                $names[$parameter->name] = $assistedNames[$parameter->name];
144 4
                continue;
145
            }
146 54
            if (isset($webcontext[$parameter->name])) {
147 4
                $default = $this->getDefault($parameter);
148 4
                $names[$parameter->name] = new AssistedWebContextParam($webcontext[$parameter->name], $default);
149 4
                continue;
150
            }
151 52
            $names[$parameter->name] = $this->getParam($parameter);
152
        }
153
154 64
        return $names;
155
    }
156
157 4
    private function getDefault(\ReflectionParameter $parameter) : ParamInterface
158
    {
159 4
        return $parameter->isDefaultValueAvailable() === true ? new DefaultParam($parameter->getDefaultValue()) : new NoDefaultParam();
160
    }
161
162 52
    private function getParam(\ReflectionParameter $parameter) : ParamInterface
163
    {
164 52
        return $parameter->isDefaultValueAvailable() === true ? new OptionalParam($parameter->getDefaultValue()) : new RequiredParam;
165
    }
166
}
167