Test Failed
Pull Request — master (#16)
by Divine Niiquaye
02:28
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.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\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 static function to(string $pattern, $methods = self::DEFAULT_METHODS, $handler = null): self
54
    {
55
        return parent::to($pattern, $methods, $handler);
0 ignored issues
show
Bug Best Practice introduced by
The expression return parent::to($pattern, $methods, $handler) returns the type Flight\Routing\Routes\DomainRoute which includes types incompatible with the type-hinted return Flight\Routing\Routes\Route.
Loading history...
56
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function prefix(string $path): self
62
    {
63
        $this->data['path'] = self::resolvePrefix($this->data['path'], $path);
64
65
        return $this;
66
    }
67
68
    /**
69
     * Locates appropriate route by name. Support dynamic route allocation using following pattern:
70
     * Pattern route:   `pattern/*<controller@action>`
71
     * Default route: `*<controller@action>`
72
     * Only action:   `pattern/*<action>`.
73
     */
74
    protected function resolvePattern(string $pattern): string
75
    {
76
        \preg_match(self::RCA_PATTERN, $pattern, $matches, \PREG_UNMATCHED_AS_NULL);
77
78
        if (!empty($matches)) {
79
            if (isset($matches[1])) {
80
                $this->data['schemes'][] = $matches[1];
81
            }
82
83
            if (isset($matches[2])) {
84
                $this->data['hosts'][] = $matches[2];
85
            }
86
87
            if (isset($matches[5])) {
88
                // Match controller from route pattern.
89
                $handler = $matches[4] ?? $this->data['handler'] ?? null;
90
                $this->data['handler'] = !empty($handler) ? [$handler, $matches[5]] : $matches[5];
91
            }
92
93
            if (empty($matches[3] ?? '')) {
94
                throw new UriHandlerException(\sprintf('The route pattern "%s" is invalid as route path must be present in pattern.', $pattern));
95
            }
96
        }
97
98
        return $matches[3] ?? $pattern ?: '/';
99
    }
100
101
    /**
102
     * Ensures that the right-most slash is trimmed for prefixes of more than
103
     * one character, and that the prefix begins with a slash.
104
     */
105
    private static function resolvePrefix(string $uri, string $prefix): string
106
    {
107
        // This is not accepted, but we're just avoiding throwing an exception ...
108
        if (empty($prefix)) {
109
            return $uri;
110
        }
111
112
        if (isset(self::URL_PREFIX_SLASHES[$prefix[-1]], self::URL_PREFIX_SLASHES[$uri[0]])) {
113
            return $prefix . \ltrim($uri, \implode('', self::URL_PREFIX_SLASHES));
114
        }
115
116
        // browser supported slashes ...
117
        $slashExist = self::URL_PREFIX_SLASHES[$prefix[-1]] ?? self::URL_PREFIX_SLASHES[$uri[0]] ?? null;
118
119
        if (null === $slashExist) {
120
            $prefix .= '/';
121
        }
122
123
        return $prefix . $uri;
124
    }
125
}
126