Passed
Push — master ( ae9c2c...ae009e )
by 世昌
01:41
created

NebulaApplication::run()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
namespace nebula;
3
4
use nebula\Context;
5
use nebula\application\Route;
6
use nebula\application\Debugger;
7
use nebula\component\loader\Path;
8
use nebula\application\Application;
9
use nebula\application\config\Config;
10
use nebula\component\request\Request;
11
use nebula\application\cache\FileCache;
12
use nebula\component\runnable\Runnable;
13
use nebula\application\filesystem\FileSystem;
14
use nebula\component\cacheable\CacheInterface;
15
use nebula\component\debug\log\AbstractLogger;
16
use nebula\component\debug\log\logger\FileLogger;
17
use nebula\component\debug\log\logger\NullLogger;
18
19
/**
20
 * 应用
21
 *
22
 */
23
class NebulaApplication extends Context
24
{
25
    /**
26
     * 应用路径
27
     *
28
     * @var string
29
     */
30
    protected $path;
31
32
    /**
33
     * 数据路径
34
     *
35
     * @var string
36
     */
37
    protected $dataPath;
38
39
    /**
40
     * 静态实例
41
     *
42
     * @var NebulaApplication
43
     */
44
    protected static $instance;
45
46
47
    /**
48
     * 获取实例化对象
49
     *
50
     * @param string $path
51
     * @return NebulaApplication
52
     */
53
    public static function configuration(string $path)
54
    {
55
        $nebula = static::instance();
56
        $nebula->path = $path;
57
        if (!FileSystem::exist($path)) {
58
            FileSystem::copyDir(NEBULA_RESOURCE.'/application', $path);
59
        }
60
        $config = new Config;
61
        $manifast = $config->loadConfig($path.'/manifast.json');
62
        $nebula->dataPath = Path::toAbsolutePath(defined('NEBULA_DATA') ? constant('NEBULA_DATA') : '~/nebula-data');
63
        $config->set('app', $manifast);
64
        $nebula->setConfig($config);
65
        return $nebula;
66
    }
67
    
68
    /**
69
     * 初始化操作
70
     *
71
     * @return void
72
     */
73
    public function initialization()
74
    {
75
        $this->setRoute(new Route($this));
76
        $this->initBaseConfig();
77
        $this->initTimezone();
78
        $this->initDebugger();
79
        $this->initCache();
80
        $this->getDebugger()->info('initialized nebula application');
81
    }
82
83
84
    /**
85
     * 初始化基本配置
86
     *
87
     * @return void
88
     */
89
    private function initBaseConfig()
90
    {
91
        $this->initConfigIfNotSet('app.route.active', defined('NEBULA_ROUTE_GROUPS')? \explode(',', \constant('NEBULA_ROUTE_GROUPS')) :['default']);
92
        $this->initConfigIfNotSet('app.import', [\constant('NEBULA_APP').'/'.'share']);
93
        $this->initConfigIfNotSet('app.resource', [\constant('NEBULA_APP').'/'.'resource']);
94
        $this->initConfigIfNotSet('app.module.scan-path', [\constant('NEBULA_APP').'/'.'modules']);
95
    }
96
97
    /**
98
     * 初始化配置值
99
     *
100
     * @param string $name
101
     * @param mixed $default
102
     * @return void
103
     */
104
    private function initConfigIfNotSet(string $name, $default)
105
    {
106
        if (!$this->config->has($name)) {
107
            $this->config->set($name, $default);
108
        }
109
    }
110
111
    /**
112
     * 初始化时区
113
     *
114
     * @return void
115
     */
116
    private function initTimezone()
117
    {
118
        $timezone = defined('DEFAULT_TIMEZONE')?constant('DEFAULT_TIMEZONE'):'PRC';
119
        date_default_timezone_set($this->config->get('app.timezone', $timezone));
120
    }
121
122
123
    /**
124
     * 初始化调试工具
125
     *
126
     * @return void
127
     */
128
    private function initDebugger()
129
    {
130
        $logger = (new Runnable($this->getConfig()->get('app.logger-build', [$this, 'buildLogger'])))->run();
131
        $debugger = new Debugger;
132
        
133
        $debugger->addAttribute('remote-ip', $this->getRequest()->ip());
134
        $debugger->addAttribute('request-uri', $this->getRequest()->getUrl());
135
        $debugger->addAttribute('request-method', $this->getRequest()->getMethod());
136
        $debugger->addAttribute('request-time', date('Y-m-d H:i:s', \constant('NEBULA_START_TIME')));
137
138
        $debugger->applyConfig([
139
            'start-time' => \constant('NEBULA_START_TIME'),
140
            'start-memory' => \constant('NEBULA_START_MEMORY'),
141
        ]);
142
        
143
        $debugger->setLogger($logger);
144
        $logger->notice(PHP_EOL.'{request-time} {remote-ip} {request-method} {request-uri}', $debugger->getAttribute());
145
        $this->setDebugger($debugger);
146
    }
147
148
    /**
149
     * 构建日志记录器
150
     *
151
     * @return AbstractLogger
152
     */
153
    private function buildLogger(): AbstractLogger
154
    {
155
        $dataPath = $this->dataPath.'/logs';
156
        if (\is_writable(dirname($dataPath))) {
157
            FileSystem::makes($dataPath.'/zip');
158
            FileSystem::makes($dataPath.'/dump');
159
            return new FileLogger(
160
                [
161
                    'log-level' => defined('NEBULA_DEBUG_LEVEL') ? defined('NEBULA_DEBUG_LEVEL') : 'debug',
162
                    'save-path' => $dataPath,
163
                    'save-zip-path' => $dataPath.'/zip',
164
                    'log-format' => '%message%',
165
                    'save-pack-path' => $dataPath.'/dump',
166
                ]
167
            );
168
        }
169
        return new NullLogger;
170
    }
171
172
    /**
173
     * 初始化缓存器
174
     *
175
     * @return void
176
     */
177
    private function initCache()
178
    {
179
        $cache = (new Runnable($this->getConfig()->get('app.cache-build', [$this, 'buildCache'])))->run();
180
        $this->cache = $cache;
181
    }
182
183
    /**
184
     * 构建文件缓存
185
     *
186
     * @return CacheInterface
187
     */
188
    private function buildCache(): CacheInterface
189
    {
190
        $dataPath = $this->dataPath.'/cache';
191
        FileSystem::makes($dataPath);
192
        return new FileCache($dataPath);
193
    }
194
195
    /**
196
     * 运行应用
197
     *
198
     * @return void
199
     */
200
    public function run()
201
    {
202
        $className  = $this->config->get('app.application', Application::class);
203
        $this->application = Runnable::newClassInstance($className);
204
        $this->application->setContext($this);
205
        $this->application->setPath($this->path);
206
        $this->application->setDataPath($this->dataPath);
207
        $this->application->initialization();
208
        $this->application->onRequest($this->getRequest());
209
        $this->getDebugger()->info('nebula application shutdown');
210
    }
211
212
    /**
213
     * Get 数据路径
214
     *
215
     * @return  string
216
     */
217
    public function getDataPath()
218
    {
219
        return $this->dataPath;
220
    }
221
222
    /**
223
     * Get 应用路径
224
     *
225
     * @return  string
226
     */
227
    public function getPath()
228
    {
229
        return $this->path;
230
    }
231
}
232