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 }