source: branches/version-2_12-dev/data/class/pages/admin/ownersstore/LC_Page_Admin_OwnersStore.php @ 22034

Revision 22034, 42.5 KB checked in by h_yoshimoto, 9 years ago (diff)

refs #1944 プラグイン管理のリファクタリング

  • 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-2012 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// {{{ requires
25require_once CLASS_EX_REALDIR . 'page_extends/admin/LC_Page_Admin_Ex.php';
26
27/**
28 * オーナーズストア:プラグイン管理 のページクラス.
29 *
30 * @package Page
31 * @author LOCKON CO.,LTD.
32 * @version $Id$
33 */
34class LC_Page_Admin_OwnersStore extends LC_Page_Admin_Ex {
35
36    // }}}
37    // {{{ functions
38
39    /**
40     * Page を初期化する.
41     *
42     * @return void
43     */
44    function init() {
45        parent::init();
46        $this->tpl_mainpage = 'ownersstore/plugin.tpl';
47        $this->tpl_subno    = 'index';
48        $this->tpl_mainno   = 'ownersstore';
49        $this->tpl_maintitle = 'オーナーズストア';
50        $this->tpl_subtitle = 'プラグイン管理';
51    }
52
53    /**
54     * Page のプロセス.
55     *
56     * @return void
57     */
58    function process() {
59        $this->action();
60        $this->sendResponse();
61    }
62
63    /**
64     * Page のアクション.
65     *
66     * @return void
67     */
68    function action() {
69        // パラメーター管理クラス
70        $objFormParam = new SC_FormParam_Ex();
71        $mode = $this->getMode();
72        // パラメーター情報の初期化
73        $this->initParam($objFormParam, $mode);
74        $objFormParam->setParam($_POST);
75
76        $mode = $this->getMode();
77
78        switch ($mode) {
79            // インストール
80            case 'install':
81                $file_key = 'plugin_file';
82                $this->arrErr = $this->checkUploadFile($file_key);
83                if ($this->isError($this->arrErr) === false) {
84                    $archive_file_name = $_FILES[$file_key]['name'];
85                    // インストール処理.
86                    $this->arrErr = $this->installPlugin($archive_file_name, 'plugin_file');
87                    if ($this->isError($this->arrErr) === false) {
88                        // コンパイルファイルのクリア処理
89                        SC_Utils_Ex::clearCompliedTemplate();
90                        $this->tpl_onload = "alert('プラグインをインストールしました。');";
91                    }
92                }
93                break;
94            // 削除
95            case 'uninstall':
96                // エラーチェック
97                $this->arrErr = $objFormParam->checkError();
98                if ($this->isError($this->arrErr) === false) {
99                    $plugin_id = $objFormParam->getValue('plugin_id');
100                    $plugin = SC_Plugin_Util_Ex::getPluginByPluginId($plugin_id);
101                    $this->arrErr = $this->uninstallPlugin($plugin);
102                    if ($this->isError($this->arrErr) === false) {
103                        // TODO 全プラグインのインスタンスを保持したまま後続処理が実行されるので、全てのインスタンスを解放する。
104                        unset($GLOBALS['_SC_Helper_Plugin_instance']);
105                        // コンパイルファイルのクリア処理
106                        SC_Utils_Ex::clearCompliedTemplate();
107                        $this->tpl_onload = "alert('" . $plugin['plugin_name'] ."を削除しました。');";
108                    }
109                }
110                break;
111            // 有効化
112            case 'enable':
113                // エラーチェック
114                $this->arrErr = $objFormParam->checkError();
115                if ($this->isError($this->arrErr) === false) {
116                    $plugin_id = $objFormParam->getValue('plugin_id');
117                    // プラグイン取得.
118                    $plugin = SC_Plugin_Util_Ex::getPluginByPluginId($plugin_id);
119                    $this->arrErr = $this->enablePlugin($plugin);
120                    if ($this->isError($this->arrErr) === false) {
121                        // TODO 全プラグインのインスタンスを保持したまま後続処理が実行されるので、全てのインスタンスを解放する。
122                        unset($GLOBALS['_SC_Helper_Plugin_instance']);
123                        // コンパイルファイルのクリア処理
124                        SC_Utils_Ex::clearCompliedTemplate();
125                        $this->tpl_onload = "alert('" . $plugin['plugin_name'] . "を有効にしました。');";
126                    }
127                }
128                break;
129            // 無効化
130            case 'disable':
131                // エラーチェック
132                $this->arrErr = $objFormParam->checkError();
133                if ($this->isError($this->arrErr) === false) {
134                    $plugin_id = $objFormParam->getValue('plugin_id');
135                    // プラグイン取得.
136                    $plugin = SC_Plugin_Util_Ex::getPluginByPluginId($plugin_id);
137                    $this->arrErr = $this->disablePlugin($plugin);
138                    if ($this->isError($this->arrErr) === false) {
139                        // TODO 全プラグインのインスタンスを保持したまま後続処理が実行されるので、全てのインスタンスを解放する。
140                        unset($GLOBALS['_SC_Helper_Plugin_instance']);
141                        // コンパイルファイルのクリア処理
142                        SC_Utils_Ex::clearCompliedTemplate();
143                        $this->tpl_onload = "alert('" . $plugin['plugin_name'] . "を無効にしました。');";
144                    }
145                }
146                break;
147            // アップデート.
148            case 'update':
149                // エラーチェック
150                $this->arrErr = $objFormParam->checkError();
151                if ($this->isError($this->arrErr) === false) {
152                    $target_plugin_code = $objFormParam->getValue('plugin_code'); // アップデート対象のプラグインコード
153                    $this->arrErr = $this->checkUploadFile($target_plugin_code);
154
155                    if ($this->isError($this->arrErr) === false) {
156                        $update_plugin_file = $_FILES[$target_plugin_code];
157                        $update_plugin_file_name = $update_plugin_file['name']; // アップデートファイルのファイル名.
158                        // インストール処理.
159                        $target_plugin = SC_Plugin_Util_Ex::getPluginByPluginCode($target_plugin_code);
160                        $this->arrErr = $this->updatePlugin($target_plugin, $update_plugin_file_name, $target_plugin_code);
161                        if ($this->isError($this->arrErr) === false) {
162                            // コンパイルファイルのクリア処理
163                            SC_Utils_Ex::clearCompliedTemplate();
164                            $this->tpl_onload = "alert('プラグインをアップデートしました。');";
165                        }
166                    }
167                }
168                break;
169            // 優先度.
170            case 'priority':
171                // エラーチェック
172                $arrErr = $objFormParam->checkError();
173                $plugin_id = $objFormParam->getValue('plugin_id');
174                if ($this->isError($arrErr) === false) {
175                    // 優先度の更新
176                    $priority = $objFormParam->getValue('priority');
177                    $this->updatePriority($plugin_id, $priority);
178                    // コンパイルファイルのクリア処理
179                    SC_Utils_Ex::clearCompliedTemplate();
180                } else {
181                    // エラーメッセージを詰め直す.
182                    $this->arrErr['priority'][$plugin_id] = $arrErr['priority'];
183                }
184
185                break;
186            default:
187                break;
188        }
189        // DBからプラグイン情報を取得
190        $plugins = SC_Plugin_Util_Ex::getAllPlugin();
191
192        foreach ($plugins as $key => $plugin) {
193            // ロゴファイルへのパスを生成(ロゴが無い場合はNO_IMAGEを表示)
194            if (file_exists(PLUGIN_HTML_REALDIR . $plugins[$key]['plugin_code'] . '/logo.png') === true){
195                $plugins[$key]['logo'] = ROOT_URLPATH . 'plugin/' . $plugins[$key]['plugin_code'] . '/logo.png';
196            } else {
197                $plugins[$key]['logo'] = IMAGE_SAVE_URLPATH . 'noimage_plugin_list.gif';
198            }
199
200            // 設定ファイルがあるかを判定.
201            $plugins[$key]['config_flg'] = $this->isContainsFile(PLUGIN_UPLOAD_REALDIR . $plugin['plugin_code'], 'config.php');
202            if ($plugins[$key]['enable'] === PLUGIN_ENABLE_TRUE) {
203                // 競合するプラグインがあるかを判定.
204                $plugins[$key]['conflict_message']= $this->checkConflictPlugin($plugin['plugin_id']);
205            }
206        }
207        $this->plugins = $plugins;
208    }
209
210    /**
211     * デストラクタ.
212     *
213     * @return void
214     */
215    function destroy() {
216        parent::destroy();
217    }
218
219    /**
220     * パラメーター初期化.
221     *
222     * @param SC_FormParam_Ex $objFormParam
223     * @param string $mode モード
224     * @return void
225     */
226    function initParam(&$objFormParam, $mode) {
227        $objFormParam->addParam('mode', 'mode', INT_LEN, '', array('ALPHA_CHECK', 'MAX_LENGTH_CHECK'));
228        $objFormParam->addParam('plugin_id', 'plugin_id', INT_LEN, '', array('NUM_CHECK', 'MAX_LENGTH_CHECK'));
229        $objFormParam->addParam('plugin_code', 'plugin_code', MTEXT_LEN, '', array('ALNUM_CHECK', 'MAX_LENGTH_CHECK'));
230        if ($mode === 'priority') {
231            $objFormParam->addParam('優先度', 'priority', INT_LEN, '', array('EXIST_CHECK', 'NUM_CHECK', 'MAX_LENGTH_CHECK'));
232        }
233    }
234
235    /**
236     * ファイルパラメーター初期化.
237     *
238     * @param SC_UploadFile_Ex $objUpFile SC_UploadFileのインスタンス.
239     * @param string $key 登録するキー.
240     * @return void
241     */
242    function initUploadFile(&$objUpFile, $key) {
243        $objUpFile->addFile('プラグインファイル', $key, explode(',', PLUGIN_EXTENSION), FILE_SIZE, true, 0, 0, false);
244    }
245
246    /**
247     * ファイルが指定されている事をチェックします.
248     *
249     * @param string $file ファイル
250     * @param string $file_key ファイルキー
251     * @return array エラー情報を格納した連想配列.
252     */
253    function checkUploadFile($file_key) {
254        $objErr = new SC_CheckError_Ex();
255        // 拡張子チェック
256        $objErr->doFunc(array('プラグインファイル', $file_key, explode(',', PLUGIN_EXTENSION)), array('FILE_EXT_CHECK'));
257        // ファイルサイズチェック
258        $objErr->doFunc(array('プラグインファイル', $file_key, FILE_SIZE), array('FILE_SIZE_CHECK'));
259        // ファイル名チェック
260        $objErr->doFunc(array('プラグインファイル', $file_key), array('FILE_NAME_CHECK'));
261
262        return $objErr->arrErr;
263    }
264
265    /**
266     * 既にインストールされているプラグインかを判定します.
267     *
268     * @param string $plugin_code プラグインコード
269     * @return boolean インストール済の場合true インストールされていない場合false
270     */
271    function isInstalledPlugin($plugin_code) {
272        $plugin = SC_Plugin_Util_Ex::getPluginByPluginCode($plugin_code);
273        if (!empty($plugin)) {
274            return true;
275        }
276        return false;
277    }
278
279    /**
280     * ファイル名からプラグインコードを取得する.
281     *
282     * ファイル名を「.」で配列に分解.
283     * 配列内から拡張子として格納される可能性のある「tar」「gz」を除外すし、再度結合する.
284     *
285     * @param string $file_name ファイル名
286     * @return string $plugin_code プラグインコード.
287     */
288    function getPluginCode($file_name) {
289        // 分解
290        $array_ext = explode('.', $file_name);
291        $array_file_name = array_diff($array_ext, array('tar','gz'));
292        // 結合
293        $plugin_code = implode('.', $array_file_name);
294        return $plugin_code;
295    }
296
297    /**
298     * プラグイン保存ディレクトリのパスを取得する.
299     *
300     * @param string $plugin_code プラグインコード
301     * @return string $plugin_dir_path プラグイン保存ディレクトリのパス.
302     */
303    function getPluginDir($plugin_code) {
304        $plugin_dir_path = PLUGIN_UPLOAD_REALDIR . $plugin_code . '/';
305        return $plugin_dir_path;
306    }
307
308    /**
309     * プラグインHTMLディレクトリのパスを取得する.
310     *
311     * @param string $plugin_code プラグインコード
312     * @return string $plugin_dir_path プラグイン保存ディレクトリのパス.
313     */
314    function getHtmlPluginDir($plugin_code) {
315        $plugin_html_dir_path = PLUGIN_HTML_REALDIR . $plugin_code . '/';
316        return $plugin_html_dir_path;
317    }
318
319    /**
320     * プラグインファイルのパスを取得する.
321     *
322     * @param string $plugin_code プラグインコード
323     * @param string $plugin_class プラグインクラス名
324     * @return string $plugin_file_path クラスファイルのパス.
325     */
326    function getPluginFilePath($plugin_code , $plugin_class) {
327        $plugin_file_path = $this->getPluginDir($plugin_code) . $plugin_class . '.php';
328        return $plugin_file_path;
329    }
330
331    /**
332     * プラグインをインストールします.
333     *
334     * @param string $archive_file_name アーカイブファイル名.
335     * @param string $key キー.
336     * @return array エラー情報を格納した連想配列.
337     */
338    function installPlugin($archive_file_name, $key) {
339        // 一時展開ディレクトリにファイルがある場合は事前に削除.
340        $arrFileHash = SC_Helper_FileManager_Ex::sfGetFileList(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR);
341        if(count($arrFileHash) > 0) {
342            SC_Helper_FileManager_Ex::deleteFile(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR, false);
343        }
344       
345        //シンタックスエラーがあるtar.gzをアップ後、削除するとたまにディレクトリが消えるので追加
346        $this->makeDir(PLUGIN_UPLOAD_REALDIR);
347
348        $arrErr = array();
349        // 必須拡張モジュールのチェック
350        $arrErr = SC_Plugin_Util_Ex::checkExtension($key);
351        if ($this->isError($arrErr) === true) {
352            return $arrErr;
353        }
354        // ファイルをチェックし一時展開用ディレクトリに展開します.
355        $arrErr = $this->unpackPluginFile($archive_file_name, DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR, $key);
356        if ($this->isError($arrErr) === true) {
357            return $arrErr;
358        }
359        // plugin_infoを読み込み.
360        $arrErr = $this->requirePluginFile(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR . 'plugin_info.php', $key);
361        if ($this->isError($arrErr) === true) {
362            $this->rollBack(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR);
363            return $arrErr;
364        }
365
366        // リフレクションオブジェクトを生成.
367        $objReflection = new ReflectionClass('plugin_info');
368        $arrPluginInfo = $this->getPluginInfo($objReflection);
369        // プラグインクラスに必須となるパラメータが正常に定義されているかチェックします.
370        $arrErr = $this->checkPluginConstants($objReflection, DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR);
371        if ($this->isError($arrErr) === true) {
372            $this->rollBack(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR);
373            return $arrErr;
374        }
375
376        // 既にインストールされていないかを判定.
377        if ($this->isInstalledPlugin($arrPluginInfo['PLUGIN_CODE']) === true) {
378            $this->rollBack(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR);
379            $arrErr['plugin_file'] = '※ ' . $arrPluginInfo['PLUGIN_NAME'] . 'は既にインストールされています。<br/>';
380            return $arrErr;
381        }
382
383        // プラグイン情報をDB登録
384        if ($this->registerData($arrPluginInfo) === false) {
385            $this->rollBack(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR);
386            $arrErr['plugin_file'] = '※ DB登録に失敗しました。<br/>';
387            return $arrErr;
388        }
389
390        // プラグイン保存ディレクトリを作成し、一時展開用ディレクトリから移動します.
391        $plugin_dir_path = $this->getPluginDir($arrPluginInfo['PLUGIN_CODE']);
392        $this->makeDir($plugin_dir_path);
393        SC_Utils_Ex::copyDirectory(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR, $plugin_dir_path);
394
395        // プラグイン情報を取得
396        $plugin = SC_Plugin_Util_Ex::getPluginByPluginCode($arrPluginInfo['PLUGIN_CODE']);
397
398        // クラスファイルを読み込み.
399        $plugin_class_file_path = $this->getPluginFilePath($plugin['plugin_code'], $plugin['class_name']);
400        $arrErr = $this->requirePluginFile($plugin_class_file_path, $key);
401        if ($this->isError($arrErr) === true) {
402            $this->rollBack(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR, $plugin['plugin_id']);
403            return $arrErr;
404        }
405        // プラグインhtmlディレクトリ作成
406        $plugin_html_dir_path = $this->getHtmlPluginDir($plugin['plugin_code']);
407        $this->makeDir($plugin_html_dir_path);
408
409        $arrErr = $this->execPlugin($plugin, $plugin['class_name'], 'install');
410        if ($this->isError($arrErr) === true) {
411            $this->rollBack(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR, $plugin['plugin_id'], $plugin_html_dir_path);
412            return $arrErr;
413        }
414
415        // 不要なファイルの削除
416        SC_Helper_FileManager_Ex::deleteFile(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR, false);
417        return $arrErr;
418    }
419
420    /**
421     * ロールバック処理
422     * インストール失敗時などに不要な一時ファイルを削除します.
423     *
424     * @param string $temp_dir インストール・アップデート時の一時展開用ディレクトリのパス.
425     * @param string $plugin_id プラグインID.
426     * @param string $plugin_html_dir_path プラグイン毎に生成されるhtmlディレクトリのパス.
427     */
428    function rollBack($temp_dir, $plugin_id = '', $plugin_html_dir_path ='') {
429        // 一時ディレクトリを削除.
430        SC_Helper_FileManager_Ex::deleteFile($temp_dir, false);
431        // DBからプラグイン情報を削除
432        if (empty($plugin_id) === false) {
433            SC_Plugin_Util_Ex::deletePluginByPluginId($plugin_id);
434        }
435        // htmlディレクトリを削除
436        if (empty($plugin_html_dir_path) === false) {
437            SC_Helper_FileManager_Ex::deleteFile($plugin_html_dir_path, true);
438        }
439    }
440
441    /**
442     * プラグイン情報を取得します.
443     *
444     * @param ReflectionClass $objReflection
445     * @return array プラグイン情報の配列
446     */
447    function getPluginInfo(ReflectionClass $objReflection) {
448        $arrStaticProps = $objReflection->getStaticProperties();
449        $arrConstants   = $objReflection->getConstants();
450
451        $arrPluginInfoKey = array(
452            'PLUGIN_CODE',
453            'PLUGIN_NAME',
454            'CLASS_NAME',
455            'PLUGIN_VERSION',
456            'COMPLIANT_VERSION',
457            'AUTHOR',
458            'DESCRIPTION',
459            'PLUGIN_SITE_URL',
460            'AUTHOR_SITE_URL',
461            'HOOK_POINTS',
462        );
463        $arrPluginInfo = array();
464        foreach ($arrPluginInfoKey as $key) {
465            // クラス変数での定義を優先
466            if (isset($arrStaticProps[$key])) {
467                $arrPluginInfo[$key] = $arrStaticProps[$key];
468            // クラス変数定義がなければ, クラス定数での定義を読み込み.
469            } elseif ($arrConstants[$key]) {
470                $arrPluginInfo[$key] = $arrConstants[$key];
471            } else {
472                $arrPluginInfo[$key] = null;
473            }
474        }
475        return $arrPluginInfo;
476    }
477
478    /**
479     * プラグインクラス内の定数をチェックします.
480     *
481     * @param ReflectionClass $objReflection リフレクションオブジェクト
482     * @param string $dir_path チェックするプラグインディレクトリ
483     * @return array エラー情報を格納した連想配列.
484     */
485    function checkPluginConstants(ReflectionClass $objReflection, $dir_path) {
486        $arrErr = array();
487        // プラグイン情報を取得
488        $arrPluginInfo = $this->getPluginInfo($objReflection);
489
490        if (!isset($arrPluginInfo['PLUGIN_CODE'])) {
491            $arrErr['plugin_file'] = '※ PLUGIN_CODEが定義されていません。<br/>';
492            return $arrErr;
493        }
494        if (!isset($arrPluginInfo['PLUGIN_NAME'])) {
495            $arrErr['plugin_file'] = '※ PLUGIN_NAMEが定義されていません。<br/>';
496            return $arrErr;
497        }
498        if (!isset($arrPluginInfo['CLASS_NAME'])) {
499            $arrErr['plugin_file'] = '※ CLASS_NAMEが定義されていません。<br/>';
500            return $arrErr;
501        }
502        $plugin_class_file_path = $dir_path . $arrPluginInfo['CLASS_NAME'] . '.php';
503        if (file_exists($plugin_class_file_path) === false) {
504            $arrErr['plugin_file'] = '※ CLASS_NAMEが正しく定義されていません。<br/>';
505            return $arrErr;
506        }
507        if (!isset($arrPluginInfo['PLUGIN_VERSION'])) {
508            $arrErr['plugin_file'] = '※ PLUGIN_VERSIONが定義されていません。<br/>';
509            return $arrErr;
510        }
511        if (!isset($arrPluginInfo['COMPLIANT_VERSION'])) {
512            $arrErr['plugin_file'] = '※ COMPLIANT_VERSIONが定義されていません。<br/>';
513            return $arrErr;
514        }
515        if (!isset($arrPluginInfo['AUTHOR'])) {
516            $arrErr['plugin_file'] = '※ AUTHORが定義されていません。<br/>';
517            return $arrErr;
518        }
519        if (!isset($arrPluginInfo['DESCRIPTION'])) {
520            $arrErr['plugin_file'] = '※ DESCRIPTIONが定義されていません。<br/>';
521            return $arrErr;
522        }
523        $objErr = new SC_CheckError_Ex($arrPluginInfo);
524        $objErr->doFunc(array('PLUGIN_CODE', 'PLUGIN_CODE', STEXT_LEN), array('MAX_LENGTH_CHECK','GRAPH_CHECK'));
525        $objErr->doFunc(array('PLUGIN_NAME', 'PLUGIN_NAME', STEXT_LEN), array('MAX_LENGTH_CHECK'));
526        $objErr->doFunc(array('CLASS_NAME', 'CLASS_NAME', STEXT_LEN), array('MAX_LENGTH_CHECK','GRAPH_CHECK'));
527        $objErr->doFunc(array('PLUGIN_VERSION', 'PLUGIN_VERSION', STEXT_LEN), array('MAX_LENGTH_CHECK'));
528        $objErr->doFunc(array('COMPLIANT_VERSION', 'COMPLIANT_VERSION', STEXT_LEN), array('MAX_LENGTH_CHECK'));
529        $objErr->doFunc(array('AUTHOR', 'AUTHOR', STEXT_LEN), array('MAX_LENGTH_CHECK'));
530        $objErr->doFunc(array('DESCRIPTION', 'DESCRIPTION', MTEXT_LEN), array('MAX_LENGTH_CHECK'));
531        if (isset($arrPluginInfo['PLUGIN_SITE_URL'])) {
532            $objErr->doFunc(array('PLUGIN_SITE_URL', 'PLUGIN_SITE_URL', URL_LEN), array('MAX_LENGTH_CHECK','GRAPH_CHECK'));
533        }
534        if (isset($arrPluginInfo['AUTHOR_SITE_URL'])) {
535            $objErr->doFunc(array('AUTHOR_SITE_URL', 'AUTHOR_SITE_URL', URL_LEN), array('MAX_LENGTH_CHECK','GRAPH_CHECK'));
536        }
537        // エラー内容を出力用の配列にセットします.
538        if ($this->isError($objErr->arrErr)) {
539            $arrErr['plugin_file'] = '';
540            foreach ($objErr->arrErr as $error) {
541                    $arrErr['plugin_file'] .= $error;
542            }
543        }
544        return $arrErr;
545    }
546
547    /**
548     * プラグインをアップデートします.
549     *
550     * @param array $target_plugin アップデートするプラグイン情報の配列.
551     * @param string $upload_file_name アップロードファイル名.
552     * @return array エラー情報を格納した連想配列.
553     */
554    function updatePlugin($target_plugin, $upload_file_name) {
555        // アップデート前に不要なファイルを消しておきます.
556        SC_Helper_FileManager_Ex::deleteFile(DOWNLOADS_TEMP_PLUGIN_UPDATE_DIR, false);
557
558        $arrErr = array();
559
560        // ファイルをチェックし展開します.
561        $arrErr = $this->unpackPluginFile($upload_file_name, DOWNLOADS_TEMP_PLUGIN_UPDATE_DIR, $target_plugin['plugin_code']);
562        if ($this->isError($arrErr) === true) {
563            return $arrErr;
564        }
565        // plugin_infoを読み込み.
566        $arrErr = $this->requirePluginFile(DOWNLOADS_TEMP_PLUGIN_UPDATE_DIR . 'plugin_info.php', $target_plugin['plugin_code']);
567        if ($this->isError($arrErr) === true) {
568            $this->rollBack(DOWNLOADS_TEMP_PLUGIN_INSTALL_DIR);
569            return $arrErr;
570        }
571        // リフレクションオブジェクトを生成.
572        $objReflection = new ReflectionClass('plugin_info');
573        $arrPluginInfo = $this->getPluginInfo($objReflection);
574        if ($arrPluginInfo['PLUGIN_CODE'] != $target_plugin['plugin_code']) {
575            $arrErr[$target_plugin['plugin_code']] = '※ プラグインコードが一致しません。<br/>';
576            return $arrErr;
577        }
578
579        // plugin_update.phpを読み込み.
580        $arrErr = $this->requirePluginFile(DOWNLOADS_TEMP_PLUGIN_UPDATE_DIR . 'plugin_update.php', $target_plugin['plugin_code']);
581        if ($this->isError($arrErr) === true) {
582            $this->rollBack(DOWNLOADS_TEMP_PLUGIN_UPDATE_DIR);
583            return $arrErr;
584        }
585        // プラグインクラスファイルのUPDATE処理を実行.
586        $arrErr = $this->execPlugin($target_plugin, 'plugin_update', 'update');
587
588        // 保存ディレクトリの削除.
589        SC_Helper_FileManager_Ex::deleteFile(DOWNLOADS_TEMP_PLUGIN_UPDATE_DIR, false);
590
591        return $arrErr;
592    }
593
594    /**
595     * ファイルをアップロードし、解凍先のディレクトリに解凍します.
596     *
597     * @param string $unpack_file_name 解凍ファイル名
598     * @param string $unpack_dir_path 解凍先ディレクトリパス
599     * @param string $file_key ファイルキー
600     * @return array エラー情報を格納した連想配列.
601     */
602    function unpackPluginFile($unpack_file_name, $unpack_dir_path, $file_key) {
603        $arrErr = array();
604        // 解凍ディレクトリディレクトリを作成し、一時ディレクトリからファイルを移動
605        $objUpFile = new SC_UploadFile_Ex(PLUGIN_TEMP_REALDIR, $unpack_dir_path);
606        $this->initUploadFile($objUpFile, $file_key);
607        $arrErr = $objUpFile->makeTempFile($file_key, false);
608        if ($this->isError($arrErr) === true) {
609            return $arrErr;
610        }
611
612        // 正常にアップロードされているかをチェック.
613        $arrErr = $objUpFile->checkExists($file_key);
614        if ($this->isError($arrErr) === true) {
615            return $arrErr;
616        }
617        $objUpFile->moveTempFile();
618        // 解凍
619        $unpack_file_path = $unpack_dir_path . $unpack_file_name;
620        if (!$this->unpackPluginArchive($unpack_file_path)) {
621            $arrErr['plugin_file'] = '※ 解凍に失敗しました。<br/>';
622            return $arrErr;
623        }
624        return $arrErr;
625    }
626
627    /**
628     * プラグインをアンインストールします.
629     *
630     * @param array $plugin プラグイン情報を確認した連想配列.
631     * @return array エラー情報を格納した連想配列.
632     */
633    function uninstallPlugin($plugin) {
634        $arrErr = array();
635        // プラグインファイルを読み込みます.
636        $plugin_class_file_path = $this->getPluginFilePath($plugin['plugin_code'], $plugin['class_name']);
637        $arrErr = $this->requirePluginFile($plugin_class_file_path, 'plugin_error');
638        if ($this->isError($arrErr) === true) {
639            return $arrErr;
640        }
641
642        // プラグインが有効な場合に無効化処理を実行
643        if ($plugin['enable'] == PLUGIN_ENABLE_TRUE){
644            // 無効化処理を実行します.
645            $arrErr = $this->execPlugin($plugin, $plugin['class_name'], 'disable');
646            if ($this->isError($arrErr) === true) {
647                return $arrErr;
648            }
649            // プラグインを無効にします.
650            $this->updatePluginEnable($plugin['plugin_id'], PLUGIN_ENABLE_FALSE);
651        }
652
653        // アンインストール処理を実行します.
654        $arrErr = $this->execPlugin($plugin, $plugin['class_name'], 'uninstall');
655        // プラグインの削除処理.
656        $arrErr = $this->deletePlugin($plugin['plugin_id'], $plugin['plugin_code']);
657
658        return $arrErr;
659    }
660
661    /**
662     * プラグインを有効にします.
663     *
664     * @param array $plugin プラグイン情報を確認した連想配列.
665     * @return array $arrErr エラー情報を格納した連想配列.
666     */
667    function enablePlugin($plugin) {
668        $arrErr = array();
669        // クラスファイルを読み込み.
670        $plugin_class_file_path = $this->getPluginFilePath($plugin['plugin_code'], $plugin['class_name']);
671        $arrErr = $this->requirePluginFile($plugin_class_file_path, 'plugin_error');
672        if ($this->isError($arrErr) === true) {
673            return $arrErr;
674        }
675        // 有効化処理を実行します.
676        $arrErr = $this->execPlugin($plugin, $plugin['class_name'], 'enable');
677        if ($this->isError($arrErr) === true) {
678            return $arrErr;
679        }
680        // プラグインを有効にします.
681        $this->updatePluginEnable($plugin['plugin_id'], PLUGIN_ENABLE_TRUE);
682
683        return $arrErr;
684    }
685
686    /**
687     * プラグインを無効にします.
688     *
689     * @param array $plugin プラグイン情報を確認した連想配列.
690     * @return array $arrErr エラー情報を格納した連想配列.
691     */
692    function disablePlugin($plugin) {
693        $arrErr = array();
694        // クラスファイルを読み込み.
695        $plugin_class_file_path =$this->getPluginFilePath($plugin['plugin_code'], $plugin['class_name']);
696        $arrErr = $this->requirePluginFile($plugin_class_file_path, 'plugin_error');
697        if ($this->isError($arrErr) === true) {
698            return $arrErr;
699        }
700
701        // 無効化処理を実行します.
702        $arrErr = $this->execPlugin($plugin, $plugin['class_name'], 'disable');
703        if ($this->isError($arrErr) === true) {
704            return $arrErr;
705        }
706        // プラグインを無効にします.
707        $this->updatePluginEnable($plugin['plugin_id'], PLUGIN_ENABLE_FALSE);
708
709        return $arrErr;
710    }
711
712    /**
713     * 優先度を更新します.
714     *
715     * @param int $plugin_id プラグインID
716     * @param int $priority 優先度
717     * @return integer 更新件数
718     */
719    function updatePriority($plugin_id, $priority) {
720        $objQuery =& SC_Query_Ex::getSingletonInstance();
721        // UPDATEする値を作成する。
722        $sqlval['priority'] = $priority;
723        $sqlval['update_date'] = 'CURRENT_TIMESTAMP';
724        $where = 'plugin_id = ?';
725        // UPDATEの実行
726        $ret = $objQuery->update('dtb_plugin', $sqlval, $where, array($plugin_id));
727        return $ret;
728    }
729
730    /**
731     * プラグイン情報をDB登録.
732     *
733     * @param array $arrPluginInfo プラグイン情報を格納した連想配列.
734     * @return array エラー情報を格納した連想配列.
735     */
736    function registerData($arrPluginInfo) {
737
738        // プラグイン情報をDB登録.
739        $objQuery =& SC_Query_Ex::getSingletonInstance();
740        $objQuery->begin();
741        $arr_sqlval_plugin = array();
742        $plugin_id = $objQuery->nextVal('dtb_plugin_plugin_id');
743        $arr_sqlval_plugin['plugin_id'] = $plugin_id;
744        $arr_sqlval_plugin['plugin_name'] = $arrPluginInfo['PLUGIN_NAME'];
745        $arr_sqlval_plugin['plugin_code'] = $arrPluginInfo['PLUGIN_CODE'];
746        $arr_sqlval_plugin['class_name'] = $arrPluginInfo['CLASS_NAME'];
747        $arr_sqlval_plugin['author'] = $arrPluginInfo['AUTHOR'];
748        // AUTHOR_SITE_URLが定義されているか判定.
749        $author_site_url = $arrPluginInfo['AUTHOR_SITE_URL'];
750        if ($author_site_url !== null) {
751            $arr_sqlval_plugin['author_site_url'] = $arrPluginInfo['AUTHOR_SITE_URL'];
752        }
753        // PLUGIN_SITE_URLが定義されているか判定.
754        $plugin_site_url = $arrPluginInfo['PLUGIN_SITE_URL'];
755        if ($plugin_site_url !== null) {
756            $arr_sqlval_plugin['plugin_site_url'] = $plugin_site_url;
757        }
758        $arr_sqlval_plugin['plugin_version'] = $arrPluginInfo['PLUGIN_VERSION'];
759        $arr_sqlval_plugin['compliant_version'] = $arrPluginInfo['COMPLIANT_VERSION'];
760        $arr_sqlval_plugin['plugin_description'] = $arrPluginInfo['DESCRIPTION'];
761        $arr_sqlval_plugin['priority'] = 0;
762        $arr_sqlval_plugin['enable'] = PLUGIN_ENABLE_FALSE;
763        $arr_sqlval_plugin['update_date'] = 'CURRENT_TIMESTAMP';
764        $objQuery->insert('dtb_plugin', $arr_sqlval_plugin);
765
766        // フックポイントをDB登録.
767        $hook_point = $arrPluginInfo['HOOK_POINTS'];
768        if ($hook_point !== null) {
769            /**
770             * FIXME コードが重複しているため、要修正
771             */
772            // フックポイントが配列で定義されている場合
773            if (is_array($hook_point)) {
774                foreach ($hook_point as $h) {
775                    $arr_sqlval_plugin_hookpoint = array();
776                    $id = $objQuery->nextVal('dtb_plugin_hookpoint_plugin_hookpoint_id');
777                    $arr_sqlval_plugin_hookpoint['plugin_hookpoint_id'] = $id;
778                    $arr_sqlval_plugin_hookpoint['plugin_id'] = $plugin_id;
779                    $arr_sqlval_plugin_hookpoint['hook_point'] = $h[0];
780                    $arr_sqlval_plugin_hookpoint['callback'] = $h[1];
781                    $arr_sqlval_plugin_hookpoint['update_date'] = 'CURRENT_TIMESTAMP';
782                    $objQuery->insert('dtb_plugin_hookpoint', $arr_sqlval_plugin_hookpoint);
783                }
784            // 文字列定義の場合
785            } else {
786                $array_hook_point = explode(',', $hook_point);
787                foreach ($array_hook_point as $h) {
788                    $arr_sqlval_plugin_hookpoint = array();
789                    $id = $objQuery->nextVal('dtb_plugin_hookpoint_plugin_hookpoint_id');
790                    $arr_sqlval_plugin_hookpoint['plugin_hookpoint_id'] = $id;
791                    $arr_sqlval_plugin_hookpoint['plugin_id'] = $plugin_id;
792                    $arr_sqlval_plugin_hookpoint['hook_point'] = $h;
793                    $arr_sqlval_plugin_hookpoint['update_date'] = 'CURRENT_TIMESTAMP';
794                    $objQuery->insert('dtb_plugin_hookpoint', $arr_sqlval_plugin_hookpoint);
795                }
796            }
797        }
798        return $objQuery->commit();
799    }
800
801    /**
802     * ファイルを読み込む.
803     *
804     * @param string $file_path クラスのpath
805     * @param string $key エラー情報のキー.
806     * @return array $arrErr エラー情報を格納した連想配列.
807     */
808    function requirePluginFile($file_path, $key) {
809        $arrErr = array();
810        if (file_exists($file_path)) {
811            require_once $file_path;
812        } else {
813            $arrErr[$key] = '※ ' . $file_path .'の読み込みに失敗しました。<br/>';
814        }
815        return $arrErr;
816    }
817
818    /**
819     * インスタンスを生成し、指定のメソッドを実行する.
820     *
821     * @param object $obj インスタンス
822     * @param string $class_name クラス名
823     * @param string $exec_func 実行するメソッド名.
824     * @return array $arrErr エラー情報を格納した連想配列.
825     *
826     */
827    function execPlugin($obj, $class_name, $exec_func) {
828        $arrErr = array();
829        if (method_exists($class_name, $exec_func) === true) {
830            $ret = call_user_func(array($class_name, $exec_func), $obj);
831            if (!(is_null($ret) || $ret === true)) {
832                $arrErr[$obj['plugin_code']] = $ret;
833            }
834        } else {
835            $arrErr['plugin_error'] = '※ ' . $class_name . '.php に' . $exec_func . 'が見つかりません。<br/>';
836        }
837        return $arrErr;
838    }
839
840    /**
841     * プラグインアーカイブを解凍する.
842     *
843     * @param string $path アーカイブパス
844     * @return boolean Archive_Tar::extractModify()のエラー
845     */
846    function unpackPluginArchive($path) {
847        // 圧縮フラグTRUEはgzip解凍をおこなう
848        $tar = new Archive_Tar($path, true);
849
850        $dir = dirname($path);
851        $file_name = basename($path);
852
853        // 拡張子を切り取る
854        $unpacking_name = preg_replace("/(\.tar|\.tar\.gz)$/", '', $file_name);
855
856        // 指定されたフォルダ内に解凍する
857        $result = $tar->extractModify($dir. '/', $unpacking_name);
858        GC_Utils_Ex::gfPrintLog('解凍:' . $dir.'/'.$file_name.'->'.$dir.'/'.$unpacking_name);
859        // 解凍元のファイルを削除する.
860        unlink($path);
861       
862        return $result;
863    }
864
865    /**
866     * plugin_idをキーにdtb_pluginのstatusを更新します.
867     *
868     * @param int $plugin_id プラグインID
869     * @param int $enable_flg 有効フラグ
870     * @return integer 更新件数
871     */
872    function updatePluginEnable($plugin_id, $enable_flg) {
873        $objQuery =& SC_Query_Ex::getSingletonInstance();
874        // UPDATEする値を作成する。
875        $sqlval['enable'] = $enable_flg;
876        $sqlval['update_date'] = 'CURRENT_TIMESTAMP';
877        $where = 'plugin_id = ?';
878        // UPDATEの実行
879        $ret = $objQuery->update('dtb_plugin', $sqlval, $where, array($plugin_id));
880        return $ret;
881    }
882
883    /**
884     * plugin_idをキーにdtb_plugin, dtb_plugin_hookpointから物理削除します.
885     *
886     * @param int $plugin_id プラグインID.
887     * @param string $plugin_code プラグインコード.
888     * @return array $arrErr エラー情報を格納した連想配列.
889     */
890    function deletePlugin($plugin_id, $plugin_code) {
891        $arrErr = array();
892        $objQuery =& SC_Query_Ex::getSingletonInstance();
893        $objQuery->begin();
894
895        SC_Plugin_Util_Ex::deletePluginByPluginId($plugin_id);
896
897        if (SC_Helper_FileManager_Ex::deleteFile($this->getPluginDir($plugin_code)) === false) {
898            // TODO エラー処理
899        }
900
901        if (SC_Helper_FileManager_Ex::deleteFile($this->getHtmlPluginDir($plugin_code)) === false) {
902            // TODO エラー処理
903        }
904
905        $objQuery->commit();
906
907        return $arrErr;
908    }
909
910    /**
911     * ファイルがあるかを判定します.
912     *
913     * @param string $plugin_dir 対象ディレクトリ.
914     * @param string $file_name ファイル名.
915     * @return boolean
916     */
917    function isContainsFile($plugin_dir, $file_name) {
918        if (file_exists($plugin_dir) && is_dir($plugin_dir)) {
919            if ($handle = opendir($plugin_dir)) {
920                while (($item = readdir($handle)) !== false) {
921                    if ($item === $file_name) return true;
922                }
923            }
924            closedir($handle);
925        }
926        return false;
927    }
928
929    /**
930     * アーカイブ内に指定のファイルが存在するかを判定します.
931     *
932     * @param Archive_Tar $tar_obj
933     * @param string $file_path 判定するファイルパス
934     * @return boolean
935     */
936    function checkContainsFile($tar_obj, $file_path) {
937        // ファイル一覧を取得
938        $arrayFile = $tar_obj->listContent();
939        foreach ($arrayFile as  $value) {
940            if ($value['filename'] === $file_path) return true;
941        }
942        return false;
943    }
944
945    /**
946     * ディレクトリを作成します.
947     *
948     * @param string $dir_path 作成するディレクトリのパス
949     * @return void
950     */
951    function makeDir($dir_path) {
952        // ディレクトリ作成
953        if (!file_exists($dir_path)) {
954            mkdir($dir_path);
955        }
956    }
957
958    /**
959     * フックポイントで衝突する可能性のあるプラグインを判定.メッセージを返します.
960     *
961     * @param int $plugin_id プラグインID
962     * @return string $conflict_alert_message メッセージ
963     */
964    function checkConflictPlugin($plugin_id) {
965        // フックポイントを取得します.
966        $hookPoints = $this->getHookPoint($plugin_id);
967
968        $conflict_alert_message = '';
969        $arrConflictPluginName = array();
970        $objQuery =& SC_Query_Ex::getSingletonInstance();
971        foreach ($hookPoints as $hookPoint) {
972            // 競合するプラグインを取得する,
973            $table = 'dtb_plugin_hookpoint AS T1 LEFT JOIN dtb_plugin AS T2 ON T1.plugin_id = T2.plugin_id';
974            $where = 'T1.hook_point = ? AND NOT T1.plugin_id = ? AND T2.enable = ' . PLUGIN_ENABLE_TRUE;
975            $objQuery->setGroupBy('T1.plugin_id, T2.plugin_name');
976            $conflictPlugins = $objQuery->select('T1.plugin_id, T2.plugin_name', $table, $where, array($hookPoint['hook_point'], $hookPoint['plugin_id']));
977
978            // プラグイン名重複を削除する為、専用の配列に格納し直す.
979            foreach ($conflictPlugins as $conflictPlugin) {
980                // プラグイン名が見つからなければ配列に格納
981                if (!in_array($conflictPlugin['plugin_name'], $arrConflictPluginName)) {
982                    $arrConflictPluginName[] = $conflictPlugin['plugin_name'];
983                }
984            }
985        }
986        // メッセージをセットします.
987        foreach ($arrConflictPluginName as $conflictPluginName) {
988            $conflict_alert_message .= '* ' .  $conflictPluginName . 'と競合する可能性があります。<br/>';
989        }
990        return $conflict_alert_message;
991    }
992
993    /**
994     * エラー情報が格納されているか判定します.
995     *
996     * @param array $arrErr エラー情報を格納した連想配列.
997     * @return boolean.
998     */
999    function isError($error) {
1000        if (is_array($error) && count($error) > 0) {
1001            return true;
1002        }
1003        return false;
1004    }
1005
1006    /**
1007     * プラグインIDからフックポイントを取得します,
1008     *
1009     * @param string $plugin_id プラグインID
1010     * @return array フックポイントの連想配列.
1011     */
1012    function getHookPoint($plugin_id) {
1013        $objQuery =& SC_Query_Ex::getSingletonInstance();
1014
1015        $table = 'dtb_plugin_hookpoint';
1016        $where = 'plugin_id = ?';
1017        return $objQuery->select('*', $table, $where, array($plugin_id));
1018    }
1019}
Note: See TracBrowser for help on using the repository browser.