Index: branches/version-2_5-dev/html/install/sql/insert_data.sql
===================================================================
--- branches/version-2_5-dev/html/install/sql/insert_data.sql	(revision 20707)
+++ branches/version-2_5-dev/html/install/sql/insert_data.sql	(revision 20733)
@@ -292,6 +292,7 @@
 INSERT INTO dtb_csv (no, csv_id, col, disp_name, rank, rw_flg, status, create_date, update_date, mb_convert_kana_option, size_const_type, error_check_types) VALUES (196, 5, 'category_name', 'カテゴリ名', 2, 1, 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'KVa', 'STEXT_LEN', 'SPTAB_CHECK,MAX_LENGTH_CHECK,EXIST_CHECK');
 INSERT INTO dtb_csv (no, csv_id, col, disp_name, rank, rw_flg, status, create_date, update_date, mb_convert_kana_option, size_const_type, error_check_types) VALUES (197, 5, 'parent_category_id', '親カテゴリID', 3, 1, 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'n', 'INT_LEN', 'NUM_CHECK,MAX_LENGTH_CHECK,EXIST_CHECK');
-INSERT INTO dtb_csv (no, csv_id, col, disp_name, rank, rw_flg, status, create_date, update_date, mb_convert_kana_option, size_const_type, error_check_types) VALUES (198, 5, 'level', '階層', 4, 1, 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'n', 'INT_LEN', 'NUM_CHECK,MAX_LENGTH_CHECK');
-INSERT INTO dtb_csv (no, csv_id, col, disp_name, rank, rw_flg, status, create_date, update_date, mb_convert_kana_option, size_const_type, error_check_types) VALUES (199, 5, 'rank', '表示ランク', 5, 1, 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'n', 'INT_LEN', 'NUM_CHECK,MAX_LENGTH_CHECK');
+INSERT INTO dtb_csv (no, csv_id, col, disp_name, rank, rw_flg, status, create_date, update_date, mb_convert_kana_option, size_const_type, error_check_types) VALUES (198, 5, 'level', '階層', NULL, 2, 2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'n', 'INT_LEN', 'NUM_CHECK,MAX_LENGTH_CHECK');
+INSERT INTO dtb_csv (no, csv_id, col, disp_name, rank, rw_flg, status, create_date, update_date, mb_convert_kana_option, size_const_type, error_check_types) VALUES (199, 5, 'rank', '表示ランク', NULL, 2, 2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'n', 'INT_LEN', 'NUM_CHECK,MAX_LENGTH_CHECK');
+INSERT INTO dtb_csv (no, csv_id, col, disp_name, rank, rw_flg, status, create_date, update_date, mb_convert_kana_option, size_const_type, error_check_types) VALUES (200, 5, 'del_flg', '削除フラグ', NULL, 1, 2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'n', 'INT_LEN', 'NUM_CHECK,MAX_LENGTH_CHECK');
 
 INSERT INTO dtb_deliv (deliv_id, product_type_id, name, service_name, confirm_url, rank, status, del_flg, creator_id, create_date, update_date) VALUES (1, 1, 'サンプル業者', 'サンプル業者', NULL, 2, 1, 0, 2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
Index: branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_UploadCSVCategory.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_UploadCSVCategory.php	(revision 20540)
+++ branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_UploadCSVCategory.php	(revision 20733)
@@ -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_CSV_Ex.php';
 
 /**
@@ -36,14 +37,28 @@
 class LC_Page_Admin_Products_UploadCSVCategory extends LC_Page_Admin_Ex {
 
+    // {{{ properties
+    /** エラー情報 **/
+    var $arrErr;
+
+    /** 表示用項目 **/
+    var $arrTitle;
+
+    /** 結果行情報 **/
+    var $arrRowResult;
+
+    /** エラー行情報 **/
+    var $arrRowErr;
+
+    /** TAGエラーチェックフィールド情報 */
+    var $arrTagCheckItem;
+
+    /** テーブルカラム情報 (登録処理用) **/
+    var $arrRegistColumn;
+
+    /** 登録フォームカラム情報 **/
+    var $arrFormKeyList;
+
     // }}}
     // {{{ functions
-
-    var $arrErr;
-
-    var $arrTitle;
-
-    var $arrRowResult;
-
-    var $arrRowErr;
 
     /**
@@ -59,4 +74,9 @@
         $this->tpl_subno    = 'upload_csv_category';
         $this->tpl_subtitle = 'カテゴリ登録CSV';
+        $this->csv_id = '5';
+
+        $masterData = new SC_DB_MasterData_Ex();
+        $this->arrAllowedTag = $masterData->getMasterData("mtb_allowed_tag");
+        $this->arrTagCheckItem = array();
     }
 
@@ -77,22 +97,58 @@
      */
     function action() {
-        $objDb        = new SC_Helper_DB_Ex();
-        $objUpFile    = new SC_UploadFile_Ex(IMAGE_TEMP_REALDIR, IMAGE_SAVE_REALDIR);
+        // CSV管理ヘルパー
+        $objCSV = new SC_Helper_CSV_Ex();
+        // CSV構造読み込み
+        $arrCSVFrame = $objCSV->sfGetCsvOutput($this->csv_id);
+
+        // CSV構造がインポート可能かのチェック
+        if(!$objCSV->sfIsImportCSVFrame($arrCSVFrame) ) {
+            // 無効なフォーマットなので初期状態に強制変更
+            $arrCSVFrame = $objCSV->sfGetCsvOutput($this->csv_id, '', array(), 'no');
+            $this->tpl_is_format_default = true;
+        }
+        // CSV構造は更新可能なフォーマットかのフラグ取得
+        $this->tpl_is_update = $objCSV->sfIsUpdateCSVFrame($arrCSVFrame);
+
+        // CSVファイルアップロード情報の初期化
+        $objUpFile = new SC_UploadFile_Ex(IMAGE_TEMP_REALDIR, IMAGE_SAVE_REALDIR);
+        $this->lfInitFile($objUpFile);
+
+        // パラメータ情報の初期化
         $objFormParam = new SC_FormParam_Ex();
-
-        // ファイルオブジェクト初期化
-        $this->initFile($objUpFile);
-
-        // 入力パラメータ初期化
-        $this->initParam($objFormParam);
+        $this->lfInitParam($objFormParam, $arrCSVFrame);
+
         $objFormParam->setHtmlDispNameArray();
         $this->arrTitle = $objFormParam->getHtmlDispNameArray();
 
-        switch ($this->getMode()) {
+        switch($this->getMode()) {
         case 'csv_upload':
-            $this->doUploadCsv($objFormParam, $objUpFile, $objDb);
-        break;
+            $this->doUploadCsv($objFormParam, $objUpFile);
+            break;
         default:
-        }
+            break;
+        }
+    }
+
+    /**
+     * 登録/編集結果のメッセージをプロパティへ追加する
+     *
+     * @param integer $line_count 行数
+     * @param stirng $message メッセージ
+     * @return void
+     */
+    function addRowResult($line_count, $message) {
+        $this->arrRowResult[] = $line_count . "行目：" . $message;
+    }
+
+    /**
+     * 登録/編集結果のエラーメッセージをプロパティへ追加する
+     *
+     * @param integer $line_count 行数
+     * @param stirng $message メッセージ
+     * @return void
+     */
+    function addRowErr($line_count, $message) {
+        $this->arrRowErr[] = $line_count . "行目：" . $message;
     }
 
@@ -105,5 +161,5 @@
      * @return void
      */
-    function doUploadCsv(&$objFormParam, &$objUpFile, &$objDb) {
+    function doUploadCsv(&$objFormParam, &$objUpFile) {
         // ファイルアップロードのチェック
         $objUpFile->makeTempFile('csv_file');
@@ -113,5 +169,4 @@
             return;
         }
-
         // 一時ファイル名の取得
         $filepath = $objUpFile->getTempFilePath('csv_file');
@@ -125,4 +180,10 @@
         }
 
+        // 登録先テーブル カラム情報の初期化
+        $this->lfInitTableInfo();
+
+        // 登録フォーム カラム情報
+        $this->arrFormKeyList = $objFormParam->getKeyList();
+
         // 登録対象の列数
         $col_max_count = $objFormParam->getCount();
@@ -130,13 +191,13 @@
         $line_count = 0;
 
-        $objQuery = SC_Query_Ex::getSingletonInstance();
+        $objQuery =& SC_Query_Ex::getSingletonInstance();
         $objQuery->begin();
 
-        $errFlg = false;
+        $errFlag = false;
 
         while (!feof($fp)) {
-            $arrRow = fgetcsv($fp, CSV_LINE_MAX);
+            $arrCSV = fgetcsv($fp, CSV_LINE_MAX);
+            // 行カウント
             $line_count++;
-
             // ヘッダ行はスキップ
             if ($line_count == 1) {
@@ -144,109 +205,40 @@
             }
             // 空行はスキップ
-            if (empty($arrRow)) {
+            if (empty($arrCSV)) {
                 continue;
             }
             // 列数が異なる場合はエラー
-            $col_count = count($arrRow);
+            $col_count = count($arrCSV);
             if ($col_max_count != $col_count) {
-                $errFlg = true;
                 $this->addRowErr($line_count, "※ 項目数が" . $col_count . "個検出されました。項目数は" . $col_max_count . "個になります。");
+                $errFlag = true;
                 break;
             }
-            // 数値インデックスから, カラム名 => 値の連想配列へ変換
-            $objFormParam->setParam($arrRow, true);
-            $arrRow = $objFormParam->getHashArray();
-            $objFormParam->setParam($arrRow);
+            // シーケンス配列を格納する。
+            $objFormParam->setParam($arrCSV, true);
+            $arrRet = $objFormParam->getHashArray();
+            $objFormParam->setParam($arrRet);
+            // 入力値の変換
             $objFormParam->convParam();
-            // 入力項目チェック
-            $arrErr = $objFormParam->checkError();
-            if (count($arrErr) > 0) {
-                foreach ($arrErr as $err) {
+            // <br>なしでエラー取得する。
+            $arrCSVErr = $this->lfCheckError($objFormParam);
+
+            // 入力エラーチェック
+            if (count($arrCSVErr) > 0) {
+                foreach ($arrCSVErr as $err) {
                     $this->addRowErr($line_count, $err);
                 }
-                $errFlg = true;
+                $errFlag = true;
                 break;
             }
 
-            // 親カテゴリIDがない場合はルートのカテゴリIDをセット
-            if ($arrRow['parent_category_id'] == '') {
-                $arrRow['parent_category_id'] = 0;
-            }
-
-            // 親カテゴリIDの存在チェック
-            $count = $objQuery->count("dtb_category", "category_id = ?", array($arrRow['parent_category_id']));
-            if ($arrRow['parent_category_id'] != 0 && $count == 0) {
-                $errFlg = true;
-                $this->addRowErr($line_count, "指定の親カテゴリID(" . $arrRow['parent_category_id'] . ")は、存在しません。");
-                break;
-            }
-
-            $count = $objQuery->count("dtb_category", "category_id = ?", array($arrRow['category_id']));
-
-            // 編集
-            if ($count > 0) {
-                // 重複チェック
-                $where = "parent_category_id = ? AND category_id <> ? AND category_name = ?";
-                $count = $objQuery->count("dtb_category",
-                                $where,
-                                array($arrRow['parent_category_id'],
-                                      $arrRow['category_id'],
-                                      $arrRow['category_name']));
-                if ($count > 0) {
-                    $errFlg = true;
-                    $this->addRowErr($line_count, "既に同じ内容の登録が存在します。");
-                    break;
-                }
-
-                // カテゴリ更新
-                $arrCategory = array();
-                $arrCategory['category_name'] = $arrRow['category_name'];
-                $arrCategory['update_date'] = 'NOW()';
-                $where = "category_id = ?";
-                $objQuery->update("dtb_category", $arrCategory, $where, array($arrRow['category_id']));
-
-                $message = "[更新] カテゴリID: " . $arrRow['category_id'] . " カテゴリ名 : " . $arrRow['category_name'];
-                $this->addRowResult($line_count, $message);
-            // 登録
-            } else {
-                // 登録数上限チェック
-                $where = "del_flg = 0";
-                $count = $objQuery->count("dtb_category", $where);
-                if ($count >= CATEGORY_MAX) {
-                    $errFlg = true;
-                    $this->addRowErr($line_count, "カテゴリの登録最大数を超えました。");
-                    break;
-                }
-                // 階層上限チェック
-                if ($this->isOverLevel($arrRow['parent_category_id'])) {
-                    $errFlg = true;
-                    $this->addRowErr($line_count, LEVEL_MAX . "階層以上の登録はできません。");
-                    break;
-                }
-                // 重複チェック
-                $where = "parent_category_id = ? AND category_name = ?";
-                $count = $objQuery->count("dtb_category",
-                                $where,
-                                array($arrRow['parent_category_id'],
-                                      $arrRow['category_name']));
-                if ($count > 0) {
-                    $errFlg = true;
-                    $this->addRowErr($line_count, "既に同じ内容の登録が存在します。");
-                    break;
-                }
-                // カテゴリ登録
-                $this->registerCategory($arrRow['parent_category_id'],
-                                        $arrRow['category_name'],
-                                        $_SESSION['member_id']);
-
-                $message = "[登録] カテゴリ名 : " . $arrRow['category_name'];
-                $this->addRowResult($line_count, $message);
-            }
-        }
-
-        fclose($fp);
+            $category_id = $this->lfRegistCategory($objQuery, $line_count, $objFormParam);
+            $this->addRowResult($line_count, "カテゴリID：".$category_id . " / カテゴリ名：" . $objFormParam->getValue('category_name'));
+        }
 
         // 実行結果画面を表示
         $this->tpl_mainpage = 'products/upload_csv_category_complete.tpl';
+
+        fclose($fp);
 
         if ($errFlg) {
@@ -258,40 +250,6 @@
 
         // カテゴリ件数を更新
-        $objDb->sfCountCategory($objQuery);
-        $objDb->sfCountMaker($objQuery);
-    }
-
-    /**
-     * 登録/編集結果のメッセージをプロパティへ追加する
-     *
-     * @param integer $line_count 行数
-     * @param stirng $message メッセージ
-     * @return void
-     */
-    function addRowResult($line_count, $message) {
-        $this->arrRowResult[] = $line_count . "行目：" . $message;
-    }
-
-    /**
-     * 登録/編集結果のエラーメッセージをプロパティへ追加する
-     *
-     * @param integer $line_count 行数
-     * @param stirng $message メッセージ
-     * @return void
-     */
-    function addRowErr($line_count, $message) {
-        $this->arrRowErr[] = $line_count . "行目：" . $message;
-    }
-
-    /**
-     * カテゴリの階層が上限を超えているかを判定する
-     *
-     * @param integer 親カテゴリID
-     * @param 超えている場合 true
-     */
-    function isOverLevel($parent_category_id) {
-        $objQuery =& SC_Query_Ex::getSingletonInstance();
-        $level = $objQuery->get('level', "dtb_category", "category_id = ?", array($parent_category_id));
-        return $level >= LEVEL_MAX;
+        SC_Helper_DB_EX::sfCountCategory($objQuery);
+        return;
     }
 
@@ -310,5 +268,5 @@
      * @return void
      */
-    function initFile(&$objUpFile) {
+    function lfInitFile(&$objUpFile) {
         $objUpFile->addFile("CSVファイル", 'csv_file', array('csv'), CSV_SIZE, true, 0, 0, false);
     }
@@ -317,11 +275,216 @@
      * 入力情報の初期化を行う.
      *
-     * @param SC_FormParam $objFormParam 
-     * @return void
-     */
-    function initParam(&$objFormParam) {
-        $objFormParam->addParam("カテゴリID","category_id",INT_LEN,'n',array("MAX_LENGTH_CHECK","NUM_CHECK"));
-        $objFormParam->addParam("カテゴリ名","category_name",STEXT_LEN,'KVa',array("EXIST_CHECK","SPTAB_CHECK","MAX_LENGTH_CHECK"));
-        $objFormParam->addParam("親カテゴリID","parent_category_id",INT_LEN,'n',array("MAX_LENGTH_CHECK","NUM_CHECK"));
+     * @param array CSV構造設定配列
+     * @return void
+     */
+    function lfInitParam(&$objFormParam, &$arrCSVFrame) {
+        // 固有の初期値調整
+        $arrCSVFrame = $this->lfSetParamDefaultValue($arrCSVFrame);
+        // CSV項目毎の処理
+        foreach($arrCSVFrame as $item) {
+            if($item['status'] == CSV_COLUMN_STATUS_FLG_DISABLE) continue;
+            //サブクエリ構造の場合は AS名 を使用
+            if(preg_match_all('/\(.+\) as (.+)$/i', $item['col'], $match, PREG_SET_ORDER)) {
+                $col = $match[0][1];
+            }else{
+                $col = $item['col'];
+            }
+            // HTML_TAG_CHECKは別途実行なので除去し、別保存しておく
+            if(strpos(strtoupper($item['error_check_types']), 'HTML_TAG_CHECK') !== FALSE) {
+                $this->arrTagCheckItem[] = $item;
+                $error_check_types = str_replace('HTML_TAG_CHECK', '', $item['error_check_types']);
+            }else{
+                $error_check_types = $item['error_check_types'];
+            }
+            $arrErrorCheckTypes = explode(',', $error_check_types);
+            foreach($arrErrorCheckTypes as $key => $val) {
+                if(trim($val) == "") {
+                    unset($arrErrorCheckTypes[$key]);
+                }else{
+                    $arrErrorCheckTypes[$key] = trim($val);
+                }
+            }
+            // パラメーター登録
+            $objFormParam->addParam(
+                    $item['disp_name']
+                    , $col
+                    , constant($item['size_const_type'])
+                    , $item['mb_convert_kana_option']
+                    , $arrErrorCheckTypes
+                    , $item['default']
+                    , ($item['rw_flg'] != CSV_COLUMN_RW_FLG_READ_ONLY) ? true : false
+                    );
+        }
+    } 
+
+    /**
+     * 入力チェックを行う.
+     *
+     * @return void
+     */
+    function lfCheckError(&$objFormParam) {
+        // 入力データを渡す。
+        $arrRet =  $objFormParam->getHashArray();
+        $objErr = new SC_CheckError_Ex($arrRet);
+        $objErr->arrErr = $objFormParam->checkError(false);
+        // HTMLタグチェックの実行
+        foreach($this->arrTagCheckItem as $item) {
+            $objErr->doFunc(array( $item['disp_name'], $item['col'], $this->arrAllowedTag), array("HTML_TAG_CHECK"));
+        }
+        // このフォーム特有の複雑系のエラーチェックを行う
+        if(count($objErr->arrErr) == 0) {
+            $objErr->arrErr = $this->lfCheckErrorDetail($arrRet, $objErr->arrErr);
+        }
+        return $objErr->arrErr;
+    }
+
+    /**
+     * 保存先テーブル情報の初期化を行う.
+     *
+     * @return void
+     */
+    function lfInitTableInfo() {
+        $objQuery =& SC_Query_Ex::getSingletonInstance();
+        $this->arrRegistColumn = $objQuery->listTableFields('dtb_category');
+    }
+
+    /**
+     * カテゴリ登録を行う.
+     *
+     * FIXME: 登録の実処理自体は、LC_Page_Admin_Products_Categoryと共通化して欲しい。
+     *
+     * @param SC_Query $objQuery SC_Queryインスタンス
+     * @param string|integer $line 処理中の行数
+     * @return integer カテゴリID
+     */
+    function lfRegistCategory($objQuery, $line, &$objFormParam) {
+        // 登録データ対象取得
+        $arrList = $objFormParam->getHashArray();
+        // 登録時間を生成(DBのnow()だとcommitした際、すべて同一の時間になってしまう)
+        $arrList['update_date'] = $this->lfGetDbFormatTimeWithLine($line);
+
+        // 登録情報を生成する。
+        // テーブルのカラムに存在しているもののうち、Form投入設定されていないデータは上書きしない。
+        $sqlval = SC_Utils_Ex::sfArrayIntersectKeys($arrList, $this->arrRegistColumn);
+
+        // 必須入力では無い項目だが、空文字では問題のある特殊なカラム値の初期値設定
+        $sqlval = $this->lfSetCategoryDefaultData($sqlval);
+
+        if($sqlval['category_id'] != "") {
+            // UPDATEの実行
+            $where = "category_id = ?";
+            $objQuery->update("dtb_category", $sqlval, $where, array($sqlval['category_id']));
+            $category_id = $sqlval['category_id'];
+            // TODO: 削除時処理
+        }else{
+            // 新規登録
+            $category_id = $this->registerCategory($sqlval['parent_category_id'],
+                                        $sqlval['category_name'],
+                                        $_SESSION['member_id']);
+        }
+        return $category_id;
+    }
+
+    /**
+     * 初期値の設定
+     *
+     * @param array $arrCSVFrame CSV構造配列
+     * @return array $arrCSVFrame CSV構造配列
+     */
+    function lfSetParamDefaultValue(&$arrCSVFrame) {
+        foreach($arrCSVFrame as $key => $val) {
+            switch($val['col']) {
+                case 'parent_category_id':
+                    $arrCSVFrame[$key]['default'] = '0';
+                    break;
+                case 'del_flg':
+                    $arrCSVFrame[$key]['default'] = '0';
+                    break;
+                default:
+                    break;
+            }
+        }
+        return $arrCSVFrame;
+    }
+
+    /**
+     * データ登録前に特殊な値の持ち方をする部分のデータ部分の初期値補正を行う
+     *
+     * @param array $sqlval 商品登録情報配列
+     * @return $sqlval 登録情報配列
+     */
+    function lfSetCategoryDefaultData(&$sqlval) {
+        if($sqlval['del_flg'] == ""){
+            $sqlval['del_flg'] = '0'; //有効
+        }
+        if($sqlval['creator_id'] == "") {
+            $sqlval['creator_id'] = $_SESSION['member_id'];
+        }
+        if($sqlval['parent_category_id'] == "") {
+            $sqlval['parent_category_id'] = (string)"0";
+        }
+        return $sqlval;
+    }
+
+    /**
+     * このフォーム特有の複雑な入力チェックを行う.
+     *
+     * @param array 確認対象データ
+     * @param array エラー配列
+     * @return array エラー配列
+     */
+    function lfCheckErrorDetail($item, $arrErr) {
+        $objQuery =& SC_Query_Ex::getSingletonInstance();
+        // カテゴリIDの存在チェック
+        if(!$this->lfIsDbRecord('dtb_category', 'category_id', $item)) {
+            $arrErr['category_id'] = "※ 指定のカテゴリIDは、登録されていません。";
+        }
+        // 親カテゴリIDの存在チェック
+        if(array_search('parent_category_id', $this->arrFormKeyList) !== FALSE
+                and $item['parent_category_id'] != ""
+                and $item['parent_category_id'] != "0"
+                and !SC_Helper_DB_Ex::sfIsRecord('dtb_category', 'category_id', array($item['parent_category_id']))
+                ) {
+            $arrErr['parent_category_id'] = "※ 指定の親カテゴリID(" . $item['parent_category_id'] . ")は、存在しません。";
+        }
+        // 削除フラグのチェック
+        if(array_search('del_flg', $this->arrFormKeyList) !== FALSE
+                and $item['del_flg'] != "") {
+            if(!($item['del_flg'] == "0" or $item['del_flg'] == "1")) {
+                $arrErr['del_flg'] = "※ 削除フラグは「0」(有効)、「1」(削除)のみが有効な値です。";
+            }
+        }
+        // 重複チェック 同じカテゴリ内に同名の存在は許可されない
+        if(array_search('category_name', $this->arrFormKeyList) !== FALSE
+                and $item['category_name'] != "") {
+            $parent_category_id = $item['parent_category_id'];
+            if($parent_category_id == '') {
+                $parent_category_id = (string)'0';
+            }
+            $where = "parent_category_id = ? AND category_id <> ? AND category_name = ?";
+            $count = $objQuery->count('dtb_category',
+                        $where,
+                        array($parent_category_id,
+                                $item['category_id'],
+                                $item['category_name']));
+            if($count > 0) {
+                $arrErr['category_name'] = "※ 既に同名のカテゴリが存在します。";
+            }
+        }
+        // 登録数上限チェック
+        $where = "del_flg = 0";
+        $count = $objQuery->count("dtb_category", $where);
+        if ($count >= CATEGORY_MAX) {
+            $item['category_name'] = "※ カテゴリの登録最大数を超えました。";
+        }
+        // 階層上限チェック
+        if (array_search('parent_category_id', $this->arrFormKeyList) !== FALSE
+                and $item['parent_category_id'] != "") {
+            $level = $objQuery->get('level', "dtb_category", "category_id = ?", array($parent_category_id));
+            if($level >= LEVEL_MAX) {
+                $arrErr['parent_category_id'] = "※ " . LEVEL_MAX . "階層以上の登録はできません。";
+            }
+        }
+        return $arrErr;
     }
 
@@ -332,5 +495,5 @@
      * @param string カテゴリ名
      * @param integer 作成者のID
-     * @return void
+     * @return integer カテゴリID
      */
     function registerCategory($parent_category_id, $category_name, $creator_id) {
@@ -365,4 +528,41 @@
         $arrCategory['category_id'] = $objQuery->nextVal('dtb_category_category_id');
         $objQuery->insert("dtb_category", $arrCategory);
-    }
+        return $arrCategory['category_id'];
+    }
+
+    /**
+     * 指定された行番号をmicrotimeに付与してDB保存用の時間を生成する。
+     * トランザクション内のnow()は全てcommit()時の時間に統一されてしまう為。
+     *
+     * @param string $line_no 行番号
+     * @return string $time DB保存用の時間文字列
+     */
+    function lfGetDbFormatTimeWithLine($line_no = '') {
+        $time = date("Y-m-d H:i:s");
+        // 秒以下を生成
+        if($line_no != '') {
+            $microtime = sprintf("%06d", $line_no);
+            $time .= ".$microtime";
+        }
+        return $time;
+    }
+
+    /**
+     * 指定されたキーと値の有効性のDB確認
+     *
+     * @param string $table テーブル名
+     * @param string $keyname キー名
+     * @param array  $item 入力データ配列
+     * @return boolean true:有効なデータがある false:有効ではない
+     */
+    function lfIsDbRecord($table, $keyname, $item) {
+        if(array_search($keyname, $this->arrFormKeyList) !== FALSE  //入力対象である
+                and $item[$keyname] != ""   // 空ではない
+                and !SC_Helper_DB_EX::sfIsRecord($table, $keyname, (array)$item[$keyname]) //DBに存在するか
+                ) {
+            return false;
+        }
+        return true;
+    }
+
 }
