Index: /branches/version-2_12-dev/data/class/helper/SC_Helper_Plugin.php
===================================================================
--- /branches/version-2_12-dev/data/class/helper/SC_Helper_Plugin.php	(revision 20870)
+++ /branches/version-2_12-dev/data/class/helper/SC_Helper_Plugin.php	(revision 21395)
@@ -28,79 +28,85 @@
  * @version $Id$
  */
-class SC_Helper_Plugin{
-
-    /**
-     * enableかどうかを判別する
-     * インスタンス化
-     */
-    function load(&$lcpage){
-        //データベースからクラス名を読み込む
-        $objQuery = new SC_Query_Ex();
-        $col = "*";
-        $table = "dtb_plugin";
-        $where = "enable = 1 AND del_flg = 0";
-        // XXX 2.11.0 互換のため
-        $arrCols = $objQuery->listTableFields($table);
-        if (in_array('rank', $arrCols)) {
-            $objQuery->setOrder('rank');
-        }
-        $arrRet = $objQuery->select($col, $table, $where);
-        $class_name = get_class($lcpage);
-
-        // 現在のページで使用するプラグインが存在するかどうかを検証する
-        foreach ($arrRet as $plugins){
-            // プラグインを稼働させるクラス名のリストを取得する
-            // プラグインのディレクトリ内の設定ファイルを参照する
-            $plugin_name = $plugins['plugin_name'];
-            $plugin_class_name = $plugins['class_name'];
-            $plugin_path = DATA_REALDIR . "plugin/{$plugin_name}/{$plugin_class_name}.php";
-
-            if (file_exists($plugin_path)) {
-                require_once $plugin_path;
-                if (class_exists($class_name)) {
-                    $code_str = "\$is_enable = {$plugin_class_name}::isEnable(\$class_name);";
-                    eval($code_str);
-                    if ($is_enable) {
-                        $arrPluginList[] = $plugin_class_name;
-                        GC_Utils_Ex::gfDebugLog($class_name . ' で、プラグイン ' . $plugin_name . ' をロードしました');
-                    } else {
-                        GC_Utils_Ex::gfDebugLog($class_name . ' で、プラグイン ' . $plugin_name . ' は無効になっています');
+class SC_Helper_Plugin {
+    // プラグインのインスタンスの配列.
+    var $arrPluginInstances = array();
+    // プラグインのアクションの配列.
+    var $arrRegistedPluginActions = array();
+    // プラグインのIDの配列.
+    var $arrPluginIds = array();
+
+    /**
+     * 有効なプラグインのロード. プラグインエンジンが有効になっていない場合は
+     * プラグインエンジン自身のインストール処理を起動する
+     *
+     * @return void
+     */
+    function load() {
+        
+        if (!defined('CONFIG_REALFILE') || !file_exists(CONFIG_REALFILE)) return; // インストール前
+        if (SC_Utils_Ex::sfIsInstallFunction()) return; // インストール中
+
+        // 有効なプラグインを取得
+        $arrPluginDataList = $this->getEnablePlugin();
+        // pluginディレクトリを取得
+        $arrPluginDirectory = $this->getPluginDirectory();
+
+        foreach ($arrPluginDataList as $arrPluginData) {
+            // プラグイン本体ファイル名が取得したプラグインディレクトリ一覧にある事を確認
+            if (array_search($arrPluginData['class_name'], $arrPluginDirectory) !== false ) {
+                // プラグイン本体ファイルをrequire.
+                require_once(DOWNLOADS_PLUGIN_REALDIR . $arrPluginData['plugin_setting_path']);
+                // プラグインのインスタンス生成.
+                $objPlugin = new $arrPluginData['class_name']($arrPluginData);
+                // メンバ変数にプラグインのインスタンスを登録.
+                $this->arrPluginInstances[$arrPluginData['plugin_id']] = $objPlugin;
+                $this->arrPluginIds[] = $arrPluginData['plugin_id'];
+                // ローカルフックポイントの登録.
+                $this->registLocalHookPoint($objPlugin, $arrPluginData['rank']);
+                // スーパーフックポイントの登録.
+                $this->registSuperHookPoint($objPlugin, HOOK_POINT_PREPROCESS, 'preProcess', $arrPluginData['rank']);
+                $this->registSuperHookPoint($objPlugin, HOOK_POINT_PROCESS, 'process', $arrPluginData['rank']);
+            }
+        }
+    }
+
+    /**
+     * SC_Helper_Plugin オブジェクトを返す（Singletonパターン）
+     *
+     * @return object SC_Helper_Pluginオブジェクト
+     */
+    function getSingletonInstance() {
+        if (!isset($GLOBALS['_SC_Helper_Plugin_instance']) || is_null($GLOBALS['_SC_Helper_Plugin_instance'])) {
+            $GLOBALS['_SC_Helper_Plugin_instance'] =& new SC_Helper_Plugin_Ex();
+            $GLOBALS['_SC_Helper_Plugin_instance']->load();
+        }
+        return $GLOBALS['_SC_Helper_Plugin_instance'];
+    }
+
+    /**
+     * プラグイン実行
+     *
+     * @param string $hook_point フックポイント
+     * @param array  $arrArgs    コールバック関数へ渡す引数
+     * @return void
+     */
+    function doAction($hook_point, $arrArgs = array()) {
+        if(is_array($arrArgs) === false) {
+            array(&$arrArgs);
+        }
+
+        if (array_key_exists($hook_point, $this->arrRegistedPluginActions)
+            && is_array($this->arrRegistedPluginActions[$hook_point])) {
+
+            ksort($this->arrRegistedPluginActions[$hook_point]);
+            foreach ($this->arrRegistedPluginActions[$hook_point] as $priority => $arrFuncs) {
+                
+                foreach ($arrFuncs as $func) {
+                    if (!is_null($func['function'])) {
+                        call_user_func_array($func['function'], $arrArgs);
                     }
-                } else {
-                    GC_Utils_Ex::gfDebugLog('プラグイン ' . $plugin_name . ' の ' . $class_name . ' が見つかりませんでした');
                 }
-            } else {
-                GC_Utils_Ex::gfDebugLog('プラグイン ' . $plugin_name . " が読み込めませんでした。\n"
-                                        . 'Failed opening required ' . $plugin_path);
-            }
-        }
-        return $arrPluginList;
-    }
-
-    function preProcess(&$lcpage){
-        //プラグインの名前を判別してページ内で有効なプラグインがあれば実行する
-        $arrPluginList = SC_Helper_Plugin_Ex::load($lcpage);
-       if(count($arrPluginList) > 0){
-            foreach ($arrPluginList as $key => $value){
-                $instance = new $value;
-                $instance->preProcess($lcpage);
-            }
-        }
-        return $lcpage;
-    }
-
-    /* 読み込んだプラグインの実行用メソッド
-     *
-     */
-    function process(&$lcpage){
-        //プラグインの名前を判別してページ内で有効なプラグインがあれば実行する
-        $arrPluginList = SC_Helper_Plugin_Ex::load($lcpage);
-        if(count($arrPluginList) > 0){
-            foreach ($arrPluginList as $key => $value){
-                $instance = new $value;
-                $instance->process($lcpage);
-            }
-        }
-        return $lcpage;
+            }
+        }
     }
 
@@ -139,12 +145,208 @@
     }
 
-    function getFilesystemPlugins(){
-        $plugin_dir = DATA_REALDIR."/plugin/";
-        if($dh = opendir($plugin_dir)){
-            while(($file = readdir($dh) !== false)){
-                if(is_dir($plugin_dir."/".$file)){
+    /**
+     * プラグインディレクトリの取得
+     *
+     * @return array $arrEccPluginDirectory
+     */
+    function getPluginDirectory() {
+        $arrPluginDirectory = array();
+        if (is_dir(DOWNLOADS_PLUGIN_REALDIR)) {
+            if ($dh = opendir(DOWNLOADS_PLUGIN_REALDIR)) {
+                while (($pluginDirectory = readdir($dh)) !== false) {
+                    $arrPluginDirectory[] = $pluginDirectory;
                 }
-            }
-        }
+                closedir($dh);
+            }
+        }
+        return $arrPluginDirectory;
+    }
+
+    /**
+     * スーパーフックポイントを登録します.
+     * 
+     * @param Object $objPlugin プラグインのインスタンス
+     * @param string $hook_point スーパーフックポイント
+     * @param string $function_name 実行する関数名
+     * @param string $priority 実行順
+     */
+    function registSuperHookPoint($objPlugin, $hook_point, $function_name, $priority) {
+        // スーパープラグイン関数を定義しているかを検証.
+        if(method_exists($objPlugin, $function_name) === true){
+            // アクションの登録
+            $this->addAction($hook_point, array($objPlugin, $function_name), $priority);
+        }
+    }
+
+    /**
+     * ローカルフックポイントを登録します.
+     *
+     * @param Object $objPlugin プラグインのインスタンス
+     * @param string $priority 実行順
+     */
+    function registLocalHookPoint($objPlugin, $priority) {
+        // ローカルプラグイン関数を定義しているかを検証.
+        if(method_exists($objPlugin, 'regist') === true){
+            // アクションの登録（プラグイン側に記述）
+            $objPluginHelper =& SC_Helper_Plugin::getSingletonInstance();
+            $objPlugin->regist($objPluginHelper, $priority);
+        }
+    }
+
+    /**
+     * プラグイン コールバック関数を追加する
+     *
+     * @param string   $hook_point フックポイント名
+     * @param callback $function   コールバック関数名
+     * @param string   $priority   同一フックポイント内での実行優先度
+     * @return boolean 成功すればtrue
+     */
+    function addAction($hook_point, $function, $priority) {
+        if (!is_callable($function)){
+            // TODO エラー処理;　コール可能な形式ではありません
+        }
+        $idx = $this->makeActionUniqueId($hook_point, $function, $priority);
+        $this->arrRegistedPluginActions[$hook_point][$priority][$idx] = array('function' => $function);
+        return true;
+    }
+
+    /**
+     * コールバック関数を一意に識別するIDの生成
+     *
+     * @param string   $hook_point フックポイント名
+     * @param callback $function   コールバック関数名
+     * @param integer  $priority   同一フックポイント内での実行優先度
+     * @return string コールバック関数を一意に識別するID
+     */
+    function makeActionUniqueId($hook_point, $function, $priority) {
+        static $filter_id_count = 0;
+
+        if (is_string($function)) {
+            return $function;
+        }
+
+        if (is_object($function)) {
+            $function = array($function, '');
+        } else {
+            $function = (array) $function;
+        }
+
+        if (is_object($function[0])) {
+            if (function_exists('spl_object_hash')) {
+                return spl_object_hash($function[0]) . $function[1];
+            } else {
+                $obj_idx = get_class($function[0]).$function[1];
+                if ( false === $priority )
+                    return false;
+                $obj_idx .= isset($this->arrRegistedPluginActions[$hook_point][$priority])
+                          ? count((array)$this->arrRegistedPluginActions[$hook_point][$priority])
+                          : $filter_id_count;
+                $function[0]->wp_filter_id = $filter_id_count;
+                ++$filter_id_count;
+
+                return $obj_idx;
+            }
+        } else if ( is_string($function[0]) ) {
+            return $function[0].$function[1];
+        }
+    }
+
+    /**
+     * 全てのテンプレートを再生成する
+     *
+     * @param boolean $test_mode true の場合、validate のみを行い、実際にテンプレートの再生成は行わない
+     * @return void
+     */
+    function remakeAllTemplates($test_mode = false) {
+        $this->load(); // 最新のデータを読み込みなおす
+        if (!is_writable(PLUGIN_TMPL_CACHE_REALDIR)) {
+            // TODO エラー処理;
+            exit;
+        }
+        // キャッシュテンプレートを削除
+        if ($test_mode === true) {
+            $this->unlinkRecurse(PLUGIN_TMPL_CACHE_REALDIR, false);
+        }
+        $objTemplateTransformList = SC_Plugin_Template_Transform_List::getSingletonInstance();
+        $objTemplateTransformList->init();
+        foreach ($this->arrPluginInstances as $objPlugin) {
+            // TODO 関数チェック;
+            $objPlugin->setTemplateTransformer();
+        }
+        // トランスフォーム実行
+        $objTemplateTransformList->transformAll($test_mode);
+    }
+
+    /**
+     * 指定されたパスの配下を再帰的に unlink
+     *
+     * @param string  $path       削除対象のディレクトリまたはファイルのパス
+     * @param boolean $del_myself $pathそのものを削除するか. true なら削除する.
+     * @return void
+     */
+    function unlinkRecurse($path, $del_myself = true) {
+        if (!file_exists($path)) {
+            // TODO エラー処理; パスが存在しません
+        } elseif (is_dir($path)) {
+            // ディレクトリ
+            $handle = opendir($path);
+            if (!$handle) {
+                // TODO エラー処理; ディレクトリが開けませんでした
+            }
+
+            while (($item = readdir($handle)) !== false) {
+                if ($item === '.' || $item === '..') continue;
+                $cur_path = $path . '/' . $item;
+                if (is_dir($cur_path)) SC_Helper_Plugin::unlinkRecurse($cur_path);
+                else @unlink($cur_path);
+            }
+            closedir($handle);
+
+            // ディレクトリを削除
+            if ($del_myself) @rmdir($path);
+        } else {
+            // ファイルが指定された
+            @unlink($path);
+        }
+    }
+
+    /**
+     * テンプレートキャッシュファイルのフルパスを返す.
+     *
+     * @param string $tpl_mainpage  返すキャッシュファイルのパスの対象となるテンプレート.
+     * @param object $objPage  ページオブジェクト.
+     */
+    function getPluginTemplateCachePath($objPage) {
+        // main_template の差し替え
+		if (strpos($objPage->tpl_mainpage, SMARTY_TEMPLATES_REALDIR) === 0) {
+			// フルパスで指定された
+			$dir = '';
+			$default_tpl_mainpage = str_replace(SMARTY_TEMPLATES_REALDIR, '', $objPage->tpl_mainpage);
+		} else {
+            // フロントページ or 管理画面を判定
+		    $dir = ($objPage instanceof LC_Page_Admin) ? 'admin/' : TEMPLATE_NAME . '/';
+			$default_tpl_mainpage = $objPage->tpl_mainpage;
+		}
+        return PLUGIN_TMPL_CACHE_REALDIR . $dir . $default_tpl_mainpage;
+    }
+
+    /**
+     * ブロックの配列から有効でないpluginのブロックを除外して返します.
+     *
+     * @param array $arrBlocs プラグインのインストールディレクトリ
+     * @return array $arrBlocsサイトルートからメディアディレクトリへの相対パス
+     */
+    function getEnableBlocs($arrBlocs) {
+        foreach ($arrBlocs as $key => $value) {
+            // 有効なpluginのブロック以外.
+            if(!in_array($value['plugin_id'] , $this->arrPluginIds)) {
+                // 通常ブロック以外.
+                if($value['plugin_id'] != ""){
+                    //　ブロック配列から削除する
+                    unset ($arrBlocs[$key]);
+                }
+            }
+        }
+        return $arrBlocs;
     }
 }
Index: /branches/version-2_12-dev/data/class/plugin/SC_Plugin_Template_Selector.php
===================================================================
--- /branches/version-2_12-dev/data/class/plugin/SC_Plugin_Template_Selector.php	(revision 21395)
+++ /branches/version-2_12-dev/data/class/plugin/SC_Plugin_Template_Selector.php	(revision 21395)
@@ -0,0 +1,162 @@
+<?php
+/*
+ * This file is part of EC-CUBE
+ *
+ * Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
+ *
+ * http://www.lockon.co.jp/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+/**
+* SmartyテンプレートをDOMを使用して変形させる際に使用するセレクタクラス
+*
+* @package Plugin
+* @author LOCKON CO.,LTD.
+* @version $Id: $
+*/
+class SC_Plugin_Template_Selector {
+
+    var $objTransformer;
+    var $arrElements;
+    var $current_plugin;
+
+    /**
+     * コンストラクタ
+     *
+     * @param SC_Plugin_Template_Transformer $objTransformer SC_Plugin_Template_Transformerオブジェクト
+     * @param string $current_plugin プラグイン名
+     * @return void
+     */
+    function __construct(SC_Plugin_Template_Transformer $objTransformer, $current_plugin) {
+        $this->objTransformer = $objTransformer;
+        $this->current_plugin = $current_plugin;
+        $this->arrElements = array();
+    }
+
+
+    /**
+     * 見つかった要素をプロパティに登録
+     *
+     * @param integer $elementNo  エレメントのインデックス
+     * @param array   $arrElement インデックスとDOMオブジェクトをペアとした配列
+     * @return void
+     */
+    function addElement($elementNo, array &$arrElement) {
+        if (!array_key_exists($arrElement[0], $this->arrElements)) {
+            $this->arrElements[$arrElement[0]] = array($elementNo, &$arrElement[1]);
+
+        }
+    }
+
+    /**
+     * jQueryライクなセレクタを用いてエレメントを検索する
+     *
+     * @param string  $selector      セレクタ
+     * @param string  $index         インデックス（指定がある場合）
+     * @param boolean $require       エレメントが見つからなかった場合、エラーとするか
+     * @param string  $err_msg       エラーメッセージ
+     * @param SC_Plugin_Template_Selector $objSelector セレクタオブジェクト
+     * @param string  $parent_index  セレクタ検索時の親要素の位置（子孫要素検索のため）
+     * @return SC_Plugin_Template_Selector SC_Plugin_Template_Selectorオブジェクト
+     */
+    function find($selector, $index = NULL, $require = true, $err_msg = NULL, SC_Plugin_Template_Selector $objSelector = NULL, $parent_index = NULL) {
+        $objSelectorChild = new SC_Plugin_Template_Selector($this->objTransformer, $this->current_plugin);
+        foreach ($this->arrElements as $key => &$objElement) {
+            $this->objTransformer->find($selector, $index, false, NULL, $objSelectorChild, $objElement[0]);
+        }
+        if ($require && $objSelectorChild->getFoundCount() == 0) {
+            $this->objTransformer->setError(
+                $this->current_plugin,
+                $selector,
+                SC_Plugin_Template_Transformer::ERR_TARGET_ELEMENT_NOT_FOUND,
+                $err_msg
+            );
+        }
+        return $objSelectorChild;
+    }
+
+
+    /**
+     * 要素の前にHTMLを挿入
+     *
+     * @param string $html_snip 挿入するHTMLの断片
+     * @return SC_Plugin_Template_Selector SC_Plugin_Template_Selectorオブジェクト
+     */
+    function insertBefore($html_snip) {
+        foreach ($this->arrElements as $key => $objElement) {
+            $this->objTransformer->setTransform('insertBefore', $objElement[0], $html_snip);
+        }
+        return $this;
+    }
+    
+
+    /**
+     * 要素の後にHTMLを挿入
+     *
+     * @param string $html_snip 挿入するHTMLの断片
+     * @return Plugin_Template_Selector Plugin_Template_Selectorオブジェクト
+     */
+    function insertAfter($html_snip) {
+        foreach ($this->arrElements as $key => $objElement) {
+            $this->objTransformer->setTransform('insertAfter', $objElement[0], $html_snip);
+        }
+        return $this;
+    }
+
+    /**
+     * 要素の末尾にHTMLを挿入
+     *
+     * @param string $html_snip 挿入するHTMLの断片
+     * @return SC_Plugin_Template_Selector SC_Plugin_Template_Selectorオブジェクト
+     */
+    function appendChild($html_snip) {
+        foreach ($this->arrElements as $key => $objElement) {
+            $this->objTransformer->setTransform('appendChild', $objElement[0], $html_snip);
+        }
+        return $this;
+    }
+    
+    
+    /**
+     * 要素を指定したHTMLに置換
+     *
+     * @param string $html_snip 置換後のHTMLの断片
+     * @return SC_Plugin_Template_Selector SC_Plugin_Template_Selectorオブジェクト
+     */
+    function replaceChild($html_snip) {
+        foreach ($this->arrElements as $key => &$objElement) {
+            $this->objTransformer->setTransform('replaceChild', $objElement[0], $html_snip);
+        }
+        return $this;
+    }
+    
+    
+    /**
+     * findで見つかったエレメントの数を返す
+     *
+     * @return integer findで見つかったエレメントの数
+     */
+    function getFoundCount() {
+        return count($this->arrElements);
+    }
+    
+
+
+}
+
+?>
Index: /branches/version-2_12-dev/data/class/plugin/SC_Plugin_Template_Transformer.php
===================================================================
--- /branches/version-2_12-dev/data/class/plugin/SC_Plugin_Template_Transformer.php	(revision 21395)
+++ /branches/version-2_12-dev/data/class/plugin/SC_Plugin_Template_Transformer.php	(revision 21395)
@@ -0,0 +1,448 @@
+<?php
+/*
+ * This file is part of EC-CUBE
+ *
+ * Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
+ *
+ * http://www.lockon.co.jp/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+/**
+ * テンプレートトランスフォーマークラス
+ *
+ * @package Plugin
+ * @author LOCKON CO.,LTD.
+ * @version $Id: $
+ */
+class SC_Plugin_Template_Transformer {
+
+    var $objDOM;
+    var $arrDomHash;
+    var $current_plugin;
+    var $arrSmartyTagsOrg;
+    var $arrSmartyTagsSub;
+    var $smarty_tags_idx;
+    var $arrErr;
+    var $arrElementTree;
+
+    const ERR_TARGET_ELEMENT_NOT_FOUND = 1;
+
+
+    /**
+     * コンストラクタ
+     *
+     * @param string $tmpl 変形前テンプレートファイルのフルパス
+     * @return void
+     */
+    function SC_Plugin_Template_Transformer($tmpl) {
+        $this->objDOM = new DOMDocument();
+        $this->objDOM->strictErrorChecking = false;
+        $this->snip_count = 0;
+        $this->smarty_tags_idx = 0;
+        $this->arrErr = array();
+        $this->arrElementTree = array();
+
+        // ファイルの内容を全て文字列に読み込む
+        $html = file_get_contents(SMARTY_TEMPLATES_REALDIR . $tmpl);
+        $err_msg = null;
+        
+        // 対象のパスが存在するかを検証する,
+        if ($html === false) {
+            $err_msg = SMARTY_TEMPLATES_REALDIR . $tmpl. "は存在しないか、読み取れません";
+        } elseif (!in_array(mb_detect_encoding($html), array('ASCII', 'UTF-8'))) {
+            $err_msg = $tmpl. "の文字コードがUTF-8ではありません";
+        }
+        
+        if (!is_null($err_msg)) {
+            // TODO エラー処理
+        }
+
+        // JavaScript内にSmartyのタグが存在するものを、コメント形式に置換
+		$html = preg_replace_callback(
+			'/<script.+?\/script>/s',
+			array($this, 'captureSmartyTags2Comment'),
+			$html
+		);
+
+        // HTMLタグ内にSmartyのタグが存在するものを、いったんダミーのタグに置換する
+        $html = preg_replace_callback(
+            '/<(?:[^<>]*?(?:(<\!--\{.+?\}-->)|(?R))[^<>]*?)*?>/s',
+            array($this, 'captureSmartyTagsInTag'),
+            $html
+        );
+
+        // 通常のノードに属する部分を、コメント形式に置換
+        $html = preg_replace_callback(
+            '/<\!--{.+?\}-->/s',
+            array($this, 'captureSmartyTags2Comment'),
+            $html
+        );
+        
+        $html = '<meta http-equiv="content-type" content="text/html; charset=UTF-8" /><html><body><!--TemplateTransformer start-->'.$html.'<!--TemplateTransformer end--></body></html>';
+        // TODO エラー処理
+        @$this->objDOM->loadHTML($html);
+        $this->arrDomHash = array('name' => array());
+
+        $this->scanChild($this->objDOM);
+
+    }
+
+    /**
+     * これから処理を行おうとするプラグインの名前をセットする
+     *
+     * @param string $plugin_name  プラグイン名
+     * @return void
+     */
+    function setCurrentPlugin($plugin_name) {
+        $this->current_plugin = $plugin_name;
+    }
+
+    /**
+     * DOMの処理の邪魔になるSmartyのタグを代理文字に置換する preg_replace_callback のコールバック関数
+     *
+     * コメント形式への置換
+     *
+     * @param array $arrMatches マッチしたタグの情報
+     * @return string 代わりの文字列
+     */
+    function captureSmartyTags2Comment(array $arrMatches) {
+        $substitute_tag = sprintf('<!--###%08d###-->', $this->smarty_tags_idx);
+        $this->arrSmartyTagsOrg[$this->smarty_tags_idx] = $arrMatches[0];
+        $this->arrSmartyTagsSub[$this->smarty_tags_idx] = $substitute_tag;
+        $this->smarty_tags_idx++;
+        return $substitute_tag;
+    }
+
+    /**
+     * DOMの処理の邪魔になるSmartyのタグを代理文字に置換する preg_replace_callback のコールバック関数
+     *
+     * HTMLエレメント内部の処理
+     *
+     * @param array $arrMatches マッチしたタグの情報
+     * @return string 代わりの文字列
+     */
+    function captureSmartyTagsInTag(array $arrMatches) {
+        // Smartyタグ内のクォートを処理しやすいよう、いったんダミーのタグに
+        $html = preg_replace_callback('/<\!--{.+?\}-->/s', array($this, 'captureSmartyTags2Temptag'), $arrMatches[0]);
+        $html = preg_replace_callback('/\"[^"]*?\"/s', array($this, 'captureSmartyTagsInQuote'), $html);
+        $html = preg_replace_callback('/###TEMP(\d{8})###/s', array($this, 'captureSmartyTags2Attr'), $html);
+        return $html;
+    }
+
+    /**
+     * DOMの処理の邪魔になるSmartyのタグを代理文字に置換する preg_replace_callback のコールバック関数
+     *
+     * ダミーへの置換実行
+     *
+     * @param array $arrMatches マッチしたタグの情報
+     * @return string 代わりの文字列
+     */
+    function captureSmartyTags2Temptag(array $arrMatches) {
+        $substitute_tag = sprintf('###TEMP%08d###', $this->smarty_tags_idx);
+        $this->arrSmartyTagsOrg[$this->smarty_tags_idx] = $arrMatches[0];
+        $this->arrSmartyTagsSub[$this->smarty_tags_idx] = $substitute_tag;
+        $this->smarty_tags_idx++;
+        return $substitute_tag;
+    }
+
+    /**
+     * DOMの処理の邪魔になるSmartyのタグを代理文字に置換する preg_replace_callback のコールバック関数
+     *
+     * クォート内（＝属性値）内にあるSmartyタグ（ダミーに置換済み）を、テキストに置換
+     *
+     * @param array $arrMatches マッチしたタグの情報
+     * @return string 代わりの文字列
+     */
+    function captureSmartyTagsInQuote(array $arrMatches) {
+        $html = preg_replace_callback('/###TEMP(\d{8})###/s', array($this, 'captureSmartyTags2Value'), $arrMatches[0]);
+        return $html;
+    }
+
+    /**
+     * DOMの処理の邪魔になるSmartyのタグを代理文字に置換する preg_replace_callback のコールバック関数
+     *
+     * テキストへの置換実行
+     *
+     * @param array $arrMatches マッチしたタグの情報
+     * @return string 代わりの文字列
+     */
+    function captureSmartyTags2Value(array $arrMatches) {
+        $tag_idx = (int)$arrMatches[1];
+        $substitute_tag = sprintf('###%08d###', $tag_idx);
+        $this->arrSmartyTagsSub[$tag_idx] = $substitute_tag;
+        return $substitute_tag;
+    }
+
+    /**
+     * DOMの処理の邪魔になるSmartyのタグを代理文字に置換する preg_replace_callback のコールバック関数
+     *
+     * エレメント内部にあって、属性値ではないものを、ダミーの属性として置換
+     *
+     * @param array $arrMatches マッチしたタグの情報
+     * @return string 代わりの文字列
+     */
+    function captureSmartyTags2Attr(array $arrMatches) {
+        $tag_idx = (int)$arrMatches[1];
+        $substitute_tag = sprintf('rel%08d="######"', $tag_idx);
+        $this->arrSmartyTagsSub[$tag_idx] = $substitute_tag;
+        return ' '.$substitute_tag.' '; // 属性はパース時にスペースが詰まるので、こちらにはスペースを入れておく
+    }
+
+    /**
+     * DOM Element / Document を走査し、name、class別に分類する
+     *
+     * @param  DOMNode $objDOMElement DOMNodeオブジェクト
+     * @param string $parent_selector 親セレクタ
+     * @return void
+     */
+    function scanChild(DOMNode $objDOMElement, $parent_selector = '') {
+        $objNodeList = $objDOMElement->childNodes;
+        
+        if (is_null($objNodeList)) return;
+        foreach ($objNodeList as $element) {
+            
+            $arrAttr = array();
+            // エレメントの場合、tag名を配列に入れる.
+            if ($element instanceof DOMElement) {
+                $arrAttr[] = $element->tagName;
+            }
+            
+            // getAttributeメソッドを持つかを検証
+            if (method_exists($element, 'getAttribute')) {
+                // id属性を持つ場合.
+                if ($element->hasAttribute('id')){
+                    // idの値を配列に格納(ex: [0] => #hoge)
+                    $arrAttr[] = '#'.$element->getAttribute('id');
+                }
+                // class属性を持つ場合.
+                if ($element->hasAttribute('class')) {
+                    // class名毎に配列に格納(ex: [0] => .hoge [1] => .huga)
+                    $arrClasses = preg_split('/\s+/', $element->getAttribute('class'));
+                    foreach ($arrClasses as $classname) $arrAttr[] = '.'.$classname;
+                }
+                // name属性を持つ場合.
+                if ($element->hasAttribute('name')){
+                    $this->arrDomHash['name'][$element->getAttribute('name')][] = $element;
+                }
+            }
+            // tag名と属性値を結合してセレクター名とする (ex: body #hoge.huga)
+            $this_selector = $parent_selector.' '.implode('', $arrAttr);
+            // セレクター名をキーにエレメントを格納.
+            $this->arrElementTree[] = array($this_selector, $element);
+            // エレメントがDOMNode場合は更に子要素を取り出す.
+            if ($element instanceof DOMNode) {
+                $this->scanChild($element, $this_selector);
+            }
+        }
+    }
+
+    /**
+     * jQueryライクなセレクタを用いてエレメントを検索する
+     *
+     * @param string  $selector      セレクタ
+     * @param integer $index         インデックス（指定がある場合）
+     * @param boolean $require       エレメントが見つからなかった場合、エラーとするか
+     * @param string  $err_msg       エラーメッセージ
+     * @param SC_Plugin_Template_Selector $objSelector セレクタオブジェクト
+     * @param string  $parent_index セレクタ検索時の親要素の位置（子孫要素検索のため）
+     * @return SC_Plugin_Template_Selector
+     */
+    function find($selector, $index = NULL, $require = true, $err_msg = NULL, SC_Plugin_Template_Selector $objSelector = NULL, $parent_index = NULL) {
+
+        if (is_null($objSelector)) $objSelector = new SC_Plugin_Template_Selector($this, $this->current_plugin);
+        
+        // jQueryライクなセレクタを正規表現に
+        $selector = preg_replace('/ *> */', ' >', $selector);
+
+        $regex = '/';
+        if (!is_null($parent_index)) $regex .= preg_quote($this->arrElementTree[$parent_index][0], '/');
+        // セレクターを配列にします.
+        $arrSelectors = explode(' ', $selector);        
+        
+        // セレクタから正規表現を生成.
+        foreach ($arrSelectors as $sub_selector) {
+            if (preg_match('/^(>?)([\w\-]+)?(#[\w\-]+)?(\.[\w\-]+)*$/', $sub_selector, $arrMatch)) {
+                if (isset($arrMatch[1]) && $arrMatch[1]) $regex .= ' ';
+                else $regex .= '.* ';
+                if (isset($arrMatch[2]) && $arrMatch[2]) $regex .= preg_quote($arrMatch[2], '/');
+                else $regex .= '([\w\-]+)?';
+                if (isset($arrMatch[3]) && $arrMatch[3]) $regex .= preg_quote($arrMatch[3], '/');
+                else $regex .= '(#(\w|\-|#{3}[0-9]{8}#{3})+)?';
+                if (isset($arrMatch[4]) && $arrMatch[4]) $regex .= '(\.(\w|\-|#{3}[0-9]{8}#{3})+)*'.preg_quote($arrMatch[4], '/').'(\.(\w|\-|#{3}[0-9]{8}#{3})+)*'; // class指定の時は前後にもclassが付いているかもしれない
+                else $regex .= '(\.(\w|\-|#{3}[0-9]{8}#{3})+)*';
+            }
+        }
+        $regex .= '$/i';
+
+        $cur_idx = 0;
+        // 絞込み検索のときは、前回見つけた位置から検索を開始する
+        $startIndex = is_null($parent_index) ? 0 : $parent_index;
+
+        // エレメントツリーのセレクタを先ほど作成した正規表現で順に検索.
+        for($iLoop=$startIndex; $iLoop < count($this->arrElementTree); $iLoop++){
+            
+            if (preg_match($regex, $this->arrElementTree[$iLoop][0])) {
+                if (is_null($index) || $cur_idx == $index) {
+                    // 検索にかかったエレメントをセレクターのメンバ変数の配列に入れる
+                    $objSelector->addElement($iLoop, $this->arrElementTree[$iLoop]);
+                }
+                $cur_idx++;
+            }
+        }
+
+        if ($require && $cur_idx == 0) {
+            $this->setError(
+                $this->current_plugin,
+                $selector,
+                SC_Plugin_Template_Transformer::ERR_TARGET_ELEMENT_NOT_FOUND,
+                $err_msg
+            );
+        }
+        
+        return $objSelector;
+    }
+    
+    /**
+     * DOMを用いた変形を実行する
+     *
+     * @param string $mode       実行するメソッドの種類
+     * @param string $target_key 変形対象のエレメントの完全なセレクタ
+     * @param string $html_snip  HTMLコード
+     * @return boolean
+     */
+    function setTransform($mode, $target_key, $html_snip) {
+        
+        $substitute_tag = sprintf('<!--###%08d###-->', $this->smarty_tags_idx);
+
+        $this->arrSmartyTagsOrg[$this->smarty_tags_idx] = $html_snip;
+        $this->arrSmartyTagsSub[$this->smarty_tags_idx] = $substitute_tag;
+        $this->smarty_tags_idx++;
+        
+        $objSnip = $this->objDOM->createDocumentFragment();
+        $objSnip->appendXML($substitute_tag);
+        
+        $objElement = false;
+        if(isset($this->arrElementTree[$target_key]) && $this->arrElementTree[$target_key][0]){
+            $objElement = &$this->arrElementTree[$target_key][1];
+        }
+
+        if (!$objElement) return false;
+        
+        try {
+            if ($mode == 'appendChild') {
+                $objElement->appendChild($objSnip);
+            } elseif ($mode == 'insertBefore') {
+                if (!is_object($objElement->parentNode)) return false;
+                $objElement->parentNode->insertBefore($objSnip, $objElement);
+            } elseif ($mode == 'insertAfter') {
+	            if ($objElement->nextSibling) {
+	                 $objElement->parentNode->insertBefore($objSnip, $objElement->nextSibling);
+	            } else {
+	                 $objElement->parentNode->appendChild($objSnip);
+	            }
+            } elseif ($mode == 'replaceChild') {
+                if (!is_object($objElement->parentNode)) return false;
+                $objElement->parentNode->replaceChild($objSnip, $objElement);
+            }
+            $this->snip_count++;
+        } catch (Exception $e) {
+            // TODO エラー処理
+        }
+        return true;
+    }
+    
+    /**
+     * セレクタエラーを記録する
+     *
+     * @param string  $plugin_name プラグイン名
+     * @param string  $selector    セレクタ
+     * @param integer $type        エラーの種類
+     * @param string  $err_msg     エラーメッセージ
+     * @return void
+     */
+    function setError($plugin_name, $selector, $type, $err_msg = NULL) {
+        $this->arrErr[] = array(
+            'plugin_name' => $plugin_name,
+            'selector'    => $selector,
+            'type'        => $type,
+            'err_msg'     => $err_msg
+        );
+    }
+    
+    /**
+     * HTMLに戻して、Transform用に付けたマーカーを削除し、Smartyのタグを復元する
+     *
+     * @return mixed トランスフォーム済みHTML。まったくトランスフォームが行われなかった場合はfalse。
+     */
+    function getHTML() {
+        if (count($this->arrErr)) {
+            // エラーメッセージ組み立て
+            $err_msg = "";
+            foreach ($this->arrErr as $arrErr) {
+                if ($arrErr['err_msg']) {
+                    $err_msg .= "<br />".$arrErr['err_msg'];
+                } else {
+                    if ($arrErr['type'] == SC_Plugin_Template_Transformer::ERR_TARGET_ELEMENT_NOT_FOUND) {
+                        $err_msg .= "<br />${arrErr['selector']} が存在しません";
+                    } else {
+                        $err_msg .= "<br />".print_r($arrErr, true);
+                    }
+                }
+            }
+            // TODO エラー処理
+            // ECC_Plugin_Engine::dispError(FREE_ERROR_MSG, "テンプレートの操作に失敗しました。".$err_msg);
+        
+        } elseif ($this->snip_count) {
+            $html = $this->objDOM->saveHTML();
+            // 置換　$htmlの$this->arrSmartyTagsSubを$this->arrSmartyTagsOrgに置換
+            $html = str_replace($this->arrSmartyTagsSub, $this->arrSmartyTagsOrg, $html);
+            $html = preg_replace('/^.*<\!--TemplateTransformer start-->/s', '', $html);
+            $html = preg_replace('/<\!--TemplateTransformer end-->.*$/s', '', $html);
+            return $html;
+        
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+     * 変形済みファイルを書き出す
+     *
+     * @param boolean $test_mode 
+     * @return mixed  書き出しに成功した場合は,書き出したファイルのパス. 失敗した場合は false.
+     */
+    function saveHTMLFile($filename, $test_mode = false) {
+        $html = $this->getHTML();
+        if ($html && $test_mode == false) {
+            // 成功し、かつ test_mode でなければファイルに書き出す
+            $filepath = PLUGIN_TMPL_CACHE_REALDIR . $filename;
+            $dir = dirname($filepath);
+            
+            if (!file_exists($dir)) mkdir($dir, PLUGIN_DIR_PERMISSION, true);
+            if (!file_put_contents($filepath, $html)) return false;
+            return $filepath;
+        } else {
+            return false;
+        }
+    }
+
+}
+
+
+?>
Index: /branches/version-2_12-dev/data/class/plugin/SC_Plugin_Template_Transform_List.php
===================================================================
--- /branches/version-2_12-dev/data/class/plugin/SC_Plugin_Template_Transform_List.php	(revision 21395)
+++ /branches/version-2_12-dev/data/class/plugin/SC_Plugin_Template_Transform_List.php	(revision 21395)
@@ -0,0 +1,177 @@
+<?php
+/*
+ * This file is part of EC-CUBE
+ *
+ * Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
+ *
+ * http://www.lockon.co.jp/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+/**
+ * テンプレートの transform に関する情報のコンテナとなるクラス
+ *
+ * @package Plugin
+ * @author LOCKON CO.,LTD.
+ * @version $Id: $
+ */
+class SC_Plugin_Template_Transform_List {
+
+    // トランスフォームするテンプレートの配列
+    var $arrConfsByTemplates;
+    var $arrTemplatesByPlugin;
+    var $arrBlocsByPlugin;
+
+    /**
+     * SC_Plugin_Template_Transform_List オブジェクトを返す（Singletonパターン）
+     *
+     * @return object SC_Plugin_Template_Transform_List
+     */
+    function getSingletonInstance() {
+        if (!isset($GLOBALS['_SC_Plugin_Template_Transform_List_instance']) || is_null($GLOBALS['_SC_Plugin_Template_Transform_List_instance'])) {
+            $GLOBALS['_SC_Plugin_Template_Transform_List_instance'] =& new SC_Plugin_Template_Transform_List();
+        }
+        return $GLOBALS['_SC_Plugin_Template_Transform_List_instance'];
+    }
+
+    /**
+     * 初期化
+     *
+     * @return void
+     */
+    function init() {
+        $this->arrConfsByTemplates = array();
+        // プラグインが介入するテンプレートの配列
+        $this->arrTemplatesByPlugin = array();
+        // HeadNaviに追加するブロックの配列
+        $this->arrHeadNaviBlocsByPlugin = array();
+    }
+
+    /**
+     * 設定対象のテンプレートをセットする
+     *
+     * @param streing $tmpl 設定対象のテンプレートパス
+     * @param SC_Plugin_Base $objPlugin プラグインオブジェクト
+     * @return SC_Plugin_Template_Transformer 指定したテンプレートを transform するための SC_Plugin_Template_Transformer オブジェクト
+     */
+    function setTemplate($tmpl, SC_Plugin_Base $objPlugin) {
+        $this->arrTemplatesByPlugin[$objPlugin->arrSelfInfo['class_name']][$tmpl] = 1;
+
+        if (!is_array($this->arrConfsByTemplates)) $this->arrConfsByTemplates = array();
+        if (!array_key_exists($tmpl, $this->arrConfsByTemplates)) {
+            // テンプレートパスをキーにトランスフォーマのインスタンスをセット.
+            $this->arrConfsByTemplates[$tmpl] = new SC_Plugin_Template_Transformer($tmpl);
+        }
+        // 処理を行うプラグイン名をセットする.
+        $this->arrConfsByTemplates[$tmpl]->setCurrentPlugin($objPlugin->arrSelfInfo['class_name']);
+        return $this->arrConfsByTemplates[$tmpl];
+    }
+
+    /**
+     * 設定対象の管理者用テンプレートをセットする
+     *
+     * @param streing $tmpl 設定対象のテンプレートのパス（adminディレクトリからの相対パス）
+     * @param SC_Plugin_Base $objPlugin プラグインオブジェクト
+     * @return SC_Plugin_Template_Transformer SC_Plugin_Template_Transformer オブジェクト
+     */
+    function setTemplateAdmin($tmpl, SC_Plugin_Base $objPlugin) {
+        return $this->setTemplate('admin/'.$tmpl, $objPlugin);
+    }
+
+    /**
+     * 設定対象のPC用テンプレートをセットする
+     *
+     * @param streing $tmpl 設定対象のテンプレートのパス（PCディレクトリからの相対パス）
+     * @param SC_Plugin_Base $objPlugin プラグインオブジェクト
+     * @return SC_Plugin_Template_Transformer SC_Plugin_Template_Transformer オブジェクト
+     */
+    function setTemplatePC($tmpl, SC_Plugin_Base $objPlugin) {
+        return $this->setTemplate(TEMPLATE_NAME.'/'.$tmpl, $objPlugin);
+    }
+
+    /**
+     * 設定対象の携帯用テンプレートをセットする
+     *
+     * @param streing $tmpl 設定対象のテンプレートのパス（携帯ディレクトリからの相対パス）
+     * @param SC_Plugin_Base $objPlugin プラグインオブジェクト
+     * @return SC_Plugin_Template_Transformer SC_Plugin_Template_Transformer オブジェクト
+     */
+    function setTemplateMobile($tmpl, SC_Plugin_Base $objPlugin) {
+        return $this->setTemplate(MOBILE_TEMPLATE_NAME.'/'.$tmpl, $objPlugin);
+    }
+
+    /**
+     * 設定対象のスマホ用テンプレートをセットする
+     *
+     * @param streing         $tmpl      設定対象のテンプレートのパス（スマホディレクトリからの相対パス）
+     * @param SC_Plugin_Base $objPlugin プラグインオブジェクト
+     * @return SC_Plugin_Template_Transformer SC_Plugin_Template_Transformer オブジェクト
+     */
+    function setTemplateSphone($tmpl, SC_Plugin_Base $objPlugin) {
+        return $this->setTemplate(SMARTPHONE_TEMPLATE_NAME.'/'.$tmpl, $objPlugin);
+    }
+
+    /**
+     * 指定したテンプレートの transform を実行する
+     *
+     * @param string $group_name transformするテンプレート
+     * @return void
+     */
+    function transform($tmpl) {
+        $this->arrConfsByTemplates[$tmpl]->saveHTMLFile($tmpl);
+    }
+
+    /**
+     * 全てのテンプレートの transform を実行する
+     *
+     * @param boolean $test_mode
+     * @return void
+     */
+    function transformAll($test_mode = false) {
+        foreach ($this->arrConfsByTemplates as $tmpl => $objTransformaer) {
+            $objTransformaer->saveHTMLFile($tmpl, $test_mode);
+        }
+    }
+
+    /**
+     * テンプレートのヘッダに追加するPHPのURLをセットする
+     *
+     * @param string $url PHPファイルのURL
+     * @return void
+     */
+    function setHeadNavi($url){
+        $this->arrHeadNaviBlocsByPlugin[$url] = TARGET_ID_HEAD;
+    }
+
+    /**
+     * PHPのURLをテンプレートのヘッダに追加する
+     *
+     * @param array|null $arrBlocs  配置情報を含めたブロックの配列
+     * @return void
+     */
+    function setHeadNaviBlocs(&$arrBlocs){
+        foreach($this->arrHeadNaviBlocsByPlugin as $key => $value){
+            $arrBlocs[] = array(
+                'target_id' =>$value,
+                'php_path' => $key
+            );
+        }
+    }
+
+}
+
+?>
Index: /branches/version-2_12-dev/data/class/pages/frontparts/bloc/LC_Page_FrontParts_Bloc.php
===================================================================
--- /branches/version-2_12-dev/data/class/pages/frontparts/bloc/LC_Page_FrontParts_Bloc.php	(revision 20935)
+++ /branches/version-2_12-dev/data/class/pages/frontparts/bloc/LC_Page_FrontParts_Bloc.php	(revision 21395)
@@ -48,7 +48,4 @@
         $this->objDisplay = new SC_Display_Ex();
 
-        // プラグインクラス生成
-        $this->objPlugin = new SC_Helper_Plugin_Ex();
-        $this->objPlugin->preProcess($this);
         $this->setTplMainpage($this->blocItems['tpl_path']);
 
Index: /branches/version-2_12-dev/data/class/pages/LC_Page.php
===================================================================
--- /branches/version-2_12-dev/data/class/pages/LC_Page.php	(revision 21027)
+++ /branches/version-2_12-dev/data/class/pages/LC_Page.php	(revision 21395)
@@ -97,8 +97,8 @@
                                  $this->objDisplay->detectDevice());
 
-        // プラグインクラス生成
-        $this->objPlugin = new SC_Helper_Plugin_Ex();
-        $this->objPlugin->preProcess($this);
-
+        // スーパーフックポイントを実行.
+        $objPlugin = SC_Helper_Plugin_Ex::getSingletonInstance();
+        $objPlugin->doAction('lc_page_preProcess', array($this));
+       
         // 店舗基本情報取得
         $this->arrSiteInfo = SC_Helper_DB_Ex::sfGetBasisData();
@@ -123,9 +123,17 @@
     function sendResponse() {
 
-        if (isset($this->objPlugin)) { // FIXME モバイルエラー応急対応
-            // post-prosess処理(暫定的)
-            $this->objPlugin->process($this);
-        }
-
+        // HeadNaviにpluginテンプレートを追加する.
+        $objTemplateTransformList = SC_Plugin_Template_Transform_List::getSingletonInstance();
+        $objTemplateTransformList->setHeadNaviBlocs($this->arrPageLayout['HeadNavi']);
+        
+        // plugin側で生成したページがあるかを検証し、ある場合は tpl_mainpage にセットする.
+        $objPlugin = SC_Helper_Plugin_Ex::getSingletonInstance();
+        $plugin_tmplpath = $objPlugin->getPluginTemplateCachePath($this);
+        if (file_exists($plugin_tmplpath)) $this->tpl_mainpage = $plugin_tmplpath;
+        
+        // スーパーフックポイントを実行.
+        $objPlugin = SC_Helper_Plugin_Ex::getSingletonInstance();
+        $objPlugin->doAction('lc_page_process', array($this));
+        
         $this->objDisplay->prepare($this);
         $this->objDisplay->response->write();
Index: /branches/version-2_12-dev/data/class/pages/admin/LC_Page_Admin.php
===================================================================
--- /branches/version-2_12-dev/data/class/pages/admin/LC_Page_Admin.php	(revision 21248)
+++ /branches/version-2_12-dev/data/class/pages/admin/LC_Page_Admin.php	(revision 21395)
@@ -65,7 +65,7 @@
         $this->objDisplay = new SC_Display_Ex();
 
-        // プラグインクラス生成
-        $this->objPlagin = new SC_Helper_Plugin_Ex();
-        $this->objPlagin->preProcess($this);
+        // スーパーフックポイントを実行.
+        $objPlugin = SC_Helper_Plugin_Ex::getSingletonInstance();
+        $objPlugin->doAction('lc_page_preProcess', array($this));
 
         // トランザクショントークンの検証と生成
@@ -88,8 +88,18 @@
      */
     function sendResponse() {
-        if (isset($this->objPlagin)) { // FIXME モバイルエラー応急対応
-            // post-prosess処理(暫定的)
-            $this->objPlagin->process($this);
-        }
+        
+        // HeadNaviにpluginテンプレートを追加する.
+        $objTemplateTransformList = SC_Plugin_Template_Transform_List::getSingletonInstance();
+        $objTemplateTransformList->setHeadNaviBlocs($this->arrPageLayout['HeadNavi']);
+
+        // プラグインによってトランスフォームされたテンプレートがあればセットする
+        $objPlugin = SC_Helper_Plugin_Ex::getSingletonInstance();
+        $plugin_tmplpath = $objPlugin->getPluginTemplateCachePath($this);
+        if (file_exists($plugin_tmplpath)) $this->tpl_mainpage = $plugin_tmplpath;
+
+        // スーパーフックポイントを実行.
+        $objPlugin = SC_Helper_Plugin_Ex::getSingletonInstance();
+        $objPlugin->doAction('lc_page_process', array($this));
+       
         $this->objDisplay->prepare($this, true);
         $this->objDisplay->response->write();
Index: /branches/version-2_12-dev/data/Smarty/templates/admin/main_frame.tpl
===================================================================
--- /branches/version-2_12-dev/data/Smarty/templates/admin/main_frame.tpl	(revision 21118)
+++ /branches/version-2_12-dev/data/Smarty/templates/admin/main_frame.tpl	(revision 21395)
@@ -53,5 +53,13 @@
 //]]>
 </script>
-
+<!--{* ▼Head COLUMN*}-->
+<!--{if $arrPageLayout.HeadNavi|@count > 0}-->
+    <!--{foreach key=HeadNaviKey item=HeadNaviItem from=$arrPageLayout.HeadNavi}-->
+        <!--{if $HeadNaviItem.php_path != ""}-->
+            <!--{include_php file=$HeadNaviItem.php_path}-->
+        <!--{/if}-->
+    <!--{/foreach}-->
+<!--{/if}-->
+<!--{* ▲Head COLUMN*}-->
 </head>
 
Index: /branches/version-2_12-dev/data/require_plugin.php
===================================================================
--- /branches/version-2_12-dev/data/require_plugin.php	(revision 20764)
+++ /branches/version-2_12-dev/data/require_plugin.php	(revision 21395)
@@ -22,26 +22,8 @@
  */
 
-// load plugins
-/* -----------------------------------------------------------------------------
- * TODO PHP4 でも使えるように, XML パーサーをファクトリークラスで実装する
- * ----------------------------------------------------------------------------*/
-define('DEBUG_LOAD_PLUGIN', true);
-
-if (version_compare("5", PHP_VERSION, "<")) {
-    $pluginsXml = SC_Utils_Ex::sfGetPluginsXml();
-    foreach ($pluginsXml->plugin as $plugin) {
-        $requireFile = PLUGIN_REALDIR . "{$plugin->path}/require.php";
-        if (file_exists($requireFile)) {
-            include_once $requireFile;
-        }
-    }
-
-    // Smarty に引き渡す目的
-    // FIXME スーパーグローバルを書き換える以外の方法に改める。(グローバル変数にセットして、Smrty 関数で読み出すなど)
-    $_ENV['pluginsXml'] = $pluginsXml;
-
-    // グローバル変数を掃除
-    unset($plugin);
-    unset($pluginsXml);
-}
+    require_once (PLUGIN_REALDIR . 'SC_Plugin_Template_Transform_List.php');
+    require_once (PLUGIN_REALDIR . 'SC_Plugin_Template_Transformer.php');
+    require_once (PLUGIN_REALDIR . 'SC_Plugin_Template_Selector.php');
+    require_once (DOWNLOADS_PLUGIN_REALDIR . 'SC_Plugin_Base.php');
+//}
 ?>
Index: /branches/version-2_12-dev/data/mtb_constants_init.php
===================================================================
--- /branches/version-2_12-dev/data/mtb_constants_init.php	(revision 21393)
+++ /branches/version-2_12-dev/data/mtb_constants_init.php	(revision 21395)
@@ -489,6 +489,14 @@
 /** プラグインディレクトリ */
 define('PLUGIN_DIR', "plugins/");
-/** プラグイン保存先 */
-define('PLUGIN_REALDIR', USER_REALDIR . PLUGIN_DIR);
+/** プラグインエンジン */
+define('PLUGIN_REALDIR', DATA_REALDIR . "class/plugin/");
+/** プラグイン保存先. */
+define('DOWNLOADS_PLUGIN_REALDIR', DATA_REALDIR . "downloads/plugin/");
+/** プラグイン・テンプレートキャッシュ. */
+define('PLUGIN_TMPL_CACHE_REALDIR', DOWNLOADS_PLUGIN_REALDIR . 'templates_cache/');
+/** プラグイン・ディレクトリパーミッション. */
+define('PLUGIN_DIR_PERMISSION', 0777);
+/** プラグイン URL. */
+define('PLUGIN_HTML_URLPATH', ROOT_URLPATH . 'plugin/');
 /** プラグイン URL */
 define('PLUGIN_URL', USER_URL . PLUGIN_DIR);
@@ -593,3 +601,7 @@
 /** 郵便番号CSVのZIPアーカイブファイルの取得元 */
 define('ZIP_DOWNLOAD_URL', "http://www.post.japanpost.jp/zipcode/dl/kogaki/zip/ken_all.zip");
+/** フックポイント（プレプロセス） */
+define('HOOK_POINT_PREPROCESS', "lc_page_preProcess");
+/** フックポイント（プロセス） */
+define('HOOK_POINT_PROCESS', "lc_page_process");
 ?>
Index: /branches/version-2_12-dev/data/downloads/plugin/SC_Plugin_Base.php
===================================================================
--- /branches/version-2_12-dev/data/downloads/plugin/SC_Plugin_Base.php	(revision 21395)
+++ /branches/version-2_12-dev/data/downloads/plugin/SC_Plugin_Base.php	(revision 21395)
@@ -0,0 +1,50 @@
+<?php
+/*
+ * This file is part of EC-CUBE
+ *
+ * Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
+ *
+ * http://www.lockon.co.jp/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *
+ */
+
+/**
+ * プラグインの基底クラス
+ *
+ * @package Plugin
+ * @author LOCKON CO.,LTD.
+ * @version $Id: $
+ */
+class SC_Plugin_Base {
+
+    var $arrSelfInfo;
+
+    /**
+     * コンストラクタ
+     * 
+     * @param array $arrSelfInfo 自身のプラグイン情報
+     * @return void
+     */
+    function SC_Plugin_Base (array $arrSelfInfo) {
+        $this->arrSelfInfo = $arrSelfInfo;
+    }
+
+}
+
+
+?>
Index: /branches/version-2_12-dev/data/require_base.php
===================================================================
--- /branches/version-2_12-dev/data/require_base.php	(revision 20764)
+++ /branches/version-2_12-dev/data/require_base.php	(revision 21395)
@@ -55,5 +55,5 @@
 
     // プラグインを読み込む
-    //require_once DATA_REALDIR . 'require_plugin.php';
+    require_once DATA_REALDIR . 'require_plugin.php';
 }
 ?>
