Passed
Push — master ( b817d9...04ae87 )
by 世昌
02:23
created

ApplicationLoader::getModuleDirectoryConfig()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace suda\application\loader;
4
5
use suda\framework\Config;
6
use suda\application\Module;
7
use suda\application\Resource;
8
use suda\application\ModuleBag;
9
use suda\application\Application;
10
use suda\application\database\Database;
11
use suda\database\exception\SQLException;
12
use suda\framework\filesystem\FileSystem;
13
use suda\application\builder\ModuleBuilder;
14
15
/**
16
 * 应用程序
17
 */
18
class ApplicationLoader
19
{
20
    /**
21
     * 应用程序
22
     *
23
     * @var Application
24
     */
25
    protected $application;
26
27
    /**
28
     * 模块加载器
29
     *
30
     * @var ModuleLoader[]
31
     */
32
    protected $moduleLoader;
33
34
35
    /**
36
     * @var array
37
     */
38
    protected $actionableModules;
39
40
    /**
41
     * @var array
42
     */
43
    protected $reachableModules;
44
45
    public function __construct(Application $application)
46
    {
47
        $this->application = $application;
48
        $this->actionableModules = [];
49
        $this->reachableModules = [];
50
    }
51
52
    public function load()
53
    {
54
        $this->loadVendorIfExist();
55
        $this->loadGlobalConfig();
56
        $this->registerModule();
57
        $this->setModuleStatus();
58
        $this->prepareModule();
59
        $this->activeModule();
60
    }
61
62
63
    public function loadRoute()
64
    {
65
        foreach ($this->application->getModules() as $name => $module) {
66
            if ($module->getStatus() === Module::REACHABLE) {
67
                call_user_func([$this->moduleLoader[$name], 'toReachable']);
68
            }
69
        }
70
    }
71
72
73
    public function loadGlobalConfig()
74
    {
75
        $resource = $this->application->getResource();
76
        if ($configPath = $resource->getConfigResourcePath('config/config')) {
77
            $this->application->getConfig()->load($configPath);
78
        }
79
        if ($listenerPath = $resource->getConfigResourcePath('config/listener')) {
80
            $this->application->loadEvent($listenerPath);
81
        }
82
    }
83
84
    public function loadVendorIfExist()
85
    {
86
        $vendorAutoload = $this->application->getPath() . '/vendor/autoload.php';
87
        if (FileSystem::exist($vendorAutoload)) {
88
            require_once $vendorAutoload;
89
        }
90
    }
91
92
    /**
93
     * @throws SQLException
94
     */
95
    public function loadDataSource()
96
    {
97
        Database::loadApplication($this->application);
98
        $dataSource = Database::getDefaultDataSource();
99
        $this->application->setDataSource($dataSource);
100
    }
101
102
103
    protected function prepareModule()
104
    {
105
        foreach ($this->application->getModules()->all() as $name => $module) {
106
            $this->moduleLoader[$name] = new ModuleLoader($this->application, $module);
107
            $this->moduleLoader[$name]->toLoad();
108
            $this->moduleLoader[$name]->loadExtraModuleResourceLibrary();
109
        }
110
    }
111
112
    protected function activeModule()
113
    {
114
        foreach ($this->application->getModules()->all() as $name => $module) {
115
            if ($module->getStatus() !== Module::LOADED) {
116
                $this->moduleLoader[$name]->toActive();
117
            }
118
        }
119
    }
120
121
    protected function registerModule()
122
    {
123
        $extractPath = $this->application->getDataPath() . '/extract-module';
124
        FileSystem::make($extractPath);
125
        foreach ($this->application->getModulePaths() as $path) {
126
            $this->registerModuleFrom($path, $extractPath);
127
        }
128
    }
129
130
    protected function setModuleStatus()
131
    {
132
        $active = $this->application->getManifest('module.active', $this->actionableModules);
133
        $reachable = $this->application->getManifest('module.reachable', $this->reachableModules);
134
        $this->setModuleActive($this->application->getModules(), $active);
135
        $this->setModuleReachable($this->application->getModules(), $reachable);
136
    }
137
138
    protected function registerModuleFrom(string $path, string $extractPath)
139
    {
140
        $modules = new ModuleBag;
141
        foreach (ModuleBuilder::scan($path, $extractPath) as $module) {
142
            $modules->add($module);
143
        }
144
        $this->prepareModuleConfig($path, $modules);
145
    }
146
147
    protected function prepareModuleConfig(string $path, ModuleBag $modules)
148
    {
149
        $config = $this->getModuleDirectoryConfig($path);
150
        $moduleNames = array_keys($modules->all());
151
        // 获取模块文件夹模块配置
152
        $load = $config['load'] ?? $moduleNames;
153
        $active = $config['active'] ?? $load;
154
        $reachable = $config['reachable'] ?? $active;
155
        // 获取允许加载的模块
156
        $load = $this->application->getManifest('module.load', $load);
157
        $this->loadModuleFromBag($modules, $load);
158
        $this->actionableModules = array_merge($this->actionableModules, $active);
159
        $this->reachableModules = array_merge($this->reachableModules, $reachable);
160
    }
161
162
    /**
163
     * @param string $path
164
     * @return array
165
     */
166
    protected function getModuleDirectoryConfig(string $path)
167
    {
168
        $resource = new Resource([$path]);
169
        $configPath = $resource->getConfigResourcePath('config');
170
        if ($configPath) {
171
            return Config::loadConfig($configPath, $this->application->getConfig()) ?? [];
172
        }
173
        return [];
174
    }
175
176
    protected function loadModuleFromBag(ModuleBag $bag, array $load)
177
    {
178
        foreach ($load as $moduleName) {
179
            if ($module = $bag->get($moduleName)) {
180
                $module->setStatus(Module::LOADED);
181
                $this->application->add($module);
182
            }
183
        }
184
    }
185
186
    protected function setModuleActive(ModuleBag $bag, array $active)
187
    {
188
        foreach ($active as $moduleName) {
189
            if ($module = $bag->get($moduleName)) {
190
                $module->setStatus(Module::ACTIVE);
191
            }
192
        }
193
    }
194
195
    protected function setModuleReachable(ModuleBag $bag, array $reachable)
196
    {
197
        foreach ($reachable as $moduleName) {
198
            if ($module = $bag->get($moduleName)) {
199
                $module->setStatus(Module::REACHABLE);
200
            }
201
        }
202
    }
203
}
204