Completed
Push — master ( 63f9e6...34eb4c )
by Kenji
10s
created

replacing/core/old/3.1.6-Loader.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
9
 * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	https://codeigniter.com
35
 * @since	Version 1.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
40
/**
41
 * Loader Class (Modified by ci-phpunit-test)
42
 *
43
 * Loads framework components.
44
 *
45
 * @package		CodeIgniter
46
 * @subpackage	Libraries
47
 * @category	Loader
48
 * @author		EllisLab Dev Team
49
 * @link		https://codeigniter.com/user_guide/libraries/loader.html
50
 */
51
class CI_Loader {
52
53
	// All these are set automatically. Don't mess with them.
54
	/**
55
	 * Nesting level of the output buffering mechanism
56
	 *
57
	 * @var	int
58
	 */
59
	protected $_ci_ob_level;
60
61
	/**
62
	 * List of paths to load views from
63
	 *
64
	 * @var	array
65
	 */
66
	protected $_ci_view_paths =	array(VIEWPATH	=> TRUE);
67
68
	/**
69
	 * List of paths to load libraries from
70
	 *
71
	 * @var	array
72
	 */
73
	protected $_ci_library_paths =	array(APPPATH, BASEPATH);
74
75
	/**
76
	 * List of paths to load models from
77
	 *
78
	 * @var	array
79
	 */
80
	protected $_ci_model_paths =	array(APPPATH);
81
82
	/**
83
	 * List of paths to load helpers from
84
	 *
85
	 * @var	array
86
	 */
87
	protected $_ci_helper_paths =	array(APPPATH, BASEPATH);
88
89
	/**
90
	 * List of cached variables
91
	 *
92
	 * @var	array
93
	 */
94
	protected $_ci_cached_vars =	array();
95
96
	/**
97
	 * List of loaded classes
98
	 *
99
	 * @var	array
100
	 */
101
	protected $_ci_classes =	array();
102
103
	/**
104
	 * List of loaded models
105
	 *
106
	 * @var	array
107
	 */
108
	protected $_ci_models =	array();
109
110
	/**
111
	 * List of loaded helpers
112
	 *
113
	 * @var	array
114
	 */
115
	protected $_ci_helpers =	array();
116
117
	/**
118
	 * List of class name mappings
119
	 *
120
	 * @var	array
121
	 */
122
	protected $_ci_varmap =	array(
123
		'unit_test' => 'unit',
124
		'user_agent' => 'agent'
125
	);
126
127
	// --------------------------------------------------------------------
128
129
	/**
130
	 * Class constructor
131
	 *
132
	 * Sets component load paths, gets the initial output buffering level.
133
	 *
134
	 * @return	void
135
	 *
136
	 * @codeCoverageIgnore
137
	 */
138
	public function __construct()
139
	{
140
		$this->_ci_ob_level = ob_get_level();
141
		$this->_ci_classes =& is_loaded();
142
143
		log_message('info', 'Loader Class Initialized');
144
	}
145
146
	// --------------------------------------------------------------------
147
148
	/**
149
	 * Initializer
150
	 *
151
	 * @todo	Figure out a way to move this to the constructor
152
	 *		without breaking *package_path*() methods.
153
	 * @uses	CI_Loader::_ci_autoloader()
154
	 * @used-by	CI_Controller::__construct()
155
	 * @return	void
156
	 *
157
	 * @codeCoverageIgnore
158
	 */
159
	public function initialize()
160
	{
161
		$this->_ci_autoloader();
162
	}
163
164
	// --------------------------------------------------------------------
165
166
	/**
167
	 * Is Loaded
168
	 *
169
	 * A utility method to test if a class is in the self::$_ci_classes array.
170
	 *
171
	 * @used-by	Mainly used by Form Helper function _get_validation_object().
172
	 *
173
	 * @param 	string		$class	Class name to check for
174
	 * @return 	string|bool	Class object name if loaded or FALSE
175
	 *
176
	 * @codeCoverageIgnore
177
	 */
178
	public function is_loaded($class)
179
	{
180
		return array_search(ucfirst($class), $this->_ci_classes, TRUE);
181
	}
182
183
	// --------------------------------------------------------------------
184
185
	/**
186
	 * Library Loader
187
	 *
188
	 * Loads and instantiates libraries.
189
	 * Designed to be called from application controllers.
190
	 *
191
	 * @param	mixed	$library	Library name
192
	 * @param	array	$params		Optional parameters to pass to the library class constructor
193
	 * @param	string	$object_name	An optional object name to assign to
194
	 * @return	object
195
	 *
196
	 * @codeCoverageIgnore
197
	 */
198
	public function library($library, $params = NULL, $object_name = NULL)
199
	{
200
		if (empty($library))
201
		{
202
			return $this;
203
		}
204
		elseif (is_array($library))
205
		{
206
			foreach ($library as $key => $value)
207
			{
208
				if (is_int($key))
209
				{
210
					$this->library($value, $params);
211
				}
212
				else
213
				{
214
					$this->library($key, $params, $value);
215
				}
216
			}
217
218
			return $this;
219
		}
220
221
		if ($params !== NULL && ! is_array($params))
222
		{
223
			$params = NULL;
224
		}
225
226
		$this->_ci_load_library($library, $params, $object_name);
227
		return $this;
228
	}
229
230
	// --------------------------------------------------------------------
231
232
	/**
233
	 * Model Loader
234
	 *
235
	 * Loads and instantiates models.
236
	 *
237
	 * @param	string	$model		Model name
238
	 * @param	string	$name		An optional object name to assign to
239
	 * @param	bool	$db_conn	An optional database connection configuration to initialize
240
	 * @return	object
241
	 *
242
	 * modified by ci-phpunit-test
243
	 */
244
	public function model($model, $name = '', $db_conn = FALSE)
245
	{
246
		if (empty($model))
247
		{
248
			return $this;
249
		}
250
		elseif (is_array($model))
251
		{
252
			foreach ($model as $key => $value)
253
			{
254
				is_int($key) ? $this->model($value, '', $db_conn) : $this->model($key, $value, $db_conn);
255
			}
256
257
			return $this;
258
		}
259
260
		$path = '';
261
262
		// Is the model in a sub-folder? If so, parse out the filename and path.
263
		if (($last_slash = strrpos($model, '/')) !== FALSE)
264
		{
265
			// The path is in front of the last slash
266
			$path = substr($model, 0, ++$last_slash);
267
268
			// And the model name behind it
269
			$model = substr($model, $last_slash);
270
		}
271
272
		if (empty($name))
273
		{
274
			$name = $model;
275
		}
276
277
		if (in_array($name, $this->_ci_models, TRUE))
278
		{
279
			return $this;
280
		}
281
282
		$CI =& get_instance();
283
		if (isset($CI->$name))
284
		{
285
			throw new RuntimeException('The model name you are loading is the name of a resource that is already being used: '.$name);
286
		}
287
288
		if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))
