Passed
Push — 5.2 ( 7d4140...dee498 )
by liu
02:46
created

App   F

Complexity

Total Complexity 104

Size/Duplication

Total Lines 759
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 193
dl 0
loc 759
rs 2
c 0
b 0
f 0
wmc 104

43 Methods

Rating   Name   Duplication   Size   Complexity  
A autoMulti() 0 7 1
A isAutoMulti() 0 3 1
A isMulti() 0 3 1
A multi() 0 4 1
A __construct() 0 9 3
A getName() 0 3 2
A debug() 0 4 1
A getRootNamespace() 0 3 1
A getBeginMem() 0 3 1
A getConfigExt() 0 3 1
A getAppPath() 0 3 2
A bootService() 0 4 2
A register() 0 17 5
A name() 0 4 1
A isDebug() 0 3 1
A defaultApp() 0 4 1
A getNamespace() 0 3 1
A getRuntimePath() 0 3 2
A getConfigPath() 0 3 1
A getThinkPath() 0 3 1
A getBasePath() 0 3 1
A getBeginTime() 0 3 1
A version() 0 3 1
A withEvent() 0 4 1
A getRootPath() 0 3 1
A setNamespace() 0 4 1
A setRootNamespace() 0 4 1
A getService() 0 6 2
A runningInConsole() 0 3 2
A parseName() 0 10 3
A factory() 0 9 3
A serialize() 0 7 1
B initialize() 0 44 7
A boot() 0 4 1
A parseClass() 0 8 2
F load() 0 57 18
A loadEvent() 0 12 4
A getDefaultRootPath() 0 5 1
B parseAppName() 0 22 10
A debugModeInit() 0 17 6
A getScriptName() 0 9 4
A classBaseName() 0 4 2
A unserialize() 0 7 1

How to fix   Complexity   

Complex Class

Complex classes like App often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use App, and based on these observations, apply Extract Interface, too.

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\exception\HttpException;
18
use think\initializer\BootService;
19
use think\initializer\Error;
20
use think\initializer\RegisterService;
21
22
/**
23
 * App 基础类
24
 * @property Route                 $route
25
 * @property Config                $config
26
 * @property Cache                 $cache
27
 * @property Request               $request
28
 * @property Http                  $http
29
 * @property Console               $console
30
 * @property Env                   $env
31
 * @property Debug                 $debug
32
 * @property Event                 $event
33
 * @property Middleware            $middleware
34
 * @property Log                   $log
35
 * @property Lang                  $lang
36
 * @property Db                    $db
37
 * @property Cookie                $cookie
38
 * @property Session               $session
39
 * @property Url                   $url
40
 * @property Validate              $validate
41
 * @property Build                 $build
42
 * @property \think\route\RuleName $rule_name
43
 */
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...
44
class App extends Container
45
{
46
    const VERSION = '5.2.0RC1';
47
48
    /**
49
     * 是否多应用模式
50
     * @var bool
51
     */
52
    protected $multi = false;
53
54
    /**
55
     * 是否自动多应用
56
     * @var bool
57
     */
58
    protected $auto = false;
59
60
    /**
61
     * 默认应用名(多应用模式)
62
     * @var string
63
     */
64
    protected $defaultApp = 'index';
65
66
    /**
67
     * 应用名称
68
     * @var string
69
     */
70
    protected $name;
71
72
    /**
73
     * 应用调试模式
74
     * @var bool
75
     */
76
    protected $appDebug = true;
77
78
    /**
79
     * 应用映射
80
     * @var array
81
     */
82
    protected $map = [];
83
84
    /**
85
     * 应用开始时间
86
     * @var float
87
     */
88
    protected $beginTime;
89
90
    /**
91
     * 应用内存初始占用
92
     * @var integer
93
     */
94
    protected $beginMem;
95
96
    /**
97
     * 应用类库顶级命名空间
98
     * @var string
99
     */
100
    protected $rootNamespace = 'app';
101
102
    /**
103
     * 当前应用类库命名空间
104
     * @var string
105
     */
106
    protected $namespace = '';
107
108
    /**
109
     * 应用根目录
110
     * @var string
111
     */
112
    protected $rootPath = '';
113
114
    /**
115
     * 框架目录
116
     * @var string
117
     */
118
    protected $thinkPath = '';
119
120
    /**
121
     * 配置后缀
122
     * @var string
123
     */
124
    protected $configExt = '.php';
125
126
    /**
127
     * 是否需要事件响应
128
     * @var bool
129
     */
130
    protected $withEvent = true;
131
132
    /**
133
     * 应用初始化器
134
     * @var array
135
     */
136
    protected static $initializers = [
137
        Error::class,
138
        RegisterService::class,
139
        BootService::class,
140
    ];
141
142
    /**
143
     * 注册的系统服务
144
     * @var array
145
     */
146
    protected $services = [];
147
148
    /**
149
     * 架构方法
150
     * @access public
151
     * @param  string $rootPath 应用根目录
152
     */
153
    public function __construct(string $rootPath = '')
154
    {
155
        $this->thinkPath = dirname(__DIR__) . DIRECTORY_SEPARATOR;
156
        $this->rootPath  = $rootPath ? realpath($rootPath) . DIRECTORY_SEPARATOR : $this->getDefaultRootPath();
157
        $this->multi     = is_dir($this->getBasePath() . 'controller') ? false : true;
158
159
        static::setInstance($this);
160
161
        $this->instance('app', $this);
162
    }
163
164
    /**
165
     * 注册服务
166
     * @access public
167
     * @param  Service|string $service 服务
168
     * @param  bool           $force 强制重新注册
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
169
     * @return Service|null
170
     */
171
    public function register($service, bool $force = false)
172
    {
173
        $registered = $this->getService($service);
174
175
        if ($registered && !$force) {
176
            return $registered;
177
        }
178
179
        if (is_string($service)) {
180
            $service = new $service($this);
181
        }
182
183
        if (method_exists($service, 'register')) {
184
            $service->register();
185
        }
186
187
        $this->services[] = $service;
188
    }
189
190
    /**
191
     * 执行服务
192
     * @access public
193
     * @param  Service $service 服务
194
     * @return mixed
195
     */
196
    public function bootService(Service $service)
197
    {
198
        if (method_exists($service, 'boot')) {
199
            return $this->invoke([$service, 'boot']);
200
        }
201
    }
202
203
    /**
204
     * 获取服务
205
     * @param  string|Service $service
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
206
     * @return Service|null
207
     */
208
    public function getService($service)
209
    {
210
        $name = is_string($service) ? $service : get_class($service);
211
        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...
212
            return $value instanceof $name;
213
        }, 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...
214
    }
