Test Failed
Pull Request — master (#16)
by Divine Niiquaye
02:28
created

DomainRoute::domain()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 5
nop 1
dl 0
loc 15
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\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 $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
    public static function to(string $pattern, $methods = self::DEFAULT_METHODS, $handler = null): self
71
    {
72
        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\FastRoute which includes types incompatible with the type-hinted return Flight\Routing\Routes\DomainRoute.
Loading history...
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     *
78
     * @throws UriHandlerException
79
     */
80
    public function match(string $method, UriInterface $uri): self
81
    {
82
        if (isset($this->data['schemes'])) {
83
            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

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