289
		{
290
			if ($db_conn === TRUE)
291
			{
292
				$db_conn = '';
293
			}
294
295
			$this->database($db_conn, FALSE, TRUE);
296
		}
297
298
		// Note: All of the code under this condition used to be just:
299
		//
300
		//	   load_class('Model', 'core');
301
		//
302
		//	   However, load_class() instantiates classes
303
		//	   to cache them for later use and that prevents
304
		//	   MY_Model from being an abstract class and is
305
		//	   sub-optimal otherwise anyway.
306
//		if ( ! class_exists('CI_Model', FALSE))
307
//		{
308
			$app_path = APPPATH.'core'.DIRECTORY_SEPARATOR;
309
			if (file_exists($app_path.'Model.php'))
310
			{
311
				require_once($app_path.'Model.php');
312
				if ( ! class_exists('CI_Model', FALSE))
313
				{
314
					throw new RuntimeException($app_path."Model.php exists, but doesn't declare class CI_Model");
315
				}
316
			}
317
			elseif ( ! class_exists('CI_Model', FALSE))
318
			{
319
				require_once(BASEPATH.'core'.DIRECTORY_SEPARATOR.'Model.php');
320
			}
321
322
			$class = config_item('subclass_prefix').'Model';
323
			if (file_exists($app_path.$class.'.php'))
324
			{
325
				require_once($app_path.$class.'.php');
326
				if ( ! class_exists($class, FALSE))
327
				{
328
					throw new RuntimeException($app_path.$class.".php exists, but doesn't declare class ".$class);
329
				}
330
			}
331
//		}
332
333
		$model = ucfirst($model);
334
		if ( ! class_exists($model, FALSE))
335
		{
336
			foreach ($this->_ci_model_paths as $mod_path)
337
			{
338
				if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
339
				{
340
					continue;
341
				}
342
343
				require_once($mod_path.'models/'.$path.$model.'.php');
344
				if ( ! class_exists($model, FALSE))
345
				{
346
					throw new RuntimeException($mod_path."models/".$path.$model.".php exists, but doesn't declare class ".$model);
347
				}
348
349
				break;
350
			}
351
352
			if ( ! class_exists($model, FALSE))
353
			{
354
				throw new RuntimeException('Unable to locate the model you have specified: '.$model);
355
			}
356
		}
357
//		elseif ( ! is_subclass_of($model, 'CI_Model'))
358
//		{
359
//			throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model");
360
//		}
361
362
		$this->_ci_models[] = $name;
363
		$CI->$name = new $model();
364
		return $this;
365
	}
366
367
	// --------------------------------------------------------------------
368
369
	/**
370
	 * Database Loader
371
	 *
372
	 * @param	mixed	$params		Database configuration options
373
	 * @param	bool	$return 	Whether to return the database object
374
	 * @param	bool	$query_builder	Whether to enable Query Builder
375
	 *					(overrides the configuration setting)
376
	 *
377
	 * @return	object|bool	Database object if $return is set to TRUE,
378
	 *					FALSE on failure, CI_Loader instance in any other case
379
	 *
380
	 * @codeCoverageIgnore
381
	 */
382
	public function database($params = '', $return = FALSE, $query_builder = NULL)
383
	{
384
		// Grab the super object
385
		$CI =& get_instance();
386
387
		// Do we even need to load the database class?
388
		if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
389
		{
390
			return FALSE;
391
		}
392
393
		require_once(BASEPATH.'database/DB.php');
394
395
		if ($return === TRUE)
396
		{
397
			return DB($params, $query_builder);
398
		}
399
400
		// Initialize the db variable. Needed to prevent
401
		// reference errors with some configurations
402
		$CI->db = '';
403
404
		// Load the DB class
405
		$CI->db =& DB($params, $query_builder);
406
		return $this;
407
	}
408
409
	// --------------------------------------------------------------------
410
411
	/**
412
	 * Load the Database Utilities Class
413
	 *
414
	 * @param	object	$db	Database object
415
	 * @param	bool	$return	Whether to return the DB Utilities class object or not
416
	 * @return	object
417
	 *
418
	 * @codeCoverageIgnore
419
	 */
420
	public function dbutil($db = NULL, $return = FALSE)