215
216
    /**
217
     * 自动多应用访问
218
     * @access public
219
     * @param  array $map 应用路由映射
220
     * @return $this
221
     */
222
    public function autoMulti(array $map = [])
223
    {
224
        $this->multi = true;
225
        $this->auto  = true;
226
        $this->map   = $map;
227
228
        return $this;
229
    }
230
231
    /**
232
     * 是否为自动多应用模式
233
     * @access public
234
     * @return bool
235
     */
236
    public function isAutoMulti(): bool
237
    {
238
        return $this->auto;
239
    }
240
241
    /**
242
     * 设置应用模式
243
     * @access public
244
     * @param  bool $multi
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
245
     * @return $this
246
     */
247
    public function multi(bool $multi)
248
    {
249
        $this->multi = $multi;
250
        return $this;
251
    }
252
253
    /**
254
     * 是否为多应用模式
255
     * @access public
256
     * @return bool
257
     */
258
    public function isMulti(): bool
259
    {
260
        return $this->multi;
261
    }
262
263
    /**
264
     * 设置默认应用(对多应用有效)
265
     * @access public
266
     * @param  string $name 应用名
267
     * @return $this
268
     */
269
    public function defaultApp(string $name)
270
    {
271
        $this->defaultApp = $name;
272
        return $this;
273
    }
274
275
    /**
276
     * 设置是否使用事件机制
277
     * @access public
278
     * @param  bool $event
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
279
     * @return $this
280
     */
281
    public function withEvent(bool $event)
282
    {
283
        $this->withEvent = $event;
284
        return $this;
285
    }
286
287
    /**
288
     * 开启应用调试模式
289
     * @access public
290
     * @param  bool $debug 开启应用调试模式
291
     * @return $this
292
     */
293
    public function debug(bool $debug = true)
294
    {
295
        $this->appDebug = $debug;
296
        return $this;
297
    }
298
299
    /**
300
     * 是否为调试模式
301
     * @access public
302
     * @return bool
303
     */
304
    public function isDebug(): bool
305
    {
306
        return $this->appDebug;
307
    }
308
309
    /**
310
     * 设置应用名称
311
     * @access public
312
     * @param  string $name 应用名称
313
     * @return $this
314
     */
315
    public function name(string $name)
316
    {
317
        $this->name = $name;
318
        return $this;
319
    }
320
321
    /**
322
     * 设置应用命名空间
323
     * @access public
324
     * @param  string $namespace 应用命名空间
325
     * @return $this
326
     */
