Completed
Push — 2.0 ( 6a7506...153dfc )
by Vermeulen
01:43
created

Router::update()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
1
<?php
2
/**
3
 * Class for the router system
4
 * @author Vermeulen Maxime <[email protected]>
5
 * @version 2.0
6
 */
7
8
namespace BfwFastRoute;
9
10
use \Exception;
11
use \FastRoute;
12
13
/**
14
 * Permet de gérer la vue et de savoir vers quel page envoyer
15
 * @package bfw-fastroute
16
 */
17
class Router implements \SplObserver
18
{
19
    /**
20
     * @var \BFW\Module $module The bfw module instance for this module
21
     */
22
    protected $module;
23
    
24
    /**
25
     * @var \BFW\Config $config The bfw config instance for this module
26
     */
27
    protected $config;
28
    
29
    /**
30
     * @var \BFW\ControllerRouterLink $routerLinker Linker between
31
     *  controller and router instance
32
     */
33
    protected $routerLinker;
34
    
35
    /**
36
     * @var \FastRoute\Dispatcher $dispatcher FastRoute dispatcher
37
     */
38
    protected $dispatcher;
39
    
40
    /**
41
     * Constructor
42
     * Get config and linker instance
43
     * Call fastRoute dispatcher
44
     * 
45
     * @param \BFW\Module $module
46
     */
47
    public function __construct(\BFW\Module $module)
48
    {
49
        $this->module = $module;
50
        $this->config = $module->getConfig();
51
        
52
        $this->routerLinker = \BFW\ControllerRouterLink::getInstance();
53
        
54
        $this->dispatcher = FastRoute\simpleDispatcher([
55
            $this,
56
            'addRoutesToCollector'
57
        ]);
58
    }
59
    
60
    /**
61
     * Observer update method
62
     * Call obtainCurrentRoute method on action "apprun_loadAllAppModules".
63
     * 
64
     * @param \SplSubject $subject
65
     * 
66
     * @return void
67
     */
68
    public function update(\SplSubject $subject)
69
    {
70
        if ($subject->getAction() === 'apprun_loadAllAppModules') {
71
            $this->obtainCurrentRoute();
72
        }
73
    }
74
    
75
    /**
76
     * Call by dispatcher; Add route in config to fastRoute router
77
     * 
78
     * @param FastRoute\RouteCollector $router FastRoute router
79
     * 
80
     * @return void
81
     */
82
    public function addRoutesToCollector(FastRoute\RouteCollector $router)
83
    {
84
        $routes = $this->config->getValue('routes');
85
        
86
        foreach ($routes as $slug => $infos) {
87
            $slug = trim($slug);
88
89
            //Défault method
90
            $method = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'];
91
            
92
            //If method is declared for the route
93
            if (isset($infos['httpMethod'])) {
94
                //Get the method ans remove it from httpMethod array
95
                $method = $infos['httpMethod'];
96
                unset($infos['httpMethod']);
97
            }
98
99
            $router->addRoute($method, $slug, $infos);
100
        }
101
    }
102
    
103
    /**
104
     * Obtain informations about the current route from fastRoute dispatcher
105
     * 
106
     * @return void
107
     */
108
    public function obtainCurrentRoute()
109
    {
110
        //Get current request informations
111
        $bfwRequest = \BFW\Request::getInstance();
112
        $request    = $bfwRequest->getRequest()->path;
113
        $method     = $bfwRequest->getMethod();
114
        
115
        //If request is index
116
        if ($request === '') {
117
            $request = '/';
118
        }
119
120
        //Get route information from dispatcher
121
        $routeInfo   = $this->dispatcher->dispatch($method, $request);
122
        $routeStatus = $routeInfo[0];
123
        
124
        //Get and send request http status to the controller/router linker
125
        $httpStatus = $this->checkStatus($routeStatus);
126
        
127
        http_response_code($httpStatus);
128
        if ($httpStatus !== 200) {
129
            return;
130
        }
131
132
        //Obtains datas for route from config file and send to linker
133
        $this->sendInfosForRouteToLinker($routeInfo[1]);
134
        
135
        //Add gets datas in route to $_GET var
136
        $this->addDatasToGetAndPostVar($routeInfo[1]);
137
        $this->addToSuperglobalVar('GET', $routeInfo[2]);
138
        
139
        $this->sendNotifyRouteFindToOthers();
140
    }
141
    
142
    /**
143
     * Get http status for response from dispatcher
144
     * 
145
     * @param int $routeStatus : Route status send by dispatcher for request
146
     * 
147
     * @return int
148
     */
149
    protected function checkStatus($routeStatus)
150
    {
151
        $httpStatus = 200;
152
        
153
        if ($routeStatus === FastRoute\Dispatcher::METHOD_NOT_ALLOWED) {
154
            $httpStatus = 405;
155
        } elseif ($routeStatus === FastRoute\Dispatcher::NOT_FOUND) {
156
            $httpStatus = 404;
157
        }
158
        
159
        return $httpStatus;
160
    }
161
    
162
    /**
163
     * Obtains route informations from config file and send this informations
164
     * to the controller/router linker
165
     * 
166
     * @param array $routeInfos : Route information from config file
167
     * 
168
     * @return void
169
     * 
170
     * @throws \Exception If target not define in config file
171
     */
172
    protected function sendInfosForRouteToLinker(array $routeInfos)
173
    {
174
        if (!isset($routeInfos['target'])) {
175
            throw new Exception('Router : target not defined');
176
        }
177
        
178
        $this->routerLinker->setTarget($routeInfos['target']);
179
    }
180
    
181
    /**
182
     * Add datas into a superglobal var
183
     * 
184
     * @param string $globalVarName : Name of the superglobal var
185
     * @param array $datasToAdd : Datas to add to $_GET var
186
     * 
187
     * @return void
188
     */
189
    protected function addToSuperglobalVar($globalVarName, array $datasToAdd)
190
    {
191
        global ${'_'.$globalVarName};
192
        ${'_'.$globalVarName} = array_merge(${'_'.$globalVarName}, $datasToAdd);
193
    }
194
    
195
    /**
196
     * If property 'get' has been declared into current route config, add
197
     * them into superglobal $_GET .
198
     * 
199
     * @param array $routeInfos route informations declared in config
200
     * 
201
     * @return void
202
     */
203
    protected function addDatasToGetAndPostVar(array $routeInfos)
204
    {
205
        if (isset($routeInfos['get'])) {
206
            $this->addToSuperglobalVar('GET', $routeInfos['get']);
207
        }
208
    }
209
    
210
    /**
211
     * Send to all observer of Application a notify who contains the message
212
     * "request_route_find" to say the route for the current request has been
213
     * found by us.
214
     * 
215
     * @return void
216
     */
217
    protected function sendNotifyRouteFindToOthers()
218
    {
219
        $app = \BFW\Application::getInstance();
220
        $app->addNotification('request_route_find');
221
    }
222
}
223