Completed
Push — master ( 686db0...29755b )
by Mikael
01:55
created

Route::matchRequestMethod()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 8.8571
cc 6
eloc 5
nc 2
nop 1
crap 6
1
<?php
2
3
namespace Anax\Route;
4
5
/**
6
 * A container for routes.
7
 *
8
 */
9
class Route
10
{
11
12
    /**
13
    * Properties
14
    *
15
    */
16
    private $name;           // A name for this route
17
    private $method;         // The methods to support
18
    private $rule;           // The rule for this route
19
    private $action;         // The callback to handle this route
20
    private $arguments = []; // Arguments for the callback
21
22
23
24
    /**
25
     * Set values for route.
26
     *
27
     * @param null|string       $rule   for this route
28
     * @param callable          $action callable to implement a controller for
29
     *                                  the route
30
     * @param null|string|array $method as request method to support
31
     *
32
     * @return $this
33
     */
34 21
    public function set($rule, $action = null, $method = null)
35
    {
36 21
        $this->rule = $rule;
37 21
        $this->action = $action;
38
39 21
        $this->method = $method;
40 21
        if (is_string($method)) {
41 3
            $this->method = array_map("trim", explode("|", $method));
42 3
        }
43
44 21
        return $this;
45
    }
46
47
48
49
    /**
50
     * Check if part of route is a argument and optionally match type
51
     * as a requirement {argument:type}.
52
     *
53
     * @param string $rulePart   the rule part to check.
54
     * @param string $queryPart  the query part to check.
55
     * @param array  &$args      add argument to args array if matched
56
     *
57
     * @return boolean
58
     */
59 2
    private function checkPartAsArgument($rulePart, $queryPart, &$args)
60
    {
61 2
        if (substr($rulePart, -1) == "}"
62 2
            && !is_null($queryPart)
63 2
        ) {
64 2
            $part = substr($rulePart, 1, -1);
65 2
            $pos = strpos($part, ":");
66 2
            if ($pos !== false) {
67 1
                $type = substr($part, $pos + 1);
68 1
                if (! $this->checkPartMatchingType($queryPart, $type)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->checkPartMatchingType($queryPart, $type) of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
69 1
                    return false;
70
                }
71 1
            }
72 2
            $args[] = $queryPart;
73 2
            return true;
74
        }
75 1
        return false;
76
    }
77
78
79
80
    /**
81
     * Check if value is matching a certain type of values.
82
     *
83
     * @param string $rulePart   the rule part to check.
0 ignored issues
show
Bug introduced by
There is no parameter named $rulePart. 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...
84
     * @param string $queryPart  the query part to check.
0 ignored issues
show
Bug introduced by
There is no parameter named $queryPart. 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...
85
     * @param array  &$args      add argument to args array if matched
86
     *
87
     * @return boolean
88
     */
89 1
    private function checkPartMatchingType($value, $type)
90
    {
91
        switch ($type) {
92 1
            case "digit":
93 1
                return ctype_digit($value);
94
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
95
96 1
            case "hex":
97 1
                return ctype_xdigit($value);
98
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
99
100 1
            case "alpha":
101 1
                return ctype_alpha($value);
102
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
103
104 1
            case "alphanum":
105 1
                return ctype_alnum($value);
106
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
107
108
            default:
109
                return false;
110
        }
111
    }
112
113
114
115
    /**
116
     * Match part of rule and query.
117
     *
118
     * @param string $rulePart   the rule part to check.
119
     * @param string $queryPart  the query part to check.
120
     * @param array  &$args      add argument to args array if matched
121
     *
122
     * @return boolean
123
     */
124 16
    private function matchPart($rulePart, $queryPart, &$args)
125
    {
126 16
        $match = false;
0 ignored issues
show
Unused Code introduced by
$match is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
127 16
        $first = isset($rulePart[0]) ? $rulePart[0] : '';
128
        switch ($first) {
129 16
            case '*':
130 1
                $match = true;
131 1
                break;
132
133 16
            case '{':
134 2
                $match = $this->checkPartAsArgument($rulePart, $queryPart, $args);
135 2
                break;
136
137 15
            default:
138 15
                $match = ($rulePart == $queryPart);
139 15
                break;
140 15
        }
141 16
        return $match;
142
    }
143
144
145
146
    /**
147
     * Check if the request method matches.
148
     *
149
     * @param string $method as request method
150
     *
151
     * @return boolean true if request method matches
152
     */
153 21
    public function matchRequestMethod($method)
154
    {
155 21
        if ($method && is_array($this->method) && !in_array($method, $this->method)
156 21
            || (is_null($method) && !empty($this->method))
157 21
        ) {
158 6
            return false;
159
        }
160 21
        return true;
161
    }
162
163
164
165
    /**
166
     * Check if the route matches a query and request method.
167
     *
168
     * @param string $query  to match against
169
     * @param string $method as request method
170
     *
171
     * @return boolean true if query matches the route
172
     */
173 21
    public function match($query, $method = null)
174
    {
175 21
        if (!$this->matchRequestMethod($method)) {
176 6
            return false;
177 1
        }
178
179
        // If any/default */** route, match anything
180 21
        if (is_null($this->rule)
181 19
            || $this->rule == "*"
182 19
            || $this->rule == "**"
183 21
        ) {
184 5
            return true;
185
        }
186
187
        // Check all parts to see if they matches
188 16
        $ruleParts  = explode('/', $this->rule);
189 16
        $queryParts = explode('/', $query);
190 16
        $ruleCount = max(count($ruleParts), count($queryParts));
191 16
        $args = [];
192
193 16
        for ($i = 0; $i < $ruleCount; $i++) {
194 16
            $rulePart  = isset($ruleParts[$i])  ? $ruleParts[$i]  : null;
195 16
            $queryPart = isset($queryParts[$i]) ? $queryParts[$i] : null;
196
197 16
            if (!$this->matchPart($rulePart, $queryPart, $args)) {
198 6
                return false;
199
            }
200 16
        }
201
202 16
        $this->arguments = $args;
203 16
        return true;
204
    }
205
206
207
208
    /**
209
     * Handle the action for the route.
210
     *
211
     * @return void
212
     */
213 12
    public function handle()
214
    {
215 12
        return call_user_func($this->action, ...$this->arguments);
216
    }
217
218
219
220
    /**
221
     * Set the name of the route.
222
     *
223
     * @param string $name set a name for the route
224
     *
225
     * @return $this
226
     */
227
    public function setName($name)
228
    {
229
        $this->name = $name;
230
        return $this;
231
    }
232
233
234
235
    /**
236
     * Get the rule for the route.
237
     *
238
     * @return string
239
     */
240 11
    public function getRule()
241
    {
242 11
        return $this->rule;
243
    }
244
}
245