source: branches/version-2_5-dev/data/class/helper/SC_Helper_CSV.php @ 19746

Revision 19746, 16.8 KB checked in by AMUAMU, 11 years ago (diff)

#652 (CSVダウンロードの改善) 商品CSVダウンロード修正。
#582 category_id が末尾に移動される不具合 の解決。
r19742 で発生したWarningの除去

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2  /*
3   * Copyright(c) 2000-2010 LOCKON CO.,LTD. All Rights Reserved.
4   *
5   * http://www.lockon.co.jp/
6   */
7
8  /**
9   * CSV 関連 のヘルパークラス.
10   *
11   * @package Page
12   * @author LOCKON CO.,LTD.
13   * @version $Id$
14   */
15class SC_Helper_CSV {
16
17    // {{{ properties
18
19    /** 項目英名 */
20    var $arrSubnavi;
21
22    /** 項目名 */
23    var $arrSubnaviName;
24
25    /** レビュー管理項目 */
26    var $arrREVIEW_CVSCOL;
27
28    /** レビュータイトル */
29    var $arrREVIEW_CVSTITLE;
30
31    /** トラックバック項目 */
32    var $arrTRACKBACK_CVSCOL;
33
34    /** トラックバックタイトル */
35    var $arrTRACKBACK_CVSTITLE;
36
37
38    // }}}
39    // {{{ constructor
40
41    /**
42     * デフォルトコンストラクタ.
43     */
44    function SC_Helper_CSV() {
45        $this->init();
46
47        $masterData = new SC_DB_MasterData_Ex();
48        $this->arrPref = $masterData->getMasterData("mtb_pref",
49                                  array("pref_id", "pref_name", "rank"));
50        $this->arrSex = $masterData->getMasterData("mtb_sex");
51        $this->arrDISP = $masterData->getMasterData("mtb_disp");
52        $this->arrRECOMMEND = $masterData->getMasterData("mtb_recommend");
53    }
54
55    // }}}
56    // {{{ functions
57
58    /**
59     * CSV 項目を出力する.
60     *
61     * @param integer $csv_id CSV ID
62     * @param string $where SQL の WHERE 句
63     * @param array $arrVal WHERE 句の要素
64     * @return array CSV 項目の配列
65     */
66    function sfgetCsvOutput($csv_id = "", $where = '0=0', $arrVal = array()){
67        $objQuery = new SC_Query();
68        $ret = array();
69
70        $sql = <<< __EOS__
71            SELECT
72                no,
73                csv_id,
74                col,
75                disp_name,
76                rank,
77                status,
78                create_date,
79                update_date,
80                mb_convert_kana_option
81            FROM
82                dtb_csv
83__EOS__;
84
85        if (strlen($csv_id) >= 1) {
86            $where = "($where) AND csv_id = ?";
87            $arrVal[] = $csv_id;
88        }
89
90        if (strlen($where) >= 1) {
91            $sql .= " WHERE $where";
92        }
93
94        $sql .= " ORDER BY ";
95        $sql .= "     rank , no";
96        $sql .= " ";
97
98        $ret = $objQuery->getAll($sql, $arrVal);
99
100        return $ret;
101    }
102
103    // CSVを送信する。(共通。現状は受注のみ利用。)
104    function sfDownloadCsv($csv_id, $where, $arrval, $order) {
105        switch ($csv_id) {
106            case 3: // 受注
107                $from = 'dtb_order';
108                break;
109        }
110
111        // CSV出力タイトル行の作成
112        $arrCsvOutput = SC_Utils_Ex::sfSwapArray($this->sfgetCsvOutput($csv_id, 'status = 1'));
113
114        if (count($arrCsvOutput) <= 0) break;
115
116        $arrCsvOutputCols = $arrCsvOutput['col'];
117        $arrCsvOutputConvs = $arrCsvOutput['conv'];
118        $arrCsvOutputTitle = $arrCsvOutput['disp_name'];
119        $head = SC_Utils_Ex::sfGetCSVList($arrCsvOutputTitle);
120        $data = $objCSV->lfGetCSV("dtb_order", $where, $option, $arrval, $arrCsvOutputCols, $arrCsvOutputConvs);
121    }
122   
123    //  CSV作成 コールバック関数
124    function cbOutputProductCSV($data) {
125        $line = $this->sfArrayToCSV($data);
126        $line = mb_convert_encoding($line, 'SJIS-Win');
127        $line .= "\r\n";
128        fwrite($this->fpOutput, $line);
129        return true;
130    }
131
132    // CSVを送信する。(商品)
133    function sfDownloadProductsCsv($where, $arrval, $order, $is_download = false) {
134        // 実行時間を制限しない
135        @set_time_limit(0);
136
137        // CSV出力タイトル行の作成
138        $arrOutput = SC_Utils_Ex::sfSwapArray($this->sfgetCsvOutput(1, 'status = 1'));
139        if (count($arrOutput) <= 0) return false; // 失敗終了
140        $arrOutputCols = $arrOutput['col'];
141
142        $objQuery = new SC_Query();
143        $objQuery->setOrder($order);
144       
145        $objProduct = new SC_Product();
146        $cols = SC_Utils_Ex::sfGetCommaList($arrOutputCols, true);
147        $sql = $objQuery->getSql($cols, $objProduct->prdclsSQL(),$where);
148        $header = $this->sfArrayToCSV($arrOutput['disp_name']);
149        $header = mb_convert_encoding($header, 'SJIS-Win');
150        $header .= "\r\n";
151       
152        //テンポラリファイル作成
153        // TODO: パフォーマンス向上には、ストリームを使うようにすると良い
154        //  環境要件がバージョン5.1以上になったら使うように変えても良いかと
155        //  fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
156        $tmp_filename = tempnam(CSV_TEMP_DIR, 'product_csv');
157        $this->fpOutput = fopen($tmp_filename, "w+");
158
159        fwrite($this->fpOutput, $header);
160
161        $objQuery->doCallbackAll(array(&$this, 'cbOutputProductCSV'), $sql, $arrval);
162
163        fclose($this->fpOutput);
164
165        if($is_download) {
166            // CSVを送信する。
167            $this->lfDownloadCSVFile($tmp_filename,"product_");
168            $res = true;
169        }else{
170            $res = SC_Utils_Ex::sfReadFile($tmp_filename);
171        }
172       
173        //テンポラリファイル削除
174        unlink($tmp_filename);
175        return $res;
176    }
177
178    // CSV出力データを作成する。(レビュー)
179    function lfGetReviewCSV($where, $option, $arrval) {
180
181        $from = "dtb_review AS A INNER JOIN dtb_products AS B on A.product_id = B.product_id ";
182        $cols = SC_Utils_Ex::sfGetCommaList($this->arrREVIEW_CVSCOL);
183
184        $objQuery = new SC_Query();
185        $objQuery->setOption($option);
186
187        $list_data = $objQuery->select($cols, $from, $where, $arrval);
188
189        $max = count($list_data);
190        if (!isset($data)) $data = "";
191        for($i = 0; $i < $max; $i++) {
192            // 各項目をCSV出力用に変換する。
193            $data .= $this->lfMakeReviewCSV($list_data[$i]);
194        }
195        return $data;
196    }
197
198    // CSV出力データを作成する。(トラックバック)
199    function lfGetTrackbackCSV($where, $option, $arrval) {
200        $from = "dtb_trackback AS A INNER JOIN dtb_products AS B on A.product_id = B.product_id ";
201        $cols = SC_Utils_Ex::sfGetCommaList($this->arrTRACKBACK_CVSCOL);
202
203        $objQuery = new SC_Query();
204        $objQuery->setOption($option);
205
206        $list_data = $objQuery->select($cols, $from, $where, $arrval);
207
208        $max = count($list_data);
209        if (!isset($data)) $data = "";
210        for($i = 0; $i < $max; $i++) {
211            // 各項目をCSV出力用に変換する。
212            $data .= $this->lfMakeTrackbackCSV($list_data[$i]);
213        }
214        return $data;
215    }
216
217    // CSVを送信する。(カテゴリ)
218    function sfDownloadCategoryCsv() {
219
220        // CSV出力タイトル行の作成
221        $arrOutput = SC_Utils_Ex::sfSwapArray($this->sfgetCsvOutput(5, 'status = 1'));
222        if (count($arrOutput) <= 0) return false; // 失敗終了
223        $arrOutputCols = $arrOutput['col'];
224
225        $objQuery = new SC_Query();
226        $objQuery->setOrder('rank DESC');
227
228        $dataRows = $objQuery->select(
229             SC_Utils_Ex::sfGetCommaList($arrOutputCols)
230            ,'dtb_category'
231            ,'del_flg = 0'
232        );
233       
234        $outputArray = array();
235       
236        // ヘッダ行
237        $outputArray[] = $arrOutput['disp_name'];
238       
239        // データ行
240        foreach ($dataRows as $row) {
241            $outputArray[] = $row;
242        }
243       
244        // CSVを送信する。
245        $this->lfDownloadCsv($outputArray, 'category');
246       
247        // 成功終了
248        return true;
249    }
250
251    // CSV出力データを作成する。
252    function lfGetCSV($from, $where, $option, $arrval, $arrCsvOutputCols = "", $arrCsvOutputConverts = array()) {
253
254        $cols = SC_Utils_Ex::sfGetCommaList($arrCsvOutputCols);
255
256        $objQuery = new SC_Query();
257        $objQuery->setOption($option);
258
259        $list_data = $objQuery->select($cols, $from, $where, $arrval, MDB2_FETCHMODE_ORDERED);
260
261        $csv = '';
262        foreach ($list_data as $row) {
263            $row = SC_Utils_Ex::mbConvertKanaWithArray($row, $arrCsvOutputConverts);
264            // 各項目をCSV出力用に変換する。
265            $line = $this->sfArrayToCsv($row);
266            $csv .= "$line\r\n";
267        }
268        return $csv;
269    }
270
271    // 各項目をCSV出力用に変換する。
272    function lfMakeCSV($list) {
273        $line = "";
274       
275        foreach($list as $key => $val) {
276            $tmp = "";
277            switch($key) {
278                case 'order_pref':
279                case 'deliv_pref':
280                    $tmp = $this->arrPref[$val];
281                    break;
282                default:
283                    $tmp = $val;
284                    break;
285            }
286
287            $tmp = preg_replace('/[",]/', " ", $tmp);
288            $line .= "\"".$tmp."\",";
289        }
290        // 文末の","を変換
291        $line = $this->replaceLineSuffix($line);
292        return $line;
293    }
294
295    // 各項目をCSV出力用に変換する。(レビュー)
296    function lfMakeReviewCSV($list) {
297        $line = "";
298
299        foreach($list as $key => $val) {
300            $tmp = "";
301            switch($key) {
302            case 'sex':
303                $tmp = isset($this->arrSex[$val]) ? $this->arrSex[$val] : "";
304                break;
305            case 'recommend_level':
306                $tmp = isset($this->arrRECOMMEND[$val]) ? $this->arrRECOMMEND[$val]
307                                                        : "";
308                break;
309            case 'status':
310                $tmp = isset($this->arrDISP[$val]) ? $this->arrDISP[$val] : "";
311                break;
312            default:
313                $tmp = $val;
314                break;
315            }
316
317            $tmp = preg_replace('/[",]/', " ", $tmp);
318            $line .= "\"".$tmp."\",";
319        }
320        // 文末の","を変換
321        $line = $this->replaceLineSuffix($line);
322        return $line;
323    }
324
325    // 各項目をCSV出力用に変換する。(トラックバック)
326    function lfMakeTrackbackCSV($list) {
327
328        $line = "";
329
330        foreach($list as $key => $val) {
331            $tmp = "";
332            switch($key) {
333            case 'status':
334                $tmp = $this->arrTrackBackStatus[$val];
335                break;
336            default:
337                $tmp = $val;
338                break;
339            }
340
341            $tmp = preg_replace('/[",]/', " ", $tmp);
342            $line .= "\"".$tmp."\",";
343        }
344        // 文末の","を変換
345        $line = $this->replaceLineSuffix($line);
346        return $line;
347    }
348
349    /**
350     * 行末の ',' を CRLF へ変換する.
351     *
352     * @access private
353     * @param string $line CSV出力用の1行分の文字列
354     * @return string 行末の ',' を CRLF に変換した文字列
355     */
356    function replaceLineSuffix($line) {
357//        return mb_ereg_replace(",$", "\r\n", $line); 
358        return preg_replace('/,$/',"\r\n",$line);
359    }
360
361    /**
362     * 項目情報を初期化する.
363     *
364     * @access private
365     * @return void
366     */
367    function init() {
368        $this->arrSubnavi = array(
369                                  1 => 'product',
370                                  2 => 'customer',
371                                  3 => 'order',
372                                  4 => 'campaign',
373                                  5 => 'category'
374                                  );
375
376        $this->arrSubnaviName = array(
377                                      1 => '商品管理',
378                                      2 => '顧客管理',
379                                      3 => '受注管理',
380                                      4 => 'キャンペーン',
381                                      5 => 'カテゴリ'
382                                      );
383
384
385        $this->arrREVIEW_CVSCOL = array(
386                                        'B.name',
387                                        'A.status',
388                                        'A.create_date',
389                                        'A.reviewer_name',
390                                        'A.sex',
391                                        'A.recommend_level',
392                                        'A.title',
393                                        'A.comment'
394                                        );
395
396        $this->arrREVIEW_CVSTITLE = array(
397                                          '商品名',
398                                          'レビュー表示',
399                                          '投稿日',
400                                          '投稿者名',
401                                          '性別',
402                                          'おすすめレベル',
403                                          'タイトル',
404                                          'コメント'
405                                          );
406
407        $this->arrTRACKBACK_CVSTITLE = array(
408                                             '商品名',
409                                             'ブログ名',
410                                             'ブログ記事タイトル',
411                                             'ブログ記事内容',
412                                             '状態',
413                                             '投稿日'
414                                             );
415
416        $this->arrTRACKBACK_CVSCOL = array(
417                                           'B.name',
418                                           'A.blog_name',
419                                           'A.title',
420                                           'A.excerpt',
421                                           'A.status',
422                                           'A.create_date'
423                                           );
424    }
425   
426    /**
427     * 1次元配列を1行のCSVとして返す
428     * 参考: http://jp.php.net/fputcsv
429     */
430    function sfArrayToCsv($fields, $delimiter = ',', $enclosure = '"', $arrayDelimiter = '|') {
431       
432        if( strlen($delimiter) != 1 ) {
433            trigger_error('delimiter must be a single character', E_USER_WARNING);
434            return "";
435        }
436       
437        if( strlen($enclosure) < 1 ) {
438            trigger_error('enclosure must be a single character', E_USER_WARNING);
439            return "";
440        }
441       
442        foreach (array_keys($fields) as $key) {
443            $field =& $fields[$key];
444           
445            // 配列を「|」区切りの文字列に変換する
446            if (is_array($field)) {
447                $field = implode($arrayDelimiter, $field);
448            }
449           
450            /* enclose a field that contains a delimiter, an enclosure character, or a newline */
451            if (
452                   is_string($field)
453                && preg_match('/[' . preg_quote($delimiter) . preg_quote($enclosure) . '\\s]/', $field)
454            ) {
455                $field = $enclosure . preg_replace('/' . preg_quote($enclosure) . '/', $enclosure . $enclosure, $field) . $enclosure;
456            }
457        }
458       
459        return implode($delimiter, $fields);
460    }
461   
462    /**
463     * CSVを送信する。
464     */
465    function lfDownloadCsv($arrayData, $prefix = ""){
466
467        if($prefix == "") {
468            $dir_name = SC_Utils::sfUpDirName();
469            $file_name = $dir_name . date("ymdHis") .".csv";
470        } else {
471            $file_name = $prefix . date("ymdHis") .".csv";
472        }
473
474        /* HTTPヘッダの出力 */
475        Header("Content-disposition: attachment; filename=${file_name}");
476        Header("Content-type: application/octet-stream; name=${file_name}");
477        Header("Cache-Control: ");
478        Header("Pragma: ");
479
480        /* データを出力 */
481        foreach ($arrayData as $lineArray) {
482            $lineString = $this->sfArrayToCsv($lineArray);
483            $lineString = mb_convert_encoding($lineString, 'SJIS-Win');
484            echo $lineString . "\r\n";
485        }
486    }
487   
488    /**
489     * CSVファイルを送信する。
490     */
491    function lfDownloadCSVFile($filepath, $prefix = "") {
492        $file_name = $prefix . date("YmdHis") . ".csv";
493       
494        /* HTTPヘッダの出力 */
495        Header("Content-disposition: attachment; filename=${file_name}");
496        Header("Content-type: application/octet-stream; name=${file_name}");
497        Header("Cache-Control: ");
498        Header("Pragma: ");
499       
500        /* データを出力 */
501        // file_get_contentsはメモリマッピングも自動的に使ってくれるので高速&省メモリ
502        echo file_get_contents($filepath);
503    }
504
505    /**
506     * CSVデータを取得する。
507     */
508    function lfGetCsv2($arrayData, $prefix = "") {
509
510        if($prefix == "") {
511            $dir_name = SC_Utils::sfUpDirName();
512            $file_name = $dir_name . date("ymdHis") .".csv";
513        } else {
514            $file_name = $prefix . date("ymdHis") .".csv";
515        }
516
517        /* データを出力 */
518        foreach ($arrayData as $lineArray) {
519            $lineString = $this->sfArrayToCsv($lineArray);
520            $lineString = mb_convert_encoding($lineString, 'SJIS-Win');
521            $lineString .= "\r\n";
522        }
523        return array($file_name, $lineString);
524    }
525}
526?>
Note: See TracBrowser for help on using the repository browser.