Passed
Push — master ( 8df7ad...310ad9 )
by Divine Niiquaye
07:56
created

ResolveTrait::resolveNamespace()   B

Complexity

Conditions 10
Paths 7

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 10

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 10
eloc 9
nc 7
nop 1
dl 0
loc 18
ccs 9
cts 9
cp 1
crap 10
rs 7.6666
c 2
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Flight Routing.
7
 *
8
 * PHP version 7.1 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 Biurad Group (https://biurad.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Flight\Routing\Traits;
19
20
use Closure;
21
use DivineNii\Invoker\Exceptions\NotCallableException;
22
use DivineNii\Invoker\Interfaces\InvokerInterface;
23
use Flight\Routing\Interfaces\RouteInterface;
24
use Psr\Http\Message\ResponseInterface;
25
use Psr\Http\Message\ServerRequestInterface;
26
use Psr\Http\Server\RequestHandlerInterface;
27
28
trait ResolveTrait
29
{
30
    /** @var RouteInterface */
31
    private $route;
32
33
    /** @var InvokerInterface */
34
    private $resolver;
35
36
    /**
37
     * @param ServerRequestInterface $request
38
     * @param string                 $path
39
     *
40
     * @return string
41
     */
42 50
    protected function resolvePath(ServerRequestInterface $request, string $path): string
43
    {
44 50
        $requestPath = $path;
45
46 50
        if ('cli' !== \PHP_SAPI) {
47
            $basePath    = \dirname($request->getServerParams()['SCRIPT_NAME'] ?? '');
48
            $requestPath = \substr($requestPath, \strlen($basePath)) ?: '/';
49
        }
50
51 50
        if (\strlen($requestPath) > 1) {
52 48
            $requestPath = \rtrim($requestPath, '/');
53
        }
54
55 50
        return \rawurldecode($requestPath);
56
    }
57
58
    /**
59
     * @param callable|object|string|string[] $controller
60
     *
61
     * @return mixed
62
     */
63 43
    protected function resolveNamespace($controller)
64
    {
65 43
        if ($controller instanceof Closure || null === $namespace = $this->namespace) {
66 39
            return $controller;
67
        }
68
69
        if (
70 4
            (\is_string($controller) && !\class_exists($controller)) &&
71 4
            !str_starts_with($controller, $namespace)
72
        ) {
73 3
            $controller = \is_callable($controller) ? $controller : $this->namespace . \ltrim($controller, '\\/');
74
        }
75
76 4
        if (\is_array($controller) && (!\is_object($controller[0]) && !\class_exists($controller[0]))) {
77 1
            $controller[0] = $this->namespace . \ltrim($controller[0], '\\/');
78
        }
79
80 4
        return $controller;
81
    }
82
83
    /**
84
     * @param ServerRequestInterface $request
85
     * @param RouteInterface         $route
86
     *
87
     * @throws NotCallableException
88
     *
89
     * @return callable|ResponseInterface
90
     */
91 43
    protected function resolveController(ServerRequestInterface $request, RouteInterface $route)
92
    {
93 43
        $handler = $this->resolveNamespace($this->resolveRestFul($request, $route));
94
95
        // For a class that implements RequestHandlerInterface, we will call handle()
96
        // if no method has been specified explicitly
97 43
        if (\is_string($handler) && \is_a($handler, RequestHandlerInterface::class, true)) {
98 12
            $handler = [$handler, 'handle'];
99
        }
100
101
        // If controller is instance of RequestHandlerInterface
102 43
        if ($handler instanceof RequestHandlerInterface) {
103 17
            return $handler->handle($request);
104
        }
105
106 26
        return $this->resolver->getCallableResolver()->resolve($handler);
107
    }
108
109
    /**
110
     * @param ServerRequestInterface $request
111
     * @param RouteInterface         $route
112
     *
113
     * @return mixed
114
     */
115 43
    protected function resolveRestFul(ServerRequestInterface $request, RouteInterface $route)
116
    {
117 43
        $controller = $route->getController();
118
119
        // Disable or enable HTTP request method prefix for action.
120 43
        if (str_ends_with($route->getName(), '__restful')) {
121
            switch (true) {
122 3
                case \is_array($controller):
123 2
                    $controller[1] = $this->getResourceMethod($request, $controller[1]);
0 ignored issues
show
Bug introduced by
It seems like getResourceMethod() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

123
                    /** @scrutinizer ignore-call */ 
124
                    $controller[1] = $this->getResourceMethod($request, $controller[1]);
Loading history...
124
125 2
                    break;
126
127 1
                case \is_string($controller) && \class_exists($controller):
128
                    $controller = [
129 1
                        $controller,
130 1
                        $this->getResourceMethod($request, \substr($route->getName(), -0, -9)),
131
                    ];
132
133 1
                    break;
134
            }
135
        }
136
137 43
        return $controller;
138
    }
139
140
    /**
141
     * @param ServerRequestInterface $request
142
     * @param ResponseInterface      $response
143
     *
144
     * @return mixed
145
     */
146 36
    protected function resolveRoute(ServerRequestInterface $request, ResponseInterface $response)
147
    {
148 36
        $handler = $this->route->getController();
149
150 36
        if ($handler instanceof ResponseInterface) {
151 11
            return $handler;
152
        }
153
154 25
        $arguments = \array_merge(
155 25
            $this->route->getArguments(),
156 25
            [\get_class($request) => $request, \get_class($response) => $response]
157
        );
158
159 25
        return $this->resolver->call($handler, $arguments);
160
    }
161
162
    /**
163
     * @param ServerRequestInterface $request
164
     * @param RouteInterface         $route
165
     */
166 43
    protected function resolveListeners(ServerRequestInterface $request, RouteInterface $route): void
167
    {
168 43
        $route->setController($this->resolveController($request, $route));
169 43
        $this->addMiddleware(...$route->getMiddlewares());
0 ignored issues
show
Bug introduced by
It seems like addMiddleware() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

169
        $this->/** @scrutinizer ignore-call */ 
170
               addMiddleware(...$route->getMiddlewares());
Loading history...
170
171 43
        foreach ($this->listeners as $listener) {
172 1
            $listener->onRoute($request, $route);
173
        }
174
175 43
        $this->route = clone $route;
176 43
    }
177
}
178