Completed
Pull Request — master (#2)
by Mathieu
05:06 queued 01:16
created

Suricate::hasService()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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