Completed
Push — master ( b11353...686db0 )
by Mikael
01:52
created

RouterInjectable::handle()   C

Complexity

Conditions 7
Paths 24

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 7.0071

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 26
ccs 18
cts 19
cp 0.9474
rs 6.7272
cc 7
eloc 17
nc 24
nop 2
crap 7.0071
1
<?php
2
3
namespace Anax\Route;
4
5
/**
6
 * A container for routes.
7
 *
8
 */
9
class RouterInjectable
10
{
11
    /**
12
     * Properties
13
     *
14
     */
15
    private $routes         = [];    // All the routes
16
    private $internalRoutes = [];    // All internal routes
17
    private $lastRoute      = null;  // Last route that was callbacked
18
19
20
21
    /**
22
     * Get all routes.
23
     *
24
     * @return array with all routes.
25
     */
26
    public function getAll()
27
    {
28
        return $this->routes;
29
    }
30
31
32
33
    /**
34
     * Get all internal routes.
35
     *
36
     * @return array with internal routes.
37
     */
38
    public function getInternal()
39
    {
40
        return $this->internalRoutes;
41
    }
42
43
44
45
    /**
46
     * Add a route to the router.
47
     *
48
     * @param string $rule   for this route
49
     * @param mixed  $action null, string or callable to implement a
50
     *                       controller for the route
51
     *
52
     * @return class as new route
53
     */
54 7
    public function add($rule, $action = null)
55
    {
56 7
        return $this->any(null, $rule, $action);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
57
    }
58
59
60
61
    /**
62
     * Add aroute to the router with specific request method.
63
     *
64
     * @param array  $method as array of strings of request methods
65
     * @param string $rule   for this route
66
     * @param mixed  $action null, string or callable to implement a
67
     *                       controller for the route
68
     *
69
     * @return class as new route
70
     */
71 9
    public function any($method, $rule, $action = null)
72
    {
73 9
        $route = new Route();
74 9
        $route->set($rule, $action, $method);
75 9
        $this->routes[] = $route;
76
77 9
        return $route;
78
    }
79
80
81
82
    /**
83
     * Add a GET route to the router.
84
     *
85
     * @param string $rule   for this route
86
     * @param mixed  $action null, string or callable to implement a
87
     *                       controller for the route
88
     *
89
     * @return class as new route
90
     */
91 1
    public function get($rule, $action = null)
92
    {
93 1
        return $this->any(["GET"], $rule, $action);
94
    }
95
96
97
98
    /**
99
     * Add a POST route to the router.
100
     *
101
     * @param string $rule   for this route
102
     * @param mixed  $action null, string or callable to implement a
103
     *                       controller for the route
104
     *
105
     * @return class as new route
106
     */
107 1
    public function post($rule, $action = null)
108
    {
109 1
        return $this->any(["POST"], $rule, $action);
110
    }
111
112
113
114
    /**
115
     * Add a PUT route to the router.
116
     *
117
     * @param string $rule   for this route
118
     * @param mixed  $action null, string or callable to implement a
119
     *                       controller for the route
120
     *
121
     * @return class as new route
122
     */
123 1
    public function put($rule, $action = null)
124
    {
125 1
        return $this->any(["PUT"], $rule, $action);
126
    }
127
128
129
130
    /**
131
     * Add a DELETE route to the router.
132
     *
133
     * @param string $rule   for this route
134
     * @param mixed  $action null, string or callable to implement a
135
     *                       controller for the route
136
     *
137
     * @return class as new route
138
     */
139 1
    public function delete($rule, $action = null)
140
    {
141 1
        return $this->any(["DELETE"], $rule, $action);
142
    }
143
144
145
146
    /**
147
     * Add an internal (not exposed to url-matching) route to the router.
148
     *
149
     * @param string $rule   for this route
150
     * @param mixed  $action null, string or callable to implement a controller for the route
151
     *
152
     * @return class as new route
153
     */
154 3
    public function addInternal($rule, $action = null)
155
    {
156 3
        $route = new Route();
157 3
        $route->set($rule, $action);
158 3
        $this->internalRoutes[$rule] = $route;
159 3
        return $route;
160
    }
161
162
163
164
    /**
165
     * Add an internal (not exposed to url-matching) route to the router.
166
     *
167
     * @param string $rule   for this route
168
     * @param mixed  $action null, string or callable to implement a
0 ignored issues
show
Bug introduced by
There is no parameter named $action. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
169
     *                       controller for the route
170
     *
171
     * @return void
172
     */
173 4
    public function handleInternal($rule)
174
    {
175 4
        if (!isset($this->internalRoutes[$rule])) {
176 1
            throw new NotFoundException("No internal route to handle: " . $rule);
177
        }
178 3
        $route = $this->internalRoutes[$rule];
179 3
        $this->lastRoute = $rule;
180 3
        $route->handle();
181
    }
182
183
184
185
    /**
186
     * Get the route for the last route that was handled.
187
     *
188
     * @return mixed
189
     */
190
    public function getLastRoute()
191
    {
192
        return $this->lastRoute;
193
    }
194
195
196
197
    /**
198
     * Handle the routes and match them towards the request, dispatch them
199
     * when a match is made. Each route handler may throw exceptions that
200
     * may redirect to an internal route for error handling.
201
     * Several routes can match and if the routehandler does not break
202
     * execution flow, the route matching will carry on.
203
     * Only the last routehandler will get its return value returned further.
204
     *
205
     * @param string $query   the query/route to match a handler for.
206
     * @param string $method  the request method to match.
207
     *
208
     * @return mixed content returned from route.
209
     */
210 10
    public function handle($query, $method = null)
211
    {
212
        try {
213 10
            $match = false;
214 10
            foreach ($this->routes as $route) {
215 9
                if ($route->match($query, $method)) {
216 9
                    $this->lastRoute = $route->getRule();
217 9
                    $match = true;
218 9
                    $results = $route->handle();
219 6
                }
220 7
            }
221
222 7
            if ($match) {
223 6
                return $results;
0 ignored issues
show
Bug introduced by
The variable $results does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
224
            }
225
226
            // No route was matched
227 1
            $this->handleInternal("404");
228 4
        } catch (ForbiddenException $e) {
229 1
            $this->handleInternal("403");
230 3
        } catch (NotFoundException $e) {
231 2
            $this->handleInternal("404");
232 1
        } catch (InternalErrorException $e) {
233 1
            $this->handleInternal("500");
234
        }
235
    }
236
}
237