Index: /branches/version-2_11-dev/data/class/helper/SC_Helper_FileManager.php
===================================================================
--- /branches/version-2_11-dev/data/class/helper/SC_Helper_FileManager.php	(revision 20764)
+++ /branches/version-2_11-dev/data/class/helper/SC_Helper_FileManager.php	(revision 20847)
@@ -345,12 +345,18 @@
      * @param string $filename ファイルパス
      * @param string $value 書き込み内容
+     * @return boolean ファイルの書き込みに成功した場合 true
      */
     function sfWriteFile($filename, $value) {
-        $fp = @fopen($filename, 'w');
-        // ファイルに書き込む
-        if($fp) {
-            fwrite($fp, $value);
-        }
-        @fclose($fp);
+        if (!is_dir(dirname($filename))) {
+            SC_Utils_Ex::recursiveMkdir(dirname($filename), 0777);
+        }
+        $fp = fopen($filename,'w');
+        if ($fp === false) {
+            return false;
+        }
+        if (fwrite($fp, $value) === false) {
+            return false;
+        }
+        return fclose($fp);;
     }
 
Index: /branches/version-2_11-dev/data/class/helper/SC_Helper_PageLayout.php
===================================================================
--- /branches/version-2_11-dev/data/class/helper/SC_Helper_PageLayout.php	(revision 20830)
+++ /branches/version-2_11-dev/data/class/helper/SC_Helper_PageLayout.php	(revision 20847)
@@ -58,4 +58,5 @@
             $arrPageData = $this->getPageProperties($device_type_id, 0);
         }
+
         $objPage->tpl_mainpage = $this->getTemplatePath($device_type_id) . $arrPageData[0]['filename'] . ".tpl";
         $objPage->arrPageLayout =& $arrPageData[0];
@@ -185,7 +186,5 @@
         if ($page_id != '') {
             $arrPageData = $this->getPageProperties($device_type_id, $page_id);
-            // SQL実行
             $ret = $objQuery->delete("dtb_pagelayout", "page_id = ? AND device_type_id = ?", array($page_id, $device_type_id));
-
             // ファイルの削除
             $this->lfDelFile($arrPageData[0]['filename'], $device_type_id);
@@ -207,5 +206,8 @@
         $objQuery =& SC_Query_Ex::getSingletonInstance();
 
-        // 同名ファイルの使用件数
+        /*
+         * 同名ファイルの使用件数
+         * PHP ファイルは, 複数のデバイスで共有するため, device_type_id を条件に入れない
+         */
         $count = $objQuery->count('dtb_pagelayout', 'filename = ?', array($filename));
 
Index: /branches/version-2_11-dev/data/class/util/SC_Utils.php
===================================================================
--- /branches/version-2_11-dev/data/class/util/SC_Utils.php	(revision 20845)
+++ /branches/version-2_11-dev/data/class/util/SC_Utils.php	(revision 20847)
@@ -2049,5 +2049,5 @@
                      * 自クラスへ再帰する.
                      */
-                    if (!SC_Utils_Ex::isBlank($in, $greedy)) {
+                    if (!SC_Utils::isBlank($in, $greedy)) {
                         return false;
                     }
@@ -2216,4 +2216,23 @@
         }
     }
+
+    /**
+     * ディレクトリを再帰的に作成する.
+     *
+     * mkdir 関数の $recursive パラメータを PHP4 でサポートする.
+     *
+     * @param string $pathname ディレクトリのパス
+     * @param integer $mode 作成するディレクトリのパーミッション
+     * @return boolean 作成に成功した場合 true; 失敗した場合 false
+     * @see http://jp.php.net/mkdir
+     */
+    function recursiveMkdir($pathname, $mode) {
+        /*
+         * SC_Utils_Ex への再帰は無限ループやメモリリークの懸念
+         * 自クラスへ再帰する.
+         */
+        is_dir(dirname($pathname)) || SC_Utils::recursiveMkdir(dirname($pathname), $mode);
+        return is_dir($pathname) || @mkdir($pathname, $mode);
+    }
 }
 ?>
Index: /branches/version-2_11-dev/data/class/pages/admin/design/LC_Page_Admin_Design_MainEdit.php
===================================================================
--- /branches/version-2_11-dev/data/class/pages/admin/design/LC_Page_Admin_Design_MainEdit.php	(revision 20841)
+++ /branches/version-2_11-dev/data/class/pages/admin/design/LC_Page_Admin_Design_MainEdit.php	(revision 20847)
@@ -24,4 +24,5 @@
 // {{{ requires
 require_once CLASS_EX_REALDIR . 'page_extends/admin/LC_Page_Admin_Ex.php';