421
	{
422
		$CI =& get_instance();
423
424
		if ( ! is_object($db) OR ! ($db instanceof CI_DB))
425
		{
426
			class_exists('CI_DB', FALSE) OR $this->database();
427
			$db =& $CI->db;
428
		}
429
430
		require_once(BASEPATH.'database/DB_utility.php');
431
		require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_utility.php');
432
		$class = 'CI_DB_'.$db->dbdriver.'_utility';
433
434
		if ($return === TRUE)
435
		{
436
			return new $class($db);
437
		}
438
439
		$CI->dbutil = new $class($db);
440
		return $this;
441
	}
442
443
	// --------------------------------------------------------------------
444
445
	/**
446
	 * Load the Database Forge Class
447
	 *
448
	 * @param	object	$db	Database object
449
	 * @param	bool	$return	Whether to return the DB Forge class object or not
450
	 * @return	object
451
	 *
452
	 * @codeCoverageIgnore
453
	 */
454
	public function dbforge($db = NULL, $return = FALSE)
455
	{
456
		$CI =& get_instance();
457
		if ( ! is_object($db) OR ! ($db instanceof CI_DB))
458
		{
459
			class_exists('CI_DB', FALSE) OR $this->database();
460
			$db =& $CI->db;
461
		}
462
463
		require_once(BASEPATH.'database/DB_forge.php');
464
		require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_forge.php');
465
466
		if ( ! empty($db->subdriver))
467
		{
468
			$driver_path = BASEPATH.'database/drivers/'.$db->dbdriver.'/subdrivers/'.$db->dbdriver.'_'.$db->subdriver.'_forge.php';
469
			if (file_exists($driver_path))
470
			{
471
				require_once($driver_path);
472
				$class = 'CI_DB_'.$db->dbdriver.'_'.$db->subdriver.'_forge';
473
			}
474
		}
475
		else
476
		{
477
			$class = 'CI_DB_'.$db->dbdriver.'_forge';
478
		}
479
480
		if ($return === TRUE)
481
		{
482
			return new $class($db);
483
		}
484
485
		$CI->dbforge = new $class($db);
486
		return $this;
487
	}
488
489
	// --------------------------------------------------------------------
490
491
	/**
492
	 * View Loader
493
	 *
494
	 * Loads "view" files.
495
	 *
496
	 * @param	string	$view	View name
497
	 * @param	array	$vars	An associative array of data
498
	 *				to be extracted for use in the view
499
	 * @param	bool	$return	Whether to return the view output
500
	 *				or leave it to the Output class
501
	 * @return	object|string
502
	 *
503
	 * @codeCoverageIgnore
504
	 */
505
	public function view($view, $vars = array(), $return = FALSE)
506
	{
507
		return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return));
508
	}
509
510
	// --------------------------------------------------------------------
511
512
	/**
513
	 * Generic File Loader
514
	 *
515
	 * @param	string	$path	File path
516
	 * @param	bool	$return	Whether to return the file output
517
	 * @return	object|string
518
	 */
519
	public function file($path, $return = FALSE)
520
	{
521
		return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));
522
	}
523
524
	// --------------------------------------------------------------------
525
526
	/**
527
	 * Set Variables
528
	 *
529
	 * Once variables are set they become available within
530
	 * the controller class and its "view" files.
531
	 *
532
	 * @param	array|object|string	$vars
533
	 *					An associative array or object containing values
534
	 *					to be set, or a value's name if string
535
	 * @param 	string	$val	Value to set, only used if $vars is a string
536
	 * @return	object
537
	 *
538
	 * @codeCoverageIgnore
539
	 */
540
	public function vars($vars, $val = '')
541
	{
542
		$vars = is_string($vars)
543
			? array($vars => $val)
544
			: $this->_ci_prepare_view_vars($vars);
545
546
		foreach ($vars as $key => $val)
547
		{
548
			$this->_ci_cached_vars[$key] = $val;
549
		}
550
551
		return $this;
552
	}
553
554
	// --------------------------------------------------------------------
555
556
	/**
557
	 * Clear Cached Variables
558
	 *
559
	 * Clears the cached variables.
560
	 *
561
	 * @return	CI_Loader
562
	 *
563
	 * @codeCoverageIgnore
564
	 */
565
	public function clear_vars()
566
	{
567
		$this->_ci_cached_vars = array();
568
		return $this;
569
	}
570
571
	// --------------------------------------------------------------------
572
573
	/**
574
	 * Get Variable
575
	 *
576
	 * Check if a variable is set and retrieve it.
577
	 *
578
	 * @param	string	$key	Variable name
579
	 * @return	mixed	The variable or NULL if not found
580
	 *
581
	 * @codeCoverageIgnore
582
	 */
583
	public function get_var($key)
584
	{
585
		return isset($this->_ci_cached_vars[$key]) ? $this->_ci_cached_vars[$key] : NULL;
586
	}
587
588
	// --------------------------------------------------------------------
589
590
	/**
591
	 * Get Variables
592
	 *
593
	 * Retrieves all loaded variables.
594
	 *
595
	 * @return	array
596
	 *
597
	 * @codeCoverageIgnore
598
	 */
599
	public function get_vars()
600
	{
601
		return $this->_ci_cached_vars;
602
	}
603
604
	// --------------------------------------------------------------------
605
606
	/**
607
	 * Helper Loader
608
	 *
609
	 * @param	string|string[]	$helpers	Helper name(s)
610
	 * @return	object
611
	 *
612
	 * @codeCoverageIgnore
613
	 */
614
	public function helper($helpers = array())
