Code Coverage |
||||||||||||||||
Lines |
Branches |
Paths |
Functions and Methods |
Classes and Traits |
||||||||||||
| Total | |
100.00% |
106 / 106 |
|
98.61% |
71 / 72 |
|
76.56% |
49 / 64 |
|
96.55% |
28 / 29 |
CRAP | |
0.00% |
0 / 1 |
| Response | |
100.00% |
106 / 106 |
|
98.61% |
71 / 72 |
|
76.56% |
49 / 64 |
|
100.00% |
29 / 29 |
89.16 | |
100.00% |
1 / 1 |
| __construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| create | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| unwrap | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| wrap | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| status | |
100.00% |
4 / 4 |
|
100.00% |
4 / 4 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| getStatusCode | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getReasonPhrase | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getProtocolVersion | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| protocolVersion | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| header | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| removeHeader | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| headers | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getHeader | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| hasHeader | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| body | |
100.00% |
9 / 9 |
|
100.00% |
9 / 9 |
|
71.43% |
5 / 7 |
|
100.00% |
1 / 1 |
5.58 | |||
| setStringBody | |
100.00% |
9 / 9 |
|
100.00% |
5 / 5 |
|
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
| setStreamBody | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| setResourceBody | |
100.00% |
6 / 6 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| getBody | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| write | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| redirect | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| withContentType | |
100.00% |
6 / 6 |
|
100.00% |
3 / 3 |
|
50.00% |
1 / 2 |
|
100.00% |
1 / 1 |
2.50 | |||
| html | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| text | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| json | |
100.00% |
4 / 4 |
|
100.00% |
4 / 4 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| file | |
100.00% |
26 / 26 |
|
100.00% |
14 / 14 |
|
50.00% |
10 / 20 |
|
100.00% |
1 / 1 |
30.00 | |||
| download | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| sendfile | |
100.00% |
7 / 7 |
|
85.71% |
6 / 7 |
|
50.00% |
2 / 4 |
|
100.00% |
1 / 1 |
2.50 | |||
| validateFile | |
100.00% |
2 / 2 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Celemas\Core; |
| 6 | |
| 7 | use Celemas\Core\Exception\FileNotFoundException; |
| 8 | use Celemas\Core\Exception\RuntimeException; |
| 9 | use Celemas\Core\Factory\Factory; |
| 10 | use Celemas\Router\ResponseWrapper; |
| 11 | use finfo; |
| 12 | use Override; |
| 13 | use Psr\Http\Message\ResponseInterface as PsrResponse; |
| 14 | use Psr\Http\Message\StreamFactoryInterface as PsrStreamFactory; |
| 15 | use Psr\Http\Message\StreamInterface as PsrStream; |
| 16 | use Stringable; |
| 17 | use Traversable; |
| 18 | |
| 19 | /** @api */ |
| 20 | class Response implements ResponseWrapper |
| 21 | { |
| 22 | public function __construct( |
| 23 | protected PsrResponse $psrResponse, |
| 24 | protected readonly ?PsrStreamFactory $streamFactory = null, |
| 25 | ) {} |
| 26 | |
| 27 | public static function create(Factory $factory): self |
| 28 | { |
| 29 | return new self($factory->response(), $factory->streamFactory()); |
| 30 | } |
| 31 | |
| 32 | #[Override] |
| 33 | public function unwrap(): PsrResponse |
| 34 | { |
| 35 | return $this->psrResponse; |
| 36 | } |
| 37 | |
| 38 | public function wrap(PsrResponse $response): static |
| 39 | { |
| 40 | $this->psrResponse = $response; |
| 41 | |
| 42 | return $this; |
| 43 | } |
| 44 | |
| 45 | public function status(int $statusCode, string $reasonPhrase = ''): static |
| 46 | { |
| 47 | if ($reasonPhrase === '') { |
| 48 | $this->psrResponse = $this->psrResponse->withStatus($statusCode); |
| 49 | } else { |
| 50 | $this->psrResponse = $this->psrResponse->withStatus($statusCode, $reasonPhrase); |
| 51 | } |
| 52 | |
| 53 | return $this; |
| 54 | } |
| 55 | |
| 56 | public function getStatusCode(): int |
| 57 | { |
| 58 | return $this->psrResponse->getStatusCode(); |
| 59 | } |
| 60 | |
| 61 | public function getReasonPhrase(): string |
| 62 | { |
| 63 | return $this->psrResponse->getReasonPhrase(); |
| 64 | } |
| 65 | |
| 66 | public function getProtocolVersion(): string |
| 67 | { |
| 68 | return $this->psrResponse->getProtocolVersion(); |
| 69 | } |
| 70 | |
| 71 | public function protocolVersion(string $protocol): static |
| 72 | { |
| 73 | $this->psrResponse = $this->psrResponse->withProtocolVersion($protocol); |
| 74 | |
| 75 | return $this; |
| 76 | } |
| 77 | |
| 78 | public function header(string $name, string $value): static |
| 79 | { |
| 80 | $this->psrResponse = $this->psrResponse->withAddedHeader($name, $value); |
| 81 | |
| 82 | return $this; |
| 83 | } |
| 84 | |
| 85 | public function removeHeader(string $name): static |
| 86 | { |
| 87 | $this->psrResponse = $this->psrResponse->withoutHeader($name); |
| 88 | |
| 89 | return $this; |
| 90 | } |
| 91 | |
| 92 | public function headers(): array |
| 93 | { |
| 94 | return $this->psrResponse->getHeaders(); |
| 95 | } |
| 96 | |
| 97 | public function getHeader(string $name): array |
| 98 | { |
| 99 | return $this->psrResponse->getHeader($name); |
| 100 | } |
| 101 | |
| 102 | public function hasHeader(string $name): bool |
| 103 | { |
| 104 | return $this->psrResponse->hasHeader($name); |
| 105 | } |
| 106 | |
| 107 | public function body(mixed $body): static |
| 108 | { |
| 109 | if ($body instanceof PsrStream) { |
| 110 | return $this->setStreamBody($body); |
| 111 | } |
| 112 | |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 114 | return $this->setStringBody((string) $body); |
| 115 | } |
| 116 | |
| 117 | if (is_resource($body)) { |
| 118 | return $this->setResourceBody($body); |
| 119 | } |
| 120 | |
| 121 | throw new RuntimeException( |
| 122 | 'Only strings, Stringable or resources are allowed to create streams!', |
| 123 | ); |
| 124 | } |
| 125 | |
| 126 | protected function setStringBody(string $body): static |
| 127 | { |
| 128 | if ($this->streamFactory) { |
| 129 | $this->psrResponse = $this->psrResponse->withBody($this->streamFactory->createStream($body)); |
| 130 | |
| 131 | return $this; |
| 132 | } |
| 133 | |
| 134 | $stream = $this->psrResponse->getBody(); |
| 135 | |
| 136 | if ($stream->isWritable()) { |
| 137 | $stream->rewind(); |
| 138 | $stream->write($body); |
| 139 | |
| 140 | return $this; |
| 141 | } |
| 142 | |
| 143 | throw new RuntimeException('The response body is not writable!'); |
| 144 | } |
| 145 | |
| 146 | protected function setStreamBody(PsrStream $body): static |
| 147 | { |
| 148 | $this->psrResponse = $this->psrResponse->withBody($body); |
| 149 | |
| 150 | return $this; |
| 151 | } |
| 152 | |
| 153 | /** |
| 154 | * @param resource $body |
| 155 | */ |
| 156 | protected function setResourceBody(mixed $body): static |
| 157 | { |
| 158 | if ($this->streamFactory) { |
| 159 | $this->psrResponse = $this->psrResponse->withBody($this->streamFactory->createStreamFromResource( |
| 160 | $body, |
| 161 | )); |
| 162 | |
| 163 | return $this; |
| 164 | } |
| 165 | |
| 166 | throw new RuntimeException('No factory available to create stream from resource!'); |
| 167 | } |
| 168 | |
| 169 | public function getBody(): PsrStream |
| 170 | { |
| 171 | return $this->psrResponse->getBody(); |
| 172 | } |
| 173 | |
| 174 | public function write(string $content): static |
| 175 | { |
| 176 | $this->psrResponse->getBody()->write($content); |
| 177 | |
| 178 | return $this; |
| 179 | } |
| 180 | |
| 181 | public function redirect(string $url, int $code = 302): static |
| 182 | { |
| 183 | $this->header('Location', $url); |
| 184 | $this->status($code); |
| 185 | |
| 186 | return $this; |
| 187 | } |
| 188 | |
| 189 | public function withContentType( |
| 190 | string $contentType, |
| 191 | mixed $body = null, |
| 192 | int $code = 200, |
| 193 | string $reasonPhrase = '', |
| 194 | ): static { |
| 195 | $this->psrResponse = $this->psrResponse |
| 196 | ->withStatus($code, $reasonPhrase) |
| 197 | ->withAddedHeader('Content-Type', $contentType); |
| 198 | |
| 199 | if ($body !== null) { |
| 200 | $this->body($body); |
| 201 | } |
| 202 | |
| 203 | return $this; |
| 204 | } |
| 205 | |
| 206 | /** |
| 207 | * @param null|PsrStream|resource|string $body |
| 208 | */ |
| 209 | public function html(mixed $body = null, int $code = 200, string $reasonPhrase = ''): static |
| 210 | { |
| 211 | return $this->withContentType('text/html', $body, $code, $reasonPhrase); |
| 212 | } |
| 213 | |
| 214 | /** |
| 215 | * @param null|PsrStream|resource|string $body |
| 216 | */ |
| 217 | public function text(mixed $body = null, int $code = 200, string $reasonPhrase = ''): static |
| 218 | { |
| 219 | return $this->withContentType('text/plain', $body, $code, $reasonPhrase); |
| 220 | } |
| 221 | |
| 222 | public function json( |
| 223 | mixed $data, |
| 224 | int $code = 200, |
| 225 | string $reasonPhrase = '', |
| 226 | int $flags = JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR, |
| 227 | ): static { |
| 228 | if ($data instanceof Traversable) { |
| 229 | $body = json_encode(iterator_to_array($data), $flags); |
| 230 | } else { |
| 231 | $body = json_encode($data, $flags); |
| 232 | } |
| 233 | |
| 234 | return $this->withContentType('application/json', $body, $code, $reasonPhrase); |
| 235 | } |
| 236 | |
| 237 | public function file( |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 246 | 'js' => 'text/javascript', |
| 247 | 'css' => 'text/css', |
| 248 | 'json' => 'application/json', |
| 249 | 'html' => 'text/html', |
| 250 | 'md' => 'text/markdown', |
| 251 | 'markdown' => 'text/markdown', |
| 252 | 'csv' => 'text/csv', |
| 253 | 'xml' => 'application/xml', |
| 254 | 'xhtml' => 'application/xhtml+xml', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 276 | } |
| 277 | |
| 278 | public function download( |
| 279 | string $file, |
| 280 | string $newName = '', |
| 281 | int $code = 200, |
| 282 | string $reasonPhrase = '', |
| 283 | ): static { |
| 284 | $response = $this->file($file, $code, $reasonPhrase); |
| 285 | $response->header( |
| 286 | 'Content-Disposition', |
| 287 | 'attachment; filename="' . ($newName ?: basename($file)) . '"', |
| 288 | ); |
| 289 | |
| 290 | return $response; |
| 291 | } |
| 292 | |
| 293 | public function sendfile( |
| 294 | string $file, |
| 295 | int $code = 200, |
| 296 | string $reasonPhrase = '', |
| 297 | ): static { |
| 298 | $this->validateFile($file); |
| 299 | $server = strtolower($_SERVER['SERVER_SOFTWARE'] ?? ''); |
| 300 | $this->psrResponse = $this->psrResponse->withStatus($code, $reasonPhrase); |
| 301 | |
| 302 | if (str_contains($server, 'nginx')) { |
| 303 | $this->psrResponse = $this->psrResponse->withAddedHeader('X-Accel-Redirect', $file); |
| 304 | } else { |
| 305 | $this->psrResponse = $this->psrResponse->withAddedHeader('X-Sendfile', $file); |
| 306 | } |
| 307 | |
| 308 | return $this; |
| 309 | } |
| 310 | |
| 311 | protected function validateFile(string $file): void |
| 312 | { |
| 313 | if (!is_file($file)) { |
| 314 | throw new FileNotFoundException('File not found: ' . $file); |
| 315 | } |
| 316 | } |
| 317 | } |
Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not
necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once.
Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement
always has an else as part of its logical flow even if you didn't write one.
| 23 | protected PsrResponse $psrResponse, |
| 24 | protected readonly ?PsrStreamFactory $streamFactory = null, |
| 25 | ) {} |
| 107 | public function body(mixed $body): static |
| 108 | { |
| 109 | if ($body instanceof PsrStream) { |
| 110 | return $this->setStreamBody($body); |
| 107 | public function body(mixed $body): static |
| 108 | { |
| 109 | if ($body instanceof PsrStream) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 114 | return $this->setStringBody((string) $body); |
| 107 | public function body(mixed $body): static |
| 108 | { |
| 109 | if ($body instanceof PsrStream) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 117 | if (is_resource($body)) { |
| 118 | return $this->setResourceBody($body); |
| 107 | public function body(mixed $body): static |
| 108 | { |
| 109 | if ($body instanceof PsrStream) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 117 | if (is_resource($body)) { |
| 121 | throw new RuntimeException( |
| 122 | 'Only strings, Stringable or resources are allowed to create streams!', |
| 123 | ); |
| 124 | } |
| 107 | public function body(mixed $body): static |
| 108 | { |
| 109 | if ($body instanceof PsrStream) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 114 | return $this->setStringBody((string) $body); |
| 107 | public function body(mixed $body): static |
| 108 | { |
| 109 | if ($body instanceof PsrStream) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 117 | if (is_resource($body)) { |
| 118 | return $this->setResourceBody($body); |
| 107 | public function body(mixed $body): static |
| 108 | { |
| 109 | if ($body instanceof PsrStream) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 113 | if (is_string($body) || $body instanceof Stringable) { |
| 117 | if (is_resource($body)) { |
| 121 | throw new RuntimeException( |
| 122 | 'Only strings, Stringable or resources are allowed to create streams!', |
| 123 | ); |
| 124 | } |
| 27 | public static function create(Factory $factory): self |
| 28 | { |
| 29 | return new self($factory->response(), $factory->streamFactory()); |
| 30 | } |
| 279 | string $file, |
| 280 | string $newName = '', |
| 281 | int $code = 200, |
| 282 | string $reasonPhrase = '', |
| 283 | ): static { |
| 284 | $response = $this->file($file, $code, $reasonPhrase); |
| 285 | $response->header( |
| 286 | 'Content-Disposition', |
| 287 | 'attachment; filename="' . ($newName ?: basename($file)) . '"', |
| 288 | ); |
| 289 | |
| 290 | return $response; |
| 291 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 246 | 'js' => 'text/javascript', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 246 | 'js' => 'text/javascript', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 247 | 'css' => 'text/css', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 247 | 'css' => 'text/css', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 248 | 'json' => 'application/json', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 248 | 'json' => 'application/json', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 249 | 'html' => 'text/html', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 249 | 'html' => 'text/html', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 250 | 'md' => 'text/markdown', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 250 | 'md' => 'text/markdown', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 251 | 'markdown' => 'text/markdown', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 251 | 'markdown' => 'text/markdown', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 252 | 'csv' => 'text/csv', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 252 | 'csv' => 'text/csv', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 253 | 'xml' => 'application/xml', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 253 | 'xml' => 'application/xml', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 254 | 'xhtml' => 'application/xhtml+xml', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 254 | 'xhtml' => 'application/xhtml+xml', |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 255 | default => $finfo->file($file), |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 272 | $this->psrResponse = $this->psrResponse->withAddedHeader('Content-Length', (string) $size); |
| 273 | } |
| 274 | |
| 275 | return $this; |
| 275 | return $this; |
| 276 | } |
| 238 | string $file, |
| 239 | int $code = 200, |
| 240 | string $reasonPhrase = '', |
| 241 | ): static { |
| 242 | $this->validateFile($file); |
| 243 | |
| 244 | $finfo = new finfo(FILEINFO_MIME_TYPE); |
| 245 | $contentType = match (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { |
| 255 | default => $finfo->file($file), |
| 255 | default => $finfo->file($file), |
| 256 | }; |
| 257 | |
| 258 | $finfo = new finfo(FILEINFO_MIME_ENCODING); |
| 259 | $encoding = $finfo->file($file); |
| 260 | assert(isset($this->streamFactory), 'Stream factory must be set before creating a file stream'); |
| 261 | $stream = $this->streamFactory->createStreamFromFile($file, 'rb'); |
| 262 | |
| 263 | $this->psrResponse = $this->psrResponse |
| 264 | ->withStatus($code, $reasonPhrase) |
| 265 | ->withAddedHeader('Content-Type', $contentType) |
| 266 | ->withAddedHeader('Content-Transfer-Encoding', $encoding) |
| 267 | ->withBody($stream); |
| 268 | |
| 269 | $size = $stream->getSize(); |
| 270 | |
| 271 | if (!($size === null)) { |
| 275 | return $this; |
| 276 | } |
| 171 | return $this->psrResponse->getBody(); |
| 172 | } |
| 97 | public function getHeader(string $name): array |
| 98 | { |
| 99 | return $this->psrResponse->getHeader($name); |
| 100 | } |
| 68 | return $this->psrResponse->getProtocolVersion(); |
| 69 | } |
| 63 | return $this->psrResponse->getReasonPhrase(); |
| 64 | } |
| 58 | return $this->psrResponse->getStatusCode(); |
| 59 | } |
| 102 | public function hasHeader(string $name): bool |
| 103 | { |
| 104 | return $this->psrResponse->hasHeader($name); |
| 105 | } |
| 78 | public function header(string $name, string $value): static |
| 79 | { |
| 80 | $this->psrResponse = $this->psrResponse->withAddedHeader($name, $value); |
| 81 | |
| 82 | return $this; |
| 83 | } |
| 94 | return $this->psrResponse->getHeaders(); |
| 95 | } |
| 209 | public function html(mixed $body = null, int $code = 200, string $reasonPhrase = ''): static |
| 210 | { |
| 211 | return $this->withContentType('text/html', $body, $code, $reasonPhrase); |
| 212 | } |
| 223 | mixed $data, |
| 224 | int $code = 200, |
| 225 | string $reasonPhrase = '', |
| 226 | int $flags = JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR, |
| 227 | ): static { |
| 228 | if ($data instanceof Traversable) { |
| 228 | if ($data instanceof Traversable) { |
| 229 | $body = json_encode(iterator_to_array($data), $flags); |
| 234 | return $this->withContentType('application/json', $body, $code, $reasonPhrase); |
| 235 | } |
| 223 | mixed $data, |
| 224 | int $code = 200, |
| 225 | string $reasonPhrase = '', |
| 226 | int $flags = JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR, |
| 227 | ): static { |
| 228 | if ($data instanceof Traversable) { |
| 231 | $body = json_encode($data, $flags); |
| 232 | } |
| 233 | |
| 234 | return $this->withContentType('application/json', $body, $code, $reasonPhrase); |
| 234 | return $this->withContentType('application/json', $body, $code, $reasonPhrase); |
| 235 | } |
| 71 | public function protocolVersion(string $protocol): static |
| 72 | { |
| 73 | $this->psrResponse = $this->psrResponse->withProtocolVersion($protocol); |
| 74 | |
| 75 | return $this; |
| 76 | } |
| 181 | public function redirect(string $url, int $code = 302): static |
| 182 | { |
| 183 | $this->header('Location', $url); |
| 184 | $this->status($code); |
| 185 | |
| 186 | return $this; |
| 187 | } |
| 85 | public function removeHeader(string $name): static |
| 86 | { |
| 87 | $this->psrResponse = $this->psrResponse->withoutHeader($name); |
| 88 | |
| 89 | return $this; |
| 90 | } |
| 294 | string $file, |
| 295 | int $code = 200, |
| 296 | string $reasonPhrase = '', |
| 297 | ): static { |
| 298 | $this->validateFile($file); |
| 299 | $server = strtolower($_SERVER['SERVER_SOFTWARE'] ?? ''); |
| 300 | $this->psrResponse = $this->psrResponse->withStatus($code, $reasonPhrase); |
| 301 | |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 303 | $this->psrResponse = $this->psrResponse->withAddedHeader('X-Accel-Redirect', $file); |
| 308 | return $this; |
| 309 | } |
| 294 | string $file, |
| 295 | int $code = 200, |
| 296 | string $reasonPhrase = '', |
| 297 | ): static { |
| 298 | $this->validateFile($file); |
| 299 | $server = strtolower($_SERVER['SERVER_SOFTWARE'] ?? ''); |
| 300 | $this->psrResponse = $this->psrResponse->withStatus($code, $reasonPhrase); |
| 301 | |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 305 | $this->psrResponse = $this->psrResponse->withAddedHeader('X-Sendfile', $file); |
| 306 | } |
| 307 | |
| 308 | return $this; |
| 308 | return $this; |
| 309 | } |
| 294 | string $file, |
| 295 | int $code = 200, |
| 296 | string $reasonPhrase = '', |
| 297 | ): static { |
| 298 | $this->validateFile($file); |
| 299 | $server = strtolower($_SERVER['SERVER_SOFTWARE'] ?? ''); |
| 300 | $this->psrResponse = $this->psrResponse->withStatus($code, $reasonPhrase); |
| 301 | |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 303 | $this->psrResponse = $this->psrResponse->withAddedHeader('X-Accel-Redirect', $file); |
| 308 | return $this; |
| 309 | } |
| 294 | string $file, |
| 295 | int $code = 200, |
| 296 | string $reasonPhrase = '', |
| 297 | ): static { |
| 298 | $this->validateFile($file); |
| 299 | $server = strtolower($_SERVER['SERVER_SOFTWARE'] ?? ''); |
| 300 | $this->psrResponse = $this->psrResponse->withStatus($code, $reasonPhrase); |
| 301 | |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 302 | if (str_contains($server, 'nginx')) { |
| 305 | $this->psrResponse = $this->psrResponse->withAddedHeader('X-Sendfile', $file); |
| 306 | } |
| 307 | |
| 308 | return $this; |
| 308 | return $this; |
| 309 | } |
| 156 | protected function setResourceBody(mixed $body): static |
| 157 | { |
| 158 | if ($this->streamFactory) { |
| 159 | $this->psrResponse = $this->psrResponse->withBody($this->streamFactory->createStreamFromResource( |
| 160 | $body, |
| 161 | )); |
| 162 | |
| 163 | return $this; |
| 156 | protected function setResourceBody(mixed $body): static |
| 157 | { |
| 158 | if ($this->streamFactory) { |
| 166 | throw new RuntimeException('No factory available to create stream from resource!'); |
| 167 | } |
| 146 | protected function setStreamBody(PsrStream $body): static |
| 147 | { |
| 148 | $this->psrResponse = $this->psrResponse->withBody($body); |
| 149 | |
| 150 | return $this; |
| 151 | } |
| 126 | protected function setStringBody(string $body): static |
| 127 | { |
| 128 | if ($this->streamFactory) { |
| 129 | $this->psrResponse = $this->psrResponse->withBody($this->streamFactory->createStream($body)); |
| 130 | |
| 131 | return $this; |
| 126 | protected function setStringBody(string $body): static |
| 127 | { |
| 128 | if ($this->streamFactory) { |
| 134 | $stream = $this->psrResponse->getBody(); |
| 135 | |
| 136 | if ($stream->isWritable()) { |
| 137 | $stream->rewind(); |
| 138 | $stream->write($body); |
| 139 | |
| 140 | return $this; |
| 126 | protected function setStringBody(string $body): static |
| 127 | { |
| 128 | if ($this->streamFactory) { |
| 134 | $stream = $this->psrResponse->getBody(); |
| 135 | |
| 136 | if ($stream->isWritable()) { |
| 143 | throw new RuntimeException('The response body is not writable!'); |
| 144 | } |
| 45 | public function status(int $statusCode, string $reasonPhrase = ''): static |
| 46 | { |
| 47 | if ($reasonPhrase === '') { |
| 47 | if ($reasonPhrase === '') { |
| 48 | $this->psrResponse = $this->psrResponse->withStatus($statusCode); |
| 53 | return $this; |
| 54 | } |
| 45 | public function status(int $statusCode, string $reasonPhrase = ''): static |
| 46 | { |
| 47 | if ($reasonPhrase === '') { |
| 50 | $this->psrResponse = $this->psrResponse->withStatus($statusCode, $reasonPhrase); |
| 51 | } |
| 52 | |
| 53 | return $this; |
| 53 | return $this; |
| 54 | } |
| 217 | public function text(mixed $body = null, int $code = 200, string $reasonPhrase = ''): static |
| 218 | { |
| 219 | return $this->withContentType('text/plain', $body, $code, $reasonPhrase); |
| 220 | } |
| 35 | return $this->psrResponse; |
| 36 | } |
| 311 | protected function validateFile(string $file): void |
| 312 | { |
| 313 | if (!is_file($file)) { |
| 314 | throw new FileNotFoundException('File not found: ' . $file); |
| 311 | protected function validateFile(string $file): void |
| 312 | { |
| 313 | if (!is_file($file)) { |
| 316 | } |
| 190 | string $contentType, |
| 191 | mixed $body = null, |
| 192 | int $code = 200, |
| 193 | string $reasonPhrase = '', |
| 194 | ): static { |
| 195 | $this->psrResponse = $this->psrResponse |
| 196 | ->withStatus($code, $reasonPhrase) |
| 197 | ->withAddedHeader('Content-Type', $contentType); |
| 198 | |
| 199 | if ($body !== null) { |
| 200 | $this->body($body); |
| 201 | } |
| 202 | |
| 203 | return $this; |
| 203 | return $this; |
| 204 | } |
| 190 | string $contentType, |
| 191 | mixed $body = null, |
| 192 | int $code = 200, |
| 193 | string $reasonPhrase = '', |
| 194 | ): static { |
| 195 | $this->psrResponse = $this->psrResponse |
| 196 | ->withStatus($code, $reasonPhrase) |
| 197 | ->withAddedHeader('Content-Type', $contentType); |
| 198 | |
| 199 | if ($body !== null) { |
| 203 | return $this; |
| 204 | } |
| 38 | public function wrap(PsrResponse $response): static |
| 39 | { |
| 40 | $this->psrResponse = $response; |
| 41 | |
| 42 | return $this; |
| 43 | } |
| 174 | public function write(string $content): static |
| 175 | { |
| 176 | $this->psrResponse->getBody()->write($content); |
| 177 | |
| 178 | return $this; |
| 179 | } |