+require_once CLASS_EX_REALDIR . 'helper_extends/SC_Helper_FileManager_Ex.php';
 
 /**
@@ -70,51 +71,59 @@
      */
     function action() {
-        $objView = new SC_AdminView_Ex();
-        $this->objLayout = new SC_Helper_PageLayout_Ex();
-
-        // ページIDを取得
-        if (isset($_REQUEST['page_id']) && is_numeric($_REQUEST['page_id'])) {
-            $page_id = $_REQUEST['page_id'];
-        }
-
-        $this->page_id = $page_id;
-
-        // 端末種別IDを取得
-        if (isset($_REQUEST['device_type_id'])
-            && is_numeric($_REQUEST['device_type_id'])) {
-            $device_type_id = $_REQUEST['device_type_id'];
-        } else {
-            $device_type_id = DEVICE_TYPE_PC;
-        }
-
-        //サブタイトルの追加
-        $this->tpl_subtitle .= ' - ' . $this->arrDeviceType[$device_type_id];
-
-        // ページ一覧を取得
-        $this->arrPageList = $this->objLayout->getPageProperties($device_type_id, null);
-
-        // メッセージ表示
-        if (isset($_GET['msg']) && $_GET['msg'] == 'on'){
-            $this->tpl_onload="alert('登録が完了しました。');";
-        }
-
-        // page_id が指定されている場合にはテンプレートデータの取得
-        if (is_numeric($page_id) && $page_id != '') {
-            $this->arrPageData = $this->lfGetPageData($page_id, $device_type_id, $objView);
-        }
+        $objLayout = new SC_Helper_PageLayout_Ex();
+        $objFormParam = new SC_FormParam_Ex();
+        $this->lfInitParam($objFormParam);
+        $objFormParam->setParam($_REQUEST);
+        $objFormParam->convParam();
+        $this->arrErr = $objFormParam->checkError();
+        $is_error = (!SC_Utils_Ex::isBlank($this->arrErr));
+
+        $this->device_type_id = $objFormParam->getValue('device_type_id', DEVICE_TYPE_PC);
+        $this->page_id = $objFormParam->getValue('page_id');
 
         switch ($this->getMode()) {
         case 'delete':
-            if ($this->objLayout->isEditablePage($device_type_id, $page_id)) {
-                $this->lfDeletePageData($page_id, $device_type_id);
-                exit;
+            if (!$is_error) {
+                if ($objLayout->isEditablePage($this->device_type_id, $this->page_id)) {
+                    $objLayout->lfDelPageData($this->page_id, $this->device_type_id);
+                    SC_Response_Ex::reload(array("device_type_id" => $this->device_type_id,
+                                                 "msg" => "on"), true);
+                    exit;
+                }
             }
             break;
 
         case 'confirm':
-            $this->lfConfirmPageData($page_id, $device_type_id);
+            if (!$is_error) {
+                $this->arrErr = $this->lfCheckError($objFormParam, $this->arrErr);
+                if (SC_Utils_Ex::isBlank($this->arrErr)) {
+                    $result = $this->doRegister($objFormParam, $objLayout);
+                    if ($result !== false) {
+                        SC_Response_Ex::reload(array("device_type_id" => $this->device_type_id,
+                                                     "page_id" => $result,
+                                                     "msg" => "on"), true);
+                    exit;
+                    }
+                }
+            }
         default:
-        }
-        $this->device_type_id = $device_type_id;
+            if (isset($_GET['msg']) && $_GET['msg'] == 'on'){
+                $this->tpl_onload = "alert('登録が完了しました。');";
+            }
+        }
+
+        if (!$is_error) {
+            $this->arrPageList = $objLayout->getPageProperties($this->device_type_id, null);
+            // page_id が指定されている場合にはテンプレートデータの取得
+            if (!SC_Utils_Ex::isBlank($this->page_id)) {
+                $arrPageData = $this->getTplMainpage($this->device_type_id, $this->page_id, $objLayout);
+                $objFormParam->setParam($arrPageData);
+            }
+        } else {
+            // 画面にエラー表示しないため, ログ出力
+            GC_Utils_Ex::gfPrintLog('Error: ' . print_r($this->arrErr, true));
+        }
+        $this->tpl_subtitle .= ' - ' . $this->arrDeviceType[$this->device_type_id];
+        $this->arrForm = $objFormParam->getFormParamList();
     }
 
