Passed
Push — master ( 8fb003...dae8ba )
by Divine Niiquaye
11:39
created

CastingTrait::castRoute()   B

Complexity

Conditions 8
Paths 7

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 8.0291

Importance

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