authenticationFactory = $authenticationFactory; $this->actionProcessor = $actionProcessor; $this->authBuilderFactory = $authBuilderFactory; $this->errorOutput = $errorOutput; $this->config = $config; $this->log = $log; $this->applicationUser = $applicationUser; } public function process(Route $route, Request $request, Response $response): void { try { $this->processInternal($route, $request, $response); } catch (Exception $exception) { $this->handleException($exception, $request, $response, $route->getRoute()); } } private function processInternal(Route $route, Request $request, Response $response): void { $authRequired = !$route->noAuth(); $apiAuth = $this->authBuilderFactory ->create() ->setAuthentication($this->authenticationFactory->create()) ->setAuthRequired($authRequired) ->build(); $authResult = $apiAuth->process($request, $response); if (!$authResult->isResolved()) { return; } if ($authResult->isResolvedUseNoAuth()) { $this->applicationUser->setupSystemUser(); } ob_start(); $this->proceed($request, $response); ob_clean(); } private function proceed(Request $request, Response $response): void { $this->beforeProceed($response); $controllerName = $this->getControllerName($request); $actionName = $request->getRouteParam('action'); $requestMethod = $request->getMethod(); if (!$actionName) { $httpMethod = strtolower($requestMethod); $crudList = $this->config->get('crud') ?? []; $actionName = $crudList[$httpMethod] ?? null; if (!$actionName) { throw new Error("No action for method {$httpMethod}."); } } $this->actionProcessor->process($controllerName, $actionName, $request, $response); $this->afterProceed($response); } private function getControllerName(Request $request): string { $controllerName = $request->getRouteParam('controller'); if (!$controllerName) { throw new Error("Route doesn't have specified controller."); } return ucfirst($controllerName); } private function handleException( Exception $exception, Request $request, Response $response, string $route ): void { try { $this->errorOutput->process($request, $response, $exception, $route); } catch (Throwable $exceptionAnother) { $this->log->error($exceptionAnother->getMessage()); $response->setStatus(500); } } private function beforeProceed(Response $response): void { $response->setHeader('Content-Type', 'application/json'); } private function afterProceed(Response $response): void { $response ->setHeader('Expires', '0') ->setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT') ->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0') ->setHeader('Pragma', 'no-cache'); } }