@@ -129,280 +138,223 @@
 
     /**
+     * パラメータ情報の初期化
+     *
+     * XXX URL のフィールドは, 実際は filename なので注意
+     *
+     * @param object $objFormParam SC_FormParamインスタンス
+     * @return void
+     */
+    function lfInitParam(&$objFormParam) {
+        $objFormParam->addParam("ページID", "page_id", INT_LEN, 'n', array("NUM_CHECK", "MAX_LENGTH_CHECK"));
+        $objFormParam->addParam("端末種別ID", "device_type_id", INT_LEN, 'n', array("NUM_CHECK", "MAX_LENGTH_CHECK"));
+        $objFormParam->addParam("名称", "page_name", STEXT_LEN, 'KVa', array("SPTAB_CHECK", "MAX_LENGTH_CHECK"));
+        $objFormParam->addParam("URL", "filename", STEXT_LEN, 'a', array("SPTAB_CHECK", "MAX_LENGTH_CHECK"));
+        $objFormParam->addParam("ヘッダチェック", "header_chk", INT_LEN, 'n', array("NUM_CHECK", "MAX_LENGTH_CHECK"));
+        $objFormParam->addParam("フッタチェック", "footer_chk", INT_LEN, 'n', array("NUM_CHECK", "MAX_LENGTH_CHECK"));
+        $objFormParam->addParam("修正フラグ", "edit_flg", INT_LEN, 'n', array("NUM_CHECK", "MAX_LENGTH_CHECK"));
+        $objFormParam->addParam("TPLデータ", "tpl_data");
+     }
+
+    /**
      * ページデータを取得する.
      *
+     * @param integer $device_type_id 端末種別ID
      * @param integer $page_id ページID
-     * @param integer $device_type_id 端末種別ID
-     * @param object $objView ビューオブジェクト
-     * @return void
-     */
-    function lfGetPageData($page_id, $device_type_id, $objView){
-        $arrPageData = $this->objLayout->getPageProperties($device_type_id, $page_id);
-
-        if (strlen($arrPageData[0]['filename']) == 0) {
-            $this->arrErr['page_id_err'] = "※ 指定されたページは編集できません。";
-            // 画面の表示
-            $objView->assignobj($this);
-            $objView->display(MAIN_FRAME);
-            exit;
-        }
-
-        // テンプレートを読み込む
-        $templatePath = $this->objLayout->getTemplatePath($device_type_id);
-        $arrPageData[0]['tpl_data'] = file_get_contents($templatePath . $arrPageData[0]['filename'] . ".tpl");
-
-        // ディレクトリを画面表示用に編集
+     * @param SC_Helper_PageLayout $objLayout SC_Helper_PageLayout インスタンス
+     * @return array ページデータの配列
+     */
+    function getTplMainpage($device_type_id, $page_id, &$objLayout){
+        $arrPageData = $objLayout->getPageProperties($device_type_id, $page_id);
+
+        $templatePath = $objLayout->getTemplatePath($device_type_id);
+        $filename = $templatePath . $arrPageData[0]['filename'] . ".tpl";
+        if (file_exists($filename)) {
+            $arrPageData[0]['tpl_data'] = file_get_contents($filename);
+        }
+        // ファイル名を画面表示用に加工しておく
         $arrPageData[0]['filename'] = preg_replace('|^' . preg_quote(USER_DIR) . '|', '', $arrPageData[0]['filename']);
-
         return $arrPageData[0];
     }
 
     /**
-     * データ登録処理.
-     *
-     * @param integer $page_id ページID
-     * @param integer $device_type_id 端末種別ID
-     * @return void
-     */
-    function lfConfirmPageData($page_id, $device_type_id) {
-        // エラーチェック
-        $this->arrErr = $this->lfErrorCheck($_POST, $device_type_id);
-
-        // エラーがなければ更新処理を行う
-        if (count($this->arrErr) == 0) {
-            // DBへデータを更新する
-            $arrTmp = $this->lfEntryPageData(
-                $device_type_id,
-                $page_id,
-                $_POST['page_name'],
-                USER_DIR . $_POST['url'],
-                intval($_POST['header_chk']) === 1 ? 1 : 2,
-                intval($_POST['footer_chk']) === 1 ? 1 : 2
-            );
-            $page_id = $arrTmp['page_id'];
-
-            $arrTmp = $this->objLayout->getPageProperties($device_type_id, $page_id);
-            $arrData = $arrTmp[0];
-
-            // ベースデータでなければファイルを削除し、PHPファイルを作成する
-            if ($this->objLayout->isEditablePage($device_type_id, $arrData['page_id'])) {
-                // PHPファイル作成
-                $this->lfCreatePHPFile($_POST['url'], $device_type_id);
-            }
-
-            // TPLファイル作成
-            $cre_tpl = $this->objLayout->getTemplatePath($device_type_id) . $arrData['filename'] . '.tpl';
-            $this->lfCreateFile($cre_tpl, $_POST['tpl_data']);
-
-            $arrQueryString = array(
-                "page_id" => $arrData['page_id'],
-                "device_type_id" => $device_type_id,
-                'msg'     => 'on',
-            );
-            $this->objDisplay->reload($arrQueryString, true);
-            exit;
+     * 登録を実行する.
+     *
+     * ファイルの作成に失敗した場合は, エラーメッセージを出力し,
+     * データベースをロールバックする.
+     *
+     * @param SC_FormParam $objFormParam SC_FormParam インスタンス
+     * @param SC_Helper_PageLayout $objLayout SC_Helper_PageLayout インスタンス
+     * @return integer|boolean 登録が成功した場合, 登録したページID;
+     *                         失敗した場合 false
+     */
+    function doRegister($objFormParam, &$objLayout) {
+        $filename = $objFormParam->getValue('filename');
+        $arrParams['device_type_id'] = $objFormParam->getValue('device_type_id');
+        $arrParams['page_id'] = $objFormParam->getValue('page_id');
+        $arrParams['header_chk'] = intval($objFormParam->getValue('header_chk')) === 1 ? 1 : 2;
+        $arrParams['footer_chk'] = intval($objFormParam->getValue('footer_chk')) === 1 ? 1 : 2;
+        $arrParams['tpl_data'] = $objFormParam->getValue('tpl_data');
+        $arrParams['page_name'] = $objFormParam->getValue('page_name');
+        $arrParams['url'] = USER_DIR . $filename . '.php';
+        $arrParams['filename'] = USER_DIR . $filename;
+
+        $objQuery =& SC_Query_Ex::getSingletonInstance();
+        $objQuery->begin();
+
+        $page_id = $this->registerPage($arrParams, $objLayout);
+
+        /*
+         * 新規登録時
+         * or 編集可能な既存ページ編集時かつ, PHP ファイルが存在しない場合に,
+         * PHP ファイルを作成する.
+         */
+        if (SC_Utils_Ex::isBlank($arrParams['page_id'])
+            || $objLayout->isEditablePage($arrParams['device_type_id'], $arrParams['page_id'])) {
+            if (!$this->createPHPFile($filename)) {
+                $this->arrErr['err'] = '※ PHPファイルの作成に失敗しました<br />';
+                $objQuery->rollback();
+                return false;
+            }
+            // 新規登録時のみ $page_id を代入
+            $arrParams['page_id'] = $page_id;
+        }
+
+        if ($objLayout->isEditablePage($arrParams['device_type_id'], $page_id)) {
+            $tpl_path = $objLayout->getTemplatePath($arrParams['device_type_id']) . $arrParams['filename'] . '.tpl';
         } else {
-            // エラーがあれば入力時のデータを表示する
-            $this->arrPageData = $_POST;
-            $this->arrPageData['directory'] = '';
-            $this->arrPageData['filename'] = $_POST['url'];
-        }
-    }
-
-    /**
-     * ブロック情報を更新する.
-     *
-     * @param integer $device_type_id
-     * @param integer $page_id
-     * @param string $page_name
-     * @param string $filename
-     * @param integer $header_chk
-     * @param integer $footer_chk
-     * @return array 実際に使用した更新データ
-     */
-    function lfEntryPageData($device_type_id, $page_id, $page_name, $filename, $header_chk, $footer_chk) {
-        $objQuery = new SC_Query_Ex();
-        $arrChk = array();          // 排他チェック用
-
-        // 更新用データの変換
-        $sqlval = $this->lfGetUpdData($device_type_id, $page_id, $page_name, $filename, $header_chk, $footer_chk);
-
-        // データが存在しているかチェックを行う
-        if ($page_id !== ''){
-            $arrChk = $this->objLayout->getPageProperties($device_type_id, $page_id);
-        }
-
-        // page_id が空 若しくは データが存在していない場合にはINSERTを行う
-        if ($page_id === '' || !isset($arrChk[0])) {
-            // FIXME device_type_id ごとの連番にする
-            $sqlval['page_id'] = $objQuery->nextVal('dtb_pagelayout_page_id');
-            $sqlval['device_type_id'] = $device_type_id;
-            $sqlval['create_date'] = 'now()';
-            $objQuery->insert('dtb_pagelayout', $sqlval);
-        }
-        // データが存在してる場合にはアップデートを行う
+            $tpl_path = $objLayout->getTemplatePath($arrParams['device_type_id']) . $filename . '.tpl';
+        }
+
+        if (!SC_Helper_FileManager_Ex::sfWriteFile($tpl_path, $arrParams['tpl_data'])) {
+            $this->arrErr['err'] = '※ TPLファイルの書き込みに失敗しました<br />';
+            $objQuery->rollback();
+            return false;
+        }
+
+        $objQuery->commit();
+        return $arrParams['page_id'];
+    }
+
+    /**
+     * 入力内容をデータベースに登録する.
+     *
+     * @param array $arrParams フォームパラメータの配列
+     * @param SC_Helper_PageLayout $objLayout SC_Helper_PageLayout インスタンス
+     * @return integer ページID
+     */
+    function registerPage($arrParams, &$objLayout) {
+        $objQuery =& SC_Query_Ex::getSingletonInstance();
+
+        // ページIDが空の場合は新規登録
+        $is_new = SC_Utils_Ex::isBlank($arrParams['page_id']);
+        // 既存ページの存在チェック
+        if (!$is_new) {
+            $arrExists = $objLayout->getPageProperties($arrParams['device_type_id'], $arrParams['page_id']);
+        }
+
+        $table = 'dtb_pagelayout';
+        $arrValues = $objQuery->extractOnlyColsOf($table, $arrParams);
+        $arrValues['update_url'] = $_SERVER['HTTP_REFERER'];
+        $arrValues['update_date'] = 'now()';
+
+        // 新規登録
+        if ($is_new || SC_Utils_Ex::isBlank($arrExists)) {
+            $objQuery->setOrder('');
+            $arrValues['page_id'] = 1 + $objQuery->max('page_id', $table, 'device_type_id = ?',
+                                                       array($arrValues['device_type_id']));
+            $arrValues['create_date'] = 'now()';
+            $objQuery->insert($table, $arrValues);
+        }
+        // 更新
         else {
-            $objQuery->update('dtb_pagelayout', $sqlval, 'page_id = ? AND device_type_id = ?',
-                              array($page_id, $device_type_id));
-            // 戻り値用
-            $sqlval['page_id'] = $page_id;
-        }
-        return $sqlval;
-    }
-
-    /**
-     * DBへ更新を行うデータを生成する.
-     *
-     * @param integer $device_type_id
-     * @param integer $page_id
-     * @param string $page_name
-     * @param string $filename
-     * @param integer $header_chk
-     * @param integer $footer_chk
-     * @return array 更新データ
-     */
-    function lfGetUpdData($device_type_id, $page_id, $page_name, $filename, $header_chk, $footer_chk) {
-        $arrUpdData = array(
-            'header_chk'    => $header_chk,  // ヘッダー使用
-            'footer_chk'    => $footer_chk,  // フッター使用
-            'update_url'    => $_SERVER['HTTP_REFERER'],                    // 更新URL
-            'update_date'   => 'now()',
-        );
-
-        // ベースデータの場合には変更しない。
-        if ($this->objLayout->isEditablePage($device_type_id, $page_id)) {
-            $arrUpdData['page_name']    = $page_name;
-            $arrUpdData['url']          = $filename . '.php';
-            $arrUpdData['filename']     = $filename; // 拡張子を付加しない
-        }
-
-        return $arrUpdData;
-    }
-
-    /**
-     * ページデータを削除する.
-     *
-     * @param integer $page_id ページID
-     * @return void
-     */
-    function lfDeletePageData($page_id, $device_type_id){
-        $this->objLayout->lfDelPageData($page_id, $device_type_id);
-        $this->objDisplay->reload(array("device_type_id" => $device_type_id), true);
-    }
-
-    /**
-     * 入力項目のエラーチェックを行う.
-     *
-     * XXX $device_type_id が dtb_pagelayout の検索条件に入ってない
-     *
-     * @param array $arrData 入力データ
-     * @param integer $device_type_id 端末種別ID
-     * @return array エラー情報
-     */
-    function lfErrorCheck($array, $device_type_id) {
-        $objErr = new SC_CheckError_Ex($array);
+            // 編集不可ページは更新しない
+            if (!$objLayout->isEditablePage($arrValues['device_type_id'], $arrValues['page_id'])) {
+                unset($arrValues['page_name']);
+                unset($arrValues['filename']);
+                unset($arrValues['url']);
+            }
+
+            $objQuery->update('dtb_pagelayout', $arrValues, 'page_id = ? AND device_type_id = ?',
+                              array($arrValues['page_id'], $arrValues['device_type_id']));
+        }
+        return $arrValues['page_id'];
+    }
+
+    /**
+     * エラーチェックを行う.
+     *
+     * @param SC_FormParam $objFormParam SC_FormParam インスタンス
+     * @return array エラーメッセージの配列
+     */
+    function lfCheckError(&$objFormParam, &$arrErr) {
+        $arrParams = $objFormParam->getHashArray();
+        $objErr = new SC_CheckError_Ex($arrParams);
+        $objErr->arrErr =& $arrErr;
         $objErr->doFunc(array("名称", "page_name", STEXT_LEN), array("EXIST_CHECK", "SPTAB_CHECK", "MAX_LENGTH_CHECK"));
-        $objErr->doFunc(array('URL', 'url', STEXT_LEN), array("EXIST_CHECK", "SPTAB_CHECK", "MAX_LENGTH_CHECK"));
-
-        // URLチェック
-        $okUrl = true;
-        foreach (explode('/', $array['url']) as $url_part) {
-            if (!ereg( '^[a-zA-Z0-9:_~\.-]+$', $url_part)) {
-                $okUrl = false;
-            }
-            if ($url_part == '.' || $url_part == '..') {
-                $okUrl = false;
-            }
-        }
-        if (!$okUrl) {
-            $objErr->arrErr['url'] = "※ URLを正しく入力してください。<br />";
-        }
-
-        // 同一のURLが存在している場合にはエラー
-        $params = array();
-
-        $sqlWhere = 'url = ?';
-        $params[] = $this->objLayout->getUserDir($device_type_id) . $array['url'] . '.php';
-
-        // プレビュー用のレコードは除外
-        $sqlWhere .= ' AND page_id <> 0';
-
-        // 変更の場合、自身のレコードは除外
-        if (strlen($array['page_id']) != 0) {
-            $sqlWhere .= ' AND page_id <> ?';
-            $params[] = $array['page_id'];
+        $objErr->doFunc(array('URL', 'filename', STEXT_LEN), array("EXIST_CHECK", "SPTAB_CHECK", "MAX_LENGTH_CHECK"));
+
+        /*
+         * URL チェック
+         * ここでチェックするのは, パスのみなので SC_CheckError::URL_CHECK()
+         * は使用しない
+         */
+        $valid_url = true;
+        foreach (explode('/', $arrParams['filename']) as $val) {
+            if (!preg_match('/^[a-zA-Z0-9:_~\.\-]+$/', $val)) {
+                $valid_url = false;
+            }
+            if ($val == '.' || $val == '..') {
+                $valid_url = false;
+            }
+        }
+        if (!$valid_url) {
+            $objErr->arrErr['filename'] = "※ URLを正しく入力してください。<br />";
+        }
+        // 同一URLの存在チェック
+        $where = 'page_id <> 0 AND device_type_id = ? AND filename = ?';
+        $arrValues = array($arrParams['device_type_id'],
+                           SC_Helper_PageLayout_Ex::getUserDir($arrParams['device_type_id']) . $arrParams['filename'] . '.php');
+        // 変更の場合は自 URL を除外
+        if (!SC_Utils_Ex::isBlank($arrParams['page_id'])) {
+            $where .= ' AND page_id <> ?';
+            $arrValues[] = $arrParams['page_id'];
         }
 
         $objQuery =& SC_Query_Ex::getSingletonInstance();
-        $arrChk = $objQuery->select('*', 'dtb_pagelayout', $sqlWhere, $params);
-
-        if (count($arrChk) >= 1) {
-            $objErr->arrErr['url'] = '※ 同じURLのデータが存在しています。別のURLを付けてください。<br />';
-        }
-
+        $count = $objQuery->count('dtb_pagelayout', $where, $arrValues);
+        if ($count > 0) {
+            $objErr->arrErr['filename'] = '※ 同じURLのデータが存在しています。別のURLを入力してください。<br />';
+        }
         return $objErr->arrErr;
     }
 
     /**
-     * ファイルを作成する.
-     *
-     * @param string $path テンプレートファイルのパス
-     * @param string $data テンプレートの内容
-     * @return void
-     */
-    function lfCreateFile($path, $data){
-
-        // ディレクトリが存在していなければ作成する
-        if (!is_dir(dirname($path))) {
-            mkdir(dirname($path), 0777, true); // FIXME (PHP4)
-        }
-
-        // ファイル作成
-        $fp = fopen($path,'w');
-        if ($fp === false) {
-            SC_Utils_Ex::sfDispException();
-        }
-        $ret = fwrite($fp, $data);
-        if ($ret === false) {
-            SC_Utils_Ex::sfDispException();
-        }
-        fclose($fp);
-    }
-
-    /**
-     * PHPファイルを作成する.
-     *
-     * @param string $path PHPファイルのパス
-     * @return void
-     */
-    function lfCreatePHPFile($url, $device_type_id){
-
-        $path = USER_REALDIR . $url . ".php";
-
-        // カスタマイズを考慮し、上書きしない。(#831)
+     * PHP ファイルを生成する.
+     *
+     * 既に同名の PHP ファイルが存在する場合は何もせず true を返す.(#831)
+     *
+     * @param string $filename フォームパラメータの filename
+     * @return boolean 作成に成功した場合 true
+     */
+    function createPHPFile($filename) {
+        $path = USER_REALDIR . $filename . '.php';
+
         if (file_exists($path)) {
-            return;
-        }
-
-        // php保存先ディレクトリが存在していなければ作成する
-        if (!is_dir(dirname($path))) {
-            mkdir(dirname($path), 0777, true); // FIXME (PHP4)
-        }
-
-        // ベースとなるPHPファイルの読み込み
-        if (file_exists(USER_DEF_PHP_REALFILE)){
-            $php_data = file_get_contents(USER_DEF_PHP_REALFILE);
-        }
-
-        // require.phpの場所を書き換える
+            return true;
+        }
+
+        if (file_exists(USER_DEF_PHP_REALFILE)) {
+            $php_contents = file_get_contents(USER_DEF_PHP_REALFILE);
+        } else {
+            return false;
+        }
+
+        // require.php の PATH を書き換える
         $defaultStrings = "exit; // Don't rewrite. This line is rewritten by EC-CUBE.";
-        $replaceStrings = "require_once '" . str_repeat('../', substr_count($url, '/')) . "../require.php';";
-        $php_data = str_replace($defaultStrings, $replaceStrings, $php_data);
-
-        // phpファイルの作成
-        $fp = fopen($path,'w');
-        fwrite($fp, $php_data);
-        fclose($fp);
-    }
-
+        $replaceStrings = "require_once '" . str_repeat('../', substr_count($filename, '/')) . "../require.php';";
+        $php_contents = str_replace($defaultStrings, $replaceStrings, $php_contents);
+
+        return SC_Helper_FileManager_Ex::sfWriteFile($path, $php_contents);
+    }
 }
 ?>
Index: /branches/version-2_11-dev/data/Smarty/templates/admin/design/main_edit.tpl
===================================================================
--- /branches/version-2_11-dev/data/Smarty/templates/admin/design/main_edit.tpl	(revision 20813)
+++ /branches/version-2_11-dev/data/Smarty/templates/admin/design/main_edit.tpl	(revision 20847)
@@ -27,12 +27,4 @@
     document.form_edit.target = "_self";
 }
