Passed
Pull Request — master (#124)
by Arman
06:03 queued 02:57
created

HttpRequest::getAllSegments()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.9.0
13
 */
14
15
namespace Quantum\Http\Request;
16
17
use Quantum\Exceptions\LangException;
18
use Quantum\Exceptions\HttpException;
19
use Quantum\Exceptions\DiException;
20
use Quantum\Libraries\Csrf\Csrf;
21
use Quantum\Environment\Server;
22
use ReflectionException;
23
use Quantum\Bootstrap;
24
25
/**
26
 * Class HttpRequest
27
 * @package Quantum\Http
28
 */
29
abstract class HttpRequest
30
{
31
32
    use Header;
33
    use Body;
34
    use Url;
35
    use Query;
36
    use Params;
37
    use File;
38
39
    /**
40
     * Multipart form data
41
     */
42
    const CONTENT_FORM_DATA = 'multipart/form-data';
43
44
    /**
45
     * JSON payload
46
     */
47
    const CONTENT_JSON_PAYLOAD = 'application/json';
48
49
    /**
50
     * URL encoded
51
     */
52
    const CONTENT_URL_ENCODED = 'application/x-www-form-urlencoded';
53
54
    /**
55
     * Available methods
56
     */
57
    const METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
58
59
    /**
60
     * Request method
61
     * @var string
62
     */
63
    private static $__method = null;
64
65
    /**
66
     * Server
67
     * @var Server
68
     */
69
    private static $server;
70
71
    /**
72
     * Initiates the Request
73
     * @param Server $server
74
     * @throws HttpException
75
     * @throws LangException
76
     * @throws DiException
77
     * @throws ReflectionException
78
     */
79
    public static function init(Server $server)
80
    {
81
        if (get_caller_class(3) !== Bootstrap::class) {
82
            throw HttpException::unexpectedRequestInitialization();
83
        }
84
85
        self::$server = $server;
86
87
        self::$__method = self::$server->method();
88
89
        self::$__protocol = self::$server->protocol();
90
91
        self::$__host = self::$server->host();
92
93
        self::$__port = self::$server->port();
94
95
        self::$__uri = self::$server->uri();
96
97
        self::$__query = self::$server->query();
98
99
        self::$__headers = array_change_key_case((array)getallheaders(), CASE_LOWER);
100
101
        list('params' => $params, 'files' => $files) = self::parsedParams();
102
103
        self::$__request = array_merge(
104
            self::$__request,
105
            self::getParams(),
106
            self::postParams(),
107
            $params
108
        );
109
110
        self::$__files = array_merge(
111
            self::handleFiles($_FILES),
112
            $files
113
        );
114
    }
115
116
    /**
117
     * Creates new request for internal use
118
     * @param string $method
119
     * @param string $url
120
     * @param array|null $data
121
     * @param array|null $files
122
     * @throws HttpException
123
     * @throws LangException
124
     * @throws DiException
125
     * @throws ReflectionException
126
     */
127
    public static function create(string $method, string $url, array $data = null, array $files = null)
128
    {
129
        $parsed = parse_url($url);
130
131
        self::setMethod($method);
132
133
        if (isset($parsed['scheme'])) {
134
            self::setProtocol($parsed['scheme']);
135
        }
136
137
        if (isset($parsed['host'])) {
138
            self::setHost($parsed['host']);
139
        }
140
141
        if (isset($parsed['port'])) {
142
            self::setPort($parsed['port']);
143
        }
144
        if (isset($parsed['path'])) {
145
            self::setUri($parsed['path']);
146
        }
147
        if (isset($parsed['query'])) {
148
            self::setQuery($parsed['query']);
149
        }
150
151
        if ($data) {
152
            self::$__request = $data;
153
        }
154
155
        if ($files) {
156
            self::$__files = self::handleFiles($files);
157
        }
158
    }
159
160
    /**
161
     * Flushes the request header , body and files
162
     */
163
    public static function flush()
164
    {
165
        self::$__headers = [];
166
        self::$__request = [];
167
        self::$__files = [];
168
        self::$__protocol = null;
169
        self::$__host = null;
170
        self::$__port = null;
171
        self::$__uri = null;
172
        self::$__query = null;
173
    }
174
175
    /**
176
     * Gets the request method
177
     * @return string|null
178
     */
179
    public static function getMethod(): ?string
180
    {
181
        return self::$__method;
182
    }
183
184
    /**
185
     * Sets the request method
186
     * @param string $method
187
     * @throws HttpException
188
     * @throws LangException
189
     */
190
    public static function setMethod(string $method)
191
    {
192
        if (!in_array($method, self::METHODS)) {
193
            throw HttpException::methodNotAvailable($method);
194
        }
195
196
        self::$__method = $method;
197
    }
198
199
    /**
200
     * @param string $method
201
     * @return bool
202
     */
203
    public static function isMethod(string $method): bool
204
    {
205
        return strcasecmp($method, self::$__method) == 0;
206
    }
207
208
    /**
209
     * Gets the nth segment
210
     * @param integer $number
211
     * @return string|null
212
     */
213
    public static function getSegment(int $number): ?string
214
    {
215
        $segments = self::getAllSegments();
216
217
        if (isset($segments[$number])) {
218
            return $segments[$number];
219
        }
220
221
        return null;
222
    }
223
224
    /**
225
     * Gets the segments of current URI
226
     * @return array
227
     */
228
    public static function getAllSegments(): array
229
    {
230
        $segments = explode('/', trim(parse_url(self::$__uri)['path'], '/'));
231
        array_unshift($segments, 'zero_segment');
232
        return $segments;
233
    }
234
235
    /**
236
     * Gets Cross Site Request Forgery Token
237
     * @return string|null
238
     */
239
    public static function getCsrfToken(): ?string
240
    {
241
        $csrfToken = null;
242
243
        if (self::has(Csrf::TOKEN_KEY)) {
244
            $csrfToken = (string)self::get(Csrf::TOKEN_KEY);
245
        } elseif (self::hasHeader('X-' . Csrf::TOKEN_KEY)) {
246
            $csrfToken = self::getHeader('X-' . Csrf::TOKEN_KEY);
247
        }
248
249
        return $csrfToken;
250
    }
251
252
    /**
253
     * Gets Authorization Bearer token
254
     * @return string|null
255
     */
256
    public static function getAuthorizationBearer(): ?string
257
    {
258
        $bearerToken = null;
259
260
        $authorization = (string)self::getHeader('Authorization');
261
262
        if (self::hasHeader('Authorization')) {
263
            if (preg_match('/Bearer\s(\S+)/', $authorization, $matches)) {
264
                $bearerToken = $matches[1];
265
            }
266
        }
267
268
        return $bearerToken;
269
    }
270
271
    /**
272
     * Checks to see if request was AJAX request
273
     * @return bool
274
     */
275
    public static function isAjax(): bool
276
    {
277
        return self::hasHeader('X-REQUESTED-WITH') || self::$server->ajax();
278
    }
279
280
    /**
281
     * Gets the referrer
282
     * @return string|null
283
     */
284
    public static function getReferrer(): ?string
285
    {
286
        return self::$server->referrer();
287
    }
288
289
}
290