Passed
Push — master ( 2a29e8...d38419 )
by 世昌
01:50
created

MatchResult::getRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
namespace nebula\application\route;
3
4
use SplFileInfo;
5
use nebula\Context;
6
use ReflectionClass;
7
use nebula\application\Loader;
8
use nebula\application\Request;
9
use nebula\application\Resource;
10
use nebula\application\Response;
11
use nebula\component\runnable\Runnable;
12
use nebula\component\route\RouteMatcher;
13
use nebula\application\filesystem\FileSystem;
14
use nebula\application\response\Response as BaseResponse;
15
16
/**
17
 * 匹配结果
18
 */
19
class MatchResult
20
{
21
    /**
22
     * 匹配对象
23
     *
24
     * @var RouteMatcher
25
     */
26
    protected $matcher;
27
28
29
    /**
30
     * 匹配的参数
31
     *
32
     * @var array
33
     */
34
    protected $parameter;
35
36
    /**
37
     * 匹配的模块
38
     *
39
     * @var string
40
     */
41
    protected $module;
42
43
    /**
44
     * 匹配的名字
45
     *
46
     * @var string
47
     */
48
    protected $name;
49
50
    public function __construct(string $module, string $name, RouteMatcher $matcher, array $parameter)
51
    {
52
        $this->matcher = $matcher;
53
        $this->parameter = $parameter;
54
        $this->module = $module;
55
        $this->name = $name;
56
    }
57
58
    /**
59
     * Get 匹配对象
60
     *
61
     * @return  RouteMatcher
62
     */
63
    public function getMatcher()
64
    {
65
        return $this->matcher;
66
    }
67
68
    /**
69
     * Set 匹配对象
70
     *
71
     * @param  RouteMatcher  $matcher  匹配对象
72
     *
73
     * @return  self
74
     */
75
    public function setMatcher(RouteMatcher $matcher)
76
    {
77
        $this->matcher = $matcher;
78
79
        return $this;
80
    }
81
82
    /**
83
     * Get 匹配的参数
84
     *
85
     * @return  array
86
     */
87
    public function getParameter()
88
    {
89
        return $this->parameter;
90
    }
91
92
    /**
93
     * Set 匹配的参数
94
     *
95
     * @param  array  $parameter  匹配的参数
96
     *
97
     * @return  self
98
     */
99
    public function setParameter(array $parameter)
100
    {
101
        $this->parameter = $parameter;
102
103
        return $this;
104
    }
105
106
    /**
107
     * Get 匹配的模块
108
     *
109
     * @return  string
110
     */
111
    public function getModule()
112
    {
113
        return $this->module;
114
    }
115
116
    /**
117
     * Set 匹配的模块
118
     *
119
     * @param  string  $module  匹配的模块
120
     *
121
     * @return  self
122
     */
123
    public function setModule(string $module)
124
    {
125
        $this->module = $module;
126
127
        return $this;
128
    }
129
130
    /**
131
     * Get 匹配的名字
132
     *
133
     * @return  string
134
     */
135
    public function getName()
136
    {
137
        return $this->name;
138
    }
139
140
    /**
141
     * Set 匹配的名字
142
     *
143
     * @param  string  $name  匹配的名字
144
     *
145
     * @return  self
146
     */
147
    public function setName(string $name)
148
    {
149
        $this->name = $name;
150
151
        return $this;
152
    }
153
154
    public function run(Context $context)
155
    {
156
        $context->getApplication()->getManager()->registerPrivateClassLoader($this->module, $context->getApplication());
157
        if (($className = $this->matcher->getAttribute('class')) !== null) {
158
            $this->runWithResponseClass($context, $className);
159
        } elseif (($sourcePath = $this->matcher->getAttribute('source')) !== null) {
160
            $this->runWithSourceResponse($context, $sourcePath);
161
        }
162
    }
163
164
    protected function runWithSourceResponse(Context $context, string $sourcePath)
165
    {
166
        $path = Resource::getPathByRelativedPath($sourcePath, $context->getApplication()->getManager()->find($this->module)->getPath());
167
        if (FileSystem::exist($path)) {
168
            $response = BaseResponse::instance();
169
            $context->setResponse($response);
170
            $response->render(new SplFileInfo($sourcePath));
171
        } else {
172
            throw new \Exception(sprintf('source route file not find %s:%s path: %s', $this->module, $this->name, $sourcePath));
173
        }
174
    }
175
176
    protected function runWithResponseClass(Context $context, string $className)
177
    {
178
        $className = Loader::realName($className);
179
        $class = new ReflectionClass($className);
180
        if ($class->isSubclassOf(Response::class)) {
181
            $object = $class->getMethod('instance')->invoke(null);
182
            $context->setResponse($object);
183
            $class->getMethod('proccess')->invokeArgs($object, [
184
                new Runnable([$object,'onRequest']),
185
                $this->getRequest($context),
186
                $this->matcher->getAttribute('buffer', true),
187
                $context->isDebug(),
188
            ]);
189
        } else {
190
            throw new \Exception(sprintf('class route must be instance of %s in route %s:%s', Response::class, $this->module, $this->name));
191
        }
192
    }
193
194
    private function getRequest(Context $context): Request {
195
        $request = $context->getRequest();
196
        $request->setUrlParameter($this->parameter);
197
        return $request;
198
    }
199
}
200