Completed
Push — master ( 38f1ea...fd6c7c )
by Matze
04:05
created

AppKernel   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 97.73%

Importance

Changes 10
Bugs 0 Features 3
Metric Value
wmc 14
c 10
b 0
f 3
lcom 1
cbo 7
dl 0
loc 142
ccs 43
cts 44
cp 0.9773
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A handle() 0 16 2
A handleRequest() 0 23 3
A applyExceptionMiddleware() 0 11 3
A __construct() 0 11 1
A applyResponseMiddleware() 0 8 2
A prepareResponse() 0 12 3
1
<?php
2
3
namespace BrainExe\Core\Application;
4
5
use BrainExe\Annotations\Annotations\Inject;
6
use BrainExe\Annotations\Annotations\Service;
7
use BrainExe\Core\Middleware\MiddlewareInterface;
8
use Iterator;
9
use Throwable;
10
use Symfony\Component\HttpFoundation\JsonResponse;
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\HttpFoundation\Response;
13
use Symfony\Component\HttpKernel\HttpKernelInterface;
14
15
/**
16
 * @Service(public=true)
17
 */
18
class AppKernel implements HttpKernelInterface
19
{
20
21
    /**
22
     * @var ControllerResolver
23
     */
24
    private $resolver;
25
26
    /**
27
     * @var SerializedRouteCollection
28
     */
29
    private $routes;
30
31
    /**
32
     * @var UrlMatcher
33
     */
34
    private $urlMatcher;
35
36
    /**
37
     * @var MiddlewareInterface[]
38
     */
39
    private $middlewares;
40
41
    /**
42
     * @Inject({
43
     *     "@ControllerResolver",
44
     *     "@Core.RouteCollection",
45
     *     "@UrlMatcher",
46
     *     null
47
     * })
48
     * @param ControllerResolver $resolver
49
     * @param SerializedRouteCollection $routes
50
     * @param UrlMatcher $urlMatcher
51
     * @param MiddlewareInterface[] $middlewares
52
     */
53 3
    public function __construct(
54
        ControllerResolver $resolver,
55
        SerializedRouteCollection $routes,
56
        UrlMatcher $urlMatcher,
57
        array $middlewares
58
    ) {
59 3
        $this->resolver    = $resolver;
60 3
        $this->routes      = $routes;
61 3
        $this->urlMatcher  = $urlMatcher;
62 3
        $this->middlewares = $middlewares;
63 3
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68 3
    public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
69
    {
70 3
        $response = null;
71
72
        try {
73 3
            $response = $this->handleRequest($request);
74 1
        } catch (Throwable $exception) {
75 1
            $response = $this->applyExceptionMiddleware($request, $exception);
76
        }
77
78 3
        $response = $this->prepareResponse($response);
79
80 3
        $this->applyResponseMiddleware($request, $response);
81
82 3
        return $response;
83
    }
84
85
    /**
86
     * @param Request $request
87
     * @return Response|mixed
88
     */
89 3
    private function handleRequest(Request $request)
90
    {
91
        // match route and set attributes in request object
92 3
        $attributes = $this->urlMatcher->match($request);
93 2
        $request->attributes->add($attributes);
94
95 2
        $routeName = $attributes['_route'];
96 2
        $route     = $this->routes->get($routeName);
97
98 2
        foreach ($this->middlewares as $middleware) {
99 2
            $response = $middleware->processRequest($request, $route);
100 2
            if ($response) {
101
                // e.g. RedirectResponse or rendered error page
102 2
                return $response;
103
            }
104
        }
105
106
        /** @var callable $callable */
107 1
        $callable  = $this->resolver->getController($request);
108 1
        $arguments = $this->resolver->getArguments($request, $callable);
109
110 1
        return $callable(...$arguments);
111
    }
112
113
    /**
114
     * @param Response|mixed $response
115
     * @return Response
116
     */
117 3
    private function prepareResponse($response) : Response
118
    {
119 3
        if ($response instanceof Iterator) {
120 1
            $response = iterator_to_array($response);
121
        }
122
123 3
        if (!$response instanceof Response) {
124 1
            return new JsonResponse($response);
125
        }
126
127 2
        return $response;
128
    }
129
130
    /**
131
     * @param Request $request
132
     * @param Response $response
133
     */
134 3
    protected function applyResponseMiddleware(Request $request, Response $response)
135
    {
136 3
        $middlewareIdx = count($this->middlewares) - 1;
137 3
        for ($i = $middlewareIdx; $i >= 0; $i--) {
138 3
            $middleware = $this->middlewares[$i];
139 3
            $middleware->processResponse($request, $response);
140
        }
141 3
    }
142
143
    /**
144
     * @param Request $request
145
     * @param Throwable $exception
146
     * @return Response|null
147
     */
148 1
    protected function applyExceptionMiddleware(Request $request, Throwable $exception)
149
    {
150 1
        foreach ($this->middlewares as $middleware) {
151 1
            $response = $middleware->processException($request, $exception);
152 1
            if ($response !== null) {
153 1
                return $response;
154
            }
155
        }
156
157
        return null;
158
    }
159
}
160