Ignore:
Timestamp:
2012/01/12 12:16:10 (14 years ago)
Author:
h_yoshimoto
Message:

#1603 プラグイン機能(エンジン部分)を作成しました。

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/version-2_12-dev/data/class/helper/SC_Helper_Plugin.php

    r20870 r21395  
    2828 * @version $Id$ 
    2929 */ 
    30 class SC_Helper_Plugin{ 
    31  
    32     /** 
    33      * enableかどうかを判別する 
    34      * インスタンス化 
    35      */ 
    36     function load(&$lcpage){ 
    37         //データベースからクラス名を読み込む 
    38         $objQuery = new SC_Query_Ex(); 
    39         $col = "*"; 
    40         $table = "dtb_plugin"; 
    41         $where = "enable = 1 AND del_flg = 0"; 
    42         // XXX 2.11.0 互換のため 
    43         $arrCols = $objQuery->listTableFields($table); 
    44         if (in_array('rank', $arrCols)) { 
    45             $objQuery->setOrder('rank'); 
    46         } 
    47         $arrRet = $objQuery->select($col, $table, $where); 
    48         $class_name = get_class($lcpage); 
    49  
    50         // 現在のページで使用するプラグインが存在するかどうかを検証する 
    51         foreach ($arrRet as $plugins){ 
    52             // プラグインを稼働させるクラス名のリストを取得する 
    53             // プラグインのディレクトリ内の設定ファイルを参照する 
    54             $plugin_name = $plugins['plugin_name']; 
    55             $plugin_class_name = $plugins['class_name']; 
    56             $plugin_path = DATA_REALDIR . "plugin/{$plugin_name}/{$plugin_class_name}.php"; 
    57  
    58             if (file_exists($plugin_path)) { 
    59                 require_once $plugin_path; 
    60                 if (class_exists($class_name)) { 
    61                     $code_str = "\$is_enable = {$plugin_class_name}::isEnable(\$class_name);"; 
    62                     eval($code_str); 
    63                     if ($is_enable) { 
    64                         $arrPluginList[] = $plugin_class_name; 
    65                         GC_Utils_Ex::gfDebugLog($class_name . ' で、プラグイン ' . $plugin_name . ' をロードしました'); 
    66                     } else { 
    67                         GC_Utils_Ex::gfDebugLog($class_name . ' で、プラグイン ' . $plugin_name . ' は無効になっています'); 
     30class SC_Helper_Plugin { 
     31    // プラグインのインスタンスの配列. 
     32    var $arrPluginInstances = array(); 
     33    // プラグインのアクションの配列. 
     34    var $arrRegistedPluginActions = array(); 
     35    // プラグインのIDの配列. 
     36    var $arrPluginIds = array(); 
     37 
     38    /** 
     39     * 有効なプラグインのロード. プラグインエンジンが有効になっていない場合は 
     40     * プラグインエンジン自身のインストール処理を起動する 
     41     * 
     42     * @return void 
     43     */ 
     44    function load() { 
     45         
     46        if (!defined('CONFIG_REALFILE') || !file_exists(CONFIG_REALFILE)) return; // インストール前 
     47        if (SC_Utils_Ex::sfIsInstallFunction()) return; // インストール中 
     48 
     49        // 有効なプラグインを取得 
     50        $arrPluginDataList = $this->getEnablePlugin(); 
     51        // pluginディレクトリを取得 
     52        $arrPluginDirectory = $this->getPluginDirectory(); 
     53 
     54        foreach ($arrPluginDataList as $arrPluginData) { 
     55            // プラグイン本体ファイル名が取得したプラグインディレクトリ一覧にある事を確認 
     56            if (array_search($arrPluginData['class_name'], $arrPluginDirectory) !== false ) { 
     57                // プラグイン本体ファイルをrequire. 
     58                require_once(DOWNLOADS_PLUGIN_REALDIR . $arrPluginData['plugin_setting_path']); 
     59                // プラグインのインスタンス生成. 
     60                $objPlugin = new $arrPluginData['class_name']($arrPluginData); 
     61                // メンバ変数にプラグインのインスタンスを登録. 
     62                $this->arrPluginInstances[$arrPluginData['plugin_id']] = $objPlugin; 
     63                $this->arrPluginIds[] = $arrPluginData['plugin_id']; 
     64                // ローカルフックポイントの登録. 
     65                $this->registLocalHookPoint($objPlugin, $arrPluginData['rank']); 
     66                // スーパーフックポイントの登録. 
     67                $this->registSuperHookPoint($objPlugin, HOOK_POINT_PREPROCESS, 'preProcess', $arrPluginData['rank']); 
     68                $this->registSuperHookPoint($objPlugin, HOOK_POINT_PROCESS, 'process', $arrPluginData['rank']); 
     69            } 
     70        } 
     71    } 
     72 
     73    /** 
     74     * SC_Helper_Plugin オブジェクトを返す(Singletonパターン) 
     75     * 
     76     * @return object SC_Helper_Pluginオブジェクト 
     77     */ 
     78    function getSingletonInstance() { 
     79        if (!isset($GLOBALS['_SC_Helper_Plugin_instance']) || is_null($GLOBALS['_SC_Helper_Plugin_instance'])) { 
     80            $GLOBALS['_SC_Helper_Plugin_instance'] =& new SC_Helper_Plugin_Ex(); 
     81            $GLOBALS['_SC_Helper_Plugin_instance']->load(); 
     82        } 
     83        return $GLOBALS['_SC_Helper_Plugin_instance']; 
     84    } 
     85 
     86    /** 
     87     * プラグイン実行 
     88     * 
     89     * @param string $hook_point フックポイント 
     90     * @param array  $arrArgs    コールバック関数へ渡す引数 
     91     * @return void 
     92     */ 
     93    function doAction($hook_point, $arrArgs = array()) { 
     94        if(is_array($arrArgs) === false) { 
     95            array(&$arrArgs); 
     96        } 
     97 
     98        if (array_key_exists($hook_point, $this->arrRegistedPluginActions) 
     99            && is_array($this->arrRegistedPluginActions[$hook_point])) { 
     100 
     101            ksort($this->arrRegistedPluginActions[$hook_point]); 
     102            foreach ($this->arrRegistedPluginActions[$hook_point] as $priority => $arrFuncs) { 
     103                 
     104                foreach ($arrFuncs as $func) { 
     105                    if (!is_null($func['function'])) { 
     106                        call_user_func_array($func['function'], $arrArgs); 
    68107                    } 
    69                 } else { 
    70                     GC_Utils_Ex::gfDebugLog('プラグイン ' . $plugin_name . ' の ' . $class_name . ' が見つかりませんでした'); 
    71108                } 
    72             } else { 
    73                 GC_Utils_Ex::gfDebugLog('プラグイン ' . $plugin_name . " が読み込めませんでした。\n" 
    74                                         . 'Failed opening required ' . $plugin_path); 
    75             } 
    76         } 
    77         return $arrPluginList; 
    78     } 
    79  
    80     function preProcess(&$lcpage){ 
    81         //プラグインの名前を判別してページ内で有効なプラグインがあれば実行する 
    82         $arrPluginList = SC_Helper_Plugin_Ex::load($lcpage); 
    83        if(count($arrPluginList) > 0){ 
    84             foreach ($arrPluginList as $key => $value){ 
    85                 $instance = new $value; 
    86                 $instance->preProcess($lcpage); 
    87             } 
    88         } 
    89         return $lcpage; 
    90     } 
    91  
    92     /* 読み込んだプラグインの実行用メソッド 
    93      * 
    94      */ 
    95     function process(&$lcpage){ 
    96         //プラグインの名前を判別してページ内で有効なプラグインがあれば実行する 
    97         $arrPluginList = SC_Helper_Plugin_Ex::load($lcpage); 
    98         if(count($arrPluginList) > 0){ 
    99             foreach ($arrPluginList as $key => $value){ 
    100                 $instance = new $value; 
    101                 $instance->process($lcpage); 
    102             } 
    103         } 
    104         return $lcpage; 
     109            } 
     110        } 
    105111    } 
    106112 
     
    139145    } 
    140146 
    141     function getFilesystemPlugins(){ 
    142         $plugin_dir = DATA_REALDIR."/plugin/"; 
    143         if($dh = opendir($plugin_dir)){ 
    144             while(($file = readdir($dh) !== false)){ 
    145                 if(is_dir($plugin_dir."/".$file)){ 
     147    /** 
     148     * プラグインディレクトリの取得 
     149     * 
     150     * @return array $arrEccPluginDirectory 
     151     */ 
     152    function getPluginDirectory() { 
     153        $arrPluginDirectory = array(); 
     154        if (is_dir(DOWNLOADS_PLUGIN_REALDIR)) { 
     155            if ($dh = opendir(DOWNLOADS_PLUGIN_REALDIR)) { 
     156                while (($pluginDirectory = readdir($dh)) !== false) { 
     157                    $arrPluginDirectory[] = $pluginDirectory; 
    146158                } 
    147             } 
    148         } 
     159                closedir($dh); 
     160            } 
     161        } 
     162        return $arrPluginDirectory; 
     163    } 
     164 
     165    /** 
     166     * スーパーフックポイントを登録します. 
     167     *  
     168     * @param Object $objPlugin プラグインのインスタンス 
     169     * @param string $hook_point スーパーフックポイント 
     170     * @param string $function_name 実行する関数名 
     171     * @param string $priority 実行順 
     172     */ 
     173    function registSuperHookPoint($objPlugin, $hook_point, $function_name, $priority) { 
     174        // スーパープラグイン関数を定義しているかを検証. 
     175        if(method_exists($objPlugin, $function_name) === true){ 
     176            // アクションの登録 
     177            $this->addAction($hook_point, array($objPlugin, $function_name), $priority); 
     178        } 
     179    } 
     180 
     181    /** 
     182     * ローカルフックポイントを登録します. 
     183     * 
     184     * @param Object $objPlugin プラグインのインスタンス 
     185     * @param string $priority 実行順 
     186     */ 
     187    function registLocalHookPoint($objPlugin, $priority) { 
     188        // ローカルプラグイン関数を定義しているかを検証. 
     189        if(method_exists($objPlugin, 'regist') === true){ 
     190            // アクションの登録(プラグイン側に記述) 
     191            $objPluginHelper =& SC_Helper_Plugin::getSingletonInstance(); 
     192            $objPlugin->regist($objPluginHelper, $priority); 
     193        } 
     194    } 
     195 
     196    /** 
     197     * プラグイン コールバック関数を追加する 
     198     * 
     199     * @param string   $hook_point フックポイント名 
     200     * @param callback $function   コールバック関数名 
     201     * @param string   $priority   同一フックポイント内での実行優先度 
     202     * @return boolean 成功すればtrue 
     203     */ 
     204    function addAction($hook_point, $function, $priority) { 
     205        if (!is_callable($function)){ 
     206            // TODO エラー処理; コール可能な形式ではありません 
     207        } 
     208        $idx = $this->makeActionUniqueId($hook_point, $function, $priority); 
     209        $this->arrRegistedPluginActions[$hook_point][$priority][$idx] = array('function' => $function); 
     210        return true; 
     211    } 
     212 
     213    /** 
     214     * コールバック関数を一意に識別するIDの生成 
     215     * 
     216     * @param string   $hook_point フックポイント名 
     217     * @param callback $function   コールバック関数名 
     218     * @param integer  $priority   同一フックポイント内での実行優先度 
     219     * @return string コールバック関数を一意に識別するID 
     220     */ 
     221    function makeActionUniqueId($hook_point, $function, $priority) { 
     222        static $filter_id_count = 0; 
     223 
     224        if (is_string($function)) { 
     225            return $function; 
     226        } 
     227 
     228        if (is_object($function)) { 
     229            $function = array($function, ''); 
     230        } else { 
     231            $function = (array) $function; 
     232        } 
     233 
     234        if (is_object($function[0])) { 
     235            if (function_exists('spl_object_hash')) { 
     236                return spl_object_hash($function[0]) . $function[1]; 
     237            } else { 
     238                $obj_idx = get_class($function[0]).$function[1]; 
     239                if ( false === $priority ) 
     240                    return false; 
     241                $obj_idx .= isset($this->arrRegistedPluginActions[$hook_point][$priority]) 
     242                          ? count((array)$this->arrRegistedPluginActions[$hook_point][$priority]) 
     243                          : $filter_id_count; 
     244                $function[0]->wp_filter_id = $filter_id_count; 
     245                ++$filter_id_count; 
     246 
     247                return $obj_idx; 
     248            } 
     249        } else if ( is_string($function[0]) ) { 
     250            return $function[0].$function[1]; 
     251        } 
     252    } 
     253 
     254    /** 
     255     * 全てのテンプレートを再生成する 
     256     * 
     257     * @param boolean $test_mode true の場合、validate のみを行い、実際にテンプレートの再生成は行わない 
     258     * @return void 
     259     */ 
     260    function remakeAllTemplates($test_mode = false) { 
     261        $this->load(); // 最新のデータを読み込みなおす 
     262        if (!is_writable(PLUGIN_TMPL_CACHE_REALDIR)) { 
     263            // TODO エラー処理; 
     264            exit; 
     265        } 
     266        // キャッシュテンプレートを削除 
     267        if ($test_mode === true) { 
     268            $this->unlinkRecurse(PLUGIN_TMPL_CACHE_REALDIR, false); 
     269        } 
     270        $objTemplateTransformList = SC_Plugin_Template_Transform_List::getSingletonInstance(); 
     271        $objTemplateTransformList->init(); 
     272        foreach ($this->arrPluginInstances as $objPlugin) { 
     273            // TODO 関数チェック; 
     274            $objPlugin->setTemplateTransformer(); 
     275        } 
     276        // トランスフォーム実行 
     277        $objTemplateTransformList->transformAll($test_mode); 
     278    } 
     279 
     280    /** 
     281     * 指定されたパスの配下を再帰的に unlink 
     282     * 
     283     * @param string  $path       削除対象のディレクトリまたはファイルのパス 
     284     * @param boolean $del_myself $pathそのものを削除するか. true なら削除する. 
     285     * @return void 
     286     */ 
     287    function unlinkRecurse($path, $del_myself = true) { 
     288        if (!file_exists($path)) { 
     289            // TODO エラー処理; パスが存在しません 
     290        } elseif (is_dir($path)) { 
     291            // ディレクトリ 
     292            $handle = opendir($path); 
     293            if (!$handle) { 
     294                // TODO エラー処理; ディレクトリが開けませんでした 
     295            } 
     296 
     297            while (($item = readdir($handle)) !== false) { 
     298                if ($item === '.' || $item === '..') continue; 
     299                $cur_path = $path . '/' . $item; 
     300                if (is_dir($cur_path)) SC_Helper_Plugin::unlinkRecurse($cur_path); 
     301                else @unlink($cur_path); 
     302            } 
     303            closedir($handle); 
     304 
     305            // ディレクトリを削除 
     306            if ($del_myself) @rmdir($path); 
     307        } else { 
     308            // ファイルが指定された 
     309            @unlink($path); 
     310        } 
     311    } 
     312 
     313    /** 
     314     * テンプレートキャッシュファイルのフルパスを返す. 
     315     * 
     316     * @param string $tpl_mainpage  返すキャッシュファイルのパスの対象となるテンプレート. 
     317     * @param object $objPage  ページオブジェクト. 
     318     */ 
     319    function getPluginTemplateCachePath($objPage) { 
     320        // main_template の差し替え 
     321        if (strpos($objPage->tpl_mainpage, SMARTY_TEMPLATES_REALDIR) === 0) { 
     322            // フルパスで指定された 
     323            $dir = ''; 
     324            $default_tpl_mainpage = str_replace(SMARTY_TEMPLATES_REALDIR, '', $objPage->tpl_mainpage); 
     325        } else { 
     326            // フロントページ or 管理画面を判定 
     327            $dir = ($objPage instanceof LC_Page_Admin) ? 'admin/' : TEMPLATE_NAME . '/'; 
     328            $default_tpl_mainpage = $objPage->tpl_mainpage; 
     329        } 
     330        return PLUGIN_TMPL_CACHE_REALDIR . $dir . $default_tpl_mainpage; 
     331    } 
     332 
     333    /** 
     334     * ブロックの配列から有効でないpluginのブロックを除外して返します. 
     335     * 
     336     * @param array $arrBlocs プラグインのインストールディレクトリ 
     337     * @return array $arrBlocsサイトルートからメディアディレクトリへの相対パス 
     338     */ 
     339    function getEnableBlocs($arrBlocs) { 
     340        foreach ($arrBlocs as $key => $value) { 
     341            // 有効なpluginのブロック以外. 
     342            if(!in_array($value['plugin_id'] , $this->arrPluginIds)) { 
     343                // 通常ブロック以外. 
     344                if($value['plugin_id'] != ""){ 
     345                    // ブロック配列から削除する 
     346                    unset ($arrBlocs[$key]); 
     347                } 
     348            } 
     349        } 
     350        return $arrBlocs; 
    149351    } 
    150352} 
Note: See TracChangeset for help on using the changeset viewer.