615
	{
616
		is_array($helpers) OR $helpers = array($helpers);
617
		foreach ($helpers as &$helper)
618
		{
619
			$filename = basename($helper);
620
			$filepath = ($filename === $helper) ? '' : substr($helper, 0, strlen($helper) - strlen($filename));
621
			$filename = strtolower(preg_replace('#(_helper)?(\.php)?$#i', '', $filename)).'_helper';
622
			$helper   = $filepath.$filename;
623
624
			if (isset($this->_ci_helpers[$helper]))
625
			{
626
				continue;
627
			}
628
629
			// Is this a helper extension request?
630
			$ext_helper = config_item('subclass_prefix').$filename;
631
			$ext_loaded = FALSE;
632
			foreach ($this->_ci_helper_paths as $path)
633
			{
634
				if (file_exists($path.'helpers/'.$ext_helper.'.php'))
635
				{
636
					include_once($path.'helpers/'.$ext_helper.'.php');
637
					$ext_loaded = TRUE;
638
				}
639
			}
640
641
			// If we have loaded extensions - check if the base one is here
642
			if ($ext_loaded === TRUE)
643
			{
644
				$base_helper = BASEPATH.'helpers/'.$helper.'.php';
645
				if ( ! file_exists($base_helper))
646
				{
647
					show_error('Unable to load the requested file: helpers/'.$helper.'.php');
648
				}
649
650
				include_once($base_helper);
651
				$this->_ci_helpers[$helper] = TRUE;
652
				log_message('info', 'Helper loaded: '.$helper);
653
				continue;
654
			}
655
656
			// No extensions found ... try loading regular helpers and/or overrides
657
			foreach ($this->_ci_helper_paths as $path)
658
			{
659
				if (file_exists($path.'helpers/'.$helper.'.php'))
660
				{
661
					include_once($path.'helpers/'.$helper.'.php');
662
663
					$this->_ci_helpers[$helper] = TRUE;
664
					log_message('info', 'Helper loaded: '.$helper);
665
					break;
666
				}
667
			}
668
669
			// unable to load the helper
670
			if ( ! isset($this->_ci_helpers[$helper]))
671
			{
672
				show_error('Unable to load the requested file: helpers/'.$helper.'.php');
673
			}
674
		}
675
676
		return $this;
677
	}
678
679
	// --------------------------------------------------------------------
680
681
	/**
682
	 * Load Helpers
683
	 *
684
	 * An alias for the helper() method in case the developer has
685
	 * written the plural form of it.
686
	 *
687
	 * @uses	CI_Loader::helper()
688
	 * @param	string|string[]	$helpers	Helper name(s)
689
	 * @return	object
690
	 *
691
	 * @codeCoverageIgnore
692
	 */
693
	public function helpers($helpers = array())
694
	{
695
		return $this->helper($helpers);
696
	}
697
698
	// --------------------------------------------------------------------
699
700
	/**
701
	 * Language Loader
702
	 *
703
	 * Loads language files.
704
	 *
705
	 * @param	string|string[]	$files	List of language file names to load
706
	 * @param	string		Language name
707
	 * @return	object
708
	 *
709
	 * @codeCoverageIgnore
710
	 */
711
	public function language($files, $lang = '')
712
	{
713
		get_instance()->lang->load($files, $lang);
714
		return $this;
715
	}
716
717
	// --------------------------------------------------------------------
718
719
	/**
720
	 * Config Loader
721
	 *
722
	 * Loads a config file (an alias for CI_Config::load()).
723
	 *
724
	 * @uses	CI_Config::load()
725
	 * @param	string	$file			Configuration file name
726
	 * @param	bool	$use_sections		Whether configuration values should be loaded into their own section
727
	 * @param	bool	$fail_gracefully	Whether to just return FALSE or display an error message
728
	 * @return	bool	TRUE if the file was loaded correctly or FALSE on failure
729
	 *
730
	 * @codeCoverageIgnore
731
	 */
732
	public function config($file, $use_sections = FALSE, $fail_gracefully = FALSE)
733
	{
734
		return get_instance()->config->load($file, $use_sections, $fail_gracefully);
735
	}
736
737
	// --------------------------------------------------------------------
738
739
	/**
740
	 * Driver Loader
741
	 *
742
	 * Loads a driver library.
743
	 *
744
	 * @param	string|string[]	$library	Driver name(s)
745
	 * @param	array		$params		Optional parameters to pass to the driver
746
	 * @param	string		$object_name	An optional object name to assign to
747
	 *
748
	 * @return	object|bool	Object or FALSE on failure if $library is a string
749
	 *				and $object_name is set. CI_Loader instance otherwise.
750
	 *
751
	 * @codeCoverageIgnore
752
	 */
753
	public function driver($library, $params = NULL, $object_name = NULL)
754
	{
755
		if (is_array($library))
756
		{
757
			foreach ($library as $key => $value)
758
			{
759
				if (is_int($key))
760
				{
761
					$this->driver($value, $params);
762
				}
763
				else
764
				{
765
					$this->driver($key, $params, $value);
766
				}
767
			}
768
769
			return $this;
770
		}
771
		elseif (empty($library))
772
		{
773
			return FALSE;
774
		}
775
776
		if ( ! class_exists('CI_Driver_Library', FALSE))
777
		{
778
			// We aren't instantiating an object here, just making the base class available
779
			require BASEPATH.'libraries/Driver.php';
780
		}
781
782
		// We can save the loader some time since Drivers will *always* be in a subfolder,
783
		// and typically identically named to the library
784
		if ( ! strpos($library, '/'))
785
		{
786
			$library = ucfirst($library).'/'.$library;
787
		}
788
789
		return $this->library($library, $params, $object_name);
790
	}
791
792
	// --------------------------------------------------------------------
