Completed
Push — master ( e7ece2...d45aba )
by Anton
11s
created

Application   C

Complexity

Total Complexity 36

Size/Duplication

Total Lines 400
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 17

Test Coverage

Coverage 57.02%

Importance

Changes 0
Metric Value
dl 0
loc 400
ccs 65
cts 114
cp 0.5702
rs 6.9142
c 0
b 0
f 0
wmc 36
lcom 3
cbo 17

22 Methods

Rating   Name   Duplication   Size   Complexity  
A getEnvironment() 0 4 1
A getPath() 0 13 3
A isDebug() 0 4 1
A useLayout() 0 8 2
A initRouter() 0 7 1
A getResponse() 0 4 1
A getRequest() 0 4 1
A run() 0 6 1
A process() 0 6 1
A preProcess() 0 15 3
A postProcess() 0 4 1
A dispatch() 0 8 1
A preDispatch() 0 4 1
A doDispatch() 0 19 1
A postDispatch() 0 4 1
A render() 0 4 1
A end() 0 4 1
B doProcess() 0 29 5
B init() 0 35 2
B initConfig() 0 17 5
A initRequest() 0 6 1
A initResponse() 0 6 1
1
<?php
2
/**
3
 * Bluz Framework Component
4
 *
5
 * @copyright Bluz PHP Team
6
 * @link https://github.com/bluzphp/framework
7
 */
8
9
declare(strict_types=1);
10
11
namespace Bluz\Application;
12
13
use Bluz\Application\Exception\ApplicationException;
14
use Bluz\Application\Exception\ForbiddenException;
15
use Bluz\Application\Exception\RedirectException;
16
use Bluz\Common;
17
use Bluz\Controller\Controller;
18
use Bluz\Proxy\Config;
19
use Bluz\Proxy\Layout;
20
use Bluz\Proxy\Logger;
21
use Bluz\Proxy\Messages;
22
use Bluz\Proxy\Request;
23
use Bluz\Proxy\Response;
24
use Bluz\Proxy\Router;
25
use Bluz\Proxy\Session;
26
use Bluz\Proxy\Translator;
27
use Bluz\Request\RequestFactory;
28
use Bluz\Response\Response as ResponseInstance;
29
30
/**
31
 * Application
32
 *
33
 * @package  Bluz\Application
34
 * @link     https://github.com/bluzphp/framework/wiki/Application
35
 * @author   Anton Shevchuk
36
 * @created  06.07.11 16:25
37
 *
38
 * @method Controller error(\Exception $exception)
39
 * @method Controller forbidden(ForbiddenException $exception)
40
 * @method null redirect(string $url)
41
 */