327
    public function setNamespace(string $namespace)
328
    {
329
        $this->namespace = $namespace;
330
        return $this;
331
    }
332
333
    /**
334
     * 设置应用根命名空间
335
     * @access public
336
     * @param  string $rootNamespace 应用命名空间
337
     * @return $this
338
     */
339
    public function setRootNamespace(string $rootNamespace)
340
    {
341
        $this->rootNamespace = $rootNamespace;
342
        return $this;
343
    }
344
345
    /**
346
     * 获取框架版本
347
     * @access public
348
     * @return string
349
     */
350
    public function version(): string
351
    {
352
        return static::VERSION;
353
    }
354
355
    /**
356
     * 获取应用名称
357
     * @access public
358
     * @return string
359
     */
360
    public function getName(): string
361
    {
362
        return $this->name ?: '';
363
    }
364
365
    /**
366
     * 获取应用根目录
367
     * @access public
368
     * @return string
369
     */
370
    public function getRootPath(): string
371
    {
372
        return $this->rootPath;
373
    }
374
375
    /**
376
     * 获取应用基础目录
377
     * @access public
378
     * @return string
379
     */
380
    public function getBasePath(): string
381
    {
382
        return $this->rootPath . 'app' . DIRECTORY_SEPARATOR;
383
    }
384
385
    /**
386
     * 获取当前应用目录
387
     * @access public
388
     * @return string
389
     */
390
    public function getAppPath(): string
391
    {
392
        return $this->getBasePath() . ($this->multi ? $this->name . DIRECTORY_SEPARATOR : '');
393
    }
394
395
    /**
396
     * 获取应用运行时目录
397
     * @access public
398
     * @return string
399
     */
400
    public function getRuntimePath(): string
401
    {
402
        return $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR . ($this->multi ? $this->name . DIRECTORY_SEPARATOR : '');
403
    }
404
405
    /**
406
     * 获取核心框架目录
407
     * @access public
408
     * @return string
409
     */
410
    public function getThinkPath(): string
411
    {
412
        return $this->thinkPath;
413
    }
414
415
    /**
416
     * 获取应用配置目录
417
     * @access public
418
     * @return string
419
     */
420
    public function getConfigPath(): string
421
    {
422
        return $this->rootPath . 'config' . DIRECTORY_SEPARATOR;
423
    }
424
425
    /**
426
     * 获取配置后缀
427
     * @access public
428
     * @return string
429
     */
430
    public function getConfigExt(): string
431
    {
432
        return $this->configExt;
433
    }
434
435
    /**
436
     * 获取应用类基础命名空间
437
     * @access public
438
     * @return string
439
     */
440
    public function getRootNamespace(): string
441
    {
442
        return $this->rootNamespace;
443
    }
444
445
    /**
446
     * 获取应用类库命名空间
447
     * @access public
448
     * @return string
449
     */
450
    public function getNamespace(): string
451
    {
452
        return $this->namespace;
453
    }
454
455
    /**
456
     * 获取应用开启时间
457
     * @access public
458
     * @return float
459
     */
460
    public function getBeginTime(): float
461
    {
462
        return $this->beginTime;
463
    }
464
465
    /**
466
     * 获取应用初始内存占用
467
     * @access public
468
     * @return integer
469
     */
470
    public function getBeginMem(): int
471
    {
472
        return $this->beginMem;
473
    }
474
475
    /**
476
     * 初始化应用
477
     * @access public
478
     * @return $this
479
     */
480
    public function initialize()
481
    {
482
        $this->beginTime = microtime(true);
483
        $this->beginMem  = memory_get_usage();
484
485
        //加载环境变量
486
        if (is_file($this->rootPath . '.env')) {
487
            $this->env->load($this->rootPath . '.env');
488
        }
489
490
        $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...
491
492
        $this->parseAppName();
493
494
        if (!$this->namespace) {
495
            $this->namespace = $this->multi ? $this->rootNamespace . '\\' . $this->name : $this->rootNamespace;
496
        }
497
498
        // 加载初始化文件
499
        if (is_file($this->getRuntimePath() . 'init.php')) {
500
            //直接加载缓存
501
            include $this->getRuntimePath() . 'init.php';
502
        } else {
503
            $this->load();
504
        }
505
506
        $this->request->setApp($this->name ?: '');
507
508
        // 设置开启事件机制
509
        $this->event->withEvent($this->withEvent);
510
511
        // 监听AppInit
512
        $this->event->trigger('AppInit');
513
514
        $this->debugModeInit();
515
516
        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

516
        date_default_timezone_set(/** @scrutinizer ignore-type */ $this->config->get('app.default_timezone', 'Asia/Shanghai'));
Loading history...
517
518
        // 初始化
519
        foreach (self::$initializers as $initializer) {
520
            $this->make($initializer)->init($this);
521
        }
522
523
        return $this;
524
    }
