Passed
Push — master ( 09221c...35c1c3 )
by Dawid
02:49
created

Application::extend()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

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