Passed
Push — master ( 00ca16...033d0f )
by Alexander
02:11
created

SapiEmitter::emit()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 36
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 6
eloc 23
c 3
b 0
f 0
nc 9
nop 1
dl 0
loc 36
rs 8.9297
1
<?php declare(strict_types=1);
2
3
namespace Yiisoft\Yii\Web\Emitter;
4
5
use Psr\Http\Message\ResponseInterface;
6
7
/**
8
 * SapiEmitter sends a response using PHP Server API
9
 */
10
final class SapiEmitter implements EmitterInterface
11
{
12
    private const NO_BODY_RESPONSE_CODES = [204, 205, 304];
13
14
    private $shouldOutputBody = true;
15
16
    public function emit(ResponseInterface $response): bool
17
    {
18
        $status = $response->getStatusCode();
19
20
        foreach ($response->getHeaders() as $header => $values) {
21
            foreach ($values as $value) {
22
                header(sprintf(
23
                    '%s: %s',
24
                    $header,
25
                    $value
26
                ), $header !== 'Set-Cookie', $status);
27
            }
28
        }
29
30
        $reason = $response->getReasonPhrase();
31
32
        header(sprintf(
33
            'HTTP/%s %d%s',
34
            $response->getProtocolVersion(),
35
            $status,
36
            ($reason !== '' ? ' ' . $reason : '')
37
        ), true, $status);
38
39
        if ($this->shouldOutputBody($response)) {
40
            $contentLength = $response->getBody()->getSize();
41
            if ($response->hasHeader('Content-Length')) {
42
                $contentLengthHeader = $response->getHeader('Content-Length');
43
                $contentLength = array_shift($contentLengthHeader);
44
            }
45
46
            header(sprintf('Content-Length: %s', $contentLength), true, $status);
47
48
            echo $response->getBody();
49
        }
50
51
        return true;
52
    }
53
54
    private function shouldOutputBody(ResponseInterface $response): bool
55
    {
56
        return $this->shouldOutputBody && !\in_array($response->getStatusCode(), self::NO_BODY_RESPONSE_CODES, true);
57
    }
58
59
    public function withoutBody(): EmitterInterface
60
    {
61
        $new = clone $this;
62
        $new->shouldOutputBody = false;
63
        return $new;
64
    }
65
}
66