mirror of
https://github.com/avecms/AVE.cms.git
synced 2026-08-01 08:45:44 +00:00
279 lines
8.0 KiB
PHP
279 lines
8.0 KiB
PHP
<?php
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------------------
|
|
| AVE.cms
|
|
|--------------------------------------------------------------------------------------
|
|
| @package AVE.cms
|
|
| @file system/App/Helpers/Response.php
|
|
| @author AVE.cms <support@ave-cms.ru>
|
|
| @copyright 2007-2026 (c) AVE.cms
|
|
| @link https://ave-cms.ru
|
|
| @version 3.3
|
|
*/
|
|
|
|
namespace App\Helpers;
|
|
|
|
defined("BASEPATH") || die('Direct access to this location is not allowed.');
|
|
|
|
class Response
|
|
{
|
|
public const HTTP_STATUSES = [
|
|
100 => 'HTTP/1.1 100 Continue',
|
|
101 => 'HTTP/1.1 101 Switching Protocols',
|
|
200 => 'HTTP/1.1 200 OK',
|
|
201 => 'HTTP/1.1 201 Created',
|
|
202 => 'HTTP/1.1 202 Accepted',
|
|
203 => 'HTTP/1.1 203 Non-Authoritative Information',
|
|
204 => 'HTTP/1.1 204 No Content',
|
|
205 => 'HTTP/1.1 205 Reset Content',
|
|
206 => 'HTTP/1.1 206 Partial Content',
|
|
300 => 'HTTP/1.1 300 Multiple Choices',
|
|
301 => 'HTTP/1.1 301 Moved Permanently',
|
|
302 => 'HTTP/1.1 302 Found',
|
|
303 => 'HTTP/1.1 303 See Other',
|
|
304 => 'HTTP/1.1 304 Not Modified',
|
|
307 => 'HTTP/1.1 307 Temporary Redirect',
|
|
400 => 'HTTP/1.1 400 Bad Request',
|
|
401 => 'HTTP/1.1 401 Unauthorized',
|
|
402 => 'HTTP/1.1 402 Payment Required',
|
|
403 => 'HTTP/1.1 403 Forbidden',
|
|
404 => 'HTTP/1.1 404 Not Found',
|
|
405 => 'HTTP/1.1 405 Method Not Allowed',
|
|
408 => 'HTTP/1.1 408 Request Timeout',
|
|
409 => 'HTTP/1.1 409 Conflict',
|
|
410 => 'HTTP/1.1 410 Gone',
|
|
413 => 'HTTP/1.1 413 Request Entity Too Large',
|
|
415 => 'HTTP/1.1 415 Unsupported Media Type',
|
|
419 => 'HTTP/1.1 419 Authentication Timeout',
|
|
422 => 'HTTP/1.1 422 Unprocessable Entity',
|
|
429 => 'HTTP/1.1 429 Too Many Requests',
|
|
500 => 'HTTP/1.1 500 Internal Server Error',
|
|
501 => 'HTTP/1.1 501 Not Implemented',
|
|
502 => 'HTTP/1.1 502 Bad Gateway',
|
|
503 => 'HTTP/1.1 503 Service Unavailable',
|
|
504 => 'HTTP/1.1 504 Gateway Timeout',
|
|
];
|
|
|
|
protected function __construct()
|
|
{
|
|
//
|
|
}
|
|
|
|
// ------------------------------------------------------------------ //
|
|
// Статус
|
|
// ------------------------------------------------------------------ //
|
|
|
|
public static function setStatus($status)
|
|
{
|
|
$status = (int)$status;
|
|
$text = isset(self::HTTP_STATUSES[$status]) ? self::HTTP_STATUSES[$status] : "HTTP/1.1 {$status}";
|
|
Request::setHeader($text, true, $status);
|
|
}
|
|
|
|
// ------------------------------------------------------------------ //
|
|
// Отправка тела
|
|
// ------------------------------------------------------------------ //
|
|
|
|
/**
|
|
* Отправить JSON-ответ и завершить выполнение.
|
|
*
|
|
* @param mixed $data
|
|
* @param int $status
|
|
* @param int $flags json_encode flags (по умолчанию кириллица без escaping)
|
|
*/
|
|
public static function json($data, $status = 200, $flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
|
{
|
|
echo self::jsonBody($data, $status, $flags);
|
|
Request::shutDown();
|
|
}
|
|
|
|
/** Build a JSON response for router callbacks without terminating the request. */
|
|
public static function jsonBody($data, $status = 200, $flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES, $cacheControl = 'no-store')
|
|
{
|
|
self::setStatus($status);
|
|
Request::setHeader('Content-Type: application/json; charset=UTF-8', true);
|
|
if ($cacheControl !== null && $cacheControl !== '') {
|
|
Request::setHeader('Cache-Control: ' . (string) $cacheControl, true);
|
|
}
|
|
|
|
return Json::encode($data, $flags);
|
|
}
|
|
|
|
/**
|
|
* Отправить успешный JSON-ответ { success: true, data: ... }
|
|
*/
|
|
public static function jsonSuccess($data = null, $message = '')
|
|
{
|
|
$body = ['success' => true];
|
|
if ($message !== '') {
|
|
$body['message'] = $message;
|
|
}
|
|
|
|
if ($data !== null) {
|
|
$body['data'] = $data;
|
|
}
|
|
|
|
self::json($body, 200);
|
|
}
|
|
|
|
/**
|
|
* Отправить JSON-ответ об ошибке { success: false, error: ... }
|
|
*/
|
|
public static function jsonError($message, $status = 400, $data = null)
|
|
{
|
|
$body = ['success' => false, 'error' => $message];
|
|
if ($data !== null) {
|
|
$body['data'] = $data;
|
|
}
|
|
|
|
self::json($body, $status);
|
|
}
|
|
|
|
/**
|
|
* Отправить HTML-ответ.
|
|
*/
|
|
public static function html($html, $status = 200)
|
|
{
|
|
self::setStatus($status);
|
|
Request::setHeader('Content-Type: text/html; charset=UTF-8', true);
|
|
echo $html;
|
|
Request::shutDown();
|
|
}
|
|
|
|
/**
|
|
* Отправить plain text.
|
|
*/
|
|
public static function text($text, $status = 200)
|
|
{
|
|
self::setStatus($status);
|
|
Request::setHeader('Content-Type: text/plain; charset=UTF-8', true);
|
|
echo $text;
|
|
Request::shutDown();
|
|
}
|
|
|
|
/**
|
|
* Отправить XML-ответ (sitemap и т.п.).
|
|
*/
|
|
public static function xml($xml, $status = 200)
|
|
{
|
|
self::setStatus($status);
|
|
Request::setHeader('Content-Type: application/xml; charset=UTF-8', true);
|
|
echo $xml;
|
|
Request::shutDown();
|
|
}
|
|
|
|
/**
|
|
* Отдать файл как скачивание.
|
|
*
|
|
* @param string $filePath Путь к файлу на сервере
|
|
* @param string|null $fileName Имя файла для клиента (null = basename($filePath))
|
|
* @param string $mimeType
|
|
*/
|
|
public static function download($filePath, $fileName = null, $mimeType = 'application/octet-stream')
|
|
{
|
|
if (!file_exists($filePath)) {
|
|
self::notFound('File not found');
|
|
}
|
|
|
|
$fileName = $fileName ?? basename($filePath);
|
|
$fileSize = filesize($filePath);
|
|
|
|
self::setStatus(200);
|
|
Request::setHeader('Content-Type: ' . $mimeType, true);
|
|
Request::setHeader('Content-Disposition: attachment; filename="' . addslashes($fileName) . '"', true);
|
|
Request::setHeader('Content-Length: ' . $fileSize, true);
|
|
Request::setHeader('Cache-Control: must-revalidate', true);
|
|
Request::setHeader('Pragma: public', true);
|
|
|
|
ob_clean();
|
|
flush();
|
|
readfile($filePath);
|
|
Request::shutDown();
|
|
}
|
|
|
|
/**
|
|
* Отдать файл для просмотра в браузере (inline).
|
|
*/
|
|
public static function inline($filePath, $mimeType = null, $fileName = null)
|
|
{
|
|
if (!file_exists($filePath)) {
|
|
self::notFound('File not found');
|
|
}
|
|
|
|
$fileName = $fileName ?? basename($filePath);
|
|
$mimeType = $mimeType ?? mime_content_type($filePath) ?: 'application/octet-stream';
|
|
|
|
self::setStatus(200);
|
|
Request::setHeader('Content-Type: ' . $mimeType, true);
|
|
Request::setHeader('Content-Disposition: inline; filename="' . addslashes($fileName) . '"', true);
|
|
Request::setHeader('Content-Length: ' . filesize($filePath), true);
|
|
|
|
ob_clean();
|
|
flush();
|
|
readfile($filePath);
|
|
Request::shutDown();
|
|
}
|
|
|
|
// ------------------------------------------------------------------ //
|
|
// Шорткаты для статусов
|
|
// ------------------------------------------------------------------ //
|
|
|
|
/** 204 No Content */
|
|
public static function noContent()
|
|
{
|
|
self::setStatus(204);
|
|
Request::shutDown();
|
|
}
|
|
|
|
/** 404 Not Found */
|
|
public static function notFound($message = 'Not Found')
|
|
{
|
|
self::jsonError($message, 404);
|
|
}
|
|
|
|
/** 403 Forbidden */
|
|
public static function forbidden($message = 'Forbidden')
|
|
{
|
|
self::jsonError($message, 403);
|
|
}
|
|
|
|
/** 401 Unauthorized */
|
|
public static function unauthorized($message = 'Unauthorized')
|
|
{
|
|
self::jsonError($message, 401);
|
|
}
|
|
|
|
/** 429 Too Many Requests */
|
|
public static function tooManyRequests($message = 'Too Many Requests', $retryAfter = null)
|
|
{
|
|
if ($retryAfter !== null) {
|
|
Request::setHeader('Retry-After: ' . (int)$retryAfter, true);
|
|
}
|
|
|
|
self::jsonError($message, 429);
|
|
}
|
|
|
|
/** 422 Unprocessable Entity (ошибки валидации) */
|
|
public static function unprocessable($errors, $message = 'Validation failed')
|
|
{
|
|
self::json(['success' => false, 'error' => $message, 'errors' => $errors], 422);
|
|
}
|
|
|
|
/** 500 Internal Server Error */
|
|
public static function serverError($message = 'Internal Server Error')
|
|
{
|
|
self::jsonError($message, 500);
|
|
}
|
|
|
|
protected function __clone()
|
|
{
|
|
//
|
|
}
|
|
|
|
protected function __wakeup()
|
|
{
|
|
//
|
|
}
|
|
}
|