blob: 1726f0a539f12c6f25ea413848a50b6075231243 [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 Jones8dca0412010-03-05 13:01:44 -0600547 * Driver
548 *
549 * Loads a driver library
550 *
551 * @param string the name of the class
552 * @param mixed the optional parameters
553 * @param string an optional object name
554 * @return void
555 */
556 function driver($library = '', $params = NULL, $object_name = NULL)
557 {
558 if ( ! class_exists('CI_Driver_Library'))
559 {
560 // we aren't instantiating an object here, that'll be done by the Library itself
Derek Jonesd5e0cb52010-03-09 20:20:46 -0600561 require BASEPATH.'libraries/Driver'.EXT;
562 }
563
564 // We can save the loader some time since Drivers will *always* be in a subfolder,
565 // and typically identically named to the library
566 if ( ! strpos($library, '/'))
567 {
568 $library = $library.'/'.$library;
Derek Jones8dca0412010-03-05 13:01:44 -0600569 }
570
571 return $this->library($library, $params, $object_name);
572 }
573
574 // --------------------------------------------------------------------
575
576 /**
Derek Jones32bf1862010-03-02 13:46:07 -0600577 * Add Package Path
Derek Allard2067d1a2008-11-13 22:59:24 +0000578 *
Derek Jones32bf1862010-03-02 13:46:07 -0600579 * Prepends a parent path to the library, model, helper, and config path arrays
Derek Allard2067d1a2008-11-13 22:59:24 +0000580 *
581 * @access public
582 * @param string
583 * @return void
Derek Jones32bf1862010-03-02 13:46:07 -0600584 */
585 function add_package_path($path)
586 {
587 array_unshift($this->_ci_library_paths, $path);
588 array_unshift($this->_ci_model_paths, $path);
589 array_unshift($this->_ci_helper_paths, $path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000590
Derek Jones32bf1862010-03-02 13:46:07 -0600591 // Add config file path
592 $config =& $this->_ci_get_component('config');
593 array_unshift($config->_config_paths, $path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000594 }
595
596 // --------------------------------------------------------------------
Derek Jones32bf1862010-03-02 13:46:07 -0600597
598 /**
599 * Remove Package Path
600 *
601 * Remove a path from the library, model, and helper path arrays if it exists
602 * If no path is provided, the most recently added path is removed.
603 *
604 * @access public
605 * @param type
606 * @return type
607 */
608 function remove_package_path($path = '', $remove_config_path = TRUE)
609 {
610 $config =& $this->_ci_get_component('config');
Derek Allard2067d1a2008-11-13 22:59:24 +0000611
Derek Jones32bf1862010-03-02 13:46:07 -0600612 if ($path == '')
613 {
614 $void = array_shift($this->_ci_library_paths);
615 $void = array_shift($this->_ci_model_paths);
616 $void = array_shift($this->_ci_helper_paths);
617 $void = array_shift($config->_config_paths);
618 }
619 else
620 {
621 foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
622 {
623 if (($key = array_search($path, $this->{$var})) !== FALSE)
624 {
625 unset($this->{$var}[$key]);
626 }
627 }
628
629 if (($key = array_search($path, $config->_config_paths)) !== FALSE)
630 {
631 unset($config->_config_paths[$key]);
632 }
633 }
634
635 // make sure the application default paths are still in the array
636 $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
637 $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
638 $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
639 $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
640 }
641
642 // --------------------------------------------------------------------
643
Derek Allard2067d1a2008-11-13 22:59:24 +0000644 /**
645 * Loader
646 *
647 * This function is used to load views and files.
648 * Variables are prefixed with _ci_ to avoid symbol collision with
649 * variables made available to view files
650 *
651 * @access private
652 * @param array
653 * @return void
654 */
655 function _ci_load($_ci_data)
656 {
657 // Set the default data variables
658 foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
659 {
660 $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];
661 }
662
663 // Set the path to the requested file
664 if ($_ci_path == '')
665 {
666 $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
667 $_ci_file = ($_ci_ext == '') ? $_ci_view.EXT : $_ci_view;
668 $_ci_path = $this->_ci_view_path.$_ci_file;
669 }
670 else
671 {
672 $_ci_x = explode('/', $_ci_path);
673 $_ci_file = end($_ci_x);
674 }
675
676 if ( ! file_exists($_ci_path))
677 {
678 show_error('Unable to load the requested file: '.$_ci_file);
679 }
680
681 // This allows anything loaded using $this->load (views, files, etc.)
682 // to become accessible from within the Controller and Model functions.
683 // Only needed when running PHP 5
684
685 if ($this->_ci_is_instance())
686 {
687 $_ci_CI =& get_instance();
688 foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
689 {
690 if ( ! isset($this->$_ci_key))
691 {
692 $this->$_ci_key =& $_ci_CI->$_ci_key;
693 }
694 }
695 }
696
697 /*
698 * Extract and cache variables
699 *
700 * You can either set variables using the dedicated $this->load_vars()
701 * function or via the second parameter of this function. We'll merge
702 * the two types and cache them so that views that are embedded within
703 * other views can have access to these variables.
704 */
705 if (is_array($_ci_vars))
706 {
707 $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
708 }
709 extract($this->_ci_cached_vars);
710
711 /*
712 * Buffer the output
713 *
714 * We buffer the output for two reasons:
715 * 1. Speed. You get a significant speed boost.
716 * 2. So that the final rendered template can be
717 * post-processed by the output class. Why do we
718 * need post processing? For one thing, in order to
719 * show the elapsed page load time. Unless we
720 * can intercept the content right before it's sent to
721 * the browser and then stop the timer it won't be accurate.
722 */
723 ob_start();
724
725 // If the PHP installation does not support short tags we'll
726 // do a little string replacement, changing the short tags
727 // to standard PHP echo statements.
728
729 if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE)
730 {
731 echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
732 }
733 else
734 {
735 include($_ci_path); // include() vs include_once() allows for multiple views with the same name
736 }
737
738 log_message('debug', 'File loaded: '.$_ci_path);
739
740 // Return the file data if requested
741 if ($_ci_return === TRUE)
742 {
743 $buffer = ob_get_contents();
744 @ob_end_clean();
745 return $buffer;
746 }
747
748 /*
749 * Flush the buffer... or buff the flusher?
750 *
751 * In order to permit views to be nested within
752 * other views, we need to flush the content back out whenever
753 * we are beyond the first level of output buffering so that
754 * it can be seen and included properly by the first included
755 * template and any subsequent ones. Oy!
756 *
757 */
758 if (ob_get_level() > $this->_ci_ob_level + 1)
759 {
760 ob_end_flush();
761 }
762 else
763 {
764 // PHP 4 requires that we use a global
765 global $OUT;
766 $OUT->append_output(ob_get_contents());
767 @ob_end_clean();
768 }
769 }
770
771 // --------------------------------------------------------------------
772
773 /**
774 * Load class
775 *
776 * This function loads the requested class.
777 *
778 * @access private
779 * @param string the item that is being loaded
780 * @param mixed any additional parameters
781 * @param string an optional object name
782 * @return void
783 */
784 function _ci_load_class($class, $params = NULL, $object_name = NULL)
785 {
786 // Get the class name, and while we're at it trim any slashes.
787 // The directory path can be included as part of the class name,
788 // but we don't want a leading slash
789 $class = str_replace(EXT, '', trim($class, '/'));
790
791 // Was the path included with the class name?
792 // We look for a slash to determine this
793 $subdir = '';
Derek Jones32bf1862010-03-02 13:46:07 -0600794 if (($last_slash = strrpos($class, '/')) !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000795 {
Derek Jones32bf1862010-03-02 13:46:07 -0600796 // Extract the path
797 $subdir = substr($class, 0, $last_slash + 1);
Derek Allard2067d1a2008-11-13 22:59:24 +0000798
Derek Jones32bf1862010-03-02 13:46:07 -0600799 // Get the filename from the path
800 $class = substr($class, $last_slash + 1);
Derek Allard2067d1a2008-11-13 22:59:24 +0000801 }
802
803 // We'll test for both lowercase and capitalized versions of the file name
804 foreach (array(ucfirst($class), strtolower($class)) as $class)
805 {
806 $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.EXT;
807
808 // Is this a class extension request?
809 if (file_exists($subclass))
810 {
811 $baseclass = BASEPATH.'libraries/'.ucfirst($class).EXT;
812
813 if ( ! file_exists($baseclass))
814 {
815 log_message('error', "Unable to load the requested class: ".$class);
816 show_error("Unable to load the requested class: ".$class);
817 }
818
819 // Safety: Was the class already loaded by a previous call?
820 if (in_array($subclass, $this->_ci_loaded_files))
821 {
822 // Before we deem this to be a duplicate request, let's see
823 // if a custom object name is being supplied. If so, we'll
824 // return a new instance of the object
825 if ( ! is_null($object_name))
826 {
827 $CI =& get_instance();
828 if ( ! isset($CI->$object_name))
829 {
830 return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
831 }
832 }
833
834 $is_duplicate = TRUE;
835 log_message('debug', $class." class already loaded. Second attempt ignored.");
836 return;
837 }
838
839 include_once($baseclass);
840 include_once($subclass);
841 $this->_ci_loaded_files[] = $subclass;
842
843 return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
844 }
845
846 // Lets search for the requested library file and load it.
Derek Jones32bf1862010-03-02 13:46:07 -0600847 $is_duplicate = FALSE;
848 foreach ($this->_ci_library_paths as $path)
Derek Allard2067d1a2008-11-13 22:59:24 +0000849 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000850 $filepath = $path.'libraries/'.$subdir.$class.EXT;
Derek Jones32bf1862010-03-02 13:46:07 -0600851
Derek Allard2067d1a2008-11-13 22:59:24 +0000852 // Does the file exist? No? Bummer...
853 if ( ! file_exists($filepath))
854 {
855 continue;
856 }
857
858 // Safety: Was the class already loaded by a previous call?
859 if (in_array($filepath, $this->_ci_loaded_files))
860 {
861 // Before we deem this to be a duplicate request, let's see
862 // if a custom object name is being supplied. If so, we'll
863 // return a new instance of the object
864 if ( ! is_null($object_name))
865 {
866 $CI =& get_instance();
867 if ( ! isset($CI->$object_name))
868 {
869 return $this->_ci_init_class($class, '', $params, $object_name);
870 }
871 }
872
873 $is_duplicate = TRUE;
874 log_message('debug', $class." class already loaded. Second attempt ignored.");
875 return;
876 }
877
878 include_once($filepath);
879 $this->_ci_loaded_files[] = $filepath;
Derek Jones32bf1862010-03-02 13:46:07 -0600880 return $this->_ci_init_class($class, '', $params, $object_name);
Derek Allard2067d1a2008-11-13 22:59:24 +0000881 }
Derek Jones32bf1862010-03-02 13:46:07 -0600882
Derek Allard2067d1a2008-11-13 22:59:24 +0000883 } // END FOREACH
884
885 // One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
886 if ($subdir == '')
887 {
888 $path = strtolower($class).'/'.$class;
889 return $this->_ci_load_class($path, $params);
890 }
891
892 // If we got this far we were unable to find the requested class.
893 // We do not issue errors if the load call failed due to a duplicate request
894 if ($is_duplicate == FALSE)
895 {
896 log_message('error', "Unable to load the requested class: ".$class);
897 show_error("Unable to load the requested class: ".$class);
898 }
899 }
900
901 // --------------------------------------------------------------------
902
903 /**
904 * Instantiates a class
905 *
906 * @access private
907 * @param string
908 * @param string
909 * @param string an optional object name
910 * @return null
911 */
912 function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL)
913 {
Derek Jones32bf1862010-03-02 13:46:07 -0600914 // Is there an associated config file for this class? Note: these should always be lowercase
Derek Allard2067d1a2008-11-13 22:59:24 +0000915 if ($config === NULL)
916 {
917 // We test for both uppercase and lowercase, for servers that
918 // are case-sensitive with regard to file names
919 if (file_exists(APPPATH.'config/'.strtolower($class).EXT))
920 {
921 include_once(APPPATH.'config/'.strtolower($class).EXT);
922 }
Derek Jonesc8dddd92009-07-10 18:58:03 +0000923 elseif (file_exists(APPPATH.'config/'.ucfirst(strtolower($class)).EXT))
Derek Allard2067d1a2008-11-13 22:59:24 +0000924 {
Derek Jonesc8dddd92009-07-10 18:58:03 +0000925 include_once(APPPATH.'config/'.ucfirst(strtolower($class)).EXT);
Derek Allard2067d1a2008-11-13 22:59:24 +0000926 }
927 }
928
929 if ($prefix == '')
930 {
931 if (class_exists('CI_'.$class))
932 {
933 $name = 'CI_'.$class;
934 }
935 elseif (class_exists(config_item('subclass_prefix').$class))
936 {
937 $name = config_item('subclass_prefix').$class;
938 }
939 else
940 {
941 $name = $class;
942 }
943 }
944 else
945 {
946 $name = $prefix.$class;
947 }
948
949 // Is the class name valid?
950 if ( ! class_exists($name))
951 {
952 log_message('error', "Non-existent class: ".$name);
953 show_error("Non-existent class: ".$class);
954 }
955
956 // Set the variable name we will assign the class to
957 // Was a custom class name supplied? If so we'll use it
958 $class = strtolower($class);
959
960 if (is_null($object_name))
961 {
962 $classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class];
963 }
964 else
965 {
966 $classvar = $object_name;
967 }
968
969 // Save the class name and object name
970 $this->_ci_classes[$class] = $classvar;
971
972 // Instantiate the class
973 $CI =& get_instance();
974 if ($config !== NULL)
975 {
976 $CI->$classvar = new $name($config);
977 }
978 else
979 {
980 $CI->$classvar = new $name;
981 }
982 }
983
984 // --------------------------------------------------------------------
985
986 /**
987 * Autoloader
988 *
989 * The config/autoload.php file contains an array that permits sub-systems,
990 * libraries, plugins, and helpers to be loaded automatically.
991 *
992 * @access private
993 * @param array
994 * @return void
995 */
996 function _ci_autoloader()
997 {
998 include_once(APPPATH.'config/autoload'.EXT);
999
1000 if ( ! isset($autoload))
1001 {
1002 return FALSE;
1003 }
1004
1005 // Load any custom config file
1006 if (count($autoload['config']) > 0)
1007 {
1008 $CI =& get_instance();
1009 foreach ($autoload['config'] as $key => $val)
1010 {
1011 $CI->config->load($val);
1012 }
1013 }
1014
1015 // Autoload plugins, helpers and languages
1016 foreach (array('helper', 'plugin', 'language') as $type)
1017 {
1018 if (isset($autoload[$type]) AND count($autoload[$type]) > 0)
1019 {
1020 $this->$type($autoload[$type]);
1021 }
1022 }
1023
1024 // A little tweak to remain backward compatible
1025 // The $autoload['core'] item was deprecated
Derek Jones32bf1862010-03-02 13:46:07 -06001026 if ( ! isset($autoload['libraries']) AND isset($autoload['core']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001027 {
1028 $autoload['libraries'] = $autoload['core'];
1029 }
1030
1031 // Load libraries
1032 if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0)
1033 {
1034 // Load the database driver.
1035 if (in_array('database', $autoload['libraries']))
1036 {
1037 $this->database();
1038 $autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
1039 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001040
1041 // Load all other libraries
1042 foreach ($autoload['libraries'] as $item)
1043 {
1044 $this->library($item);
1045 }
1046 }
1047
1048 // Autoload models
1049 if (isset($autoload['model']))
1050 {
1051 $this->model($autoload['model']);
1052 }
1053
1054 }
1055
1056 // --------------------------------------------------------------------
1057
1058 /**
1059 * Assign to Models
1060 *
1061 * Makes sure that anything loaded by the loader class (libraries, plugins, etc.)
1062 * will be available to models, if any exist.
1063 *
1064 * @access private
1065 * @param object
1066 * @return array
1067 */
1068 function _ci_assign_to_models()
1069 {
1070 if (count($this->_ci_models) == 0)
1071 {
1072 return;
1073 }
1074
Derek Jones32bf1862010-03-02 13:46:07 -06001075 foreach($this->_ci_models as $model)
Derek Allard2067d1a2008-11-13 22:59:24 +00001076 {
Derek Jones32bf1862010-03-02 13:46:07 -06001077 $model = $this->_ci_get_component($model);
1078 $model->_assign_libraries();
Derek Allard2067d1a2008-11-13 22:59:24 +00001079 }
1080 }
1081
1082 // --------------------------------------------------------------------
1083
1084 /**
1085 * Object to Array
1086 *
1087 * Takes an object as input and converts the class variables to array key/vals
1088 *
1089 * @access private
1090 * @param object
1091 * @return array
1092 */
1093 function _ci_object_to_array($object)
1094 {
1095 return (is_object($object)) ? get_object_vars($object) : $object;
1096 }
1097
1098 // --------------------------------------------------------------------
1099
1100 /**
1101 * Determines whether we should use the CI instance or $this
Derek Jones32bf1862010-03-02 13:46:07 -06001102 * @PHP4
1103 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001104 * @access private
1105 * @return bool
1106 */
1107 function _ci_is_instance()
1108 {
Derek Jones32bf1862010-03-02 13:46:07 -06001109 if (is_php('5.0.0') == TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001110 {
1111 return TRUE;
1112 }
1113
1114 global $CI;
1115 return (is_object($CI)) ? TRUE : FALSE;
1116 }
Derek Jones32bf1862010-03-02 13:46:07 -06001117
1118 // --------------------------------------------------------------------
1119
1120 /**
1121 * Get a reference to a specific library or model
1122 *
1123 * @access private
1124 * @return bool
1125 */
1126 function &_ci_get_component($component)
1127 {
1128 if ($this->_ci_is_instance())
1129 {
1130 $CI =& get_instance();
1131 return $CI->$component;
1132 }
1133 else
1134 {
1135 return $this->$component;
1136 }
1137 }
1138
1139 // --------------------------------------------------------------------
1140
1141 /**
1142 * Prep filename
1143 *
1144 * This function preps the name of various items to make loading them more reliable.
1145 *
1146 * @access private
1147 * @param mixed
1148 * @return array
1149 */
1150 function _ci_prep_filename($filename, $extension)
1151 {
1152 if ( ! is_array($filename))
1153 {
1154 return array(strtolower(str_replace(EXT, '', str_replace($extension, '', $filename)).$extension));
1155 }
1156 else
1157 {
1158 foreach ($filename as $key => $val)
1159 {
1160 $filename[$key] = strtolower(str_replace(EXT, '', str_replace($extension, '', $val)).$extension);
1161 }
1162
1163 return $filename;
1164 }
1165 }
1166
Derek Allard2067d1a2008-11-13 22:59:24 +00001167
1168}
1169
1170/* End of file Loader.php */
Derek Jonesc68dfbf2010-03-02 12:59:23 -06001171/* Location: ./system/core/Loader.php */