Test Failed
Push — master ( fd3819...5bc6ef )
by Divine Niiquaye
13:04
created

PrototypeTrait   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 230
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 39
c 2
b 0
f 0
dl 0
loc 230
rs 10
wmc 23

15 Methods

Rating   Name   Duplication   Size   Complexity  
A defaults() 0 3 1
A arguments() 0 3 1
A domain() 0 3 1
A piped() 0 3 1
A doPrototype() 0 19 5
A asserts() 0 3 1
A end() 0 14 3
A argument() 0 3 1
A prototype() 0 10 3
A scheme() 0 3 1
A prefix() 0 3 1
A assert() 0 3 1
A namespace() 0 3 1
A default() 0 3 1
A method() 0 3 1
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\Traits;
19
20
/**
21
 * A trait providing route method prototyping.
22
 *
23
 * @author Divine Niiquaye Ibok <[email protected]>
24
 */
25
trait PrototypeTrait
26
{
27
    private ?string $uniqueId;
28
29
    /** @var array<string,mixed[]>|null */
30
    private ?array $prototypes = [];
31
32
    /** @var array<string,bool> */
33
    private array $prototyped = [];
34
35
    /**
36
     * Allows a proxied method call to route's.
37
     *
38
     * @throws \RuntimeException if locked
39
     *
40
     * @return $this
41
     */
42
    public function prototype()
43
    {
44
        if (null === $uniqueId = $this->uniqueId) {
45
            throw new \RuntimeException('Routes method prototyping must be done before calling the getRoutes() method.');
46
        }
47
48
        $this->prototypes = (null !== $this->parent) ? $this->parent->prototypes : [];
49
        $this->prototyped[$uniqueId] = true; // Prototyping calls to routes ...
50
51
        return $this;
52
    }
53
54
    /**
55
     * Unmounts a group collection to continue routes stalk.
56
     *
57
     * @return \Flight\Routing\RouteCollection
58
     */
59
    public function end()
60
    {
61
        if (isset($this->prototyped[$this->uniqueId])) {
62
            unset($this->prototyped[$this->uniqueId]);
63
64
            // Remove last element from stack.
65
            if (null !== $stack = $this->prototypes) {
66
                \array_pop($stack);
67
            }
68
69
            return $this;
70
        }
71
72
        return $this->parent ?? $this;
73
    }
74
75
    /**
76
     * Prototype the optional default value which maybe required by routes.
77
     *
78
     * @param mixed $default The default value
79
     *
80
     * @see Route::default() for more information
81
     *
82
     * @return $this
83
     */
84
    public function default(string $variable, $default)
85
    {
86
        return $this->doPrototype('default', \func_get_args());
87
    }
88
89
    /**
90
     * Prototype the optional default values which maybe required by routes.
91
     *
92
     * @param array<string,mixed> $values
93
     *
94
     * @see Route::defaults() for more information
95
     *
96
     * @return $this
97
     */
98
    public function defaults(array $values)
99
    {
100
        return $this->doPrototype('defaults', \func_get_args());
101
    }
102
103
    /**
104
     * Prototype a rule to a named placeholder in route pattern.
105
     *
106
     * @param string|string[] $regexp The regexp to apply
107
     *
108
     * @see Route::assert() for more information
109
     *
110
     * @return $this
111
     */
112
    public function assert(string $variable, $regexp)
113
    {
114
        return $this->doPrototype('assert', \func_get_args());
115
    }
116
117
    /**
118
     * Prototype a set of rules to a named placeholder in route pattern.
119
     *
120
     * @param array<string,string|string[]> $regexps The regexps to apply
121
     *
122
     * @see Route::asserts() for more information
123
     *
124
     * @return $this
125
     */
126
    public function asserts(array $regexps)
127
    {
128
        return $this->doPrototype('asserts', \func_get_args());
129
    }
130
131
    /**
132
     * Prototype the arguments supplied to route handler's constructor/factory.
133
     *
134
     * @param mixed $value The parameter value
135
     *
136
     * @see Route::argument() for more information
137
     *
138
     * @return $this
139
     */
140
    public function argument(string $parameter, $value)
141
    {
142
        return $this->doPrototype('argument', \func_get_args());
143
    }
144
145
    /**
146
     * Prototype the arguments supplied to route handler's constructor/factory.
147
     *
148
     * @param array<int|string> $parameters The route handler parameters
149
     *
150
     * @see Route::arguments() for more information
151
     *
152
     * @return $this
153
     */
154
    public function arguments(array $parameters)
155
    {
156
        return $this->doPrototype('arguments', \func_get_args());
157
    }
158
159
    /**
160
     * Prototype the missing namespace for all routes handlers.
161
     *
162
     * @see Route::namespace() for more information
163
     *
164
     * @return $this
165
     */
166
    public function namespace(string $namespace)
167
    {
168
        return $this->doPrototype('namespace', \func_get_args());
169
    }
170
171
    /**
172
     * Prototype HTTP request method(s) to all routes.
173
     *
174
     * @see Route::method() for more information
175
     *
176
     * @return $this
177
     */
178
    public function method(string ...$methods)
179
    {
180
        return $this->doPrototype('method', \func_get_args());
181
    }
182
183
    /**
184
     * Prototype HTTP host scheme(s) to all routes.
185
     *
186
     * @see Route::scheme() for more information
187
     *
188
     * @return $this
189
     */
190
    public function scheme(string ...$schemes)
191
    {
192
        return $this->doPrototype('scheme', \func_get_args());
193
    }
194
195
    /**
196
     * Prototype HTTP host scheme(s) to all routes.
197
     *
198
     * @see Route::scheme() for more information
199
     *
200
     * @return $this
201
     */
202
    public function domain(string ...$hosts)
203
    {
204
        return $this->doPrototype('domain', \func_get_args());
205
    }
206
207
    /**
208
     * Prototype a prefix prepended to route's path.
209
     *
210
     * @see Route::prefix() for more information
211
     *
212
     * @return $this
213
     */
214
    public function prefix(string $path)
215
    {
216
        return $this->doPrototype('prefix', \func_get_args());
217
    }
218
219
    /**
220
     * Prototype named middleware group(s) to all routes.
221
     *
222
     * @see Route::piped() for more information
223
     *
224
     * @return $this
225
     */
226
    public function piped(string ...$to)
227
    {
228
        return $this->doPrototype('piped', \func_get_args());
229
    }
230
231
    /**
232
     * @param array<int,mixed> $arguments
233
     *
234
     * @return $this
235
     */
236
    protected function doPrototype(string $routeMethod, array $arguments)
237
    {
238
        if (isset($this->prototyped[$this->uniqueId])) {
239
            $this->prototypes[$routeMethod] = \array_merge($this->prototypes[$routeMethod] ?? [], $arguments);
240
        } else {
241
            foreach ($this->routes as $route) {
242
                \call_user_func_array([$route, $routeMethod], $arguments);
243
            }
244
245
            foreach ($this->groups as $group) {
246
                \call_user_func_array([$group, $routeMethod], $arguments);
247
            }
248
249
            if (\array_key_exists($routeMethod, $this->prototypes ?? [])) {
250
                unset($this->prototypes[$routeMethod]);
251
            }
252
        }
253
254
        return $this;
255
    }
256
}
257