PageRenderTime 65ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/system/core/Loader.php

https://bitbucket.org/ellislab/codeigniter-reactor/
PHP | 1147 lines | 609 code | 160 blank | 378 comment | 87 complexity | d4786dc9b8f34ac30e5b186abc14e47a MD5 | raw file
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 5.1.6 or newer
  6. *
  7. * @package CodeIgniter
  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
  12. * @since Version 1.0
  13. * @filesource
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * Loader Class
  18. *
  19. * Loads views and files
  20. *
  21. * @package CodeIgniter
  22. * @subpackage Libraries
  23. * @author ExpressionEngine Dev Team
  24. * @category Loader
  25. * @link http://codeigniter.com/user_guide/libraries/loader.html
  26. */
  27. class CI_Loader {
  28. // All these are set automatically. Don't mess with them.
  29. protected $_ci_ob_level;
  30. protected $_ci_view_paths = array();
  31. protected $_ci_library_paths = array();
  32. protected $_ci_model_paths = array();
  33. protected $_ci_helper_paths = array();
  34. protected $_base_classes = array(); // Set by the controller class
  35. protected $_ci_cached_vars = array();
  36. protected $_ci_classes = array();
  37. protected $_ci_loaded_files = array();
  38. protected $_ci_models = array();
  39. protected $_ci_helpers = array();
  40. protected $_ci_varmap = array('unit_test' => 'unit',
  41. 'user_agent' => 'agent');
  42. /**
  43. * Constructor
  44. *
  45. * Sets the path to the view files and gets the initial output buffering level
  46. */
  47. public function __construct()
  48. {
  49. $this->_ci_ob_level = ob_get_level();
  50. $this->_ci_library_paths = array(APPPATH, BASEPATH);
  51. $this->_ci_helper_paths = array(APPPATH, BASEPATH);
  52. $this->_ci_model_paths = array(APPPATH);
  53. $this->_ci_view_paths = array(APPPATH.'views/' => TRUE);
  54. log_message('debug', "Loader Class Initialized");
  55. }
  56. // --------------------------------------------------------------------
  57. /**
  58. * Set _base_classes variable
  59. *
  60. * This method is called once in CI_Controller.
  61. *
  62. * @param array
  63. * @return object
  64. */
  65. public function set_base_classes()
  66. {
  67. $this->_base_classes =& is_loaded();
  68. return $this;
  69. }
  70. // --------------------------------------------------------------------
  71. /**
  72. * Is Loaded
  73. *
  74. * A utility function to test if a class is in the self::$_ci_classes array.
  75. * This function returns the object name if the class tested for is loaded,
  76. * and returns FALSE if it isn't.
  77. *
  78. * It is mainly used in the form_helper -> _get_validation_object()
  79. *
  80. * @param string class being checked for
  81. * @return mixed class object name on the CI SuperObject or FALSE
  82. */
  83. public function is_loaded($class)
  84. {
  85. if (isset($this->_ci_classes[$class]))
  86. {
  87. return $this->_ci_classes[$class];
  88. }
  89. return FALSE;
  90. }
  91. // --------------------------------------------------------------------
  92. /**
  93. * Class Loader
  94. *
  95. * This function lets users load and instantiate classes.
  96. * It is designed to be called from a user's app controllers.
  97. *
  98. * @param string the name of the class
  99. * @param mixed the optional parameters
  100. * @param string an optional object name
  101. * @return void
  102. */
  103. public function library($library = '', $params = NULL, $object_name = NULL)
  104. {
  105. if (is_array($library))
  106. {
  107. foreach ($library as $class)
  108. {
  109. $this->library($class, $params);
  110. }
  111. return;
  112. }
  113. if ($library == '' OR isset($this->_base_classes[$library]))
  114. {
  115. return FALSE;
  116. }
  117. if ( ! is_null($params) && ! is_array($params))
  118. {
  119. $params = NULL;
  120. }
  121. $this->_ci_load_class($library, $params, $object_name);
  122. }
  123. // --------------------------------------------------------------------
  124. /**
  125. * Model Loader
  126. *
  127. * This function lets users load and instantiate models.
  128. *
  129. * @param string the name of the class
  130. * @param string name for the model
  131. * @param bool database connection
  132. * @return void
  133. */
  134. public function model($model, $name = '', $db_conn = FALSE)
  135. {
  136. if (is_array($model))
  137. {
  138. foreach ($model as $babe)
  139. {
  140. $this->model($babe);
  141. }
  142. return;
  143. }
  144. if ($model == '')
  145. {
  146. return;
  147. }
  148. $path = '';
  149. // Is the model in a sub-folder? If so, parse out the filename and path.
  150. if (($last_slash = strrpos($model, '/')) !== FALSE)
  151. {
  152. // The path is in front of the last slash
  153. $path = substr($model, 0, $last_slash + 1);
  154. // And the model name behind it
  155. $model = substr($model, $last_slash + 1);
  156. }
  157. if ($name == '')
  158. {
  159. $name = $model;
  160. }
  161. if (in_array($name, $this->_ci_models, TRUE))
  162. {
  163. return;
  164. }
  165. $CI =& get_instance();
  166. if (isset($CI->$name))
  167. {
  168. show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
  169. }
  170. $model = strtolower($model);
  171. foreach ($this->_ci_model_paths as $mod_path)
  172. {
  173. if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
  174. {
  175. continue;
  176. }
  177. if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
  178. {
  179. if ($db_conn === TRUE)
  180. {
  181. $db_conn = '';
  182. }
  183. $CI->load->database($db_conn, FALSE, TRUE);
  184. }
  185. if ( ! class_exists('CI_Model'))
  186. {
  187. load_class('Model', 'core');
  188. }
  189. require_once($mod_path.'models/'.$path.$model.'.php');
  190. $model = ucfirst($model);
  191. $CI->$name = new $model();
  192. $this->_ci_models[] = $name;
  193. return;
  194. }
  195. // couldn't find the model
  196. show_error('Unable to locate the model you have specified: '.$model);
  197. }
  198. // --------------------------------------------------------------------
  199. /**
  200. * Database Loader
  201. *
  202. * @param string the DB credentials
  203. * @param bool whether to return the DB object
  204. * @param bool whether to enable active record (this allows us to override the config setting)
  205. * @return object
  206. */
  207. public function database($params = '', $return = FALSE, $active_record = NULL)
  208. {
  209. // Grab the super object
  210. $CI =& get_instance();
  211. // Do we even need to load the database class?
  212. if (class_exists('CI_DB') AND $return == FALSE AND $active_record == NULL AND isset($CI->db) AND is_object($CI->db))
  213. {
  214. return FALSE;
  215. }
  216. require_once(BASEPATH.'database/DB.php');
  217. if ($return === TRUE)
  218. {
  219. return DB($params, $active_record);
  220. }
  221. // Initialize the db variable. Needed to prevent
  222. // reference errors with some configurations
  223. $CI->db = '';
  224. // Load the DB class
  225. $CI->db =& DB($params, $active_record);
  226. }
  227. // --------------------------------------------------------------------
  228. /**
  229. * Load the Utilities Class
  230. *
  231. * @return string
  232. */
  233. public function dbutil()
  234. {
  235. if ( ! class_exists('CI_DB'))
  236. {
  237. $this->database();
  238. }
  239. $CI =& get_instance();
  240. // for backwards compatibility, load dbforge so we can extend dbutils off it
  241. // this use is deprecated and strongly discouraged
  242. $CI->load->dbforge();
  243. require_once(BASEPATH.'database/DB_utility.php');
  244. require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility.php');
  245. $class = 'CI_DB_'.$CI->db->dbdriver.'_utility';
  246. $CI->dbutil = new $class();
  247. }
  248. // --------------------------------------------------------------------
  249. /**
  250. * Load the Database Forge Class
  251. *
  252. * @return string
  253. */
  254. public function dbforge()
  255. {
  256. if ( ! class_exists('CI_DB'))
  257. {
  258. $this->database();
  259. }
  260. $CI =& get_instance();
  261. require_once(BASEPATH.'database/DB_forge.php');
  262. require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge.php');
  263. $class = 'CI_DB_'.$CI->db->dbdriver.'_forge';
  264. $CI->dbforge = new $class();
  265. }
  266. // --------------------------------------------------------------------
  267. /**
  268. * Load View
  269. *
  270. * This function is used to load a "view" file. It has three parameters:
  271. *
  272. * 1. The name of the "view" file to be included.
  273. * 2. An associative array of data to be extracted for use in the view.
  274. * 3. TRUE/FALSE - whether to return the data or load it. In
  275. * some cases it's advantageous to be able to return data so that
  276. * a developer can process it in some way.
  277. *
  278. * @param string
  279. * @param array
  280. * @param bool
  281. * @return void
  282. */
  283. public function view($view, $vars = array(), $return = FALSE)
  284. {
  285. return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
  286. }
  287. // --------------------------------------------------------------------
  288. /**
  289. * Load File
  290. *
  291. * This is a generic file loader
  292. *
  293. * @param string
  294. * @param bool
  295. * @return string
  296. */
  297. public function file($path, $return = FALSE)
  298. {
  299. return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));
  300. }
  301. // --------------------------------------------------------------------
  302. /**
  303. * Set Variables
  304. *
  305. * Once variables are set they become available within
  306. * the controller class and its "view" files.
  307. *
  308. * @param array
  309. * @return void
  310. */
  311. public function vars($vars = array(), $val = '')
  312. {
  313. if ($val != '' AND is_string($vars))
  314. {
  315. $vars = array($vars => $val);
  316. }
  317. $vars = $this->_ci_object_to_array($vars);
  318. if (is_array($vars) AND count($vars) > 0)
  319. {
  320. foreach ($vars as $key => $val)
  321. {
  322. $this->_ci_cached_vars[$key] = $val;
  323. }
  324. }
  325. }
  326. // --------------------------------------------------------------------
  327. /**
  328. * Load Helper
  329. *
  330. * This function loads the specified helper file.
  331. *
  332. * @param mixed
  333. * @return void
  334. */
  335. public function helper($helpers = array())
  336. {
  337. foreach ($this->_ci_prep_filename($helpers, '_helper') as $helper)
  338. {
  339. if (isset($this->_ci_helpers[$helper]))
  340. {
  341. continue;
  342. }
  343. $ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.'.php';
  344. // Is this a helper extension request?
  345. if (file_exists($ext_helper))
  346. {
  347. $base_helper = BASEPATH.'helpers/'.$helper.'.php';
  348. if ( ! file_exists($base_helper))
  349. {
  350. show_error('Unable to load the requested file: helpers/'.$helper.'.php');
  351. }
  352. include_once($ext_helper);
  353. include_once($base_helper);
  354. $this->_ci_helpers[$helper] = TRUE;
  355. log_message('debug', 'Helper loaded: '.$helper);
  356. continue;
  357. }
  358. // Try to load the helper
  359. foreach ($this->_ci_helper_paths as $path)
  360. {
  361. if (file_exists($path.'helpers/'.$helper.'.php'))
  362. {
  363. include_once($path.'helpers/'.$helper.'.php');
  364. $this->_ci_helpers[$helper] = TRUE;
  365. log_message('debug', 'Helper loaded: '.$helper);
  366. break;
  367. }
  368. }
  369. // unable to load the helper
  370. if ( ! isset($this->_ci_helpers[$helper]))
  371. {
  372. show_error('Unable to load the requested file: helpers/'.$helper.'.php');
  373. }
  374. }
  375. }
  376. // --------------------------------------------------------------------
  377. /**
  378. * Load Helpers
  379. *
  380. * This is simply an alias to the above function in case the
  381. * user has written the plural form of this function.
  382. *
  383. * @param array
  384. * @return void
  385. */
  386. public function helpers($helpers = array())
  387. {
  388. $this->helper($helpers);
  389. }
  390. // --------------------------------------------------------------------
  391. /**
  392. * Loads a language file
  393. *
  394. * @param array
  395. * @param string
  396. * @return void
  397. */
  398. public function language($file = array(), $lang = '')
  399. {
  400. $CI =& get_instance();
  401. if ( ! is_array($file))
  402. {
  403. $file = array($file);
  404. }
  405. foreach ($file as $langfile)
  406. {
  407. $CI->lang->load($langfile, $lang);
  408. }
  409. }
  410. // --------------------------------------------------------------------
  411. /**
  412. * Loads a config file
  413. *
  414. * @param string
  415. * @return void
  416. */
  417. public function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
  418. {
  419. $CI =& get_instance();
  420. $CI->config->load($file, $use_sections, $fail_gracefully);
  421. }
  422. // --------------------------------------------------------------------
  423. /**
  424. * Driver
  425. *
  426. * Loads a driver library
  427. *
  428. * @param string the name of the class
  429. * @param mixed the optional parameters
  430. * @param string an optional object name
  431. * @return void
  432. */
  433. public function driver($library = '', $params = NULL, $object_name = NULL)
  434. {
  435. if ( ! class_exists('CI_Driver_Library'))
  436. {
  437. // we aren't instantiating an object here, that'll be done by the Library itself
  438. require BASEPATH.'libraries/Driver.php';
  439. }
  440. // We can save the loader some time since Drivers will *always* be in a subfolder,
  441. // and typically identically named to the library
  442. if ( ! strpos($library, '/'))
  443. {
  444. $library = ucfirst($library).'/'.$library;
  445. }
  446. return $this->library($library, $params, $object_name);
  447. }
  448. // --------------------------------------------------------------------
  449. /**
  450. * Add Package Path
  451. *
  452. * Prepends a parent path to the library, model, helper, and config path arrays
  453. *
  454. * @param string
  455. * @param boolean
  456. * @return void
  457. */
  458. public function add_package_path($path, $view_cascade=TRUE)
  459. {
  460. $path = rtrim($path, '/').'/';
  461. array_unshift($this->_ci_library_paths, $path);
  462. array_unshift($this->_ci_model_paths, $path);
  463. array_unshift($this->_ci_helper_paths, $path);
  464. $this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;
  465. // Add config file path
  466. $config =& $this->_ci_get_component('config');
  467. array_unshift($config->_config_paths, $path);
  468. }
  469. // --------------------------------------------------------------------
  470. /**
  471. * Get Package Paths
  472. *
  473. * Return a list of all package paths, by default it will ignore BASEPATH.
  474. *
  475. * @param string
  476. * @return void
  477. */
  478. public function get_package_paths($include_base = FALSE)
  479. {
  480. return $include_base === TRUE ? $this->_ci_library_paths : $this->_ci_model_paths;
  481. }
  482. // --------------------------------------------------------------------
  483. /**
  484. * Remove Package Path
  485. *
  486. * Remove a path from the library, model, and helper path arrays if it exists
  487. * If no path is provided, the most recently added path is removed.
  488. *
  489. * @param type
  490. * @return type
  491. */
  492. public function remove_package_path($path = '', $remove_config_path = TRUE)
  493. {
  494. $config =& $this->_ci_get_component('config');
  495. if ($path == '')
  496. {
  497. $void = array_shift($this->_ci_library_paths);
  498. $void = array_shift($this->_ci_model_paths);
  499. $void = array_shift($this->_ci_helper_paths);
  500. $void = array_shift($this->_ci_view_paths);
  501. $void = array_shift($config->_config_paths);
  502. }
  503. else
  504. {
  505. $path = rtrim($path, '/').'/';
  506. foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
  507. {
  508. if (($key = array_search($path, $this->{$var})) !== FALSE)
  509. {
  510. unset($this->{$var}[$key]);
  511. }
  512. }
  513. if (isset($this->_ci_view_paths[$path.'views/']))
  514. {
  515. unset($this->_ci_view_paths[$path.'views/']);
  516. }
  517. if (($key = array_search($path, $config->_config_paths)) !== FALSE)
  518. {
  519. unset($config->_config_paths[$key]);
  520. }
  521. }
  522. // make sure the application default paths are still in the array
  523. $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
  524. $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
  525. $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
  526. $this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));
  527. $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
  528. }
  529. // --------------------------------------------------------------------
  530. /**
  531. * Loader
  532. *
  533. * This function is used to load views and files.
  534. * Variables are prefixed with _ci_ to avoid symbol collision with
  535. * variables made available to view files
  536. *
  537. * @param array
  538. * @return void
  539. */
  540. protected function _ci_load($_ci_data)
  541. {
  542. // Set the default data variables
  543. foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
  544. {
  545. $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];
  546. }
  547. $file_exists = FALSE;
  548. // Set the path to the requested file
  549. if ($_ci_path != '')
  550. {
  551. $_ci_x = explode('/', $_ci_path);
  552. $_ci_file = end($_ci_x);
  553. }
  554. else
  555. {
  556. $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
  557. $_ci_file = ($_ci_ext == '') ? $_ci_view.'.php' : $_ci_view;
  558. foreach ($this->_ci_view_paths as $view_file => $cascade)
  559. {
  560. if (file_exists($view_file.$_ci_file))
  561. {
  562. $_ci_path = $view_file.$_ci_file;
  563. $file_exists = TRUE;
  564. break;
  565. }
  566. if ( ! $cascade)
  567. {
  568. break;
  569. }
  570. }
  571. }
  572. if ( ! $file_exists && ! file_exists($_ci_path))
  573. {
  574. show_error('Unable to load the requested file: '.$_ci_file);
  575. }
  576. // This allows anything loaded using $this->load (views, files, etc.)
  577. // to become accessible from within the Controller and Model functions.
  578. $_ci_CI =& get_instance();
  579. foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
  580. {
  581. if ( ! isset($this->$_ci_key))
  582. {
  583. $this->$_ci_key =& $_ci_CI->$_ci_key;
  584. }
  585. }
  586. /*
  587. * Extract and cache variables
  588. *
  589. * You can either set variables using the dedicated $this->load_vars()
  590. * function or via the second parameter of this function. We'll merge
  591. * the two types and cache them so that views that are embedded within
  592. * other views can have access to these variables.
  593. */
  594. if (is_array($_ci_vars))
  595. {
  596. $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
  597. }
  598. extract($this->_ci_cached_vars);
  599. /*
  600. * Buffer the output
  601. *
  602. * We buffer the output for two reasons:
  603. * 1. Speed. You get a significant speed boost.
  604. * 2. So that the final rendered template can be
  605. * post-processed by the output class. Why do we
  606. * need post processing? For one thing, in order to
  607. * show the elapsed page load time. Unless we
  608. * can intercept the content right before it's sent to
  609. * the browser and then stop the timer it won't be accurate.
  610. */
  611. ob_start();
  612. // If the PHP installation does not support short tags we'll
  613. // do a little string replacement, changing the short tags
  614. // to standard PHP echo statements.
  615. if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE)
  616. {
  617. echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
  618. }
  619. else
  620. {
  621. include($_ci_path); // include() vs include_once() allows for multiple views with the same name
  622. }
  623. log_message('debug', 'File loaded: '.$_ci_path);
  624. // Return the file data if requested
  625. if ($_ci_return === TRUE)
  626. {
  627. $buffer = ob_get_contents();
  628. @ob_end_clean();
  629. return $buffer;
  630. }
  631. /*
  632. * Flush the buffer... or buff the flusher?
  633. *
  634. * In order to permit views to be nested within
  635. * other views, we need to flush the content back out whenever
  636. * we are beyond the first level of output buffering so that
  637. * it can be seen and included properly by the first included
  638. * template and any subsequent ones. Oy!
  639. *
  640. */
  641. if (ob_get_level() > $this->_ci_ob_level + 1)
  642. {
  643. ob_end_flush();
  644. }
  645. else
  646. {
  647. $_ci_CI->output->append_output(ob_get_contents());
  648. @ob_end_clean();
  649. }
  650. }
  651. // --------------------------------------------------------------------
  652. /**
  653. * Load class
  654. *
  655. * This function loads the requested class.
  656. *
  657. * @param string the item that is being loaded
  658. * @param mixed any additional parameters
  659. * @param string an optional object name
  660. * @return void
  661. */
  662. protected function _ci_load_class($class, $params = NULL, $object_name = NULL)
  663. {
  664. // Get the class name, and while we're at it trim any slashes.
  665. // The directory path can be included as part of the class name,
  666. // but we don't want a leading slash
  667. $class = str_replace('.php', '', trim($class, '/'));
  668. // Was the path included with the class name?
  669. // We look for a slash to determine this
  670. $subdir = '';
  671. if (($last_slash = strrpos($class, '/')) !== FALSE)
  672. {
  673. // Extract the path
  674. $subdir = substr($class, 0, $last_slash + 1);
  675. // Get the filename from the path
  676. $class = substr($class, $last_slash + 1);
  677. }
  678. // We'll test for both lowercase and capitalized versions of the file name
  679. foreach (array(ucfirst($class), strtolower($class)) as $class)
  680. {
  681. $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';
  682. // Is this a class extension request?
  683. if (file_exists($subclass))
  684. {
  685. $baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php';
  686. if ( ! file_exists($baseclass))
  687. {
  688. log_message('error', "Unable to load the requested class: ".$class);
  689. show_error("Unable to load the requested class: ".$class);
  690. }
  691. // Safety: Was the class already loaded by a previous call?
  692. if (in_array($subclass, $this->_ci_loaded_files))
  693. {
  694. // Before we deem this to be a duplicate request, let's see
  695. // if a custom object name is being supplied. If so, we'll
  696. // return a new instance of the object
  697. if ( ! is_null($object_name))
  698. {
  699. $CI =& get_instance();
  700. if ( ! isset($CI->$object_name))
  701. {
  702. return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
  703. }
  704. }
  705. $is_duplicate = TRUE;
  706. log_message('debug', $class." class already loaded. Second attempt ignored.");
  707. return;
  708. }
  709. include_once($baseclass);
  710. include_once($subclass);
  711. $this->_ci_loaded_files[] = $subclass;
  712. return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
  713. }
  714. // Lets search for the requested library file and load it.
  715. $is_duplicate = FALSE;
  716. foreach ($this->_ci_library_paths as $path)
  717. {
  718. $filepath = $path.'libraries/'.$subdir.$class.'.php';
  719. // Does the file exist? No? Bummer...
  720. if ( ! file_exists($filepath))
  721. {
  722. continue;
  723. }
  724. // Safety: Was the class already loaded by a previous call?
  725. if (in_array($filepath, $this->_ci_loaded_files))
  726. {
  727. // Before we deem this to be a duplicate request, let's see
  728. // if a custom object name is being supplied. If so, we'll
  729. // return a new instance of the object
  730. if ( ! is_null($object_name))
  731. {
  732. $CI =& get_instance();
  733. if ( ! isset($CI->$object_name))
  734. {
  735. return $this->_ci_init_class($class, '', $params, $object_name);
  736. }
  737. }
  738. $is_duplicate = TRUE;
  739. log_message('debug', $class." class already loaded. Second attempt ignored.");
  740. return;
  741. }
  742. include_once($filepath);
  743. $this->_ci_loaded_files[] = $filepath;
  744. return $this->_ci_init_class($class, '', $params, $object_name);
  745. }
  746. } // END FOREACH
  747. // One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
  748. if ($subdir == '')
  749. {
  750. $path = strtolower($class).'/'.$class;
  751. return $this->_ci_load_class($path, $params);
  752. }
  753. // If we got this far we were unable to find the requested class.
  754. // We do not issue errors if the load call failed due to a duplicate request
  755. if ($is_duplicate == FALSE)
  756. {
  757. log_message('error', "Unable to load the requested class: ".$class);
  758. show_error("Unable to load the requested class: ".$class);
  759. }
  760. }
  761. // --------------------------------------------------------------------
  762. /**
  763. * Instantiates a class
  764. *
  765. * @param string
  766. * @param string
  767. * @param string an optional object name
  768. * @return null
  769. */
  770. protected function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL)
  771. {
  772. // Is there an associated config file for this class? Note: these should always be lowercase
  773. if ($config === NULL)
  774. {
  775. // Fetch the config paths containing any package paths
  776. $config_component = $this->_ci_get_component('config');
  777. if (is_array($config_component->_config_paths))
  778. {
  779. // Break on the first found file, thus package files
  780. // are not overridden by default paths
  781. foreach ($config_component->_config_paths as $path)
  782. {
  783. // We test for both uppercase and lowercase, for servers that
  784. // are case-sensitive with regard to file names. Check for environment
  785. // first, global next
  786. if (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
  787. {
  788. include_once($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
  789. break;
  790. }
  791. elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
  792. {
  793. include_once($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
  794. break;
  795. }
  796. elseif (file_exists($path .'config/'.strtolower($class).'.php'))
  797. {
  798. include_once($path .'config/'.strtolower($class).'.php');
  799. break;
  800. }
  801. elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).'.php'))
  802. {
  803. include_once($path .'config/'.ucfirst(strtolower($class)).'.php');
  804. break;
  805. }
  806. }
  807. }
  808. }
  809. if ($prefix == '')
  810. {
  811. if (class_exists('CI_'.$class))
  812. {
  813. $name = 'CI_'.$class;
  814. }
  815. elseif (class_exists(config_item('subclass_prefix').$class))
  816. {
  817. $name = config_item('subclass_prefix').$class;
  818. }
  819. else
  820. {
  821. $name = $class;
  822. }
  823. }
  824. else
  825. {
  826. $name = $prefix.$class;
  827. }
  828. // Is the class name valid?
  829. if ( ! class_exists($name))
  830. {
  831. log_message('error', "Non-existent class: ".$name);
  832. show_error("Non-existent class: ".$class);
  833. }
  834. // Set the variable name we will assign the class to
  835. // Was a custom class name supplied? If so we'll use it
  836. $class = strtolower($class);
  837. if (is_null($object_name))
  838. {
  839. $classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class];
  840. }
  841. else
  842. {
  843. $classvar = $object_name;
  844. }
  845. // Save the class name and object name
  846. $this->_ci_classes[$class] = $classvar;
  847. // Instantiate the class
  848. $CI =& get_instance();
  849. if ($config !== NULL)
  850. {
  851. $CI->$classvar = new $name($config);
  852. }
  853. else
  854. {
  855. $CI->$classvar = new $name;
  856. }
  857. }
  858. // --------------------------------------------------------------------
  859. /**
  860. * Autoloader
  861. *
  862. * The config/autoload.php file contains an array that permits sub-systems,
  863. * libraries, and helpers to be loaded automatically.
  864. *
  865. * This function is public, as it's used in the CI_Controller class.
  866. * However, there is no reason you should ever needs to use it.
  867. *
  868. * @param array
  869. * @return void
  870. */
  871. public function ci_autoloader()
  872. {
  873. if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
  874. {
  875. include_once(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
  876. }
  877. else
  878. {
  879. include_once(APPPATH.'config/autoload.php');
  880. }
  881. if ( ! isset($autoload))
  882. {
  883. return FALSE;
  884. }
  885. // Autoload packages
  886. if (isset($autoload['packages']))
  887. {
  888. foreach ($autoload['packages'] as $package_path)
  889. {
  890. $this->add_package_path($package_path);
  891. }
  892. }
  893. // Load any custom config file
  894. if (count($autoload['config']) > 0)
  895. {
  896. $CI =& get_instance();
  897. foreach ($autoload['config'] as $key => $val)
  898. {
  899. $CI->config->load($val);
  900. }
  901. }
  902. // Autoload helpers and languages
  903. foreach (array('helper', 'language') as $type)
  904. {
  905. if (isset($autoload[$type]) AND count($autoload[$type]) > 0)
  906. {
  907. $this->$type($autoload[$type]);
  908. }
  909. }
  910. // A little tweak to remain backward compatible
  911. // The $autoload['core'] item was deprecated
  912. if ( ! isset($autoload['libraries']) AND isset($autoload['core']))
  913. {
  914. $autoload['libraries'] = $autoload['core'];
  915. }
  916. // Load libraries
  917. if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0)
  918. {
  919. // Load the database driver.
  920. if (in_array('database', $autoload['libraries']))
  921. {
  922. $this->database();
  923. $autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
  924. }
  925. // Load all other libraries
  926. foreach ($autoload['libraries'] as $item)
  927. {
  928. $this->library($item);
  929. }
  930. }
  931. // Autoload models
  932. if (isset($autoload['model']))
  933. {
  934. $this->model($autoload['model']);
  935. }
  936. }
  937. // --------------------------------------------------------------------
  938. /**
  939. * Object to Array
  940. *
  941. * Takes an object as input and converts the class variables to array key/vals
  942. *
  943. * @param object
  944. * @return array
  945. */
  946. protected function _ci_object_to_array($object)
  947. {
  948. return (is_object($object)) ? get_object_vars($object) : $object;
  949. }
  950. // --------------------------------------------------------------------
  951. /**
  952. * Get a reference to a specific library or model
  953. *
  954. * @return bool
  955. */
  956. protected function &_ci_get_component($component)
  957. {
  958. $CI =& get_instance();
  959. return $CI->$component;
  960. }
  961. // --------------------------------------------------------------------
  962. /**
  963. * Prep filename
  964. *
  965. * This function preps the name of various items to make loading them more reliable.
  966. *
  967. * @param mixed
  968. * @return array
  969. */
  970. protected function _ci_prep_filename($filename, $extension)
  971. {
  972. if ( ! is_array($filename))
  973. {
  974. return array(strtolower(str_replace('.php', '', str_replace($extension, '', $filename)).$extension));
  975. }
  976. else
  977. {
  978. foreach ($filename as $key => $val)
  979. {
  980. $filename[$key] = strtolower(str_replace('.php', '', str_replace($extension, '', $val)).$extension);
  981. }
  982. return $filename;
  983. }
  984. }
  985. }
  986. /* End of file Loader.php */
  987. /* Location: ./system/core/Loader.php */