Test Failed
Branch master (effa58)
by Divine Niiquaye
02:13
created

Route::resolvePattern()   B

Complexity

Conditions 8
Paths 25

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 12
nc 25
nop 1
dl 0
loc 25
rs 8.4444
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.4 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\Routes;
19
20
use Flight\Routing\Exceptions\UriHandlerException;
21
22
/**
23
 * Value object representing a single route.
24
 *
25
 * The default support for this route class includes DomainRoute support:
26
 * - domain and schemes and handler casting from route pattern
27
 * - resolves route pattern prefixing
28
 *
29
 * @author Divine Niiquaye Ibok <[email protected]>
30
 */
31
class Route extends DomainRoute
32
{
33
    /**
34
     * A Pattern to Locates appropriate route by name, support dynamic route allocation using following pattern:
35
     * Pattern route:   `pattern/*<controller@action>`
36
     * Default route: `*<controller@action>`
37
     * Only action:   `pattern/*<action>`.
38
     *
39
     * @var string
40
     */
41
    public const RCA_PATTERN = '#^(?:([a-z]+)\:)?(?:\/{2}([^\/]+))?([^*]*)(?:\*\<(?:([\w+\\\\]+)\@)?(\w+)\>)?$#u';
42
43
    /**
44
     * Slashes supported on browser when used.
45
     *
46
     * @var string[]
47
     */
48
    public const URL_PREFIX_SLASHES = ['/' => '/', ':' => ':', '-' => '-', '_' => '_', '~' => '~', '@' => '@'];
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function prefix(string $path)
54
    {
55
        $this->data['path'] = self::resolvePrefix($this->data['path'], $path);
56
57
        return $this;
58
    }
59
60
    /**
61
     * Locates appropriate route by name. Support dynamic route allocation using following pattern:
62
     * Pattern route:   `pattern/*<controller@action>`
63
     * Default route: `*<controller@action>`
64
     * Only action:   `pattern/*<action>`.
65
     */
66
    protected function resolvePattern(string $pattern): string
67
    {
68
        \preg_match(self::RCA_PATTERN, $pattern, $matches, \PREG_UNMATCHED_AS_NULL);
69
70
        if (!empty($matches)) {
71
            if (isset($matches[1])) {
72
                $this->data['schemes'][] = $matches[1];
73
            }
74
75
            if (isset($matches[2])) {
76
                $this->data['hosts'][] = $matches[2];
77
            }
78
79
            if (isset($matches[5])) {
80
                // Match controller from route pattern.
81
                $handler = $matches[4] ?? $this->data['handler'] ?? null;
82
                $this->data['handler'] = !empty($handler) ? [$handler, $matches[5]] : $matches[5];
83
            }
84
85
            if (empty($matches[3] ?? '')) {
86
                throw new UriHandlerException(\sprintf('The route pattern "%s" is invalid as route path must be present in pattern.', $pattern));
87
            }
88
        }
89
90
        return $matches[3] ?? $pattern ?: '/';
91
    }
92
93
    /**
94
     * Ensures that the right-most slash is trimmed for prefixes of more than
95
     * one character, and that the prefix begins with a slash.
96
     */
97
    private static function resolvePrefix(string $uri, string $prefix): string
98
    {
99
        // This is not accepted, but we're just avoiding throwing an exception ...
100
        if (empty($prefix)) {
101
            return $uri;
102
        }
103
104
        if (isset(self::URL_PREFIX_SLASHES[$prefix[-1]], self::URL_PREFIX_SLASHES[$uri[0]])) {
105
            return $prefix . \ltrim($uri, \implode('', self::URL_PREFIX_SLASHES));
106
        }
107
108
        // browser supported slashes ...
109
        $slashExist = self::URL_PREFIX_SLASHES[$prefix[-1]] ?? self::URL_PREFIX_SLASHES[$uri[0]] ?? null;
110
111
        if (null === $slashExist) {
112
            $prefix .= '/';
113
        }
114
115
        return $prefix . $uri;
116
    }
117
}
118