Passed
Push — main ( 92bf86...8347d6 )
by Thomas
02:44
created

ResponseFactory::createPsr7Stream()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 15
ccs 9
cts 9
cp 1
rs 9.9666
c 0
b 0
f 0
cc 4
nc 3
nop 1
crap 4

1 Method

Rating   Name   Duplication   Size   Complexity  
A ResponseFactory::validateFile() 0 8 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Conia\Chuck;
6
7
use Conia\Chuck\Exception\HttpNotFound;
8
use Conia\Chuck\Exception\RuntimeException;
9
use Conia\Chuck\Http\Factory;
10
use Conia\Chuck\Json;
11
use Conia\Chuck\Registry\Registry;
12
use Conia\Chuck\Response;
13
use finfo;
14
use Psr\Http\Message\ResponseInterface;
15
use Psr\Http\Message\StreamInterface;
16
17
class ResponseFactory
18
{
19 45
    public function __construct(protected Registry $registry)
20
    {
21 45
    }
22
23
    /**
24
     * @param null|resource|StreamInterface|string $body
25
     */
26 1
    public function create(
27
        int $code = 200,
28
        string $reasonPhrase = '',
29
    ): Response {
30 1
        return new Response($this->createPsr7Response($code, $reasonPhrase), $this->createHttpFactory());
31
    }
32
33
    /**
34
     * @param null|resource|StreamInterface|string $body
35
     */
36 13
    public function html(
37
        mixed $body = null,
38
        int $code = 200,
39
        string $reasonPhrase = '',
40
    ): Response {
41 13
        $psr7Response = $this->createPsr7Response($code, $reasonPhrase)->withAddedHeader(
42 13
            'Content-Type',
43 13
            'text/html'
44 13
        );
45
46 13
        if ($body) {
47 10
            $psr7Response = $psr7Response->withBody($this->createHttp($body));
48
        }
49
50 12
        return new Response($psr7Response, $this->createHttpFactory());
51
    }
52
53
    /**
54
     * @param null|resource|StreamInterface|string $body
55
     */
56 11
    public function text(
57
        mixed $body = null,
58
        int $code = 200,
59
        string $reasonPhrase = '',
60
    ): Response {
61 11
        $psr7Response = $this->createPsr7Response($code, $reasonPhrase)->withAddedHeader(
62 11
            'Content-Type',
63 11
            'text/plain'
64 11
        );
65
66 11
        if ($body) {
67 10
            $psr7Response = $psr7Response->withBody($this->createHttp($body));
68
        }
69
70 11
        return new Response($psr7Response, $this->createHttpFactory());
71
    }
72
73 13
    public function json(
74
        mixed $data,
75
        int $code = 200,
76
        string $reasonPhrase = '',
77
    ): Response {
78 13
        $psr7Response = $this->createPsr7Response($code, $reasonPhrase)->withAddedHeader(
79 13
            'Content-Type',
80 13
            'application/json'
81 13
        );
82
83 13
        $psr7Response = $psr7Response->withBody($this->createHttp(Json::encode($data)));
84
85 13
        return new Response($psr7Response, $this->createHttpFactory());
86
    }
87
88 6
    public function file(
89
        string $file,
90
        bool $throwNotFound = true,
91
        int $code = 200,
92
        string $reasonPhrase = '',
93
    ): Response {
94 6
        $this->validateFile($file, $throwNotFound);
95
96 4
        $finfo = new finfo(FILEINFO_MIME_TYPE);
97 4
        $contentType = $finfo->file($file);
98 4
        $finfo = new finfo(FILEINFO_MIME_ENCODING);
99 4
        $encoding = $finfo->file($file);
100
101 4
        $psr7Response = $this->createPsr7Response($code, $reasonPhrase)
102 4
            ->withAddedHeader('Content-Type', $contentType)
103 4
            ->withAddedHeader('Content-Transfer-Encoding', $encoding);
104
105 4
        $stream = $this->createHttpFactory()->streamFromFile($file, 'rb');
106 4
        $size = $stream->getSize();
107
108 4
        if (!is_null($size)) {
109 4
            $psr7Response = $psr7Response->withAddedHeader('Content-Length', (string)$size);
110
        }
111
112 4
        return new Response($psr7Response->withBody($stream), $this->createHttpFactory());
113
    }
114
115 3
    public function download(
116
        string $file,
117
        string $newName = '',
118
        bool $throwNotFound = true,
119
        int $code = 200,
120
        string $reasonPhrase = '',
121
    ): Response {
122 3
        $response = $this->file($file, $throwNotFound, $code, $reasonPhrase);
123 3
        $response->header(
124 3
            'Content-Disposition',
125 3
            'attachment; filename="' . ($newName ?: basename($file)) . '"'
126 3
        );
127
128 3
        return $response;
129
    }
130
131 1
    public function sendfile(
132
        string $file,
133
        bool $throwNotFound = true,
134
        int $code = 200,
135
        string $reasonPhrase = '',
136
    ): Response {
137 1
        $this->validateFile($file, $throwNotFound);
138 1
        $server = strtolower($_SERVER['SERVER_SOFTWARE'] ?? '');
139 1
        $psr7Response = $this->createPsr7Response($code, $reasonPhrase);
140
141 1
        if (strpos($server, 'nginx') !== false) {
142 1
            $psr7Response = $psr7Response->withAddedHeader('X-Accel-Redirect', $file);
143
        } else {
144 1
            $psr7Response = $psr7Response->withAddedHeader('X-Sendfile', $file);
145
        }
146
147 1
        return new Response($psr7Response, $this->createHttpFactory());
148
    }
149
150 43
    protected function createPsr7Response(
151
        int $code = 200,
152
        string $reasonPhrase = ''
153
    ): ResponseInterface {
154 43
        $response = $this->createHttpFactory()->response($code, $reasonPhrase);
155 43
        assert($response instanceof ResponseInterface);
156
157 43
        return $response;
158
    }
159
160 43
    protected function createHttpFactory(): Factory
161
    {
162 43
        $factory = $this->registry->get(Factory::class);
163 43
        assert($factory instanceof Factory);
164
165 43
        return $factory;
166
    }
167
168 33
    protected function createHttp(mixed $body): StreamInterface
169
    {
170 33
        $factory = $this->createHttpFactory();
171 33
        $stream = $factory->stream($body);
172 32
        assert($stream instanceof StreamInterface);
173
174 32
        return $stream;
175
    }
176
177 7
    protected function validateFile(string $file, bool $throwNotFound): void
178
    {
179 7
        if (!is_file($file)) {
180 2
            if ($throwNotFound) {
181 1
                throw new HttpNotFound();
182
            }
183
184 1
            throw new RuntimeException('File not found');
185
        }
186
    }
187
}
188