source: branches/feature-module-update/data/class/pages/admin/products/LC_Page_Admin_Products_UploadCSV.php @ 15551

Revision 15551, 21.6 KB checked in by nanasess, 17 years ago (diff)

CSV アップロード関連の修正

  • Property svn:keywords set to Id Revision Date
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2/*
3 * Copyright(c) 2000-2007 LOCKON CO.,LTD. All Rights Reserved.
4 *
5 * http://www.lockon.co.jp/
6 */
7
8// {{{ requires
9require_once(CLASS_PATH . "pages/LC_Page.php");
10
11/**
12 * CSV アップロード のページクラス.
13 *
14 * :XXX: 要テスト
15 *
16 * @package Page
17 * @author LOCKON CO.,LTD.
18 * @version $Id:LC_Page_Admin_Products_UploadCSV.php 15532 2007-08-31 14:39:46Z nanasess $
19 */
20class LC_Page_Admin_Products_UploadCSV extends LC_Page {
21
22    // }}}
23    // {{{ functions
24
25    /** フォームパラメータ */
26    var $objFormParam;
27
28    /** SC_UploadFile インスタンス */
29    var $objUpfile;
30
31    /**
32     * Page を初期化する.
33     *
34     * @return void
35     */
36    function init() {
37        parent::init();
38        $this->tpl_mainpage = 'products/upload_csv.tpl';
39        $this->tpl_subnavi = 'products/subnavi.tpl';
40        $this->tpl_mainno = 'products';
41        $this->tpl_subno = 'upload_csv';
42    }
43
44    /**
45     * Page のプロセス.
46     *
47     * @return void
48     */
49    function process() {
50        $conn = new SC_DBConn();
51        $objView = new SC_AdminView();
52        $objSess = new SC_Session();
53        $objDb = new SC_Helper_DB_Ex();
54
55        // 認証可否の判定
56        SC_Utils_Ex::sfIsSuccess($objSess);
57
58        // ファイル管理クラス
59        $this->objUpFile = new SC_UploadFile(IMAGE_TEMP_DIR, IMAGE_SAVE_DIR);
60        // ファイル情報の初期化
61        $this->lfInitFile();
62        // パラメータ管理クラス
63        $this->objFormParam = new SC_FormParam();
64        // パラメータ情報の初期化
65        $this->lfInitParam();
66        $colmax = $this->objFormParam->getCount();
67        $this->objFormParam->setHtmlDispNameArray();
68        $this->arrTitle = $this->objFormParam->getHtmlDispNameArray();
69
70        if (!isset($_POST['mode'])) $_POST['mode'] = "";
71
72        switch($_POST['mode']) {
73        case 'csv_upload':
74            $err = false;
75            // エラーチェック
76            $arrErr['csv_file'] = $this->objUpFile->makeTempFile('csv_file');
77
78            if($arrErr['css_file'] == "") {
79                $arrErr = $this->objUpFile->checkEXISTS();
80            }
81
82            // 実行時間を制限しない
83            set_time_limit(0);
84
85            // 出力をバッファリングしない(==日本語自動変換もしない)
86            ob_end_clean();
87
88            // IEのために256バイト空文字出力
89            echo str_pad('',256);
90
91            if(empty($arrErr['csv_file'])) {
92                // 一時ファイル名の取得
93                $filepath = $this->objUpFile->getTempFilePath('csv_file');
94                // エンコード
95                $enc_filepath = SC_Utils_Ex::sfEncodeFile($filepath,
96                                                          CHAR_CODE, CSV_TEMP_DIR);
97
98                // レコード数を得る
99                $rec_count = $this->lfCSVRecordCount($enc_filepath);
100
101                $fp = fopen($enc_filepath, "r");
102                $line = 0;      // 行数
103                $regist = 0;    // 登録数
104
105                $objQuery = new SC_Query();
106                $objQuery->begin();
107
108                echo "■ CSV登録進捗状況 <br/><br/>\n";
109
110                while(!feof($fp) && !$err) {
111                    $arrCSV = fgetcsv($fp, CSV_LINE_MAX);
112
113                    // 行カウント
114                    $line++;
115
116                    if($line <= 1) {
117                        continue;
118                    }
119
120                    // 項目数カウント
121                    $max = count($arrCSV);
122
123                    // 項目数が1以下の場合は無視する
124                    if($max <= 1) {
125                        continue;
126                    }
127
128                    // 項目数チェック
129                    if($max != $colmax) {
130                        echo "※ 項目数が" . $max . "個検出されました。項目数は" . $colmax . "個になります。</br>\n";
131                        $err = true;
132                    } else {
133                        // シーケンス配列を格納する。
134                        $this->objFormParam->setParam($arrCSV, true);
135                        $arrRet = $this->objFormParam->getHashArray();
136                        $this->objFormParam->setParam($arrRet);
137                        // 入力値の変換
138                        $this->objFormParam->convParam();
139                        // <br>なしでエラー取得する。
140                        $arrCSVErr = $this->lfCheckError();
141                    }
142
143                    // 入力エラーチェック
144                    if(count($arrCSVErr) > 0) {
145                        echo "<font color=\"red\">■" . $line . "行目でエラーが発生しました。</font></br>\n";
146                        foreach($arrCSVErr as $val) {
147                            $this->printError($val);
148                        }
149                        $err = true;
150                    }
151
152                    if(!$err) {
153                        $this->lfRegistProduct($objQuery, $line);
154                        $regist++;
155                    }
156                    $arrParam = $this->objFormParam->getHashArray();
157
158                    if(!$err) echo $line." / ".$rec_count. "行目 (商品ID:".$arrParam['product_id']." / 商品名:".$arrParam['name'].")\n<br />";
159                    flush();
160                }
161                fclose($fp);
162
163                if(!$err) {
164                    $objQuery->commit();
165                    echo "■" . $regist . "件のレコードを登録しました。";
166                    // 商品件数カウント関数の実行
167                    $objDb->sfCategory_Count($objQuery);
168                } else {
169                    $objQuery->rollback();
170                }
171            } else {
172                foreach($arrErr as $val) {
173                    $this->printError($val);
174                }
175            }
176            echo "<br/><a href=\"javascript:window.close()\">→閉じる</a>";
177            flush();
178            exit;
179            break;
180        default:
181            break;
182        }
183
184        $objView->assignobj($this);
185        $objView->display(MAIN_FRAME);
186    }
187
188    /**
189     * デストラクタ.
190     *
191     * @return void
192     */
193    function destroy() {
194        parent::destroy();
195    }
196
197
198    /**
199     * ファイル情報の初期化を行う.
200     *
201     * @return void
202     */
203    function lfInitFile() {
204        $this->objUpFile->addFile("CSVファイル", 'csv_file', array('csv'),
205                                  CSV_SIZE, true, 0, 0, false);
206    }
207
208    /**
209     * 入力情報の初期化を行う.
210     *
211     * @return void
212     */
213    function lfInitParam() {
214
215        $this->objFormParam->addParam("商品ID", "product_id", INT_LEN, "n", array("MAX_LENGTH_CHECK","NUM_CHECK"));
216        $this->objFormParam->addParam("商品規格ID", "product_class_id", INT_LEN, "n", array("MAX_LENGTH_CHECK","NUM_CHECK"));
217
218        $this->objFormParam->addParam("規格名1", "dummy1");
219        $this->objFormParam->addParam("規格名2", "dummy2");
220
221        $this->objFormParam->addParam("商品名", "name", STEXT_LEN, "KVa", array("EXIST_CHECK","SPTAB_CHECK","MAX_LENGTH_CHECK"));
222        $this->objFormParam->addParam("公開フラグ(1:公開 2:非公開)", "status", INT_LEN, "n", array("EXIST_CHECK","MAX_LENGTH_CHECK","NUM_CHECK"));
223        $this->objFormParam->addParam("商品ステータス", "product_flag", INT_LEN, "n", array("EXIST_CHECK","MAX_LENGTH_CHECK","NUM_CHECK"));
224        $this->objFormParam->addParam("商品コード", "product_code", STEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
225        $this->objFormParam->addParam(NORMAL_PRICE_TITLE, "price01", PRICE_LEN, "n", array("MAX_LENGTH_CHECK","NUM_CHECK"));
226        $this->objFormParam->addParam(SALE_PRICE_TITLE, "price02", PRICE_LEN, "n", array("EXIST_CHECK","MAX_LENGTH_CHECK","NUM_CHECK"));
227        $this->objFormParam->addParam("在庫数", "stock", INT_LEN, "n", array("MAX_LENGTH_CHECK","NUM_CHECK"));
228        $this->objFormParam->addParam("送料", "deliv_fee", PRICE_LEN, "n", array("MAX_LENGTH_CHECK","NUM_CHECK"));
229        $this->objFormParam->addParam("ポイント付与率", "point_rate", PERCENTAGE_LEN, "n", array("EXIST_CHECK","MAX_LENGTH_CHECK","NUM_CHECK"));
230        $this->objFormParam->addParam("購入制限", "sale_limit", INT_LEN, "n", array("MAX_LENGTH_CHECK","NUM_CHECK"));
231        $this->objFormParam->addParam("メーカーURL", "comment1", URL_LEN, "KVa", array("SPTAB_CHECK","URL_CHECK","MAX_LENGTH_CHECK"));
232        $this->objFormParam->addParam("検索ワード", "comment3", LLTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
233        $this->objFormParam->addParam("一覧-メインコメント", "main_list_comment", LTEXT_LEN, "KVa", array("EXIST_CHECK","SPTAB_CHECK","MAX_LENGTH_CHECK"));
234        $this->objFormParam->addParam("一覧-メイン画像", "main_list_image", LTEXT_LEN, "KVa", array("EXIST_CHECK","FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
235        $this->objFormParam->addParam("メインコメント", "main_comment", LTEXT_LEN, "KVa", array("EXIST_CHECK","SPTAB_CHECK","MAX_LENGTH_CHECK"));
236        $this->objFormParam->addParam("メイン画像", "main_image", LTEXT_LEN, "KVa", array("EXIST_CHECK","FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
237        $this->objFormParam->addParam("メイン拡大画像", "main_large_image", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
238        $this->objFormParam->addParam("カラー比較画像", "file1", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
239        $this->objFormParam->addParam("商品詳細ファイル", "file2", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
240        $this->objFormParam->addParam("詳細-サブタイトル(1)", "sub_title1", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
241        $this->objFormParam->addParam("詳細-サブコメント(1)", "sub_comment1", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
242        $this->objFormParam->addParam("詳細-サブ画像(1)", "sub_image1", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
243        $this->objFormParam->addParam("詳細-サブ拡大画像(1)", "sub_large_image1", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
244
245        $this->objFormParam->addParam("詳細-サブタイトル(2)", "sub_title2", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
246        $this->objFormParam->addParam("詳細-サブコメント(2)", "sub_comment2", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
247        $this->objFormParam->addParam("詳細-サブ画像(2)", "sub_image2", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
248        $this->objFormParam->addParam("詳細-サブ拡大画像(2)", "sub_large_image2", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
249
250        $this->objFormParam->addParam("詳細-サブタイトル(3)", "sub_title3", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
251        $this->objFormParam->addParam("詳細-サブコメント(3)", "sub_comment3", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
252        $this->objFormParam->addParam("詳細-サブ画像(3)", "sub_image3", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
253        $this->objFormParam->addParam("詳細-サブ拡大画像(3)", "sub_large_image3", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
254
255        $this->objFormParam->addParam("詳細-サブタイトル(4)", "sub_title4", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
256        $this->objFormParam->addParam("詳細-サブコメント(4)", "sub_comment4", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
257        $this->objFormParam->addParam("詳細-サブ画像(4)", "sub_image4", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
258        $this->objFormParam->addParam("詳細-サブ拡大画像(4)", "sub_large_image4", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
259
260        $this->objFormParam->addParam("詳細-サブタイトル(5)", "sub_title5", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
261        $this->objFormParam->addParam("詳細-サブコメント(5)", "sub_comment5", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
262        $this->objFormParam->addParam("詳細-サブ画像(5)", "sub_image5", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
263        $this->objFormParam->addParam("詳細-サブ拡大画像(5)", "sub_large_image5", LTEXT_LEN, "KVa", array("FILE_EXISTS","SPTAB_CHECK","MAX_LENGTH_CHECK"));
264
265        $this->objFormParam->addParam("発送日目安", "deliv_date_id", INT_LEN, "n", array("MAX_LENGTH_CHECK","NUM_CHECK"));
266
267        for ($cnt = 1; $cnt <= RECOMMEND_PRODUCT_MAX; $cnt++) {
268            $this->objFormParam->addParam("おすすめ商品($cnt)", "recommend_product_id$cnt", INT_LEN, "n", array("MAX_LENGTH_CHECK","NUM_CHECK"));
269            $this->objFormParam->addParam("詳細-サブコメント($cnt)", "recommend_comment$cnt", LTEXT_LEN, "KVa", array("SPTAB_CHECK","MAX_LENGTH_CHECK"));
270        }
271
272        $this->objFormParam->addParam("商品カテゴリ", "category_id", STEXT_LEN, "n", array("EXIST_CHECK", "SPTAB_CHECK", "MAX_LENGTH_CHECK"));
273    }
274
275    /**
276     * 商品登録を行う.
277     *
278     * @param SC_Query $objQuery SC_Queryインスタンス
279     * @param string|integer $line 処理中の行数
280     * @return void
281     */
282    function lfRegistProduct($objQuery, $line = "") {
283
284        $objDb = new SC_Helper_DB_Ex();
285
286        $arrRet = $this->objFormParam->getHashArray();
287
288        // dtb_products以外に登録される値を除外する。
289        foreach($arrRet as $key => $val) {
290            switch($key) {
291            case 'product_code':
292            case 'price01':
293            case 'price02':
294            case 'stock':
295            case 'product_class_id':
296            case 'recommend_product_id1':
297            case 'recommend_product_id2':
298            case 'recommend_product_id3':
299            case 'recommend_product_id4':
300            case 'recommend_product_id5':
301            case 'recommend_product_id6':
302            case 'recommend_comment1':
303            case 'recommend_comment2':
304            case 'recommend_comment3':
305            case 'recommend_comment4':
306            case 'recommend_comment5':
307            case 'recommend_comment6':
308                break;
309            default:
310                if(!ereg("^dummy", $key)) {
311                    $sqlval[$key] = $val;
312                }
313                break;
314            }
315        }
316        // 登録時間を生成(DBのnow()だとcommitした際、すべて同一の時間になってしまう)
317        $time = date("Y-m-d H:i:s");
318        // 秒以下を生成
319        if($line != "") {
320            $microtime = sprintf("%06d", $line);
321            $time .= ".$microtime";
322        }
323        $sqlval['update_date'] = $time;
324        $sqlval['creator_id'] = $_SESSION['member_id'];
325
326        if($sqlval['sale_limit'] == "") {
327            $sqlval['sale_unlimited'] = '1';
328        } else {
329            $sqlval['sale_unlimited'] = '0';
330        }
331
332        if($sqlval['status'] == "") {
333            $sqlval['status'] = 2;
334        }
335
336        if($arrRet['product_id'] != "" && $arrRet['product_class_id'] != "") {
337            // カテゴリ内ランクの調整処理
338            $old_catid = $objQuery->get("dtb_products", "category_id", "product_id = ?", array($arrRet['product_id']));
339            $objDb->sfMoveCatRank($objQuery, "dtb_products", "product_id", "category_id", $old_catid, $arrRet['category_id'], $arrRet['product_id']);
340
341            // UPDATEの実行
342            $where = "product_id = ?";
343            $objQuery->update("dtb_products", $sqlval, $where, array($sqlval['product_id']));
344        } else {
345
346            // 新規登録
347            // postgresqlとmysqlとで処理を分ける
348            if (DB_TYPE == "pgsql") {
349                $product_id = $objQuery->nextval("dtb_products","product_id");
350            }elseif (DB_TYPE == "mysql") {
351                $product_id = $objQuery->get_auto_increment("dtb_products");
352            }
353            $sqlval['product_id'] = $product_id;
354            $sqlval['create_date'] = $time;
355
356            // カテゴリ内で最大のランクを割り当てる
357            $sqlval['rank'] = $objQuery->max("dtb_products", "rank", "category_id = ?", array($arrRet['category_id'])) + 1;
358
359            // INSERTの実行
360            $objQuery->insert("dtb_products", $sqlval);
361        }
362
363        // 規格登録
364        $this->lfRegistProductClass($objQuery, $arrRet, $sqlval['product_id'], $arrRet['product_class_id']);
365
366        // おすすめ商品登録
367        $objQuery->delete("dtb_recommend_products", "product_id = ?", array($sqlval['product_id']));
368        for($i = 1; $i <= RECOMMEND_PRODUCT_MAX; $i++) {
369            $keyname = "recommend_product_id" . $i;
370            $comment_key = "recommend_comment" . $i;
371            if($arrRet[$keyname] != "") {
372                $arrProduct = $objQuery->select("product_id", "dtb_products", "product_id = ?", array($arrRet[$keyname]));
373                if($arrProduct[0]['product_id'] != "") {
374                    $arrval['product_id'] = $sqlval['product_id'];
375                    $arrval['recommend_product_id'] = $arrProduct[0]['product_id'];
376                    $arrval['comment'] = $arrRet[$comment_key];
377                    $arrval['update_date'] = "Now()";
378                    $arrval['create_date'] = "Now()";
379                    $arrval['creator_id'] = $_SESSION['member_id'];
380                    $arrval['rank'] = RECOMMEND_PRODUCT_MAX - $i + 1;
381                    $objQuery->insert("dtb_recommend_products", $arrval);
382                }
383            }
384        }
385    }
386
387    /**
388     * 商品規格登録を行う.
389     *
390     * @param SC_Query $objQuery SC_Queryインスタンス
391     * @param array $arrList 商品規格情報配列
392     * @param integer $product_id 商品ID
393     * @param integer $product_class_id 商品規格ID
394     * @return void
395     */
396    function lfRegistProductClass($objQuery, $arrList, $product_id, $product_class_id) {
397        $sqlval['product_code'] = $arrList["product_code"];
398        $sqlval['stock'] = $arrList["stock"];
399        if($sqlval['stock'] == "") {
400            $sqlval['stock_unlimited'] = '1';
401        } else {
402            $sqlval['stock_unlimited'] = '0';
403        }
404        $sqlval['price01'] = $arrList['price01'];
405        $sqlval['price02'] = $arrList['price02'];
406        $sqlval['creator_id'] = $_SESSION['member_id'];
407
408        // FIXME $sqlval['member_id'] は何処から出てくる?
409        if($sqlval['member_id'] == "") {
410            $sqlval['creator_id'] = '0';
411        }
412
413        if($product_class_id == "") {
414            // 新規登録
415            $where = "product_id = ?";
416            // 念のために既存の規格を削除
417            $objQuery->delete("dtb_products_class", $where, array($product_id));
418            $sqlval['product_id'] = $product_id;
419            $sqlval['classcategory_id1'] = '0';
420            $sqlval['classcategory_id2'] = '0';
421            $sqlval['create_date'] = "now()";
422            $objQuery->insert("dtb_products_class", $sqlval);
423        } else {
424            // 既存編集
425            $where = "product_id = ? AND product_class_id = ?";
426            $objQuery->update("dtb_products_class", $sqlval, $where, array($product_id, $product_class_id));
427        }
428    }
429
430    /**
431     * 入力チェックを行う.
432     *
433     * @return void
434     */
435    function lfCheckError() {
436
437        // 入力データを渡す。
438        $arrRet =  $this->objFormParam->getHashArray();
439        $objErr = new SC_CheckError($arrRet);
440        $objErr->arrErr = $this->objFormParam->checkError(false);
441
442        if(count($objErr->arrErr) == 0) {
443            $objQuery = new SC_Query();
444            // 商品ID、規格IDの存在チェック
445            if($arrRet['product_id'] != "") {
446                $count = $objQuery->count("dtb_products", "product_id = ?", array($arrRet['product_id']));
447                if($count == 0) {
448                    $objErr->arrErr['product_id'] = "※ 指定の商品IDは、登録されていません。";
449                }
450            }
451
452            if($arrRet['product_class_id'] != "") {
453                $count = 0;
454                if($arrRet['product_id'] != "") {
455                    $count = $objQuery->count("dtb_products_class", "product_id = ? AND product_class_id = ?", array($arrRet['product_id'], $arrRet['product_class_id']));
456                }
457                if($count == 0) {
458                    $objErr->arrErr['product_class_id'] = "※ 指定の規格IDは、登録されていません。";
459                }
460            }
461
462            // 存在するカテゴリIDかチェック
463            $count = $objQuery->count("dtb_category", "category_id = ?", array($arrRet['category_id']));
464            if($count == 0) {
465                $objErr->arrErr['product_id'] = "※ 指定のカテゴリIDは、登録されていません。";
466            }
467        }
468        return $objErr->arrErr;
469    }
470
471    /**
472     * CSVのカウント数を得る.
473     *
474     * @param string $file_name ファイルパス
475     * @return integer CSV のカウント数
476     */
477    function lfCSVRecordCount($file_name) {
478
479        $count = 0;
480        $fp = fopen($file_name, "r");
481        while(!feof($fp)) {
482            $arrCSV = fgetcsv($fp, CSV_LINE_MAX);
483            $count++;
484        }
485
486        return $count-1;
487    }
488
489    /**
490     * 引数の文字列をエラー出力する.
491     *
492     * 引数 $val の内容は, htmlspecialchars() によってサニタイズされる
493     *
494     * @param string $val 出力する文字列
495     * @return void
496     */
497    function printError($val) {
498         echo "<font color=\"red\">"
499             . htmlspecialchars($val, ENT_QUOTES)
500             . "</font></br>\n";
501    }
502}
503?>
Note: See TracBrowser for help on using the repository browser.