Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
ResponseBuilder
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
8 / 8
11
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 withResponse
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 withHeader
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addHeader
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 withStatus
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 withHtml
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 withJson
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 build
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3// ╔════════════════════════════════════════════════════════════╗
4// ║ MIT Licence (#Expat) - https://opensource.org/licenses/MIT ║
5// ║ Copyright 2026 Frederic Poeydomenge <dyno@phexium.com>     ║
6// ╚════════════════════════════════════════════════════════════╝
7
8declare(strict_types=1);
9
10namespace Phexium\Presentation;
11
12use Override;
13use Psr\Http\Message\ResponseInterface;
14
15final class ResponseBuilder implements ResponseBuilderInterface
16{
17    private array $headers = [];
18
19    private int $statusCode = 200;
20
21    private ?string $body = null;
22
23    public function __construct(
24        private ResponseInterface $response,
25    ) {
26        $this->withResponse($response);
27    }
28
29    #[Override]
30    public function withResponse(ResponseInterface $response): self
31    {
32        $this->response = $response;
33        $this->statusCode = $response->getStatusCode();
34
35        return $this;
36    }
37
38    #[Override]
39    public function withHeader(string $name, string $value): self
40    {
41        $this->headers[$name] = [$value];
42
43        return $this;
44    }
45
46    #[Override]
47    public function addHeader(string $name, string $value): self
48    {
49        $this->headers[$name][] = $value;
50
51        return $this;
52    }
53
54    #[Override]
55    public function withStatus(int $code): self
56    {
57        $this->statusCode = $code;
58
59        return $this;
60    }
61
62    #[Override]
63    public function withHtml(string $html, string $charset = 'utf-8'): self
64    {
65        $this->body = $html;
66
67        $this->withHeader('Content-Type', sprintf('text/html; charset=%s', $charset));
68
69        return $this;
70    }
71
72    #[Override]
73    public function withJson(array $data, string $charset = 'utf-8'): self
74    {
75        $this->body = json_encode($data, JSON_PRETTY_PRINT);
76
77        $this->withHeader('Content-Type', sprintf('application/json; charset=%s', $charset));
78
79        return $this;
80    }
81
82    #[Override]
83    public function build(): ResponseInterface
84    {
85        $response = $this->response;
86
87        $response = $response->withStatus($this->statusCode);
88
89        foreach ($this->headers as $name => $values) {
90            foreach ($values as $value) {
91                $response = $response->withAddedHeader($name, $value);
92            }
93        }
94
95        if ($this->body !== null) {
96            $response->getBody()->write($this->body);
97        }
98
99        return $response;
100    }
101}