Completed
Push — master ( 64d284...b1eb46 )
by Mathieu
02:15 queued 46s
created

Suricate::initServices()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 32
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 15
c 1
b 0
f 0
nc 12
nop 0
dl 0
loc 32
rs 8.439
ccs 0
cts 21
cp 0
crap 42
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 $config;
28
    private $configFile;
29
30
    private $useAutoloader = false;
31
32
    private static $servicesContainer;
33
    private static $servicesRepository;
34
35
    private $servicesList = array(
36
        'Logger'            => '\Suricate\Logger',
37
        'App'               => '\Suricate\App',
38
        'I18n'              => '\Suricate\I18n',
39
        'Error'             => '\Suricate\Error',
40
        'Router'            => '\Suricate\Router',
41
        'Request'           => '\Suricate\Request',
42
        'Database'          => '\Suricate\Database',
43
        'Cache'             => '\Suricate\Cache',
44
        'CacheMemcache'     => '\Suricate\Cache\Memcache',
45
        'CacheApc'          => '\Suricate\Cache\Apc',
46
        'CacheFile'         => '\Suricate\Cache\File',
47
        'Curl'              => '\Suricate\Curl',
48
        'Response'          => '\Suricate\Request',
49
        'Session'           => '\Suricate\Session',
50
        'SessionNative'     => '\Suricate\Session\Native',
51
        'SessionCookie'     => '\Suricate\Session\Cookie',
52
        'SessionMemcache'   => '\Suricate\Session\Memcache',
53
    );
54
55
56
    public function __construct($paths = array(), $configFile = null)
57
    {
58
        if ($configFile !== null) {
59
            $this->setConfigFile($configFile);
60
        }
61
       
62
        // Load helpers
63
        require_once __DIR__ . DIRECTORY_SEPARATOR . 'Helper.php';
64
65
        $this->loadConfig();
66
        $this->setAppPaths($paths);
67
68
        if ($this->useAutoloader) {
69
            // Configure autoloader
70
            require_once __DIR__ . DIRECTORY_SEPARATOR . 'AutoLoader.php';
71
            AutoLoader::register();
72
        }
73
74
        // Define error handler
75
        set_exception_handler(array('\Suricate\Error', 'handleException'));
76
        set_error_handler(array('\Suricate\Error', 'handleError'));
77
        register_shutdown_function(array('\Suricate\Error', 'handleShutdownError'));
78
79
        self::$servicesRepository = new Container();
80
81
        $this->initServices();
82
    }
83
84
    private function setAppPaths($paths = array())
85
    {
86
        foreach ($paths as $key => $value) {
87
            $this->config['App']['path.' . $key] = realpath($value);
88
        }
89
90
        return $this;
91
    }
92
    /**
93
     * Initialize Framework services
94
     * @return null
95
     */
96
    private function initServices()
97
    {
98
        self::$servicesRepository->setWarehouse($this->servicesList);
99
100
        self::$servicesRepository['Request']->parse();
101
        if (isset($this->config['App']['locale'])) {
102
            $this->config['I18n'] = array('locale' => $this->config['App']['locale']);
103
        }
104
        // first sync, && init, dependency to Suricate::request
105
        self::$servicesContainer = clone self::$servicesRepository;
106
107
        foreach (array_keys($this->servicesList) as $serviceName) {
108
            if (isset($this->config[$serviceName])) {
109
                self::$servicesRepository[$serviceName]->configure($this->config[$serviceName]);
110
111
                /**
112
                 TODO : remove sync in service creation
113
                */
114
                self::$servicesContainer = clone self::$servicesRepository;
115
            }
116
        }
117
118
        if (isset($this->config['Constants'])) {
119
            foreach ($this->config['Constants'] as $constantName => $constantValue) {
120
                $constantName = strtoupper($constantName);
121
                define($constantName, $constantValue);
122
            }
123
        }
124
125
        // final sync, repository is complete
126
        self::$servicesContainer = clone self::$servicesRepository;
127
    }
128
129
    private function setConfigFile($configFile)
130
    {
131
        foreach ((array) $configFile as $file) {
132
            if (is_file($file)) {
133
                $this->configFile[] = $file;
134
            }
135
        }
136
        
137
        
138
139
        return $this;
140
    }
