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

Dispatcher   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 16
c 1
b 0
f 0
lcom 1
cbo 8
dl 0
loc 125
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A setRouterConfig() 0 4 1
A setViewEngineConfig() 0 4 1
A dispatch() 0 11 1
A buildRouterMap() 0 7 1
A getControllerParameterMap() 0 10 1
A resolveUrl() 0 5 2
A bindUrlParameter() 0 8 2
A bindViewModelParameter() 0 4 1
A executeController() 0 15 1
A getMatchedHandler() 0 5 1
A triggerEvent() 0 6 1
A renderView() 0 10 2
A resolveView() 0 5 1
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