blob: 292fdc9551b9fa54893e2644372fef53f1dbda11 [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();
Derek Allard2067d1a2008-11-13 22:59:24 +000044 var $_ci_varmap = array('unit_test' => 'unit', 'user_agent' => 'agent');
45
46
47 /**
48 * Constructor
49 *
50 * Sets the path to the view files and gets the initial output buffering level
51 *
52 * @access public
53 */
54 function CI_Loader()
55 {
Derek Allard2067d1a2008-11-13 22:59:24 +000056 $this->_ci_view_path = APPPATH.'views/';
57 $this->_ci_ob_level = ob_get_level();
Derek Jones32bf1862010-03-02 13:46:07 -060058 $this->_ci_library_paths = array(APPPATH, BASEPATH);
59 $this->_ci_helper_paths = array(APPPATH, BASEPATH);
60 $this->_ci_model_paths = array(APPPATH);
61
Derek Allard2067d1a2008-11-13 22:59:24 +000062 log_message('debug', "Loader Class Initialized");
63 }
64
65 // --------------------------------------------------------------------
66
67 /**
68 * Class Loader
69 *
70 * This function lets users load and instantiate classes.
71 * It is designed to be called from a user's app controllers.
72 *
73 * @access public
74 * @param string the name of the class
75 * @param mixed the optional parameters
76 * @param string an optional object name
77 * @return void
78 */
79 function library($library = '', $params = NULL, $object_name = NULL)
80 {
Derek Jones32bf1862010-03-02 13:46:07 -060081 if ($library == '' OR isset($this->_base_classes[$library]))
Derek Allard2067d1a2008-11-13 22:59:24 +000082 {
83 return FALSE;
84 }
85
Derek Jones32bf1862010-03-02 13:46:07 -060086 if ( ! is_null($params) && ! is_array($params))
Derek Allard2067d1a2008-11-13 22:59:24 +000087 {
88 $params = NULL;
89 }
90
91 if (is_array($library))
92 {
93 foreach ($library as $class)
94 {
95 $this->_ci_load_class($class, $params, $object_name);
96 }
97 }
98 else
99 {
100 $this->_ci_load_class($library, $params, $object_name);
101 }
102
103 $this->_ci_assign_to_models();
104 }
105
106 // --------------------------------------------------------------------
107
108 /**
109 * Model Loader
110 *
111 * This function lets users load and instantiate models.
112 *
113 * @access public
114 * @param string the name of the class
115 * @param string name for the model
116 * @param bool database connection
117 * @return void
118 */
119 function model($model, $name = '', $db_conn = FALSE)
120 {
121 if (is_array($model))
122 {
123 foreach($model as $babe)
124 {
125 $this->model($babe);
126 }
127 return;
128 }
129
130 if ($model == '')
131 {
132 return;
133 }
134
Derek Jones32bf1862010-03-02 13:46:07 -0600135 $path = '';
136
Derek Allard2067d1a2008-11-13 22:59:24 +0000137 // Is the model in a sub-folder? If so, parse out the filename and path.
Derek Jones32bf1862010-03-02 13:46:07 -0600138 if (($last_slash = strrpos($model, '/')) !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000139 {
Derek Jones32bf1862010-03-02 13:46:07 -0600140 // The path is in front of the last slash
141 $path = substr($model, 0, $last_slash + 1);
142
143 // And the model name behind it
144 $model = substr($model, $last_slash + 1);
Derek Allard2067d1a2008-11-13 22:59:24 +0000145 }
146
147 if ($name == '')
148 {
149 $name = $model;
150 }
151
152 if (in_array($name, $this->_ci_models, TRUE))
153 {
154 return;
155 }
156
157 $CI =& get_instance();
158 if (isset($CI->$name))
159 {
160 show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
161 }
162
163 $model = strtolower($model);
Derek Allard2067d1a2008-11-13 22:59:24 +0000164
Derek Jones32bf1862010-03-02 13:46:07 -0600165 foreach ($this->_ci_model_paths as $mod_path)
166 {
167 if ( ! file_exists($mod_path.'models/'.$path.$model.EXT))
168 {
169 continue;
170 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000171
Derek Jones32bf1862010-03-02 13:46:07 -0600172 if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
173 {
174 if ($db_conn === TRUE)
175 $db_conn = '';
176
177 $CI->load->database($db_conn, FALSE, TRUE);
178 }
179
180 if ( ! class_exists('Model'))
181 {
182 load_class('Model', 'core');
183 }
184
185 require_once($mod_path.'models/'.$path.$model.EXT);
186
187 $model = ucfirst($model);
188
189 $CI->$name = new $model();
190 $CI->$name->_assign_libraries();
191
192 $this->_ci_models[] = $name;
193 return;
194 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000195
Derek Jones32bf1862010-03-02 13:46:07 -0600196 // couldn't find the model
197 show_error('Unable to locate the model you have specified: '.$model);
Derek Allard2067d1a2008-11-13 22:59:24 +0000198 }
199
200 // --------------------------------------------------------------------
201
202 /**
203 * Database Loader
204 *
205 * @access public
206 * @param string the DB credentials
207 * @param bool whether to return the DB object
208 * @param bool whether to enable active record (this allows us to override the config setting)
209 * @return object
210 */
Derek Jonesffca6c22009-12-05 15:31:44 +0000211 function database($params = '', $return = FALSE, $active_record = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000212 {
213 // Grab the super object
214 $CI =& get_instance();
215
216 // Do we even need to load the database class?
Derek Jones9fb6dd12009-12-05 15:32:48 +0000217 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 +0000218 {
219 return FALSE;
220 }
221
222 require_once(BASEPATH.'database/DB'.EXT);
223
224 if ($return === TRUE)
225 {
226 return DB($params, $active_record);
227 }
228
229 // Initialize the db variable. Needed to prevent
230 // reference errors with some configurations
231 $CI->db = '';
232
233 // Load the DB class
234 $CI->db =& DB($params, $active_record);
235
236 // Assign the DB object to any existing models
237 $this->_ci_assign_to_models();
238 }
239
240 // --------------------------------------------------------------------
241
242 /**
243 * Load the Utilities Class
244 *
245 * @access public
246 * @return string
247 */
248 function dbutil()
249 {
250 if ( ! class_exists('CI_DB'))
251 {
252 $this->database();
253 }
254
255 $CI =& get_instance();
256
257 // for backwards compatibility, load dbforge so we can extend dbutils off it
258 // this use is deprecated and strongly discouraged
259 $CI->load->dbforge();
260
261 require_once(BASEPATH.'database/DB_utility'.EXT);
262 require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility'.EXT);
263 $class = 'CI_DB_'.$CI->db->dbdriver.'_utility';
264
Derek Jonesf0a9b332009-07-29 14:19:18 +0000265 $CI->dbutil =& instantiate_class(new $class());
Derek Allard2067d1a2008-11-13 22:59:24 +0000266
267 $CI->load->_ci_assign_to_models();
268 }
269
270 // --------------------------------------------------------------------
271
272 /**
273 * Load the Database Forge Class
274 *
275 * @access public
276 * @return string
277 */
278 function dbforge()
279 {
280 if ( ! class_exists('CI_DB'))
281 {
282 $this->database();
283 }
284
285 $CI =& get_instance();
286
287 require_once(BASEPATH.'database/DB_forge'.EXT);
288 require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge'.EXT);
289 $class = 'CI_DB_'.$CI->db->dbdriver.'_forge';
290
291 $CI->dbforge = new $class();
292
293 $CI->load->_ci_assign_to_models();
294 }
295
296 // --------------------------------------------------------------------
297
298 /**
299 * Load View
300 *
301 * This function is used to load a "view" file. It has three parameters:
302 *
303 * 1. The name of the "view" file to be included.
304 * 2. An associative array of data to be extracted for use in the view.
305 * 3. TRUE/FALSE - whether to return the data or load it. In
306 * some cases it's advantageous to be able to return data so that
307 * a developer can process it in some way.
308 *
309 * @access public
310 * @param string
311 * @param array
312 * @param bool
313 * @return void
314 */
315 function view($view, $vars = array(), $return = FALSE)
316 {
317 return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
318 }
319
320 // --------------------------------------------------------------------
321
322 /**
323 * Load File
324 *
325 * This is a generic file loader
326 *
327 * @access public
328 * @param string
329 * @param bool
330 * @return string
331 */
332 function file($path, $return = FALSE)
333 {
334 return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));
335 }
336
337 // --------------------------------------------------------------------
338
339 /**
340 * Set Variables
341 *
342 * Once variables are set they become available within
343 * the controller class and its "view" files.
344 *
345 * @access public
346 * @param array
347 * @return void
348 */
349 function vars($vars = array(), $val = '')
350 {
351 if ($val != '' AND is_string($vars))
352 {
353 $vars = array($vars => $val);
354 }
355
356 $vars = $this->_ci_object_to_array($vars);
357
358 if (is_array($vars) AND count($vars) > 0)
359 {
360 foreach ($vars as $key => $val)
361 {
362 $this->_ci_cached_vars[$key] = $val;
363 }
364 }
365 }
366
367 // --------------------------------------------------------------------
368
369 /**
370 * Load Helper
371 *
372 * This function loads the specified helper file.
373 *
374 * @access public
375 * @param mixed
376 * @return void
377 */
378 function helper($helpers = array())
Derek Jones32bf1862010-03-02 13:46:07 -0600379 {
380 foreach ($this->_ci_prep_filename($helpers, '_helper') as $helper)
381 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000382 if (isset($this->_ci_helpers[$helper]))
383 {
384 continue;
385 }
Derek Jones32bf1862010-03-02 13:46:07 -0600386
Derek Allard2067d1a2008-11-13 22:59:24 +0000387 $ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.EXT;
388
389 // Is this a helper extension request?
390 if (file_exists($ext_helper))
391 {
392 $base_helper = BASEPATH.'helpers/'.$helper.EXT;
393
394 if ( ! file_exists($base_helper))
395 {
396 show_error('Unable to load the requested file: helpers/'.$helper.EXT);
397 }
398
399 include_once($ext_helper);
400 include_once($base_helper);
Derek Jones32bf1862010-03-02 13:46:07 -0600401
402 $this->_ci_helpers[$helper] = TRUE;
403 log_message('debug', 'Helper loaded: '.$helper);
404 continue;
Derek Allard2067d1a2008-11-13 22:59:24 +0000405 }
Derek Jones32bf1862010-03-02 13:46:07 -0600406
407 // Try to load the helper
408 foreach ($this->_ci_helper_paths as $path)
409 {
410 if (file_exists($path.'helpers/'.$helper.EXT))
411 {
412 include_once($path.'helpers/'.$helper.EXT);
413
414 $this->_ci_helpers[$helper] = TRUE;
415 log_message('debug', 'Helper loaded: '.$helper);
416 break;
Derek Allard2067d1a2008-11-13 22:59:24 +0000417 }
418 }
419
Derek Jones32bf1862010-03-02 13:46:07 -0600420 // unable to load the helper
421 if ( ! isset($this->_ci_helpers[$helper]))
422 {
423 show_error('Unable to load the requested file: helpers/'.$helper.EXT);
424 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000425 }
426 }
427
428 // --------------------------------------------------------------------
429
430 /**
431 * Load Helpers
432 *
433 * This is simply an alias to the above function in case the
434 * user has written the plural form of this function.
435 *
436 * @access public
437 * @param array
438 * @return void
439 */
440 function helpers($helpers = array())
441 {
442 $this->helper($helpers);
443 }
444
445 // --------------------------------------------------------------------
446
447 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000448 * Loads a language file
449 *
450 * @access public
451 * @param array
452 * @param string
453 * @return void
454 */
455 function language($file = array(), $lang = '')
456 {
457 $CI =& get_instance();
458
459 if ( ! is_array($file))
460 {
461 $file = array($file);
462 }
463
464 foreach ($file as $langfile)
465 {
466 $CI->lang->load($langfile, $lang);
467 }
468 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000469
470 // --------------------------------------------------------------------
471
472 /**
473 * Loads a config file
474 *
475 * @access public
476 * @param string
477 * @return void
478 */
479 function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
480 {
481 $CI =& get_instance();
482 $CI->config->load($file, $use_sections, $fail_gracefully);
483 }
484
485 // --------------------------------------------------------------------
Derek Jones32bf1862010-03-02 13:46:07 -0600486
Derek Allard2067d1a2008-11-13 22:59:24 +0000487 /**
Derek Jones8dca0412010-03-05 13:01:44 -0600488 * Driver
489 *
490 * Loads a driver library
491 *
492 * @param string the name of the class
493 * @param mixed the optional parameters
494 * @param string an optional object name
495 * @return void
496 */
497 function driver($library = '', $params = NULL, $object_name = NULL)
498 {
499 if ( ! class_exists('CI_Driver_Library'))
500 {
501 // we aren't instantiating an object here, that'll be done by the Library itself
Derek Jonesd5e0cb52010-03-09 20:20:46 -0600502 require BASEPATH.'libraries/Driver'.EXT;
503 }
504
505 // We can save the loader some time since Drivers will *always* be in a subfolder,
506 // and typically identically named to the library
507 if ( ! strpos($library, '/'))
508 {
Greg Akerd25e66a2010-03-28 01:07:09 -0500509 $library = ucfirst($library).'/'.$library;
Derek Jones8dca0412010-03-05 13:01:44 -0600510 }
511
512 return $this->library($library, $params, $object_name);
513 }
514
515 // --------------------------------------------------------------------
516
517 /**
Derek Jones32bf1862010-03-02 13:46:07 -0600518 * Add Package Path
Derek Allard2067d1a2008-11-13 22:59:24 +0000519 *
Derek Jones32bf1862010-03-02 13:46:07 -0600520 * Prepends a parent path to the library, model, helper, and config path arrays
Derek Allard2067d1a2008-11-13 22:59:24 +0000521 *
522 * @access public
523 * @param string
524 * @return void
Derek Jones32bf1862010-03-02 13:46:07 -0600525 */
526 function add_package_path($path)
527 {
528 array_unshift($this->_ci_library_paths, $path);
529 array_unshift($this->_ci_model_paths, $path);
530 array_unshift($this->_ci_helper_paths, $path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000531
Derek Jones32bf1862010-03-02 13:46:07 -0600532 // Add config file path
533 $config =& $this->_ci_get_component('config');
534 array_unshift($config->_config_paths, $path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000535 }
536
537 // --------------------------------------------------------------------
Derek Jones32bf1862010-03-02 13:46:07 -0600538
539 /**
540 * Remove Package Path
541 *
542 * Remove a path from the library, model, and helper path arrays if it exists
543 * If no path is provided, the most recently added path is removed.
544 *
545 * @access public
546 * @param type
547 * @return type
548 */
549 function remove_package_path($path = '', $remove_config_path = TRUE)
550 {
551 $config =& $this->_ci_get_component('config');
Derek Allard2067d1a2008-11-13 22:59:24 +0000552
Derek Jones32bf1862010-03-02 13:46:07 -0600553 if ($path == '')
554 {
555 $void = array_shift($this->_ci_library_paths);
556 $void = array_shift($this->_ci_model_paths);
557 $void = array_shift($this->_ci_helper_paths);
558 $void = array_shift($config->_config_paths);
559 }
560 else
561 {
562 foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
563 {
564 if (($key = array_search($path, $this->{$var})) !== FALSE)
565 {
566 unset($this->{$var}[$key]);
567 }
568 }
569
570 if (($key = array_search($path, $config->_config_paths)) !== FALSE)
571 {
572 unset($config->_config_paths[$key]);
573 }
574 }
575
576 // make sure the application default paths are still in the array
577 $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
578 $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
579 $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
580 $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
581 }
582
583 // --------------------------------------------------------------------
584
Derek Allard2067d1a2008-11-13 22:59:24 +0000585 /**
586 * Loader
587 *
588 * This function is used to load views and files.
589 * Variables are prefixed with _ci_ to avoid symbol collision with
590 * variables made available to view files
591 *
592 * @access private
593 * @param array
594 * @return void
595 */
596 function _ci_load($_ci_data)
597 {
598 // Set the default data variables
599 foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
600 {
601 $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];
602 }
603
604 // Set the path to the requested file
605 if ($_ci_path == '')
606 {
607 $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
608 $_ci_file = ($_ci_ext == '') ? $_ci_view.EXT : $_ci_view;
609 $_ci_path = $this->_ci_view_path.$_ci_file;
610 }
611 else
612 {
613 $_ci_x = explode('/', $_ci_path);
614 $_ci_file = end($_ci_x);
615 }
616
617 if ( ! file_exists($_ci_path))
618 {
619 show_error('Unable to load the requested file: '.$_ci_file);
620 }
621
622 // This allows anything loaded using $this->load (views, files, etc.)
623 // to become accessible from within the Controller and Model functions.
624 // Only needed when running PHP 5
625
626 if ($this->_ci_is_instance())
627 {
628 $_ci_CI =& get_instance();
629 foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
630 {
631 if ( ! isset($this->$_ci_key))
632 {
633 $this->$_ci_key =& $_ci_CI->$_ci_key;
634 }
635 }
636 }
637
638 /*
639 * Extract and cache variables
640 *
641 * You can either set variables using the dedicated $this->load_vars()
642 * function or via the second parameter of this function. We'll merge
643 * the two types and cache them so that views that are embedded within
644 * other views can have access to these variables.
645 */
646 if (is_array($_ci_vars))
647 {
648 $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
649 }
650 extract($this->_ci_cached_vars);
651
652 /*
653 * Buffer the output
654 *
655 * We buffer the output for two reasons:
656 * 1. Speed. You get a significant speed boost.
657 * 2. So that the final rendered template can be
658 * post-processed by the output class. Why do we
659 * need post processing? For one thing, in order to
660 * show the elapsed page load time. Unless we
661 * can intercept the content right before it's sent to
662 * the browser and then stop the timer it won't be accurate.
663 */
664 ob_start();
665
666 // If the PHP installation does not support short tags we'll
667 // do a little string replacement, changing the short tags
668 // to standard PHP echo statements.
669
670 if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE)
671 {
672 echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
673 }
674 else
675 {
676 include($_ci_path); // include() vs include_once() allows for multiple views with the same name
677 }
678
679 log_message('debug', 'File loaded: '.$_ci_path);
680
681 // Return the file data if requested
682 if ($_ci_return === TRUE)
683 {
684 $buffer = ob_get_contents();
685 @ob_end_clean();
686 return $buffer;
687 }
688
689 /*
690 * Flush the buffer... or buff the flusher?
691 *
692 * In order to permit views to be nested within
693 * other views, we need to flush the content back out whenever
694 * we are beyond the first level of output buffering so that
695 * it can be seen and included properly by the first included
696 * template and any subsequent ones. Oy!
697 *
698 */
699 if (ob_get_level() > $this->_ci_ob_level + 1)
700 {
701 ob_end_flush();
702 }
703 else
704 {
705 // PHP 4 requires that we use a global
706 global $OUT;
707 $OUT->append_output(ob_get_contents());
708 @ob_end_clean();
709 }
710 }
711
712 // --------------------------------------------------------------------
713
714 /**
715 * Load class
716 *
717 * This function loads the requested class.
718 *
719 * @access private
720 * @param string the item that is being loaded
721 * @param mixed any additional parameters
722 * @param string an optional object name
723 * @return void
724 */
725 function _ci_load_class($class, $params = NULL, $object_name = NULL)
726 {
727 // Get the class name, and while we're at it trim any slashes.
728 // The directory path can be included as part of the class name,
729 // but we don't want a leading slash
730 $class = str_replace(EXT, '', trim($class, '/'));
731
732 // Was the path included with the class name?
733 // We look for a slash to determine this
734 $subdir = '';
Derek Jones32bf1862010-03-02 13:46:07 -0600735 if (($last_slash = strrpos($class, '/')) !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000736 {
Derek Jones32bf1862010-03-02 13:46:07 -0600737 // Extract the path
738 $subdir = substr($class, 0, $last_slash + 1);
Derek Allard2067d1a2008-11-13 22:59:24 +0000739
Derek Jones32bf1862010-03-02 13:46:07 -0600740 // Get the filename from the path
741 $class = substr($class, $last_slash + 1);
Derek Allard2067d1a2008-11-13 22:59:24 +0000742 }
743
744 // We'll test for both lowercase and capitalized versions of the file name
745 foreach (array(ucfirst($class), strtolower($class)) as $class)
746 {
747 $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.EXT;
748
749 // Is this a class extension request?
750 if (file_exists($subclass))
751 {
752 $baseclass = BASEPATH.'libraries/'.ucfirst($class).EXT;
753
754 if ( ! file_exists($baseclass))
755 {
756 log_message('error', "Unable to load the requested class: ".$class);
757 show_error("Unable to load the requested class: ".$class);
758 }
759
760 // Safety: Was the class already loaded by a previous call?
761 if (in_array($subclass, $this->_ci_loaded_files))
762 {
763 // Before we deem this to be a duplicate request, let's see
764 // if a custom object name is being supplied. If so, we'll
765 // return a new instance of the object
766 if ( ! is_null($object_name))
767 {
768 $CI =& get_instance();
769 if ( ! isset($CI->$object_name))
770 {
771 return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
772 }
773 }
774
775 $is_duplicate = TRUE;
776 log_message('debug', $class." class already loaded. Second attempt ignored.");
777 return;
778 }
779
780 include_once($baseclass);
781 include_once($subclass);
782 $this->_ci_loaded_files[] = $subclass;
783
784 return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
785 }
786
787 // Lets search for the requested library file and load it.
Derek Jones32bf1862010-03-02 13:46:07 -0600788 $is_duplicate = FALSE;
789 foreach ($this->_ci_library_paths as $path)
Derek Allard2067d1a2008-11-13 22:59:24 +0000790 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000791 $filepath = $path.'libraries/'.$subdir.$class.EXT;
Derek Jones32bf1862010-03-02 13:46:07 -0600792
Derek Allard2067d1a2008-11-13 22:59:24 +0000793 // Does the file exist? No? Bummer...
794 if ( ! file_exists($filepath))
795 {
796 continue;
797 }
798
799 // Safety: Was the class already loaded by a previous call?
800 if (in_array($filepath, $this->_ci_loaded_files))
801 {
802 // Before we deem this to be a duplicate request, let's see
803 // if a custom object name is being supplied. If so, we'll
804 // return a new instance of the object
805 if ( ! is_null($object_name))
806 {
807 $CI =& get_instance();
808 if ( ! isset($CI->$object_name))
809 {
810 return $this->_ci_init_class($class, '', $params, $object_name);
811 }
812 }
813
814 $is_duplicate = TRUE;
815 log_message('debug', $class." class already loaded. Second attempt ignored.");
816 return;
817 }
818
819 include_once($filepath);
820 $this->_ci_loaded_files[] = $filepath;
Derek Jones32bf1862010-03-02 13:46:07 -0600821 return $this->_ci_init_class($class, '', $params, $object_name);
Derek Allard2067d1a2008-11-13 22:59:24 +0000822 }
Derek Jones32bf1862010-03-02 13:46:07 -0600823
Derek Allard2067d1a2008-11-13 22:59:24 +0000824 } // END FOREACH
825
826 // One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
827 if ($subdir == '')
828 {
829 $path = strtolower($class).'/'.$class;
830 return $this->_ci_load_class($path, $params);
831 }
832
833 // If we got this far we were unable to find the requested class.
834 // We do not issue errors if the load call failed due to a duplicate request
835 if ($is_duplicate == FALSE)
836 {
837 log_message('error', "Unable to load the requested class: ".$class);
838 show_error("Unable to load the requested class: ".$class);
839 }
840 }
841
842 // --------------------------------------------------------------------
843
844 /**
845 * Instantiates a class
846 *
847 * @access private
848 * @param string
849 * @param string
850 * @param string an optional object name
851 * @return null
852 */
853 function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL)
854 {
Derek Jones32bf1862010-03-02 13:46:07 -0600855 // Is there an associated config file for this class? Note: these should always be lowercase
Derek Allard2067d1a2008-11-13 22:59:24 +0000856 if ($config === NULL)
857 {
858 // We test for both uppercase and lowercase, for servers that
859 // are case-sensitive with regard to file names
860 if (file_exists(APPPATH.'config/'.strtolower($class).EXT))
861 {
862 include_once(APPPATH.'config/'.strtolower($class).EXT);
863 }
Derek Jonesc8dddd92009-07-10 18:58:03 +0000864 elseif (file_exists(APPPATH.'config/'.ucfirst(strtolower($class)).EXT))
Derek Allard2067d1a2008-11-13 22:59:24 +0000865 {
Derek Jonesc8dddd92009-07-10 18:58:03 +0000866 include_once(APPPATH.'config/'.ucfirst(strtolower($class)).EXT);
Derek Allard2067d1a2008-11-13 22:59:24 +0000867 }
868 }
869
870 if ($prefix == '')
871 {
872 if (class_exists('CI_'.$class))
873 {
874 $name = 'CI_'.$class;
875 }
876 elseif (class_exists(config_item('subclass_prefix').$class))
877 {
878 $name = config_item('subclass_prefix').$class;
879 }
880 else
881 {
882 $name = $class;
883 }
884 }
885 else
886 {
887 $name = $prefix.$class;
888 }
889
890 // Is the class name valid?
891 if ( ! class_exists($name))
892 {
893 log_message('error', "Non-existent class: ".$name);
894 show_error("Non-existent class: ".$class);
895 }
896
897 // Set the variable name we will assign the class to
898 // Was a custom class name supplied? If so we'll use it
899 $class = strtolower($class);
900
901 if (is_null($object_name))
902 {
903 $classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class];
904 }
905 else
906 {
907 $classvar = $object_name;
908 }
909
910 // Save the class name and object name
911 $this->_ci_classes[$class] = $classvar;
912
913 // Instantiate the class
914 $CI =& get_instance();
915 if ($config !== NULL)
916 {
917 $CI->$classvar = new $name($config);
918 }
919 else
920 {
921 $CI->$classvar = new $name;
922 }
923 }
924
925 // --------------------------------------------------------------------
926
927 /**
928 * Autoloader
929 *
930 * The config/autoload.php file contains an array that permits sub-systems,
Derek Jonesc6da5032010-03-09 20:44:27 -0600931 * libraries, and helpers to be loaded automatically.
Derek Allard2067d1a2008-11-13 22:59:24 +0000932 *
933 * @access private
934 * @param array
935 * @return void
936 */
937 function _ci_autoloader()
938 {
939 include_once(APPPATH.'config/autoload'.EXT);
940
941 if ( ! isset($autoload))
942 {
943 return FALSE;
944 }
945
946 // Load any custom config file
947 if (count($autoload['config']) > 0)
948 {
949 $CI =& get_instance();
950 foreach ($autoload['config'] as $key => $val)
951 {
952 $CI->config->load($val);
953 }
954 }
955
Derek Jonesc6da5032010-03-09 20:44:27 -0600956 // Autoload helpers and languages
957 foreach (array('helper', 'language') as $type)
Derek Allard2067d1a2008-11-13 22:59:24 +0000958 {
959 if (isset($autoload[$type]) AND count($autoload[$type]) > 0)
960 {
961 $this->$type($autoload[$type]);
962 }
963 }
964
965 // A little tweak to remain backward compatible
966 // The $autoload['core'] item was deprecated
Derek Jones32bf1862010-03-02 13:46:07 -0600967 if ( ! isset($autoload['libraries']) AND isset($autoload['core']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000968 {
969 $autoload['libraries'] = $autoload['core'];
970 }
971
972 // Load libraries
973 if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0)
974 {
975 // Load the database driver.
976 if (in_array('database', $autoload['libraries']))
977 {
978 $this->database();
979 $autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
980 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000981
982 // Load all other libraries
983 foreach ($autoload['libraries'] as $item)
984 {
985 $this->library($item);
986 }
987 }
988
989 // Autoload models
990 if (isset($autoload['model']))
991 {
992 $this->model($autoload['model']);
993 }
994
995 }
996
997 // --------------------------------------------------------------------
998
999 /**
1000 * Assign to Models
1001 *
Derek Jonesc6da5032010-03-09 20:44:27 -06001002 * Makes sure that anything loaded by the loader class (libraries, etc.)
Derek Allard2067d1a2008-11-13 22:59:24 +00001003 * will be available to models, if any exist.
1004 *
1005 * @access private
1006 * @param object
1007 * @return array
1008 */
1009 function _ci_assign_to_models()
1010 {
1011 if (count($this->_ci_models) == 0)
1012 {
1013 return;
1014 }
1015
Derek Jones32bf1862010-03-02 13:46:07 -06001016 foreach($this->_ci_models as $model)
Derek Allard2067d1a2008-11-13 22:59:24 +00001017 {
Derek Jones32bf1862010-03-02 13:46:07 -06001018 $model = $this->_ci_get_component($model);
1019 $model->_assign_libraries();
Derek Allard2067d1a2008-11-13 22:59:24 +00001020 }
1021 }
1022
1023 // --------------------------------------------------------------------
1024
1025 /**
1026 * Object to Array
1027 *
1028 * Takes an object as input and converts the class variables to array key/vals
1029 *
1030 * @access private
1031 * @param object
1032 * @return array
1033 */
1034 function _ci_object_to_array($object)
1035 {
1036 return (is_object($object)) ? get_object_vars($object) : $object;
1037 }
1038
1039 // --------------------------------------------------------------------
1040
1041 /**
1042 * Determines whether we should use the CI instance or $this
Derek Jones32bf1862010-03-02 13:46:07 -06001043 * @PHP4
1044 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001045 * @access private
1046 * @return bool
1047 */
1048 function _ci_is_instance()
1049 {
Derek Jones32bf1862010-03-02 13:46:07 -06001050 if (is_php('5.0.0') == TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001051 {
1052 return TRUE;
1053 }
1054
1055 global $CI;
1056 return (is_object($CI)) ? TRUE : FALSE;
1057 }
Derek Jones32bf1862010-03-02 13:46:07 -06001058
1059 // --------------------------------------------------------------------
1060
1061 /**
1062 * Get a reference to a specific library or model
1063 *
1064 * @access private
1065 * @return bool
1066 */
1067 function &_ci_get_component($component)
1068 {
1069 if ($this->_ci_is_instance())
1070 {
1071 $CI =& get_instance();
1072 return $CI->$component;
1073 }
1074 else
1075 {
1076 return $this->$component;
1077 }
1078 }
1079
1080 // --------------------------------------------------------------------
1081
1082 /**
1083 * Prep filename
1084 *
1085 * This function preps the name of various items to make loading them more reliable.
1086 *
1087 * @access private
1088 * @param mixed
1089 * @return array
1090 */
1091 function _ci_prep_filename($filename, $extension)
1092 {
1093 if ( ! is_array($filename))
1094 {
1095 return array(strtolower(str_replace(EXT, '', str_replace($extension, '', $filename)).$extension));
1096 }
1097 else
1098 {
1099 foreach ($filename as $key => $val)
1100 {
1101 $filename[$key] = strtolower(str_replace(EXT, '', str_replace($extension, '', $val)).$extension);
1102 }
1103
1104 return $filename;
1105 }
1106 }
1107
Derek Allard2067d1a2008-11-13 22:59:24 +00001108
1109}
1110
1111/* End of file Loader.php */
Derek Jonesc68dfbf2010-03-02 12:59:23 -06001112/* Location: ./system/core/Loader.php */