Code Duplication    Length = 287-287 lines in 2 locations

src/Route/Router.php 1 location

@@ 11-297 (lines=287) @@
8
/**
9
 * A container for routes.
10
 */
11
class Router implements InjectionAwareInterface
12
{
13
    use InjectionAwareTrait;
14
15
    /**
16
     * @var array       $routes         all the routes.
17
     * @var array       $internalRoutes all internal routes.
18
     * @var null|string $lastRoute      last route that was matched and called.
19
     */
20
    private $routes         = [];
21
    private $internalRoutes = [];
22
    private $lastRoute      = null;
23
24
25
26
    /**
27
     * Handle the routes and match them towards the request, dispatch them
28
     * when a match is made. Each route handler may throw exceptions that
29
     * may redirect to an internal route for error handling.
30
     * Several routes can match and if the routehandler does not break
31
     * execution flow, the route matching will carry on.
32
     * Only the last routehandler will get its return value returned further.
33
     *
34
     * @param string $path    the path to find a matching handler for.
35
     * @param string $method  the request method to match.
36
     *
37
     * @return mixed content returned from route.
38
     */
39
    public function handle($path, $method = null)
40
    {
41
        try {
42
            $match = false;
43
            foreach ($this->routes as $route) {
44
                if ($route->match($path, $method)) {
45
                    $this->lastRoute = $route->getRule();
46
                    $match = true;
47
                    $results = $route->handle($this->di);
48
                }
49
            }
50
51
            if ($match) {
52
                return $results;
53
            }
54
55
            $this->handleInternal("404");
56
        } catch (ForbiddenException $e) {
57
            $this->handleInternal("403");
58
        } catch (NotFoundException $e) {
59
            $this->handleInternal("404");
60
        } catch (InternalErrorException $e) {
61
            $this->handleInternal("500");
62
        }
63
    }
64
65
66
67
    /**
68
     * Handle an internal route, the internal routes are not exposed to the
69
     * end user.
70
     *
71
     * @param string $rule for this route.
72
     *
73
     * @return void
74
     *
75
     * @throws \Anax\Route\NotFoundException
76
     */
77
    public function handleInternal($rule)
78
    {
79
        if (!isset($this->internalRoutes[$rule])) {
80
            throw new NotFoundException("No internal route to handle: " . $rule);
81
        }
82
        $route = $this->internalRoutes[$rule];
83
        $this->lastRoute = $rule;
84
        $route->handle();
85
    }
86
87
88
89
    /**
90
     * Load routes from a config file, the file should return an array with
91
     * routes.
92
     *
93
     * @param string $file to load routes from.
94
     *
95
     * @return self
96
     */
97
    public function load($file)
98
    {
99
        $config = require $file;
100
        foreach ($config["routes"] as $route) {
101
            $this->any(
102
                $route["requestMethod"],
103
                $route["path"],
104
                $route["callable"]
105
            );
106
        }
107
        return $this;
108
    }
109
110
111
112
    /**
113
     * Add a route with a request method, a path rule to match and an action
114
     * as the callback. Adding several path rules (array) results in several
115
     * routes being created.
116
     *
117
     * @param null|string|array    $method as a valid request method.
118
     * @param null|string|array    $rule   path rule for this route.
119
     * @param null|string|callable $action to implement a handler for the route.
120
     *
121
     * @return class|array as new route(s), class if one added, else array.
122
     */
123
    public function any($method, $rule, $action)
124
    {
125
        $rules = is_array($rule) ? $rule : [$rule];
126
127
        $routes = [];
128
        foreach ($rules as $val) {
129
            $route = new Route();
130
            $route->set($val, $action, $method);
131
            $routes[] = $route;
132
            $this->routes[] = $route;
133
        }
134
135
        return count($routes) === 1 ? $routes[0] : $routes;
136
    }
137
138
139
140
    /**
141
     * Add a route to the router by rule(s) and a callback.
142
     *
143
     * @param null|string|array    $rule   for this route.
144
     * @param null|string|callable $action a callback handler for the route.
145
     *
146
     * @return class|array as new route(s), class if one added, else array.
147
     */
148
    public function add($rule, $action = null)
149
    {
150
        return $this->any(null, $rule, $action);
151
    }
152
153
154
155
    /**
156
    * Add a default route which will be applied for any path.
157
     *
158
     * @param string|callable $action a callback handler for the route.
159
     *
160
     * @return class as new route.
161
     */
162
    public function always($action)
163
    {
164
        return $this->any(null, null, $action);
165
    }
166
167
168
169
    /**
170
     * Add a default route which will be applied for any path, if the choosen
171
     * request method is matching.
172
     *
173
     * @param null|string|array    $method as request methods
174
     * @param null|string|callable $action a callback handler for the route.
175
     *
176
     * @return class|array as new route(s), class if one added, else array.
177
     */
178
    public function all($method, $action)
179
    {
180
        return $this->any($method, null, $action);
181
    }
182
183
184
185
    /**
186
     * Shortcut to add a GET route.
187
     *
188
     * @param null|string|array    $method as request methods
189
     * @param null|string|callable $action a callback handler for the route.
190
     *
191
     * @return class|array as new route(s), class if one added, else array.
192
     */
193
    public function get($rule, $action)
194
    {
195
        return $this->any(["GET"], $rule, $action);
196
    }
197
198
199
200
    /**
201
    * Shortcut to add a POST route.
202
     *
203
     * @param null|string|array    $method as request methods
204
     * @param null|string|callable $action a callback handler for the route.
205
     *
206
     * @return class|array as new route(s), class if one added, else array.
207
     */
208
    public function post($rule, $action)
209
    {
210
        return $this->any(["POST"], $rule, $action);
211
    }
212
213
214
215
    /**
216
    * Shortcut to add a PUT route.
217
     *
218
     * @param null|string|array    $method as request methods
219
     * @param null|string|callable $action a callback handler for the route.
220
     *
221
     * @return class|array as new route(s), class if one added, else array.
222
     */
223
    public function put($rule, $action)
224
    {
225
        return $this->any(["PUT"], $rule, $action);
226
    }
227
228
229
230
    /**
231
    * Shortcut to add a DELETE route.
232
     *
233
     * @param null|string|array    $method as request methods
234
     * @param null|string|callable $action a callback handler for the route.
235
     *
236
     * @return class|array as new route(s), class if one added, else array.
237
     */
238
    public function delete($rule, $action)
239
    {
240
        return $this->any(["DELETE"], $rule, $action);
241
    }
242
243
244
245
    /**
246
     * Add an internal route to the router, this route is not exposed to the
247
     * browser and the end user.
248
     *
249
     * @param string               $rule   for this route
250
     * @param null|string|callable $action a callback handler for the route.
251
     *
252
     * @return class|array as new route(s), class if one added, else array.
253
     */
254
    public function addInternal($rule, $action)
255
    {
256
        $route = new Route();
257
        $route->set($rule, $action);
258
        $this->internalRoutes[$rule] = $route;
259
        return $route;
260
    }
261
262
263
264
    /**
265
     * Get the route for the last route that was handled.
266
     *
267
     * @return mixed
268
     */
269
    public function getLastRoute()
270
    {
271
        return $this->lastRoute;
272
    }
273
274
275
276
    /**
277
     * Get all routes.
278
     *
279
     * @return array with all routes.
280
     */
281
    public function getAll()
282
    {
283
        return $this->routes;
284
    }
285
286
287
288
    /**
289
     * Get all internal routes.
290
     *
291
     * @return array with internal routes.
292
     */
293
    public function getInternal()
294
    {
295
        return $this->internalRoutes;
296
    }
297
}
298

