f3 = Base::instance(); } /** * Renders an application error in the response format for the request type. * * @return null Always returns null for PHP/F3 requests after writing JSON. * @sideEffects Clears output buffers, writes a log entry, and renders or exits. */ public function Handler() { $error = $this->f3->get('ERROR'); $errorValues = [$error['code'], $error['status'], $error['text']]; while (ob_get_level() > 0) { ob_end_clean(); } $this->writeLog(implode(' - ', $errorValues)); if ($this->f3->get('CLI')) { print_r($errorValues); exit(1); } if ($this->isApiRequest()) { $this->f3->status((int) $error['code']); } header('Content-Type: ' . self::JSON_CONTENT_TYPE); echo json_encode(['error' => $error['text']], JSON_THROW_ON_ERROR); return null; } /** * Determine whether the current request belongs to the versioned API. * * @return bool True when the request path is rooted at /api/v1. * @sideEffects Reads the current request URI from the framework. */ private function isApiRequest(): bool { $uri = $this->f3->get('URI'); if (!is_string($uri)) { return false; } $path = parse_url($uri, PHP_URL_PATH); $basePath = $this->f3->get('BASE'); if (is_string($path) && is_string($basePath)) { $basePath = rtrim($basePath, '/'); if ($basePath !== '' && $basePath !== '/' && ($path === $basePath || str_starts_with($path, $basePath . '/'))) { $path = substr($path, strlen($basePath)) ?: '/'; } } return is_string($path) && ($path === self::API_PATH_PREFIX || str_starts_with($path, self::API_PATH_PREFIX . '/')); } /** * Writes an error message with the relevant caller context. * * @param string $message Error message. * @param int $traceIndex Caller index in the debug trace. * @return void * @sideEffects Writes to the application log. */ private function writeLog(string $message, int $traceIndex = 1): void { $trace = debug_backtrace(); $context = $trace[$traceIndex] ?? []; $prefix = ($context['line'] ?? '') . ':' . ($context['class'] ?? '') . ':' . ($context['function'] ?? '') . ':'; $sanitizedMessage = str_replace(["\r", "\n"], '', $message); OMUtils::getInstance()->getLogger()->write( "{$prefix} {$sanitizedMessage}", self::LOG_DATE_FORMAT, ); } }