Test Failed
Pull Request — master (#13)
by Divine Niiquaye
02:21
created

CastingTrait::castRoute()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 10
c 4
b 0
f 0
dl 0
loc 21
rs 9.2222
ccs 9
cts 9
cp 1
cc 6
nc 7
nop 1
crap 6
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 Flight\Routing\Exceptions\InvalidControllerException;
21
use Flight\Routing\Route;
22
23
trait CastingTrait
24
{
25
    /** @var null|string */
26
    private $name;
27
28
    /** @var string */
29
    private $path;
30
31 67
    /** @var array<string,bool> */
32
    private $methods = [];
33 67
34
    /** @var array<string,bool> */
35
    private $domain = [];
36
37
    /** @var array<string,bool> */
38
    private $schemes = [];
39
40
    /** @var array<string,mixed> */
41 28
    private $defaults = [];
42
43 28
    /** @var array<string,string|string[]> */
44 28
    private $patterns = [];
45
46
    /** @var array<int,mixed> */
47
    private $middlewares = [];
48
49
    /** @var mixed */
50
    private $controller;
51
52
    /**
53
     * Locates appropriate route by name. Support dynamic route allocation using following pattern:
54
     * Pattern route:   `pattern/*<controller@action>`
55
     * Default route: `*<controller@action>`
56
     * Only action:   `pattern/*<action>`.
57
     *
58 151
     * @param string $route
59
     *
60 151
     * @throws InvalidControllerException
61
     *
62
     * @return string
63 151
     */
64
    private function castRoute(string $route): string
65 151
    {
66 5
        $urlRegex = \strtr(Route::URL_PATTERN, ['/^' => '/^(?:', '$/u' => ')']);
67
68
        // Match url + rca from pattern...
69 150
        \preg_match($urlRegex . \strtr(Route::RCA_PATTERN, ['/^' => '?']), $route, $matches);
70 5
71 4
        if (empty($matches)) {
72
            return $route;
73
        }
74 5
75
        if (isset($matches['c'], $matches['a'])) {
76
            $handler          = $matches['c'] ?: $this->controller;
77 150
            $this->controller = !$handler ? $matches['a'] : [$handler, $matches['a']];
78 150
        }
79
80
        if (isset($matches['domain'])) {
81 149
            $route = $this->castDomain($matches, $route);
82
        }
83
84
        return $route;
85
    }
86
87
    /**
88
     * Match scheme and domain from route patterned path
89
     *
90
     * @param array<int|string,null|string> $matches
91
     * @param string                        $route
92 150
     *
93
     * @return string
94 150
     */
95
    private function castDomain(array $matches, string $route): string
96 150
    {
97 4
        $domain = $matches['domain'] ?? null;
98
99
        if (isset($matches['scheme']) && !empty($matches['scheme'])) {
100 150
            $this->schemes[$matches['scheme']] = true;
101 139
        }
102 139
103
        if ((!isset($matches[4]) || empty($matches[4])) && false === \strpos($domain ?? '', '//')) {
104
            $matches['route'] = $domain . ($matches['route'] ?? null);
105 150
            $domain           = null;
106
        }
107 150
108 1
        if (!empty($domain)) {
109
            $this->domain[$matches['host']] = true;
110
        }
111 149
112
        if (!isset($matches['route']) || empty($matches['route'])) {
113
            throw new InvalidControllerException("Unable to locate route candidate on `{$route}`");
114
        }
115
116
        return $matches['route'];
117
    }
118
119
    /**
120
     * Ensures that the right-most slash is trimmed for prefixes of more than
121
     * one character, and that the prefix begins with a slash.
122
     *
123 16
     * @param string $uri
124
     * @param string $prefix
125
     *
126 16
     * @return string
127 4
     */
128
    private function castPrefix(string $uri, string $prefix): string
129
    {
130 16
        // Allow homepage uri on prefix just like python django url style.
131 1
        if (empty($uri) || '/' === $uri) {
132
            return \rtrim($prefix, '/') . $uri;
133
        }
134 15
135
        if (1 === \preg_match('/^([^\/&\-_~\|@]+)(&|-|_|~|@)$/', $prefix, $matches)) {
136
            return \rtrim($prefix, $matches[2]) . $matches[2] . $uri;
137
        }
138
139
        return \rtrim($prefix, '/') . '/' . \ltrim($uri, '/');
140
    }
141
}
142