response(true, $data, $status); } #[NoReturn] public function response(bool $success, mixed $data, int $status = null): void { global $DEBUG; header('Content-Type: application/json; charset=utf-8'); if ($status) { http_response_code($status); } else { http_response_code($success ? 200 : 400); } // If the data isn't an array, convert it to an array if (!is_array($data) && !is_object($data)) { // Check if the variable is a valid JSON string if (is_string($data) && json_decode($data) !== null) { $data = json_decode($data, true); } else { // If the variable is not a valid JSON string, convert it to an array $data = ['message' => $data]; } } // If the debug mode is enabled, add the debug data to the response if ($DEBUG && false) { $this->add_include('debug', [ 'memory' => memory_get_usage(), 'time' => microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'], 'data' => $this->get_data() ]); } echo json_encode([ 'success' => $success, 'data' => $data, 'meta' => $this->meta, 'includes' => $this->includes ], JSON_UNESCAPED_UNICODE); exit; } public function add_include(string $string, array $dataArray): void { $this->add_included($string, $dataArray); } public function add_included(string $key, mixed $value): void { $this->includes[$key] = $value; } public function get_data(): array { return $this->data; } #[NoReturn] public function not_found(): void { $this->error('Not found', 404); } #[NoReturn] public function error(mixed $data, int $status = null): void { $this->response(false, $data, $status); } #[NoReturn] public function rate_limit_exceeded(): void { $this->error('Rate limit exceeded', 429); } public function matching_route_found(): void { $this->matching_route_found = true; } #[NoReturn] public function method_not_allowed(): void { $this->error('Method not allowed', 405); } #[NoReturn] public function internal_server_error($error): void { $this->error('Internal server error' . ($error ? ': ' . $error : ''), 500); } public function paginate(int $page, int $per_page, int $total, string $search = null, array $filters = null, array $order = null): void { // If the total is 0, return 1 page, 0 total if ($total === 0) { $total = 1; } $this->add_meta('pagination', [ 'page' => $page, 'per_page' => $per_page, 'total' => $total, 'search' => $search, 'filters' => $filters, 'order' => $order ]); } public function add_meta(string $key, mixed $value): void { $this->meta[$key] = $value; } public function is_matching_route_found(): bool { return $this->matching_route_found; } public function add_debug(mixed $data): void { $this->add_data('debug', $data); } public function add_data(string $key, mixed $value): void { $this->data[$key] = $value; } public function getRequestParameter(string $key): mixed { $data = []; // Get the request data if the method is POST, PUT or PATCH if ($_SERVER['REQUEST_METHOD'] === 'POST' || $_SERVER['REQUEST_METHOD'] === 'PUT' || $_SERVER['REQUEST_METHOD'] === 'PATCH') { $data = json_decode(file_get_contents('php://input'), true); } // Get the request data if the method is GET, DELETE or OPTIONS if ($_SERVER['REQUEST_METHOD'] === 'GET' || $_SERVER['REQUEST_METHOD'] === 'DELETE' || $_SERVER['REQUEST_METHOD'] === 'OPTIONS') { $data = $_GET; } if (!is_array($data)) { $data = []; } // If the data key is not set, try to get it from the opposite method if (!array_key_exists($key, $data)) { if ($_SERVER['REQUEST_METHOD'] === 'POST' || $_SERVER['REQUEST_METHOD'] === 'PUT' || $_SERVER['REQUEST_METHOD'] === 'PATCH') { $data = $_GET; } else { $data = json_decode(file_get_contents('php://input'), true); } } if (!is_array($data)) { $data = []; } // Return the data return $data[$key] ?? null; } /** * Get all request parameters * @return array */ public function getAllRequestParameters(): array { $data = []; // Get the request data if the method is POST, PUT or PATCH if ($_SERVER['REQUEST_METHOD'] === 'POST' || $_SERVER['REQUEST_METHOD'] === 'PUT' || $_SERVER['REQUEST_METHOD'] === 'PATCH') { $data = json_decode(file_get_contents('php://input'), true); } // Get the request data if the method is GET, DELETE or OPTIONS if ($_SERVER['REQUEST_METHOD'] === 'GET' || $_SERVER['REQUEST_METHOD'] === 'DELETE' || $_SERVER['REQUEST_METHOD'] === 'OPTIONS') { $data = $_GET; } if (!is_array($data)) { return []; } return $data; } /** * This function checks if a request parameter is set. * This is different from getRequestParameter because this function allows for empty & null values. * @param string $key * @return bool */ public function isRequestParameterSet(string $key): bool { $data = []; // Get the request data if the method is POST, PUT or PATCH if ($_SERVER['REQUEST_METHOD'] === 'POST' || $_SERVER['REQUEST_METHOD'] === 'PUT' || $_SERVER['REQUEST_METHOD'] === 'PATCH') { $data = json_decode(file_get_contents('php://input'), true); } // Get the request data if the method is GET, DELETE or OPTIONS if ($_SERVER['REQUEST_METHOD'] === 'GET' || $_SERVER['REQUEST_METHOD'] === 'DELETE' || $_SERVER['REQUEST_METHOD'] === 'OPTIONS') { $data = $_GET; } if (!is_array($data)) { return false; } return array_key_exists($key, $data); } public function parseFilters(?string $filters): array|null { if ($filters) { $filters = explode(',', $filters); $temp = []; foreach ( $filters as $filter ) { $filter = explode(':', $filter); $temp[$filter[0]] = $filter[1]; } $filters = $temp; } if ($filters) { return $filters; } return null; } public function add_debug_list(string $list_name, int $key, $value): void { $this->add_data($list_name, [$key => $value]); } #[NoReturn] public function displayPDF($raw_pdf): void { self::disableAll(); $virtual_file = fopen('php://temp', 'r+'); fwrite($virtual_file, $raw_pdf); fseek($virtual_file, 0); file_put_contents('/tmp/debug_output.pdf', stream_get_contents($virtual_file)); // Return the PDF /tmp/debug_output.pdf header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="debug_output.pdf"'); header('Content-Length: ' . filesize('/tmp/debug_output.pdf')); header('Content-Transfer-Encoding: binary'); header('Accept-Ranges: bytes'); readfile('/tmp/debug_output.pdf'); exit; } private static function disableAll(): void { error_reporting(0); ini_set('display_errors', '0'); } /** * This function gets the user object from the token * @throws Exception If the token is invalid, or the user is not found */ public function get_user(): users_o|false { // Check if the user is already set if (!isset($this->users_o)) { // Get the user object $this->users_o = (new authentication())->get_user(); } // Return the user object return $this->users_o; } }