-
-browser_type = 0;
-if(navigator.userAgent.indexOf("MSIE") >= 0){
-    browser_type = 1;
-}
-else if(navigator.userAgent.indexOf("Mozilla") >= 0){
-    browser_type = 2;
-}
 //-->
 </script>
@@ -45,7 +37,7 @@
 <input type="hidden" name="device_type_id" value="<!--{$device_type_id|h}-->" />
 
-    <!--{if $arrErr.page_id_err != ""}-->
+    <!--{if $arrErr.err != ""}-->
         <div class="message">
-            <span class="attention"><!--{$arrErr.page_id_err}--></span>
+            <span class="attention"><!--{$arrErr.err}--></span>
         </div>
     <!--{/if}-->
@@ -54,12 +46,13 @@
             <th>名称</th>
             <td>
-                <!--{if $arrPageData.edit_flg == 2}-->
-                    <!--{$arrPageData.page_name|h}--><input type="hidden" name="page_name" value="<!--{$arrPageData.page_name|h}-->" />
+                <!--{assign var=key value="page_name"}-->
+                <!--{if $arrForm.edit_flg.value == 2}-->
+                    <!--{$arrForm[$key].value|h}--><input type="hidden" name="<!--{$key}-->" value="<!--{$arrForm[$key].value|h}-->" />
                 <!--{else}-->
