Completed
Push — 6.0 ( d1e6bc...ccb086 )
by liu
03:41
created

App::debugModeInit()   A

Complexity

Conditions 6
Paths 15

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 10.5

Importance

Changes 0
Metric Value
cc 6
eloc 9
nc 15
nop 0
dl 0
loc 16
ccs 5
cts 10
cp 0.5
crap 10.5
rs 9.2222
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
use Opis\Closure\SerializableClosure;
16
use think\exception\ClassNotFoundException;
17
use think\initializer\BootService;
18
use think\initializer\Error;
19
use think\initializer\RegisterService;
20
21
/**
22
 * App 基础类
23
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
24
class App extends Container
25
{
26
    const VERSION = '6.0.0RC2';
27
28
    /**
29
     * 应用调试模式
30
     * @var bool
31
     */
32
    protected $appDebug = true;
33
34
    /**
35
     * 应用开始时间
36
     * @var float
37
     */
38
    protected $beginTime;
39
40
    /**
41
     * 应用内存初始占用
42
     * @var integer
43
     */
44
    protected $beginMem;
45
46
    /**
47
     * 当前应用类库命名空间
48
     * @var string
49
     */
50
    protected $namespace = 'app';
51
52
    /**
53
     * 应用根目录
54
     * @var string
55
     */
56
    protected $rootPath = '';
57
58
    /**
59
     * 框架目录
60
     * @var string
61
     */
62
    protected $thinkPath = '';
63
64
    /**
65
     * 应用目录
66
     * @var string
67
     */
68
    protected $appPath = '';
69
70
    /**
71
     * Runtime目录
72
     * @var string
73
     */
74
    protected $runtimePath = '';
75
76
    /**
77
     * 配置后缀
78
     * @var string
79
     */
80
    protected $configExt = '.php';
81
82
    /**
83
     * 应用初始化器
84
     * @var array
85
     */
86
    protected $initializers = [
87
        Error::class,
88
        RegisterService::class,
89
        BootService::class,
90
    ];
91
92
    /**
93
     * 注册的系统服务
94
     * @var array
95
     */
96
    protected $services = [];
97
98
    /**
99
     * 初始化
100
     * @var bool
101
     */
102
    protected $initialized = false;
103
104
    /**
105
     * 架构方法
106
     * @access public
107
     * @param string $rootPath 应用根目录
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
108
     */
109 18
    public function __construct(string $rootPath = '')
110
    {
111 18
        $this->thinkPath   = dirname(__DIR__) . DIRECTORY_SEPARATOR;
112 18
        $this->rootPath    = $rootPath ? rtrim($rootPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : $this->getDefaultRootPath();
113 18
        $this->appPath     = $this->rootPath . 'app' . DIRECTORY_SEPARATOR;
114 18
        $this->runtimePath = $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR;
115
116 18
        static::setInstance($this);
117
118 18
        $this->instance('app', $this);
119 18
        $this->instance('think\Container', $this);
120 18
    }
121
122
    /**
123
     * 注册服务
124
     * @access public
125
     * @param Service|string $service 服务
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
126
     * @param bool           $force   强制重新注册
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
127
     * @return Service|null
128
     */
129 1
    public function register($service, bool $force = false)
130
    {
131 1
        $registered = $this->getService($service);
132
133 1
        if ($registered && !$force) {
134 1
            return $registered;
135
        }
136
137 1
        if (is_string($service)) {
138 1
            $service = new $service($this);
139
        }
140
141 1
        if (method_exists($service, 'register')) {
142 1
            $service->register();
143
        }
144
145 1
        if (property_exists($service, 'bind')) {
146 1
            $this->bind($service->bind);
147
        }
148
149 1
        $this->services[] = $service;
150 1
    }
151
152
    /**
153
     * 执行服务
154
     * @access public
155
     * @param Service $service 服务
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
156
     * @return mixed
157
     */
158 1
    public function bootService($service)
159
    {
160 1
        if (method_exists($service, 'boot')) {
161 1
            return $this->invoke([$service, 'boot']);
162
        }
163 1
    }
164
165
    /**
166
     * 获取服务
167
     * @param string|Service $service
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
168
     * @return Service|null
169
     */
170 1
    public function getService($service)
171
    {
172 1
        $name = is_string($service) ? $service : get_class($service);
173
        return array_values(array_filter($this->services, function ($value) use ($name) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
174 1
            return $value instanceof $name;
175 1
        }, ARRAY_FILTER_USE_BOTH))[0] ?? null;
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
176
    }
