Test Failed
Push — 1.0.0-dev ( 877729...f17fe5 )
by nguereza
02:30
created

save_to_log()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
nc 2
nop 3
dl 0
loc 6
rs 10
c 1
b 0
f 0
1
<?php
2
    defined('ROOT_PATH') || exit('Access denied');
3
    /**
4
     * TNH Framework
5
     *
6
     * A simple PHP framework using HMVC architecture
7
     *
8
     * This content is released under the MIT License (MIT)
9
     *
10
     * Copyright (c) 2017 TNH Framework
11
     *
12
     * Permission is hereby granted, free of charge, to any person obtaining a copy
13
     * of this software and associated documentation files (the "Software"), to deal
14
     * in the Software without restriction, including without limitation the rights
15
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
     * copies of the Software, and to permit persons to whom the Software is
17
     * furnished to do so, subject to the following conditions:
18
     *
19
     * The above copyright notice and this permission notice shall be included in all
20
     * copies or substantial portions of the Software.
21
     *
22
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
     * SOFTWARE.
29
     */
30
31
    /**
32
     *  @file common.php
33
     *  
34
     *  Contains most of the commons functions used by the system
35
     *  
36
     *  @package	core
37
     *  @author	TNH Framework team
38
     *  @copyright	Copyright (c) 2017
39
     *  @license	http://opensource.org/licenses/MIT	MIT License
40
     *  @link	http://www.iacademy.cf
41
     *  @version 1.0.0
42
     *  @filesource
43
     */
44
	
45
46
    /**
47
     * This function is the class loader helper is used if the library "Loader" not yet loaded
48
     * he load the class once
49
     * @param  string $class  the class name to be loaded
50
     * @param  string $dir    the directory where to find the class
51
     * @param  mixed $params the parameter to pass as argument to the constructor of the class
52
     * @codeCoverageIgnore
53
     * 
54
     * @return object         the instance of the loaded class
55
     */
56
    function & class_loader($class, $dir = 'libraries', $params = null){
57
        //put the first letter of class to upper case 
58
        $class = ucfirst($class);
59
        static $classes = array();
60
        if (isset($classes[$class]) /*hack for duplicate log Logger name*/ && $class != 'Log') {
61
            return $classes[$class];
62
        }
63
        $found = false;
64
        foreach (array(APPS_PATH, CORE_PATH) as $path) {
65
            $file = $path . $dir . DS . $class . '.php';
66
            if (file_exists($file)) {
67
                require_once $file;
68
                //already found
69
                $found = true;
70
                break;
71
            }
72
        }
73
        if (!$found) {
74
            //can't use show_error() at this time because some dependencies not yet loaded
75
            set_http_status_header(503);
76
            echo 'Cannot find the class [' . $class . ']';
77
            die();
78
        }
79
		
80
        /*
81
		   TODO use the best method to get the Log instance
82
		 */
83
        if ($class == 'Log') {
84
            //can't use the instruction like "return new Log()" 
85
            //because we need return the reference instance of the loaded class.
86
            $log = new Log();
87
            return $log;
88
        }
89
        //track of loaded classes
90
        class_loaded($class);
91
		
92
        //record the class instance
93
        $classes[$class] = isset($params) ? new $class($params) : new $class();
94
		
95
        return $classes[$class];
96
    }
97
98
    /**
99
     * This function is the helper to record the loaded classes
100
     * @param  string $class the loaded class name
101
     * @codeCoverageIgnore
102
     * 
103
     * @return array        the list of the loaded classes
104
     */
105
    function & class_loaded($class = null){
106
        static $list = array();
107
        if ($class !== null) {
108
            $list[strtolower($class)] = $class;
109
        }
110
        return $list;
111
    }
112
113
    /**
114
     * This function is used to load the configurations in the 
115
     * case the "Config" library not yet loaded
116
     * @codeCoverageIgnore
117
     * 
118
     * @return array  the configurations values
119
     */
120
    function & load_configurations(){
121
        static $config;
122
        if (empty($config)) {
123
            $file = CONFIG_PATH . 'config.php';
124
            $found = false;
125
            if (file_exists($file)) {
126
                require_once $file;
127
                $found = true;
128
            }
129
            if (!$found) {
130
                set_http_status_header(503);
131
                echo 'Unable to find the configuration file [' . $file . ']';
132
                die();
133
            }
134
        }
135
        return $config;
136
    }
137
138
    /**
139
     * This function is the helper to get the config value in case the "Config" library not yet loaded
140
     * @param  string $key     the config item to get the vale
141
     * @param  mixed $default the default value to return if can't find the config item in the configuration
142
     * @test
143
     * 
144
     * @return mixed          the config value
145
     */