-                    <input type="text" name="page_name" value="<!--{$arrPageData.page_name|h}-->" maxlength="<!--{$smarty.const.STEXT_LEN}-->" style="<!--{if $arrErr.page_name != ""}-->background-color: <!--{$smarty.const.ERR_COLOR}-->;<!--{/if}-->" size="60" class="box60" /><span class="attention"> (上限<!--{$smarty.const.STEXT_LEN}-->文字)</span>
+                    <input type="text" name="<!--{$key}-->" value="<!--{$arrForm[$key].value|h}-->" maxlength="<!--{$arrForm[$key].length|h}-->" style="<!--{$arrErr[$key]|sfGetErrorColor}-->" size="60" class="box60" /><span class="attention"> (上限<!--{$arrForm[$key].length|h}-->文字)</span>
                 <!--{/if}-->
-                <!--{if $arrErr.page_name != ""}-->
+                <!--{if $arrErr[$key] != ""}-->
                     <div class="message">
-                        <span class="attention"><!--{$arrErr.page_name}--></span>
+                        <span class="attention"><!--{$arrErr[$key]}--></span>
                     </div>
                 <!--{/if}-->
@@ -69,13 +62,14 @@
         <th>URL</th>
             <td>
-                <!--{if $arrPageData.edit_flg == 2}-->
-                    <!--{$smarty.const.HTTP_URL|h}--><!--{$arrPageData.url|h}-->
-                    <input type="hidden" name="url" value="<!--{$arrPageData.filename|h}-->" />
+                <!--{assign var=key value="filename"}-->
+                <!--{if $arrForm.edit_flg.value == 2}-->
+                    <!--{$smarty.const.HTTP_URL|h}--><!--{$arrForm[$key].value|h}-->.php
+                    <input type="hidden" name="<!--{$key}-->" value="<!--{$arrForm[$key].value|h}-->" />
                 <!--{else}-->
