'OK', 301 => 'Moved Permanently', 302 => 'Found', 304 => 'Not Modified', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 408 => 'Request Timeout', 500 => 'Internal Server Error', 501 => 'Not Implemented', 503 => 'Service Unavailable', ]; /** * cookies to send * @var null|Cookies */ protected $cookies; /** * HTTP CODE * @var int */ protected $code; /** * content as array * @var array */ protected $content; /** * headers * @var array */ protected $headers; public function __construct(int $code, array $content, array $headers = [],?Cookies $cookies = null){ $this->code = array_key_exists($code, self::HTTP_CODES) ? $code : 501; // default $this->content = $content; $this->headers = array_merge([ 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*', 'Access-Control-Allow-Credentials' => 'true', 'Access-Control-Allow-Headers' => 'X-Requested-With, Location, Slug, Accept, Content-Type', 'Access-Control-Expose-Headers' => 'Location, Slug, Accept, Content-Type', 'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, DELETE, PUT, PATCH', 'Access-Control-Max-Age' => '86400' ], $headers); $this->cookies = $cookies; } /** * set Cookies instance * @param Cookies $cookies */ public function setCookies(Cookies $cookies) { $this->cookies = $cookies; } /** * merge in content * @param array $newContent * @return $this */ public function mergeInContent(array $newContent){ $this->content = array_merge( $this->content, $newContent ); } /** * prepend in content * @param array $newContent * @return $this */ protected function prependInContent(array $newContent){ $this->content = array_merge( $newContent, $this->content ); } /** * set code * @param int */ public function setCode(int $code) { $this->code = $code; } /* === Getters === */ /** * return code * @return int */ public function getCode(): int { return $this->code; } /** * return content * @return array */ public function getContent(): array { return $this->content; } /* === === */ /** * Sends HTTP headers. * * @return $this */ public function sendHeaders(): JsonResponse { // headers have already been sent by the developer if (JsonResponse::canSendHeaders()) { // headers foreach ($this->headers as $name => $value) { header($name.': '.$value); } // cookies if (!is_null($this->cookies)){ $this->cookies->sendCookiesOnce(); } // status $statusText = self::HTTP_CODES[$this->code]; $protocol = !empty($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; header("$protocol {$this->code} $statusText"); } return $this; } /** * test if headers can be sent * @return bool */ public static function canSendHeaders(): bool { return !headers_sent() && !in_array(php_sapi_name(), ['cli', 'cli-server',' phpdbg'], true); } /** * send headers and return output * @return string */ public function send(): string { return $this->preparedOutput()->prepareStatusText()->sendHeaders()->returnContent(); } /** * check if output is JSONSerializable * @return JsonResponse $this */ protected function preparedOutput(): JsonResponse { try { if (!empty($GLOBALS['errorMessages'])){ $this->mergeInContent(['errorMessages'=>$GLOBALS['errorMessages']]); } json_encode($this->content); } catch (Throwable $th) { $this->code = 500; $this->content = ['code' => 500, 'reason' =>"Not possible to JSONSerialize content"]; } return $this; } /** * prepare statusText * @return JsonResponse $this */ protected function prepareStatusText(): JsonResponse { if (!array_key_exists($this->code,self::HTTP_CODES)){ $previousCode = intval($this->code); $this->code = 501; $this->prependInContent(['code' => 501, 'reason' =>"Wanted code ($previousCode) is not implemented !"]); } return $this; } /** * return content as String * @return string */ protected function returnContent(): string { return json_encode($this->getContent()); } /** * export class as array * @return array */ public function jsonSerialize(): mixed { return [ 'code' => $this->getCode(), 'content' => $this->getContent(), 'headers' => $this->headers, ]; } }