Completed
Push — master ( b893df...d009f8 )
by Park Jong-Hun
03:04
created

Dispatcher::buildRouterMap()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
3
namespace Core\ControllerDispatcher;
4
5
use Prob\Handler\Proc;
6
use Prob\Handler\ParameterMap;
7
use Prob\Router\Dispatcher as RouterDispatcher;
8
use Prob\Rewrite\Request;
9
use Prob\Router\Matcher;
10
use Prob\Router\Map;
11
use Core\ViewModel;
12
use Core\Application;
13
use Core\ViewResolver;
14
15
class Dispatcher
16
{
17
18
    /**
19
     * @var Map
20
     */
21
    private $routerMap;
22
    private $routerConfig = [];
23
    private $viewEngineConfig = [];
24
25
    public function setRouterConfig(array $routerConfig)
26
    {
27
        $this->routerConfig = $routerConfig;
28
    }
29
30
    public function setViewEngineConfig(array $config)
31
    {
32
        $this->viewEngineConfig = $config;
33
    }
34
35
    public function dispatch(Request $request)
36
    {
37
        $this->buildRouterMap();
38
39
        $viewModel = new ViewModel();
40
        $parameterMap = $this->getControllerParameterMap($request, $viewModel);
41
42
        $returnOfController = $this->executeController($request, $parameterMap);
43
44
        $this->renderView($returnOfController, $viewModel);
45
    }
46
47
    private function buildRouterMap()
48
    {
49
        $builder = new RouterMapBuilder();
50
        $builder->setRouterConfig($this->routerConfig);
51
52
        $this->routerMap = $builder->build();
53
    }
54
55
    private function getControllerParameterMap(Request $request, ViewModel $viewModel)
56
    {
57
        $url = $this->resolveUrl($request);
58
59
        $parameterMap = new ParameterMap();
60
        $this->bindUrlParameter($parameterMap, $url);
61
        $this->bindViewModelParameter($parameterMap, $viewModel);
62
63
        return $parameterMap;
64
    }
65
66
    private function resolveUrl(Request $request)
67
    {
68
        $matcher = new Matcher($this->routerMap);
69
        return $matcher->match($request)['urlNameMatching'] ?: [];
70
    }
71
72
    private function bindUrlParameter(ParameterMap $map, array $url)
73
    {
74
        $map->bindByNameWithType('array', 'url', $url);
75
76
        foreach ($url as $name => $value) {
77
            $map->bindByName($name, $value);
78
        }
79
    }
80
81
    private function bindViewModelParameter(ParameterMap $map, ViewModel $viewModel)
82
    {
83
        $map->bindByType(ViewModel::class, $viewModel);
84
    }
85
86
87
    private function executeController(Request $request, ParameterMap $parameterMap)
88
    {
89
        $dispatcher = new RouterDispatcher($this->routerMap);
90
91
        /**
92
         * TODO 클로저와 일반함수 형태에서도 컨트롤러 이벤트가 작동하도록 수정해야함.
93
         */
94
        $handlerResolvedName = $this->getMatchedHandler($request)->getResolvedName();
95
96
        $this->triggerEvent('Controller.' . $handlerResolvedName['class'] . '.' . $handlerResolvedName['func'] . '.before');
97
        $result = $dispatcher->dispatch($request, $parameterMap);
98
        $this->triggerEvent('Controller.' . $handlerResolvedName['class'] . '.' . $handlerResolvedName['func'] . '.after');
99
100
        return $result;
101
    }
102
103
    /**
104
     * @return Proc
105
     */
106
    private function getMatchedHandler(Request $request)
107
    {
108
        $matcher = new Matcher($this->routerMap);
109
        return $matcher->match($request)['handler'];
110
    }
111
112
    private function triggerEvent($eventName)
113
    {
114
        Application::getInstance()
115
            ->getEventManager()
116
                ->trigger($eventName);
117
    }
118
119
    private function renderView($returnOfController, ViewModel $viewModel)
120
    {
121
        $view = $this->resolveView($returnOfController);
122
123
        foreach ($viewModel->getVariables() as $key => $value) {
124
            $view->set($key, $value);
125
        }
126
127
        $view->render();
128
    }
129
130
    /**
131
     * @param  mixed $returnOfController
132
     * @return View
133
     */
134
    private function resolveView($returnOfController)
135
    {
136
        $viewResolver = new ViewResolver($returnOfController);
137
        return $viewResolver->resolve($this->viewEngineConfig);
138
    }
139
}
140