Passed
Push — master ( 21c73c...dfa0e8 )
by Fran
04:26
created

Dispatcher::run()   B

Complexity

Conditions 7
Paths 19

Size

Total Lines 21
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 19
nop 0
dl 0
loc 21
rs 7.551
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Fran López <[email protected]>
4
 * @version 1.0
5
 */
6
7
namespace PSFS;
8
9
use PSFS\base\exception\AdminCredentialsException;
10
use PSFS\base\exception\RouterException;
11
use PSFS\base\exception\SecurityException;
12
use PSFS\base\Logger;
13
use PSFS\base\Singleton;
14
use PSFS\base\types\helpers\I18nHelper;
15
use PSFS\controller\ConfigController;
16
use PSFS\controller\UserController;
17
18
/**
19
 * Class Dispatcher
20
 * @package PSFS
21
 */
22
class Dispatcher extends Singleton
23
{
24
    /**
25
     * @Inyectable
26
     * @var \PSFS\base\Security $security
27
     */
28
    protected $security;
29
    /**
30
     * @Inyectable
31
     * @var \PSFS\base\Router $router
32
     */
33
    protected $router;
34
    /**
35
     * @Inyectable
36
     * @var \PSFS\base\Request $parser
37
     */
38
    protected $parser;
39
    /**
40
     * @Inyectable
41
     * @var \PSFS\base\Logger $log
42
     */
43
    protected $log;
44
    /**
45
     * @Inyectable
46
     * @var \PSFS\base\config\Config $config
47
     */
48
    protected $config;
49
50
    protected $ts;
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ts. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
51
    protected $mem;
52
53
    private $actualUri;
54
55
    /**
56
     * Initializer method
57
     */
58
    public function init()
59
    {
60
        Logger::log('Dispatcher init');
61
        parent::init();
62
        $this->initiateStats();
63
        I18nHelper::setLocale();
64
        $this->bindWarningAsExceptions();
65
        $this->actualUri = $this->parser->getServer("REQUEST_URI");
66
        Logger::log('End dispatcher init');
67
    }
68
69
    /**
70
     * Run method
71
     * @return string HTML
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
72
     */
73
    public function run()
74
    {
75
        Logger::log('Begin runner');
76
        try {
77
            if ($this->config->isConfigured()) {
78
                if (!$this->parser->isFile()) {
79
                    return $this->router->execute($this->actualUri);
80
                }
81
            } else {
82
                return ConfigController::getInstance()->config();
83
            }
84
        } catch (AdminCredentialsException $a) {
85
            return UserController::showAdminManager();
86
        } catch (SecurityException $s) {
87
            return $this->security->notAuthorized($this->actualUri);
88
        } catch (RouterException $r) {
89
            return $this->router->httpNotFound($r);
90
        } catch (\Exception $e) {
91
            return $this->dumpException($e);
92
        }
93
    }
94
95
    /**
96
     * Method that convert an exception to html
97
     *
98
     * @param \Exception $e
99
     *
100
     * @return string HTML
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
101
     */
102
    protected function dumpException(\Exception $e)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $e. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
103
    {
104
        Logger::log('Starting dump exception');
105
        $ex = (NULL !== $e->getPrevious()) ? $e->getPrevious() : $e;
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ex. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
106
        $error = array(
107
            "error" => $ex->getMessage(),
108
            "file" => $ex->getFile(),
109
            "line" => $ex->getLine(),
110
        );
111
        Logger::log('Throwing exception', LOG_ERR, $error);
112
        unset($error);
113
114
        return $this->router->httpNotFound($ex);
115
    }
116
117
    /**
118
     * Method that returns the memory used at this specific moment
119
     *
120
     * @param $unit string
121
     *
122
     * @return int
123
     */
124
    public function getMem($unit = "Bytes")
125
    {
126
        $use = memory_get_usage() - $this->mem;
127
        switch ($unit) {
128
            case "KBytes":
129
                $use /= 1024;
130
                break;
131
            case "MBytes":
132
                $use /= (1024 * 1024);
133
                break;
134
            case "Bytes":
135
            default:
136
        }
137
138
        return $use;
139
    }
140
141
    /**
142
     * Method that returns the seconds spent with the script
143
     * @return double
144
     */
145
    public function getTs()
146
    {
147
        return microtime(TRUE) - $this->ts;
148
    }
149
150
    /**
151
     * Debug function to catch warnings as exceptions
152
     */
153
    protected function bindWarningAsExceptions()
154
    {
155
        Logger::log('Added handlers for errors');
156
        //Warning & Notice handler
157
        set_error_handler(function ($errno, $errstr, $errfile, $errline) {
158
            Logger::log($errstr, LOG_CRIT, ['file' => $errfile, 'line' => $errline, 'errno' => $errno]);
159
            return true;
160
        }, E_ALL | E_STRICT);
161
    }
162
163
    /**
164
     * Stats initializer
165
     */
166
    private function initiateStats()
0 ignored issues
show
Coding Style introduced by
initiateStats uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
167
    {
168
        Logger::log('Initializing stats (mem + ts)');
169
        if (null !== $_SERVER && array_key_exists('REQUEST_TIME_FLOAT', $_SERVER)) {
170
            $this->ts = (float)$_SERVER['REQUEST_TIME_FLOAT'];
171
        } else {
172
            $this->ts = $this->parser->getTs();
173
        }
174
        $this->mem = memory_get_usage();
175
    }
176
177
}
178