Completed
Push — master ( 2fc074...386195 )
by Mikael
03:23
created

Response::setStatusCode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Anax\Response;
4
5
/**
6
 * Handling a response.
7
 */
8
class Response
9
{
10
    /**
11
    * @var array $headers    set all headers to send.
12
    * @var array $statusCode set statuscode to use.
13
    * @var array $body       body to send with response.
14
    */
15
    private $headers = [];
16
    private $statusCode;
17
    private $body;
18
19
20
21
    /**
22
     * @var array $validStatusCode these status codes are supported.
23
     */
24
    private $validStatusCode = [
25
        "200" => "HTTP/1.1 200 OK",
26
        "400" => "HTTP/1.1 400 Bad Request",
27
        "403" => "HTTP/1.1 403 Forbidden",
28
        "404" => "HTTP/1.1 404 Not Found",
29
        "405" => "HTTP/1.1 405 Method Not Allowed",
30
        "418" => "HTTP/1.1 418 I'm a teapot",
31
        "500" => "HTTP/1.1 500 Internal Server Error",
32
        "501" => "HTTP/1.1 501 Not Implemented",
33
    ];
34
35
36
37
    /**
38
     * Set status code to be sent as part of headers.
39
     *
40
     * @param string $header type of header to set
0 ignored issues
show
Bug introduced by
There is no parameter named $header. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
41
     *
42
     * @return $this
43
     */
44 2
    public function setStatusCode($value)
45
    {
46 2
        if (!array_key_exists($value, $this->validStatusCode)) {
47 1
            throw new Exception("Unsupported statuscode: $value");
48
        }
49 1
        $this->statusCode = $value;
50 1
    }
51
52
53
54
    /**
55
     * Set headers.
56
     *
57
     * @param string $header type of header to set
58
     *
59
     * @return $this
60
     */
61
    public function addHeader($header)
62
    {
63
        $this->headers[] = $header;
64
    }
65
66
67
68
    /**
69
     * Check if headers are already sent and throw exception if it is.
70
     *
71
     * @return void
72
     *
73
     * @throws Exception
74
     */
75 1
    public function checkIfHeadersAlreadySent()
76
    {
77 1
        if (headers_sent($file, $line)) {
78 1
            throw new Exception("Try to send headers but headers already sent, output started at $file line $line.");
79
        }
80
    }
81
82
83
84
    /**
85
     * Send headers.
86
     *
87
     * @return $this
88
     */
89
    public function sendHeaders()
90
    {
91
        $this->checkIfHeadersAlreadySent();
92
93
        if (isset($this->statusCode)) {
94
            header($this->validStatusCode[$this->statusCode]);
95
        }
96
97
        foreach ($this->headers as $header) {
98
            header($header);
99
        }
100
101
        return $this;
102
    }
103
104
105
106
    /**
107
     * Set the body.
108
     *
109
     * @param callable|string $body either a string or a callable that
110
     *                              can generate the body.
111
     *
112
     * @return this
113
     */
114 1
    public function setBody($body)
115
    {
116 1
        if (is_string($body)) {
117 1
            $this->body = $body;
118 1
        } elseif (is_callable($body)) {
119
            ob_start();
120
            $res1 = call_user_func($body);
121
            $res2 = ob_get_contents();
122
            $this->body = $res2 . $res1;
123
            ob_end_clean();
124
        }
125 1
        return $this;
126
    }
127
128
129
130
    /**
131
     * Get the body.
132
     *
133
     * @return void
134
     */
135 1
    public function getBody()
136
    {
137 1
        return $this->body;
138
    }
139
140
141
142
    /**
143
     * Send response with an optional statuscode.
144
     *
145
     * @param integer $statusCode optional statuscode to send.
146
     *
147
     * @return void
148
     */
149
    public function send($statusCode = null)
150
    {
151
        if ($statusCode) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $statusCode of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. 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 integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
152
            $this->setStatusCode($statusCode);
153
        }
154
155
        if (!headers_sent()) {
156
            $this->sendHeaders();
157
        }
158
        echo $this->getBody();
159
    }
160
161
162
163
    /**
164
     * Send JSON response with an optional statuscode.
165
     *
166
     * @param mixed   $data       to be encoded as json.
167
     * @param integer $statusCode optional statuscode to send.
168
     *
169
     * @return void
170
     */
171
    public function sendJson($data, $statusCode = null)
172
    {
173
        if ($statusCode) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $statusCode of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. 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 integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
174
            $this->setStatusCode($statusCode);
175
        }
176
177
        if (!headers_sent()) {
178
            $this->addHeader("Content-Type: application/json; charset=utf8");
179
            $this->sendHeaders();
180
        }
181
        echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
182
    }
183
184
185
186
    /**
187
     * Redirect to another page.
188
     *
189
     * @param string $url to redirect to
190
     *
191
     * @return void
192
     *
193
     * @SuppressWarnings(PHPMD.ExitExpression)
194
     */
195
    public function redirect($url)
196
    {
197
        $this->checkIfHeadersAlreadySent();
198
        header("Location: " . $url);
199
        exit;
200
    }
201
}
202