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 // 根据配置(application/config/hooks.php)中的特定配置来调用函数 16 // ------------------------------------------------------------------------ 17 18 19 //调用 20 21 /* * 22 * CodeIgniter Hooks Class 23 * 24 * Provides a mechanism to extend the base system without hacking. 25 * 26 * @package CodeIgniter 27 * @subpackage Libraries 28 * @category Libraries 29 * @author ExpressionEngine Dev Team 30 * @link http://codeigniter.com/user_guide/libraries/encryption.html 31 */ 32 class CI_Hooks { 33 34 /* * 35 * Determines wether hooks are enabled 36 * 37 * @var bool 38 */ 39 var $enabled = FALSE; // 开启hook的标志,默认是关闭的。APPPATH/config/config.php中的配置也是默认关闭的,如果想使用hook,要在config.php中开启。 40 /* * 41 * List of all hooks set in config/hooks.php 42 * 43 * @var array 44 */ 45 var $hooks = array(); // //在_initialize()函数初始化的过程中将APPPATH/config/hook.php中定义的hook数组,引用到$this->hooks; 46 /* * 47 * Determines wether hook is in progress, used to prevent infinte loops 48 * 49 * @var bool 50 */ 51 var $in_progress = FALSE; // 当一个hook执行的时候,会给标记 $in_process = TRUE ,是为了防止同一个hook被同时调用。 52 53 /* * 54 * Constructor 55 * 56 */ 57 function __construct() 58 { 59 $this->_initialize(); 60 log_message('debug', "Hooks Class Initialized"); 61 } 62 63 // -------------------------------------------------------------------- 64 65 /* * 66 * Initialize the Hooks Preferences 67 * 68 * @access private 69 * @return void 70 */ 71 // 初始化hook 72 function _initialize() 73 { 74 $CFG =& load_class('Config', 'core'); // 获取配置文件 75 // If hooks are not enabled in the config file 76 // there is nothing else to do 77 //如果配置文件中设置了是不允许hooks,则直接返回退出本函数。 78 if ( $CFG->item('enable_hooks') == FALSE) // //判断config.php中是否开启hook 79 { 80 return; 81 } 82 83 // Grab the "hooks" definition file. 84 // If there are no hooks, we're done. 85 //要使用到的钩子,必须在配置目录下的hooks.php里面定义好。否则无法使用。 86 if ( defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks.php')) 87 { 88 include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'); 89 } 90 elseif ( is_file(APPPATH.'config/hooks.php')) 91 { 92 include(APPPATH.'config/hooks.php'); 93 } 94 95 96 if ( ! isset( $hook) OR ! is_array( $hook)) 97 { 98 return; 99 } 100 101 $this->hooks =& $hook; // include(hook.php),将文件里定义的hook数组引用到$this->hooks 102 $this->enabled = TRUE; 103 } 104 105 // -------------------------------------------------------------------- 106 107 /* * 108 * Call Hook 109 * 外部其实就是调用这个_call_hook函数进行调用钩子程序。而此方法中再调用_run_hook去执行相应的钩子 110 * Calls a particular hook 111 * 112 * @access private 113 * @param string the hook name 114 * @return mixed 115 */ 116 function _call_hook( $which = '') 117 { 118 if ( ! $this->enabled OR ! isset( $this->hooks[ $which])) // //以pre_system挂钩点为例,当调用_call_hook('pre_system')时 119 { 120 return FALSE; // //确保$this->enable = TRUE && 定义了$this->hooks['pre_system'] 121 } 122 // //如果是二维数组就遍历,依次_run_hook($this->hooks['pre_system'][$val]) 123 if ( isset( $this->hooks[ $which][0]) AND is_array( $this->hooks[ $which][0])) 124 { 125 foreach ( $this->hooks[ $which] as $val) 126 { 127 $this->_run_hook( $val); 128 } 129 } 130 else // 如果是一维数组,那么直接_run_hook($this->hooks['pre_system']) //同一个位置可以执行多个hook 131 { 132 $this->_run_hook( $this->hooks[ $which]); 133 } 134 135 return TRUE; 136 } 137 138 // -------------------------------------------------------------------- 139 140 /* * 141 * Run Hook 取得 hook.php中配置并组装成对应的类 函数 参数类执行 142 * 143 * Runs a particular hook 144 * 145 * @access private 146 * @param array the hook details 147 * @return bool 148 */ 149 function _run_hook( $data) 150 { 151 if ( ! is_array( $data)) // $data 是传递过来的hook数组 152 { 153 return FALSE; 154 } 155 // $data 就是我们在APPPATH/config/hook.php 定义的hook数组 156 //$hook['pre_controller'] = array( 157 // 'class' => 'MyClass', 158 // 'function' => 'Myfunction', 159 // 'filename' => 'Myclass.php', 160 // 'filepath' => 'hooks', 161 // 'params' => array('beer', 'wine', 'snacks') 162 // ); 163 164 // ----------------------------------- 165 // Safety - Prevents run-away loops 166 // ----------------------------------- 167 168 // If the script being called happens to have the same 169 // hook call within it a loop can happen 170 171 if ( $this->in_progress == TRUE) 172 { 173 return; 174 } 175 176 // ----------------------------------- 177 // Set file path 178 // ----------------------------------- 179 180 if ( ! isset( $data['filepath']) OR ! isset( $data['filename'])) 181 { 182 return FALSE; 183 } 184 185 $filepath = APPPATH. $data['filepath'].'/'. $data['filename']; 186 187 if ( ! file_exists( $filepath)) 188 { 189 return FALSE; 190 } 191 192 // ----------------------------------- 193 // Set class/function name 194 // ----------------------------------- 195 196 /* * 197 * 取出data里面的数据,加载 APPPATH.$data['filepath'].$data['filename']; 198 实例化钩子类,调用function。应用到示例中就是 199 $this->in_process = TRUE; 200 $Hook = new MyClass(); 201 $Hook->Myfunction($params); 202 $this->in_process = FALSE; 203 */ 204 205 $class = FALSE; 206 $function = FALSE; 207 $params = ''; 208 209 if ( isset( $data['class']) AND $data['class'] != '') 210 { 211 $class = $data['class']; 212 } 213 214 if ( isset( $data['function'])) 215 { 216 $function = $data['function']; 217 } 218 219 if ( isset( $data['params'])) 220 { 221 $params = $data['params']; 222 } 223 224 if ( $class === FALSE AND $function === FALSE) 225 { 226 return FALSE; 227 } 228 229 // ----------------------------------- 230 // Set the in_progress flag 231 // ----------------------------------- 232 233 $this->in_progress = TRUE; 234 235 // ----------------------------------- 236 // Call the requested class and/or function 237 // ----------------------------------- 238 239 if ( $class !== FALSE) 240 { 241 if ( ! class_exists( $class)) 242 { 243 require( $filepath); 244 } 245 246 $HOOK = new $class; 247 $HOOK-> $function( $params); 248 } 249 else 250 { 251 if ( ! function_exists( $function)) 252 { 253 require( $filepath); 254 } 255 256 $function( $params); 257 } 258 259 $this->in_progress = FALSE; 260 return TRUE; 261 } 262 263 } 264 265 // END CI_Hooks class 266 267 /* End of file Hooks.php */ 268 /* Location: ./system/core/Hooks.php */