Test Failed
Push — 1.0.0-dev ( dc6bfa...14bd99 )
by nguereza
02:55
created

Loader::loadLibrary()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 4
nop 4
dl 0
loc 17
rs 9.8333
c 0
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 GNU GPL License (GPL)
9
	 *
10
	 * Copyright (C) 2017 Tony NGUEREZA
11
	 *
12
	 * This program is free software; you can redistribute it and/or
13
	 * modify it under the terms of the GNU General Public License
14
	 * as published by the Free Software Foundation; either version 3
15
	 * of the License, or (at your option) any later version.
16
	 *
17
	 * This program is distributed in the hope that it will be useful,
18
	 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
	 * GNU General Public License for more details.
21
	 *
22
	 * You should have received a copy of the GNU General Public License
23
	 * along with this program; if not, write to the Free Software
24
	 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25
	*/
26
	class Loader{
27
		
28
		/**
29
		 * List of loaded resources
30
		 * @var array
31
		 */
32
		public static $loaded = array();
33
		
34
		/**
35
		 * The logger instance
36
		 * @var object
37
		 */
38
		private static $logger;
39
40
41
		public function __construct(){
42
			//add the resources already loaded during application bootstrap
43
			//in the list to prevent duplicate or loading the resources again.
44
			static::$loaded = class_loaded();
45
			
46
			//Load resources from autoload configuration
47
			$this->loadResourcesFromAutoloadConfig();
48
		}
49
50
		/**
51
		 * The signleton of the logger
52
		 * @return object the Log instance
53
		 */
54
		private static function getLogger(){
55
			if(self::$logger == null){
56
				$logger = array();
57
				$logger[0] =& class_loader('Log', 'classes');
58
				$logger[0]->setLogger('Library::Loader');
59
				self::$logger = $logger[0];
60
			}
61
			return self::$logger;			
62
		}
63
64
		/**
65
		 * Set the log instance for future use
66
		 * @param object $logger the log object
67
		 * @return object the log instance
68
		 */
69
		public static function setLogger($logger){
70
			self::$logger = $logger;
71
			return self::$logger;
72
		}
73
74
		
75
		/**
76
		 * Load the model class
77
		 *
78
		 * @param  string $class    the class name to be loaded
79
		 * @param  string $instance the name of the instance to use in super object
80
		 *
81
		 * @return void
82
		 */
83
		public static function model($class, $instance = null){
84
			$logger = static::getLogger();
85
			$class = str_ireplace('.php', '', $class);
86
			$class = trim($class, '/\\');
87
			$file = ucfirst($class).'.php';
88
			$logger->debug('Loading model [' . $class . '] ...');
89
			//************
90
			if (! $instance){
91
				$instance = self::getModelLibraryInstanceName($class);
92
			}
93
			//****************
94
			if (isset(static::$loaded[$instance])){
95
				$logger->info('Model [' . $class . '] already loaded no need to load it again, cost in performance');
96
				return;
97
			}
98
			$classFilePath = APPS_MODEL_PATH . $file;
99
			//first check if this model is in the module
100
			$logger->debug('Checking model [' . $class . '] from module list ...');
101
			//check if the request class contains module name
102
			$moduleInfo = self::getModuleInfoForModelLibrary($class);
103
			$module = $moduleInfo['module'];
104
			$class  = $moduleInfo['class'];
105
			
106
			$moduleModelFilePath = Module::findModelFullPath($class, $module);
107
			if ($moduleModelFilePath){
108
				$logger->info('Found model [' . $class . '] from module [' .$module. '], the file path is [' .$moduleModelFilePath. '] we will used it');
109
				$classFilePath = $moduleModelFilePath;
110
			}
111
			else{
112
				$logger->info('Cannot find model [' . $class . '] from modules using the default location');
113
			}
114
			$logger->info('The model file path to be loaded is [' . $classFilePath . ']');
115
			if (file_exists($classFilePath)){
116
				require_once $classFilePath;
117
				if (class_exists($class)){
118
					$c = new $class();
119
					$obj = & get_instance();
120
					$obj->{$instance} = $c;
121
					static::$loaded[$instance] = $class;
122
					$logger->info('Model [' . $class . '] --> ' . $classFilePath . ' loaded successfully.');
123
				}
124
				else{
125
					show_error('The file '.$classFilePath.' exists but does not contain the class ['. $class . ']');
126
				}
127
			}
128
			else{
129
				show_error('Unable to find the model [' . $class . ']');
130
			}
131
		}
132
133
		
134
		/**
135
		 * Load the library class
136
		 *
137
		 * @param  string $class    the library class name to be loaded
138
		 * @param  string $instance the instance name to use in super object
139
		 * @param mixed $params the arguments to pass to the constructor
140
		 *
141
		 * @return void
142
		 */
143
		public static function library($class, $instance = null, array $params = array()){
144
			$logger = static::getLogger();
145
			$class = str_ireplace('.php', '', $class);
146
			$class = trim($class, '/\\');
147
			$file = ucfirst($class) .'.php';
148
			$logger->debug('Loading library [' . $class . '] ...');
149
			if (! $instance){
150
				$instance = self::getModelLibraryInstanceName($class);
151
			}
152
			if (isset(static::$loaded[$instance])){
153
				$logger->info('Library [' . $class . '] already loaded no need to load it again, cost in performance');
154
				return;
155
			}
156
			$obj = & get_instance();
157
			//Check and load Database library
158
			if (strtolower($class) == 'database'){
159
				$logger->info('This is the Database library ...');
160
				$obj->{$instance} = & class_loader('Database', 'classes/database', $params);
161
				static::$loaded[$instance] = $class;
162
				$logger->info('Library Database loaded successfully.');
163
				return;
164
			}
165
			$libraryFilePath = null;
166
			$logger->debug('Check if this is a system library ...');
167
			if (file_exists(CORE_LIBRARY_PATH . $file)){
168
				$libraryFilePath = CORE_LIBRARY_PATH . $file;
169
				$class = ucfirst($class);
170
				$logger->info('This library is a system library');
171
			}
172
			else{
173
				$logger->info('This library is not a system library');	
174
				//first check if this library is in the module
175
				$libraryFilePath = self::getLibraryPathUsingModuleInfo($class);
176
				//***************
177
			}
178
			if (! $libraryFilePath && file_exists(LIBRARY_PATH . $file)){
179
				$libraryFilePath = LIBRARY_PATH . $file;
180
			}
181
			$logger->info('The library file path to be loaded is [' . $libraryFilePath . ']');
182
			//*************************
183
			self::loadLibrary($libraryFilePath, $class, $instance, $params);
184
		}
185
186
		/**
187
		 * Load the helper
188
		 *
189
		 * @param  string $function the helper name to be loaded
190
		 *
191
		 * @return void
192
		 */
193
		public static function functions($function){
194
			$logger = static::getLogger();
195
			$function = str_ireplace('.php', '', $function);
196
			$function = trim($function, '/\\');
197
			$function = str_ireplace('function_', '', $function);
198
			$file = 'function_'.$function.'.php';
199
			$logger->debug('Loading helper [' . $function . '] ...');
200
			if (isset(static::$loaded['function_' . $function])){
201
				$logger->info('Helper [' . $function . '] already loaded no need to load it again, cost in performance');
202
				return;
203
			}
204
			$functionFilePath = null;
205
			//first check if this helper is in the module
206
			$logger->debug('Checking helper [' . $function . '] from module list ...');
207
			$moduleInfo = self::getModuleInfoForFunction($function);
208
			$module    = $moduleInfo['module'];
209
			$function  = $moduleInfo['function'];
210
			if(! empty($moduleInfo['file'])){
211
				$file = $moduleInfo['file'];
212
			}
213
			$moduleFunctionPath = Module::findFunctionFullPath($function, $module);
214
			if ($moduleFunctionPath){
215
				$logger->info('Found helper [' . $function . '] from module [' .$module. '], the file path is [' .$moduleFunctionPath. '] we will used it');
216
				$functionFilePath = $moduleFunctionPath;
217
			}
218
			else{
219
				$logger->info('Cannot find helper [' . $function . '] from modules using the default location');
220
			}
221
			if (! $functionFilePath){
222
				$searchDir = array(FUNCTIONS_PATH, CORE_FUNCTIONS_PATH);
223
				foreach($searchDir as $dir){
224
					$filePath = $dir . $file;
225
					if (file_exists($filePath)){
226
						$functionFilePath = $filePath;
227
						//is already found not to continue
228
						break;
229
					}
230
				}
231
			}
232
			$logger->info('The helper file path to be loaded is [' . $functionFilePath . ']');
233
			if ($functionFilePath){
234
				require_once $functionFilePath;
235
				static::$loaded['function_' . $function] = $functionFilePath;
236
				$logger->info('Helper [' . $function . '] --> ' . $functionFilePath . ' loaded successfully.');
237
			}
238
			else{
239
				show_error('Unable to find helper file [' . $file . ']');
240
			}
241
		}
242
243
		/**
244
		 * Load the configuration file
245
		 *
246
		 * @param  string $filename the configuration filename located at CONFIG_PATH or MODULE_PATH/config
247
		 *
248
		 * @return void
249
		 */
250
		public static function config($filename){
251
			$logger = static::getLogger();
252
			$filename = str_ireplace('.php', '', $filename);
253
			$filename = trim($filename, '/\\');
254
			$filename = str_ireplace('config_', '', $filename);
255
			$file = 'config_'.$filename.'.php';
256
			$logger->debug('Loading configuration [' . $filename . '] ...');
257
			if (isset(static::$loaded['config_' . $filename])){
258
				$logger->info('Configuration [' . $file . '] already loaded no need to load it again, cost in performance');
259
				return;
260
			}
261
			$configFilePath = CONFIG_PATH . $file;
262
			//first check if this config is in the module
263
			$logger->debug('Checking config [' . $filename . '] from module list ...');
264
			$moduleInfo = self::getModuleInfoForConfig($filename);
265
			$module    = $moduleInfo['module'];
266
			$filename  = $moduleInfo['filename'];
267
			$moduleConfigPath = Module::findConfigFullPath($filename, $module);
268
			if ($moduleConfigPath){
269
				$logger->info('Found config [' . $filename . '] from module [' .$module. '], the file path is [' .$moduleConfigPath. '] we will used it');
270
				$configFilePath = $moduleConfigPath;
271
			}
272
			else{
273
				$logger->info('Cannot find config [' . $filename . '] from modules using the default location');
274
			}
275
			$logger->info('The config file path to be loaded is [' . $configFilePath . ']');
276
			$config = array();
277
			if (file_exists($configFilePath)){
278
				require_once $configFilePath;
279
				if (! empty($config) && is_array($config)){
280
					Config::setAll($config);
281
					static::$loaded['config_' . $filename] = $configFilePath;
282
					$logger->info('Configuration [' . $configFilePath . '] loaded successfully.');
283
					$logger->info('The custom application configuration loaded are listed below: ' . stringfy_vars($config));
284
					unset($config);
285
				}
286
			}
287
			else{
288
				show_error('Unable to find config file ['. $configFilePath . ']');
289
			}
290
		}
291
292
293
		/**
294
		 * Load the language
295
		 *
296
		 * @param  string $language the language name to be loaded
297
		 *
298
		 * @return void
299
		 */
300
		public static function lang($language){
301
			$logger = static::getLogger();
302
			$language = str_ireplace('.php', '', $language);
303
			$language = trim($language, '/\\');
304
			$language = str_ireplace('lang_', '', $language);
305
			$file = 'lang_'.$language.'.php';
306
			$logger->debug('Loading language [' . $language . '] ...');
307
			if (isset(static::$loaded['lang_' . $language])){
308
				$logger->info('Language [' . $language . '] already loaded no need to load it again, cost in performance');
309
				return;
310
			}
311
			//get the current language
312
			$appLang = self::getAppLang();
313
			$languageFilePath = null;
314
			//first check if this language is in the module
315
			$logger->debug('Checking language [' . $language . '] from module list ...');
316
			$moduleInfo = self::getModuleInfoForLanguage($language);
317
			$module    = $moduleInfo['module'];
318
			$language  = $moduleInfo['language'];
319
			if(! empty($moduleInfo['file'])){
320
				$file = $moduleInfo['file'];
321
			}
322
			$moduleLanguagePath = Module::findLanguageFullPath($language, $module, $appLang);
323
			if ($moduleLanguagePath){
324
				$logger->info('Found language [' . $language . '] from module [' .$module. '], the file path is [' .$moduleLanguagePath. '] we will used it');
325
				$languageFilePath = $moduleLanguagePath;
326
			}
327
			else{
328
				$logger->info('Cannot find language [' . $language . '] from modules using the default location');
329
			}
330
			if (! $languageFilePath){
331
				$searchDir = array(APP_LANG_PATH, CORE_LANG_PATH);
332
				foreach($searchDir as $dir){
333
					$filePath = $dir . $appLang . DS . $file;
334
					if (file_exists($filePath)){
335
						$languageFilePath = $filePath;
336
						//already found no need continue
337
						break;
338
					}
339
				}
340
			}
341
			$logger->info('The language file path to be loaded is [' . $languageFilePath . ']');
342
			self::loadLanguage($languageFilePath, $language);
343
		}
344
345
		/**
346
		 * Return the current app language by default will use the value from cookie 
347
		 * if can not found will use the default value from configuration
348
		 * @return string the app language like "en", "fr"
349
		 */
350
		protected static function getAppLang(){
351
			//determine the current language
352
			$appLang = get_config('default_language');
353
			//if the language exists in the cookie use it
354
			$cfgKey = get_config('language_cookie_name');
355
			$objCookie = & class_loader('Cookie');
356
			$cookieLang = $objCookie->get($cfgKey);
357
			if ($cookieLang){
358
				$appLang = $cookieLang;
359
			}
360
			return $appLang;
361
		}
362
		/**
363
		 * Get the module information for the model and library to load
364
		 * @param  string $class the full class name like moduleName/className, className,
365
		 * @return array        the module information
366
		 * array(
367
		 * 	'module'=> 'module_name'
368
		 * 	'class' => 'class_name'
369
		 * )
370
		 */
371
		protected static function getModuleInfoForModelLibrary($class){
372
			$module = null;
373
			$obj = & get_instance();
374
			if (strpos($class, '/') !== false){
375
				$path = explode('/', $class);
376
				if (isset($path[0]) && in_array($path[0], Module::getModuleList())){
377
					$module = $path[0];
378
					$class = ucfirst($path[1]);
379
				}
380
			}
381
			else{
382
				$class = ucfirst($class);
383
			}
384
			if (! $module && !empty($obj->moduleName)){
385
				$module = $obj->moduleName;
386
			}
387
			return array(
388
						'class' => $class,
389
						'module' => $module
390
					);
391
		}
392
393
		/**
394
		 * Get the module information for the function to load
395
		 * @param  string $function the function name like moduleName/functionName, functionName,
396
		 * @return array        the module information
397
		 * array(
398
		 * 	'module'=> 'module_name'
399
		 * 	'function' => 'function'
400
		 * 	'file' => 'file'
401
		 * )
402
		 */
403
		protected static function getModuleInfoForFunction($function){
404
			$module = null;
405
			$file = null;
406
			$obj = & get_instance();
407
			//check if the request class contains module name
408
			if (strpos($function, '/') !== false){
409
				$path = explode('/', $function);
410
				if (isset($path[0]) && in_array($path[0], Module::getModuleList())){
411
					$module = $path[0];
412
					$function = 'function_' . $path[1];
413
					$file = $path[0] . DS . $function.'.php';
414
				}
415
			}
416
			if (! $module && !empty($obj->moduleName)){
417
				$module = $obj->moduleName;
418
			}
419
			return array(
420
						'function' => $function,
421
						'module' => $module,
422
						'file' => $file
423
					);
424
		}
425
426
		/**
427
		 * Get the module information for the language to load
428
		 * @param  string $language the language name like moduleName/languageName, languageName,
429
		 * @return array        the module information
430
		 * array(
431
		 * 	'module'=> 'module_name'
432
		 * 	'language' => 'language'
433
		 * 	'file' => 'file'
434
		 * )
435
		 */
436
		protected static function getModuleInfoForLanguage($language){
437
			$module = null;
438
			$file = null;
439
			$obj = & get_instance();
440
			//check if the request class contains module name
441
			if (strpos($language, '/') !== false){
442
				$path = explode('/', $language);
443
				if (isset($path[0]) && in_array($path[0], Module::getModuleList())){
444
					$module = $path[0];
445
					$language = 'lang_' . $path[1] . '.php';
446
					$file = $path[0] . DS .$language;
447
				}
448
			}
449
			if (! $module && !empty($obj->moduleName)){
450
				$module = $obj->moduleName;
451
			}
452
			return array(
453
						'language' => $language,
454
						'module' => $module,
455
						'file' => $file
456
					);
457
		}
458
459
460
		/**
461
		 * Get the module information for the config to load
462
		 * @param  string $filename the filename of the configuration file,
463
		 * @return array        the module information
464
		 * array(
465
		 * 	'module'=> 'module_name'
466
		 * 	'filename' => 'filename'
467
		 * )
468
		 */
469
		protected static function getModuleInfoForConfig($filename){
470
			$module = null;
471
			$obj = & get_instance();
472
			//check if the request class contains module name
473
			if (strpos($filename, '/') !== false){
474
				$path = explode('/', $filename);
475
				if (isset($path[0]) && in_array($path[0], Module::getModuleList())){
476
					$module = $path[0];
477
					$filename = $path[1] . '.php';
478
				}
479
			}
480
			if (! $module && !empty($obj->moduleName)){
481
				$module = $obj->moduleName;
482
			}
483
			return array(
484
						'filename' => $filename,
485
						'module' => $module
486
					);
487
		}
488
489
		/**
490
		 * Get the name of model or library instance if is null
491
		 * @param  string $class the class name to determine the instance
492
		 * @return string        the instance name
493
		 */
494
		protected static function getModelLibraryInstanceName($class){
495
			//for module
496
			$instance = null;
497
			if (strpos($class, '/') !== false){
498
				$path = explode('/', $class);
499
				if (isset($path[1])){
500
					$instance = strtolower($path[1]);
501
				}
502
			}
503
			else{
504
				$instance = strtolower($class);
505
			}
506
			return $instance;
507
		}
508
509
		/**
510
		 * Get the library file path using the module information
511
		 * @param  string $class the class name
512
		 * @return string|null        the library file path otherwise null will be returned
513
		 */
514
		protected static function getLibraryPathUsingModuleInfo($class){
515
			$logger = static::getLogger();
516
			$libraryFilePath = null;
517
			$logger->debug('Checking library [' . $class . '] from module list ...');
518
			$moduleInfo = self::getModuleInfoForModelLibrary($class);
519
			$module = $moduleInfo['module'];
520
			$class  = $moduleInfo['class'];
521
			$moduleLibraryPath = Module::findLibraryFullPath($class, $module);
522
			if ($moduleLibraryPath){
523
				$logger->info('Found library [' . $class . '] from module [' .$module. '], the file path is [' .$moduleLibraryPath. '] we will used it');
524
				$libraryFilePath = $moduleLibraryPath;
525
			}
526
			else{
527
				$logger->info('Cannot find library [' . $class . '] from modules using the default location');
528
			}
529
			return $libraryFilePath;
530
		}
531
532
		/**
533
		 * Load the library 
534
		 * @param  string $libraryFilePath the file path of the library to load
535
		 * @param  string $class           the class name
536
		 * @param  string $instance        the instance
537
		 * @param  array  $params          the parameter to use
538
		 * @return void
539
		 */
540
		protected static function loadLibrary($libraryFilePath, $class, $instance, $params = array()){
541
			if ($libraryFilePath){
542
				$logger = static::getLogger();
543
				require_once $libraryFilePath;
544
				if (class_exists($class)){
545
					$c = $params ? new $class($params) : new $class();
546
					$obj = & get_instance();
547
					$obj->{$instance} = $c;
548
					static::$loaded[$instance] = $class;
549
					$logger->info('Library [' . $class . '] --> ' . $libraryFilePath . ' loaded successfully.');
550
				}
551
				else{
552
					show_error('The file '.$libraryFilePath.' exists but does not contain the class '.$class);
553
				}
554
			}
555
			else{
556
				show_error('Unable to find library class [' . $class . ']');
557
			}
558
		}
559
560
		/**
561
		 * Load the language 
562
		 * @param  string $languageFilePath the file path of the language to load
563
		 * @param  string $language           the language name
564
		 * @return void
565
		 */
566
		protected static function loadLanguage($languageFilePath, $language){
567
			if ($languageFilePath){
568
				$logger = static::getLogger();
569
				$lang = array();
570
				require_once $languageFilePath;
571
				if (! empty($lang) && is_array($lang)){
572
					$logger->info('Language file  [' .$languageFilePath. '] contains the valid languages keys add them to language list');
573
					//Note: may be here the class 'Lang' not yet loaded
574
					$langObj =& class_loader('Lang', 'classes');
575
					$langObj->addLangMessages($lang);
576
					//free the memory
577
					unset($lang);
578
				}
579
				static::$loaded['lang_' . $language] = $languageFilePath;
580
				$logger->info('Language [' . $language . '] --> ' . $languageFilePath . ' loaded successfully.');
581
			}
582
			else{
583
				show_error('Unable to find language [' . $language . ']');
584
			}
585
		}
586
587
588
589
590
		/**
591
		 * Get all the autoload using the configuration file
592
		 * @return array
593
		 */
594
		private function getResourcesFromAutoloadConfig(){
595
			$autoloads = array();
596
			$autoloads['config']    = array();
597
			$autoloads['languages'] = array();
598
			$autoloads['libraries'] = array();
599
			$autoloads['models']    = array();
600
			$autoloads['functions'] = array();
601
			//loading of the resources from autoload configuration file
602
			if (file_exists(CONFIG_PATH . 'autoload.php')){
603
				$autoload = array();
604
				require_once CONFIG_PATH . 'autoload.php';
605
				if (! empty($autoload) && is_array($autoload)){
606
					$autoloads = array_merge($autoloads, $autoload);
607
					unset($autoload);
608
				}
609
			}
610
			//loading autoload configuration for modules
611
			$modulesAutoloads = Module::getModulesAutoloadConfig();
612
			if (! empty($modulesAutoloads) && is_array($modulesAutoloads)){
613
				$autoloads = array_merge_recursive($autoloads, $modulesAutoloads);
614
			}
615
			return $autoloads;
616
		}
617
618
		/**
619
		 * Load the autoload configuration
620
		 * @return void
621
		 */
622
		private function loadResourcesFromAutoloadConfig(){
623
			$autoloads = array();
624
			$autoloads['config']    = array();
625
			$autoloads['languages'] = array();
626
			$autoloads['libraries'] = array();
627
			$autoloads['models']    = array();
628
			$autoloads['functions'] = array();
629
630
			$list = $this->getResourcesFromAutoloadConfig();
631
			$autoloads = array_merge($autoloads, $list);
632
			
633
			//config autoload
634
			$this->loadAutoloadResourcesArray('config', $autoloads['config']);
635
			
636
			//languages autoload
637
			$this->loadAutoloadResourcesArray('lang', $autoloads['languages']);
638
			
639
			//libraries autoload
640
			$this->loadAutoloadResourcesArray('library', $autoloads['libraries']);
641
642
			//models autoload
643
			$this->loadAutoloadResourcesArray('model', $autoloads['models']);
644
			
645
			//functions autoload
646
			$this->loadAutoloadResourcesArray('functions', $autoloads['functions']);
647
		}
648
649
		/**
650
		 * Load the resources autoload array
651
		 * @param  string $method    this object method name to call
652
		 * @param  array  $resources the resource to load
653
		 * @return void            
654
		 */
655
		private function loadAutoloadResourcesArray($method, array $resources){
656
			foreach ($resources as $name) {
657
				$this->{$method}($name);
658
			}
659
		}
660
	}
661