793
794
	/**
795
	 * Add Package Path
796
	 *
797
	 * Prepends a parent path to the library, model, helper and config
798
	 * path arrays.
799
	 *
800
	 * @see	CI_Loader::$_ci_library_paths
801
	 * @see	CI_Loader::$_ci_model_paths
802
	 * @see CI_Loader::$_ci_helper_paths
803
	 * @see CI_Config::$_config_paths
804
	 *
805
	 * @param	string	$path		Path to add
806
	 * @param 	bool	$view_cascade	(default: TRUE)
807
	 * @return	object
808
	 *
809
	 * @codeCoverageIgnore
810
	 */
811
	public function add_package_path($path, $view_cascade = TRUE)
812
	{
813
		$path = rtrim($path, '/').'/';
814
815
		array_unshift($this->_ci_library_paths, $path);
816
		array_unshift($this->_ci_model_paths, $path);
817
		array_unshift($this->_ci_helper_paths, $path);
818
819
		$this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;
820
821
		// Add config file path
822
		$config =& $this->_ci_get_component('config');
823
		$config->_config_paths[] = $path;
824
825
		return $this;
826
	}
827
828
	// --------------------------------------------------------------------
829
830
	/**
831
	 * Get Package Paths
832
	 *
833
	 * Return a list of all package paths.
834
	 *
835
	 * @param	bool	$include_base	Whether to include BASEPATH (default: FALSE)
836
	 * @return	array
837
	 *
838
	 * @codeCoverageIgnore
839
	 */
840
	public function get_package_paths($include_base = FALSE)
841
	{
842
		return ($include_base === TRUE) ? $this->_ci_library_paths : $this->_ci_model_paths;
843
	}
844
845
	// --------------------------------------------------------------------
846
847
	/**
848
	 * Remove Package Path
849
	 *
850
	 * Remove a path from the library, model, helper and/or config
851
	 * path arrays if it exists. If no path is provided, the most recently
852
	 * added path will be removed removed.
853
	 *
854
	 * @param	string	$path	Path to remove
855
	 * @return	object
856
	 *
857
	 * @codeCoverageIgnore
858
	 */
859
	public function remove_package_path($path = '')
860
	{
861
		$config =& $this->_ci_get_component('config');
862
863
		if ($path === '')
864
		{
865
			array_shift($this->_ci_library_paths);
866
			array_shift($this->_ci_model_paths);
867
			array_shift($this->_ci_helper_paths);
868
			array_shift($this->_ci_view_paths);
869
			array_pop($config->_config_paths);
870
		}
871
		else
872
		{
873
			$path = rtrim($path, '/').'/';
874
			foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
875
			{
876
				if (($key = array_search($path, $this->{$var})) !== FALSE)
877
				{
878
					unset($this->{$var}[$key]);
879
				}
880
			}
881
882
			if (isset($this->_ci_view_paths[$path.'views/']))
883
			{
884
				unset($this->_ci_view_paths[$path.'views/']);
885
			}
886
887
			if (($key = array_search($path, $config->_config_paths)) !== FALSE)
888
			{
889
				unset($config->_config_paths[$key]);
890
			}
891
		}
892
893
		// make sure the application default paths are still in the array
894
		$this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
895
		$this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
896
		$this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
897
		$this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));
898
		$config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
899
900
		return $this;
901
	}
902
903
	// --------------------------------------------------------------------
904
905
	/**
906
	 * Internal CI Data Loader
907
	 *
908
	 * Used to load views and files.
909
	 *
910
	 * Variables are prefixed with _ci_ to avoid symbol collision with
911
	 * variables made available to view files.
912
	 *
913
	 * @used-by	CI_Loader::view()
914
	 * @used-by	CI_Loader::file()
915
	 * @param	array	$_ci_data	Data to load
916
	 * @return	object
917
	 *
918
	 * @codeCoverageIgnore
919
	 */
920
	protected function _ci_load($_ci_data)
921
	{
922
		// Set the default data variables
923
		foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
924
		{
925
			$$_ci_val = isset($_ci_data[$_ci_val]) ? $_ci_data[$_ci_val] : FALSE;
926
		}
927
928
		$file_exists = FALSE;
929
930
		// Set the path to the requested file
931
		if (is_string($_ci_path) && $_ci_path !== '')
932
		{
933
			$_ci_x = explode('/', $_ci_path);
934
			$_ci_file = end($_ci_x);
935
		}
936
		else
937
		{
938
			$_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
939
			$_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view;
940
941
			foreach ($this->_ci_view_paths as $_ci_view_file => $cascade)
942
			{
943
				if (file_exists($_ci_view_file.$_ci_file))
944
				{
945
					$_ci_path = $_ci_view_file.$_ci_file;
946
					$file_exists = TRUE;
947
					break;
948
				}
949
950
				if ( ! $cascade)
951
				{
952
					break;
953
				}
954
			}
955
		}
956
957
		if ( ! $file_exists && ! file_exists($_ci_path))
958
		{
959
			show_error('Unable to load the requested file: '.$_ci_file);
960
		}
961
962
		// This allows anything loaded using $this->load (views, files, etc.)
963
		// to become accessible from within the Controller and Model functions.
964
		$_ci_CI =& get_instance();
965
		foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
966
		{
967
			if ( ! isset($this->$_ci_key))
968
			{
969
				$this->$_ci_key =& $_ci_CI->$_ci_key;
970
			}
971
		}
972
973
		/*
974
		 * Extract and cache variables
975
		 *
976
		 * You can either set variables using the dedicated $this->load->vars()
977
		 * function or via the second parameter of this function. We'll merge
978
		 * the two types and cache them so that views that are embedded within
979
		 * other views can have access to these variables.
980
		 */
981
		empty($_ci_vars) OR $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
982
		extract($this->_ci_cached_vars);
983
984
		/*
985
		 * Buffer the output
986
		 *
987
		 * We buffer the output for two reasons:
988
		 * 1. Speed. You get a significant speed boost.
989
		 * 2. So that the final rendered template can be post-processed by
990
		 *	the output class. Why do we need post processing? For one thing,
991
		 *	in order to show the elapsed page load time. Unless we can
992
		 *	intercept the content right before it's sent to the browser and
993
		 *	then stop the timer it won't be accurate.
994
		 */
995
		ob_start();
996
997
		// If the PHP installation does not support short tags we'll
998
		// do a little string replacement, changing the short tags
999
		// to standard PHP echo statements.
1000
		if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)