525
526
    /**
527
     * 引导应用
528
     * @access public
529
     * @return void
530
     */
531
    public function boot(): void
532
    {
533
        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...
534
            $this->bootService($service);
535
        });
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...
536
    }
537
538
    /**
539
     * 加载应用文件和配置
540
     * @access protected
541
     * @return void
542
     */
543
    protected function load(): void
544
    {
545
        $basePath = $this->getBasePath();
546
        $appPath  = $this->getAppPath();
547
548
        if ($this->multi && is_file($basePath . 'common.php')) {
549
            include_once $basePath . 'common.php';
550
        }
551
552
        if (is_file($appPath . 'common.php')) {
553
            include_once $appPath . 'common.php';
554
        }
555
556
        include $this->thinkPath . 'helper.php';
557
558
        $configPath = $this->getConfigPath();
559
560
        $files = [];
561
562
        if (is_dir($configPath)) {
563
            $files = glob($configPath . '*' . $this->configExt);
564
        }
565
566
        if ($this->multi) {
567
            if (is_dir($appPath . 'config')) {
568
                $files = array_merge($files, glob($appPath . 'config' . DIRECTORY_SEPARATOR . '*' . $this->configExt));
569
            } elseif (is_dir($configPath . $this->name)) {
570
                $files = array_merge($files, glob($configPath . $this->name . DIRECTORY_SEPARATOR . '*' . $this->configExt));
571
            }
572
        }
573
574
        foreach ($files as $file) {
575
            $this->config->load($file, pathinfo($file, PATHINFO_FILENAME));
576
        }
577
578
        if ($this->multi && is_file($basePath . 'event.php')) {
579
            $this->loadEvent(include $basePath . 'event.php');
580
        }
581
582
        if (is_file($appPath . 'event.php')) {
583
            $this->loadEvent(include $appPath . 'event.php');
584
        }
585
586
        if ($this->multi && is_file($basePath . 'middleware.php')) {
587
            $this->middleware->import(include $basePath . 'middleware.php');
588
        }
589
590
        if (is_file($appPath . 'middleware.php')) {
591
            $this->middleware->import(include $appPath . 'middleware.php');
592
        }
593
594
        if ($this->multi && is_file($basePath . 'provider.php')) {
595
            $this->bind(include $basePath . 'provider.php');
596
        }
597
598
        if (is_file($appPath . 'provider.php')) {
599
            $this->bind(include $appPath . 'provider.php');
600
        }
601
    }
602
603
    /**
604
     * 调试模式设置
605
     * @access protected
606
     * @return void
607
     */
608
    protected function debugModeInit(): void
609
    {
610
        // 应用调试模式
611
        if (!$this->appDebug) {
612
            $this->appDebug = $this->env->get('app_debug', false);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->env->get('app_debug', false) can also be of type string. However, the property $appDebug is declared as type boolean. 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...
613
        }
614
615
        if (!$this->appDebug) {
616
            ini_set('display_errors', 'Off');
617
        } elseif (!$this->runningInConsole()) {
618
            //重新申请一块比较大的buffer
619
            if (ob_get_level() > 0) {
620
                $output = ob_get_clean();
621
            }
622
            ob_start();
623
            if (!empty($output)) {
624
                echo $output;
625
            }
626
        }
627
    }
628
629
    /**
630
     * 注册应用事件
631
     * @access protected
632
     * @param  array $event 事件数据
633
     * @return void
634
     */
635
    protected function loadEvent(array $event): void
636
    {
637
        if (isset($event['bind'])) {
638
            $this->event->bind($event['bind']);
639
        }
640
641
        if (isset($event['listen'])) {
642
            $this->event->listenEvents($event['listen']);
643
        }
644
645
        if (isset($event['subscribe'])) {
646
            $this->event->subscribe($event['subscribe']);
647
        }
648
    }
649
650
    /**
651
     * 解析应用类的类名
652
     * @access public
653
     * @param  string $layer 层名 controller model ...
654
     * @param  string $name  类名
655
     * @return string
656
     */
657
    public function parseClass(string $layer, string $name): string
658
    {
659
        $name  = str_replace(['/', '.'], '\\', $name);
660
        $array = explode('\\', $name);
661
        $class = self::parseName(array_pop($array), 1);
662
        $path  = $array ? implode('\\', $array) . '\\' : '';
663
664
        return $this->namespace . '\\' . $layer . '\\' . $path . $class;
665
    }
