Application::runController()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Selami;
5
6
use Psr\Container\ContainerInterface;
7
use Psr\Http\Message\ServerRequestInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Server\RequestHandlerInterface;
10
use Selami\Router\Route;
11
use Selami\Router\Router;
12
use Selami\View\ViewInterface;
13
use Zend\Config\Config;
14
15
16
class Application implements RequestHandlerInterface
17
{
18
19
    private $id;
20
    /**
21
     * @var ContainerInterface
22
     */
23
    private $container;
24
    /**
25
     * @var Config
26
     */
27
    private $config;
28
    /**
29
     * @var Router
30
     */
31
    private $router;
32
33
    /**
34
     * @var ApplicationResponse
35
     */
36
    private $response;
37
38
    /**
39
     * @var ServerRequestInterface
40
     */
41
    private $request;
42
    private $requestedMethod;
43
    private $requestedPath;
44
    private $route;
45
46
    public function __construct(
47
        string $id,
48
        ContainerInterface $container,
49
        Router $router,
50
        Config $config
51
    ) {
52
        $this->id = $id;
53
        $this->config = $config;
54
        $this->router = $router;
55
        $this->container  = $container;
56
    }
57
58
    public static function createWithContainer(ContainerInterface $container, ?string $id = 'selami-app') : self
59
    {
60
        return new self(
61
            $id,
62
            $container,
63
            $container->get(Router::class),
64
            $container->get(Config::class)
65
        );
66
    }
67
68
    public function handle(ServerRequestInterface $request) : ResponseInterface
69
    {
70
        $this->request = $request;
71
        $this->run();
72
        return $this->response->returnResponse();
73
    }
74
75
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
76
    : ResponseInterface
77
    {
78
        $this->request = $request;
79
        $this->run();
80
        return $this->response->returnResponse();
81
    }
82
83
    private function run() : void
84
    {
85
        $this->requestedMethod = $this->request->getMethod();
86
        $this->requestedPath = $this->request->getUri()->getPath();
87
        $route = $this->getRoute();
88
        $statusCode = $route->getStatusCode();
89
        switch ($statusCode) {
90
            case 405:
91
                $this->notFound(405, 'Method Not Allowed');
92
                break;
93
            case 200:
94
                $this->runController(
95
                    $route->getController(),
96
                    $route->getUriParameters()
97
                );
98
                break;
99
            case 404:
100
            default:
101
                $this->notFound($statusCode, 'Not Found');
102
                break;
103
        }
104
    }
105
106
    private function notFound($status, $message) : void
107
    {
108
        $errorHandlerClass = $this->config->get('app')->get('http-error-handler');
109
        $errorHandler = new $errorHandlerClass($status, $message);
110
        $this->response = new ApplicationResponse(
111
            $this->request,
112
            $errorHandlerClass,
113
            $errorHandler(),
114
            $this->config,
115
            $this->container->get(ViewInterface::class)
116
        );
117
    }
118
119
    private function getRoute() : Route
120
    {
121
        $appConfig = $this->config->get('app');
122
        $this->router = $this->router
123
            ->withSubFolder($appConfig->get('app_sub_folder', ''));
124
        if ($appConfig->get('router_cache_enabled', false) === true) {
125
            $cacheFile = $appConfig->get('cache_dir').'/'.$this->id.'.fastroute.cache';
126
            $this->router = $this->router
127
                ->withCacheFile($cacheFile);
128
        }
129
        $this->addRoutes($this->config->get('routes')->get($this->id)->toArray());
130
        return $this->route ?? $this->router->getRoute();
131
    }
132
133
    private function addRoutes($routes) : void
134
    {
135
        foreach ($routes as $route) {
136
            if ($this->requestedMethod === $route[0] && $this->requestedPath === $route[1]) {
137
                $this->route = new Route($route[0], $route[1], 200,  $route[3], $route[2], []);
138
                break;
139
            }
140
            $this->router->add($route[0], $route[1], $route[2], $route[3], $route[4] ?? '');
141
        }
142
    }
143
144
    private function runController($controllerClass, array $args) : void
145
    {
146
        $controller = new FrontController($this->container, $this->request, $controllerClass, $args);
147
        $this->response = new ApplicationResponse(
148
            $this->request,
149
            $controllerClass,
150
            $controller->getControllerResponse(),
151
            $this->config,
152
            $this->container->get(ViewInterface::class)
153
        );
154
    }
155
}
156