1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
5 * An open source application development framework for PHP 5.1.6 or newer
8 * @author ExpressionEngine Dev Team
9 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
10 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
16 // ------------------------------------------------------------------------
21 * Loads views and files
23 * @package CodeIgniter
24 * @subpackage Libraries
25 * @author ExpressionEngine Dev Team
27 * @link http://codeigniter.com/user_guide/libraries/loader.html
31 // All these are set automatically. Don't mess with them.
33 var $_ci_view_path = '';
34 var $_ci_library_paths = array();
35 var $_ci_model_paths = array();
36 var $_ci_helper_paths = array();
37 var $_base_classes = array(); // Set by the controller class
38 var $_ci_cached_vars = array();
39 var $_ci_classes = array();
40 var $_ci_loaded_files = array();
41 var $_ci_models = array();
42 var $_ci_helpers = array();
43 var $_ci_varmap = array('unit_test' => 'unit', 'user_agent' => 'agent');
49 * Sets the path to the view files and gets the initial output buffering level
53 function __construct()
55 $this->_ci_view_path = APPPATH.'views/';
56 $this->_ci_ob_level = ob_get_level();
57 $this->_ci_library_paths = array(APPPATH, BASEPATH);
58 $this->_ci_helper_paths = array(APPPATH, BASEPATH);
59 $this->_ci_model_paths = array(APPPATH);
61 log_message('debug', "Loader Class Initialized");
64 // --------------------------------------------------------------------
69 * This function lets users load and instantiate classes.
70 * It is designed to be called from a user's app controllers.
73 * @param string the name of the class
74 * @param mixed the optional parameters
75 * @param string an optional object name
78 function library($library = '', $params = NULL, $object_name = NULL)
80 if (is_array($library))
82 foreach ($library as $class)
84 $this->library($class, $params);
90 if ($library == '' OR isset($this->_base_classes[$library]))
95 if ( ! is_null($params) && ! is_array($params))
100 $this->_ci_load_class($library, $params, $object_name);
103 // --------------------------------------------------------------------
108 * This function lets users load and instantiate models.
111 * @param string the name of the class
112 * @param string name for the model
113 * @param bool database connection
116 function model($model, $name = '', $db_conn = FALSE)
118 if (is_array($model))
120 foreach ($model as $babe)
134 // Is the model in a sub-folder? If so, parse out the filename and path.
135 if (($last_slash = strrpos($model, '/')) !== FALSE)
137 // The path is in front of the last slash
138 $path = substr($model, 0, $last_slash + 1);
140 // And the model name behind it
141 $model = substr($model, $last_slash + 1);
149 if (in_array($name, $this->_ci_models, TRUE))
154 $CI =& get_instance();
155 if (isset($CI->$name))
157 show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
160 $model = strtolower($model);
162 foreach ($this->_ci_model_paths as $mod_path)
164 if ( ! file_exists($mod_path.'models/'.$path.$model.EXT))
169 if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
171 if ($db_conn === TRUE)
176 $CI->load->database($db_conn, FALSE, TRUE);
179 if ( ! class_exists('CI_Model'))
181 load_class('Model', 'core');
184 require_once($mod_path.'models/'.$path.$model.EXT);
186 $model = ucfirst($model);
188 $CI->$name = new $model();
190 $this->_ci_models[] = $name;
194 // couldn't find the model
195 show_error('Unable to locate the model you have specified: '.$model);
198 // --------------------------------------------------------------------
204 * @param string the DB credentials
205 * @param bool whether to return the DB object
206 * @param bool whether to enable active record (this allows us to override the config setting)
209 function database($params = '', $return = FALSE, $active_record = NULL)
211 // Grab the super object
212 $CI =& get_instance();
214 // Do we even need to load the database class?
215 if (class_exists('CI_DB') AND $return == FALSE AND $active_record == NULL AND isset($CI->db) AND is_object($CI->db))
220 require_once(BASEPATH.'database/DB'.EXT);
222 if ($return === TRUE)
224 return DB($params, $active_record);
227 // Initialize the db variable. Needed to prevent
228 // reference errors with some configurations
232 $CI->db =& DB($params, $active_record);
235 // --------------------------------------------------------------------
238 * Load the Utilities Class
245 if ( ! class_exists('CI_DB'))
250 $CI =& get_instance();
252 // for backwards compatibility, load dbforge so we can extend dbutils off it
253 // this use is deprecated and strongly discouraged
254 $CI->load->dbforge();
256 require_once(BASEPATH.'database/DB_utility'.EXT);
257 require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility'.EXT);
258 $class = 'CI_DB_'.$CI->db->dbdriver.'_utility';
260 $CI->dbutil = new $class();
263 // --------------------------------------------------------------------
266 * Load the Database Forge Class
273 if ( ! class_exists('CI_DB'))
278 $CI =& get_instance();
280 require_once(BASEPATH.'database/DB_forge'.EXT);
281 require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge'.EXT);
282 $class = 'CI_DB_'.$CI->db->dbdriver.'_forge';
284 $CI->dbforge = new $class();
287 // --------------------------------------------------------------------
292 * This function is used to load a "view" file. It has three parameters:
294 * 1. The name of the "view" file to be included.
295 * 2. An associative array of data to be extracted for use in the view.
296 * 3. TRUE/FALSE - whether to return the data or load it. In
297 * some cases it's advantageous to be able to return data so that
298 * a developer can process it in some way.
306 function view($view, $vars = array(), $return = FALSE)
308 return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
311 // --------------------------------------------------------------------
316 * This is a generic file loader
323 function file($path, $return = FALSE)
325 return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));
328 // --------------------------------------------------------------------
333 * Once variables are set they become available within
334 * the controller class and its "view" files.
340 function vars($vars = array(), $val = '')
342 if ($val != '' AND is_string($vars))
344 $vars = array($vars => $val);
347 $vars = $this->_ci_object_to_array($vars);
349 if (is_array($vars) AND count($vars) > 0)
351 foreach ($vars as $key => $val)
353 $this->_ci_cached_vars[$key] = $val;
358 // --------------------------------------------------------------------
363 * This function loads the specified helper file.
369 function helper($helpers = array())
371 foreach ($this->_ci_prep_filename($helpers, '_helper') as $helper)
373 if (isset($this->_ci_helpers[$helper]))
378 $ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.EXT;
380 // Is this a helper extension request?
381 if (file_exists($ext_helper))
383 $base_helper = BASEPATH.'helpers/'.$helper.EXT;
385 if ( ! file_exists($base_helper))
387 show_error('Unable to load the requested file: helpers/'.$helper.EXT);
390 include_once($ext_helper);
391 include_once($base_helper);
393 $this->_ci_helpers[$helper] = TRUE;
394 log_message('debug', 'Helper loaded: '.$helper);
398 // Try to load the helper
399 foreach ($this->_ci_helper_paths as $path)
401 if (file_exists($path.'helpers/'.$helper.EXT))
403 include_once($path.'helpers/'.$helper.EXT);
405 $this->_ci_helpers[$helper] = TRUE;
406 log_message('debug', 'Helper loaded: '.$helper);
411 // unable to load the helper
412 if ( ! isset($this->_ci_helpers[$helper]))
414 show_error('Unable to load the requested file: helpers/'.$helper.EXT);
419 // --------------------------------------------------------------------
424 * This is simply an alias to the above function in case the
425 * user has written the plural form of this function.
431 function helpers($helpers = array())
433 $this->helper($helpers);
436 // --------------------------------------------------------------------
439 * Loads a language file
446 function language($file = array(), $lang = '')
448 $CI =& get_instance();
450 if ( ! is_array($file))
452 $file = array($file);
455 foreach ($file as $langfile)
457 $CI->lang->load($langfile, $lang);
461 // --------------------------------------------------------------------
464 * Loads a config file
470 function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
472 $CI =& get_instance();
473 $CI->config->load($file, $use_sections, $fail_gracefully);
476 // --------------------------------------------------------------------
481 * Loads a driver library
483 * @param string the name of the class
484 * @param mixed the optional parameters
485 * @param string an optional object name
488 function driver($library = '', $params = NULL, $object_name = NULL)
490 if ( ! class_exists('CI_Driver_Library'))
492 // we aren't instantiating an object here, that'll be done by the Library itself
493 require BASEPATH.'libraries/Driver'.EXT;
496 // We can save the loader some time since Drivers will *always* be in a subfolder,
497 // and typically identically named to the library
498 if ( ! strpos($library, '/'))
500 $library = ucfirst($library).'/'.$library;
503 return $this->library($library, $params, $object_name);
506 // --------------------------------------------------------------------
511 * Prepends a parent path to the library, model, helper, and config path arrays
517 function add_package_path($path)
519 $path = rtrim($path, '/').'/';
521 array_unshift($this->_ci_library_paths, $path);
522 array_unshift($this->_ci_model_paths, $path);
523 array_unshift($this->_ci_helper_paths, $path);
525 // Add config file path
526 $config =& $this->_ci_get_component('config');
527 array_unshift($config->_config_paths, $path);
530 // --------------------------------------------------------------------
535 * Return a list of all package paths, by default it will ignore BASEPATH.
541 function get_package_paths($include_base = FALSE)
543 return $include_base === TRUE ? $this->_ci_library_paths : $this->_ci_model_paths;
546 // --------------------------------------------------------------------
549 * Remove Package Path
551 * Remove a path from the library, model, and helper path arrays if it exists
552 * If no path is provided, the most recently added path is removed.
558 function remove_package_path($path = '', $remove_config_path = TRUE)
560 $config =& $this->_ci_get_component('config');
564 $void = array_shift($this->_ci_library_paths);
565 $void = array_shift($this->_ci_model_paths);
566 $void = array_shift($this->_ci_helper_paths);
567 $void = array_shift($config->_config_paths);
571 $path = rtrim($path, '/').'/';
573 foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
575 if (($key = array_search($path, $this->{$var})) !== FALSE)
577 unset($this->{$var}[$key]);
581 if (($key = array_search($path, $config->_config_paths)) !== FALSE)
583 unset($config->_config_paths[$key]);
587 // make sure the application default paths are still in the array
588 $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
589 $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
590 $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
591 $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
594 // --------------------------------------------------------------------
599 * This function is used to load views and files.
600 * Variables are prefixed with _ci_ to avoid symbol collision with
601 * variables made available to view files
607 function _ci_load($_ci_data)
609 // Set the default data variables
610 foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
612 $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];
615 // Set the path to the requested file
618 $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
619 $_ci_file = ($_ci_ext == '') ? $_ci_view.EXT : $_ci_view;
620 $_ci_path = $this->_ci_view_path.$_ci_file;
624 $_ci_x = explode('/', $_ci_path);
625 $_ci_file = end($_ci_x);
628 if ( ! file_exists($_ci_path))
630 show_error('Unable to load the requested file: '.$_ci_file);
633 // This allows anything loaded using $this->load (views, files, etc.)
634 // to become accessible from within the Controller and Model functions.
636 $_ci_CI =& get_instance();
637 foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
639 if ( ! isset($this->$_ci_key))
641 $this->$_ci_key =& $_ci_CI->$_ci_key;
646 * Extract and cache variables
648 * You can either set variables using the dedicated $this->load_vars()
649 * function or via the second parameter of this function. We'll merge
650 * the two types and cache them so that views that are embedded within
651 * other views can have access to these variables.
653 if (is_array($_ci_vars))
655 $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
657 extract($this->_ci_cached_vars);
662 * We buffer the output for two reasons:
663 * 1. Speed. You get a significant speed boost.
664 * 2. So that the final rendered template can be
665 * post-processed by the output class. Why do we
666 * need post processing? For one thing, in order to
667 * show the elapsed page load time. Unless we
668 * can intercept the content right before it's sent to
669 * the browser and then stop the timer it won't be accurate.
673 // If the PHP installation does not support short tags we'll
674 // do a little string replacement, changing the short tags
675 // to standard PHP echo statements.
677 if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE)
679 echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
683 include($_ci_path); // include() vs include_once() allows for multiple views with the same name
686 log_message('debug', 'File loaded: '.$_ci_path);
688 // Return the file data if requested
689 if ($_ci_return === TRUE)
691 $buffer = ob_get_contents();
697 * Flush the buffer... or buff the flusher?
699 * In order to permit views to be nested within
700 * other views, we need to flush the content back out whenever
701 * we are beyond the first level of output buffering so that
702 * it can be seen and included properly by the first included
703 * template and any subsequent ones. Oy!
706 if (ob_get_level() > $this->_ci_ob_level + 1)
712 $_ci_CI->output->append_output(ob_get_contents());
717 // --------------------------------------------------------------------
722 * This function loads the requested class.
725 * @param string the item that is being loaded
726 * @param mixed any additional parameters
727 * @param string an optional object name
730 function _ci_load_class($class, $params = NULL, $object_name = NULL)
732 // Get the class name, and while we're at it trim any slashes.
733 // The directory path can be included as part of the class name,
734 // but we don't want a leading slash
735 $class = str_replace(EXT, '', trim($class, '/'));
737 // Was the path included with the class name?
738 // We look for a slash to determine this
740 if (($last_slash = strrpos($class, '/')) !== FALSE)
743 $subdir = substr($class, 0, $last_slash + 1);
745 // Get the filename from the path
746 $class = substr($class, $last_slash + 1);
749 // We'll test for both lowercase and capitalized versions of the file name
750 foreach (array(ucfirst($class), strtolower($class)) as $class)
752 $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.EXT;
754 // Is this a class extension request?
755 if (file_exists($subclass))
757 $baseclass = BASEPATH.'libraries/'.ucfirst($class).EXT;
759 if ( ! file_exists($baseclass))
761 log_message('error', "Unable to load the requested class: ".$class);
762 show_error("Unable to load the requested class: ".$class);
765 // Safety: Was the class already loaded by a previous call?
766 if (in_array($subclass, $this->_ci_loaded_files))
768 // Before we deem this to be a duplicate request, let's see
769 // if a custom object name is being supplied. If so, we'll
770 // return a new instance of the object
771 if ( ! is_null($object_name))
773 $CI =& get_instance();
774 if ( ! isset($CI->$object_name))
776 return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
780 $is_duplicate = TRUE;
781 log_message('debug', $class." class already loaded. Second attempt ignored.");
785 include_once($baseclass);
786 include_once($subclass);
787 $this->_ci_loaded_files[] = $subclass;
789 return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
792 // Lets search for the requested library file and load it.
793 $is_duplicate = FALSE;
794 foreach ($this->_ci_library_paths as $path)
796 $filepath = $path.'libraries/'.$subdir.$class.EXT;
798 // Does the file exist? No? Bummer...
799 if ( ! file_exists($filepath))
804 // Safety: Was the class already loaded by a previous call?
805 if (in_array($filepath, $this->_ci_loaded_files))
807 // Before we deem this to be a duplicate request, let's see
808 // if a custom object name is being supplied. If so, we'll
809 // return a new instance of the object
810 if ( ! is_null($object_name))
812 $CI =& get_instance();
813 if ( ! isset($CI->$object_name))
815 return $this->_ci_init_class($class, '', $params, $object_name);
819 $is_duplicate = TRUE;
820 log_message('debug', $class." class already loaded. Second attempt ignored.");
824 include_once($filepath);
825 $this->_ci_loaded_files[] = $filepath;
826 return $this->_ci_init_class($class, '', $params, $object_name);
831 // One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
834 $path = strtolower($class).'/'.$class;
835 return $this->_ci_load_class($path, $params);
838 // If we got this far we were unable to find the requested class.
839 // We do not issue errors if the load call failed due to a duplicate request
840 if ($is_duplicate == FALSE)
842 log_message('error', "Unable to load the requested class: ".$class);
843 show_error("Unable to load the requested class: ".$class);
847 // --------------------------------------------------------------------
850 * Instantiates a class
855 * @param string an optional object name
858 function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL)
860 // Is there an associated config file for this class? Note: these should always be lowercase
861 if ($config === NULL)
863 // Fetch the config paths containing any package paths
864 $config_component = $this->_ci_get_component('config');
866 if (is_array($config_component->_config_paths))
868 // Break on the first found file, thus package files
869 // are not overridden by default paths
870 foreach ($config_component->_config_paths as $path)
872 // We test for both uppercase and lowercase, for servers that
873 // are case-sensitive with regard to file names. Check for environment
874 // first, global next
875 if (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).EXT))
877 include_once($path .'config/'.ENVIRONMENT.'/'.strtolower($class).EXT);
880 elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).EXT))
882 include_once($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).EXT);
885 elseif (file_exists($path .'config/'.strtolower($class).EXT))
887 include_once($path .'config/'.strtolower($class).EXT);
890 elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).EXT))
892 include_once($path .'config/'.ucfirst(strtolower($class)).EXT);
901 if (class_exists('CI_'.$class))
903 $name = 'CI_'.$class;
905 elseif (class_exists(config_item('subclass_prefix').$class))
907 $name = config_item('subclass_prefix').$class;
916 $name = $prefix.$class;
919 // Is the class name valid?
920 if ( ! class_exists($name))
922 log_message('error', "Non-existent class: ".$name);
923 show_error("Non-existent class: ".$class);
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);
930 if (is_null($object_name))
932 $classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class];
936 $classvar = $object_name;
939 // Save the class name and object name
940 $this->_ci_classes[$class] = $classvar;
942 // Instantiate the class
943 $CI =& get_instance();
944 if ($config !== NULL)
946 $CI->$classvar = new $name($config);
950 $CI->$classvar = new $name;
954 // --------------------------------------------------------------------
959 * The config/autoload.php file contains an array that permits sub-systems,
960 * libraries, and helpers to be loaded automatically.
966 function _ci_autoloader()
968 if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload'.EXT))
970 include_once(APPPATH.'config/'.ENVIRONMENT.'/autoload'.EXT);
974 include_once(APPPATH.'config/autoload'.EXT);
978 if ( ! isset($autoload))
984 if (isset($autoload['packages']))
986 foreach ($autoload['packages'] as $package_path)
988 $this->add_package_path($package_path);
992 // Load any custom config file
993 if (count($autoload['config']) > 0)
995 $CI =& get_instance();
996 foreach ($autoload['config'] as $key => $val)
998 $CI->config->load($val);
1002 // Autoload helpers and languages
1003 foreach (array('helper', 'language') as $type)
1005 if (isset($autoload[$type]) AND count($autoload[$type]) > 0)
1007 $this->$type($autoload[$type]);
1011 // A little tweak to remain backward compatible
1012 // The $autoload['core'] item was deprecated
1013 if ( ! isset($autoload['libraries']) AND isset($autoload['core']))
1015 $autoload['libraries'] = $autoload['core'];
1019 if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0)
1021 // Load the database driver.
1022 if (in_array('database', $autoload['libraries']))
1025 $autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
1028 // Load all other libraries
1029 foreach ($autoload['libraries'] as $item)
1031 $this->library($item);
1036 if (isset($autoload['model']))
1038 $this->model($autoload['model']);
1042 // --------------------------------------------------------------------
1047 * Takes an object as input and converts the class variables to array key/vals
1053 function _ci_object_to_array($object)
1055 return (is_object($object)) ? get_object_vars($object) : $object;
1058 // --------------------------------------------------------------------
1061 * Get a reference to a specific library or model
1066 function &_ci_get_component($component)
1068 $CI =& get_instance();
1069 return $CI->$component;
1072 // --------------------------------------------------------------------
1077 * This function preps the name of various items to make loading them more reliable.
1083 function _ci_prep_filename($filename, $extension)
1085 if ( ! is_array($filename))
1087 return array(strtolower(str_replace(EXT, '', str_replace($extension, '', $filename)).$extension));
1091 foreach ($filename as $key => $val)
1093 $filename[$key] = strtolower(str_replace(EXT, '', str_replace($extension, '', $val)).$extension);
1103 /* End of file Loader.php */
1104 /* Location: ./system/core/Loader.php */