Completed
Push — master ( 929e4f...acab5f )
by Anton
07:41
created

Request::checkAccept()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5.0342

Importance

Changes 0
Metric Value
cc 5
nc 4
nop 1
dl 0
loc 20
ccs 8
cts 9
cp 0.8889
crap 5.0342
rs 9.2888
c 0
b 0
f 0
1
<?php
2
/**
3
 * Bluz Framework Component
4
 *
5
 * @copyright Bluz PHP Team
6
 * @link      https://github.com/bluzphp/framework
7
 */
8
9
declare(strict_types=1);
10
11
namespace Bluz\Proxy;
12
13
use Bluz\Common\Exception\ComponentException;
14
use Bluz\Http\RequestMethod;
15
use Bluz\Request\RequestFactory;
16
use Psr\Http\Message\UriInterface;
17
use Zend\Diactoros\ServerRequest as Instance;
18
19
/**
20
 * Proxy to Request
21
 *
22
 * Example of usage
23
 * <code>
24
 *     use Bluz\Proxy\Request;
25
 *
26
 *     Request::getParam('foo');
27
 * </code>
28
 *
29
 * @package  Bluz\Proxy
30
 * @author   Anton Shevchuk
31
 *
32
 * @todo     Proxy class should be clean
33
 *
34
 * @method   static Instance getInstance()
35
 *
36
 * @method   static UriInterface getUri()
37
 * @see      \Zend\Diactoros\RequestTrait::getUri()
38
 */