141
    /**
142
     * Load framework configuration from ini file
143
     * @return null
144
     */
145
    private function loadConfig()
146
    {
147
        $userConfig = array();
148
        if ($this->configFile !== null) {
149
            $userConfig = array();
150
            foreach ($this->configFile as $configFile) {
151
                $userConfig = array_merge_recursive($userConfig, parse_ini_file($configFile, true));
152
            }
153
154
            // Advanced ini parsing, split key with '.' into subarrays
155
            foreach ($userConfig as $section => $configData) {
156
                foreach ($configData as $name => $value) {
157
                    if (stripos($name, '.') !== false) {
158
                        $subkeys = explode('.', $name);
159
                        unset($userConfig[$section][$name]);
160
                        $str = "['" . implode("']['", $subkeys) . "'] = \$value;";
161
                        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...
162
                    }
163
                }
164
            }
165
        }
166
167
        foreach ($this->getDefaultConfig() as $context => $directives) {
168
            if (isset($userConfig[$context])) {
169
                $this->config[$context] = array_merge($directives, $userConfig[$context]);
170
                unset($userConfig[$context]);
171
            } else {
172
                $this->config[$context] = $directives;
173
            }
174
        }
175
176
        $this->config = array_merge($this->config, $userConfig);
177
178
        $this->configureAppMode();
179
    }
180
181
    private function configureAppMode()
182
    {
183
        $errorReporting     = false;
184
        $errorDumpContext   = false;
185
        $logLevel           = Logger::LOGLEVEL_WARN;
186
        $logFile            = 'php://stdout';
187
        
188
        if (isset($this->config['App']['mode'])) {
189
            switch ($this->config['App']['mode']) {
190 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...
191
                    $errorReporting     = true;
192
                    $errorDumpContext   = true;
193
                    $logLevel           = Logger::LOGLEVEL_INFO;
194
                    $logFile            = 'php://stdout';
195
                    break;
196 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...
197
                    $errorReporting     = true;
198
                    $errorDumpContext   = true;
199
                    $logLevel           = Logger::LOGLEVEL_DEBUG;
200
                    $logFile            = 'php://stdout';
201
                    break;
202 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...
203
                    $errorReporting     = true;
204
                    $errorDumpContext   = false;
205
                    $logLevel           = Logger::LOGLEVEL_WARN;
206
                    $logFile            = 'php://stderr';
207
                    break;
208 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...
209
                    $errorReporting     = false;
210
                    $errorDumpContext   = false;
211
                    $logLevel           = Logger::LOGLEVEL_WARN;
212
                    $logFile            = 'php://stderr';
213
                    break;
214
            }
215
        }
216
        if (isset($this->config['Logger']['level'])) {
217
            $logLevel = $this->config['Logger']['level'];
218
        }
219
        if (isset($this->config['Logger']['logfile'])) {
220
            $logFile = $this->config['Logger']['logfile'];
221
        }
222
        if (isset($this->config['Error']['report'])) {
223
            $errorReporting = $this->config['Error']['report'];
224
        }
225
        if (isset($this->config['Error']['dumpContext'])) {
226
            $errorDumpContext = $this->config['Error']['dumpContext'];
227
        }
228
229
        $this->config['Logger']['level']        = $logLevel;
230
        $this->config['Logger']['logfile']      = $logFile;
231
        $this->config['Error']['report']        = $errorReporting;
232
        $this->config['Error']['dumpContext']   =  $errorDumpContext;
233
    }
234
    /**
235
     * Default setup template
236
     * @return array setup
237
     */
238
    private function getDefaultConfig()
239
    {
240
        return [
241
            'Router'    => [],
242
            'Session'   => ['type' => 'native'],
243
            'Logger'    => [
244
                'enabled'   => true,
245
            ],
246
            'App'       => ['base_uri' => '/'],
247
        ];
248
    }
249
250
    public function run()
251
    {
252
        self::$servicesContainer['Router']->doRouting();
253
    }
254
255 1
    public static function __callStatic($name, $arguments)
256
    {
257 1
        if (isset($arguments[0]) && $arguments[0] === true) {
258
            return clone self::$servicesRepository[$name];
259
        } else {
260 1
            return self::$servicesContainer[$name];
261
        }
262
    }
263
}
264