Completed
Push — master ( fc5b9e...2c231d )
by Mathieu
01:50
created

Suricate::run()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * Fwk - Another micro PHP 5 framework
4
 *
5
 * @author      Mathieu LESNIAK <[email protected]>
6
 * @copyright   2013-2014 Mathieu LESNIAK
7
 * @version     0.1
8
 * @package     Suricate
9
 *
10
 * @method App          App() App() Get instance of App service
11
 * @method Database     Database() Database() Get instance of Database service
12
 * @method Error        Error() Error() Get instance of Error service
13
 * @method I18n         I18n() I18n() Get instance of I18n service
14
 * @method Request      Request() Request() Get instance of Request service
15
 */
16
namespace Suricate;
17
18
class Suricate
19
{
20
21
    const VERSION = '0.1.7';
22
23
    const CONF_DIR = '/conf/';
24
25
    protected $router;
26
27
    private $defaultConfig = [];
0 ignored issues
show
Unused Code introduced by
The property $defaultConfig is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
28
    private $config;
29
    private $configFile;
30
31
    private $useAutoloader = false;
32
33
    private static $servicesContainer;
34
    private static $servicesRepository;
35
36
    private $servicesList = array(
37
        'Logger'            => '\Suricate\Logger',
38
        'App'               => '\Suricate\App',
39
        'I18n'              => '\Suricate\I18n',
40
        'Error'             => '\Suricate\Error',
41
        'Router'            => '\Suricate\Router',
42
        'Request'           => '\Suricate\Request',
43
        'Database'          => '\Suricate\Database',
44
        'Cache'             => '\Suricate\Cache',
45
        'CacheMemcache'     => '\Suricate\Cache\Memcache',
46
        'CacheApc'          => '\Suricate\Cache\Apc',
47
        'CacheFile'         => '\Suricate\Cache\File',
48
        'Curl'              => '\Suricate\Curl',
49
        'Response'          => '\Suricate\Request',
50
        'Session'           => '\Suricate\Session',
51
        'SessionNative'     => '\Suricate\Session\Native',
52
        'SessionCookie'     => '\Suricate\Session\Cookie',
53
        'SessionMemcache'   => '\Suricate\Session\Memcache',
54
    );
55
56
57
    public function __construct($paths = array(), $configFile = null)
58
    {
59
        if ($configFile !== null) {
60
            $this->setConfigFile($configFile);
61
        }
62
       
63
        // Load helpers
64
        require_once __DIR__ . DIRECTORY_SEPARATOR . 'Helper.php';
65
66
        $this->loadConfig();
67
        $this->setAppPaths($paths);
68
69
        if ($this->useAutoloader) {
70
            // Configure autoloader
71
            require_once __DIR__ . DIRECTORY_SEPARATOR . 'AutoLoader.php';
72
            AutoLoader::register();
73
        }
74
75
        // Define error handler
76
        set_exception_handler(array('\Suricate\Error', 'handleException'));
77
        set_error_handler(array('\Suricate\Error', 'handleError'));
78
        register_shutdown_function(array('\Suricate\Error', 'handleShutdownError'));
79
80
        self::$servicesRepository = new Container();
81
82
        $this->initServices();
83
    }
84
85
    private function setAppPaths($paths = array())
86
    {
87
        foreach ($paths as $key => $value) {
88
            $this->config['App']['path.' . $key] = realpath($value);
89
        }
90
91
        return $this;
92
    }
93
    /**
94
     * Initialize Framework services
95
     * @return null
96
     */
97
    private function initServices()
98
    {
99
        self::$servicesRepository->setWarehouse($this->servicesList);
100
101
        self::$servicesRepository['Request']->parse();
102
        if (isset($this->config['App']['locale'])) {
103
            $this->config['I18n'] = array('locale' => $this->config['App']['locale']);
104
        }
105
        // first sync, && init, dependency to Suricate::request
106
        self::$servicesContainer = clone self::$servicesRepository;
107
108
        foreach (array_keys($this->servicesList) as $serviceName) {
109
            if (isset($this->config[$serviceName])) {
110
                self::$servicesRepository[$serviceName]->configure($this->config[$serviceName]);
111
112
                /**
113
                 TODO : remove sync in service creation
114
                */
115
                self::$servicesContainer = clone self::$servicesRepository;
116
            }
117
        }
118
119
        if (isset($this->config['Constants'])) {
120
            foreach ($this->config['Constants'] as $constantName => $constantValue) {
121
                $constantName = strtoupper($constantName);
122
                define($constantName, $constantValue);
123
            }
124
        }
125
126
        // final sync, repository is complete
127
        self::$servicesContainer = clone self::$servicesRepository;
128
    }
129
130
    private function setConfigFile($configFile)
131
    {
132
        foreach ((array) $configFile as $file) {
133
            if (is_file($file)) {
134
                $this->configFile[] = $file;
135
            }
136
        }
137
        
138
        
139
140
        return $this;
141
    }
142
    /**
143
     * Load framework configuration from ini file
144
     * @return null
145
     */
146
    private function loadConfig()
147
    {
148
        $userConfig = array();
149
        if ($this->configFile !== null) {
150
            $userConfig = array();
151
            foreach ($this->configFile as $configFile) {
152
                $userConfig = array_merge($userConfig, parse_ini_file($configFile, true));
153
            }
154
155
            // Advanced ini parsing, split key with '.' into subarrays
156
            foreach ($userConfig as $section => $configData) {
157
                foreach ($configData as $name => $value) {
158
                    if (stripos($name, '.') !== false) {
159
                        $subkeys = explode('.', $name);
160
                        unset($userConfig[$section][$name]);
161
                        $str = "['" . implode("']['", $subkeys) . "'] = \$value;";
162
                        eval("\$userConfig[\$section]" . $str);
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
163
                    }
164
                }
165
            }
166
        }
167
168
        foreach ($this->getDefaultConfig() as $context => $directives) {
169
            if (isset($userConfig[$context])) {
170
                $this->config[$context] = array_merge($directives, $userConfig[$context]);
171
                unset($userConfig[$context]);
172
            } else {
173
                $this->config[$context] = $directives;
174
            }
175
        }
176
177
        $this->config = array_merge($this->config, $userConfig);
178
179
        $this->configureAppMode();
180
    }
181
182
    private function configureAppMode()
183
    {
184
        $errorReporting     = false;
185
        $errorDumpContext   = false;
186
        $logLevel           = Logger::LOGLEVEL_WARN;
187
        $logFile            = 'php://stdout';
188
        
189
        if (isset($this->config['App']['mode'])) {
190
            switch ($this->config['App']['mode']) {
191 View Code Duplication
                case App::DEVELOPMENT_MODE:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
192
                    $errorReporting     = true;
193
                    $errorDumpContext   = true;
194
                    $logLevel           = Logger::LOGLEVEL_INFO;
195
                    $logFile            = 'php://stdout';
196
                    break;
197 View Code Duplication
                case App::DEBUG_MODE:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
198
                    $errorReporting     = true;
199
                    $errorDumpContext   = true;
200
                    $logLevel           = Logger::LOGLEVEL_DEBUG;
201
                    $logFile            = 'php://stdout';
202
                    break;
203 View Code Duplication
                case App::PRELIVE_MODE:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
204
                    $errorReporting     = true;
205
                    $errorDumpContext   = false;
206
                    $logLevel           = Logger::LOGLEVEL_WARN;
207
                    $logFile            = 'php://stderr';
208
                    break;
209 View Code Duplication
                case App::PRODUCTION_MODE:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
210
                    $errorReporting     = false;
211
                    $errorDumpContext   = false;
212
                    $logLevel           = Logger::LOGLEVEL_WARN;
213
                    $logFile            = 'php://stderr';
214
                    break;
215
            }
216
        }
217
        if (isset($this->config['Logger']['level'])) {
218
            $logLevel = $this->config['Logger']['level'];
219
        }
220
        if (isset($this->config['Logger']['logfile'])) {
221
            $logFile = $this->config['Logger']['logfile'];
222
        }
223
        if (isset($this->config['Error']['report'])) {
224
            $errorReporting = $this->config['Error']['report'];
225
        }
226
        if (isset($this->config['Error']['dumpContext'])) {
227
            $errorDumpContext = $this->config['Error']['dumpContext'];
228
        }
229
230
        $this->config['Logger']['level']        = $logLevel;
231
        $this->config['Logger']['logfile']      = $logFile;
232
        $this->config['Error']['report']        = $errorReporting;
233
        $this->config['Error']['dumpContext']   =  $errorDumpContext;
234
    }
235
236
    private function getDefaultConfig()
237
    {
238
        return [
239
            'Router'    => [],
240 1
            'Session'   => ['type' => 'native'],
241
            'Logger'    => [
242 1
                'enabled'   => true,
243
            ],
244
            'App'       => ['base_uri' => '/'],
245 1
        ];
246
    }
247
248
    public function run()
249
    {
250
        self::$servicesContainer['Router']->doRouting();
251
    }
252
253
    public static function __callStatic($name, $arguments)
254
    {
255
        if (isset($arguments[0]) && $arguments[0] === true) {
256
            return clone self::$servicesRepository[$name];
257
        } else {
258
            return self::$servicesContainer[$name];
259
        }
260
    }
261
}
262