source: branches/version-2_13-dev/data/class/helper/SC_Helper_CSV.php @ 22856

Revision 22856, 11.6 KB checked in by Seasoft, 11 years ago (diff)

#2043 (typo修正・ソース整形・ソースコメントの改善 for 2.13.0)

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