Passed
Push — 5.2 ( 8f25db...d9cbb6 )
by
unknown
03:07
created

App::boot()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

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