Test Failed
Push — dev ( e79643...3785bc )
by 世昌
04:25
created

ApplicationLoader::loadRouteFromModules()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 0
dl 0
loc 6
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\Application;
8
use suda\application\ApplicationModule;
9
10
/**
11
 * 应用程序
12
 */
13
class ApplicationLoader extends ApplicationBaseLoader
14
{
15
16
    const CACHE_ROUTE = 'application-route';
17
    const CACHE_ROUTE_RUNNABLE = 'application-route-runnable';
18
19
    /**
20
     * @var Application
21
     */
22
    protected $application;
23
24
    /**
25
     * ApplicationLoader constructor.
26
     * @param Application $application
27
     */
28
    public function __construct(Application $application)
29
    {
30
        parent::__construct($application);
31
    }
32
33
    /**
34
     * 加载路由
35
     */
36
    public function loadRoute()
37
    {
38
        $name = 'application-route';
39
        $this->application->debug()->time($name);
40
        if (static::isDebug()) {
41
            $this->setRouteCache();
42
        } elseif ($this->routeCacheAvailable()) {
43
            $route = $this->application->cache()->get(ApplicationLoader::CACHE_ROUTE);
44
            $runnable = $this->application->cache()->get(ApplicationLoader::CACHE_ROUTE_RUNNABLE);
45
            $this->application->getRoute()->setRouteCollection($route);
46
            $this->application->getRoute()->setRunnable($runnable);
47
            $this->application->debug()->info('load route from cache');
48
        } else {
49
            $this->loadRouteFromModules();
50
        }
51
        $this->application->debug()->timeEnd($name);
52
    }
53
54
    /**
55
     * 设置路由缓存
56
     */
57
    private function setRouteCache() {
58
        $this->application->cache()->delete(ApplicationLoader::CACHE_ROUTE);
59
        $this->application->cache()->delete(ApplicationLoader::CACHE_ROUTE_RUNNABLE);
60
        $this->application->debug()->info('delete route cache');
61
        $this->loadRouteFromModules();
62
        if ($this->application->getRoute()->isContainClosure()) {
63
            $this->application->debug()->warning('route contain closure, route prepare cannot be cacheables');
64
        } else {
65
            $this->application->cache()->set(ApplicationLoader::CACHE_ROUTE, $this->application->getRoute()->getRouteCollection());
66
            $this->application->cache()->set(ApplicationLoader::CACHE_ROUTE_RUNNABLE, $this->application->getRoute()->getRunnable());
67
            $this->application->debug()->info('set route cache');
68
        }
69
    }
70
71
    /**
72
     * 从模块中加载路由
73
     */
74
    private function loadRouteFromModules()
75
    {
76
        foreach ($this->application->getModules() as $name => $module) {
77
            if ($module->getStatus() === Module::REACHABLE) {
78
                $this->loadModuleRoute($module);
79
                $this->application->debug()->debug('reachable # ' . $module->getFullName());
80
            }
81
        }
82
    }
83
84
    /**
85
     * @return bool
86
     */
87
    private function routeCacheAvailable()
88
    {
89
        return $this->application->cache()->has(ApplicationLoader::CACHE_ROUTE)
90
            && $this->application->cache()->has(ApplicationLoader::CACHE_ROUTE_RUNNABLE);
91
    }
92
93
    /**
94
     * 加载路由
95
     * @param Module $module
96
     */
97
    protected function loadModuleRoute(Module $module)
98
    {
99
        foreach ($this->application->getRouteGroup() as $group) {
100
            $this->loadRouteGroup($module, $group);
101
        }
102
    }
103
104
    /**
105
     * 加载路由组
106
     *
107
     * @param Module $module
108
     * @param string $groupName
109
     * @return void
110
     */
111
    protected function loadRouteGroup(Module $module, string $groupName)
112
    {
113
        $group = $groupName === 'default' ? '' : '-' . $groupName;
114
        if ($path = $module->getResource()->getConfigResourcePath('config/route' . $group)) {
115
            $routeConfig = Config::loadConfig($path, [
116
                'module' => $module->getName(),
117
                'group' => $groupName,
118
                'property' => $module->getProperty(),
119
                'config' => $module->getConfig(),
120
            ]);
121
            if ($routeConfig !== null) {
122
                $prefix = $module->getConfig('route-prefix.' . $groupName, '');
123
                $this->loadRouteConfig($module, $prefix, $groupName, $routeConfig);
124
            }
125
        }
126
    }
127
128
    /**
129
     * 加载模块路由配置
130
     *
131
     * @param Module $module
132
     * @param string $prefix
133
     * @param string $groupName
134
     * @param array $routeConfig
135
     * @return void
136
     */
137
    protected function loadRouteConfig(Module $module, string $prefix, string $groupName, array $routeConfig)
138
    {
139
        $module = $module->getFullName();
140
        foreach ($routeConfig as $name => $config) {
141
            $exname = $this->application->getRouteName($name, $module, $groupName);
142
            $method = $config['method'] ?? [];
143
            $attributes = [];
144
            $attributes['module'] = $module;
145
            $attributes['config'] = $config;
146
            $attributes['group'] = $groupName;
147
            $attributes['route'] = $exname;
148
            $uri = $config['uri'] ?? '/';
149
            $anti = array_key_exists('anti-prefix', $config) && $config['anti-prefix'];
150
            if ($anti) {
151
                $uri = '/' . trim($uri, '/');
152
            } else {
153
                $uri = '/' . trim($prefix . $uri, '/');
154
            }
155
            $this->application->request($method, $exname, $uri, $attributes);
156
        }
157
    }
158
}
159