PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.41
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.41
2.1.0 2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 1.41 All 42 releases
fluent-boards / vendor / wpfluent / framework / src / WPFluent / Http / Response / Response.php

Response.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.41, at vendor/wpfluent/framework/src/WPFluent/Http/Response/Response.php

376 lines 8.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBoards\Framework\Http\Response;
4
5 use DateTime;
6 use WP_Error;
7 use DateTimeInterface;
8 use WP_REST_Response;
9 use FluentBoards\Framework\App\App;
10 use InvalidArgumentException;
11 use FluentBoards\Framework\Http\Request\File;
12
13 class Response
14 {
15 /**
16 * Response Data
17 * @var mixed
18 */
19 protected $data = null;
20
21 /**
22 * Response Status Code
23 * @var integer
24 */
25 protected $code = 200;
26
27 /**
28 * Response Headers
29 * @var array
30 */
31 protected $headers = [];
32
33 /**
34 * Response Cookies
35 * @var array
36 */
37 protected $cookies = [];
38
39 /**
40 * Construct the response instance.
41 *
42 * @param array $data
43 * @param integer $code
44 * @param array $headers
45 */
46 public function __construct($data = null, $code = 200, $headers = [])
47 {
48 $this->data = $data;
49 $this->code = $code;
50 $this->headers = $headers;
51 }
52
53 /**
54 * Creates an instance of self.
55 *
56 * @param mixed $data
57 * @param integer $code
58 * @param array $headers
59 * @return self
60 */
61 public static function make($data = null, $code = 200, $headers = [])
62 {
63 return new static($data, $code, $headers);
64 }
65
66 /**
67 * Send json response.
68 *
69 * @param array $data
70 * @param integer $code
71 * @return string|false JSON encoded string, or false if fails to encode.
72 */
73 public function json($data = null, $code = 200)
74 {
75 return wp_send_json($data, $code);
76 }
77
78 /**
79 * Send rest response.
80 *
81 * @param mixed $data
82 * @param integer $code
83 * @param array $headers
84 * @return \WP_REST_Response
85 */
86 public function send($data = null, $code = 200, $headers = [])
87 {
88 $response = new WP_REST_Response($data, $code, $headers);
89
90 return $this->maybeMergeHeaders(
91 $this->MaybeMergeCookies($response)
92 );
93 }
94
95 /**
96 * Send a success rest response.
97 *
98 * @param mixed $data
99 * @param integer $code
100 * @return \WP_REST_Response
101 */
102 public function sendSuccess($data = null, $code = 200, $headers = [])
103 {
104 return $this->send($data, $code, $headers);
105 }
106
107 /**
108 * Send an error json response
109 * @param array $data
110 * @param integer $code
111 * @return \WP_REST_Response
112 */
113 public function sendError($data = null, $code = 422, $headers = [])
114 {
115 if (!$code || $code < 400 ) {
116 $code = 422;
117 }
118
119 return $this->send($data, $code, $headers);
120 }
121
122 /**
123 * Convert the WP_Error to WP_REST_Response
124 *
125 * @param \WP_Error $wpError
126 * @return \WP_REST_Response
127 */
128 public function wpErrorToResponse(WP_Error $wpError)
129 {
130 return rest_convert_error_to_response($wpError);
131 }
132
133 /**
134 * Set response headers
135 * @param string|array $key
136 * @param string|null $value
137 * @return self
138 */
139 public function withHeader($key, $value = null)
140 {
141 if (is_array($key) && !$value) {
142 $this->headers = $key;
143 } else {
144 $this->headers = [$key => $value];
145 }
146
147 return $this;
148 }
149
150 /**
151 * Set response cookie
152 *
153 * @param string $name
154 * @param mixed $value
155 * @param int $minutes
156 * @param string $path
157 * @param string|null $domain
158 * @param bool $secure
159 * @param bool $httpOnly
160 * @return self
161 */
162 public function withCookie(
163 $name,
164 $value,
165 $minutes,
166 $path = '/',
167 $domain = null,
168 $secure = false,
169 $httpOnly = true
170 )
171 {
172 $cookie = $this->buildCookie(
173 $name, $value, $minutes, $path, $domain, $secure, $httpOnly
174 );
175
176 $this->cookies[] = $cookie;
177
178 return $this;
179 }
180
181 /**
182 * Build cookie header for response
183 *
184 * @param string $name
185 * @param mixed $value
186 * @param int $minutes
187 * @param string $path
188 * @param string|null $domain
189 * @param bool $secure
190 * @param bool $httpOnly
191 * @return string
192 */
193 protected function buildCookie(
194 $name,
195 $value,
196 $minutes,
197 $path,
198 $domain,
199 $secure,
200 $httpOnly
201 ) {
202 $expiration = static::expiresAt($minutes);
203
204 $cookieHeader = "{$name}=" . rawurlencode($value);
205
206 $cookieHeader .= "; Expires=" . gmdate('D, d-M-Y H:i:s T', $expiration);
207
208 $cookieHeader .= "; Path=" . $path;
209
210 if ($domain) {
211 $cookieHeader .= "; Domain=" . $domain;
212 }
213
214 if ($secure) {
215 $cookieHeader .= "; Secure";
216 }
217
218 if ($httpOnly) {
219 $cookieHeader .= "; HttpOnly";
220 }
221
222 return $cookieHeader;
223 }
224
225 /**
226 * Merge additional headers if exist.
227 *
228 * @param \WP_REST_Response $response
229 */
230 protected function maybeMergeHeaders(WP_REST_Response $response)
231 {
232 if ($this->headers) {
233 foreach ($this->headers as $key => $value) {
234 $response->header($key, $value);
235 }
236 }
237
238 $this->headers = [];
239
240 return $response;
241 }
242
243 /**
244 * Merge cookies if exist.
245 *
246 * @param \WP_REST_Response $response
247 */
248 protected function MaybeMergeCookies(WP_REST_Response $response)
249 {
250 if ($this->cookies) {
251 foreach ($this->cookies as $cookie) {
252 $response->header('Set-Cookie', $cookie);
253 }
254 }
255
256 $this->cookies = [];
257
258 return $response;
259 }
260
261 /**
262 * Prepares expiration time in minutes.
263 *
264 * @param int|DateTimeInterface $minutes
265 * @return int
266 */
267 protected static function expiresAt($minutes = 0)
268 {
269 if (is_int($minutes)) {
270 if ($minutes === 0) {
271 return $minutes;
272 }
273
274 $minutes = new DateTime('+' . $minutes . ' minutes');
275 }
276
277 if (!($minutes instanceof DateTimeInterface)) {
278 throw new InvalidArgumentException(
279 'Invalid expiration time provided.'
280 );
281 }
282
283 return $minutes->getTimestamp();
284 }
285
286 /**
287 * Send the response
288 *
289 * @return \WP_REST_Response
290 */
291 public function toArray()
292 {
293 $response = new WP_REST_Response(
294 $this->data, $this->code
295 );
296
297 return $this->MaybeMergeCookies(
298 $this->maybeMergeHeaders($response)
299 );
300 }
301
302 /**
303 * Send a file download response.
304 *
305 * @param string $filePath
306 * @param string|null $fileName
307 * @return void
308 */
309 public static function download($filePath, $fileName = null)
310 {
311 if ($filePath instanceof File) {
312 $array = $filePath->toArray();
313 $filePath = $array['tmp_name'];
314 $fileName ??= $fileName ?? $array['name'];
315 }
316
317 if (!file_exists($filePath) || !is_readable($filePath)) {
318 wp_die('File does not exist or unreadable.', '404 Not Found');
319 }
320
321 $mimeType = mime_content_type($filePath) ?: 'application/octet-stream';
322
323 $fileName = sanitize_file_name($fileName ?? basename($filePath));
324
325 header('Content-Description: File Transfer');
326 header('Content-Type: ' . $mimeType);
327 header('Content-Disposition: attachment; filename="' . $fileName . '"');
328 header('Content-Transfer-Encoding: binary');
329 header('Expires: 0');
330 header('Cache-Control: must-revalidate');
331 header('Pragma: public');
332 header('Content-Length: ' . filesize($filePath));
333
334 if (php_sapi_name() === 'cli') {
335 ob_start();
336 readfile($filePath);
337 $content = ob_get_clean();
338 add_action('shutdown', function() { exit; });
339 return $content;
340 } else {
341 ob_get_level() && ob_end_clean() && flush();
342 readfile($filePath);
343 exit;
344 }
345 }
346
347 /**
348 * Send a redirect response.
349 *
350 * @param string $route
351 * @param integer $status
352 * @return \WP_REST_Response
353 */
354 public static function redirect($route, $status = 303)
355 {
356 [$ns, $ver] = App::config()->only('rest_namespace', 'rest_version');
357
358 $baseUrl = rest_url("{$ns}/{$ver}");
359
360 $parsedUrl = parse_url($route);
361
362 $path = trim($parsedUrl['path'] ?? '', '/');
363
364 parse_str($parsedUrl['query'] ?? '', $queryParams);
365
366 $queryParams['x_redirect_to'] = $path;
367 $queryParams['x_redirected_from'] = App::request()->url();
368
369 $location = "{$baseUrl}/{$path}?" . http_build_query($queryParams);
370
371 return new WP_REST_Response(null, $status, [
372 'Location' => $location
373 ]);
374 }
375 }
376