source: branches/version-2_12-dev/data/class/helper/SC_Helper_CSV.php @ 22206

Revision 22206, 11.9 KB checked in by kim, 11 years ago (diff)

#2003 copyrightを2013に更新

  • 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  /*
[22206]3   * Copyright(c) 2000-2013 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    // {{{ constructor
27
28    /**
29     * デフォルトコンストラクタ.
30     */
[21767]31    function __construct() {
[15535]32        $this->init();
33    }
34
35    // }}}
36    // {{{ functions
37
[15566]38    /**
[20280]39     * 項目情報を初期化する.
40     *
41     * @access private
42     * @return void
43     */
44    function init() {
45        $this->arrSubnavi = array(
[21527]46            1 => 'product',
47            2 => 'customer',
48            3 => 'order',
49            4 => 'review',
50            5 => 'category',
51        );
[20280]52
53        $this->arrSubnaviName = array(
[21527]54            1 => '商品管理',
55            2 => '会員管理',
56            3 => '受注管理',
57            4 => 'レビュー',
58            5 => 'カテゴリ',
59        );
[20280]60    }
61
62    /**
[20737]63     * CSVファイルを送信する
64     *
65     * @param integer $csv_id CSVフォーマットID
66     * @param string $where WHERE条件文
[21118]67     * @param array $arrVal プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。
[20737]68     * @param string $order ORDER文
69     * @param boolean $is_download true:ダウンロード用出力までさせる false:CSVの内容を返す(旧方式、メモリを食います。)
70     * @return mixed $is_download = true時 成功失敗フラグ(boolean) 、$is_downalod = false時 string
71     */
[21514]72    function sfDownloadCsv($csv_id, $where = '', $arrVal = array(), $order = '', $is_download = false) {
[20737]73        // CSV出力タイトル行の作成
74        $arrOutput = SC_Utils_Ex::sfSwapArray($this->sfGetCsvOutput($csv_id, 'status = ' . CSV_COLUMN_STATUS_FLG_ENABLE));
75        if (count($arrOutput) <= 0) return false; // 失敗終了
76        $arrOutputCols = $arrOutput['col'];
77
78        $objQuery =& SC_Query_Ex::getSingletonInstance();
[21118]79        $objQuery->setOrder($order);
[20737]80        $cols = SC_Utils_Ex::sfGetCommaList($arrOutputCols, true);
81
82        // TODO: 固有処理 なんかエレガントな処理にしたい
[21441]83        if ($csv_id == '1') {
[20737]84            //商品の場合
85            $objProduct = new SC_Product_Ex();
86            // このWhereを足さないと無効な規格も出力される。現行仕様と合わせる為追加。
87            $inner_where = 'dtb_products_class.del_flg = 0';
88            $sql = $objQuery->getSql($cols, $objProduct->prdclsSQL($inner_where),$where);
[21686]89        } else if ($csv_id == '2') {
[20953]90            // 会員の場合
[21514]91            $sql = 'SELECT ' . $cols . ' FROM dtb_customer ' . $where;
[21686]92        } else if ($csv_id == '3') {
[20737]93            // 注文の場合
[21514]94            $sql = 'SELECT ' . $cols . ' FROM dtb_order ' . $where;
[21686]95        } else if ($csv_id == '4') {
[20737]96            // レビューの場合
[21514]97            $sql = 'SELECT ' . $cols . ' FROM dtb_review AS A INNER JOIN dtb_products AS B on A.product_id = B.product_id ' . $where;
[21686]98        } else if ($csv_id == '5') {
[20737]99            // カテゴリの場合
[21514]100            $sql = 'SELECT ' . $cols . ' FROM dtb_category ' . $where;
[20737]101        }
102        // 固有処理ここまで
103        return $this->sfDownloadCsvFromSql($sql, $arrVal, $this->arrSubnavi[$csv_id], $arrOutput['disp_name'], $is_download);
104    }
105
106    /**
[15566]107     * CSV 項目を出力する.
108     *
109     * @param integer $csv_id CSV ID
110     * @param string $where SQL の WHERE 句
111     * @param array $arrVal WHERE 句の要素
[19752]112     * @param array $order SQL の ORDER BY 句
[15566]113     * @return array CSV 項目の配列
114     */
[21514]115    function sfGetCsvOutput($csv_id = '', $where = '', $arrVal = array(), $order = 'rank, no') {
[20507]116        $objQuery =& SC_Query_Ex::getSingletonInstance();
[20540]117
[19752]118        $cols = 'no, csv_id, col, disp_name, rank, status, rw_flg, mb_convert_kana_option, size_const_type, error_check_types';
119        $table = 'dtb_csv';
[20540]120
[21441]121        if (SC_Utils_Ex::sfIsInt($csv_id)) {
[21514]122            if ($where == '') {
123                $where = 'csv_id = ?';
[21441]124            } else {
[19752]125                $where = "$where AND csv_id = ?";
126            }
[18616]127            $arrVal[] = $csv_id;
[15566]128        }
[19752]129        $objQuery->setOrder($order);
[20540]130
[19752]131        $arrRet = $objQuery->select($cols, $table, $where, $arrVal);
132        return $arrRet;
[15566]133    }
134
[19752]135    /**
136     * CSVが出力設定でインポート可能かのチェック
137     *
[19999]138     * @param array sfGetCsvOutputで取得した内容(またはそれと同等の配列)
[19752]139     * @return boolean true:インポート可能、false:インポート不可
140     */
141    function sfIsImportCSVFrame(&$arrCSVFrame) {
142        $result = true;
[21927]143        foreach ($arrCSVFrame as $val) {
[21684]144            if ($val['status'] != CSV_COLUMN_STATUS_FLG_ENABLE
145                && $val['rw_flg'] == CSV_COLUMN_RW_FLG_READ_WRITE
146                && $val['error_check_types'] != ''
147                && strpos(strtoupper($val['error_check_types']), 'EXIST_CHECK') !== FALSE
148            ) {
[19752]149                //必須フィールド
150                $result = false;
151            }
152        }
153        return $result;
154    }
[20540]155
[19752]156    /**
157     * CSVが出力設定で更新可能かのチェック
158     *
[19999]159     * @param array sfGetCsvOutputで取得した内容(またはそれと同等の配列)
[19752]160     * @return boolean true:更新可能、false:新規追加のみ不可
161     */
162    function sfIsUpdateCSVFrame(&$arrCSVFrame) {
163        $result = true;
[21927]164        foreach ($arrCSVFrame as $val) {
[21684]165            if ($val['status'] != CSV_COLUMN_STATUS_FLG_ENABLE
166                && $val['rw_flg'] == CSV_COLUMN_RW_FLG_KEY_FIELD
167            ) {
[19752]168                //キーフィールド
169                $result = false;
170            }
171        }
172        return $result;
173    }
[20540]174
[19752]175    /**
176     * CSVファイルのカウント数を得る.
177     *
178     * @param resource $fp fopenを使用して作成したファイルポインタ
179     * @return integer CSV のカウント数
180     */
181    function sfGetCSVRecordCount($fp) {
182        $count = 0;
[21441]183        while (!feof($fp)) {
[19752]184            $arrCSV = fgetcsv($fp, CSV_LINE_MAX);
185            $count++;
186        }
187        // ファイルポインタを戻す
188        if (rewind($fp)) {
189            return $count-1;
190        } else {
191            return FALSE;
192        }
193    }
194
[20280]195    /**
196     * CSV作成 テンポラリファイル出力 コールバック関数
197     *
198     * @param mixed $data 出力データ
199     * @return boolean true (true:固定 false:中断)
200     */
201    function cbOutputCSV($data) {
[19742]202        $line = $this->sfArrayToCSV($data);
203        $line = mb_convert_encoding($line, 'SJIS-Win');
204        $line .= "\r\n";
205        fwrite($this->fpOutput, $line);
[22021]206        SC_Utils_Ex::extendTimeOut();
[19742]207        return true;
208    }
[18616]209
[20280]210    /**
[20318]211     * SQL文からクエリ実行し CSVファイルを送信する
212     *
213     * @param integer $sql SQL文
[21118]214     * @param array $arrVal プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。
[20318]215     * @param string $file_head ファイル名の頭に付ける文字列
216     * @param array $arrHeader ヘッダ出力列配列
217     * @param boolean $is_download true:ダウンロード用出力までさせる false:CSVの内容を返す(旧方式、メモリを食います。)
218     * @return mixed $is_download = true時 成功失敗フラグ(boolean) 、$is_downalod = false時 string
219     */
220    function sfDownloadCsvFromSql($sql, $arrVal = array(), $file_head = 'csv', $arrHeader = array(), $is_download = false) {
[20507]221        $objQuery =& SC_Query_Ex::getSingletonInstance();
[20318]222
[20280]223        // ヘッダ構築
[21441]224        if (is_array($arrHeader)) {
[20318]225            $header = $this->sfArrayToCSV($arrHeader);
226            $header = mb_convert_encoding($header, 'SJIS-Win');
227            $header .= "\r\n";
228        }
[20285]229
[20276]230        //テンポラリファイル作成
231        // TODO: パフォーマンス向上には、ストリームを使うようにすると良い
[20318]232        //  環境要件がPHPバージョン5.1以上になったら使うように変えても良いかと
[20276]233        //  fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
[20318]234        $tmp_filename = tempnam(CSV_TEMP_REALDIR, $file_head . '_csv');
[21514]235        $this->fpOutput = fopen($tmp_filename, 'w+');
[20276]236        fwrite($this->fpOutput, $header);
[20280]237        $objQuery->doCallbackAll(array(&$this, 'cbOutputCSV'), $sql, $arrVal);
[20276]238
239        fclose($this->fpOutput);
240
[21441]241        if ($is_download) {
[20276]242            // CSVを送信する。
[21480]243            $this->lfDownloadCSVFile($tmp_filename, $file_head . '_');
[20276]244            $res = true;
[21441]245        } else {
[21757]246            $res = SC_Helper_FileManager_Ex::sfReadFile($tmp_filename);
[20276]247        }
[20318]248
[20276]249        //テンポラリファイル削除
250        unlink($tmp_filename);
251        return $res;
252    }
253
[15535]254    /**
[17799]255     * 1次元配列を1行のCSVとして返す
256     * 参考: http://jp.php.net/fputcsv
[20737]257     *
258     * @param array $fields データ1次元配列
259     * @param string $delimiter
260     * @param string $enclosure
261     * @param string $arrayDelimiter
262     * @return string 結果行
[17799]263     */
264    function sfArrayToCsv($fields, $delimiter = ',', $enclosure = '"', $arrayDelimiter = '|') {
[21442]265        if (strlen($delimiter) != 1) {
[17799]266            trigger_error('delimiter must be a single character', E_USER_WARNING);
[21514]267            return '';
[17799]268        }
[20540]269
[21442]270        if (strlen($enclosure) < 1) {
[17799]271            trigger_error('enclosure must be a single character', E_USER_WARNING);
[21514]272            return '';
[17799]273        }
[20540]274
[21935]275        foreach ($fields as $key => $value) {
[17799]276            $field =& $fields[$key];
[20540]277
[17799]278            // 配列を「|」区切りの文字列に変換する
279            if (is_array($field)) {
280                $field = implode($arrayDelimiter, $field);
281            }
[20540]282
[17799]283            /* enclose a field that contains a delimiter, an enclosure character, or a newline */
[21527]284            if (is_string($field)
[17799]285                && preg_match('/[' . preg_quote($delimiter) . preg_quote($enclosure) . '\\s]/', $field)
286            ) {
287                $field = $enclosure . preg_replace('/' . preg_quote($enclosure) . '/', $enclosure . $enclosure, $field) . $enclosure;
288            }
289        }
[20540]290
[17799]291        return implode($delimiter, $fields);
292    }
[20540]293
[17799]294    /**
[20737]295     * 配列データのCSVを送信する。
296     *
297     * @param array $fields データ配列
298     * @param string $prefix
299     * @return void
[17799]300     */
[21514]301    function lfDownloadCsv($arrData, $prefix = '') {
[17799]302
[21514]303        if ($prefix == '') {
[20484]304            $dir_name = SC_Utils_Ex::sfUpDirName();
[21514]305            $file_name = $dir_name . date('ymdHis') .'.csv';
[17799]306        } else {
[21514]307            $file_name = $prefix . date('ymdHis') .'.csv';
[17799]308        }
309
310        /* HTTPヘッダの出力 */
311        Header("Content-disposition: attachment; filename=${file_name}");
312        Header("Content-type: application/octet-stream; name=${file_name}");
[21514]313        Header('Cache-Control: ');
314        Header('Pragma: ');
[17799]315
316        /* データを出力 */
[20737]317        foreach ($arrData as $lineArray) {
[17799]318            $lineString = $this->sfArrayToCsv($lineArray);
319            $lineString = mb_convert_encoding($lineString, 'SJIS-Win');
[18616]320            echo $lineString . "\r\n";
[17799]321        }
322    }
[20540]323
[19742]324    /**
325     * CSVファイルを送信する。
[20737]326     *
327     * @param string $filepath 送信するファイルのフルパス
328     * @param string $prefix
329     * @return void
[19742]330     */
[21514]331    function lfDownloadCSVFile($filepath, $prefix = '') {
332        $file_name = $prefix . date('YmdHis') . '.csv';
[20540]333
[19742]334        /* HTTPヘッダの出力 */
[21927]335        Header("Content-disposition: attachment; filename={$file_name}");
336        Header("Content-type: application/octet-stream; name={$file_name}");
[21514]337        Header('Cache-Control: ');
338        Header('Pragma: ');
[20540]339
[19742]340        /* データを出力 */
341        // file_get_contentsはメモリマッピングも自動的に使ってくれるので高速&省メモリ
342        echo file_get_contents($filepath);
343    }
[15542]344}
Note: See TracBrowser for help on using the repository browser.