Completed
Push — master ( 467d47...6f2bb4 )
by Anton
14s
created

Application   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 415
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 16

Test Coverage

Coverage 79.13%

Importance

Changes 0
Metric Value
dl 0
loc 415
ccs 91
cts 115
cp 0.7913
rs 7.4461
c 0
b 0
f 0
wmc 36
lcom 3
cbo 16

22 Methods

Rating   Name   Duplication   Size   Complexity  
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 process() 0 6 1
A getEnvironment() 0 4 1
A getPath() 0 13 3
B init() 0 35 2
B initConfig() 0 17 5
A initRequest() 0 6 1
A initResponse() 0 6 1
A preProcess() 0 15 3
A run() 0 6 1
B doProcess() 0 30 5
A postProcess() 0 4 1
A dispatch() 0 15 1
A preDispatch() 0 11 1
A doDispatch() 0 5 1
A postDispatch() 0 4 1
A render() 0 4 1
A end() 0 4 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\Http\Exception\ForbiddenException;
15
use Bluz\Http\Exception\NotAcceptableException;
16
use Bluz\Http\Exception\NotAllowedException;
17
use Bluz\Http\Exception\RedirectException;
18
use Bluz\Common;
19
use Bluz\Common\Exception\CommonException;
20
use Bluz\Common\Exception\ComponentException;
21
use Bluz\Controller\Controller;
22
use Bluz\Controller\ControllerException;
23
use Bluz\Proxy\Config;
24
use Bluz\Proxy\Layout;
25
use Bluz\Proxy\Logger;
26
use Bluz\Proxy\Messages;
27
use Bluz\Proxy\Request;
28
use Bluz\Proxy\Response;
29
use Bluz\Proxy\Router;
30
use Bluz\Proxy\Session;
31
use Bluz\Proxy\Translator;
32
use Bluz\Request\RequestFactory;
33
use Bluz\Response\Response as ResponseInstance;
34
use Zend\Diactoros\ServerRequest;
35
36
/**
37
 * Application
38
 *
39
 * @package  Bluz\Application
40
 * @link     https://github.com/bluzphp/framework/wiki/Application
41
 * @author   Anton Shevchuk
42
 * @created  06.07.11 16:25
43
 *
44
 * @method Controller error(\Exception $exception)
45
 * @method mixed forbidden(ForbiddenException $exception)
46
 * @method null redirect(RedirectException $url)
47
 */
