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

Revision 21757, 12.1 KB checked in by shutta, 10 years ago (diff)

#1612 不要な関数の削除
SC_UtilsとSC_Helper_FileManager間の重複している(もしくは同機能の)関数の整理。

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