source: branches/version-2_13-dev/data/class/helper/SC_Helper_Plugin.php @ 22808

Revision 22808, 11.9 KB checked in by Seasoft, 7 years ago (diff)

#2241 (プラグイン機構の自殺を阻止)

  • DB接続できない場合、DB接続エラーで落ちるのは仕方がないかなと思いこの対応。現状把握しているよりも早死する経路があると、この対応は不適切な懸念はある。インスタンスを生成しつつ、関連するDB接続のみ回避できると、ベターなのかも。

#2242 (プラグインが破損している場合に強行突破できる機会を与える)

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2/*
3 * This file is part of EC-CUBE
4 *
5 * Copyright(c) 2000-2013 LOCKON CO.,LTD. All Rights Reserved.
6 *
7 * http://www.lockon.co.jp/
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 */
23
24/**
25 * プラグインのヘルパークラス.
26 *
27 * @package Helper
28 * @version $Id$
29 */
30class SC_Helper_Plugin
31{
32    // プラグインのインスタンスの配列.
33    var $arrPluginInstances = array();
34    // プラグインのアクションの配列.
35    var $arrRegistedPluginActions = array();
36    // プラグインのIDの配列.
37    var $arrPluginIds = array();
38    // HeadNaviブロックの配列
39    var $arrHeadNaviBlocsByPlugin = array();
40
41    /**
42     * 有効なプラグインのロード. プラグインエンジンが有効になっていない場合は
43     * プラグインエンジン自身のインストール処理を起動する
44     *
45     * @return void
46     */
47    function load($plugin_activate_flg = true)
48    {
49
50        if (!defined('CONFIG_REALFILE') || !file_exists(CONFIG_REALFILE)) return; // インストール前
51        if (GC_Utils_Ex::isInstallFunction()) return; // インストール中
52        if ($plugin_activate_flg === false) return;
53        // 有効なプラグインを取得
54        $arrPluginDataList = SC_Plugin_Util_Ex::getEnablePlugin();
55        // pluginディレクトリを取得
56        $arrPluginDirectory = SC_Plugin_Util_Ex::getPluginDirectory();
57        foreach ($arrPluginDataList as $arrPluginData) {
58            // プラグイン本体ファイル名が取得したプラグインディレクトリ一覧にある事を確認
59            if (array_search($arrPluginData['plugin_code'], $arrPluginDirectory) !== false) {
60                $plugin_file_path = PLUGIN_UPLOAD_REALDIR . $arrPluginData['plugin_code'] . '/' . $arrPluginData['class_name'] . '.php';
61                // プラグイン本体ファイルが存在しない場合
62                if (!file_exists($plugin_file_path)) {
63                    // エラー出力
64                    $msg = 'プラグイン本体ファイルが存在しない。当該プラグインを無視して続行する。';
65                    $msg .= 'ファイル=' . var_export($plugin_file_path, true) . '; ';
66                    trigger_error($msg, E_USER_WARNING);
67                    // 次のプラグインへ続行
68                    continue 1;
69                }
70                // プラグイン本体ファイルをrequire.
71                require_once $plugin_file_path;
72
73                // プラグインのインスタンス生成.
74                $objPlugin = new $arrPluginData['class_name']($arrPluginData);
75                // メンバ変数にプラグインのインスタンスを登録.
76                $this->arrPluginInstances[$arrPluginData['plugin_id']] = $objPlugin;
77                $this->arrPluginIds[] = $arrPluginData['plugin_id'];
78                // ローカルフックポイントの登録.
79                $this->registerLocalHookPoint($objPlugin, $arrPluginData['priority']);
80                // スーパーフックポイントの登録.
81                $this->registerSuperHookPoint($objPlugin, HOOK_POINT_PREPROCESS, 'preProcess', $arrPluginData['priority']);
82                $this->registerSuperHookPoint($objPlugin, HOOK_POINT_PROCESS, 'process', $arrPluginData['priority']);
83            }
84        }
85    }
86
87    /**
88     * SC_Helper_Plugin オブジェクトを返す(Singletonパターン)
89     *
90     * @return object SC_Helper_Pluginオブジェクト
91     */
92    static function getSingletonInstance($plugin_activate_flg = true)
93    {
94        if (!isset($GLOBALS['_SC_Helper_Plugin_instance'])) {
95            $GLOBALS['_SC_Helper_Plugin_instance'] = new SC_Helper_Plugin_Ex();
96            $GLOBALS['_SC_Helper_Plugin_instance']->load($plugin_activate_flg);
97        }
98        return $GLOBALS['_SC_Helper_Plugin_instance'];
99    }
100
101    /**
102     * プラグイン実行
103     *
104     * @param string $hook_point フックポイント
105     * @param array  $arrArgs    コールバック関数へ渡す引数
106     * @return void
107     */
108    function doAction($hook_point, $arrArgs = array())
109    {
110        if (is_array($arrArgs) === false) {
111            array(&$arrArgs);
112        }
113
114        if ($hook_point == 'loadClassFileChange') {
115            $arrSaveArgs = $arrArgs;
116            $arrClassName = array();
117            $arrClassPath = array();
118        }
119
120        if (array_key_exists($hook_point, $this->arrRegistedPluginActions)
121            && is_array($this->arrRegistedPluginActions[$hook_point])) {
122
123            krsort($this->arrRegistedPluginActions[$hook_point]);
124            foreach ($this->arrRegistedPluginActions[$hook_point] as $arrFuncs) {
125
126                foreach ($arrFuncs as $func) {
127                    if (!is_null($func['function'])) {
128                        if ($hook_point == 'loadClassFileChange') {
129                            $classname = $arrSaveArgs[0];
130                            $classpath = $arrSaveArgs[1];
131                            $arrTempArgs = array(&$classname, &$classpath);
132
133                            call_user_func_array($func['function'], $arrTempArgs);
134
135                            if ($classname !== $arrSaveArgs[0]) {
136                                $arrClassName[] = $classname;
137                                $arrClassPath[] = $classpath;
138                            }
139                        } else {
140                            call_user_func_array($func['function'], $arrArgs);
141                        }
142                    }
143                }
144            }
145
146            if ($hook_point == 'loadClassFileChange') {
147                if (count($arrClassName) > 0) {
148                    $arrArgs[0] = $arrClassName;
149                    $arrArgs[1] = $arrClassPath;
150                }
151            }
152        }
153    }
154
155    /**
156     * スーパーフックポイントを登録します.
157     *
158     * @param Object $objPlugin プラグインのインスタンス
159     * @param string $hook_point スーパーフックポイント
160     * @param string $function_name 実行する関数名
161     * @param string $priority 実行順
162     */
163    function registerSuperHookPoint($objPlugin, $hook_point, $function_name, $priority)
164    {
165        // スーパープラグイン関数を定義しているかを検証.
166        if (method_exists($objPlugin, $function_name) === true) {
167            // アクションの登録
168            $this->addAction($hook_point, array($objPlugin, $function_name), $priority);
169        }
170    }
171
172    /**
173     * ローカルフックポイントを登録します.
174     *
175     * @param Object $objPlugin プラグインのインスタンス
176     * @param string $priority 実行順
177     */
178    function registerLocalHookPoint($objPlugin, $priority)
179    {
180        // ローカルプラグイン関数を定義しているかを検証.
181        if (method_exists($objPlugin, 'register') === true) {
182            // アクションの登録(プラグイン側に記述)
183            $objPluginHelper =& SC_Helper_Plugin::getSingletonInstance();
184            $objPlugin->register($objPluginHelper, $priority);
185        }
186    }
187
188    /**
189     * プラグイン コールバック関数を追加する
190     *
191     * @param string   $hook_point フックポイント名
192     * @param callback $function   コールバック関数名
193     * @param string   $priority   同一フックポイント内での実行優先度
194     * @return boolean 成功すればtrue
195     */
196    function addAction($hook_point, $function, $priority = 0)
197    {
198        if (!is_callable($function)) {
199            // TODO エラー処理; コール可能な形式ではありません
200        }
201        $idx = $this->makeActionUniqueId($hook_point, $function, $priority);
202        $this->arrRegistedPluginActions[$hook_point][$priority][$idx] = array('function' => $function);
203        return true;
204    }
205
206    /**
207     * コールバック関数を一意に識別するIDの生成
208     *
209     * @param string   $hook_point フックポイント名
210     * @param callback $function   コールバック関数名
211     * @param integer  $priority   同一フックポイント内での実行優先度
212     * @return string コールバック関数を一意に識別するID
213     */
214    function makeActionUniqueId($hook_point, $function, $priority)
215    {
216        static $filter_id_count = 0;
217
218        if (is_string($function)) {
219            return $function;
220        }
221
222        if (is_object($function)) {
223            $function = array($function, '');
224        } else {
225            $function = (array) $function;
226        }
227
228        if (is_object($function[0])) {
229            if (function_exists('spl_object_hash')) {
230                return spl_object_hash($function[0]) . $function[1];
231            } else {
232                $obj_idx = get_class($function[0]).$function[1];
233                if ( false === $priority)
234                    return false;
235                $obj_idx .= isset($this->arrRegistedPluginActions[$hook_point][$priority])
236                         ? count((array)$this->arrRegistedPluginActions[$hook_point][$priority])
237                         : $filter_id_count;
238                $function[0]->wp_filter_id = $filter_id_count;
239                ++$filter_id_count;
240
241                return $obj_idx;
242            }
243        } else if (is_string($function[0])) {
244            return $function[0].$function[1];
245        }
246    }
247
248    /**
249     * ブロックの配列から有効でないpluginのブロックを除外して返します.
250     *
251     * @param array $arrBlocs プラグインのインストールディレクトリ
252     * @return array $arrBlocsサイトルートからメディアディレクトリへの相対パス
253     */
254    function getEnableBlocs($arrBlocs)
255    {
256        foreach ($arrBlocs as $key => $value) {
257            // 有効なpluginのブロック以外.
258            if (!in_array($value['plugin_id'] , $this->arrPluginIds)) {
259                // 通常ブロック以外.
260                if ($value['plugin_id'] != '') {
261                    // ブロック配列から削除する
262                    unset ($arrBlocs[$key]);
263                }
264            }
265        }
266        return $arrBlocs;
267    }
268
269   /**
270     * テンプレートのヘッダに追加するPHPのURLをセットする
271     *
272     * @param string $url PHPファイルのURL
273     * @return void
274     */
275    function setHeadNavi($url)
276    {
277        $this->arrHeadNaviBlocsByPlugin[$url] = TARGET_ID_HEAD;
278    }
279
280    /**
281     * PHPのURLをテンプレートのヘッダに追加する
282     *
283     * @param array|null $arrBlocs  配置情報を含めたブロックの配列
284     * @return void
285     */
286    function setHeadNaviBlocs(&$arrBlocs)
287    {
288        foreach ($this->arrHeadNaviBlocsByPlugin as $key => $value) {
289            $arrBlocs[] = array(
290                'target_id' =>$value,
291                'php_path' => $key
292            );
293        }
294    }
295
296    /**
297     * Utility function to set a hook point.
298     *
299     * @param string    $hook_point  hook point
300     * @param array     $arrArgs     argument passing to callback function
301     * @param boolean   $plugin_activate_flg
302     * @return void
303     */
304    public static function hook($hook_point, $arrArgs = array(), $plugin_activate_flg = PLUGIN_ACTIVATE_FLAG)
305    {
306        $objPlugin = SC_Helper_Plugin::getSingletonInstance($plugin_activate_flg);
307        $objPlugin->doAction($hook_point, $arrArgs);
308    }
309}
Note: See TracBrowser for help on using the repository browser.