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

Revision 20686, 17.7 KB checked in by kotani, 13 years ago (diff)

#854(PHP4対応)

  • stripos() を変更
  • 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
RevLine 
[15535]1<?php
2  /*
[18701]3   * Copyright(c) 2000-2010 LOCKON CO.,LTD. All Rights Reserved.
[15535]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    // {{{ constructor
33
34    /**
35     * デフォルトコンストラクタ.
36     */
37    function SC_Helper_CSV() {
38        $this->init();
39
40        $masterData = new SC_DB_MasterData_Ex();
[19773]41        $this->arrPref = $masterData->getMasterData('mtb_pref');
[15535]42        $this->arrSex = $masterData->getMasterData("mtb_sex");
43        $this->arrDISP = $masterData->getMasterData("mtb_disp");
44        $this->arrRECOMMEND = $masterData->getMasterData("mtb_recommend");
45    }
46
47    // }}}
48    // {{{ functions
49
[15566]50    /**
[20280]51     * 項目情報を初期化する.
52     *
53     * @access private
54     * @return void
55     */
56    function init() {
57        $this->arrSubnavi = array(
58                                  1 => 'product',
59                                  2 => 'customer',
60                                  3 => 'order',
61                                  5 => 'category'
62                                  );
63
64        $this->arrSubnaviName = array(
65                                      1 => '商品管理',
66                                      2 => '顧客管理',
67                                      3 => '受注管理',
68                                      5 => 'カテゴリ'
69                                      );
70
71        $this->arrREVIEW_CVSCOL = array(
72                                        'B.name',
73                                        'A.status',
74                                        'A.create_date',
75                                        'A.reviewer_name',
76                                        'A.sex',
77                                        'A.recommend_level',
78                                        'A.title',
79                                        'A.comment'
80                                        );
81
82        $this->arrREVIEW_CVSTITLE = array(
83                                          '商品名',
84                                          'レビュー表示',
85                                          '投稿日',
86                                          '投稿者名',
87                                          '性別',
88                                          'おすすめレベル',
89                                          'タイトル',
90                                          'コメント'
91                                          );
92    }
93
94    /**
[15566]95     * CSV 項目を出力する.
96     *
97     * @param integer $csv_id CSV ID
98     * @param string $where SQL の WHERE 句
99     * @param array $arrVal WHERE 句の要素
[19752]100     * @param array $order SQL の ORDER BY 句
[15566]101     * @return array CSV 項目の配列
102     */
[19999]103    function sfGetCsvOutput($csv_id = "", $where = '', $arrVal = array(), $order = 'rank, no'){
[20507]104        $objQuery =& SC_Query_Ex::getSingletonInstance();
[20540]105
[19752]106        $cols = 'no, csv_id, col, disp_name, rank, status, rw_flg, mb_convert_kana_option, size_const_type, error_check_types';
107        $table = 'dtb_csv';
[20540]108
[19752]109        if(SC_Utils_Ex::sfIsInt($csv_id)){
110            if($where == "") {
111                $where = "csv_id = ?";
112            }else{
113                $where = "$where AND csv_id = ?";
114            }
[18616]115            $arrVal[] = $csv_id;
[15566]116        }
[19752]117        $objQuery->setOrder($order);
[20540]118
[19752]119        $arrRet = $objQuery->select($cols, $table, $where, $arrVal);
120        return $arrRet;
[15566]121    }
122
[19752]123    /**
124     * CSVが出力設定でインポート可能かのチェック
125     *
[19999]126     * @param array sfGetCsvOutputで取得した内容(またはそれと同等の配列)
[19752]127     * @return boolean true:インポート可能、false:インポート不可
128     */
129    function sfIsImportCSVFrame(&$arrCSVFrame) {
130        $result = true;
131        foreach($arrCSVFrame as $key => $val) {
[19950]132            if($val['status'] != CSV_COLUMN_STATUS_FLG_ENABLE
133                    and $val['rw_flg'] == CSV_COLUMN_RW_FLG_READ_WRITE
[19752]134                    and $val['error_check_types'] != ""
[20686]135                    and strpos(strtoupper($val['error_check_types']), "EXIST_CHECK") !== FALSE) {
[19752]136                //必須フィールド
137                $result = false;
138            }
139        }
140        return $result;
141    }
[20540]142
[19752]143    /**
144     * CSVが出力設定で更新可能かのチェック
145     *
[19999]146     * @param array sfGetCsvOutputで取得した内容(またはそれと同等の配列)
[19752]147     * @return boolean true:更新可能、false:新規追加のみ不可
148     */
149    function sfIsUpdateCSVFrame(&$arrCSVFrame) {
150        $result = true;
151        foreach($arrCSVFrame as $key => $val) {
[19950]152            if($val['status'] != CSV_COLUMN_STATUS_FLG_ENABLE
153                    and $val['rw_flg'] == CSV_COLUMN_RW_FLG_KEY_FIELD) {
[19752]154                //キーフィールド
155                $result = false;
156            }
157        }
158        return $result;
159    }
[20540]160
[19752]161    /**
162     * CSVファイルのカウント数を得る.
163     *
164     * @param resource $fp fopenを使用して作成したファイルポインタ
165     * @return integer CSV のカウント数
166     */
167    function sfGetCSVRecordCount($fp) {
168        $count = 0;
169        while(!feof($fp)) {
170            $arrCSV = fgetcsv($fp, CSV_LINE_MAX);
171            $count++;
172        }
173        // ファイルポインタを戻す
174        if (rewind($fp)) {
175            return $count-1;
176        } else {
177            return FALSE;
178        }
179    }
180
[20280]181    /**
182     * CSV作成 テンポラリファイル出力 コールバック関数
183     *
184     * @param mixed $data 出力データ
185     * @return boolean true (true:固定 false:中断)
186     */
187    function cbOutputCSV($data) {
[19742]188        $line = $this->sfArrayToCSV($data);
189        $line = mb_convert_encoding($line, 'SJIS-Win');
190        $line .= "\r\n";
191        fwrite($this->fpOutput, $line);
192        return true;
193    }
[18616]194
[20280]195    /**
196     * CSVファイルを送信する
197     *
198     * @param integer $csv_id CSVフォーマットID
199     * @param string $where WHERE条件文
200     * @param array $arrVal プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。
201     * @param string $order ORDER文
202     * @param boolean $is_download true:ダウンロード用出力までさせる false:CSVの内容を返す(旧方式、メモリを食います。)
203     * @return mixed $is_download = true時 成功失敗フラグ(boolean) 、$is_downalod = false時 string
204     */
205    function sfDownloadCsv($csv_id, $where = "", $arrVal = array(), $order = "", $is_download = false) {
[20276]206        // 実行時間を制限しない
207        @set_time_limit(0);
208
209        // CSV出力タイトル行の作成
[20280]210        $arrOutput = SC_Utils_Ex::sfSwapArray($this->sfGetCsvOutput($csv_id, 'status = ' . CSV_COLUMN_STATUS_FLG_ENABLE));
[20276]211        if (count($arrOutput) <= 0) return false; // 失敗終了
212        $arrOutputCols = $arrOutput['col'];
213
[20507]214        $objQuery =& SC_Query_Ex::getSingletonInstance();
[20280]215        $objQuery->setOrder($order);       
216        $cols = SC_Utils_Ex::sfGetCommaList($arrOutputCols, true);
[20540]217
[20280]218        // TODO: 固有処理 なんかエレガントな処理にしたい
219        if($csv_id == '1') {
220            //商品の場合
[20487]221            $objProduct = new SC_Product_Ex();
[20280]222            // このWhereを足さないと無効な規格も出力される。現行仕様と合わせる為追加。
223            $inner_where = 'dtb_products_class.del_flg = 0';
224            $sql = $objQuery->getSql($cols, $objProduct->prdclsSQL($inner_where),$where);
225        }else if($csv_id == '2') {
226            // 顧客の場合
[20285]227            $sql = "SELECT " . $cols . " FROM dtb_customer " . $where;
[20540]228
[20280]229        }
230        // 固有処理ここまで
[20318]231        return $this->sfDownloadCsvFromSql($sql, $arrVal, $this->arrSubnavi[$csv_id], $arrOutput['disp_name'], $is_download);
232    }
[20285]233
[20318]234    /**
235     * SQL文からクエリ実行し CSVファイルを送信する
236     *
237     * @param integer $sql SQL文
238     * @param array $arrVal プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。
239     * @param string $file_head ファイル名の頭に付ける文字列
240     * @param array $arrHeader ヘッダ出力列配列
241     * @param boolean $is_download true:ダウンロード用出力までさせる false:CSVの内容を返す(旧方式、メモリを食います。)
242     * @return mixed $is_download = true時 成功失敗フラグ(boolean) 、$is_downalod = false時 string
243     */
244    function sfDownloadCsvFromSql($sql, $arrVal = array(), $file_head = 'csv', $arrHeader = array(), $is_download = false) {
[20507]245        $objQuery =& SC_Query_Ex::getSingletonInstance();
[20318]246
247        // 実行時間を制限しない
248        @set_time_limit(0);
[20280]249        // ヘッダ構築
[20318]250        if(is_array($arrHeader)) {
251            $header = $this->sfArrayToCSV($arrHeader);
252            $header = mb_convert_encoding($header, 'SJIS-Win');
253            $header .= "\r\n";
254        }
[20285]255
[20276]256        //テンポラリファイル作成
257        // TODO: パフォーマンス向上には、ストリームを使うようにすると良い
[20318]258        //  環境要件がPHPバージョン5.1以上になったら使うように変えても良いかと
[20276]259        //  fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
[20318]260        $tmp_filename = tempnam(CSV_TEMP_REALDIR, $file_head . '_csv');
[20276]261        $this->fpOutput = fopen($tmp_filename, "w+");
262        fwrite($this->fpOutput, $header);
[20280]263        $objQuery->doCallbackAll(array(&$this, 'cbOutputCSV'), $sql, $arrVal);
[20276]264
265        fclose($this->fpOutput);
266
267        if($is_download) {
268            // CSVを送信する。
[20318]269            $this->lfDownloadCSVFile($tmp_filename, $file_head . "_");
[20276]270            $res = true;
271        }else{
272            $res = SC_Utils_Ex::sfReadFile($tmp_filename);
273        }
[20318]274
[20276]275        //テンポラリファイル削除
276        unlink($tmp_filename);
277        return $res;
278    }
279
[15535]280    // CSV出力データを作成する。(レビュー)
281    function lfGetReviewCSV($where, $option, $arrval) {
282
283        $from = "dtb_review AS A INNER JOIN dtb_products AS B on A.product_id = B.product_id ";
284        $cols = SC_Utils_Ex::sfGetCommaList($this->arrREVIEW_CVSCOL);
285
[20507]286        $objQuery =& SC_Query_Ex::getSingletonInstance();
[18675]287        $objQuery->setOption($option);
[15535]288
289        $list_data = $objQuery->select($cols, $from, $where, $arrval);
290
291        $max = count($list_data);
[15543]292        if (!isset($data)) $data = "";
[15535]293        for($i = 0; $i < $max; $i++) {
294            // 各項目をCSV出力用に変換する。
295            $data .= $this->lfMakeReviewCSV($list_data[$i]);
296        }
297        return $data;
298    }
299
[17799]300    // CSVを送信する。(カテゴリ)
301    function sfDownloadCategoryCsv() {
[17156]302
[18545]303        // CSV出力タイトル行の作成
[19999]304        $arrOutput = SC_Utils_Ex::sfSwapArray($this->sfGetCsvOutput(5, 'status = ' . CSV_COLUMN_STATUS_FLG_ENABLE));
[18545]305        if (count($arrOutput) <= 0) return false; // 失敗終了
[17799]306        $arrOutputCols = $arrOutput['col'];
[17156]307
[20507]308        $objQuery =& SC_Query_Ex::getSingletonInstance();
[18675]309        $objQuery->setOrder('rank DESC');
[17156]310
[17799]311        $dataRows = $objQuery->select(
312             SC_Utils_Ex::sfGetCommaList($arrOutputCols)
313            ,'dtb_category'
314            ,'del_flg = 0'
315        );
[20540]316
[17799]317        $outputArray = array();
[20540]318
[17799]319        // ヘッダ行
320        $outputArray[] = $arrOutput['disp_name'];
[20540]321
[17799]322        // データ行
323        foreach ($dataRows as $row) {
324            $outputArray[] = $row;
[17156]325        }
[20540]326
[17799]327        // CSVを送信する。
328        $this->lfDownloadCsv($outputArray, 'category');
[20540]329
[17799]330        // 成功終了
[18544]331        return true;
[17156]332    }
333
[15581]334    // CSV出力データを作成する。
[18616]335    function lfGetCSV($from, $where, $option, $arrval, $arrCsvOutputCols = "", $arrCsvOutputConverts = array()) {
[15581]336
337        $cols = SC_Utils_Ex::sfGetCommaList($arrCsvOutputCols);
338
[20507]339        $objQuery =& SC_Query_Ex::getSingletonInstance();
[18675]340        $objQuery->setOption($option);
[15581]341
[18791]342        $list_data = $objQuery->select($cols, $from, $where, $arrval, MDB2_FETCHMODE_ORDERED);
[15581]343
[18616]344        $csv = '';
345        foreach ($list_data as $row) {
346            $row = SC_Utils_Ex::mbConvertKanaWithArray($row, $arrCsvOutputConverts);
[15581]347            // 各項目をCSV出力用に変換する。
[18616]348            $line = $this->sfArrayToCsv($row);
349            $csv .= "$line\r\n";
[15581]350        }
[18616]351        return $csv;
[15581]352    }
353
354    // 各項目をCSV出力用に変換する。
355    function lfMakeCSV($list) {
356        $line = "";
[20562]357
[18545]358        foreach($list as $key => $val) {
[15581]359            $tmp = "";
360            switch($key) {
[18545]361                case 'order_pref':
362                case 'deliv_pref':
363                    $tmp = $this->arrPref[$val];
364                    break;
365                default:
366                    $tmp = $val;
367                    break;
[15581]368            }
369
[18779]370            $tmp = preg_replace('/[",]/', " ", $tmp);
[15581]371            $line .= "\"".$tmp."\",";
372        }
373        // 文末の","を変換
[15583]374        $line = $this->replaceLineSuffix($line);
[15581]375        return $line;
376    }
377
[15535]378    // 各項目をCSV出力用に変換する。(レビュー)
379    function lfMakeReviewCSV($list) {
380        $line = "";
[18545]381
382        foreach($list as $key => $val) {
[15535]383            $tmp = "";
384            switch($key) {
385            case 'sex':
[15540]386                $tmp = isset($this->arrSex[$val]) ? $this->arrSex[$val] : "";
[15535]387                break;
388            case 'recommend_level':
[15540]389                $tmp = isset($this->arrRECOMMEND[$val]) ? $this->arrRECOMMEND[$val]
390                                                        : "";
[15535]391                break;
392            case 'status':
[15540]393                $tmp = isset($this->arrDISP[$val]) ? $this->arrDISP[$val] : "";
[15535]394                break;
395            default:
396                $tmp = $val;
397                break;
398            }
399
[18781]400            $tmp = preg_replace('/[",]/', " ", $tmp);
[15535]401            $line .= "\"".$tmp."\",";
402        }
403        // 文末の","を変換
[15583]404        $line = $this->replaceLineSuffix($line);
[15535]405        return $line;
406    }
407
408    /**
[15583]409     * 行末の ',' を CRLF へ変換する.
410     *
411     * @access private
412     * @param string $line CSV出力用の1行分の文字列
413     * @return string 行末の ',' を CRLF に変換した文字列
414     */
415    function replaceLineSuffix($line) {
[18781]416        return preg_replace('/,$/',"\r\n",$line);
[15583]417    }
418
[17799]419    /**
420     * 1次元配列を1行のCSVとして返す
421     * 参考: http://jp.php.net/fputcsv
422     */
423    function sfArrayToCsv($fields, $delimiter = ',', $enclosure = '"', $arrayDelimiter = '|') {
424        if( strlen($delimiter) != 1 ) {
425            trigger_error('delimiter must be a single character', E_USER_WARNING);
426            return "";
427        }
[20540]428
[17799]429        if( strlen($enclosure) < 1 ) {
430            trigger_error('enclosure must be a single character', E_USER_WARNING);
431            return "";
432        }
[20540]433
[17799]434        foreach (array_keys($fields) as $key) {
435            $field =& $fields[$key];
[20540]436
[17799]437            // 配列を「|」区切りの文字列に変換する
438            if (is_array($field)) {
439                $field = implode($arrayDelimiter, $field);
440            }
[20540]441
[17799]442            /* enclose a field that contains a delimiter, an enclosure character, or a newline */
443            if (
444                   is_string($field)
445                && preg_match('/[' . preg_quote($delimiter) . preg_quote($enclosure) . '\\s]/', $field)
446            ) {
447                $field = $enclosure . preg_replace('/' . preg_quote($enclosure) . '/', $enclosure . $enclosure, $field) . $enclosure;
448            }
449        }
[20540]450
[17799]451        return implode($delimiter, $fields);
452    }
[20540]453
[17799]454    /**
455     * CSVを送信する。
456     */
457    function lfDownloadCsv($arrayData, $prefix = ""){
458
459        if($prefix == "") {
[20484]460            $dir_name = SC_Utils_Ex::sfUpDirName();
[20538]461            $file_name = $dir_name . date('ymdHis') .".csv";
[17799]462        } else {
[20538]463            $file_name = $prefix . date('ymdHis') .".csv";
[17799]464        }
465
466        /* HTTPヘッダの出力 */
467        Header("Content-disposition: attachment; filename=${file_name}");
468        Header("Content-type: application/octet-stream; name=${file_name}");
469        Header("Cache-Control: ");
470        Header("Pragma: ");
471
472        /* データを出力 */
473        foreach ($arrayData as $lineArray) {
474            $lineString = $this->sfArrayToCsv($lineArray);
475            $lineString = mb_convert_encoding($lineString, 'SJIS-Win');
[18616]476            echo $lineString . "\r\n";
[17799]477        }
478    }
[20540]479
[19742]480    /**
481     * CSVファイルを送信する。
482     */
483    function lfDownloadCSVFile($filepath, $prefix = "") {
[20538]484        $file_name = $prefix . date('YmdHis') . ".csv";
[20540]485
[19742]486        /* HTTPヘッダの出力 */
487        Header("Content-disposition: attachment; filename=${file_name}");
488        Header("Content-type: application/octet-stream; name=${file_name}");
489        Header("Cache-Control: ");
490        Header("Pragma: ");
[20540]491
[19742]492        /* データを出力 */
493        // file_get_contentsはメモリマッピングも自動的に使ってくれるので高速&省メモリ
494        echo file_get_contents($filepath);
495    }
[19661]496
497    /**
498     * CSVデータを取得する。
499     */
500    function lfGetCsv2($arrayData, $prefix = "") {
501
502        if($prefix == "") {
[20484]503            $dir_name = SC_Utils_Ex::sfUpDirName();
[20538]504            $file_name = $dir_name . date('ymdHis') .".csv";
[19661]505        } else {
[20538]506            $file_name = $prefix . date('ymdHis') .".csv";
[19661]507        }
508
509        /* データを出力 */
510        foreach ($arrayData as $lineArray) {
511            $lineString = $this->sfArrayToCsv($lineArray);
512            $lineString = mb_convert_encoding($lineString, 'SJIS-Win');
513            $lineString .= "\r\n";
514        }
515        return array($file_name, $lineString);
516    }
[15542]517}
[15535]518?>
Note: See TracBrowser for help on using the repository browser.