Completed
Push — master ( ea8fd7...b1104c )
by Oleg
03:59
created

Application::run()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 10
nc 3
nop 1
1
<?php
2
3
namespace Micro\base;
4
5
use Micro\Web\ResponseInjector;
6
use Psr\Http\Message\ResponseInterface;
7
use Psr\Http\Message\ServerRequestInterface;
8
9
/**
10
 * Base class for applications
11
 *
12
 * Start point for application and sender system messages to dispatcher
13
 *
14
 * @package Micro\base
15
 */
16
abstract class Application implements ApplicationInterface
17
{
18
    /** @var KernelInterface $kernel */
19
    protected $kernel;
20
21
    /**
22
     * Application constructor.
23
     * @param KernelInterface $kernel
24
     */
25
    final public function __construct(KernelInterface $kernel = null)
26
    {
27
        $this->kernel = $kernel;
28
29
        if (!$this->kernel) {
30
            $this->kernel = new Kernel('devel', true);
31
        }
32
33
        // init injectors
34
        $this->kernel->loadInjectorsFromCache(); // TODO: load injectors
35
    }
36
37
    /**
38
     * Running application
39
     *
40
     * @param ServerRequestInterface $server
41
     * @return ResponseInterface
42
     * @throws \Exception
43
     */
44
    final public function run(ServerRequestInterface $server)
45
    {
46
        $this->kernel->initialize($server);
47
48
        FatalError::register(); // TODO: fix for FatalErrors
49
50
        try {
51
            return $this->doRun();
52
        } catch (\Exception $e) {
53
            if ($this->kernel->isDebug()) {
54
                (new DispatcherInjector)->build()->signal('kernel.exception', ['exception' => $e]);
55
56
                throw $e;
57
            }
58
59
            return $this->doException($e);
60
        }
61
    }
62
63
    /**
64
     * Real run application
65
     *
66
     * @return ResponseInterface
67
     */
68
    private function doRun()
69
    {
70
        $dispatcher = (new DispatcherInjector)->build();
71
72
        //покажем событие Request
73
        if (($response = $dispatcher->signal('kernel.request')) instanceof ResponseInterface) {
74
            return $response; // событие завершило очередь
75
        }
76
77
        $resolver = $this->getResolver();
78
79
        //покажем событие Route
80
        if (($response = $dispatcher->signal('kernel.route', ['resolver' => $resolver])) instanceof ResponseInterface) {
81
            return $response; // событие завершило очередь
82
        }
83
84
        $controller = $resolver->getApp();
85
        $action = $resolver->getAction();
86
87
        //покажем событие Controller
88
        if (($response = $dispatcher->signal('kernel.controller',
89
                ['controller' => $controller, 'action' => $action])) instanceof ResponseInterface
90
        ) {
91
            return $response; // событие завершило очередь
92
        }
93
94
        $response = $controller->action((string)$action);
95
96
        if (!($response instanceof ResponseInterface)) {
97
            $responser = (new ResponseInjector)->build();
98
            $stream = $responser->getBody();
99
            $stream->write((string)$response);
100
101
            $response = $responser->withBody($stream);
102
        }
103
104
        $dispatcher->signal('kernel.response', ['response' => $response]);
105
106
        return $response;
107
    }
108
109
    /**
110
     * Run application with error
111
     *
112
     * @param \Exception $error
113
     * @return ResponseInterface
114
     */
115
    abstract protected function doException(\Exception $error);
116
117
    /**
118
     * Send response to client
119
     *
120
     * @param ResponseInterface $response
121
     */
122
    public function send(ResponseInterface $response)
123
    {
124
        printf($response->getBody() . PHP_EOL);
125
    }
126
127
    /**
128
     * Terminate application
129
     */
130
    public function terminate()
131
    {
132
        try {
133
            (new DispatcherInjector)->build()->signal('kernel.kill', []);
134
        } catch (Exception $e) {
135
            (new Dispatcher)->signal('kernel.kill', []);
136
        }
137
    }
138
}