177
178
    /**
179
     * 开启应用调试模式
180
     * @access public
181
     * @param bool $debug 开启应用调试模式
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
182
     * @return $this
183
     */
184 2
    public function debug(bool $debug = true)
185
    {
186 2
        $this->appDebug = $debug;
187 2
        return $this;
188
    }
189
190
    /**
191
     * 是否为调试模式
192
     * @access public
193
     * @return bool
194
     */
195 7
    public function isDebug(): bool
196
    {
197 7
        return $this->appDebug;
198
    }
199
200
    /**
201
     * 设置应用命名空间
202
     * @access public
203
     * @param string $namespace 应用命名空间
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
204
     * @return $this
205
     */
206 7
    public function setNamespace(string $namespace)
207
    {
208 7
        $this->namespace = $namespace;
209 7
        return $this;
210
    }
211
212
    /**
213
     * 获取应用类库命名空间
214
     * @access public
215
     * @return string
216
     */
217 1
    public function getNamespace(): string
218
    {
219 1
        return $this->namespace;
220
    }
221
222
    /**
223
     * 获取框架版本
224
     * @access public
225
     * @return string
226
     */
227 1
    public function version(): string
228
    {
229 1
        return static::VERSION;
230
    }
231
232
    /**
233
     * 获取应用根目录
234
     * @access public
235
     * @return string
236
     */
237 1
    public function getRootPath(): string
238
    {
239 1
        return $this->rootPath;
240
    }
241
242
    /**
243
     * 获取应用基础目录
244
     * @access public
245
     * @return string
246
     */
247 10
    public function getBasePath(): string
248
    {
249 10
        return $this->rootPath . 'app' . DIRECTORY_SEPARATOR;
250
    }
251
252
    /**
253
     * 获取当前应用目录
254
     * @access public
255
     * @return string
256
     */
257 7
    public function getAppPath(): string
258
    {
259 7
        return $this->appPath;
260
    }
261
262
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $path should have a doc-comment as per coding-style.
Loading history...
263
     * 设置应用目录
264
     * @param $path
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
265
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
266 6
    public function setAppPath($path)
267
    {
268 6
        $this->appPath = $path;
269 6
    }
270
271
    /**
272
     * 获取应用运行时目录
273
     * @access public
274
     * @return string
275
     */
276 8
    public function getRuntimePath(): string
277
    {
278 8
        return $this->runtimePath;
279
    }
280
281
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $path should have a doc-comment as per coding-style.
Loading history...
282
     * 设置runtime目录
283
     * @param $path
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
284
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
285 6
    public function setRuntimePath($path)
286
    {
287 6
        $this->runtimePath = $path;
288 6
    }
289
290
    /**
291
     * 获取核心框架目录
292
     * @access public
293
     * @return string
294
     */
295 1
    public function getThinkPath(): string
296
    {
297 1
        return $this->thinkPath;
298
    }
299
300
    /**
301
     * 获取应用配置目录
302
     * @access public
303
     * @return string
304
     */
305 10
    public function getConfigPath(): string
306
    {
307 10
        return $this->rootPath . 'config' . DIRECTORY_SEPARATOR;
308
    }
309
310
    /**
311
     * 获取配置后缀
312
     * @access public
313
     * @return string
314
     */
315 9
    public function getConfigExt(): string
316
    {
317 9
        return $this->configExt;
318
    }
319
320
    /**
321
     * 获取应用开启时间
322
     * @access public
323
     * @return float
324
     */
325 1
    public function getBeginTime(): float
326
    {
327 1
        return $this->beginTime;
328
    }
329
330
    /**
331
     * 获取应用初始内存占用
332
     * @access public
333
     * @return integer
334
     */
335 1
    public function getBeginMem(): int
336
    {
337 1
        return $this->beginMem;
338
    }
339
340
    /**
341
     * 初始化应用
342
     * @access public
343
     * @return $this
344
     */
345 1
    public function initialize()
