Completed
Push — master ( f6e733...e82db7 )
by Park Jong-Hun
03:41
created

Dispatcher::setRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Core\ControllerDispatcher;
4
5
use Prob\Handler\ProcInterface;
6
use Prob\Handler\ParameterMap;
7
use Psr\Http\Message\RequestInterface;
8
use Prob\Router\Dispatcher as RouterDispatcher;
9
use Prob\Router\Matcher;
10
use Prob\Router\Map;
11
use Core\ViewModel;
12
use Core\Application;
13
use Core\ViewResolver;
14
use Core\ViewEngineInterface;
15
use Core\ViewResolverInterface;
16
17
class Dispatcher
18
{
19
20
    /**
21
     * @var Map
22
     */
23
    private $routerMap;
24
    private $routerConfig = [];
25
    private $viewEngineConfig = [];
26
27
    private $viewResolvers = [];
28
29
    /**
30
     * @var RequestInterface
31
     */
32
    private $request;
33
34
    public function setRouterConfig(array $routerConfig)
35
    {
36
        $this->routerConfig = $routerConfig;
37
    }
38
39
    public function setViewEngineConfig(array $config)
40
    {
41
        $this->viewEngineConfig = $config;
42
    }
43
44
    public function setViewResolver(array $viewResolvers)
45
    {
46
        $this->viewResolvers = $viewResolvers;
47
    }
48
49
    public function setRequest(RequestInterface $request)
50
    {
51
        $this->request = $request;
52
    }
53
54
    public function dispatch()
55
    {
56
        $this->buildRouterMap();
57
58
        $viewModel = new ViewModel();
59
        $parameterMap = $this->getParameterMap($viewModel);
60
61
        $result = $this->execute($parameterMap);
62
        $this->renderView($result, $viewModel);
63
    }
64
65
    private function buildRouterMap()
66
    {
67
        $builder = new RouterMapBuilder();
68
        $builder->setRouterConfig($this->routerConfig);
69
70
        $this->routerMap = $builder->build();
71
    }
72
73
    /**
74
     * @param  ViewModel $viewModel [description]
75
     * @return ParameterMap
76
     */
77
    private function getParameterMap(ViewModel $viewModel)
78
    {
79
        $parameterMapper = new ParameterMapper();
80
81
        $parameterMapper->setRequest($this->request);
82
        $parameterMapper->setViewModel($viewModel);
83
        $parameterMapper->setRouterMap($this->routerMap);
84
85
        return $parameterMapper->getParameterMap();
86
    }
87
88
89
    private function execute(ParameterMap $parameterMap)
90
    {
91
        $dispatcher = new RouterDispatcher($this->routerMap);
92
93
        /**
94
         * TODO 클로저와 일반함수 형태에서도 컨트롤러 이벤트가 작동하도록 수정해야함.
95
         */
96
97
        if ($this->getMatchedHandler()) {
98
            $this->triggerEvent($this->getEventName('before'));
99
        }
100
101
        $result = $dispatcher->dispatch($this->request, $parameterMap);
102
103
        if ($this->getMatchedHandler()) {
104
            $this->triggerEvent($this->getEventName('after'));
105
        }
106
107
        return $result;
108
    }
109
110
    /**
111
     * @param  string $action 'before' || 'after'
112
     * @return string event name
113
     */
114
    private function getEventName($action)
115
    {
116
        return sprintf(
117
            'Controller.%s.%s',
118
            $this->getMatchedHandler()->getName(),
119
            $action
120
        );
121
    }
122
123
    /**
124
     * @return ProcInterface
125
     */
126
    private function getMatchedHandler()
127
    {
128
        $matcher = new Matcher($this->routerMap);
129
        return $matcher->match($this->request)['handler'];
130
    }
131
132
    private function triggerEvent($eventName)
133
    {
134
        $parameterMapper = new ParameterMapper();
135
        $parameterMapper->setRequest($this->request);
136
        $parameterMapper->setRouterMap($this->routerMap);
137
138
        $parameterMap = $parameterMapper->getParameterMap();
139
140
        Application::getInstance()->getEventManager()->trigger($eventName, [$parameterMap]);
141
    }
142
143
    private function renderView($controllerResult, ViewModel $viewModel)
144
    {
145
        $view = $this->resolveView($controllerResult);
146
147
        foreach ($viewModel->getVariables() as $key => $value) {
148
            $view->set($key, $value);
149
        }
150
151
        $view->render();
152
    }
153
154
    /**
155
     * @param  mixed $controllerResult
156
     * @return ViewEngineInterface
157
     */
158
    private function resolveView($controllerResult)
159
    {
160
        foreach ($this->viewResolvers as $name => $resolverClassName) {
161
            /** @var ViewResolverInterface */
162
            $resolver = new $resolverClassName();
163
            $resolver->setViewEngineConfig(
164
                isset($this->viewEngineConfig[$name])
165
                    ? $this->viewEngineConfig[$name]
166
                    : []
167
            );
168
169
            $view = $resolver->resolve($controllerResult);
170
171
            if ($view !== null) {
172
                return $view;
173
            }
174
        }
175
    }
176
}
177