1001
		{
1002
			echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
1003
		}
1004
		else
1005
		{
1006
			include($_ci_path); // include() vs include_once() allows for multiple views with the same name
1007
		}
1008
1009
		log_message('info', 'File loaded: '.$_ci_path);
1010
1011
		// Return the file data if requested
1012
		if ($_ci_return === TRUE)
1013
		{
1014
			$buffer = ob_get_contents();
1015
			@ob_end_clean();
1016
			return $buffer;
1017
		}
1018
1019
		/*
1020
		 * Flush the buffer... or buff the flusher?
1021
		 *
1022
		 * In order to permit views to be nested within
1023
		 * other views, we need to flush the content back out whenever
1024
		 * we are beyond the first level of output buffering so that
1025
		 * it can be seen and included properly by the first included
1026
		 * template and any subsequent ones. Oy!
1027
		 */
1028
		if (ob_get_level() > $this->_ci_ob_level + 1)
1029
		{
1030
			ob_end_flush();
1031
		}
1032
		else
1033
		{
1034
			$_ci_CI->output->append_output(ob_get_contents());
1035
			@ob_end_clean();
1036
		}
1037
1038
		return $this;
1039
	}
1040
1041
	// --------------------------------------------------------------------
1042
1043
	/**
1044
	 * Internal CI Library Loader
1045
	 *
1046
	 * @used-by	CI_Loader::library()
1047
	 * @uses	CI_Loader::_ci_init_library()
1048
	 *
1049
	 * @param	string	$class		Class name to load
1050
	 * @param	mixed	$params		Optional parameters to pass to the class constructor
1051
	 * @param	string	$object_name	Optional object name to assign to
1052
	 * @return	void
1053
	 *
1054
	 * modified by ci-phpunit-test
1055
	 */
1056 View Code Duplication
	protected function _ci_load_library($class, $params = NULL, $object_name = NULL)
0 ignored issues
show
This method seems to be duplicated in 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...
1057
	{
1058
		// Get the class name, and while we're at it trim any slashes.
1059
		// The directory path can be included as part of the class name,
1060
		// but we don't want a leading slash
1061
		$class = str_replace('.php', '', trim($class, '/'));
1062
1063
		// Was the path included with the class name?
1064
		// We look for a slash to determine this
1065
		if (($last_slash = strrpos($class, '/')) !== FALSE)
1066
		{
1067
			// Extract the path
1068
			$subdir = substr($class, 0, ++$last_slash);
1069
1070
			// Get the filename from the path
1071
			$class = substr($class, $last_slash);
1072
		}
1073
		else
1074
		{
1075
			$subdir = '';
1076
		}
1077
1078
		$class = ucfirst($class);
1079
1080
		// Replace library in ci-phpuni-test
1081
		if (file_exists(TESTPATH.'_ci_phpunit_test/replacing/libraries/'.$subdir.$class.'.php'))
1082
		{
1083
			return $this->_ci_load_stock_library($class, $subdir, $params, $object_name);
1084
		}
1085
1086
		// Is this a stock library? There are a few special conditions if so ...
1087
		if (file_exists(BASEPATH.'libraries/'.$subdir.$class.'.php'))
1088
		{
1089
			return $this->_ci_load_stock_library($class, $subdir, $params, $object_name);
1090
		}
1091
1092
		// Safety: Was the class already loaded by a previous call?
1093
		if (class_exists($class, FALSE))
1094
		{
1095
			$property = $object_name;
1096
			if (empty($property))
1097
			{
1098
				$property = strtolower($class);
1099
				isset($this->_ci_varmap[$property]) && $property = $this->_ci_varmap[$property];
1100
			}
1101
1102
			$CI =& get_instance();
1103
			if (isset($CI->$property))
1104
			{
1105
//				log_message('debug', $class.' class already loaded. Second attempt ignored.');
1106
//				return;
1107
			}
1108
1109
			return $this->_ci_init_library($class, '', $params, $object_name);
1110
		}
1111
1112
		// Let's search for the requested library file and load it.
1113
		foreach ($this->_ci_library_paths as $path)
1114
		{
1115
			// BASEPATH has already been checked for
1116
			if ($path === BASEPATH)
1117
			{
1118
				continue;
1119
			}
1120
1121
			$filepath = $path.'libraries/'.$subdir.$class.'.php';
1122
			// Does the file exist? No? Bummer...
1123
			if ( ! file_exists($filepath))
1124
			{
1125
				continue;
1126
			}
1127
1128
			include_once($filepath);
1129
			return $this->_ci_init_library($class, '', $params, $object_name);
1130
		}
1131
1132
		// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
1133
		if ($subdir === '')
1134
		{
1135
			return $this->_ci_load_library($class.'/'.$class, $params, $object_name);
1136
		}
1137
1138
		// If we got this far we were unable to find the requested class.
1139
		log_message('error', 'Unable to load the requested class: '.$class);
1140
		show_error('Unable to load the requested class: '.$class);
1141
	}