48
class Application
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
49
{
50
    use Common\Helper;
51
    use Common\Singleton;
52
53
    /**
54
     * @var string Environment name
55
     */
56
    protected $environment = 'production';
57
58
    /**
59
     * @var string Application path
60
     */
61
    protected $path;
62
63
    /**
64
     * @var bool Debug application flag
65
     */
66
    protected $debugFlag = false;
67
68
    /**
69
     * @var bool Layout usage flag
70
     */
71
    protected $layoutFlag = true;
72
73
    /**
74
     * Get application environment
75
     *
76
     * @return string
77
     */
78 585
    public function getEnvironment() : string
79
    {
80 585
        return $this->environment;
81
    }
82
83
    /**
84
     * Get path to Application
85
     *
86
     * @return string
87
     */
88 585
    public function getPath() : string
89
    {
90 585
        if (!$this->path) {
91 579
            if (defined('PATH_APPLICATION')) {
92 579
                $this->path = PATH_APPLICATION;
93
            } else {
94
                $reflection = new \ReflectionClass($this);
95
                // 3 level up
96
                $this->path = dirname($reflection->getFileName(), 3);
97
            }
98
        }
99 585
        return $this->path;
100
    }
101
102
    /**
103
     * Return Debug flag
104
     *
105
     * @return bool
106
     */
107 2
    public function isDebug() : bool
108
    {
109 2
        return $this->debugFlag;
110
    }
111
112
    /**
113
     * Return/setup Layout Flag
114
     *
115
     * @param  bool|null $flag
116
     *
117
     * @return bool
118
     */
119 35
    public function useLayout($flag = null) : bool
120
    {
121 35
        if (is_bool($flag)) {
122 28
            $this->layoutFlag = $flag;
123
        }
124
125 35
        return $this->layoutFlag;
126
    }
127
128
    /**
129
     * Initialize system packages
130
     *
131
     * @param  string $environment
132
     *
133
     * @throws ApplicationException
134
     * @return void
135
     */
136 580
    public function init($environment = 'production') : void
137
    {
138 580
        $this->environment = $environment;
139
140
        try {
141
            // initial default helper path
142 580
            $this->addHelperPath(__DIR__ . '/Helper/');
143
144
            // init Config
145 580
            $this->initConfig();
146
147
            // first log message
148 580
            Logger::info('app:init');
149
150
            // init Session, start inside class (if needed)
151 580
            Session::getInstance();
152
153
            // init Messages
154 580
            Messages::getInstance();
155
156
            // init Translator
157 580
            Translator::getInstance();
158
159
            // init Request
160 580
            $this->initRequest();
161
162
            // init Response
163 580
            $this->initResponse();
164
165
            // init Router
166 580
            $this->initRouter();
167
        } catch (\Exception $e) {
168
            throw new ApplicationException("Application can't be loaded: " . $e->getMessage());
169
        }
170 580
    }
171
172
    /**
173
     * Initial Request instance
174
     *
175
     * @return void
176
     */
177 580
    protected function initConfig() : void
178
    {
179 580
        Config::getInstance();
180
181
        // setup configuration for current environment
182 580
        if ($debug = Config::getData('debug')) {
183
            $this->debugFlag = (bool)$debug;
184
        }
185
186
        // initial php settings
187 580
        if ($ini = Config::getData('php')) {
188
            foreach ($ini as $key => $value) {
189
                $result = ini_set($key, $value);
190
                Logger::info('app:init:php:' . $key . ':' . ($result ?: '---'));
191
            }
192
        }
193 580
    }
194
195
    /**
196
     * Initial Request instance
197
     *
198
     * @return void
199
     * @throws \InvalidArgumentException
200
     */
201 580
    protected function initRequest() : void
202
    {
203 580
        $request = RequestFactory::fromGlobals();
204
205 580
        Request::setInstance($request);
206 580
    }
207
208
    /**
209
     * Initial Response instance
210
     *
211
     * @return void
212
     */
213 580
    protected function initResponse() : void
214
    {
215 580
        $response = new ResponseInstance();
216
217 580
        Response::setInstance($response);
218 580
    }
219
220
    /**
221
     * Initial Router instance
222
     *
223
     * @return void
224
     */
225 580
    protected function initRouter() : void
226
    {
227 580
        $router = new \Bluz\Router\Router();
228 580
        $router->setOptions(Config::getData('router'));
229
230 580
        Router::setInstance($router);
231 580
    }
232
233
    /**
234
     * Get Response instance
235
     *
236
     * @return \Bluz\Response\Response
237
     */
238 3
    public function getResponse() : ResponseInstance
239
    {
240 3
        return Response::getInstance();
241
    }
242
243
    /**
244
     * Get Request instance
245
     *
246
     * @return \Zend\Diactoros\ServerRequest
247
     */
248 1
    public function getRequest() : ServerRequest
249
    {
250 1
        return Request::getInstance();
251
    }
252
253
    /**
254
     * Run application
255
     *
256
     * @return void
257
     * @throws ApplicationException
258
     */
259 1
    public function run() : void
260
    {
261 1
        $this->process();
262 1
        $this->render();
263 1
        $this->end();
264 1
    }
265
266
    /**
267
     * Process application
268
     *
269
     * Note:
270
     * - Why you don't use "X-" prefix for custom headers?
271
     * - Because it deprecated ({@link http://tools.ietf.org/html/rfc6648})
272
     *
273
     * @return void
274
     * @throws ApplicationException
275
     */
276 9
    public function process() : void
277
    {
278 9
        $this->preProcess();
279 9
        $this->doProcess();
280 9
        $this->postProcess();
281 9
    }
282
283
    /**
284
     * Extension point: pre process
285
     *
286
     * - Router processing
287
     * - Analyse request headers
288
     *
289
     * @return void
290
     * @throws ApplicationException
291
     */
292 9
    protected function preProcess() : void
293
    {
294 9
        Router::process();
295
296
        // disable Layout for XmlHttpRequests
297 9
        if (Request::isXmlHttpRequest()) {
298 2
            $this->layoutFlag = false;
299
        }
300
301
        // switch to JSON response based on Accept header
302 9
        if (Request::checkAccept([Request::TYPE_HTML, Request::TYPE_JSON]) === Request::TYPE_JSON) {
303 1
            $this->layoutFlag = false;
304 1
            Response::setType('JSON');
305
        }
306 9
    }
307
308
    /**
309
     * Do process
310
     *
311
     * - Dispatch controller
312
     * - Exceptions handling
313
     * - Setup layout
314
     * - Setup response body
315
     *
316
     * @return void
317
     */
318
    protected function doProcess() : void
319
    {
320
        $module = Request::getModule();
321
        $controller = Request::getController();
322
        $params = Request::getParams();
323
324
        try {
325
            // try to dispatch controller
326
            $result = $this->dispatch($module, $controller, $params);
327
        } catch (ForbiddenException $e) {
328
            // dispatch default error controller
329
            $result = $this->forbidden($e);
330
        } catch (RedirectException $e) {
331
            // should return `null` for disable output and setup redirect headers
332
            $result = $this->redirect($e);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as $this->redirect($e) (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...
333
        } catch (\Exception $e) {
334
            // dispatch default error controller
335
            $result = $this->error($e);
336
        }
337
338
        // setup layout, if needed
339
        if ($this->useLayout()) {
340
            // render view to layout
341
            // needed for headScript and headStyle helpers
342
            Layout::setContent($result->render());
343
            Response::setBody(Layout::getInstance());
344
        } else {
345
            Response::setBody($result);
346
        }
347
    }
348
349
    /**
350
     * Extension point: post process
351
     *
352
     * @return void
353
     */
354 9
    protected function postProcess() : void
355
    {
356
        // nothing
357 9
    }
358
359
    /**
360
     * Dispatch controller with params
361
     *
362
     * Call dispatch from any \Bluz\Package
363
     *     Application::getInstance()->dispatch($module, $controller, array $params);
364
     *
365
     * @param  string $module
366
     * @param  string $controller
367
     * @param  array  $params
368
     *
369
     * @return Controller
370
     * @throws ComponentException
371
     * @throws CommonException
372
     * @throws ControllerException
373
     * @throws ForbiddenException
374
     * @throws NotAcceptableException
375
     * @throws NotAllowedException
376
     */
377 41
    public function dispatch($module, $controller, array $params = []) : Controller
378
    {
379 41
        $instance = new Controller($module, $controller, $params);
380
381 41
        Logger::info("app:dispatch:>>>: $module/$controller");
382 41
        $this->preDispatch($instance);
383
384 40
        Logger::info("app:dispatch:===: $module/$controller");
385 40
        $this->doDispatch($instance);
386
387 38
        Logger::info("app:dispatch:<<<: $module/$controller");
388 38
        $this->postDispatch($instance);
389
390 38
        return $instance;
391
    }
392
393
    /**
394
     * Extension point: pre dispatch
395
     *
396
     * @param  Controller $controller
397
     *
398
     * @return void
399
     * @throws ComponentException
400
     * @throws ForbiddenException
401
     * @throws NotAcceptableException
402
     * @throws NotAllowedException
403
     */
404 41
    protected function preDispatch($controller) : void
405
    {
406
        // check HTTP method
407 41
        $controller->checkHttpMethod();
408
409
        // check ACL privileges
410 40
        $controller->checkPrivilege();
411
412
        // check HTTP Accept header
413 40
        $controller->checkHttpAccept();
414 40
    }
415
416
    /**
417
     * Do dispatch
418
     *
419
     * @param  Controller $controller
420
     *
421
     * @return void
422
     * @throws ComponentException
423
     * @throws ControllerException
424
     */
425 40
    protected function doDispatch($controller) : void
426
    {
427
        // run controller
428 40
        $controller->run();
429 38
    }
430
431
    /**
432
     * Extension point: post dispatch
433
     *
434
     * @param  Controller $controller
435
     *
436
     * @return void
437
     */
438 38
    protected function postDispatch($controller) : void
0 ignored issues
show
Unused Code introduced by
The parameter $controller is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
439
    {
440
        // nothing by default
441 38
    }
442
443
    /**
444
     * Render, is send Response
445
     *
446
     * @return void
447
     */
448 1
    public function render() : void
449
    {
450 1
        Response::send();
451 1
    }
452
453
    /**
454
     * Extension point: finally method
455
     *
456
     * @return void
457
     */
458 1
    public function end() : void
459
    {
460
        // nothing
461 1
    }
462
}
463