Completed
Push — master ( 28e5e2...3bec47 )
by Mathieu
01:38
created

Suricate::__callStatic()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.1406

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 8
ccs 3
cts 4
cp 0.75
crap 3.1406
rs 9.4285
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($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
        
187
        if (isset($this->config['App']['mode'])) {
188
            switch ($this->config['App']['mode']) {
189 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...
190
                    $errorReporting     = true;
191
                    $errorDumpContext   = true;
192
                    $logLevel           = Logger::LOGLEVEL_INFO;
193
                    break;
194 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...
195
                    $errorReporting     = true;
196
                    $errorDumpContext   = true;
197
                    $logLevel           = Logger::LOGLEVEL_DEBUG;
198
                    break;
199 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...
200
                    $errorReporting     = true;
201
                    $errorDumpContext   = false;
202
                    $logLevel           = Logger::LOGLEVEL_WARN;
203
                    break;
204 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...
205
                    $errorReporting     = false;
206
                    $errorDumpContext   = false;
207
                    $logLevel           = Logger::LOGLEVEL_WARN;
208
                    break;
209
            }
210
        }
211
212
        $this->config['Error']['report']        = $errorReporting;
213
        $this->config['Error']['dumpContext']   = $errorDumpContext;
214
        $this->config['Logger']['level']        = $logLevel;
215
    }
216
217
    /**
218
     * Default setup template
219
     * @return array setup
220
     */
221
    private function getDefaultConfig()
222
    {
223
        return array(
224
                'Router'    => array(),
225
                'Session'   => array('type' => 'native'),
226
                'Logger'    => array(
227
                                'logfile'   => 'php://output',
228
                                'enabled'   => true,
229
                                'level'     => Logger::LOGLEVEL_INFO,
230
                            ),
231
                'App'       => array('base_uri' => '/'),
232
                );
233
    }
234
235
    public function run()
236
    {
237
        self::$servicesContainer['Router']->doRouting();
238
    }
239
240 1
    public static function __callStatic($name, $arguments)
241
    {
242 1
        if (isset($arguments[0]) && $arguments[0] === true) {
243
            return clone self::$servicesRepository[$name];
244
        } else {
245 1
            return self::$servicesContainer[$name];
246
        }
247
    }
248
}
249