Completed
Push — master ( 22aab3...557f5d )
by Dawid
10s
created

Application::getContainer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Igni\Application;
4
5
use Igni\Application\Exception\ApplicationException;
6
use Igni\Application\Http\MiddlewareAggregator;
7
use Igni\Application\Listeners\OnBootListener;
8
use Igni\Application\Listeners\OnErrorListener;
9
use Igni\Application\Listeners\OnRunListener;
10
use Igni\Application\Listeners\OnShutDownListener;
11
use Igni\Application\Providers\ConfigProvider;
12
use Igni\Application\Providers\ControllerProvider;
13
use Igni\Application\Providers\MiddlewareProvider;
14
use Igni\Application\Providers\ServiceProvider;
15
use Igni\Container\DependencyResolver;
16
use Igni\Container\ServiceLocator;
17
use Psr\Container\ContainerInterface;
18
use Throwable;
19
20
/**
21
 * Main glue between all components.
22
 *
23
 * @package Igni\Application
24
 */
25
abstract class Application
26
{
27
    /**
28
     * @var ServiceLocator|ContainerInterface
29
     */
30
    private $container;
31
32
    /**
33
     * @var Config
34
     */
35
    private $config;
36
37
    /**
38
     * @var bool
39
     */
40
    private $initialized = false;
41
42
    /**
43
     * @var object[]|class[]
44
     */
45
    protected $modules;
46
47
    /**
48
     * @var DependencyResolver
49
     */
50
    protected $resolver;
51
52
    /**
53
     * Application constructor.
54
     *
55
     * @param ContainerInterface|null $container
56
     */
57 23
    public function __construct(ContainerInterface $container = null)
58
    {
59 23
        if ($container === null) {
60 20
            $container = new ServiceLocator();
61
        }
62
63 23
        $this->container = $container;
64 23
        $this->resolver = new DependencyResolver($this->container);
65
66 23
        if ($this->container->has(Config::class)) {
67
            $this->config = $this->container->get(Config::class);
68
        } else {
69 23
            $this->config = new Config([]);
70
        }
71
72 23
        $this->modules = [];
73 23
    }
74
75
    /**
76
     * Allows for application extension by modules.
77
     * Module can be any valid object or class name.
78
     *
79
     * @param $module
80
     */
81 4
    public function extend($module): void
82
    {
83 4
        if (is_object($module) || class_exists($module)) {
84 3
            $this->modules[] = $module;
85
        } else {
86 1
            throw ApplicationException::forInvalidModule($module);
87
        }
88 3
    }
89
90
    /**
91
     * Starts the application.
92
     * Initialize modules. Performs tasks to generate response for the client.
93
     *
94
     * @return mixed
95
     */
96
    abstract public function run();
97
98
    /**
99
     * Controller aggregator is used to register application's controllers.
100
     * @return ControllerAggregator
101
     */
102
    abstract public function getControllerAggregator(): ControllerAggregator;
103
104
    /**
105
     * Middleware aggregator is used to register application's middlewares.
106
     * @return MiddlewareAggregator
107
     */
108
    abstract public function getMiddlewareAggregator(): MiddlewareAggregator;
109
110
    /**
111
     * @return Config
112
     */
113 1
    public function getConfig(): Config
114
    {
115 1
        return $this->config;
116
    }
117
118 20
    public function getContainer(): ContainerInterface
119
    {
120 20
        return $this->container;
121
    }
122
123 9
    protected function handleOnBootListeners(): void
124
    {
125 9
        foreach ($this->modules as $module) {
126 2
            if ($module instanceof OnBootListener) {
127 2
                $module->onBoot($this);
128
            }
129
        }
130 9
    }
131
132 2
    protected function handleOnShutDownListeners(): void
133
    {
134 2
        foreach ($this->modules as $module) {
135 2
            if ($module instanceof OnShutDownListener) {
136 2
                $module->onShutDown($this);
137
            }
138
        }
139 2
    }
140
141 3
    protected function handleOnErrorListeners(Throwable $exception): Throwable
142
    {
143 3
        foreach ($this->modules as $module) {
144 2
            if ($module instanceof OnErrorListener) {
145 2
                $exception = $module->onError($this, $exception);
146
            }
147
        }
148
149 3
        return $exception;
150
    }
151
152 9
    protected function handleOnRunListeners(): void
153
    {
154 9
        foreach ($this->modules as $module) {
155 2
            if ($module instanceof OnRunListener) {
156 2
                $module->onRun($this);
157
            }
158
        }
159 9
    }
160
161 9
    protected function initialize(): void
162
    {
163 9
        if ($this->initialized) {
164
            return;
165
        }
166
167 9
        foreach ($this->modules as &$module) {
168 2
            $this->initializeModule($module);
169
        }
170
171 9
        $this->initialized = true;
172 9
    }
173
174 2
    protected function initializeModule(&$module): void
175
    {
176 2
        if (is_string($module)) {
177 1
            $module = $this->resolver->resolve($module);
178
        }
179
180 2
        if ($module instanceof ConfigProvider) {
181
            $module->provideConfig($this->getConfig());
182
        }
183
184 2
        if ($module instanceof ControllerProvider) {
185 1
            $module->provideControllers($this->getControllerAggregator());
186
        }
187
188 2
        if ($module instanceof ServiceProvider) {
189
            $module->provideServices($this->getContainer());
190
        }
191
192 2
        if ($module instanceof MiddlewareProvider) {
193 1
            $module->provideMiddleware($this->getMiddlewareAggregator());
194
        }
195 2
    }
196
}
197