-                    <!--{$smarty.const.USER_URL|h}--><input type="text" name="url" value="<!--{$arrPageData.filename|h}-->" maxlength="<!--{$smarty.const.STEXT_LEN}-->" style="<!--{if $arrErr.url != ""}-->background-color: <!--{$smarty.const.ERR_COLOR}-->;<!--{/if}--> ime-mode: disabled;" size="40" class="box40" />.php<span class="attention"> (上限<!--{$smarty.const.STEXT_LEN}-->文字)</span>
+                    <!--{$smarty.const.USER_URL|h}--><input type="text" name="<!--{$key}-->" value="<!--{$arrForm[$key].value|h}-->" maxlength="<!--{$arrForm[$key].length|h}-->" style="<!--{$arrErr[$key]|sfGetErrorColor}-->" ime-mode: disabled;" size="40" class="box40" />.php<span class="attention"> (上限<!--{$arrForm[$key].length|h}-->文字)</span>
                 <!--{/if}-->
-                <!--{if $arrErr.url != ""}-->
+                <!--{if $arrErr[$key] != ""}-->
                     <div class="attention">
-                        <span class="attention"><!--{$arrErr.url}--></span>
+                        <span class="attention"><!--{$arrErr[$key]}--></span>
                     </div>
                 <!--{/if}-->
