Completed
Push — master ( 7c0e2b...79c67e )
by Mikael
02:05
created

Request::extractRoute()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 40
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 7.025

Importance

Changes 0
Metric Value
dl 0
loc 40
ccs 23
cts 25
cp 0.92
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 22
nc 16
nop 0
crap 7.025
1
<?php
2
3
namespace Anax\Request;
4
5
/**
6
 * Storing information from the request and calculating related essentials.
7
 *
8
 */
9
class Request
10
{
11
    /**
12
     * @var string $requestUri Request URI from $_SERVER.
13
     * @var string $scriptName Scriptname from $_SERVER, actual scriptname part.
14
     * @var string $path       Scriptname from $_SERVER, path-part.
15
     */
16
    private $requestUri;
17
    private $scriptName;
18
    private $path;
19
20
21
22
    /**
23
     * @var string $route      The route.
24
     * @var array  $routeParts The route as an array.
25
     */
26
    private $route;
27
    private $routeParts;
28
29
30
31
    /**
32
     * @var string $currentUrl Current url.
33
     * @var string $siteUrl    Url to this site, http://dbwebb.se.
34
     * @var string $baseUrl    Url to root dir,
35
     *                         siteUrl . /some/installation/directory/.
36
     */
37
    private $currentUrl;
38
    private $siteUrl;
39
    private $baseUrl;
40
41
42
43
    /**
44
     * @var string $server Mapped to $_SERVER.
45
     * @var string $get    Mapped to $_GET.
46
     * @var string $post   Mapped to $_POST.
47
     */
48
    private $server;
49
    private $get;
50
    private $post;
51
52
53
54
    /**
55
     * Constructor.
56
     */
57 26
    public function __construct()
58
    {
59 26
        $this->setGlobals();
60 26
    }
61
62
63
64
    /**
65
     * Read info from the globals.
66
     *
67
     * @param array $globals use to initiate globals with values.
68
     *
69
     * @return void
70
     */
71 26
    public function setGlobals($globals = [])
72
    {
73 26
        $this->server = isset($globals["server"])
74 26
            ? array_merge($_SERVER, $globals["server"])
75 26
            : $_SERVER;
76
77 26
        $this->get = isset($globals["get"])
78 26
            ? array_merge($_GET, $globals["get"])
79
            : $_GET;
80
81 26
        $this->post = isset($globals["post"])
82 26
            ? array_merge($_POST, $globals["post"])
83
            : $_POST;
84 26
    }
85
86
87
88
    /**
89
     * Init the request class by reading information from the request.
90
     *
91
     * @return $this
92
     */
93 10
    public function init()
94
    {
95 10
        $this->requestUri = rawurldecode($this->getServer("REQUEST_URI"));
96 10
        $scriptName = rawurldecode($this->getServer("SCRIPT_NAME"));
97 10
        $this->path = rtrim(dirname($scriptName), "/");
98 10
        $this->scriptName = basename($scriptName);
99
100
        // The route and its parts
101 10
        $this->extractRoute();
102
103
        // Prepare to create siteUrl and baseUrl by using currentUrl
104 10
        $this->currentUrl = $this->getCurrentUrl();
105 10
        $parts = parse_url($this->currentUrl);
106 10
        $this->siteUrl = "{$parts["scheme"]}://{$parts["host"]}"
107 10
            . (isset($parts["port"])
108 10
                ? ":{$parts["port"]}"
109 10
                : "");
110 10
        $this->baseUrl = $this->siteUrl . $this->path;
111
112 10
        return $this;
113
    }
114
115
116
117
    /**
118
     * Get site url.
119
     *
120
     * @return string
121
     */
122 4
    public function getSiteUrl()
123
    {
124 4
        return $this->siteUrl;
125
    }
126
127
128
129
    /**
130
     * Get base url.
131
     *
132
     * @return string
133
     */
134 4
    public function getBaseUrl()
135
    {
136 4
        return $this->baseUrl;
137
    }
138
139
140
141
    /**
142
     * Get script name.
143
     *
144
     * @return string
145
     */
146
    public function getScriptName()
147
    {
148
        return $this->scriptName;
149
    }
150
151
152
153
    /**
154
     * Get route parts.
155
     *
156
     * @return array with route in its parts
157
     */
158
    public function getRouteParts()
159
    {
160
        return $this->routeParts;
161
    }
162
163
164
165
    /**
166
     * Get the route.
167
     *
168
     * @return string as the current extracted route
169
     */
170 6
    public function getRoute()
171
    {
172 6
        return $this->route;
173
    }
174
175
176
177
    /**
178
     * Get the request method.
179
     *
180
     * @return string as the request method
181
     */
182 5
    public function getMethod()
183
    {
184 5
        return $this->getServer("REQUEST_METHOD");
185
    }
186
187
188
189
    /**
190
     * Extract the part containing the route.
191
     *
192
     * @return string as the current extracted route
193
     */
194 10
    public function extractRoute()
195
    {
196 10
        $requestUri = $this->requestUri;
197 10
        $scriptPath = $this->path;
198 10
        $scriptFile = $this->scriptName;
199
200
        // Compare REQUEST_URI and SCRIPT_NAME as long they match,
201
        // leave the rest as current request.
202 10
        $i = 0;
203 10
        $len = min(strlen($requestUri), strlen($scriptPath));
204
        while ($i < $len
205 10
               && $requestUri[$i] == $scriptPath[$i]
206 10
        ) {
207 10
            $i++;
208 10
        }
209 10
        $route = trim(substr($requestUri, $i), "/");
210
211
        // Does the request start with script-name - remove it.
212 10
        $len1 = strlen($route);
213 10
        $len2 = strlen($scriptFile);
214
215
        if ($len2 <= $len1
216 10
            && substr_compare($scriptFile, $route, 0, $len2, true) === 0
217 10
        ) {
218 10
            $route = substr($route, $len2 + 1);
219 10
        }
220
221
        // Remove the ?-part from the query when analysing controller/metod/arg1/arg2
222 10
        $queryPos = strpos($route, "?");
223 10
        if ($queryPos !== false) {
224
            $route = substr($route, 0, $queryPos);
225
        }
226
227 10
        $route = ($route === false) ? "" : $route;
228
229 10
        $this->route = $route;
230 10
        $this->routeParts = explode("/", trim($route, "/"));
231
232 10
        return $this->route;
233
    }
234
235
236
237
    /**
238
     * Get the current url.
239
     *
240
     * @param boolean $queryString attach query string, default is true.
241
     *
242
     * @return string as current url.
243
     */
244 24
    public function getCurrentUrl($queryString = true)
245
    {
246 24
        $port  = $this->getServer("SERVER_PORT");
247 24
        $https = $this->getServer("HTTPS") == "on" ? true : false;
248
249
        $scheme = $https
250 24
            ? "https"
251 24
            : $this->getServer("REQUEST_SCHEME", "http");
252
253 24
        $server = $this->getServer("SERVER_NAME")
254 24
            ?: $this->getServer("HTTP_HOST");
255
256 24
        $port  = ($port === "80")
257 24
            ? ""
258 24
            : (($port == 443 && $https)
259 9
                ? ""
260 24
                : ":" . $port);
261
262 24
        $uri = rawurldecode($this->getServer("REQUEST_URI"));
263
        $uri = $queryString
264 24
            ? rtrim($uri, "/")
265 24
            : rtrim(strtok($uri, "?"), "/");
266
267 24
        $url  = htmlspecialchars($scheme) . "://";
268 24
        $url .= htmlspecialchars($server)
269 24
            . $port . htmlspecialchars(rawurldecode($uri));
270
271 24
        return $url;
272
    }
273
274
275
276
    /**
277
     * Get a value from the _SERVER array and use default if it is not set.
278
     *
279
     * @param string $key     to check if it exists in the $_SERVER variable
280
     * @param string $default value to return as default
281
     *
282
     * @return mixed
283
     */
284 25
    public function getServer($key, $default = null)
285
    {
286 25
        return isset($this->server[$key]) ? $this->server[$key] : $default;
287
    }
288
289
290
291
    /**
292
     * Set variable in the server array.
293
     *
294
     * @param mixed  $key   the key an the , or an key-value array
295
     * @param string $value the value of the key
296
     *
297
     * @return self
298
     */
299 18 View Code Duplication
    public function setServer($key, $value = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
300
    {
301 18
        if (is_array($key)) {
302
            $this->server = array_merge($this->server, $key);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($this->server, $key) of type array is incompatible with the declared type string of property $server.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
303
        } else {
304 18
            $this->server[$key] = $value;
305
        }
306 18
        return $this;
307
    }
308
309
310
311
    /**
312
     * Get a value from the _GET array and use default if it is not set.
313
     *
314
     * @param string $key     to check if it exists in the $_GET variable
315
     * @param string $default value to return as default
316
     *
317
     * @return mixed
318
     */
319 1
    public function getGet($key, $default = null)
320
    {
321 1
        return isset($this->get[$key]) ? $this->get[$key] : $default;
322
    }
323
324
325
326
    /**
327
     * Set variable in the get array.
328
     *
329
     * @param mixed  $key   the key an the , or an key-value array
330
     * @param string $value the value of the key
331
     *
332
     * @return self
333
     */
334 1 View Code Duplication
    public function setGet($key, $value = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
335
    {
336 1
        if (is_array($key)) {
337
            $this->get = array_merge($this->get, $key);
338
        } else {
339 1
            $this->get[$key] = $value;
340
        }
341 1
        return $this;
342
    }
343
344
345
346
    /**
347
     * Get a value from the _POST array and use default if it is not set.
348
     *
349
     * @param string $key     to check if it exists in the $_POST variable
350
     * @param string $default value to return as default
351
     *
352
     * @return mixed
353
     */
354
    public function getPost($key = null, $default = null)
355
    {
356
        if ($key) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $key of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
357
            return isset($this->post[$key]) ? $this->post[$key] : $default;
358
        }
359
360
        return $this->post;
361
    }
362
}
363