346
    {
347 1
        $this->initialized = true;
348
349 1
        $this->beginTime = microtime(true);
350 1
        $this->beginMem  = memory_get_usage();
351
352
        // 加载环境变量
353 1
        if (is_file($this->rootPath . '.env')) {
354 1
            $this->env->load($this->rootPath . '.env');
355
        }
356
357 1
        $this->configExt = $this->env->get('config_ext', '.php');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->env->get('config_ext', '.php') can also be of type boolean. However, the property $configExt is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
358
359
        // 加载全局初始化文件
360 1
        if (is_file($this->getRuntimePath() . 'init.php')) {
361
            //直接加载缓存
362
            include $this->getRuntimePath() . 'init.php';
363
        } else {
364 1
            $this->load();
365
        }
366
367 1
        $this->debugModeInit();
368
369
        // 监听AppInit
370 1
        $this->event->trigger('AppInit');
371
372 1
        date_default_timezone_set($this->config->get('app.default_timezone', 'Asia/Shanghai'));
0 ignored issues
show
Bug introduced by
It seems like $this->config->get('app....zone', 'Asia/Shanghai') can also be of type array and array; however, parameter $timezone_identifier of date_default_timezone_set() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

372
        date_default_timezone_set(/** @scrutinizer ignore-type */ $this->config->get('app.default_timezone', 'Asia/Shanghai'));
Loading history...
373
374
        // 初始化
375 1
        foreach ($this->initializers as $initializer) {
376 1
            $this->make($initializer)->init($this);
377
        }
378
379 1
        return $this;
380
    }
381
382
    /**
383
     * 是否初始化过
384
     * @return bool
385
     */
386 1
    public function initialized()
387
    {
388 1
        return $this->initialized;
389
    }
390
391
    /**
392
     * 引导应用
393
     * @access public
394
     * @return void
395
     */
396 1
    public function boot(): void
397
    {
398
        array_walk($this->services, function ($service) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
399 1
            $this->bootService($service);
400 1
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
401 1
    }
402
403
    /**
404
     * 加载应用文件和配置
405
     * @access protected
406
     * @return void
407
     */
408 1
    protected function load(): void
409
    {
410 1
        $appPath = $this->getAppPath();
411
412 1
        if (is_file($appPath . 'common.php')) {
413 1
            include_once $appPath . 'common.php';
414
        }
415
416 1
        include $this->thinkPath . 'helper.php';
417
418 1
        $configPath = $this->getConfigPath();
419
420 1
        $files = [];
421
422 1
        if (is_dir($configPath)) {
423 1
            $files = glob($configPath . '*' . $this->configExt);
424
        }
425
426 1
        foreach ($files as $file) {
427
            $this->config->load($file, pathinfo($file, PATHINFO_FILENAME));
428
        }
429
430 1
        if (is_file($appPath . 'event.php')) {
431 1
            $this->loadEvent(include $appPath . 'event.php');
432
        }
433
434 1
        if (is_file($appPath . 'provider.php')) {
435 1
            $this->bind(include $appPath . 'provider.php');
436
        }
437
438 1
        if (is_file($appPath . 'service.php')) {
439
            $services = include $appPath . 'service.php';
440
            foreach ($services as $service) {
441
                $this->register($service);
442
            }
443
        }
444 1
    }
445
446
    /**
447
     * 调试模式设置
448
     * @access protected
449
     * @return void
450
     */
451 1
    protected function debugModeInit(): void
452
    {
453
        // 应用调试模式
454 1
        if (!$this->appDebug) {
455 1
            $this->appDebug = $this->env->get('app_debug') ? true : false;
456 1
            ini_set('display_errors', 'Off');
457
        }
458
459 1
        if (!$this->runningInConsole()) {
460
            //重新申请一块比较大的buffer
461
            if (ob_get_level() > 0) {
462
                $output = ob_get_clean();
463
            }
464
            ob_start();
465
            if (!empty($output)) {
466
                echo $output;
467
            }
468
        }
469 1
    }
470
471
    /**
472
     * 注册应用事件
473
     * @access protected
474
     * @param array $event 事件数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
475
     * @return void
476
     */
477 2
    public function loadEvent(array $event): void
478
    {
479 2
        if (isset($event['bind'])) {
480 2
            $this->event->bind($event['bind']);
481
        }
482
483 2
        if (isset($event['listen'])) {
484 2
            $this->event->listenEvents($event['listen']);
485
        }
486
487 2
        if (isset($event['subscribe'])) {
488 2
            $this->event->subscribe($event['subscribe']);
489
        }
490 2
    }
491
492
    /**
493
     * 解析应用类的类名
494
     * @access public
495
     * @param string $layer 层名 controller model ...
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
496
     * @param string $name  类名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
497
     * @return string
498
     */
499 1
    public function parseClass(string $layer, string $name): string
500
    {
501 1
        $name  = str_replace(['/', '.'], '\\', $name);
502 1
        $array = explode('\\', $name);
503 1
        $class = self::parseName(array_pop($array), 1);
504 1
        $path  = $array ? implode('\\', $array) . '\\' : '';
505
506 1
        return $this->namespace . '\\' . $layer . '\\' . $path . $class;
507
    }
508
509
    /**
510
     * 是否运行在命令行下
511
     * @return bool
512
     */
513 1
    public function runningInConsole()
514
    {
515 1
        return php_sapi_name() === 'cli' || php_sapi_name() === 'phpdbg';
516
    }
517
518
    /**
519
     * 获取应用根目录
520
     * @access protected
521
     * @return string
522
     */
523 18
    protected function getDefaultRootPath(): string
524
    {
525 18
        $path = dirname(dirname(dirname(dirname($this->thinkPath))));
526
527 18
        return $path . DIRECTORY_SEPARATOR;
528
    }
529
530
    /**
531
     * 字符串命名风格转换
532
     * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
533
     * @access public
534
     * @param string  $name    字符串
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
535
     * @param integer $type    转换类型
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
536
     * @param bool    $ucfirst 首字母是否大写(驼峰规则)
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
537
     * @return string
538
     */
539 13
    public static function parseName(string $name = null, int $type = 0, bool $ucfirst = true): string
540
    {
541 13
        if ($type) {
542
            $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
543 2
                return strtoupper($match[1]);
544 2
            }, $name);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
545 2
            return $ucfirst ? ucfirst($name) : lcfirst($name);
546
        }
