JsonResponse::withJsonData()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace HttpSoft\Response;
6
7
use InvalidArgumentException;
8
use JsonException;
9
use Psr\Http\Message\ResponseInterface;
10
11
use function is_resource;
12
use function json_encode;
13
use function json_last_error;
14
use function json_last_error_msg;
15
use function sprintf;
16
17
use const JSON_ERROR_NONE;
18
use const JSON_HEX_AMP;
19
use const JSON_HEX_APOS;
20
use const JSON_HEX_QUOT;
21
use const JSON_HEX_TAG;
22
use const JSON_UNESCAPED_SLASHES;
23
use const JSON_UNESCAPED_UNICODE;
24
25
final class JsonResponse implements ResponseInterface, ResponseStatusCodeInterface
26
{
27
    use ResponseExtensionTrait;
28
29
    /**
30
     * Default options for `json_encode()`.
31
     */
32
    public const DEFAULT_OPTIONS = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
33
34
    /**
35
     * Options for the HTML encoding to `json_encode()`.
36
     */
37
    public const HTML_OPTIONS = JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG | JSON_UNESCAPED_UNICODE;
38
39
    /**
40
     * @param mixed $data
41
     * @param int $code
42
     * @param array $headers
43
     * @param string $protocol
44
     * @param string $reasonPhrase
45
     * @param int $encodingOptions
46
     * @throws InvalidArgumentException If it is impossible to encode the data in JSON.
47
     */
48 49
    public function __construct(
49
        $data,
50
        int $code = self::STATUS_OK,
51
        array $headers = [],
52
        string $protocol = '1.1',
53
        string $reasonPhrase = '',
54
        int $encodingOptions = self::DEFAULT_OPTIONS
55
    ) {
56 49
        $json = $this->encode($data, $encodingOptions);
57 49
        $this->init($code, $reasonPhrase, $headers, $this->createBody($json), $protocol);
58 49
        $this->setContentTypeHeaderIfNotExists('application/json; charset=UTF-8');
59
    }
60
61
    /**
62
     * @param mixed $data
63
     * @param int $encodingOptions
64
     * @return self
65
     */
66 7
    public function withJsonData($data, int $encodingOptions = self::DEFAULT_OPTIONS): self
67
    {
68 7
        return $this->withBody($this->createBody($this->encode($data, $encodingOptions)));
69
    }
70
71
    /**
72
     * @param mixed $data
73
     * @param int $options
74
     * @return string
75
     * @throws InvalidArgumentException If it is impossible to encode the data in JSON.
76
     */
77 49
    private function encode($data, int $options): string
78
    {
79 49
        if (is_resource($data)) {
80 4
            throw new InvalidArgumentException('Resources cannot be encoded in JSON.');
81
        }
82
83
        try {
84
            /** @psalm-suppress UnusedFunctionCall */
85 49
            json_encode(null);
86 49
            $json = json_encode($data, $options);
87
88 49
            if (JSON_ERROR_NONE !== json_last_error()) {
89 2
                throw new JsonException(json_last_error_msg());
90
            }
91
92 49
            return $json;
93 4
        } catch (JsonException $e) {
94 4
            throw new InvalidArgumentException(sprintf('Unable to encode data to JSON: `%s`', $e->getMessage()));
95
        }
96
    }
97
}
98