@@ -84,8 +78,8 @@
         <tr>
             <td colspan="2">
-                <label for="header-chk"><input type="checkbox" name="header_chk" id="header-chk" value="1" <!--{if $arrPageData.header_chk == "1"}-->checked="checked"<!--{/if}--> />共通のヘッダーを使用する</label>&nbsp;
-                <label for="footer-chk"><input type="checkbox" name="footer_chk" id="footer-chk" value="1" <!--{if $arrPageData.footer_chk == "1"}-->checked="checked"<!--{/if}--> />共通のフッターを使用する</label>
+                <label for="header-chk"><input type="checkbox" name="header_chk" id="header-chk" value="1" <!--{if $arrForm.header_chk.value == "1"}-->checked="checked"<!--{/if}--> />共通のヘッダーを使用する</label>&nbsp;
+                <label for="footer-chk"><input type="checkbox" name="footer_chk" id="footer-chk" value="1" <!--{if $arrForm.footer_chk.value == "1"}-->checked="checked"<!--{/if}--> />共通のフッターを使用する</label>
                 <div>
-                    <textarea id="tpl_data" class="top" name="tpl_data" rows=<!--{$text_row}--> style="width: 98%;"><!--{$arrPageData.tpl_data|h|smarty:nodefaults}--></textarea>
+                    <textarea id="tpl_data" class="top" name="tpl_data" rows=<!--{$text_row}--> style="width: 98%;"><!--{$arrForm.tpl_data.value|h|smarty:nodefaults}--></textarea>
                     <input type="hidden" name="html_area_row" value="<!--{$text_row}-->" /><br />
                     <a id="resize-btn" class="btn-normal" href="javascript:;" onclick="ChangeSize('#resize-btn', '#tpl_data', 50, 13); return false;"><span>拡大</span></a>
