Test Failed
Push — master ( b83ac1...f35ed8 )
by Divine Niiquaye
03:05
created

ValidationTrait::resolveController()   B

Complexity

Conditions 8
Paths 16

Size

Total Lines 36
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 17
c 1
b 0
f 0
nc 16
nop 2
dl 0
loc 36
rs 8.4444
ccs 11
cts 11
cp 1
crap 8
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 Flight\Routing\Interfaces\RouteInterface;
22
use Flight\Routing\Router;
23
use Psr\Http\Message\ServerRequestInterface;
24
use Psr\Http\Server\RequestHandlerInterface;
25
26
trait ValidationTrait
27
{
28
    /**
29
     * @param callable|object|string|string[] $controller
30
     *
31
     * @return mixed
32
     */
33 34
    protected function resolveNamespace($controller)
34
    {
35 34
        $namespace = $this->namespace;
36
37 4
        if (null !== $namespace && (\is_string($controller) || !$controller instanceof Closure)) {
38 4
            if (
39 4
                (
40
                    \is_string($controller) &&
41 3
                    !\class_exists($controller)
42
                ) &&
43
                !str_starts_with($controller, $namespace)
44 4
            ) {
45 1
                $controller = \is_callable($controller) ? $controller : $this->namespace . \ltrim($controller, '\\/');
46
            }
47
48
            if (\is_array($controller) && (!\is_object($controller[0]) && !\class_exists($controller[0]))) {
49 34
                $controller[0] = $this->namespace . \ltrim($controller[0], '\\/');
50
            }
51
        }
52
53
        return $controller;
54
    }
55
56
    /**
57
     * @param ServerRequestInterface $request
58 34
     * @param RouteInterface         $route
59
     *
60 34
     * @return mixed
61
     */
62
    protected function resolveController(ServerRequestInterface $request, RouteInterface &$route)
63
    {
64 34
        $controller = $route->getController();
65 34
66
        // Disable or enable HTTP request method prefix for action.
67 3
        if (str_ends_with($route->getName(), '__restful')) {
68
            switch (true) {
69
                case \is_array($controller):
70 34
                    $controller[1] = $this->getResourceMethod($request, $controller[1]);
71
72
                    break;
73
74 34
                case \is_string($controller) && \class_exists($controller):
75 11
                    $controller = [
76
                        $controller,
77
                        $this->getResourceMethod($request, \substr($route->getName(), -0, -9)),
78
                    ];
79 34
80 11
                    break;
81
            }
82
        }
83 23
84
        $handler = $this->resolveNamespace($controller);
85
86
        // For a class that implements RequestHandlerInterface, we will call handle()
87
        // if no method has been specified explicitly
88
        if (\is_string($handler) && \is_a($handler, RequestHandlerInterface::class, true)) {
89
            $handler = [$handler, 'handle'];
90
        }
91
92
        // If controller is instance of RequestHandlerInterface
93
        if ($handler instanceof RequestHandlerInterface) {
94 45
            return $handler->handle($request);
95
        }
96 45
97
        return $handler;
98
    }
99
100
    /**
101
     * Check if given request method matches given route method.
102
     *
103
     * @param string[] $routeMethod
104
     * @param string   $requestMethod
105
     *
106
     * @return bool
107
     */
108 43
    private function compareMethod(array $routeMethod, string $requestMethod): bool
109
    {
110 43
        return \in_array($requestMethod, $routeMethod, true);
111 43
    }
112
113
    /**
114
     * Check if given request domain matches given route domain.
115
     *
116
     * @param null|string              $routeDomain
117
     * @param string                   $requestDomain
118
     * @param array<int|string,string> $parameters
119
     *
120
     * @return bool
121
     */
122
    private function compareDomain(?string $routeDomain, string $requestDomain, array &$parameters): bool
123 47
    {
124
        return ($routeDomain === null || empty($routeDomain)) ||
125 47
            (bool) \preg_match($routeDomain, $requestDomain, $parameters);
126
    }
127
128
    /**
129
     * Check if given request uri matches given uri method.
130
     *
131
     * @param string                   $routeUri
132
     * @param string                   $requestUri
133
     * @param array<int|string,string> $parameters
134
     *
135
     * @return bool
136 42
     */
137
    private function compareUri(string $routeUri, string $requestUri, array &$parameters): bool
138 42
    {
139
        return (bool) \preg_match($routeUri, $requestUri, $parameters);
140
    }
141
142
    /**
143
     * Check if given request uri scheme matches given route scheme.
144
     *
145
     * @param string[] $routeScheme
146
     * @param string   $requestScheme
147
     *
148
     * @return bool
149 41
     */
150
    private function compareScheme(array $routeScheme, string $requestScheme): bool
151 41
    {
152 41
        return empty($routeScheme) || \in_array($requestScheme, $routeScheme, true);
153 6
    }
154
155
    /**
156
     * Get merged default parameters.
157 41
     *
158
     * @param array<int|string,mixed> $params
159
     * @param array<string,string>    $defaults
160
     *
161
     * @return array<string,string> Merged default parameters
162
     */
163
    private function mergeDefaults(array $params, array $defaults): array
164
    {
165
        foreach ($params as $key => $value) {
166
            if (!\is_int($key) && (!isset($defaults[$key]) || null !== $value)) {
167 47
                $defaults[$key] = $value;
168
            }
169 47
        }
170 1
171 1
        return $defaults;
172
    }
173 1
174
    /**
175
     * Merge Router attributes in route default and patterns.
176 1
     *
177
     * @param RouteInterface $route
178
     *
179 47
     * @return RouteInterface
180
     */
181
    private function mergeAttributes(RouteInterface $route): RouteInterface
182
    {
183
        foreach ($this->attributes as $type => $attributes) {
184
            if (Router::TYPE_DEFAULT === $type) {
185
                $route->setDefaults($attributes);
186
187
                continue;
188
            }
189
190
            $route->setPatterns($attributes);
191
        }
192
193
        return $route;
194
    }
195
196
    /**
197
     * @param ServerRequestInterface $request
198
     * @param string                 $name
199
     */
200
    private function getResourceMethod(ServerRequestInterface $request, string $name): string
201
    {
202
        return \strtolower($request->getMethod()) . \ucfirst($name);
203
    }
204
}
205