HttpUtility   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 170
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 19
eloc 92
dl 0
loc 170
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A redirect() 0 6 1
A setResponseCodeAndExit() 0 5 1
A setResponseCode() 0 8 1
B buildUrl() 0 10 7
B buildQueryString() 0 20 9
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Core\Utility;
17
18
/**
19
 * HTTP Utility class
20
 */
21
class HttpUtility
22
{
23
    // HTTP Headers, see https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
24
    // INFORMATIONAL CODES
25
    const HTTP_STATUS_100 = 'HTTP/1.1 100 Continue';
26
    const HTTP_STATUS_101 = 'HTTP/1.1 101 Switching Protocols';
27
    const HTTP_STATUS_102 = 'HTTP/1.1 102 Processing';
28
    const HTTP_STATUS_103 = 'HTTP/1.1 103 Early Hints';
29
    // SUCCESS CODES
30
    const HTTP_STATUS_200 = 'HTTP/1.1 200 OK';
31
    const HTTP_STATUS_201 = 'HTTP/1.1 201 Created';
32
    const HTTP_STATUS_202 = 'HTTP/1.1 202 Accepted';
33
    const HTTP_STATUS_203 = 'HTTP/1.1 203 Non-Authoritative Information';
34
    const HTTP_STATUS_204 = 'HTTP/1.1 204 No Content';
35
    const HTTP_STATUS_205 = 'HTTP/1.1 205 Reset Content';
36
    const HTTP_STATUS_206 = 'HTTP/1.1 206 Partial Content';
37
    const HTTP_STATUS_207 = 'HTTP/1.1 207 Multi-status';
38
    const HTTP_STATUS_208 = 'HTTP/1.1 208 Already Reported';
39
    const HTTP_STATUS_226 = 'HTTP/1.1 226 IM Used';
40
    // REDIRECTION CODES
41
    const HTTP_STATUS_300 = 'HTTP/1.1 300 Multiple Choices';
42
    const HTTP_STATUS_301 = 'HTTP/1.1 301 Moved Permanently';
43
    const HTTP_STATUS_302 = 'HTTP/1.1 302 Found';
44
    const HTTP_STATUS_303 = 'HTTP/1.1 303 See Other';
45
    const HTTP_STATUS_304 = 'HTTP/1.1 304 Not Modified';
46
    const HTTP_STATUS_305 = 'HTTP/1.1 305 Use Proxy';
47
    const HTTP_STATUS_306 = 'HTTP/1.1 306 Switch Proxy'; // Deprecated
48
    const HTTP_STATUS_307 = 'HTTP/1.1 307 Temporary Redirect';
49
    const HTTP_STATUS_308 = 'HTTP/1.1 308 Permanent Redirect';
50
    // CLIENT ERROR
51
    const HTTP_STATUS_400 = 'HTTP/1.1 400 Bad Request';
52
    const HTTP_STATUS_401 = 'HTTP/1.1 401 Unauthorized';
53
    const HTTP_STATUS_402 = 'HTTP/1.1 402 Payment Required';
54
    const HTTP_STATUS_403 = 'HTTP/1.1 403 Forbidden';
55
    const HTTP_STATUS_404 = 'HTTP/1.1 404 Not Found';
56
    const HTTP_STATUS_405 = 'HTTP/1.1 405 Method Not Allowed';
57
    const HTTP_STATUS_406 = 'HTTP/1.1 406 Not Acceptable';
58
    const HTTP_STATUS_407 = 'HTTP/1.1 407 Proxy Authentication Required';
59
    const HTTP_STATUS_408 = 'HTTP/1.1 408 Request Timeout';
60
    const HTTP_STATUS_409 = 'HTTP/1.1 409 Conflict';
61
    const HTTP_STATUS_410 = 'HTTP/1.1 410 Gone';
62
    const HTTP_STATUS_411 = 'HTTP/1.1 411 Length Required';
63
    const HTTP_STATUS_412 = 'HTTP/1.1 412 Precondition Failed';
64
    const HTTP_STATUS_413 = 'HTTP/1.1 413 Request Entity Too Large';
65
    const HTTP_STATUS_414 = 'HTTP/1.1 414 URI Too Long';
66
    const HTTP_STATUS_415 = 'HTTP/1.1 415 Unsupported Media Type';
67
    const HTTP_STATUS_416 = 'HTTP/1.1 416 Requested range not satisfiable';
68
    const HTTP_STATUS_417 = 'HTTP/1.1 417 Expectation Failed';
69
    const HTTP_STATUS_418 = 'HTTP/1.1 418 I\'m a teapot';
70
    const HTTP_STATUS_422 = 'HTTP/1.1 422 Unprocessable Entity';
71
    const HTTP_STATUS_423 = 'HTTP/1.1 423 Locked';
72
    const HTTP_STATUS_424 = 'HTTP/1.1 424 Failed Dependency';
73
    const HTTP_STATUS_425 = 'HTTP/1.1 425 Unordered Collection';
74
    const HTTP_STATUS_426 = 'HTTP/1.1 426 Upgrade Required';
75
    const HTTP_STATUS_428 = 'HTTP/1.1 428 Precondition Required';
76
    const HTTP_STATUS_429 = 'HTTP/1.1 429 Too Many Requests';
77
    const HTTP_STATUS_431 = 'HTTP/1.1 431 Request Header Fields Too Large';
78
    const HTTP_STATUS_451 = 'HTTP/1.1 451 Unavailable For Legal Reasons';
79
    // SERVER ERROR
80
    const HTTP_STATUS_500 = 'HTTP/1.1 500 Internal Server Error';
81
    const HTTP_STATUS_501 = 'HTTP/1.1 501 Not Implemented';
82
    const HTTP_STATUS_502 = 'HTTP/1.1 502 Bad Gateway';
83
    const HTTP_STATUS_503 = 'HTTP/1.1 503 Service Unavailable';
84
    const HTTP_STATUS_504 = 'HTTP/1.1 504 Gateway Time-out';
85
    const HTTP_STATUS_505 = 'HTTP/1.1 505 Version not Supported';
86
    const HTTP_STATUS_506 = 'HTTP/1.1 506 Variant Also Negotiates';
87
    const HTTP_STATUS_507 = 'HTTP/1.1 507 Insufficient Storage';
88
    const HTTP_STATUS_508 = 'HTTP/1.1 508 Loop Detected';
89
    const HTTP_STATUS_509 = 'HTTP/1.1 509 Bandwidth Limit Exceeded';
90
    const HTTP_STATUS_511 = 'HTTP/1.1 511 Network Authentication Required';
91
    // URL Schemes
92
    const SCHEME_HTTP = 1;
93
    const SCHEME_HTTPS = 2;
94
95
    /**
96
     * Sends a redirect header response and exits. Additionally the URL is
97
     * checked and if needed corrected to match the format required for a
98
     * Location redirect header. By default the HTTP status code sent is
99
     * a 'HTTP/1.1 303 See Other'.
100
     *
101
     * @param string $url The target URL to redirect to
102
     * @param string $httpStatus An optional HTTP status header. Default is 'HTTP/1.1 303 See Other'
103
     * @deprecated since v11, will be removed in v12.
104
     */
105
    public static function redirect($url, $httpStatus = self::HTTP_STATUS_303)
106
    {
107
        // Deprecation logged by setResponseCode()
108
        self::setResponseCode($httpStatus);
109
        header('Location: ' . GeneralUtility::locationHeaderUrl($url));
110
        die;
111
    }
112
113
    /**
114
     * Set a specific response code like 404.
115
     *
116
     * @param string $httpStatus One of the HTTP_STATUS_* class class constants, default to self::HTTP_STATUS_303
117
     * @deprecated since v11, will be removed in v12.
118
     */
119
    public static function setResponseCode($httpStatus = self::HTTP_STATUS_303)
120
    {
121
        trigger_error(
122
            'All methods in ' . __CLASS__ . ', manipulationg HTTP headers, are deprecated and will be removed in v12.',
123
            E_USER_DEPRECATED
124
        );
125
126
        header($httpStatus);
127
    }
128
129
    /**
130
     * Set a specific response code and exit script execution.
131
     *
132
     * @param string $httpStatus One of the HTTP_STATUS_* class class constants, default to self::HTTP_STATUS_303
133
     * @deprecated since v11, will be removed in v12.
134
     */
135
    public static function setResponseCodeAndExit($httpStatus = self::HTTP_STATUS_303)
136
    {
137
        // Deprecation logged by setResponseCode()
138
        self::setResponseCode($httpStatus);
139
        die;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
140
    }
141
142
    /**
143
     * Builds a URL string from an array with the URL parts, as e.g. output by parse_url().
144
     *
145
     * @param array $urlParts
146
     * @return string
147
     * @see http://www.php.net/parse_url
148
     */
149
    public static function buildUrl(array $urlParts)
150
    {
151
        return (isset($urlParts['scheme']) ? $urlParts['scheme'] . '://' : '') .
152
            (isset($urlParts['user']) ? $urlParts['user'] .
153
            (isset($urlParts['pass']) ? ':' . $urlParts['pass'] : '') . '@' : '') .
154
            ($urlParts['host'] ?? '') .
155
            (isset($urlParts['port']) ? ':' . $urlParts['port'] : '') .
156
            ($urlParts['path'] ?? '') .
157
            (isset($urlParts['query']) ? '?' . $urlParts['query'] : '') .
158
            (isset($urlParts['fragment']) ? '#' . $urlParts['fragment'] : '');
159
    }
160
161
    /**
162
     * Implodes a multidimensional array of query parameters to a string of GET parameters (eg. param[key][key2]=value2&param[key][key3]=value3)
163
     * and properly encodes parameter names as well as values. Spaces are encoded as %20
164
     *
165
     * @param array $parameters The (multidimensional) array of query parameters with values
166
     * @param string $prependCharacter If the created query string is not empty, prepend this character "?" or "&" else no prepend
167
     * @param bool $skipEmptyParameters If true, empty parameters (blank string, empty array, null) are removed.
168
     * @return string Imploded result, for example param[key][key2]=value2&param[key][key3]=value3
169
     * @see explodeUrl2Array()
170
     */
171
    public static function buildQueryString(array $parameters, string $prependCharacter = '', bool $skipEmptyParameters = false): string
172
    {
173
        if (empty($parameters)) {
174
            return '';
175
        }
176
177
        if ($skipEmptyParameters) {
178
            // This callback filters empty strings, array and null but keeps zero integers
179
            $parameters = ArrayUtility::filterRecursive(
180
                $parameters,
181
                function ($item) {
182
                    return $item !== '' && $item !== [] && $item !== null;
183
                }
184
            );
185
        }
186
187
        $queryString = http_build_query($parameters, '', '&', PHP_QUERY_RFC3986);
188
        $prependCharacter = $prependCharacter === '?' || $prependCharacter === '&' ? $prependCharacter : '';
189
190
        return $queryString && $prependCharacter ? $prependCharacter . $queryString : $queryString;
191
    }
192
}
193