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

Revision 22036, 42.5 KB checked in by h_yoshimoto, 8 years ago (diff)

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