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

DomainRoute::resolvePattern()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 9
nop 1
dl 0
loc 19
rs 9.6111
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
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
 * @method string[] getSchemes() Gets the route hosts schemes.
32
 * @method string[] getHosts()   Gets the route hosts.
33
 *
34
 * @author Divine Niiquaye Ibok <[email protected]>
35
 */
36
class DomainRoute extends FastRoute
37
{
38
    /**
39
     * A Pattern to match protocol, host and port from a url.
40
     *
41
     * Examples of urls that can be matched: http://en.example.domain, {sub}.example.domain, https://example.com:34, example.com, etc.
42
     *
43
     * @var string[]
44
     */
45
    public const URL_PATTERN = ['#^(?:([a-z]+)\:\/{2})?([^\/]+)?$#u', '#^(?:([a-z]+)\:)?(?:\/{2}([^\/]+))?(?:(\/.*))?$#u'];
46
47
    protected static array $getter = [
48
        'name' => 'name',
49
        'path' => 'path',
50
        'methods' => 'methods*',
51
        'schemes' => 'schemes*',
52
        'hosts' => 'hosts*',
53
        'handler' => 'handler',
54
        'arguments' => 'arguments*',
55
        'patterns' => 'patterns*',
56
        'defaults' => 'defaults*',
57
    ];
58
59
    public function __construct(string $pattern, $methods = self::DEFAULT_METHODS, $handler = null)
60
    {
61
        parent::__construct('', $methods, $handler);
62
63
        // Resolve route pattern ...
64
        $this->data['path'] .= $this->resolvePattern($pattern);
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     *
70
     * @throws UriHandlerException
71
     */
72
    public function match(string $method, UriInterface $uri)
73
    {
74
        $matched = parent::match($method, $uri);
75
76
        if (isset($this->data['schemes'])) {
77
            if (\in_array($uri->getScheme(), $this->get('schemes'), true)) {
0 ignored issues
show
Bug introduced by
It seems like $this->get('schemes') can also be of type null; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

77
            if (\in_array($uri->getScheme(), /** @scrutinizer ignore-type */ $this->get('schemes'), true)) {
Loading history...
78
                return $matched;
79
            }
80
81
            throw new UriHandlerException(\sprintf('Unfortunately current scheme "%s" is not allowed on requested uri [%s].', $uri->getScheme(), $uri->getPath()), 400);
82
        }
83
84
        return $matched;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function path(string $pattern)
91
    {
92
        return parent::path($this->resolvePattern($pattern));
93
    }
94
95
    /**
96
     * Sets the requirement of host on this Route.
97
     *
98
     * @param string $hosts The host for which this route should be enabled
99
     *
100
     * @return static
101
     */
102
    public function domain(string ...$hosts)
103
    {
104
        foreach ($hosts as $host) {
105
            \preg_match(self::URL_PATTERN[0], $host, $matches, \PREG_UNMATCHED_AS_NULL);
106
107
            if (isset($matches[1])) {
108
                $this->data['schemes'][] = $matches[1];
109
            }
110
111
            if (isset($matches[2])) {
112
                $this->data['hosts'][] = $matches[2];
113
            }
114
        }
115
116
        return $this;
117
    }
118
119
    /**
120
     * Sets the requirement of domain scheme on this Route.
121
     *
122
     * @param string ...$schemes
123
     *
124
     * @return static
125
     */
126
    public function scheme(string ...$schemes)
127
    {
128
        foreach ($schemes as $scheme) {
129
            $this->data['schemes'][] = \strtolower($scheme);
130
        }
131
132
        return $this;
133
    }
134
135
    protected function resolvePattern(string $pattern): string
136
    {
137
        \preg_match(self::URL_PATTERN[1], $pattern, $matches, \PREG_UNMATCHED_AS_NULL);
138
139
        if (!empty($matches)) {
140
            if (isset($matches[1])) {
141
                $this->data['schemes'][] = $matches[1];
142
            }
143
144
            if (isset($matches[2])) {
145
                $this->data['hosts'][] = $matches[2];
146
            }
147
148
            if (!isset($matches[3])) {
149
                throw new UriHandlerException('A route path not could not be found, Did you forget include one.');
150
            }
151
        }
152
153
        return $matches[3] ?? $pattern;
154
    }
155
}
156