CRouterBasic::handle()   C
last analyzed

Complexity

Conditions 11
Paths 97

Size

Total Lines 58
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 0 Features 0
Metric Value
c 8
b 0
f 0
dl 0
loc 58
rs 6.4179
cc 11
eloc 30
nc 97
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Anax\Route;
4
5
/**
6
 * A container for routes.
7
 *
8
 */
9
class CRouterBasic implements \Anax\DI\IInjectionAware
10
{
11
    use \Anax\DI\TInjectionAware;
12
13
14
15
    /**
16
     * Properties
17
     *
18
     */
19
    private $routes         = [];    // All the routes
20
    private $internalRoutes = [];    // All internal routes
21
    private $defaultRoute   = null;  // A default rout to catch all
22
23
24
25
    /**
26
     * Get all routes.
27
     *
28
     * @return array with all routes.
29
     */
30
    public function getAll()
31
    {
32
        return $this->routes;
33
    }
34
35
36
37
    /**
38
     * Get all internal routes.
39
     *
40
     * @return array with internal routes.
41
     */
42
    public function getInternal()
43
    {
44
        return $this->internalRoutes;
45
    }
46
47
48
49
    /**
50
     * Add a route to the router.
51
     *
52
     * @param string $rule   for this route
53
     * @param mixed  $action null, string or callable to implement a controller for the route
54
     *
55
     * @return object as new route
56
     */
57
    public function add($rule, $action = null)
58
    {
59
        $route = $this->di->get('route');
60
        $route->set($rule, $action);
61
        $this->routes[] = $route;
62
63
        // Set as default route
64
        if ($rule == "*") {
65
            $this->defaultRoute = $route;
66
        }
67
        
68
        return $route;
69
    }
70
71
72
73
    /**
74
     * Add an internal (not exposed to url-matching) route to the router.
75
     *
76
     * @param string $rule   for this route
77
     * @param mixed  $action null, string or callable to implement a controller for the route
78
     *
79
     * @return object as new route
80
     */
81
    public function addInternal($rule, $action = null)
82
    {
83
        $route = $this->di->get('route');
84
        $route->set($rule, $action);
85
        $this->internalRoutes[$rule] = $route;
86
        return $route;
87
    }
88
89
90
    /**
91
     * Add an internal (not exposed to url-matching) route to the router.
92
     *
93
     * @param string $rule for this route
94
     *
95
     * @return object as new route
96
     * @throws \Anax\Exception\NotFoundException
97
     */
98
    public function handleInternal($rule)
99
    {
100
        if (isset($this->internalRoutes[$rule])) {
101
            $route = $this->internalRoutes[$rule];
102
            $route->handle();
103
        } else {
104
            throw new \Anax\Exception\NotFoundException("No internal route to handle: " . $rule);
105
        }
106
    }
107
108
109
    /**
110
     * Handle the routes and match them towards the request, dispatch them when a match is made.
111
     *
112
     * @return $this
113
     * @throws \Anax\Exception\NotFoundException
114
     * @throws \Exception
115
     */
116
    public function handle()
117
    {
118
        try {
119
120
            $query = $this->di->request->getRoute();
121
            $parts = $this->di->request->getRouteParts();
122
123
            // Match predefined routes
124
            foreach ($this->routes as $route) {
125
                if ($route->match($query)) {
126
                    return $route->handle();
127
                }
128
            }
129
130
            // Default handling route as :controller/:action/:params using the dispatcher
131
            $dispatcher = $this->di->dispatcher;
132
            $dispatcher->setControllerName(isset($parts[0]) ? $parts[0] : 'index');
133
134
            if ($dispatcher->isValidController()) {
135
136
                $dispatcher->setActionName(isset($parts[1]) ? $parts[1] : 'index');
137
138
                $params = [];
139
                if (isset($parts[2])) {
140
                    $params = $parts;
141
                    array_shift($params);
142
                    array_shift($params);
143
                }
144
                $dispatcher->setParams($params);
145
146
                if ($dispatcher->isCallable()) {
147
                    return $dispatcher->dispatch();
148
                }
149
            }
150
151
            // Use the "catch-all" route
152
            if ($this->defaultRoute) {
153
                return $this->defaultRoute->handle();
154
            }
155
156
            // No route was matched
157
            $this->handleInternal('404');
158
        
159
        } catch (\Exception $e) {
160
161
            // Exception codes can match a route for a http status code
162
            $code = $e->getCode();
163
            $statusCodes = [403, 404, 500];
164
            if (in_array($code, $statusCodes)) {
165
166
                $this->di->flash->setMessage($e->getMessage());
167
                $this->handleInternal($code);
168
            
169
            } else {
170
                throw $e;
171
            }
172
        }
173
    }
174
}
175