f240786e1455f0c231d98ccf32b106decbb5e721
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Http / JsonResponse.php
1 <?php
2 namespace TYPO3\CMS\Core\Http;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * Standard values for a JSON response
19 *
20 * Highly inspired by ZF zend-diactoros
21 *
22 * @internal Note that this is not public API yet.
23 */
24 class JsonResponse extends Response
25 {
26 /**
27 * Default flags for json_encode; value of:
28 *
29 * <code>
30 * JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_SLASHES
31 * </code>
32 *
33 * @const int
34 */
35 const DEFAULT_JSON_FLAGS = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_SLASHES;
36
37 /**
38 * Create a JSON response with the given data.
39 *
40 * Default JSON encoding is performed with the following options, which
41 * produces RFC4627-compliant JSON, capable of embedding into HTML.
42 *
43 * - JSON_HEX_TAG
44 * - JSON_HEX_APOS
45 * - JSON_HEX_AMP
46 * - JSON_HEX_QUOT
47 * - JSON_UNESCAPED_SLASHES
48 *
49 * @param mixed $data Data to convert to JSON.
50 * @param int $status Integer status code for the response; 200 by default.
51 * @param array $headers Array of headers to use at initialization.
52 * @param int $encodingOptions JSON encoding options to use.
53 */
54 public function __construct(
55 $data = [],
56 $status = 200,
57 array $headers = [],
58 $encodingOptions = self::DEFAULT_JSON_FLAGS
59 ) {
60 $body = new Stream('php://temp', 'wb+');
61 parent::__construct($body, $status, $headers);
62
63 if (!empty($data)) {
64 $this->setPayload($data, $encodingOptions);
65 }
66
67 // Ensure that application/json header is set, if Content-Type was not set before
68 if (!$this->hasHeader('Content-Type')) {
69 $this->headers['Content-Type'][] = 'application/json; charset=utf-8';
70 $this->lowercasedHeaderNames['content-type'] = 'Content-Type';
71 }
72 }
73
74 /**
75 * Overrides the exiting content, takes an array as input
76 *
77 * @param array $data
78 * @param int $encodingOptions
79 * @return $this
80 */
81 public function setPayload(array $data = [], $encodingOptions = self::DEFAULT_JSON_FLAGS): JsonResponse
82 {
83 $this->body->write($this->jsonEncode($data, $encodingOptions));
84 $this->body->rewind();
85 return $this;
86 }
87
88 /**
89 * Encode the provided data to JSON.
90 *
91 * @param mixed $data
92 * @param int $encodingOptions
93 * @return string
94 * @throws \InvalidArgumentException if unable to encode the $data to JSON.
95 */
96 private function jsonEncode($data, $encodingOptions)
97 {
98 if (is_resource($data)) {
99 throw new \InvalidArgumentException('Cannot JSON encode resources', 1504972433);
100 }
101 // Clear json_last_error()
102 json_encode(null);
103 $json = json_encode($data, $encodingOptions);
104 if (JSON_ERROR_NONE !== json_last_error()) {
105 throw new \InvalidArgumentException(sprintf(
106 'Unable to encode data to JSON in %s: %s',
107 __CLASS__,
108 json_last_error_msg()
109 ), 1504972434);
110 }
111 return $json;
112 }
113 }