666
667
    /**
668
     * 是否运行在命令行下
669
     * @return bool
670
     */
671
    public function runningInConsole()
672
    {
673
        return php_sapi_name() === 'cli' || php_sapi_name() === 'phpdbg';
674
    }
675
676
    /**
677
     * 分析当前请求的应用名
678
     * @access protected
679
     * @return void
680
     */
681
    protected function parseAppName(): void
682
    {
683
        if (!$this->runningInConsole()) {
684
            if ($this->auto) {
685
                // 自动多应用识别
686
                $path = $this->request->pathinfo();
687
                unset($this->request);
688
                $name = current(explode('/', $path));
689
690
                if (isset($this->map[$name])) {
691
                    if ($this->map[$name] instanceof \Closure) {
692
                        call_user_func_array($this->map[$name], [$this]);
693
                    } else {
694
                        $this->name = $this->map[$name];
695
                    }
696
                } elseif ($name && false !== array_search($name, $this->map)) {
697
                    throw new HttpException(404, 'app not exists:' . $name);
698
                } else {
699
                    $this->name = $name ?: $this->defaultApp;
700
                }
701
            } elseif ($this->multi) {
702
                $this->name = $this->name ?: $this->getScriptName();
703
            }
704
705
        }
706
    }
707
708
    /**
709
     * 获取当前运行入口名称
710
     * @access protected
711
     * @return string
712
     */
713
    protected function getScriptName(): string
714
    {
715
        if (isset($_SERVER['SCRIPT_FILENAME'])) {
716
            $file = $_SERVER['SCRIPT_FILENAME'];
717
        } elseif (isset($_SERVER['argv'][0])) {
718
            $file = realpath($_SERVER['argv'][0]);
719
        }
720
721
        return isset($file) ? pathinfo($file, PATHINFO_FILENAME) : $this->defaultApp;
722
    }
723
724
    /**
725
     * 获取应用根目录
726
     * @access protected
727
     * @return string
728
     */
729
    protected function getDefaultRootPath(): string
730
    {
731
        $path = dirname(dirname(dirname(dirname($this->thinkPath))));
732
733
        return $path . DIRECTORY_SEPARATOR;
734
    }
735
736
    /**
737
     * 字符串命名风格转换
738
     * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
739
     * @access public
740
     * @param  string  $name    字符串
741
     * @param  integer $type    转换类型
742
     * @param  bool    $ucfirst 首字母是否大写(驼峰规则)
743
     * @return string
744
     */
745
    public static function parseName(string $name = null, int $type = 0, bool $ucfirst = true): string
746
    {
747
        if ($type) {
748
            $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...
749
                return strtoupper($match[1]);
750
            }, $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...
751
            return $ucfirst ? ucfirst($name) : lcfirst($name);
752
        }
753
754
        return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
755
    }
756
757
    /**
758
     * 获取类名(不包含命名空间)
759
     * @access public
760
     * @param  string|object $class
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
761
     * @return string
762
     */
763
    public static function classBaseName($class): string
764
    {
765
        $class = is_object($class) ? get_class($class) : $class;
766
        return basename(str_replace('\\', '/', $class));
767
    }
768
769
    /**
0 ignored issues
show
Coding Style introduced by
Parameter ...$args should have a doc-comment as per coding-style.
Loading history...
770
     * 创建工厂对象实例
771
     * @access public
772
     * @param  string $name      工厂类名
773
     * @param  string $namespace 默认命名空间
774
     * @return mixed
775
     */
776
    public static function factory(string $name, string $namespace = '', ...$args)
777
    {
778
        $class = false !== strpos($name, '\\') ? $name : $namespace . ucwords($name);
779
780
        if (class_exists($class)) {
781
            return Container::getInstance()->invokeClass($class, $args);
782
        }
783
784
        throw new ClassNotFoundException('class not exists:' . $class, $class);
785
    }
786
787
    public static function serialize($data): string
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
788
    {
789
        SerializableClosure::enterContext();
790
        SerializableClosure::wrapClosures($data);
791
        $data = \serialize($data);
792
        SerializableClosure::exitContext();
793
        return $data;
794
    }
795
796
    public static function unserialize(string $data)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
797
    {
798
        SerializableClosure::enterContext();
799
        $data = \unserialize($data);
800
        SerializableClosure::unwrapClosures($data);
801
        SerializableClosure::exitContext();
802
        return $data;
803
    }
804
}
805