Completed
Push — master ( 18696b...b19b02 )
by Igor
02:18
created

Response::is404()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * @license MIT
4
 */
5
namespace Pivasic\Core;
6
7
/**
8
 * Represents a HTTP response.
9
 *
10
 * Class Response
11
 * @package Pivasic\Core
12
 */
13
class Response
14
{
15
    /**
16
     * Response constructor.
17
     */
18
    public function __construct()
19
    {
20
        $this->content = '';
21
        $this->is404 = true;
22
    }
23
24
    /**
25
     * False if response body was set.
26
     * @return bool
27
     */
28
    public function is404(): bool
29
    {
30
        return $this->is404;
31
    }
32
33
    /**
34
     * Send response.
35
     */
36
    public function send()
37
    {
38
        echo $this->content;
39
40
        if (function_exists('fastcgi_finish_request')) {
41
            fastcgi_finish_request();
42
        } elseif ('cli' !== php_sapi_name()) {
43
            $level = ob_get_level();
44
            if (0 < $level) {
45
                $status = ob_get_status(true);
46
                // PHP_OUTPUT_HANDLER_* are not defined on HHVM 3.3
47
                $flags = defined('PHP_OUTPUT_HANDLER_REMOVABLE') ? PHP_OUTPUT_HANDLER_REMOVABLE | PHP_OUTPUT_HANDLER_FLUSHABLE : -1;
48
                while ($level-- > 0 && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || $flags === ($s['flags'] & $flags) : $s['del'])) {
49
                    ob_end_flush();
50
                }
51
            }
52
        }
53
    }
54
55
    /**
56
     * Set response body.
57
     *
58
     * @param string $content
59
     */
60
    public function setContent(string $content)
61
    {
62
        $this->is404 = false;
63
        $this->content = $content;
64
    }
65
66
    /**
67
     * Set response header.
68
     *
69
     * @param string $name
70
     * @param string $value
71
     * @return bool
72
     */
73
    public function header(string $name, string $value): bool
74
    {
75
        if (!empty($name) && !empty($value) && !headers_sent()) {
76
            header($name . ': ' . $value);
77
            return true;
78
        }
79
        return false;
80
    }
81
82
    /**
83
     * @return bool
84
     */
85
    public function setContentTypeJson(): bool
86
    {
87
        return $this->header('Content-Type', 'application/json; charset=utf-8');
88
    }
89
90
    /**
91
     * @return bool
92
     */
93
    public function setContentTypeXml(): bool
94
    {
95
        return $this->header('Content-Type', 'text/xml; charset=utf-8');
96
    }
97
98
    /**
99
     * Set response status.
100
     *
101
     * @param int $statusCode           - status
102
     * @param string $version           - HTTP version
103
     * @param string $statusText   - status text
104
     * @return bool
105
     */
106
    public function setStatusCode(int $statusCode, string $version = '1.1', string $statusText = ''): bool
107
    {
108
        if (!headers_sent()) {
109
            $statusCode = intval($statusCode);
110
111
            if ('' == $statusText) {
112
                $statusTexts = [
113
                    100 => 'Continue',
114
                    101 => 'Switching Protocols',
115
                    102 => 'Processing',            // RFC2518
116
                    200 => 'OK',
117
                    201 => 'Created',
118
                    202 => 'Accepted',
119
                    203 => 'Non-Authoritative Information',
120
                    204 => 'No Content',
121
                    205 => 'Reset Content',
122
                    206 => 'Partial Content',
123
                    207 => 'Multi-Status',          // RFC4918
124
                    208 => 'Already Reported',      // RFC5842
125
                    226 => 'IM Used',               // RFC3229
126
                    300 => 'Multiple Choices',
127
                    301 => 'Moved Permanently',
128
                    302 => 'Found',
129
                    303 => 'See Other',
130
                    304 => 'Not Modified',
131
                    305 => 'Use Proxy',
132
                    307 => 'Temporary Redirect',
133
                    308 => 'Permanent Redirect',    // RFC7238
134
                    400 => 'Bad Request',
135
                    401 => 'Unauthorized',
136
                    402 => 'Payment Required',
137
                    403 => 'Forbidden',
138
                    404 => 'Not Found',
139
                    405 => 'Method Not Allowed',
140
                    406 => 'Not Acceptable',
141
                    407 => 'Proxy Authentication Required',
142
                    408 => 'Request Timeout',
143
                    409 => 'Conflict',
144
                    410 => 'Gone',
145
                    411 => 'Length Required',
146
                    412 => 'Precondition Failed',
147
                    413 => 'Payload Too Large',
148
                    414 => 'URI Too Long',
149
                    415 => 'Unsupported Media Type',
150
                    416 => 'Range Not Satisfiable',
151
                    417 => 'Expectation Failed',
152
                    418 => 'I\'m a teapot',                                               // RFC2324
153
                    422 => 'Unprocessable Entity',                                        // RFC4918
154
                    423 => 'Locked',                                                      // RFC4918
155
                    424 => 'Failed Dependency',                                           // RFC4918
156
                    425 => 'Reserved for WebDAV advanced collections expired proposal',   // RFC2817
157
                    426 => 'Upgrade Required',                                            // RFC2817
158
                    428 => 'Precondition Required',                                       // RFC6585
159
                    429 => 'Too Many Requests',                                           // RFC6585
160
                    431 => 'Request Header Fields Too Large',                             // RFC6585
161
                    500 => 'Internal Server Error',
162
                    501 => 'Not Implemented',
163
                    502 => 'Bad Gateway',
164
                    503 => 'Service Unavailable',
165
                    504 => 'Gateway Timeout',
166
                    505 => 'HTTP Version Not Supported',
167
                    506 => 'Variant Also Negotiates (Experimental)',                      // RFC2295
168
                    507 => 'Insufficient Storage',                                        // RFC4918
169
                    508 => 'Loop Detected',                                               // RFC5842
170
                    510 => 'Not Extended',                                                // RFC2774
171
                    511 => 'Network Authentication Required',                             // RFC6585
172
                ];
173
                $statusText = $statusTexts[$statusCode];
174
            }
175
176
            header(sprintf('HTTP/%s %s %s', $version, $statusCode, $statusText), true, $statusCode);
177
            return true;
178
        }
179
180
        return false;
181
    }
182
183
    /**
184
     * Redirect to url with statusCode and terminate.
185
     *
186
     * @param string $url
187
     * @param int $statusCode
188
     */
189
    public function redirect(string $url = '', int $statusCode = 302)
190
    {
191
        $this->is404 = false;
192
        $server = filter_input_array(INPUT_SERVER);
193
        if ('' == $url && isset($server['REQUEST_URI'])) {
194
            $url = '/' . trim($server['REQUEST_URI'], '/');
195
            preg_match('/^[\\a-zA-Z0-9-\._~:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=%]*$/iD', $url, $match);
196
            $url = $match[1] ?? '';
197
        }
198
199
        if (!headers_sent()) {
200
            header('Location: ' . $url, true, $statusCode);
201
        }
202
203
        echo sprintf('<!DOCTYPE html>
204
<html>
205
    <head>
206
        <meta charset="UTF-8" />
207
        <meta http-equiv="refresh" content="0;url=%1$s" />
208
        <title>Redirecting to %1$s</title>
209
    </head>
210
    <body>
211
        <script type="text/javascript"> window.location.href = "%1$s"; </script>
212
        Redirecting to <a href="%1$s">%1$s</a>.
213
    </body>
214
</html>', htmlspecialchars($url, ENT_QUOTES, 'UTF-8'));
215
216
    }
217
218
    private $content;
219
    private $is404;
220
}