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

CastingTrait::setController()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
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 array<mixed,string>|callable|string */
26
    private $controller;
27
28
    /**
29
     * {@inheritdoc}
30
     */
31 72
    public function getController()
32
    {
33 72
        return $this->controller;
34
    }
35
36
    /**
37
     * @internal Used to see a new handler, when matched.
38
     *
39
     * @param mixed $handler
40
     */
41 43
    public function setController($handler): void
42
    {
43 43
        $this->controller = $handler;
44 43
    }
45
46
    /**
47
     * Locates appropriate route by name. Support dynamic route allocation using following pattern:
48
     * Pattern route:   `pattern/*<controller@action>`
49
     * Default route: `*<controller@action>`
50
     * Only action:   `pattern/*<action>`.
51
     *
52
     * @param string $route
53
     *
54
     * @throws InvalidControllerException
55
     *
56
     * @return string
57
     */
58 152
    private function castRoute(string $route): string
59
    {
60
        // Match domain + scheme from pattern...
61 152
        if (false !== \preg_match($regex = '@^(?:(https?):)?(//[^/]+)@i', $route)) {
62 152
            $route = $this->castDomain($route, $regex);
63
        }
64
65 152
        if (false !== \strpbrk($route, '*') && false !== \preg_match(Route::RCA_PATTERN, $route, $matches)) {
66 5
            if (!isset($matches['route']) || empty($matches['route'])) {
67 1
                throw new InvalidControllerException("Unable to locate route candidate on `{$route}`");
68
            }
69
70 4
            if (isset($matches['controller'], $matches['action'])) {
71 4
                $this->controller = [$matches['controller'] ?: $this->controller, $matches['action']];
72
            }
73
74 4
            $route = $matches['route'];
75
        }
76
77 151
        return (empty($route) || '/' === $route) ? '/' : $route;
78
    }
79
80
    /**
81
     * Match scheme and domain from route patterned path
82
     *
83
     * @param string $route
84
     * @param string $regex
85
     *
86
     * @return string
87
     */
88 152
    private function castDomain(string $route, string $regex): string
89
    {
90 152
        return (string) \preg_replace_callback($regex, function (array $matches): string {
91 9
            $this->setDomain(isset($matches[1]) ? $matches[0] : $matches[2]);
0 ignored issues
show
Bug introduced by
It seems like setDomain() 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

91
            $this->/** @scrutinizer ignore-call */ 
92
                   setDomain(isset($matches[1]) ? $matches[0] : $matches[2]);
Loading history...
92
93 9
            return '';
94 152
        }, $route);
95
    }
96
97
    /**
98
     * Ensures that the right-most slash is trimmed for prefixes of more than
99
     * one character, and that the prefix begins with a slash.
100
     *
101
     * @param string $uri
102
     * @param string $prefix
103
     *
104
     * @return string
105
     */
106 15
    private function castPrefix(string $uri, string $prefix): string
107
    {
108
        // Allow homepage uri on prefix just like python django url style.
109 15
        if (\in_array($uri, ['', '/'], true)) {
110 7
            return \rtrim($prefix, '/') . $uri;
111
        }
112
113 15
        if (1 === \preg_match('/^([^\|\/|&|-|_|~|@]+)(&|-|_|~|@)/i', $prefix, $matches)) {
114 1
            $newPattern = \rtrim($prefix, $matches[2]) . $matches[2] . $uri;
115
        }
116
117 15
        return !empty($newPattern) ? $newPattern : \rtrim($prefix, '/') . '/' . \ltrim($uri, '/');
118
    }
119
}
120