[CLEANUP] The correct case must be used for standard PHP types in phpdoc
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Http / AjaxRequestHandler.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 use Psr\Http\Message\ResponseInterface;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Class to hold all the information about an AJAX call and send
22 * the right headers for the request type
23 * @deprecated since TYPO3 v8, will be removed in TYPO3 v9
24 */
25 class AjaxRequestHandler
26 {
27 /**
28 * @var string|null
29 */
30 protected $ajaxId = null;
31
32 /**
33 * @var string|null
34 */
35 protected $errorMessage = null;
36
37 /**
38 * @var bool
39 */
40 protected $isError = false;
41
42 /**
43 * @var array
44 */
45 protected $content = [];
46
47 /**
48 * @var string
49 */
50 protected $contentFormat = 'plain';
51
52 /**
53 * @var string
54 */
55 protected $javascriptCallbackWrap = '
56 <script type="text/javascript">
57 /*<![CDATA[*/
58 response = |;
59 /*]]>*/
60 </script>
61 ';
62
63 /**
64 * Sets the ID for the AJAX call
65 *
66 * @param string $ajaxId The AJAX id
67 */
68 public function __construct($ajaxId)
69 {
70 $this->ajaxId = $ajaxId;
71 }
72
73 /**
74 * Returns the ID for the AJAX call
75 *
76 * @return string The AJAX id
77 */
78 public function getAjaxID()
79 {
80 return $this->ajaxId;
81 }
82
83 /**
84 * Overwrites the existing content with the data supplied
85 *
86 * @param array $content The new content
87 * @return mixed The old content as array; if the new content was not an array, FALSE is returned
88 */
89 public function setContent($content)
90 {
91 $oldcontent = false;
92 if (is_array($content)) {
93 $oldcontent = $this->content;
94 $this->content = $content;
95 }
96 return $oldcontent;
97 }
98
99 /**
100 * Adds new content
101 *
102 * @param string $key The new content key where the content should be added in the content array
103 * @param string $content The new content to add
104 * @return mixed The old content; if the old content didn't exist before, FALSE is returned
105 */
106 public function addContent($key, $content)
107 {
108 $oldcontent = false;
109 if (array_key_exists($key, $this->content)) {
110 $oldcontent = $this->content[$key];
111 }
112 if (!isset($content) || empty($content)) {
113 unset($this->content[$key]);
114 } elseif (!isset($key) || empty($key)) {
115 $this->content[] = $content;
116 } else {
117 $this->content[$key] = $content;
118 }
119 return $oldcontent;
120 }
121
122 /**
123 * Returns the content for the ajax call
124 *
125 * @return mixed The content for a specific key or the whole content
126 */
127 public function getContent($key = '')
128 {
129 return $key && array_key_exists($key, $this->content) ? $this->content[$key] : $this->content;
130 }
131
132 /**
133 * Sets the content format for the ajax call
134 *
135 * @param string $format Can be one of 'plain' (default), 'xml', 'json', 'javascript', 'jsonbody' or 'jsonhead'
136 */
137 public function setContentFormat($format)
138 {
139 if (in_array($format, ['plain', 'xml', 'json', 'jsonhead', 'jsonbody', 'javascript'], true)) {
140 $this->contentFormat = $format;
141 }
142 }
143
144 /**
145 * Specifies the wrap to be used if contentFormat is "javascript".
146 * The wrap used by default stores the results in a variable "response" and
147 * adds <script>-Tags around it.
148 *
149 * @param string $javascriptCallbackWrap The javascript callback wrap to be used
150 */
151 public function setJavascriptCallbackWrap($javascriptCallbackWrap)
152 {
153 $this->javascriptCallbackWrap = $javascriptCallbackWrap;
154 }
155
156 /**
157 * Sets an error message and the error flag
158 *
159 * @param string $errorMsg The error message
160 */
161 public function setError($errorMsg = '')
162 {
163 $this->errorMessage = $errorMsg;
164 $this->isError = true;
165 }
166
167 /**
168 * Checks whether an error occurred during the execution or not
169 *
170 * @return bool Whether this AJAX call had errors
171 */
172 public function isError()
173 {
174 return $this->isError;
175 }
176
177 /**
178 * Renders the AJAX call based on the $contentFormat variable and exits the request
179 *
180 * @return ResponseInterface|null
181 */
182 public function render()
183 {
184 if ($this->isError) {
185 return $this->renderAsError();
186 }
187 switch ($this->contentFormat) {
188 case 'jsonhead':
189 case 'jsonbody':
190 case 'json':
191 return $this->renderAsJSON();
192 break;
193 case 'javascript':
194 return $this->renderAsJavascript();
195 break;
196 case 'xml':
197 return $this->renderAsXML();
198 break;
199 default:
200 return $this->renderAsPlain();
201 }
202 }
203
204 /**
205 * Renders the AJAX call in XML error style to handle with JS
206 * the "responseXML" of the transport object will be filled with the error message then
207 *
208 * @return ResponseInterface
209 */
210 protected function renderAsError()
211 {
212 /** @var Response $response */
213 $response = GeneralUtility::makeInstance(Response::class);
214 $response = $response
215 ->withStatus(500, ' (AJAX)')
216 ->withHeader('Content-Type', 'text/xml; charset=utf-8')
217 ->withHeader('X-JSON', 'false');
218
219 $response->getBody()->write('<t3err>' . htmlspecialchars($this->errorMessage) . '</t3err>');
220 return $response;
221 }
222
223 /**
224 * Renders the AJAX call with text/html headers
225 * the content will be available in the "responseText" value of the transport object
226 *
227 * @return ResponseInterface
228 * @throws \InvalidArgumentException
229 */
230 protected function renderAsPlain()
231 {
232 /** @var Response $response */
233 $response = GeneralUtility::makeInstance(Response::class);
234 $response = $response
235 ->withHeader('Content-Type', 'text/html; charset=utf-8')
236 ->withHeader('X-JSON', 'true');
237
238 $response->getBody()->write(implode('', $this->content));
239 return $response;
240 }
241
242 /**
243 * Renders the AJAX call with text/xml headers
244 * the content will be available in the "responseXML" value of the transport object
245 *
246 * @return ResponseInterface
247 * @throws \InvalidArgumentException
248 */
249 protected function renderAsXML()
250 {
251 /** @var Response $response */
252 $response = GeneralUtility::makeInstance(Response::class);
253 $response = $response
254 ->withHeader('Content-Type', 'text/xml; charset=utf-8')
255 ->withHeader('X-JSON', 'true');
256
257 $response->getBody()->write(implode('', $this->content));
258 return $response;
259 }
260
261 /**
262 * Renders the AJAX call with JSON evaluated headers
263 * note that you need to have requestHeaders: {Accept: 'application/json'},
264 * in your AJAX options of your AJAX request object in JS
265 *
266 * the content will be available
267 * - in the second parameter of the onSuccess / onComplete callback
268 * - and in the xhr.responseText as a string (except when contentFormat = 'jsonhead')
269 * you can evaluate this in JS with xhr.responseText.evalJSON();
270 *
271 * @return ResponseInterface
272 * @throws \InvalidArgumentException
273 */
274 protected function renderAsJSON()
275 {
276 /** @var Response $response */
277 $response = GeneralUtility::makeInstance(Response::class);
278 $response = $response->withHeader('Content-Type', 'application/json; charset=utf-8');
279
280 $content = json_encode($this->content);
281 // Bring content in xhr.responseText except when in "json head only" mode
282 if ($this->contentFormat === 'jsonhead') {
283 $response = $response->withHeader('X-JSON', $content);
284 } else {
285 $response = $response->withHeader('X-JSON', 'true');
286 $response->getBody()->write($content);
287 }
288 return $response;
289 }
290
291 /**
292 * Renders the AJAX call as inline JSON inside a script tag. This is useful
293 * when an iframe is used as the AJAX transport.
294 *
295 * @return ResponseInterface
296 * @throws \InvalidArgumentException
297 */
298 protected function renderAsJavascript()
299 {
300 $response = GeneralUtility::makeInstance(Response::class);
301 $response = $response->withHeader('Content-Type', 'text/html; charset=utf-8');
302 $response->getBody()->write(str_replace('|', json_encode($this->content), $this->javascriptCallbackWrap));
303 return $response;
304 }
305 }