Test Failed
Push — master ( 08de7a...d45f24 )
by Divine Niiquaye
11:57
created

DomainRoute::getSchemes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 5
rs 10
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
use Psr\Http\Message\UriInterface;
22
23
/**
24
 * Value object representing a single route.
25
 *
26
 * The default support for this route class includes FastRoute support:
27
 * - hosts binding
28
 * - schemes binding
29
 * - domain and schemes casting from route pattern
30
 *
31
 * @author Divine Niiquaye Ibok <[email protected]>
32
 */
33
class DomainRoute extends FastRoute
34
{
35
    /**
36
     * A Pattern to match protocol, host and port from a url.
37
     *
38
     * Examples of urls that can be matched: http://en.example.domain, {sub}.example.domain, https://example.com:34, example.com, etc.
39
     *
40
     * @var string[]
41
     */
42
    public const URL_PATTERN = ['#^(?:([a-z]+)\:\/{2})?([^\/]+)?$#u', '#^(?:([a-z]+)\:)?(?:\/{2}([^\/]+))?(?:(\/.*))?$#u'];
43
44
    public function __construct(string $pattern, $methods = self::DEFAULT_METHODS, $handler = null)
45
    {
46
        parent::__construct('', $methods, $handler);
47
48
        // Resolve route pattern ...
49
        $this->data['path'] .= $this->resolvePattern($pattern);
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     *
55
     * @throws UriHandlerException
56
     */
57
    public function match(string $method, UriInterface $uri)
58
    {
59
        $matched = parent::match($method, $uri);
60
61
        if (isset($this->data['schemes'])) {
62
            if (\array_key_exists($uri->getScheme(), $this->data['schemes'])) {
63
                return $matched;
64
            }
65
66
            throw new UriHandlerException(\sprintf('Unfortunately current scheme "%s" is not allowed on requested uri [%s].', $uri->getScheme(), $uri->getPath()), 400);
67
        }
68
69
        return $matched;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function path(string $pattern)
76
    {
77
        return parent::path($this->resolvePattern($pattern));
78
    }
79
80
    /**
81
     * Sets the requirement of host on this Route.
82
     *
83
     * @param string $hosts The host for which this route should be enabled
84
     *
85
     * @return static
86
     */
87
    public function domain(string ...$hosts)
88
    {
89
        foreach ($hosts as $host) {
90
            \preg_match(self::URL_PATTERN[0], $host, $matches, \PREG_UNMATCHED_AS_NULL);
91
92
            if (isset($matches[1])) {
93
                $this->data['schemes'][$matches[1]] = true;
94
            }
95
96
            if (isset($matches[2])) {
97
                $this->data['hosts'][$matches[2]] = true;
98
            }
99
        }
100
101
        return $this;
102
    }
103
104
    /**
105
     * Sets the requirement of domain scheme on this Route.
106
     *
107
     * @param string ...$schemes
108
     *
109
     * @return static
110
     */
111
    public function scheme(string ...$schemes)
112
    {
113
        foreach ($schemes as $scheme) {
114
            $this->data['schemes'][$scheme] = true;
115
        }
116
117
        return $this;
118
    }
119
120
    /**
121
     * @return array<int,string>
122
     */
123
    public function getSchemes(): array
124
    {
125
        $schemes = $this->data['schemes'] ?? [];
126
127
        return [] === $schemes ? $schemes : \array_keys($schemes);
128
    }
129
130
    /**
131
     * @return array<int,string>
132
     */
133
    public function getHosts(): array
134
    {
135
        $hosts = $this->data['hosts'] ?? [];
136
137
        return [] === $hosts ? $hosts : \array_keys($hosts);
138
    }
139
140
    protected function resolvePattern(string $pattern): string
141
    {
142
        if (1 === \preg_match(self::URL_PATTERN[1], $pattern, $matches, \PREG_UNMATCHED_AS_NULL)) {
143
            if (null !== $matches[1]) {
144
                $this->data['schemes'][$matches[1]] = true;
145
            }
146
147
            if (null !== $matches[2]) {
148
                $this->data['hosts'][$matches[2]] = true;
149
            }
150
151
            if (empty($matches[3])) {
152
                throw new UriHandlerException('A route path not could not be found, Did you forget include one.');
153
            }
154
155
            return $matches[3];
156
        }
157
158
        return $pattern;
159
    }
160
}
161