39
final class Request
40
{
41
    use ProxyTrait;
42
43
    /**
44
     * @const string HTTP content types
45
     */
46
    public const TYPE_ANY = '*/*';
47
    public const TYPE_HTML = 'text/html';
48
    public const TYPE_JSON = 'application/json';
49
50
    /**
51
     * @var array|null Accepted type
52
     */
53
    static private $accept;
54
55
    /**
56
     * Init instance
57
     *
58
     * @throws ComponentException
59
     */
60
    private static function initInstance()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
61
    {
62
        throw new ComponentException('Class `Proxy\\Request` required external initialization');
63
    }
64
65
    /**
66
     * Retrieve a member of the $_GET super global
67
     *
68
     * If no $key is passed, returns the entire $_GET array.
69
     *
70
     * @param  string $key
71
     * @param  string $default Default value to use if key not found
72
     *
73
     * @return string Returns null if key does not exist
74
     */
75 77
    public static function getQuery($key = null, $default = null)
76
    {
77 77
        return self::getInstance()->getQueryParams()[$key] ?? $default;
78
    }
79
80
    /**
81
     * Retrieve a member of the $_POST super global
82
     *
83
     * If no $key is passed, returns the entire $_POST array.
84
     *
85
     * @param  string $key
86
     * @param  string $default Default value to use if key not found
87
     *
88
     * @return string Returns null if key does not exist
89
     */
90 67
    public static function getPost($key = null, $default = null)
91
    {
92 67
        return self::getInstance()->getParsedBody()[$key] ?? $default;
93
    }
94
95
    /**
96
     * Retrieve a member of the $_SERVER super global
97
     *
98
     * If no $key is passed, returns the entire $_SERVER array.
99
     *
100
     * @param  string $key
101
     * @param  string $default Default value to use if key not found
102
     *
103
     * @return string Returns null if key does not exist
104
     */
105 8
    public static function getServer($key = null, $default = null)
106
    {
107 8
        return self::getInstance()->getServerParams()[$key] ?? $default;
108
    }
109
110
    /**
111
     * Retrieve a member of the $_COOKIE super global
112
     *
113
     * If no $key is passed, returns the entire $_COOKIE array.
114
     *
115
     * @param  string $key
116
     * @param  string $default Default value to use if key not found
117
     *
118
     * @return string Returns null if key does not exist
119
     */
120 1
    public static function getCookie($key = null, $default = null)
121
    {
122 1
        return self::getInstance()->getCookieParams()[$key] ?? $default;
123
    }
124
125
    /**
126
     * Retrieve a member of the $_ENV super global
127
     *
128
     * If no $key is passed, returns the entire $_ENV array.
129
     *
130
     * @param  string $key
131
     * @param  string $default Default value to use if key not found
132
     *
133
     * @return string Returns null if key does not exist
134
     */
135 1
    public static function getEnv($key = null, $default = null)
136
    {
137 1
        return $_ENV[$key] ?? $default;
138
    }
139
140
    /**
141
     * Search for a header value
142
     *
143
     * @param string $header
144
     * @param mixed  $default
145
     *
146
     * @return string
147
     */
148 40
    public static function getHeader($header, $default = null)
149
    {
150 40
        $header  = strtolower($header);
151 40
        $headers = self::getInstance()->getHeaders();
152 40
        $headers = array_change_key_case($headers, CASE_LOWER);
153 40
        if (array_key_exists($header, $headers)) {
154 5
            $value = \is_array($headers[$header]) ? implode(', ', $headers[$header]) : $headers[$header];
155 5
            return $value;
156
        }
157 40
        return $default;
158
    }
159
160
    /**
161
     * Access values contained in the superglobals as public members
162
     * Order of precedence: 1. GET, 2. POST
163
     *
164
     * @param  string $key
165
     * @param  null   $default
166
     *
167
     * @return string|null
168
     * @link http://msdn.microsoft.com/en-us/library/system.web.httprequest.item.aspx
169
     */
170 77
    public static function getParam($key, $default = null)
171
    {
172
        return
173 77
            self::getQuery($key) ??
174 66
            self::getPost($key) ??
175 77
            $default;
176
    }
177
178
    /**
179
     * Get all params from GET and POST or PUT
180
     *
181
     * @return array
182
     */
183 36
    public static function getParams()
184
    {
185 36
        $body = (array)self::getInstance()->getParsedBody();
186 36
        $query = (array)self::getInstance()->getQueryParams();
187 36
        return array_merge($body, $query);
188
    }
189
190
    /**
191
     * Get uploaded file
192
     *
193
     * @param  string $name
194
     *
195
     * @return \Zend\Diactoros\UploadedFile
196
     */
197
    public static function getFile($name)
198
    {
199
        return self::getInstance()->getUploadedFiles()[$name] ?? false;
200
    }
201
202
    /**
203
     * Get the client's IP address
204
     *
205
     * @param  bool $checkProxy
206
     *
207
     * @return string
208
     */
209 1
    public static function getClientIp($checkProxy = true)
210
    {
211 1
        $result = null;
212 1
        if ($checkProxy) {
213 1
            $result = self::getServer('HTTP_CLIENT_IP') ?? self::getServer('HTTP_X_FORWARDED_FOR') ?? null;
214
        }
215 1
        return $result ?? self::getServer('REMOTE_ADDR');
216
    }
217
218
    /**
219
     * Get module
220
     *
221
     * @return string
222
     */
223 46
    public static function getModule(): string
224
    {
225 46
        return self::getParam('_module', Router::getDefaultModule());
226
    }
227
228
    /**
229
     * Get controller
230
     *
231
     * @return string
232
     */
233 46
    public static function getController(): string
234
    {
235 46
        return self::getParam('_controller', Router::getDefaultController());
236
    }
237
238
    /**
239
     * Get method
240
     *
241
     * @return string
242
     */
243 25
    public static function getMethod(): string
244
    {
245 25
        return self::getParam('_method', self::getInstance()->getMethod());
246
    }
247
248
    /**
249
     * Get Accept MIME Type
250
     *
251
     * @return array
252
     */
253 40
    public static function getAccept(): array
254
    {
255 40
        if (!self::$accept) {
256
            // save to static variable
257 40
            self::$accept = [];
258
259
            // get header from request
260 40
            $header = self::getHeader('accept');
261
262
            // nothing ...
263 40
            if (!$header) {
264 37
                return self::$accept;
265
            }
266
267
            // make array if types
268 3
            $header = explode(',', $header);
269 3
            $header = array_map('trim', $header);
270
271 3
            foreach ($header as $a) {
272
                // the default quality is 1.
273 3
                $q = 1;
274
                // check if there is a different quality
275 3
                if (strpos($a, ';q=') or strpos($a, '; q=')) {
276
                    // divide "mime/type;q=X" into two parts: "mime/type" i "X"
277
                    [$a, $q] = preg_split('/;([ ]?)q=/', $a);
278
                }
279
                // remove other extension
280 3
                if (strpos($a, ';')) {
281
                    $a = substr($a, 0, strpos($a, ';'));
282
                }
283
284
                // mime-type $a is accepted with the quality $q
285
                // WARNING: $q == 0 means, that mime-type isn’t supported!
286 3
                self::$accept[$a] = (float)$q;
287
            }
288 3
            arsort(self::$accept);
289
        }
290 3
        return self::$accept;
291
    }
292
293
    /**
294
     * Reset accept for tests
295
     *
296
     * @return void
297
     */
298 849
    public static function resetAccept()
299
    {
300 849
        self::$accept = null;
301 849
    }
302
303
    /**
304
     * Check Accept header
305
     *
306
     * @param array $allowTypes
307
     *
308
     * @return string|false
309
     */
310 40
    public static function checkAccept(array $allowTypes = [])
311
    {
312 40
        $accept = self::getAccept();
313
314
        // if no parameter was passed, just return first mime type from parsed data
315 40
        if (empty($allowTypes)) {
316
            return current(array_keys($accept));
317
        }
318
319 40
        $allowTypes = array_map('strtolower', $allowTypes);
320
321
        // let’s check our supported types:
322 40
        foreach ($accept as $mime => $quality) {
323 3
            if ($quality && in_array($mime, $allowTypes)) {
324 3
                return $mime;
325
            }
326
        }
327
        // no mime-type found
328 38
        return false;
329
    }
330
331
    /**
332
     * Check CLI
333
     *
334
     * @return bool
335
     */
336 1
    public static function isCli(): bool
337
    {
338 1
        return (PHP_SAPI === 'cli');
339
    }
340
341
    /**
342
     * Check HTTP
343
     *
344
     * @return bool
345
     */
346 3
    public static function isHttp(): bool
347
    {
348 3
        return (PHP_SAPI !== 'cli');
349
    }
350
351
    /**
352
     * Is this a GET method request?
353
     *
354
     * @return bool
355
     */
356 2
    public static function isGet(): bool
357
    {
358 2
        return (self::getInstance()->getMethod() === RequestMethod::GET);
359
    }
360
361
    /**
362
     * Is this a POST method request?
363
     *
364
     * @return bool
365
     */
366 2
    public static function isPost(): bool
367
    {
368 2
        return (self::getInstance()->getMethod() === RequestMethod::POST);
369
    }
370
371
    /**
372
     * Is this a PUT method request?
373
     *
374
     * @return bool
375
     */
376 1
    public static function isPut(): bool
377
    {
378 1
        return (self::getInstance()->getMethod() === RequestMethod::PUT);
379
    }
380
381
    /**
382
     * Is this a DELETE method request?
383
     *
384
     * @return bool
385
     */
386 1
    public static function isDelete(): bool
387
    {
388 1
        return (self::getInstance()->getMethod() === RequestMethod::DELETE);
389
    }
390
391
    /**
392
     * Is the request a Javascript XMLHttpRequest?
393
     *
394
     * @return bool
395
     */
396 9
    public static function isXmlHttpRequest(): bool
397
    {
398 9
        return (self::getHeader('X-Requested-With') === 'XMLHttpRequest');
399
    }
400
}
401