Passed
Push — master ( 3c4285...612067 )
by Anatoly
01:05 queued 12s
created

ReferenceResolver::toMiddleware()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 23
ccs 13
cts 13
cp 1
rs 8.8333
cc 7
nc 5
nop 1
crap 7
1
<?php declare(strict_types=1);
2
3
/**
4
 * It's free open-source software released under the MIT License.
5
 *
6
 * @author Anatoly Fenric <[email protected]>
7
 * @copyright Copyright (c) 2018, Anatoly Fenric
8
 * @license https://github.com/sunrise-php/http-router/blob/master/LICENSE
9
 * @link https://github.com/sunrise-php/http-router
10
 */
11
12
namespace Sunrise\Http\Router;
13
14
/**
15
 * Import classes
16
 */
17
use Psr\Container\ContainerInterface;
18
use Psr\Http\Server\MiddlewareInterface;
19
use Psr\Http\Server\RequestHandlerInterface;
20
use Sunrise\Http\Router\Exception\UnresolvableReferenceException;
21
use Sunrise\Http\Router\Middleware\CallableMiddleware;
22
use Sunrise\Http\Router\RequestHandler\CallableRequestHandler;
23
use Closure;
24
use ReflectionClass;
25
use ReflectionMethod;
26
27
/**
28
 * Import functions
29
 */
30
use function is_array;
31
use function is_callable;
32
use function is_string;
33
use function is_subclass_of;
34
use function method_exists;
35
use function sprintf;
36
37
/**
38
 * ReferenceResolver
39
 *
40
 * @since 2.10.0
41
 */
42
class ReferenceResolver implements ReferenceResolverInterface
43
{
44
45
    /**
46
     * The reference resolver container
47
     *
48
     * @var ContainerInterface|null
49
     */
50
    private $container = null;
51
52
    /**
53
     * {@inheritdoc}
54
     */
55 4
    public function getContainer() : ?ContainerInterface
56
    {
57 4
        return $this->container;
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 5
    public function setContainer(?ContainerInterface $container) : void
64
    {
65 5
        $this->container = $container;
66 5
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71 28
    public function toRequestHandler($reference) : RequestHandlerInterface
72
    {
73 28
        if ($reference instanceof RequestHandlerInterface) {
74 14
            return $reference;
75
        }
76
77 16
        if ($reference instanceof Closure) {
78 1
            return new CallableRequestHandler($reference);
79
        }
80
81 16
        list($class, $method) = $this->normalizeReference($reference);
82
83 16
        if (isset($class, $method) && method_exists($class, $method)) {
84 3
            return new CallableRequestHandler([$this->resolveClass($class), $method]);
85
        }
86
87 15
        if (isset($class) && is_subclass_of($class, RequestHandlerInterface::class)) {
88 11
            return $this->resolveClass($class);
89
        }
90
91 4
        throw new UnresolvableReferenceException(sprintf(
92 4
            'Unable to resolve the "%s" reference to a request handler.',
93 4
            $this->stringifyReference($reference)
94
        ));
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100 19
    public function toMiddleware($reference) : MiddlewareInterface
101
    {
102 19
        if ($reference instanceof MiddlewareInterface) {
103 10
            return $reference;
104
        }
105
106 10
        if ($reference instanceof Closure) {
107 1
            return new CallableMiddleware($reference);
108
        }
109
110 10
        list($class, $method) = $this->normalizeReference($reference);
111
112 10
        if (isset($class, $method) && method_exists($class, $method)) {
113 2
            return new CallableMiddleware([$this->resolveClass($class), $method]);
114
        }
115
116 10
        if (isset($class) && is_subclass_of($class, MiddlewareInterface::class)) {
117 6
            return $this->resolveClass($class);
118
        }
119
120 4
        throw new UnresolvableReferenceException(sprintf(
121 4
            'Unable to resolve the "%s" reference to a middleware.',
122 4
            $this->stringifyReference($reference)
123
        ));
124
    }
125
126
    /**
127
     * Normalizes the given reference
128
     *
129
     * @param mixed $reference
130
     *
131
     * @return array
132
     */
133 21
    private function normalizeReference($reference) : array
134
    {
135 21
        if ($reference instanceof ReflectionClass) {
136 14
            return [$reference->getName(), null];
137
        }
138
139 14
        if ($reference instanceof ReflectionMethod) {
140 4
            return [$reference->getDeclaringClass()->getName(), $reference->getName()];
141
        }
142
143 13
        if (is_array($reference) && is_callable($reference, true)) {
144 5
            return $reference;
145
        }
146
147 11
        if (is_string($reference)) {
148 9
            return [$reference, null];
149
        }
150
151 2
        return [null, null];
152
    }
153
154
    /**
155
     * Stringifies the given reference
156
     *
157
     * @param mixed $reference
158
     *
159
     * @return string
160
     */
161 8
    private function stringifyReference($reference) : string
162
    {
163 8
        if ($reference instanceof ReflectionClass) {
164 2
            return $reference->getName();
165
        }
166
167
        // if ($reference instanceof ReflectionMethod) {
168
        //     return $reference->getDeclaringClass()->getName() . '@' . $reference->getName();
169
        // }
170
171 6
        if (is_array($reference) && is_callable($reference, true)) {
172 2
            return $reference[0] . '@' . $reference[1];
173
        }
174
175 4
        if (is_string($reference)) {
176 2
            return $reference;
177
        }
178
179 2
        return '';
180
    }
181
182
    /**
183
     * Resolves the given class
184
     *
185
     * @param string $class
186
     *
187
     * @return object
188
     */
189 13
    private function resolveClass(string $class)
190
    {
191 13
        if ($this->container && $this->container->has($class)) {
192 1
            return $this->container->get($class);
193
        }
194
195 12
        return new $class;
196
    }
197
}
198