547
548 12
        return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
549
    }
550
551
    /**
552
     * 获取类名(不包含命名空间)
553
     * @access public
554
     * @param string|object $class
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
555
     * @return string
556
     */
557 1
    public static function classBaseName($class): string
558
    {
559 1
        $class = is_object($class) ? get_class($class) : $class;
560 1
        return basename(str_replace('\\', '/', $class));
561
    }
562
563
    /**
0 ignored issues
show
Coding Style introduced by
Parameter ...$args should have a doc-comment as per coding-style.
Loading history...
564
     * 创建工厂对象实例
565
     * @access public
566
     * @param string $name      工厂类名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
567
     * @param string $namespace 默认命名空间
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
568
     * @param array  $args
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $args does not match actual variable name ...$args
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
569
     * @return mixed
570
     */
571 1
    public static function factory(string $name, string $namespace = '', ...$args)
572
    {
573 1
        $class = false !== strpos($name, '\\') ? $name : $namespace . ucwords($name);
574
575 1
        if (class_exists($class)) {
576 1
            return Container::getInstance()->invokeClass($class, $args);
577
        }
578
579 1
        throw new ClassNotFoundException('class not exists:' . $class, $class);
580
    }
581
582
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $data should have a doc-comment as per coding-style.
Loading history...
583
     * @param $data
1 ignored issue
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 14 spaces but found 1
Loading history...
584
     * @codeCoverageIgnore
585
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 13 spaces but found 1
Loading history...
586
     */
587
    public static function serialize($data): string
588
    {
589
        SerializableClosure::enterContext();
590
        SerializableClosure::wrapClosures($data);
591
        $data = \serialize($data);
592
        SerializableClosure::exitContext();
593
        return $data;
594
    }
595
596
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
597
     * @param string $data
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 14 spaces but found 1
Loading history...
598
     * @codeCoverageIgnore
599
     * @return mixed|string
1 ignored issue
show
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 13 spaces but found 1
Loading history...
600
     */
601
    public static function unserialize(string $data)
602
    {
603
        SerializableClosure::enterContext();
604
        $data = \unserialize($data);
605
        SerializableClosure::unwrapClosures($data);
606
        SerializableClosure::exitContext();
607
        return $data;
608
    }
609
}
610