146
    function get_config($key, $default = null) {
147
        static $cfg;
148
        if (empty($cfg)) {
149
            $cfg[0] = & load_configurations();
150
            if(! is_array($cfg[0])){
151
                $cfg[0] = array();
152
            }
153
        }
154
        return array_key_exists($key, $cfg[0]) ? $cfg[0][$key] : $default;
155
    }
156
157
    /**
158
     *  This function displays an error message to the user and ends the 
159
     *  execution of the script.
160
     *  
161
     *  @param string $msg the message to display
162
     *  @param string $title the message title: "error", "info", "warning", etc.
163
     *  @param boolean $logging either to save error in log
164
     *  @param string $logLevel the log level to use
165
     *  
166
     *  @codeCoverageIgnore
167
     */
168
    function show_error($msg, $title = 'error', $logging = true, $logLevel = 'ERROR') {
169
        $title = strtoupper($title);
170
        $data = array();
171
        $data['error'] = $msg;
172
        $data['title'] = $title;
173
        if ($logging) {
174
            $log = & class_loader('Log', 'classes');
175
            $log->setLogger('APP::ERROR');
176
            $log->log($logLevel, strip_tags($msg));
177
        }
178
        $response = & class_loader('Response', 'classes');
179
        $response->sendError($data);
180
        die();
181
    }
182
183
     /**
184
     *  Function defined for PHP error message handling
185
     *              
186
     *  @param int $errno the type of error for example: E_USER_ERROR, E_USER_WARNING, etc.
187
     *  @param string $errstr the error message
188
     *  @param string $errfile the file where the error occurred
189
     *  @param int $errline the line number where the error occurred
190
     *  @codeCoverageIgnore
191
     *  
192
     *  @return boolean 
193
     */
194
    function fw_error_handler($errno, $errstr, $errfile, $errline) {
195
        $isError = (((E_ERROR | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $errno) === $errno);
196
        if ($isError) {
197
            set_http_status_header(500);
198
        }
199
        $errorType = 'Error';
200
        $errorsType = array (
201
                E_ERROR              => 'Error',
202
                E_WARNING            => 'Warning',
203
                E_PARSE              => 'Parsing Error',
204
                E_NOTICE             => 'Notice',
205
                E_CORE_ERROR         => 'Core Error',
206
                E_CORE_WARNING       => 'Core Warning',
207
                E_COMPILE_ERROR      => 'Compile Error',
208
                E_COMPILE_WARNING    => 'Compile Warning',
209
                E_USER_ERROR         => 'User Error',
210
                E_USER_WARNING       => 'User Warning',
211
                E_USER_NOTICE        => 'User Notice',
212
                E_STRICT             => 'Runtime Notice',
213
                E_RECOVERABLE_ERROR  => 'Catchable Fatal Error'
214
        );
215
        if (isset($errorsType[$errno])) {
216
           $errorType = $errorsType[$errno];
217
        }
218
        $errorText = 'An error is occurred in the file ' . $errfile . ' at line ' . $errline . ' raison : ' . $errstr;
219
        if ((error_reporting() & $errno) !== $errno) {
220
            return;
221
        }
222
        if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors'))) {
223
            show_error($errorText, 'PHP ' . $errorType);
224
        } else {
225
            $log = & class_loader('Log', 'classes');
226
            $log->setLogger('PHP ' . $errorType);
227
            $log->critical($errorText);
228
        }
229
        if ($isError) {
230
            die();
231
        }
232
        return true;
233
    }
234
235
    /**
236
     *  Function defined for handling PHP exception error message, 
237
     *  it displays an error message using the function "show_error"
238
     *  
239
     *  @param object $ex instance of the "Exception" class or a derived class
240
     *  @codeCoverageIgnore
241
     *  
242
     *  @return boolean
243
     */
244
    function fw_exception_handler($ex) {
245
        $errorText = 'An exception is occured in file ' . $ex->getFile() . ' at line ' . $ex->getLine() . ' raison : ' . $ex->getMessage();
246
        if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors'))) {
247
            show_error($errorText, 'PHP Exception #' . $ex->getCode());
248
        } else {
249
            $log = & class_loader('Log', 'classes');
250
            $log->setLogger('PHP Exception #' . $ex->getCode());
251
            $log->critical($errorText);
252
        }
253
        return true;
254
    }
255
    
256
    /**
257
     * This function is used to run in shutdown situation of the script
258
     * @codeCoverageIgnore
259
     */