1142
1143
	// --------------------------------------------------------------------
1144
1145
	/**
1146
	 * Internal CI Stock Library Loader
1147
	 *
1148
	 * @used-by	CI_Loader::_ci_load_library()
1149
	 * @uses	CI_Loader::_ci_init_library()
1150
	 *
1151
	 * @param	string	$library_name	Library name to load
1152
	 * @param	string	$file_path	Path to the library filename, relative to libraries/
1153
	 * @param	mixed	$params		Optional parameters to pass to the class constructor
1154
	 * @param	string	$object_name	Optional object name to assign to
1155
	 * @return	void
1156
	 *
1157
	 * modified by ci-phpunit-test
1158
	 */
1159 View Code Duplication
	protected function _ci_load_stock_library($library_name, $file_path, $params, $object_name)
0 ignored issues
show
This method seems to be duplicated in 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...
1160
	{
1161
		$prefix = 'CI_';
1162
1163
		if (class_exists($prefix.$library_name, FALSE))
1164
		{
1165
			if (class_exists(config_item('subclass_prefix').$library_name, FALSE))
1166
			{
1167
				$prefix = config_item('subclass_prefix');
1168
			}
1169
1170
			$property = $object_name;
1171
			if (empty($property))
1172
			{
1173
				$property = strtolower($library_name);
1174
				isset($this->_ci_varmap[$property]) && $property = $this->_ci_varmap[$property];
1175
			}
1176
1177
			$CI =& get_instance();
1178
			if ( ! isset($CI->$property))
1179
			{
1180
				return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1181
			}
1182
1183
			log_message('debug', $library_name.' class already loaded. Second attempt ignored.');
1184
			return;
1185
		}
1186
1187
		$paths = $this->_ci_library_paths;
1188
		array_pop($paths); // BASEPATH
1189
		array_pop($paths); // APPPATH (needs to be the first path checked)
1190
		array_unshift($paths, APPPATH);
1191
1192
		foreach ($paths as $path)
1193
		{
1194
			if (file_exists($path = $path.'libraries/'.$file_path.$library_name.'.php'))
1195
			{
1196
				// Override
1197
				include_once($path);
1198
//				if (class_exists($prefix.$library_name, FALSE))
1199
				{
1200
					return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1201
				}
1202
1203
				log_message('debug', $path.' exists, but does not declare '.$prefix.$library_name);
1204
			}
1205
		}
1206
1207
		// Replace library in ci-phpuni-test
1208
		if (file_exists(TESTPATH.'_ci_phpunit_test/replacing/libraries/'.$file_path.$library_name.'.php'))
1209
		{
1210
			include_once(TESTPATH.'_ci_phpunit_test/replacing/libraries/'.$file_path.$library_name.'.php');
1211
		}
1212
		else
1213
		{
1214
			include_once(BASEPATH.'libraries/'.$file_path.$library_name.'.php');
1215
		}
1216
1217
		// Check for extensions
1218
		$subclass = config_item('subclass_prefix').$library_name;
1219
		foreach ($paths as $path)
1220
		{
1221
			if (file_exists($path = $path.'libraries/'.$file_path.$subclass.'.php'))
1222
			{
1223
				include_once($path);
1224
				if (class_exists($subclass, FALSE))
1225
				{
1226
					$prefix = config_item('subclass_prefix');
1227
					break;
1228
				}
1229
1230
				log_message('debug', $path.' exists, but does not declare '.$subclass);
1231
			}
1232
		}
1233
1234
		return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1235
	}
1236
1237
	// --------------------------------------------------------------------
1238
1239
	/**
1240
	 * Internal CI Library Instantiator
1241
	 *
1242
	 * @used-by	CI_Loader::_ci_load_stock_library()
1243
	 * @used-by	CI_Loader::_ci_load_library()
1244
	 *
1245
	 * @param	string		$class		Class name
1246
	 * @param	string		$prefix		Class name prefix
1247
	 * @param	array|null|bool	$config		Optional configuration to pass to the class constructor:
1248
	 *						FALSE to skip;
1249
	 *						NULL to search in config paths;
1250
	 *						array containing configuration data
1251
	 * @param	string		$object_name	Optional object name to assign to
1252
	 * @return	void
1253
	 *
1254
	 * @codeCoverageIgnore
1255
	 */
1256
	protected function _ci_init_library($class, $prefix, $config = FALSE, $object_name = NULL)