@@ -102,4 +96,7 @@
 
     <h2>編集可能ページ一覧</h2>
+    <div class="btn addnew">
+        <a class="btn-normal" href="?device_type_id=<!--{$device_type_id|u}-->"><span>ページを新規入力</span></a>
+    </div>
     <table class="list">
         <colgroup width="70%">
@@ -134,6 +131,3 @@
         <!--{/foreach}-->
     </table>
-    <div class="btn addnew">
-        <a class="btn-normal" href="?device_type_id=<!--{$device_type_id|u}-->"><span>ページを新規入力</span></a>
-    </div>
 </form>
Index: /branches/version-2_11-dev/test/class/util/SC_Utils_Test.php
===================================================================
--- /branches/version-2_11-dev/test/class/util/SC_Utils_Test.php	(revision 20841)
+++ /branches/version-2_11-dev/test/class/util/SC_Utils_Test.php	(revision 20847)
@@ -144,4 +144,16 @@
         $this->assertFalse(SC_Utils::isAbsoluteRealPath($empty));
     }
+
+    function testRecursiveMkdir() {
+        $tmp_dir = sys_get_temp_dir();
+        $dir = 'foo/bar';
+        $results = false;
+        if (is_dir($tmp_dir . $dir)) {
+            rmdir($tmp_dir . '/foo/bar');
+            rmdir($tmp_dir . '/foo');
+        }
+        $results = SC_Utils::recursiveMkdir($tmp_dir . $dir, 0777);
+        $this->assertTrue($results);
+    }
 }
 ?>
