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

AbstractRoute::__set_state()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 6
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\{RouteCollection, Router};
21
use Flight\Routing\Exceptions\MethodNotAllowedException;
22
use Psr\Http\Message\UriInterface;
23
24
/**
25
 * An abstract route extended to routes.
26
 *
27
 * @author Divine Niiquaye Ibok <[email protected]>
28
 */
29
abstract class AbstractRoute
30
{
31
    /** @var array<int,string> Default methods for route. */
32
    public const DEFAULT_METHODS = [Router::METHOD_GET, Router::METHOD_HEAD];
33
34
    /** @var array<string,mixed> */
35
    protected array $data;
36
37
    /** @var array<int,string> */
38
    protected array $middlewares = [];
39
40
    private ?RouteCollection $collection = null;
41
42
    /**
43
     * Create a new Route constructor.
44
     *
45
     * @param string          $pattern The route pattern
46
     * @param string|string[] $methods the route HTTP methods
47
     * @param mixed           $handler The PHP class, object or callable that returns the response when matched
48
     */
49
    public function __construct(string $pattern, $methods = self::DEFAULT_METHODS, $handler = null)
50
    {
51
        $this->data = ['path' => $pattern, 'handler' => $handler];
52
53
        foreach ((array) $methods as $method) {
54
            $this->data['methods'][\strtoupper($method)] = true;
55
        }
56
    }
57
58
    /**
59
     * @internal
60
     */
61
    public function __serialize(): array
62
    {
63
        return $this->data;
64
    }
65
66
    /**
67
     * @internal
68
     *
69
     * @param array<string,mixed> $data
70
     */
71
    public function __unserialize(array $data): void
72
    {
73
        $this->data = $data;
74
    }
75
76
    /**
77
     * @internal
78
     *
79
     * @param array<string,mixed> $properties The route data properties
80
     *
81
     * @return static
82
     */
83
    public static function __set_state(array $properties)
84
    {
85
        $route = new static($properties['path'] ?? '', $properties['methods'] ?? [], $properties['handler'] ?? null);
86
        $route->data += \array_diff_key($properties, ['path' => null, 'methods' => [], 'handler' => null]);
87
88
        return $route;
89
    }
90
91
    /**
92
     * Create a new Route statically.
93
     *
94
     * @param string          $pattern The route pattern
95
     * @param string|string[] $methods the route HTTP methods
96
     * @param mixed           $handler The PHP class, object or callable that returns the response when matched
97
     *
98
     * @return static
99
     */
100
    public static function to(string $pattern, $methods = self::DEFAULT_METHODS, $handler = null)
101
    {
102
        return new static($pattern, $methods, $handler);
103
    }
104
105
    /**
106
     * Asserts route.
107
     *
108
     * @throws MethodNotAllowedException
109
     *
110
     * @return static
111
     */
112
    public function match(string $method, UriInterface $uri)
113
    {
114
        if (!\array_key_exists($method, $this->data['methods'] ?? [])) {
115
            throw new MethodNotAllowedException($this->getMethods(), $uri->getPath(), $method);
116
        }
117
118
        return $this;
119
    }
120
121
    /**
122
     * Sets the route belonging to a particular collection.
123
     *
124
     * This method is kinda internal, only used in RouteCollection class,
125
     * and retrieved using this class end method.
126
     *
127
     * @internal used by RouteCollection class
128
     */
129
    public function belong(RouteCollection $to): void
130
    {
131
        $this->collection = $to;
132
    }
133
134
    /**
135
     * End a group stack or return self.
136
     */
137
    public function end(): ?RouteCollection
138
    {
139
        if (null !== $stack = $this->collection) {
140
            $this->collection = null; // Just remove it.
141
        }
142
143
        return $stack;
144
    }
145
146
    public function getName(): ?string
147
    {
148
        return $this->data['name'] ?? null;
149
    }
150
151
    public function getPath(): string
152
    {
153
        $path = $this->data['path'] ?? '/';
154
155
        if ('/' === $path[0]) {
156
            return $path;
157
        }
158
159
        return '/' . $path;
160
    }
161
162
    /**
163
     * @return array<int,string>
164
     */
165
    public function getMethods(): array
166
    {
167
        return \array_keys($this->data['methods'] ?? []);
168
    }
169
170
    /**
171
     * @return array<int|string,mixed>
172
     */
173
    public function getArguments(): array
174
    {
175
        return $this->data['arguments'] ?? [];
176
    }
177
178
    /**
179
     * @return mixed
180
     */
181
    public function getHandler()
182
    {
183
        return $this->data['handler'] ?? null;
184
    }
185
186
    /**
187
     * @return array<int|string,mixed>
188
     */
189
    public function getDefaults(): array
190
    {
191
        return $this->data['defaults'] ?? [];
192
    }
193
194
    /**
195
     * @return array<string,string|string[]>
196
     */
197
    public function getPatterns(): array
198
    {
199
        return $this->data['patterns'] ?? [];
200
    }
201
202
    /**
203
     * Return the list of attached grouped middlewares.
204
     *
205
     * @return array<int,string>
206
     */
207
    public function getPiped(): array
208
    {
209
        return $this->middlewares;
210
    }
211
212
    public function generateRouteName(string $prefix): string
213
    {
214
        $routeName = \implode('_', $this->getMethods()) . '_' . $prefix . $this->data['path'] ?? '';
215
        $routeName = \str_replace(['/', ':', '|', '-'], '_', $routeName);
216
        $routeName = (string) \preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName);
217
218
        return (string) \preg_replace(['/\_+/', '/\.+/'], ['_', '.'], $routeName);
219
    }
220
}
221