1257
	{
1258
		// Is there an associated config file for this class? Note: these should always be lowercase
1259
		if ($config === NULL)
1260
		{
1261
			// Fetch the config paths containing any package paths
1262
			$config_component = $this->_ci_get_component('config');
1263
1264
			if (is_array($config_component->_config_paths))
1265
			{
1266
				$found = FALSE;
1267
				foreach ($config_component->_config_paths as $path)
1268
				{
1269
					// We test for both uppercase and lowercase, for servers that
1270
					// are case-sensitive with regard to file names. Load global first,
1271
					// override with environment next
1272
					if (file_exists($path.'config/'.strtolower($class).'.php'))
1273
					{
1274
						include($path.'config/'.strtolower($class).'.php');
1275
						$found = TRUE;
1276
					}
1277
					elseif (file_exists($path.'config/'.ucfirst(strtolower($class)).'.php'))
1278
					{
1279
						include($path.'config/'.ucfirst(strtolower($class)).'.php');
1280
						$found = TRUE;
1281
					}
1282
1283
					if (file_exists($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
1284
					{
1285
						include($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
1286
						$found = TRUE;
1287
					}
1288
					elseif (file_exists($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
1289
					{
1290
						include($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
1291
						$found = TRUE;
1292
					}
1293
1294
					// Break on the first found configuration, thus package
1295
					// files are not overridden by default paths
1296
					if ($found === TRUE)
1297
					{
1298
						break;
1299
					}
1300
				}
1301
			}
1302
		}
1303
1304
		$class_name = $prefix.$class;
1305
1306
		// Is the class name valid?
1307
		if ( ! class_exists($class_name, FALSE))
1308
		{
1309
			log_message('error', 'Non-existent class: '.$class_name);
1310
			show_error('Non-existent class: '.$class_name);
1311
		}
1312
1313
		// Set the variable name we will assign the class to
1314
		// Was a custom class name supplied? If so we'll use it
1315
		if (empty($object_name))
1316
		{
1317
			$object_name = strtolower($class);
1318
			if (isset($this->_ci_varmap[$object_name]))
1319
			{
1320
				$object_name = $this->_ci_varmap[$object_name];
1321
			}
1322
		}
1323
1324
		// Don't overwrite existing properties
1325
		$CI =& get_instance();
1326
		if (isset($CI->$object_name))
1327
		{
1328
			if ($CI->$object_name instanceof $class_name)
1329
			{
1330
				log_message('debug', $class_name." has already been instantiated as '".$object_name."'. Second attempt aborted.");
1331
				return;
1332
			}
1333
1334
			show_error("Resource '".$object_name."' already exists and is not a ".$class_name." instance.");
1335
		}
1336
1337
		// Save the class name and object name
1338
		$this->_ci_classes[$object_name] = $class;
1339
1340
		// Instantiate the class
1341
		$CI->$object_name = isset($config)
1342
			? new $class_name($config)
1343
			: new $class_name();
1344
	}
1345
1346
	// --------------------------------------------------------------------
1347
1348
	/**
1349
	 * CI Autoloader
1350
	 *
1351
	 * Loads component listed in the config/autoload.php file.
1352
	 *
1353
	 * @used-by	CI_Loader::initialize()
1354
	 * @return	void
1355
	 *
1356
	 * @codeCoverageIgnore
1357
	 */
1358
	protected function _ci_autoloader()
1359
	{
1360
		if (file_exists(APPPATH.'config/autoload.php'))
1361
		{
1362
			include(APPPATH.'config/autoload.php');
1363
		}
1364
1365
		if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
1366
		{
1367
			include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
1368
		}
1369
1370
		if ( ! isset($autoload))
1371
		{
1372
			return;
1373
		}
1374
1375
		// Autoload packages
1376
		if (isset($autoload['packages']))
1377
		{
1378
			foreach ($autoload['packages'] as $package_path)
1379
			{
1380
				$this->add_package_path($package_path);
1381
			}
1382
		}
1383
1384
		// Load any custom config file
1385
		if (count($autoload['config']) > 0)
1386
		{
1387
			foreach ($autoload['config'] as $val)
1388
			{
1389
				$this->config($val);
1390
			}
1391
		}
1392
1393
		// Autoload helpers and languages
1394
		foreach (array('helper', 'language') as $type)
1395
		{
1396
			if (isset($autoload[$type]) && count($autoload[$type]) > 0)
1397
			{
1398
				$this->$type($autoload[$type]);
1399
			}
1400
		}
1401
1402
		// Autoload drivers
1403
		if (isset($autoload['drivers']))
1404
		{
1405
			$this->driver($autoload['drivers']);
1406
		}
1407
1408
		// Load libraries
1409
		if (isset($autoload['libraries']) && count($autoload['libraries']) > 0)
1410
		{
1411
			// Load the database driver.
1412
			if (in_array('database', $autoload['libraries']))
1413
			{
1414
				$this->database();
1415
				$autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
1416
			}
1417
1418
			// Load all other libraries
1419
			$this->library($autoload['libraries']);
1420
		}
1421
1422
		// Autoload models
1423
		if (isset($autoload['model']))
1424
		{
1425
			$this->model($autoload['model']);
1426
		}
1427
	}
1428
1429
	// --------------------------------------------------------------------
1430
1431
	/**
1432
	 * Prepare variables for _ci_vars, to be later extract()-ed inside views
1433
	 *
1434
	 * Converts objects to associative arrays and filters-out internal
1435
	 * variable names (i.e. keys prefixed with '_ci_').
1436
	 *
1437
	 * @param	mixed	$vars
1438
	 * @return	array
1439
	 *
1440
	 * @codeCoverageIgnore
1441
	 */
1442
	protected function _ci_prepare_view_vars($vars)
1443
	{
1444
		if ( ! is_array($vars))
1445
		{
1446
			$vars = is_object($vars)
1447
				? get_object_vars($vars)
1448
				: array();
1449
		}
1450
1451
		foreach (array_keys($vars) as $key)
1452
		{
1453
			if (strncmp($key, '_ci_', 4) === 0)
1454
			{
1455
				unset($vars[$key]);
1456
			}
1457
		}
1458
1459
		return $vars;
1460
	}
1461
1462
	// --------------------------------------------------------------------
1463
1464
	/**
1465
	 * CI Component getter
1466
	 *
1467
	 * Get a reference to a specific library or model.
1468
	 *
1469
	 * @param 	string	$component	Component name
1470
	 * @return	bool
1471
	 *
1472
	 * @codeCoverageIgnore
1473
	 */
1474
	protected function &_ci_get_component($component)
1475
	{
1476
		$CI =& get_instance();
1477
		return $CI->$component;
1478
	}
1479
}
1480