260
    function fw_shudown_handler() {
261
        $lastError = error_get_last();
262
        if (is_array($lastError) &&
263
            ($lastError['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING))) {
264
            fw_error_handler($lastError['type'], $lastError['message'], $lastError['file'], $lastError['line']);
265
        }
266
    }
267
268
    /**
269
     * Set the HTTP status header
270
     * @param integer $code the HTTP status code
271
     * @param string  $text the HTTP status text
272
     * 
273
     * @codeCoverageIgnore
274
     */
275
    function set_http_status_header($code = 200, $text = null) {
276
        if (empty($text)) {
277
            $httpStatus = array(
278
                                100 => 'Continue',
279
                                101 => 'Switching Protocols',
280
                                200 => 'OK',
281
                                201 => 'Created',
282
                                202 => 'Accepted',
283
                                203 => 'Non-Authoritative Information',
284
                                204 => 'No Content',
285
                                205 => 'Reset Content',
286
                                206 => 'Partial Content',
287
                                300 => 'Multiple Choices',
288
                                301 => 'Moved Permanently',
289
                                302 => 'Found',
290
                                303 => 'See Other',
291
                                304 => 'Not Modified',
292
                                305 => 'Use Proxy',
293
                                307 => 'Temporary Redirect',
294
                                400 => 'Bad Request',
295
                                401 => 'Unauthorized',
296
                                402 => 'Payment Required',
297
                                403 => 'Forbidden',
298
                                404 => 'Not Found',
299
                                405 => 'Method Not Allowed',
300
                                406 => 'Not Acceptable',
301
                                407 => 'Proxy Authentication Required',
302
                                408 => 'Request Timeout',
303
                                409 => 'Conflict',
304
                                410 => 'Gone',
305
                                411 => 'Length Required',
306
                                412 => 'Precondition Failed',
307
                                413 => 'Request Entity Too Large',
308
                                414 => 'Request-URI Too Long',
309
                                415 => 'Unsupported Media Type',
310
                                416 => 'Requested Range Not Satisfiable',
311
                                417 => 'Expectation Failed',
312
                                418 => 'I\'m a teapot',
313
                                500 => 'Internal Server Error',
314
                                501 => 'Not Implemented',
315
                                502 => 'Bad Gateway',
316
                                503 => 'Service Unavailable',
317
                                504 => 'Gateway Timeout',
318
                                505 => 'HTTP Version Not Supported',
319
                            );
320
            if (isset($httpStatus[$code])) {
321
                $text = $httpStatus[$code];
322
            } else {
323
                show_error('No HTTP status text found for your code please check it.');
324
            }
325
        }
326
        
327
        if (strpos(php_sapi_name(), 'cgi') === 0) {
328
            header('Status: ' . $code . ' ' . $text, TRUE);
329
        } else {
330
            $globals = & class_loader('GlobalVar', 'classes');
331
            $proto = 'HTTP/1.1';
332
            if ($globals->server('SERVER_PROTOCOL')) {
333
                $proto = $globals->server('SERVER_PROTOCOL');
334
            }
335
            header($proto . ' ' . $code . ' ' . $text, TRUE, $code);
336
        }
337
    }
338
339
340
    /**
341
     *  Check whether the protocol used is "https" or not
342
     *  That is, the web server is configured to use a secure connection.
343
     *  @codeCoverageIgnore
344
     *  
345
     *  @return boolean true if the web server uses the https protocol, false if not.
346
     */
347
    function is_https() {
348
        /*
349
		* some servers pass the "HTTPS" parameter in the server variable,
350
		* if is the case, check if the value is "on", "true", "1".
351
		*/
352
        $globals = & class_loader('GlobalVar', 'classes');
353
        if ($globals->server('HTTPS') && strtolower($globals->server('HTTPS')) !== 'off') {
354
            return true;
355
        }
356
        if ($globals->server('HTTP_X_FORWARDED_PROTO') && $globals->server('HTTP_X_FORWARDED_PROTO') === 'https') {
357
            return true;
358
        }
359
        if ($globals->server('HTTP_FRONT_END_HTTPS') && strtolower($globals->server('HTTP_FRONT_END_HTTPS')) !== 'off') {
360
            return true;
361
        }
362
        return false;
363
    }
364
	
365
    /**
366
     *  This function is used to check the URL format of the given string argument. 
367
     *  The address is valid if the protocol is http, https, ftp, etc.
368
     *
369
     *  @param string $url the URL address to check
370
     *  @test
371
     *  
372
     *  @return boolean true if is a valid URL address or false.
373
     */
374
    function is_url($url) {
375
        return preg_match('/^(http|https|ftp):\/\/(.*)/', $url) == 1;
376
    }
377
	
378
    /**
379
     *  Function defined to load controller
380
     *  
381
     *  @param string $controllerClass the controller class name to be loaded
382
     *  @codeCoverageIgnore
383
     */
384
    function autoload_controller($controllerClass) {
385
        if (file_exists($path = APPS_CONTROLLER_PATH . $controllerClass . '.php')) {
386
            require_once $path;
387
        }
388
    }
389
390
    /**
391
     *  Convert array attributes to string
392
     *
393
     *  This function converts an associative array into HTML attributes.
394
     *  For example :
395
     *  $a = array('name' => 'Foo', 'type' => 'text'); => produces the following string:
396
     *  name = "Foo" type = "text"
397
     *
398
     *  @param array $attributes associative array to convert to a string attribute.
399
     *   
400
     *  @return string string of the HTML attribute.
401
     */
402
    function attributes_to_string(array $attributes) {
403
        $str = ' ';
404
        //we check that the array passed as an argument is not empty.
405
        if (!empty($attributes)) {
406
            foreach ($attributes as $key => $value) {
407
                $key = trim(htmlspecialchars($key));
408
                $value = trim(htmlspecialchars($value));
409
                /*
410
				* To predict the case where the string to convert contains the character "
411
				* we check if this is the case we add a slash to solve this problem.
412
				* For example:
413
				* 	$attr = array('placeholder' => 'I am a "puple"')
414
				* 	$str = attributes_to_string($attr); => placeholder = "I am a \"puple\""
415
				 */
416
                if ($value && strpos('"', $value) !== false) {
417
                    $value = addslashes($value);
418
                }
419
                $str .= $key . ' = "' . $value . '" ';
420
            }
421
        }
422
        //remove the space after using rtrim()
423
        return rtrim($str);
424
    }
425
426
427
    /**
428
     * Function to stringfy PHP variable, useful in debug situation
429
     *
430
     * @param mixed $var the variable to stringfy
431
     * @codeCoverageIgnore
432
     *
433
     * @return string the stringfy value
434
     */
435
    function stringfy_vars($var) {
436
        return print_r($var, true);
437
    }
438
439
    /**
440
     * Clean the user input
441
     * @param  mixed $str the value to clean
442
     * @test
443
     * 
444
     * @return mixed   the sanitize value
445
     */
446
    function clean_input($str) {
447
        if (is_array($str)) {
448
            $str = array_map('clean_input', $str);
449
        } else if (is_object($str)) {
450
            $obj = $str;
451
            foreach ($str as $var => $value) {
452
                $obj->$var = clean_input($value);
453
            }
454
            $str = $obj;
455
        } else {
456
            $str = htmlspecialchars(strip_tags($str), ENT_QUOTES, 'UTF-8');
457
        }
458
        return $str;
459
    }
460
	
461
    /**
462
     * This function is used to hidden some part of the given string. Helpful if you need hide some confidential 
463
     * Information like credit card number, password, etc.
464
     *
465
     * @param  string $str the string you want to hide some part
466
     * @param  int $startCount the length of non hidden for the beginning char
467
     * @param  int $endCount the length of non hidden for the ending char
468
     * @param  string $hiddenChar the char used to hide the given string
469
     * @test
470
     * 
471
     * @return string the string with the hidden part.
472
     */
473
    function string_hidden($str, $startCount = 0, $endCount = 0, $hiddenChar = '*') {
474
        //get the string length
475
        $len = strlen($str);
476
        //if str is empty
477
        if ($len <= 0) {
478
            return str_repeat($hiddenChar, 6);
479
        }
480
        //if the length is less than startCount and endCount
481
        //or the startCount and endCount length is 0
482
        //or startCount is negative or endCount is negative
483
        //return the full string hidden
484
		
485
        if ((($startCount + $endCount) > $len) || ($startCount == 0 && $endCount == 0) || ($startCount < 0 || $endCount < 0)) {
486
            return str_repeat($hiddenChar, $len);
487
        }
488
        //the start non hidden string
489
        $startNonHiddenStr = substr($str, 0, $startCount);
490
        //the end non hidden string
491
        $endNonHiddenStr = null;
492
        if ($endCount > 0) {
493
            $endNonHiddenStr = substr($str, - $endCount);
494
        }
495
        //the hidden string
496
        $hiddenStr = str_repeat($hiddenChar, $len - ($startCount + $endCount));
497
		
498
        return $startNonHiddenStr . $hiddenStr . $endNonHiddenStr;
499
    }
500
	
501
    /**
502
     * This function is very useful, it allows to use the shared instance of 
503
     * the super controller in of all parts of your application.
504
     * 
505
     * NOTE: this function always returns the reference of the super instance.
506
     * For example :
507
     * $obj = & get_instance();
508
     * 
509
     * @codeCoverageIgnore
510
     *  
511
     * @return object the instance of the "Controller" class
512
     */
513
    function & get_instance(){
514
        return Controller::getInstance();
515
    }
516