Ticket #132: Hook.class.php

File Hook.class.php, 5.3 KB (added by 1d1ot, 22 months ago)

ModuleHook? with regexp hooks

Line 
1<?php
2/*-------------------------------------------------------
3*
4*   LiveStreet Engine Social Networking
5*   Copyright © 2008 Mzhelskiy Maxim
6*
7*--------------------------------------------------------
8*
9*   Official site: www.livestreet.ru
10*   Contact e-mail: rus.engine@gmail.com
11*
12*   GNU General Public License, version 2:
13*   http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
14*
15---------------------------------------------------------
16*/
17/**
18 * Модуль поддержки хуков(hooks)
19 *
20 */
21class ModuleHook extends Module {               
22               
23        /**
24         * Содержит список хуков
25         *
26         * @var array( 'name' => array(
27         *              array(
28         *                      'type' => 'module' | 'hook' | 'function',
29         *                      'callback' => 'callback_name',
30         *                      'priority'      => 1,
31         *                      'params' => array()
32         *              ),
33         *      ),
34         * )
35         */
36        protected $aHooks = array();
37        protected $aPregNames = array();
38        protected $aHookPool = array();
39       
40        /**
41         * Инициализация модуля
42         *
43         */
44        public function Init() {       
45               
46        }
47       
48        public function Add($sName,$sType,$sCallBack,$iPriority=1,$aParams=array()) {
49                $bPreg = preg_match('#^([^\w\d]).*\1[A-Za-z]*$#', $sName);
50                $sName = $bPreg
51                        ? $sName
52                        : strtolower($sName)
53                ;
54                $sType = strtolower($sType);
55                if (!in_array($sType,array('module','hook','function'))) {
56                        return false;
57                }
58                $this->aHooks[$sName][]=array('type'=>$sType,'callback'=>$sCallBack,'params'=>$aParams,'priority'=>(int)$iPriority);
59                if($bPreg && !in_array($sName, $this->aPregNames)){
60                        $this->aPregNames[] = $sName;
61                }
62                return true;
63        }
64       
65        public function AddExecModule($sName,$sCallBack,$iPriority=1) {
66                return $this->Add($sName,'module',$sCallBack,$iPriority);
67        }
68       
69        public function AddExecFunction($sName,$sCallBack,$iPriority=1) {
70                return $this->Add($sName,'function',$sCallBack,$iPriority);
71        }
72       
73        public function AddExecHook($sName,$sCallBack,$iPriority=1,$aParams=array()) {
74                return $this->Add($sName,'hook',$sCallBack,$iPriority,$aParams);
75        }
76       
77        public function AddDelegateModule($sName,$sCallBack,$iPriority=1) {
78                return $this->Add($sName,'module',$sCallBack,$iPriority,array('delegate'=>true));
79        }
80       
81        public function AddDelegateFunction($sName,$sCallBack,$iPriority=1) {
82                return $this->Add($sName,'function',$sCallBack,$iPriority,array('delegate'=>true));
83        }
84       
85        public function AddDelegateHook($sName,$sCallBack,$iPriority=1,$aParams=array()) {
86                $aParams['delegate']=true;
87                return $this->Add($sName,'hook',$sCallBack,$iPriority,$aParams);
88        }
89       
90        public function Run($sName,&$aVars=array()) {
91                $result=array();
92                $sName=strtolower($sName);
93                dump(__METHOD__.": $sName");
94                $bTemplateHook=strpos($sName,'template_')===0 ? true : false;
95               
96                $aSelectedHooks = array();
97                if (isset($this->aHooks[$sName])) {
98                        $aSelectedHooks = $this->aHooks[$sName];
99                }
100                foreach($this->aPregNames as $sPregName){
101                        if($sName != $sPregName && preg_match($sPregName, $sName)){
102                                $aSelectedHooks = array_merge($aSelectedHooks, $this->aHooks[$sPregName]);
103                        }
104                }
105               
106                if ($aSelectedHooks) {
107                        $aVars['__hook_name'] = $sName;
108                        $aHookNum=array();
109                        $aHookNumDelegate=array();
110                        /**
111                         * Все хуки делим на обычные(exec) и делигирующие(delegate)
112                         */
113                        for ($i=0;$i<count($aSelectedHooks);$i++) {                             
114                                if (isset($aSelectedHooks[$i]['params']['delegate']) and $aSelectedHooks[$i]['params']['delegate']) {
115                                        $aHookNumDelegate[$i]=$aSelectedHooks[$i]['priority'];
116                                } else {
117                                        $aHookNum[$i]=$aSelectedHooks[$i]['priority'];
118                                }                               
119                        }                       
120                        arsort($aHookNum,SORT_NUMERIC);
121                        arsort($aHookNumDelegate,SORT_NUMERIC);
122                        /**
123                         * Сначала запускаем на выполнение простые
124                         */
125                        foreach ($aHookNum as $iKey => $iPr) {
126                                $aHook=$aSelectedHooks[$iKey];
127                                if ($bTemplateHook) {
128                                        /**
129                                         * Если это шаблонных хук то сохраняем результат
130                                         */
131                                        $result['template_result'][]=$this->RunType($aHook,$aVars);
132                                } else {
133                                        $this->RunType($aHook,$aVars);
134                                }
135                        }
136                        /**
137                         * Теперь запускаем делигирующие
138                         * Делегирующий хук должен вернуть результат в формате:
139                         *
140                         */
141                        foreach ($aHookNumDelegate as $iKey => $iPr) {
142                                $aHook=$aSelectedHooks[$iKey];                         
143                                $result=array(
144                                        'delegate_result'=>$this->RunType($aHook,$aVars)
145                                );
146                                /**
147                                 * На данный момент только один хук может быть делегирующим
148                                 */
149                                break;
150                        }
151                }
152                return $result;
153        }
154       
155        protected function RunType($aHook,&$aVars) {
156                $result=null;
157                $sHookName = isset($aVars['__hook_name']) ? $aVars['__hook_name'] : null;
158                unset($aVars['__hook_name']);
159                switch ($aHook['type']) {
160                        case 'module':
161                                $result=call_user_func_array(array($this,$aHook['callback']),array(&$aVars));
162                                break;
163                        case 'function':
164                                $result=call_user_func_array($aHook['callback'],array(&$aVars));
165                                break;
166                        case 'hook':
167                                if (isset($aHook['params']['sClassName']) and class_exists($aHook['params']['sClassName'])) {
168                                        $sHookClass = $aHook['params']['sClassName'];
169                                        $oHook = isset($this->aHookPool[$sHookClass])
170                                                ? $this->aHookPool[$sHookClass]
171                                                : ($this->aHookPool[$sHookClass] = new $sHookClass)
172                                        ;
173                                        $oHook->sHookName = $sHookName;
174                                        $result=call_user_func_array(array($oHook,$aHook['callback']),array(&$aVars));
175                                }
176                                break;
177                        default:
178                                break;
179                }
180                return $result;
181        }
182}
183?>