Passed
Push — master ( 4b954d...b01812 )
by Gabor
03:38
created

WebApplication::prepareContainer()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 63
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 63
ccs 0
cts 0
cp 0
rs 9.4347
c 0
b 0
f 0
cc 2
eloc 42
nc 3
nop 0
crap 6

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * WebHemi.
4
 *
5
 * PHP version 5.6
6
 *
7
 * @copyright 2012 - 2016 Gixx-web (http://www.gixx-web.com)
8
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
9
 *
10
 * @link      http://www.gixx-web.com
11
 */
12
namespace WebHemi\Application\Web;
13
14
use Exception;
15
use WebHemi\Adapter\Http\ResponseInterface;
16
use WebHemi\Adapter\Http\ServerRequestInterface;
17
use WebHemi\Adapter\Http\HttpAdapterInterface;
18
use WebHemi\Application\AbstractApplication;
19
use WebHemi\Application\EnvironmentManager;
20
use WebHemi\Application\PipelineManager;
21
use WebHemi\Application\SessionManager;
22
use WebHemi\Middleware\DispatcherMiddleware;
23
use WebHemi\Middleware\FinalMiddleware;
24
use WebHemi\Middleware\MiddlewareInterface;
25
26
/**
27
 * Class WebApplication.
28
 */
29
class WebApplication extends AbstractApplication
30
{
31
    /**
32
     * Starts the session.
33
     *
34
     * @codeCoverageIgnore - not testing session (yet)
35
     */
36
    private function initSession()
37
    {
38
        if (defined('PHPUNIT_WEBHEMI_TESTSUITE')) {
39
            return;
40
        }
41
42
        /** @var SessionManager $sessionManager */
43
        $sessionManager = $this->getContainer()->get(SessionManager::class);
44
        /** @var EnvironmentManager $environmentManager */
45
        $environmentManager = $this->getContainer()->get(EnvironmentManager::class);
46
47
        $name = $environmentManager->getSelectedApplication();
48
        $timeOut = 3600;
49
        $path = $environmentManager->getSelectedApplicationUri();
50
        $domain = $environmentManager->getApplicationDomain();
51
        $secure = $environmentManager->isSecuredApplication();
52
        $httpOnly = true;
53
54
        $sessionManager->start($name, $timeOut, $path, $domain, $secure, $httpOnly);
55
    }
56
57
    /**
58
     * Runs the application. This is where the magic happens.
59
     * According tho the environment settings this must build up the middleware pipeline and execute it.
60
     *
61
     * a Pre-Routing Middleware can be; priority < 0:
62
     *  - LockCheck - check if the client IP is banned > S102|S403
63
     *  - Auth - if the user is not logged in, but there's a "Remember me" cookie, then logs in > S102
64
     *
65
     * Routing Middleware is fixed (RoutingMiddleware::class); priority = 0:
66
     *  - A middleware that routes the incoming Request and delegates to the matched middleware. > S102|S404|S405
67
     *    The RouteResult should be attached to the Request.
68
     *    If the Routing is not defined explicitly in the pipeline, then it will be injected with priority 0.
69
     *
70
     * a Post-Routing Middleware can be; priority between 0 and 100:
71
     *  - Acl - checks if the given route is available for the client. Also checks the auth > S102|S401|S403
72
     *  - CacheReader - checks if a suitable response body is cached. > S102|S200
73
     *
74
     * Dispatcher Middleware is fixed (DispatcherMiddleware::class); priority = 100:
75
     *  - A middleware which gets the corresponding Action middleware and applies it > S102
76
     *    If the Dispatcher is not defined explicitly in the pipeline, then it will be injected with priority 100.
77
     *    The Dispatcher should not set the response Status Code to 200 to let Post-Dispatchers to be called.
78
     *
79
     * a Post-Dispatch Middleware can be; priority > 100:
80
     *  - CacheWriter - writes response body into DataStorage (DB, File etc.) > S102
81
     *
82
     * Final Middleware is fixed (FinalMiddleware:class):
83
     *  - This middleware behaves a bit differently. It cannot be ordered, it's always the last called middleware:
84
     *    - when the middleware pipeline reached its end (typically when the Status Code is still 102)
85
     *    - when one item of the middleware pipeline returns with return response (status code is set to 200|40*|500)
86
     *    - when during the pipeline process an Exception is thrown.
87
     *
88
     * When the middleware pipeline is finished the application prints the header and the output.
89
     *
90
     * If a middleware other than the Routing, Dispatcher and Final Middleware has no priority set, it will be
91
     * considered to have priority = 50.
92
     *
93
     * @return void
94
     */
95 4
    public function run()
96
    {
97
        // Start session.
98 4
        $this->initSession();
99
100
        /** @var HttpAdapterInterface $httpAdapter */
101 4
        $httpAdapter = $this->getContainer()->get(HttpAdapterInterface::class);
102
        /** @var PipelineManager $pipelineManager */
103 4
        $pipelineManager = $this->getContainer()->get(PipelineManager::class);
104
105
        /** @var ServerRequestInterface $request */
106 4
        $request = $httpAdapter->getRequest();
107
        /** @var ResponseInterface $response */
108 4
        $response = $httpAdapter->getResponse();
109
        /** @var string $middlewareClass */
110 4
        $middlewareClass = $pipelineManager->start();
111
112
        while ($middlewareClass !== null
113 4
            && $response->getStatusCode() == ResponseInterface::STATUS_PROCESSING
114 4
        ) {
115
            try {
116
                /** @var MiddlewareInterface $middleware */
117 4
                $middleware = $this->getContainer()->get($middlewareClass);
118 4
                $requestAttributes = $request->getAttributes();
119
120
                // As an extra step if the action middleware is resolved, it is invoked right before the dispatcher.
121
                // Only the container knows how to instantiate it in the right way, and the container must not be
122
                // injected into other classes. It seems like a hack but it is by purpose.
123
                if ($middleware instanceof DispatcherMiddleware
124 4
                    && isset($requestAttributes[ServerRequestInterface::REQUEST_ATTR_RESOLVED_ACTION_CLASS])
125 4
                ) {
126
                    /** @var MiddlewareInterface $actionMiddleware */
127 2
                    $actionMiddleware = $this->getContainer()
128 2
                        ->get($requestAttributes[ServerRequestInterface::REQUEST_ATTR_RESOLVED_ACTION_CLASS]);
129 2
                    $request = $request->withAttribute(
130 2
                        ServerRequestInterface::REQUEST_ATTR_ACTION_MIDDLEWARE,
131
                        $actionMiddleware
132 2
                    );
133 2
                }
134 4
                $response = $middleware($request, $response);
135 4
            } catch (Exception $exception) {
136 1
                $response = $response->withStatus(ResponseInterface::STATUS_INTERNAL_SERVER_ERROR);
137 1
                $request = $request->withAttribute(
138 1
                    ServerRequestInterface::REQUEST_ATTR_MIDDLEWARE_EXCEPTION,
139
                    $exception
140 1
                );
141
            }
142
143 4
            $middlewareClass = $pipelineManager->next();
144 4
        };
145
146
        // If there was no error, we mark as ready for output.
147 4
        if ($response->getStatusCode() == ResponseInterface::STATUS_PROCESSING) {
148 1
            $response = $response->withStatus(ResponseInterface::STATUS_OK);
149 1
        }
150
151
        /** @var FinalMiddleware $finalMiddleware */
152 4
        $finalMiddleware = $this->getContainer()->get(FinalMiddleware::class);
153
154
        // Send out headers and content.
155 4
        $finalMiddleware($request, $response);
156 4
    }
157
}
158