Passed
Pull Request — master (#46)
by Arman
02:33
created

Route   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 212
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 71
dl 0
loc 212
rs 10
c 5
b 0
f 0
wmc 25

9 Methods

Rating   Name   Duplication   Size   Complexity  
A post() 0 3 1
A get() 0 3 1
A group() 0 11 1
B name() 0 23 8
A add() 0 22 3
B middlewares() 0 31 6
A getRuntimeRoutes() 0 9 3
A getVirtualRoutes() 0 3 1
A __construct() 0 4 1
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.5.0
13
 */
14
15
namespace Quantum\Routes;
16
17
use Quantum\Exceptions\RouteException;
18
use Closure;
19
20
/**
21
 * Route Class
22
 *
23
 * Route class allows to add new route entries
24
 *
25
 * @package Quantum
26
 * @category Routes
27
 */
28
29
class Route
30
{
31
32
    /**
33
     * Current module
34
     * @var string
35
     */
36
    private $module;
37
38
    /**
39
     * Identifies the group middleware
40
     * @var bool
41
     */
42
    private $isGroupeMiddlewares;
43
44
    /**
45
     * Identifies the group
46
     * @var boolean
47
     */
48
    private $isGroupe = false;
49
50
    /**
51
     * Current group name
52
     * @var string
53
     */
54
    private $currentGroupName = null;
55
56
    /**
57
     * Current route
58
     * @var array
59
     */
60
    private $currentRoute = [];
61
62
    /**
63
     * Virtual routes
64
     * @var array
65
     */
66
    private $virtualRoutes = [];
67
68
    /**
69
     * Class constructor
70
     * @param string $module
71
     */
72
    public function __construct(string $module)
73
    {
74
        $this->virtualRoutes['*'] = [];
75
        $this->module = $module;
76
    }
77
78
    /**
79
     * Adds new route entry to routes
80
     * @param string $route
81
     * @param string $method
82
     * @param array $params
83
     * @return $this
84
     */
85
    public function add(string $route, string $method, ...$params): self
86
    {
87
        $this->currentRoute = [
88
            'route' => $route,
89
            'method' => $method,
90
            'module' => $this->module
91
        ];
92
93
        if (is_callable($params[0])) {
94
            $this->currentRoute['callback'] = $params[0];
95
        } else {
96
            $this->currentRoute['controller'] = $params[0];
97
            $this->currentRoute['action'] = $params[1];
98
        }
99
100
        if ($this->currentGroupName) {
101
            $this->virtualRoutes[$this->currentGroupName][] = $this->currentRoute;
102
        } else {
103
            $this->virtualRoutes['*'][] = $this->currentRoute;
104
        }
105
106
        return $this;
107
    }
108
109
    /**
110
     * Adds new get route entry to routes
111
     * @param string $route
112
     * @param array $params
113
     * @return $this
114
     */
115
    public function get(string $route, ...$params): self
116
    {
117
        return $this->add($route, 'GET', ...$params);
118
    }
119
120
    /**
121
     * Adds new post route entry to routes
122
     * @param string $route
123
     * @param array $params
124
     * @return $this
125
     */
126
    public function post(string $route, ...$params): self
127
    {
128
        return $this->add($route, 'POST', ...$params);
129
    }
130
131
    /**
132
     * Starts a named group of routes
133
     * @param string $groupName
134
     * @param Closure $callback
135
     * @return $this
136
     */
137
    public function group(string $groupName, Closure $callback): self
138
    {
139
        $this->currentGroupName = $groupName;
140
141
        $this->isGroupe = true;
142
        $this->isGroupeMiddlewares = false;
143
        $callback($this);
144
        $this->isGroupeMiddlewares = true;
145
        $this->currentGroupName = null;
146
147
        return $this;
148
    }
149
150
    /**
151
     * Adds middlewares to routes and route groups
152
     * @param array $middlewares
153
     * @return $this
154
     */
155
    public function middlewares(array $middlewares = []): self
156
    {
157
        if (!$this->isGroupe) {
158
            end($this->virtualRoutes['*']);
159
            $lastKey = key($this->virtualRoutes['*']);
160
            $this->virtualRoutes['*'][$lastKey]['middlewares'] = $middlewares;
161
        } else {
162
            end($this->virtualRoutes);
163
            $lastKeyOfFirstRound = key($this->virtualRoutes);
164
165
            if (!$this->isGroupeMiddlewares) {
166
                end($this->virtualRoutes[$lastKeyOfFirstRound]);
167
                $lastKeyOfSecondRound = key($this->virtualRoutes[$lastKeyOfFirstRound]);
168
                $this->virtualRoutes[$lastKeyOfFirstRound][$lastKeyOfSecondRound]['middlewares'] = $middlewares;
169
            } else {
170
                $this->isGroupe = false;
171
                foreach ($this->virtualRoutes[$lastKeyOfFirstRound] as &$route) {
172
                    $hasMiddleware = end($route);
173
                    if (!is_array($hasMiddleware)) {
174
                        $route['middlewares'] = $middlewares;
175
                    } else {
176
                        $reversedMiddlewares = array_reverse($middlewares);
177
                        foreach ($reversedMiddlewares as $middleware) {
178
                            array_unshift($route['middlewares'], $middleware);
179
                        }
180
                    }
181
                }
182
            }
183
        }
184
185
        return $this;
186
    }
187
188
    /**
189
     * Sets a unique name for a route
190
     * @param string $name
191
     * @return $this
192
     * @throws \Quantum\Exceptions\RouteException
193
     */
194
    public function name(string $name): self
195
    {
196
        if (empty($this->currentRoute)) {
197
            throw RouteException::nameBeforeDefinition();
198
        }
199
200
        if ($this->isGroupeMiddlewares) {
201
            throw RouteException::nameOnGroup();
202
        }
203
204
        foreach ($this->virtualRoutes as &$virtualRoute) {
205
            foreach ($virtualRoute as &$route) {
206
                if (isset($route['name']) && $route['name'] == $name) {
207
                    throw RouteException::nonUniqueName();
208
                }
209
210
                if ($route['route'] == $this->currentRoute['route']) {
211
                    $route['name'] = $name;
212
                }
213
            }
214
        }
215
216
        return $this;
217
    }
218
219
    /**
220
     * Gets the run-time routes
221
     * @return array
222
     */
223
    public function getRuntimeRoutes(): array
224
    {
225
        $runtimeRoutes = [];
226
        foreach ($this->virtualRoutes as $virtualRoute) {
227
            foreach ($virtualRoute as $route) {
228
                $runtimeRoutes[] = $route;
229
            }
230
        }
231
        return $runtimeRoutes;
232
    }
233
234
    /**
235
     * Gets the virtual routes
236
     * @return array
237
     */
238
    public function getVirtualRoutes(): array
239
    {
240
        return $this->virtualRoutes;
241
    }
242
243
}
244