blob: f70ee0334a47964cc017126a6c00818eed12a605 [file] [log] [blame]
Derek Allard2067d1a2008-11-13 22:59:24 +00001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author ExpressionEngine Dev Team
Derek Jones7f3719f2010-01-05 13:35:37 +00009 * @copyright Copyright (c) 2008 - 2010, EllisLab, Inc.
Derek Allard2067d1a2008-11-13 22:59:24 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * Loader Class
20 *
21 * Loads views and files
22 *
23 * @package CodeIgniter
24 * @subpackage Libraries
25 * @author ExpressionEngine Dev Team
26 * @category Loader
27 * @link http://codeigniter.com/user_guide/libraries/loader.html
28 */
29class CI_Loader {
30
31 // All these are set automatically. Don't mess with them.
32 var $_ci_ob_level;
33 var $_ci_view_path = '';
Derek Jones32bf1862010-03-02 13:46:07 -060034 var $_ci_library_paths = array();
35 var $_ci_model_paths = array();
36 var $_ci_helper_paths = array();
Derek Allard2067d1a2008-11-13 22:59:24 +000037 var $_ci_is_instance = FALSE; // Whether we should use $this or $CI =& get_instance()
Derek Jones32bf1862010-03-02 13:46:07 -060038 var $_base_classes = array(); // Set by the controller class
Derek Allard2067d1a2008-11-13 22:59:24 +000039 var $_ci_cached_vars = array();
40 var $_ci_classes = array();
41 var $_ci_loaded_files = array();
42 var $_ci_models = array();
43 var $_ci_helpers = array();
44 var $_ci_plugins = array();
45 var $_ci_varmap = array('unit_test' => 'unit', 'user_agent' => 'agent');
46
47
48 /**
49 * Constructor
50 *
51 * Sets the path to the view files and gets the initial output buffering level
52 *
53 * @access public
54 */
55 function CI_Loader()
56 {
Derek Allard2067d1a2008-11-13 22:59:24 +000057 $this->_ci_view_path = APPPATH.'views/';
58 $this->_ci_ob_level = ob_get_level();
Derek Jones32bf1862010-03-02 13:46:07 -060059 $this->_ci_library_paths = array(APPPATH, BASEPATH);
60 $this->_ci_helper_paths = array(APPPATH, BASEPATH);
61 $this->_ci_model_paths = array(APPPATH);
62
Derek Allard2067d1a2008-11-13 22:59:24 +000063 log_message('debug', "Loader Class Initialized");
64 }
65
66 // --------------------------------------------------------------------
67
68 /**
69 * Class Loader
70 *
71 * This function lets users load and instantiate classes.
72 * It is designed to be called from a user's app controllers.
73 *
74 * @access public
75 * @param string the name of the class
76 * @param mixed the optional parameters
77 * @param string an optional object name
78 * @return void
79 */
80 function library($library = '', $params = NULL, $object_name = NULL)
81 {
Derek Jones32bf1862010-03-02 13:46:07 -060082 if ($library == '' OR isset($this->_base_classes[$library]))
Derek Allard2067d1a2008-11-13 22:59:24 +000083 {
84 return FALSE;
85 }
86
Derek Jones32bf1862010-03-02 13:46:07 -060087 if ( ! is_null($params) && ! is_array($params))
Derek Allard2067d1a2008-11-13 22:59:24 +000088 {
89 $params = NULL;
90 }
91
92 if (is_array($library))
93 {
94 foreach ($library as $class)
95 {
96 $this->_ci_load_class($class, $params, $object_name);
97 }
98 }
99 else
100 {
101 $this->_ci_load_class($library, $params, $object_name);
102 }
103
104 $this->_ci_assign_to_models();
105 }
106
107 // --------------------------------------------------------------------
108
109 /**
110 * Model Loader
111 *
112 * This function lets users load and instantiate models.
113 *
114 * @access public
115 * @param string the name of the class
116 * @param string name for the model
117 * @param bool database connection
118 * @return void
119 */
120 function model($model, $name = '', $db_conn = FALSE)
121 {
122 if (is_array($model))
123 {
124 foreach($model as $babe)
125 {
126 $this->model($babe);
127 }
128 return;
129 }
130
131 if ($model == '')
132 {
133 return;
134 }
135
Derek Jones32bf1862010-03-02 13:46:07 -0600136 $path = '';
137
Derek Allard2067d1a2008-11-13 22:59:24 +0000138 // Is the model in a sub-folder? If so, parse out the filename and path.
Derek Jones32bf1862010-03-02 13:46:07 -0600139 if (($last_slash = strrpos($model, '/')) !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000140 {
Derek Jones32bf1862010-03-02 13:46:07 -0600141 // The path is in front of the last slash
142 $path = substr($model, 0, $last_slash + 1);
143
144 // And the model name behind it
145 $model = substr($model, $last_slash + 1);
Derek Allard2067d1a2008-11-13 22:59:24 +0000146 }
147
148 if ($name == '')
149 {
150 $name = $model;
151 }
152
153 if (in_array($name, $this->_ci_models, TRUE))
154 {
155 return;
156 }
157
158 $CI =& get_instance();
159 if (isset($CI->$name))
160 {
161 show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
162 }
163
164 $model = strtolower($model);
Derek Allard2067d1a2008-11-13 22:59:24 +0000165
Derek Jones32bf1862010-03-02 13:46:07 -0600166 foreach ($this->_ci_model_paths as $mod_path)
167 {
168 if ( ! file_exists($mod_path.'models/'.$path.$model.EXT))
169 {
170 continue;
171 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000172
Derek Jones32bf1862010-03-02 13:46:07 -0600173 if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
174 {
175 if ($db_conn === TRUE)
176 $db_conn = '';
177
178 $CI->load->database($db_conn, FALSE, TRUE);
179 }
180
181 if ( ! class_exists('Model'))
182 {
183 load_class('Model', 'core');
184 }
185
186 require_once($mod_path.'models/'.$path.$model.EXT);
187
188 $model = ucfirst($model);
189
190 $CI->$name = new $model();
191 $CI->$name->_assign_libraries();
192
193 $this->_ci_models[] = $name;
194 return;
195 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000196
Derek Jones32bf1862010-03-02 13:46:07 -0600197 // couldn't find the model
198 show_error('Unable to locate the model you have specified: '.$model);
Derek Allard2067d1a2008-11-13 22:59:24 +0000199 }
200
201 // --------------------------------------------------------------------
202
203 /**
204 * Database Loader
205 *
206 * @access public
207 * @param string the DB credentials
208 * @param bool whether to return the DB object
209 * @param bool whether to enable active record (this allows us to override the config setting)
210 * @return object
211 */
Derek Jonesffca6c22009-12-05 15:31:44 +0000212 function database($params = '', $return = FALSE, $active_record = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000213 {
214 // Grab the super object
215 $CI =& get_instance();
216
217 // Do we even need to load the database class?
Derek Jones9fb6dd12009-12-05 15:32:48 +0000218 if (class_exists('CI_DB') AND $return == FALSE AND $active_record == NULL AND isset($CI->db) AND is_object($CI->db))
Derek Allard2067d1a2008-11-13 22:59:24 +0000219 {
220 return FALSE;
221 }
222
223 require_once(BASEPATH.'database/DB'.EXT);
224
225 if ($return === TRUE)
226 {
227 return DB($params, $active_record);
228 }
229
230 // Initialize the db variable. Needed to prevent
231 // reference errors with some configurations
232 $CI->db = '';
233
234 // Load the DB class
235 $CI->db =& DB($params, $active_record);
236
237 // Assign the DB object to any existing models
238 $this->_ci_assign_to_models();
239 }
240
241 // --------------------------------------------------------------------
242
243 /**
244 * Load the Utilities Class
245 *
246 * @access public
247 * @return string
248 */
249 function dbutil()
250 {
251 if ( ! class_exists('CI_DB'))
252 {
253 $this->database();
254 }
255
256 $CI =& get_instance();
257
258 // for backwards compatibility, load dbforge so we can extend dbutils off it
259 // this use is deprecated and strongly discouraged
260 $CI->load->dbforge();
261
262 require_once(BASEPATH.'database/DB_utility'.EXT);
263 require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility'.EXT);
264 $class = 'CI_DB_'.$CI->db->dbdriver.'_utility';
265
Derek Jonesf0a9b332009-07-29 14:19:18 +0000266 $CI->dbutil =& instantiate_class(new $class());
Derek Allard2067d1a2008-11-13 22:59:24 +0000267
268 $CI->load->_ci_assign_to_models();
269 }
270
271 // --------------------------------------------------------------------
272
273 /**
274 * Load the Database Forge Class
275 *
276 * @access public
277 * @return string
278 */
279 function dbforge()
280 {
281 if ( ! class_exists('CI_DB'))
282 {
283 $this->database();
284 }
285
286 $CI =& get_instance();
287
288 require_once(BASEPATH.'database/DB_forge'.EXT);
289 require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge'.EXT);
290 $class = 'CI_DB_'.$CI->db->dbdriver.'_forge';
291
292 $CI->dbforge = new $class();
293
294 $CI->load->_ci_assign_to_models();
295 }
296
297 // --------------------------------------------------------------------
298
299 /**
300 * Load View
301 *
302 * This function is used to load a "view" file. It has three parameters:
303 *
304 * 1. The name of the "view" file to be included.
305 * 2. An associative array of data to be extracted for use in the view.
306 * 3. TRUE/FALSE - whether to return the data or load it. In
307 * some cases it's advantageous to be able to return data so that
308 * a developer can process it in some way.
309 *
310 * @access public
311 * @param string
312 * @param array
313 * @param bool
314 * @return void
315 */
316 function view($view, $vars = array(), $return = FALSE)
317 {
318 return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
319 }
320
321 // --------------------------------------------------------------------
322
323 /**
324 * Load File
325 *
326 * This is a generic file loader
327 *
328 * @access public
329 * @param string
330 * @param bool
331 * @return string
332 */
333 function file($path, $return = FALSE)
334 {
335 return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));
336 }
337
338 // --------------------------------------------------------------------
339
340 /**
341 * Set Variables
342 *
343 * Once variables are set they become available within
344 * the controller class and its "view" files.
345 *
346 * @access public
347 * @param array
348 * @return void
349 */
350 function vars($vars = array(), $val = '')
351 {
352 if ($val != '' AND is_string($vars))
353 {
354 $vars = array($vars => $val);
355 }
356
357 $vars = $this->_ci_object_to_array($vars);
358
359 if (is_array($vars) AND count($vars) > 0)
360 {
361 foreach ($vars as $key => $val)
362 {
363 $this->_ci_cached_vars[$key] = $val;
364 }
365 }
366 }
367
368 // --------------------------------------------------------------------
369
370 /**
371 * Load Helper
372 *
373 * This function loads the specified helper file.
374 *
375 * @access public
376 * @param mixed
377 * @return void
378 */
379 function helper($helpers = array())
Derek Jones32bf1862010-03-02 13:46:07 -0600380 {
381 foreach ($this->_ci_prep_filename($helpers, '_helper') as $helper)
382 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000383 if (isset($this->_ci_helpers[$helper]))
384 {
385 continue;
386 }
Derek Jones32bf1862010-03-02 13:46:07 -0600387
Derek Allard2067d1a2008-11-13 22:59:24 +0000388 $ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.EXT;
389
390 // Is this a helper extension request?
391 if (file_exists($ext_helper))
392 {
393 $base_helper = BASEPATH.'helpers/'.$helper.EXT;
394
395 if ( ! file_exists($base_helper))
396 {
397 show_error('Unable to load the requested file: helpers/'.$helper.EXT);
398 }
399
400 include_once($ext_helper);
401 include_once($base_helper);
Derek Jones32bf1862010-03-02 13:46:07 -0600402
403 $this->_ci_helpers[$helper] = TRUE;
404 log_message('debug', 'Helper loaded: '.$helper);
405 continue;
Derek Allard2067d1a2008-11-13 22:59:24 +0000406 }
Derek Jones32bf1862010-03-02 13:46:07 -0600407
408 // Try to load the helper
409 foreach ($this->_ci_helper_paths as $path)
410 {
411 if (file_exists($path.'helpers/'.$helper.EXT))
412 {
413 include_once($path.'helpers/'.$helper.EXT);
414
415 $this->_ci_helpers[$helper] = TRUE;
416 log_message('debug', 'Helper loaded: '.$helper);
417 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000418 }
419 }
420
Derek Jones32bf1862010-03-02 13:46:07 -0600421 // unable to load the helper
422 if ( ! isset($this->_ci_helpers[$helper]))
423 {
424 show_error('Unable to load the requested file: helpers/'.$helper.EXT);
425 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000426 }
427 }
428
429 // --------------------------------------------------------------------
430
431 /**
432 * Load Helpers
433 *
434 * This is simply an alias to the above function in case the
435 * user has written the plural form of this function.
436 *
437 * @access public
438 * @param array
439 * @return void
440 */
441 function helpers($helpers = array())
442 {
443 $this->helper($helpers);
444 }
445
446 // --------------------------------------------------------------------
447
448 /**
449 * Load Plugin
450 *
451 * This function loads the specified plugin.
452 *
453 * @access public
454 * @param array
455 * @return void
456 */
457 function plugin($plugins = array())
458 {
Derek Jones32bf1862010-03-02 13:46:07 -0600459 foreach ($this->_ci_prep_filename($plugins, '_pi') as $plugin)
Derek Allard2067d1a2008-11-13 22:59:24 +0000460 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000461 if (isset($this->_ci_plugins[$plugin]))
462 {
463 continue;
464 }
465
466 if (file_exists(APPPATH.'plugins/'.$plugin.EXT))
467 {
468 include_once(APPPATH.'plugins/'.$plugin.EXT);
469 }
470 else
471 {
472 if (file_exists(BASEPATH.'plugins/'.$plugin.EXT))
473 {
474 include_once(BASEPATH.'plugins/'.$plugin.EXT);
475 }
476 else
477 {
478 show_error('Unable to load the requested file: plugins/'.$plugin.EXT);
479 }
480 }
481
482 $this->_ci_plugins[$plugin] = TRUE;
483 log_message('debug', 'Plugin loaded: '.$plugin);
484 }
485 }
486
487 // --------------------------------------------------------------------
488
489 /**
490 * Load Plugins
491 *
492 * This is simply an alias to the above function in case the
493 * user has written the plural form of this function.
494 *
495 * @access public
496 * @param array
497 * @return void
498 */
499 function plugins($plugins = array())
500 {
501 $this->plugin($plugins);
502 }
503
504 // --------------------------------------------------------------------
505
506 /**
507 * Loads a language file
508 *
509 * @access public
510 * @param array
511 * @param string
512 * @return void
513 */
514 function language($file = array(), $lang = '')
515 {
516 $CI =& get_instance();
517
518 if ( ! is_array($file))
519 {
520 $file = array($file);
521 }
522
523 foreach ($file as $langfile)
524 {
525 $CI->lang->load($langfile, $lang);
526 }
527 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000528
529 // --------------------------------------------------------------------
530
531 /**
532 * Loads a config file
533 *
534 * @access public
535 * @param string
536 * @return void
537 */
538 function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
539 {
540 $CI =& get_instance();
541 $CI->config->load($file, $use_sections, $fail_gracefully);
542 }
543
544 // --------------------------------------------------------------------
Derek Jones32bf1862010-03-02 13:46:07 -0600545
Derek Allard2067d1a2008-11-13 22:59:24 +0000546 /**
Derek Jones32bf1862010-03-02 13:46:07 -0600547 * Add Package Path
Derek Allard2067d1a2008-11-13 22:59:24 +0000548 *
Derek Jones32bf1862010-03-02 13:46:07 -0600549 * Prepends a parent path to the library, model, helper, and config path arrays
Derek Allard2067d1a2008-11-13 22:59:24 +0000550 *
551 * @access public
552 * @param string
553 * @return void
Derek Jones32bf1862010-03-02 13:46:07 -0600554 */
555 function add_package_path($path)
556 {
557 array_unshift($this->_ci_library_paths, $path);
558 array_unshift($this->_ci_model_paths, $path);
559 array_unshift($this->_ci_helper_paths, $path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000560
Derek Jones32bf1862010-03-02 13:46:07 -0600561 // Add config file path
562 $config =& $this->_ci_get_component('config');
563 array_unshift($config->_config_paths, $path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000564 }
565
566 // --------------------------------------------------------------------
Derek Jones32bf1862010-03-02 13:46:07 -0600567
568 /**
569 * Remove Package Path
570 *
571 * Remove a path from the library, model, and helper path arrays if it exists
572 * If no path is provided, the most recently added path is removed.
573 *
574 * @access public
575 * @param type
576 * @return type
577 */
578 function remove_package_path($path = '', $remove_config_path = TRUE)
579 {
580 $config =& $this->_ci_get_component('config');
Derek Allard2067d1a2008-11-13 22:59:24 +0000581
Derek Jones32bf1862010-03-02 13:46:07 -0600582 if ($path == '')
583 {
584 $void = array_shift($this->_ci_library_paths);
585 $void = array_shift($this->_ci_model_paths);
586 $void = array_shift($this->_ci_helper_paths);
587 $void = array_shift($config->_config_paths);
588 }
589 else
590 {
591 foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
592 {
593 if (($key = array_search($path, $this->{$var})) !== FALSE)
594 {
595 unset($this->{$var}[$key]);
596 }
597 }
598
599 if (($key = array_search($path, $config->_config_paths)) !== FALSE)
600 {
601 unset($config->_config_paths[$key]);
602 }
603 }
604
605 // make sure the application default paths are still in the array
606 $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
607 $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
608 $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
609 $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
610 }
611
612 // --------------------------------------------------------------------
613
Derek Allard2067d1a2008-11-13 22:59:24 +0000614 /**
615 * Loader
616 *
617 * This function is used to load views and files.
618 * Variables are prefixed with _ci_ to avoid symbol collision with
619 * variables made available to view files
620 *
621 * @access private
622 * @param array
623 * @return void
624 */
625 function _ci_load($_ci_data)
626 {
627 // Set the default data variables
628 foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
629 {
630 $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];
631 }
632
633 // Set the path to the requested file
634 if ($_ci_path == '')
635 {
636 $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
637 $_ci_file = ($_ci_ext == '') ? $_ci_view.EXT : $_ci_view;
638 $_ci_path = $this->_ci_view_path.$_ci_file;
639 }
640 else
641 {
642 $_ci_x = explode('/', $_ci_path);
643 $_ci_file = end($_ci_x);
644 }
645
646 if ( ! file_exists($_ci_path))
647 {
648 show_error('Unable to load the requested file: '.$_ci_file);
649 }
650
651 // This allows anything loaded using $this->load (views, files, etc.)
652 // to become accessible from within the Controller and Model functions.
653 // Only needed when running PHP 5
654
655 if ($this->_ci_is_instance())
656 {
657 $_ci_CI =& get_instance();
658 foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
659 {
660 if ( ! isset($this->$_ci_key))
661 {
662 $this->$_ci_key =& $_ci_CI->$_ci_key;
663 }
664 }
665 }
666
667 /*
668 * Extract and cache variables
669 *
670 * You can either set variables using the dedicated $this->load_vars()
671 * function or via the second parameter of this function. We'll merge
672 * the two types and cache them so that views that are embedded within
673 * other views can have access to these variables.
674 */
675 if (is_array($_ci_vars))
676 {
677 $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
678 }
679 extract($this->_ci_cached_vars);
680
681 /*
682 * Buffer the output
683 *
684 * We buffer the output for two reasons:
685 * 1. Speed. You get a significant speed boost.
686 * 2. So that the final rendered template can be
687 * post-processed by the output class. Why do we
688 * need post processing? For one thing, in order to
689 * show the elapsed page load time. Unless we
690 * can intercept the content right before it's sent to
691 * the browser and then stop the timer it won't be accurate.
692 */
693 ob_start();
694
695 // If the PHP installation does not support short tags we'll
696 // do a little string replacement, changing the short tags
697 // to standard PHP echo statements.
698
699 if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE)
700 {
701 echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
702 }
703 else
704 {
705 include($_ci_path); // include() vs include_once() allows for multiple views with the same name
706 }
707
708 log_message('debug', 'File loaded: '.$_ci_path);
709
710 // Return the file data if requested
711 if ($_ci_return === TRUE)
712 {
713 $buffer = ob_get_contents();
714 @ob_end_clean();
715 return $buffer;
716 }
717
718 /*
719 * Flush the buffer... or buff the flusher?
720 *
721 * In order to permit views to be nested within
722 * other views, we need to flush the content back out whenever
723 * we are beyond the first level of output buffering so that
724 * it can be seen and included properly by the first included
725 * template and any subsequent ones. Oy!
726 *
727 */
728 if (ob_get_level() > $this->_ci_ob_level + 1)
729 {
730 ob_end_flush();
731 }
732 else
733 {
734 // PHP 4 requires that we use a global
735 global $OUT;
736 $OUT->append_output(ob_get_contents());
737 @ob_end_clean();
738 }
739 }
740
741 // --------------------------------------------------------------------
742
743 /**
744 * Load class
745 *
746 * This function loads the requested class.
747 *
748 * @access private
749 * @param string the item that is being loaded
750 * @param mixed any additional parameters
751 * @param string an optional object name
752 * @return void
753 */
754 function _ci_load_class($class, $params = NULL, $object_name = NULL)
755 {
756 // Get the class name, and while we're at it trim any slashes.
757 // The directory path can be included as part of the class name,
758 // but we don't want a leading slash
759 $class = str_replace(EXT, '', trim($class, '/'));
760
761 // Was the path included with the class name?
762 // We look for a slash to determine this
763 $subdir = '';
Derek Jones32bf1862010-03-02 13:46:07 -0600764 if (($last_slash = strrpos($class, '/')) !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000765 {
Derek Jones32bf1862010-03-02 13:46:07 -0600766 // Extract the path
767 $subdir = substr($class, 0, $last_slash + 1);
Derek Allard2067d1a2008-11-13 22:59:24 +0000768
Derek Jones32bf1862010-03-02 13:46:07 -0600769 // Get the filename from the path
770 $class = substr($class, $last_slash + 1);
Derek Allard2067d1a2008-11-13 22:59:24 +0000771 }
772
773 // We'll test for both lowercase and capitalized versions of the file name
774 foreach (array(ucfirst($class), strtolower($class)) as $class)
775 {
776 $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.EXT;
777
778 // Is this a class extension request?
779 if (file_exists($subclass))
780 {
781 $baseclass = BASEPATH.'libraries/'.ucfirst($class).EXT;
782
783 if ( ! file_exists($baseclass))
784 {
785 log_message('error', "Unable to load the requested class: ".$class);
786 show_error("Unable to load the requested class: ".$class);
787 }
788
789 // Safety: Was the class already loaded by a previous call?
790 if (in_array($subclass, $this->_ci_loaded_files))
791 {
792 // Before we deem this to be a duplicate request, let's see
793 // if a custom object name is being supplied. If so, we'll
794 // return a new instance of the object
795 if ( ! is_null($object_name))
796 {
797 $CI =& get_instance();
798 if ( ! isset($CI->$object_name))
799 {
800 return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
801 }
802 }
803
804 $is_duplicate = TRUE;
805 log_message('debug', $class." class already loaded. Second attempt ignored.");
806 return;
807 }
808
809 include_once($baseclass);
810 include_once($subclass);
811 $this->_ci_loaded_files[] = $subclass;
812
813 return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
814 }
815
816 // Lets search for the requested library file and load it.
Derek Jones32bf1862010-03-02 13:46:07 -0600817 $is_duplicate = FALSE;
818 foreach ($this->_ci_library_paths as $path)
Derek Allard2067d1a2008-11-13 22:59:24 +0000819 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000820 $filepath = $path.'libraries/'.$subdir.$class.EXT;
Derek Jones32bf1862010-03-02 13:46:07 -0600821
Derek Allard2067d1a2008-11-13 22:59:24 +0000822 // Does the file exist? No? Bummer...
823 if ( ! file_exists($filepath))
824 {
825 continue;
826 }
827
828 // Safety: Was the class already loaded by a previous call?
829 if (in_array($filepath, $this->_ci_loaded_files))
830 {
831 // Before we deem this to be a duplicate request, let's see
832 // if a custom object name is being supplied. If so, we'll
833 // return a new instance of the object
834 if ( ! is_null($object_name))
835 {
836 $CI =& get_instance();
837 if ( ! isset($CI->$object_name))
838 {
839 return $this->_ci_init_class($class, '', $params, $object_name);
840 }
841 }
842
843 $is_duplicate = TRUE;
844 log_message('debug', $class." class already loaded. Second attempt ignored.");
845 return;
846 }
847
848 include_once($filepath);
849 $this->_ci_loaded_files[] = $filepath;
Derek Jones32bf1862010-03-02 13:46:07 -0600850 return $this->_ci_init_class($class, '', $params, $object_name);
Derek Allard2067d1a2008-11-13 22:59:24 +0000851 }
Derek Jones32bf1862010-03-02 13:46:07 -0600852
Derek Allard2067d1a2008-11-13 22:59:24 +0000853 } // END FOREACH
854
855 // One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
856 if ($subdir == '')
857 {
858 $path = strtolower($class).'/'.$class;
859 return $this->_ci_load_class($path, $params);
860 }
861
862 // If we got this far we were unable to find the requested class.
863 // We do not issue errors if the load call failed due to a duplicate request
864 if ($is_duplicate == FALSE)
865 {
866 log_message('error', "Unable to load the requested class: ".$class);
867 show_error("Unable to load the requested class: ".$class);
868 }
869 }
870
871 // --------------------------------------------------------------------
872
873 /**
874 * Instantiates a class
875 *
876 * @access private
877 * @param string
878 * @param string
879 * @param string an optional object name
880 * @return null
881 */
882 function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL)
883 {
Derek Jones32bf1862010-03-02 13:46:07 -0600884 // Is there an associated config file for this class? Note: these should always be lowercase
Derek Allard2067d1a2008-11-13 22:59:24 +0000885 if ($config === NULL)
886 {
887 // We test for both uppercase and lowercase, for servers that
888 // are case-sensitive with regard to file names
889 if (file_exists(APPPATH.'config/'.strtolower($class).EXT))
890 {
891 include_once(APPPATH.'config/'.strtolower($class).EXT);
892 }
Derek Jonesc8dddd92009-07-10 18:58:03 +0000893 elseif (file_exists(APPPATH.'config/'.ucfirst(strtolower($class)).EXT))
Derek Allard2067d1a2008-11-13 22:59:24 +0000894 {
Derek Jonesc8dddd92009-07-10 18:58:03 +0000895 include_once(APPPATH.'config/'.ucfirst(strtolower($class)).EXT);
Derek Allard2067d1a2008-11-13 22:59:24 +0000896 }
897 }
898
899 if ($prefix == '')
900 {
901 if (class_exists('CI_'.$class))
902 {
903 $name = 'CI_'.$class;
904 }
905 elseif (class_exists(config_item('subclass_prefix').$class))
906 {
907 $name = config_item('subclass_prefix').$class;
908 }
909 else
910 {
911 $name = $class;
912 }
913 }
914 else
915 {
916 $name = $prefix.$class;
917 }
918
919 // Is the class name valid?
920 if ( ! class_exists($name))
921 {
922 log_message('error', "Non-existent class: ".$name);
923 show_error("Non-existent class: ".$class);
924 }
925
926 // Set the variable name we will assign the class to
927 // Was a custom class name supplied? If so we'll use it
928 $class = strtolower($class);
929
930 if (is_null($object_name))
931 {
932 $classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class];
933 }
934 else
935 {
936 $classvar = $object_name;
937 }
938
939 // Save the class name and object name
940 $this->_ci_classes[$class] = $classvar;
941
942 // Instantiate the class
943 $CI =& get_instance();
944 if ($config !== NULL)
945 {
946 $CI->$classvar = new $name($config);
947 }
948 else
949 {
950 $CI->$classvar = new $name;
951 }
952 }
953
954 // --------------------------------------------------------------------
955
956 /**
957 * Autoloader
958 *
959 * The config/autoload.php file contains an array that permits sub-systems,
960 * libraries, plugins, and helpers to be loaded automatically.
961 *
962 * @access private
963 * @param array
964 * @return void
965 */
966 function _ci_autoloader()
967 {
968 include_once(APPPATH.'config/autoload'.EXT);
969
970 if ( ! isset($autoload))
971 {
972 return FALSE;
973 }
974
975 // Load any custom config file
976 if (count($autoload['config']) > 0)
977 {
978 $CI =& get_instance();
979 foreach ($autoload['config'] as $key => $val)
980 {
981 $CI->config->load($val);
982 }
983 }
984
985 // Autoload plugins, helpers and languages
986 foreach (array('helper', 'plugin', 'language') as $type)
987 {
988 if (isset($autoload[$type]) AND count($autoload[$type]) > 0)
989 {
990 $this->$type($autoload[$type]);
991 }
992 }
993
994 // A little tweak to remain backward compatible
995 // The $autoload['core'] item was deprecated
Derek Jones32bf1862010-03-02 13:46:07 -0600996 if ( ! isset($autoload['libraries']) AND isset($autoload['core']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000997 {
998 $autoload['libraries'] = $autoload['core'];
999 }
1000
1001 // Load libraries
1002 if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0)
1003 {
1004 // Load the database driver.
1005 if (in_array('database', $autoload['libraries']))
1006 {
1007 $this->database();
1008 $autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
1009 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001010
1011 // Load all other libraries
1012 foreach ($autoload['libraries'] as $item)
1013 {
1014 $this->library($item);
1015 }
1016 }
1017
1018 // Autoload models
1019 if (isset($autoload['model']))
1020 {
1021 $this->model($autoload['model']);
1022 }
1023
1024 }
1025
1026 // --------------------------------------------------------------------
1027
1028 /**
1029 * Assign to Models
1030 *
1031 * Makes sure that anything loaded by the loader class (libraries, plugins, etc.)
1032 * will be available to models, if any exist.
1033 *
1034 * @access private
1035 * @param object
1036 * @return array
1037 */
1038 function _ci_assign_to_models()
1039 {
1040 if (count($this->_ci_models) == 0)
1041 {
1042 return;
1043 }
1044
Derek Jones32bf1862010-03-02 13:46:07 -06001045 foreach($this->_ci_models as $model)
Derek Allard2067d1a2008-11-13 22:59:24 +00001046 {
Derek Jones32bf1862010-03-02 13:46:07 -06001047 $model = $this->_ci_get_component($model);
1048 $model->_assign_libraries();
Derek Allard2067d1a2008-11-13 22:59:24 +00001049 }
1050 }
1051
1052 // --------------------------------------------------------------------
1053
1054 /**
1055 * Object to Array
1056 *
1057 * Takes an object as input and converts the class variables to array key/vals
1058 *
1059 * @access private
1060 * @param object
1061 * @return array
1062 */
1063 function _ci_object_to_array($object)
1064 {
1065 return (is_object($object)) ? get_object_vars($object) : $object;
1066 }
1067
1068 // --------------------------------------------------------------------
1069
1070 /**
1071 * Determines whether we should use the CI instance or $this
Derek Jones32bf1862010-03-02 13:46:07 -06001072 * @PHP4
1073 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001074 * @access private
1075 * @return bool
1076 */
1077 function _ci_is_instance()
1078 {
Derek Jones32bf1862010-03-02 13:46:07 -06001079 if (is_php('5.0.0') == TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001080 {
1081 return TRUE;
1082 }
1083
1084 global $CI;
1085 return (is_object($CI)) ? TRUE : FALSE;
1086 }
Derek Jones32bf1862010-03-02 13:46:07 -06001087
1088 // --------------------------------------------------------------------
1089
1090 /**
1091 * Get a reference to a specific library or model
1092 *
1093 * @access private
1094 * @return bool
1095 */
1096 function &_ci_get_component($component)
1097 {
1098 if ($this->_ci_is_instance())
1099 {
1100 $CI =& get_instance();
1101 return $CI->$component;
1102 }
1103 else
1104 {
1105 return $this->$component;
1106 }
1107 }
1108
1109 // --------------------------------------------------------------------
1110
1111 /**
1112 * Prep filename
1113 *
1114 * This function preps the name of various items to make loading them more reliable.
1115 *
1116 * @access private
1117 * @param mixed
1118 * @return array
1119 */
1120 function _ci_prep_filename($filename, $extension)
1121 {
1122 if ( ! is_array($filename))
1123 {
1124 return array(strtolower(str_replace(EXT, '', str_replace($extension, '', $filename)).$extension));
1125 }
1126 else
1127 {
1128 foreach ($filename as $key => $val)
1129 {
1130 $filename[$key] = strtolower(str_replace(EXT, '', str_replace($extension, '', $val)).$extension);
1131 }
1132
1133 return $filename;
1134 }
1135 }
1136
Derek Allard2067d1a2008-11-13 22:59:24 +00001137
1138}
1139
1140/* End of file Loader.php */
Derek Jonesc68dfbf2010-03-02 12:59:23 -06001141/* Location: ./system/core/Loader.php */