add generic HttpResponse #6
							
								
								
									
										109
									
								
								src/Response/HttpResponse.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/Response/HttpResponse.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,109 @@
 | 
			
		||||
<?php namespace SokoWeb\Response;
 | 
			
		||||
 | 
			
		||||
use SokoWeb\Interfaces\Response\IRedirect;
 | 
			
		||||
use SokoWeb\Interfaces\Response\IContent;
 | 
			
		||||
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
 | 
			
		||||
use SokoWeb\Interfaces\Authorization\ISecured;
 | 
			
		||||
use SokoWeb\Interfaces\Request\IRequest;
 | 
			
		||||
use SokoWeb\Response\Redirect;
 | 
			
		||||
use SokoWeb\Response\HtmlContent;
 | 
			
		||||
use SokoWeb\Response\JsonContent;
 | 
			
		||||
use SokoWeb\Routing\RouteCollection;
 | 
			
		||||
 | 
			
		||||
class HttpResponse
 | 
			
		||||
{
 | 
			
		||||
    private IRequest $request;
 | 
			
		||||
 | 
			
		||||
    private RouteCollection $routeCollection;
 | 
			
		||||
 | 
			
		||||
    private array $appConfig;
 | 
			
		||||
 | 
			
		||||
    private string $method;
 | 
			
		||||
 | 
			
		||||
    private string $rawUrl;
 | 
			
		||||
 | 
			
		||||
    private array $parsedUrl;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        IRequest $request,
 | 
			
		||||
        RouteCollection $routeCollection,
 | 
			
		||||
        array $appConfig,
 | 
			
		||||
        string $requestMethod,
 | 
			
		||||
        string $requestUrl
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->request = $request;
 | 
			
		||||
        $this->routeCollection = $routeCollection;
 | 
			
		||||
        $this->appConfig = $appConfig;
 | 
			
		||||
        $this->method = strtolower($requestMethod);
 | 
			
		||||
        $this->parsedUrl = parse_url($requestUrl);
 | 
			
		||||
        $this->rawUrl = $requestUrl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function render(): void
 | 
			
		||||
    {
 | 
			
		||||
        $match = $this->routeCollection->match($this->method, $this->parsedUrl['path']);
 | 
			
		||||
        if ($match === null) {
 | 
			
		||||
            $this->render404();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        list($route, $params) = $match;
 | 
			
		||||
        $this->request->setParsedRouteParams($params);
 | 
			
		||||
        $handler = $route->getHandler();
 | 
			
		||||
        $controller = new $handler[0]($this->request);
 | 
			
		||||
 | 
			
		||||
        if (
 | 
			
		||||
            $controller instanceof IAuthenticationRequired &&
 | 
			
		||||
            $controller->isAuthenticationRequired() &&
 | 
			
		||||
            $this->request->user() === null
 | 
			
		||||
        ) {
 | 
			
		||||
            $this->redirectToLogin();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (
 | 
			
		||||
            $this->method === 'post' &&
 | 
			
		||||
            !in_array($this->parsedUrl['path'], $this->appConfig['antiCsrfTokenExceptions']) &&
 | 
			
		||||
            $this->request->post($this->appConfig['antiCsrfTokenName']) !== $this->request->session()->get($this->appConfig['antiCsrfTokenName'])
 | 
			
		||||
        ) {
 | 
			
		||||
            $this->renderAntiCsrfError();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($controller instanceof ISecured && !$controller->authorize()) {
 | 
			
		||||
            $this->render404();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $response = call_user_func([$controller, $handler[1]]);
 | 
			
		||||
        if ($response instanceof IContent) {
 | 
			
		||||
            header('Content-Type: ' . $response->getContentType() . '; charset=UTF-8');
 | 
			
		||||
            $response->render();
 | 
			
		||||
        } elseif ($response instanceof IRedirect) {
 | 
			
		||||
            header('Location: ' . $response->getUrl(), true, $response->getHttpCode());
 | 
			
		||||
        } else {
 | 
			
		||||
            $this->render404();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function redirectToLogin(): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->request->session()->set('redirect_after_login', $this->rawUrl);
 | 
			
		||||
        $response = new Redirect($this->routeCollection->getRoute($this->appConfig['loginRouteId'])->generateLink(), IRedirect::TEMPORARY);
 | 
			
		||||
        header('Location: ' . $response->getUrl(), true, $response->getHttpCode());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function renderAntiCsrfError(): void
 | 
			
		||||
    {
 | 
			
		||||
        $content = new JsonContent($this->appConfig['antiCsrfTokenErrorResponse']);
 | 
			
		||||
        header('Content-Type: text/html; charset=UTF-8', true, 403);
 | 
			
		||||
        $content->render();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function render404(): void
 | 
			
		||||
    {
 | 
			
		||||
        $content = new HtmlContent($this->appConfig['error404View']);
 | 
			
		||||
        header('Content-Type: text/html; charset=UTF-8', true, 404);
 | 
			
		||||
        $content->render();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user