42
class Application
43
{
44
    use Common\Helper;
45
    use Common\Singleton;
46
47
    /**
48
     * @var string Environment name
49
     */
50
    protected $environment = 'production';
51
52
    /**
53
     * @var string Application path
54
     */
55
    protected $path;
56
57
    /**
58
     * @var bool Debug application flag
59
     */
60
    protected $debugFlag = false;
61
62
    /**
63
     * @var bool Layout usage flag
64
     */
65
    protected $layoutFlag = true;
66
67
    /**
68
     * Get application environment
69
     *
70
     * @return string
71
     */
72
    public function getEnvironment()
73
    {
74
        return $this->environment;
75
    }
76
77
    /**
78
     * Get path to Application
79
     *
80
     * @return string
81
     */
82 640
    public function getPath()
83
    {
84 640
        if (!$this->path) {
85
            if (defined('PATH_APPLICATION')) {
86
                $this->path = PATH_APPLICATION;
87
            } else {
88
                $reflection = new \ReflectionClass($this);
89
                // 3 level up
90
                $this->path = dirname(dirname(dirname($reflection->getFileName())));
91
            }
92
        }
93 640
        return $this->path;
94
    }
95
96
    /**
97
     * Return Debug flag
98
     *
99
     * @return bool
100
     */
101 2
    public function isDebug()
102
    {
103 2
        return $this->debugFlag;
104
    }
105
106
    /**
107
     * Return/setup Layout Flag
108
     *
109
     * @param  bool|null $flag
110
     * @return bool
111
     */
112 638
    public function useLayout($flag = null)
113
    {
114 638
        if (is_bool($flag)) {
115 638
            $this->layoutFlag = $flag;
116
        }
117
        
118 638
        return $this->layoutFlag;
119
    }
120
121
    /**
122
     * Initialize system packages
123
     *
124
     * @param  string $environment
125
     * @throws ApplicationException
126
     * @return void
127
     */
128
    public function init($environment = 'production')
129
    {
130
        $this->environment = $environment;
131
132
        try {
133
            // first log message
134
            Logger::info('app:init');
135
136
            // initial default helper path
137
            $this->addHelperPath(dirname(__FILE__) . '/Helper/');
138
139
            // init Config
140
            $this->initConfig();
141
142
            // init Session, start inside class (if needed)
143
            Session::getInstance();
144
145
            // init Messages
146
            Messages::getInstance();
147
148
            // init Translator
149
            Translator::getInstance();
150
151
            // init Request
152
            $this->initRequest();
153
154
            // init Response
155
            $this->initResponse();
156
157
            // init Router
158
            $this->initRouter();
159
        } catch (\Exception $e) {
160
            throw new ApplicationException("Application can't be loaded: " . $e->getMessage());
161
        }
162
    }
163
164
    /**
165
     * Initial Request instance
166
     *
167
     * @return void
168
     */
169
    protected function initConfig()
170
    {
171
        Config::getInstance();
172
173
        // setup configuration for current environment
174
        if ($debug = Config::getData('debug')) {
175
            $this->debugFlag = (bool) $debug;
176
        }
177
178
        // initial php settings
179
        if ($ini = Config::getData('php')) {
180
            foreach ($ini as $key => $value) {
181
                $result = ini_set($key, $value);
182
                Logger::info('app:init:php:'.$key.':'.($result?:'---'));
183
            }
184
        }
185
    }
186
187
    /**
188
     * Initial Request instance
189
     *
190
     * @return void
191
     */
192
    protected function initRequest()
193
    {
194
        $request = RequestFactory::fromGlobals();
195
196
        Request::setInstance($request);
197
    }
198
199
    /**
200
     * Initial Response instance
201
     *
202
     * @return void
203
     */
204
    protected function initResponse()
205
    {
206
        $response = new ResponseInstance();
207
208
        Response::setInstance($response);
209
    }
210
211
    /**
212
     * Initial Router instance
213
     *
214
     * @return void
215
     */
216 638
    protected function initRouter()
217
    {
218 638
        $router = new \Bluz\Router\Router();
219 638
        $router->setOptions(Config::getData('router'));
220
221 638
        Router::setInstance($router);
222 638
    }
223
224
    /**
225
     * Get Response instance
226
     *
227
     * @return \Bluz\Response\Response
228
     */
229 1
    public function getResponse()
230
    {
231 1
        return Response::getInstance();
232
    }
233
234
    /**
235
     * Get Request instance
236
     *
237
     * @return \Zend\Diactoros\ServerRequest
238
     */
239 1
    public function getRequest()
240
    {
241 1
        return Request::getInstance();
242
    }
243
244
    /**
245
     * Run application
246
     *
247
     * @return void
248
     */
249
    public function run()
250
    {
251
        $this->process();
252
        $this->render();
253
        $this->end();
254
    }
255
256
    /**
257
     * Process application
258
     *
259
     * Note:
260
     * - Why you don't use "X-" prefix for custom headers?
261
     * - Because it deprecated ({@link http://tools.ietf.org/html/rfc6648})
262
     *
263
     * @return void
264
     */
265 6
    public function process()
266
    {
267 6
        $this->preProcess();
268 6
        $this->doProcess();
269 6
        $this->postProcess();
270 6
    }
271
272
    /**
273
     * Extension point: pre process
274
     *
275
     * - Router processing
276
     * - Analyse request headers
277
     *
278
     * @return void
279
     * @throws ApplicationException
280
     */
281 6
    protected function preProcess()
282
    {
283 6
        Router::process();
284
285
        // disable Layout for XmlHttpRequests
286 6
        if (Request::isXmlHttpRequest()) {
287 1
            $this->layoutFlag = false;
288
        }
289
290
        // switch to JSON response based on Accept header
291 6
        if (Request::getAccept([Request::TYPE_HTML, Request::TYPE_JSON]) == Request::TYPE_JSON) {
292
            $this->layoutFlag = false;
293
            Response::switchType('JSON');
294
        }
295 6
    }
296
297
    /**
298
     * Do process
299
     *
300
     * - Dispatch controller
301
     * - Exceptions handling
302
     * - Setup layout
303
     * - Setup response body
304
     *
305
     * @return void
306
     */
307 6
    protected function doProcess()
308
    {
309 6
        $module = Request::getModule();
310 6
        $controller = Request::getController();
311 6
        $params = Request::getParams();
312
313
        // try to dispatch controller
314
        try {
315
            // dispatch controller
316 6
            $result = $this->dispatch($module, $controller, $params);
317 5
        } catch (ForbiddenException $e) {
318 1
            $result = $this->forbidden($e);
319 4
        } catch (RedirectException $e) {
320
            // redirect to URL
321 2
            $result = $this->redirect($e->getUrl());
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as $this->redirect($e->getUrl()) (which targets Bluz\Application\Application::redirect()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
322 2
        } catch (\Exception $e) {
323 2
            $result = $this->error($e);
324
        }
325
326
        // setup layout, if needed
327 6
        if ($this->useLayout()) {
328
            // render view to layout
329
            // needed for headScript and headStyle helpers
330 2
            Layout::setContent($result->render());
331 2
            Response::setBody(Layout::getInstance());
332
        } else {
333 4
            Response::setBody($result);
334
        }
335 6
    }
336
337
    /**
338
     * Extension point: post process
339
     *
340
     * @return void
341
     */
342 6
    protected function postProcess()
343
    {
344
        // nothing
345 6
    }
346
347
    /**
348
     * Dispatch controller with params
349
     *
350
     * Call dispatch from any \Bluz\Package
351
     *     Application::getInstance()->dispatch($module, $controller, array $params);
352
     *
353
     * @param  string $module
354
     * @param  string $controller
355
     * @param  array  $params
356
     * @return Controller
357
     * @throws ApplicationException
358
     */
359 9
    public function dispatch($module, $controller, $params = [])
360
    {
361 9
        $this->preDispatch($module, $controller, $params);
362 9
        $result = $this->doDispatch($module, $controller, $params);
363 6
        $this->postDispatch($module, $controller, $params);
364
365 6
        return $result;
366
    }
367
368
    /**
369
     * Extension point: pre dispatch
370
     *
371
     * @param  string $module
372
     * @param  string $controller
373
     * @param  array  $params
374
     * @return void
375
     */
376 9
    protected function preDispatch($module, $controller, $params = [])
377
    {
378 9
        Logger::info("app:dispatch:pre: $module/$controller");
379 9
    }
380
381
    /**
382
     * Do dispatch
383
     *
384
     * @param  string $module
385
     * @param  string $controller
386
     * @param  array  $params
387
     * @return Controller
388
     */
389 9
    protected function doDispatch($module, $controller, $params = [])
390
    {
391
        // @TODO: try to find custom controller class
392
393
        // create controller controller
394 9
        $controllerInstance = new Controller($module, $controller);
395
396
        // check HTTP Accept header
397 9
        $controllerInstance->checkAccept();
398
        // check HTTP method
399 9
        $controllerInstance->checkMethod();
400
        // check ACL privileges
401 8
        $controllerInstance->checkPrivilege();
402
403
        // run controller
404 8
        $controllerInstance->run($params);
405
406 6
        return $controllerInstance;
407
    }
408
409
    /**
410
     * Extension point: post dispatch
411
     *
412
     * @param  string $module
413
     * @param  string $controller
414
     * @param  array  $params
415
     * @return void
416
     */
417 6
    protected function postDispatch($module, $controller, $params = [])
418
    {
419 6
        Logger::info("<<<:dispatch:post: $module/$controller");
420 6
    }
421
422
    /**
423
     * Render, is send Response
424
     *
425
     * @return void
426
     */
427
    public function render()
428
    {
429
        Response::send();
430
    }
431
432
    /**
433
     * Extension point: finally method
434
     *
435
     * @return void
436
     */
437
    public function end()
438
    {
439
        // nothing
440
    }
441
}
442