1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 2 // ------------------------------------------------------------------------ 3 4 /** 5 * CodeIgniter Hooks Class 6 */ 7 class CI_Hooks { 8 9 /** 10 * Determines wether hooks are enabled 11 */ 12 var $enabled = FALSE; 13 14 15 /** 16 * List of all hooks set in config/hooks.php 17 */ 18 var $hooks = array(); 19 20 21 /** 22 * Determines wether hook is in progress, used to prevent infinte loops 23 */ 24 var $in_progress = FALSE; 25 26 /** 27 * Constructor 28 */ 29 function __construct() 30 { 31 $this->_initialize(); 32 log_message('debug', "Hooks Class Initialized"); 33 } 34 35 // -------------------------------------------------------------------- 36 37 /** 38 * Initialize the Hooks Preferences 39 */ 40 function _initialize() 41 { 42 $CFG =& load_class('Config', 'core'); 43 44 45 //如果配置文件中设置了是不允许hooks,则直接返回退出本函数。 46 if ($CFG->item('enable_hooks') == FALSE) 47 { 48 return; 49 } 50 51 //要使用到的钩子,必须在配置目录下的hooks.php里面定义好。否则无法使用。 52 if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks.php')) 53 { 54 include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'); 55 } 56 elseif (is_file(APPPATH.'config/hooks.php')) 57 { 58 include(APPPATH.'config/hooks.php'); 59 } 60 61 62 if ( ! isset($hook) OR ! is_array($hook)) 63 { 64 return; 65 } 66 67 //把钩子信息都保存到Hook组件中。 68 $this->hooks =& $hook; 69 $this->enabled = TRUE; 70 } 71 72 // -------------------------------------------------------------------- 73 74 /** 75 * Call Hook 76 * 外部其实就是调用这个_call_hook函数进行调用钩子程序。而此方法中再调用_run_hook去执行相应的钩子。 77 */ 78 function _call_hook($which = '') 79 { 80 if ( ! $this->enabled OR ! isset($this->hooks[$which])) 81 { 82 return FALSE; 83 } 84 85 //同一个位置可以执行多个hook 86 if (isset($this->hooks[$which][0]) AND is_array($this->hooks[$which][0])) 87 { 88 foreach ($this->hooks[$which] as $val) 89 { 90 $this->_run_hook($val); 91 } 92 } 93 else 94 { 95 $this->_run_hook($this->hooks[$which]); 96 } 97 98 return TRUE; 99 } 100 101 // -------------------------------------------------------------------- 102 103 /** 104 * Run Hook 105 */ 106 function _run_hook($data) 107 { 108 //一般来说,这个$data会有:类名,方法名,参数,类文件路径等参数。 109 if ( ! is_array($data)) 110 { 111 return FALSE; 112 } 113 114 // ----------------------------------- 115 // Safety - Prevents run-away loops 116 // ----------------------------------- 117 118 119 //如果调用某一个hook,执行某些脚本,而有可能这些脚本里面再会触发其它hook,如果这个其它hook里面又包含了当前 120 //的hook,那么就会进入死循环,这个in_progress的存在就是阻止这种情况。 121 if ($this->in_progress == TRUE) 122 { 123 return; 124 } 125 126 //下面都是一些执行钩子的预处理,包括判断类文件是否存在,类和方法是否正确等等。 127 // ----------------------------------- 128 // Set file path 129 // ----------------------------------- 130 131 if ( ! isset($data['filepath']) OR ! isset($data['filename'])) 132 { 133 return FALSE; 134 } 135 136 $filepath = APPPATH.$data['filepath'].'/'.$data['filename']; 137 138 if ( ! file_exists($filepath)) 139 { 140 return FALSE; 141 } 142 143 // ----------------------------------- 144 // Set class/function name 145 // ----------------------------------- 146 147 $class = FALSE; 148 $function = FALSE; 149 $params = ''; 150 151 if (isset($data['class']) AND $data['class'] != '') 152 { 153 $class = $data['class']; 154 } 155 156 if (isset($data['function'])) 157 { 158 $function = $data['function']; 159 } 160 161 if (isset($data['params'])) 162 { 163 $params = $data['params']; 164 } 165 166 if ($class === FALSE AND $function === FALSE) 167 { 168 return FALSE; 169 } 170 171 // ----------------------------------- 172 // Set the in_progress flag 173 // ----------------------------------- 174 175 //在开始执行钩子相应的程序之前,先把当前hook的状态设为正在运行中。 176 $this->in_progress = TRUE; 177 178 // ----------------------------------- 179 // Call the requested class and/or function 180 // ----------------------------------- 181 182 //执行 183 if ($class !== FALSE) 184 { 185 if ( ! class_exists($class)) 186 { 187 require($filepath); 188 } 189 190 $HOOK = new $class; 191 $HOOK->$function($params); 192 } 193 else 194 { 195 if ( ! function_exists($function)) 196 { 197 require($filepath); 198 } 199 200 $function($params); 201 } 202 203 //执行相应程序完毕后,重新把当前hook的状态改为非运行中,以让它可以再次被触发。 204 $this->in_progress = FALSE; 205 return TRUE; 206 } 207 208 }