src/Route/RouterInjectable.php 1 location

@@ 11-297 (lines=287) @@
8
/**
9
 * A container for routes.
10
 */
11
class RouterInjectable implements AppInjectableInterface
12
{
13
    use AppInjectableTrait;
14
15
    /**
16
     * @var array       $routes         all the routes.
17
     * @var array       $internalRoutes all internal routes.
18
     * @var null|string $lastRoute      last route that was matched and called.
19
     */
20
    private $routes         = [];
21
    private $internalRoutes = [];
22
    private $lastRoute      = null;
23
24
25
26
    /**
27
     * Handle the routes and match them towards the request, dispatch them
28
     * when a match is made. Each route handler may throw exceptions that
29
     * may redirect to an internal route for error handling.
30
     * Several routes can match and if the routehandler does not break
31
     * execution flow, the route matching will carry on.
32
     * Only the last routehandler will get its return value returned further.
33
     *
34
     * @param string $path    the path to find a matching handler for.
35
     * @param string $method  the request method to match.
36
     *
37
     * @return mixed content returned from route.
38
     */
39
    public function handle($path, $method = null)
40
    {
41
        try {
42
            $match = false;
43
            foreach ($this->routes as $route) {
44
                if ($route->match($path, $method)) {
45
                    $this->lastRoute = $route->getRule();
46
                    $match = true;
47
                    $results = $route->handle($this->app);
48
                }
49
            }
50
51
            if ($match) {
52
                return $results;
53
            }
54
55
            $this->handleInternal("404");
56
        } catch (ForbiddenException $e) {
57
            $this->handleInternal("403");
58
        } catch (NotFoundException $e) {
59
            $this->handleInternal("404");
60
        } catch (InternalErrorException $e) {
61
            $this->handleInternal("500");
62
        }
63
    }
64
65
66
67
    /**
68
     * Handle an internal route, the internal routes are not exposed to the
69
     * end user.
70
     *
71
     * @param string $rule for this route.
72
     *
73
     * @return void
74
     *
75
     * @throws \Anax\Route\NotFoundException
76
     */
77
    public function handleInternal($rule)
78
    {
79
        if (!isset($this->internalRoutes[$rule])) {
80
            throw new NotFoundException("No internal route to handle: " . $rule);
81
        }
82
        $route = $this->internalRoutes[$rule];
83
        $this->lastRoute = $rule;
84
        $route->handle();
85
    }
86
87
88
89
    /**
90
     * Load routes from a config file, the file should return an array with
91
     * routes.
92
     *
93
     * @param string $file to load routes from.
94
     *
95
     * @return self
96
     */
97
    public function load($file)
98
    {
99
        $config = require $file;
100
        foreach ($config["routes"] as $route) {
101
            $this->any(
102
                $route["requestMethod"],
103
                $route["path"],
104
                $route["callable"]
105
            );
106
        }
107
        return $this;
108
    }
109
110
111
112
    /**
113
     * Add a route with a request method, a path rule to match and an action
114
     * as the callback. Adding several path rules (array) results in several
115
     * routes being created.
116
     *
117
     * @param null|string|array    $method as a valid request method.
118
     * @param null|string|array    $rule   path rule for this route.
119
     * @param null|string|callable $action to implement a handler for the route.
120
     *
121
     * @return class|array as new route(s), class if one added, else array.
122
     */
123
    public function any($method, $rule, $action)
124
    {
125
        $rules = is_array($rule) ? $rule : [$rule];
126
127
        $routes = [];
128
        foreach ($rules as $val) {
129
            $route = new Route();
130
            $route->set($val, $action, $method);
131
            $routes[] = $route;
132
            $this->routes[] = $route;
133
        }
134
135
        return count($routes) === 1 ? $routes[0] : $routes;
136
    }
137
138
139
140
    /**
141
     * Add a route to the router by rule(s) and a callback.
142
     *
143
     * @param null|string|array    $rule   for this route.
144
     * @param null|string|callable $action a callback handler for the route.
145
     *
146
     * @return class|array as new route(s), class if one added, else array.
147
     */
148
    public function add($rule, $action = null)
149
    {
150
        return $this->any(null, $rule, $action);
151
    }
152
153
154
155
    /**
156
    * Add a default route which will be applied for any path.
157
     *
158
     * @param string|callable $action a callback handler for the route.
159
     *
160
     * @return class as new route.
161
     */
162
    public function always($action)
163
    {
164
        return $this->any(null, null, $action);
165
    }
166
167
168
169
    /**
170
     * Add a default route which will be applied for any path, if the choosen
171
     * request method is matching.
172
     *
173
     * @param null|string|array    $method as request methods
174
     * @param null|string|callable $action a callback handler for the route.
175
     *
176
     * @return class|array as new route(s), class if one added, else array.
177
     */
178
    public function all($method, $action)
179
    {
180
        return $this->any($method, null, $action);
181
    }
182
183
184
185
    /**
186
     * Shortcut to add a GET route.
187
     *
188
     * @param null|string|array    $method as request methods
189
     * @param null|string|callable $action a callback handler for the route.
190
     *
191
     * @return class|array as new route(s), class if one added, else array.
192
     */
193
    public function get($rule, $action)
194
    {
195
        return $this->any(["GET"], $rule, $action);
196
    }
197
198
199
200
    /**
201
    * Shortcut to add a POST route.
202
     *
203
     * @param null|string|array    $method as request methods
204
     * @param null|string|callable $action a callback handler for the route.
205
     *
206
     * @return class|array as new route(s), class if one added, else array.
207
     */
208
    public function post($rule, $action)
209
    {
210
        return $this->any(["POST"], $rule, $action);
211
    }
212
213
214
215
    /**
216
    * Shortcut to add a PUT route.
217
     *
218
     * @param null|string|array    $method as request methods
219
     * @param null|string|callable $action a callback handler for the route.
220
     *
221
     * @return class|array as new route(s), class if one added, else array.
222
     */
223
    public function put($rule, $action)
224
    {
225
        return $this->any(["PUT"], $rule, $action);
226
    }
227
228
229
230
    /**
231
    * Shortcut to add a DELETE route.
232
     *
233
     * @param null|string|array    $method as request methods
234
     * @param null|string|callable $action a callback handler for the route.
235
     *
236
     * @return class|array as new route(s), class if one added, else array.
237
     */
238
    public function delete($rule, $action)
239
    {
240
        return $this->any(["DELETE"], $rule, $action);
241
    }
242
243
244
245
    /**
246
     * Add an internal route to the router, this route is not exposed to the
247
     * browser and the end user.
248
     *
249
     * @param string               $rule   for this route
250
     * @param null|string|callable $action a callback handler for the route.
251
     *
252
     * @return class|array as new route(s), class if one added, else array.
253
     */
254
    public function addInternal($rule, $action)
255
    {
256
        $route = new Route();
257
        $route->set($rule, $action);
258
        $this->internalRoutes[$rule] = $route;
259
        return $route;
260
    }
261
262
263
264
    /**
265
     * Get the route for the last route that was handled.
266
     *
267
     * @return mixed
268
     */
269
    public function getLastRoute()
270
    {
271
        return $this->lastRoute;
272
    }
273
274
275
276
    /**
277
     * Get all routes.
278
     *
279
     * @return array with all routes.
280
     */
281
    public function getAll()
282
    {
283
        return $this->routes;
284
    }
285
286
287
288
    /**
289
     * Get all internal routes.
290
     *
291
     * @return array with internal routes.
292
     */
293
    public function getInternal()
294
    {
295
        return $this->internalRoutes;
296
    }
297
}
298