Page
[ class tree: Page ] [ index: Page ] [ all elements ]

Source for file SC_Helper_CSV.php

Documentation is available at SC_Helper_CSV.php

  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: SC_Helper_CSV.php 21118 2011-08-03 12:28:10Z kajiwara $
  14.    */
  15. class 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.                     and $val['rw_flg'] == CSV_COLUMN_RW_FLG_READ_WRITE
  149.                     and $val['error_check_types'] != ""
  150.                     and strpos(strtoupper($val['error_check_types']), "EXIST_CHECK") !== FALSE) {
  151.                 //必須フィールド
  152.                 $result = false;
  153.             }
  154.         }
  155.         return $result;
  156.     }
  157.  
  158.     /**
  159.      * CSVが出力設定で更新可能かのチェック
  160.      *
  161.      * @param array sfGetCsvOutputで取得した内容(またはそれと同等の配列)
  162.      * @return boolean true:更新可能、false:新規追加のみ不可
  163.      */
  164.     function sfIsUpdateCSVFrame(&$arrCSVFrame) {
  165.         $result = true;
  166.         foreach($arrCSVFrame as $key => $val) {
  167.             if($val['status'] != CSV_COLUMN_STATUS_FLG_ENABLE
  168.                     and $val['rw_flg'] == CSV_COLUMN_RW_FLG_KEY_FIELD) {
  169.                 //キーフィールド
  170.                 $result = false;
  171.             }
  172.         }
  173.         return $result;
  174.     }
  175.  
  176.     /**
  177.      * CSVファイルのカウント数を得る.
  178.      *
  179.      * @param resource $fp fopenを使用して作成したファイルポインタ
  180.      * @return integer CSV のカウント数
  181.      */
  182.     function sfGetCSVRecordCount($fp) {
  183.         $count = 0;
  184.         while(!feof($fp)) {
  185.             $arrCSV = fgetcsv($fp, CSV_LINE_MAX);
  186.             $count++;
  187.         }
  188.         // ファイルポインタを戻す
  189.         if (rewind($fp)) {
  190.             return $count-1;
  191.         } else {
  192.             return FALSE;
  193.         }
  194.     }
  195.  
  196.     /**
  197.      * CSV作成 テンポラリファイル出力 コールバック関数
  198.      *
  199.      * @param mixed $data 出力データ
  200.      * @return boolean true (true:固定 false:中断)
  201.      */
  202.     function cbOutputCSV($data) {
  203.         $line = $this->sfArrayToCSV($data);
  204.         $line = mb_convert_encoding($line, 'SJIS-Win');
  205.         $line .= "\r\n";
  206.         fwrite($this->fpOutput, $line);
  207.         return true;
  208.     }
  209.  
  210.     /**
  211.      * SQL文からクエリ実行し CSVファイルを送信する
  212.      *
  213.      * @param integer $sql SQL文
  214.      * @param array $arrVal プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。
  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) {
  221.         $objQuery =& SC_Query_Ex::getSingletonInstance();
  222.  
  223.         // 実行時間を制限しない
  224.         @set_time_limit(0);
  225.         // ヘッダ構築
  226.         if(is_array($arrHeader)) {
  227.             $header = $this->sfArrayToCSV($arrHeader);
  228.             $header = mb_convert_encoding($header, 'SJIS-Win');
  229.             $header .= "\r\n";
  230.         }
  231.  
  232.         //テンポラリファイル作成
  233.         // TODO: パフォーマンス向上には、ストリームを使うようにすると良い
  234.         //  環境要件がPHPバージョン5.1以上になったら使うように変えても良いかと
  235.         //  fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
  236.         $tmp_filename = tempnam(CSV_TEMP_REALDIR, $file_head . '_csv');
  237.         $this->fpOutput = fopen($tmp_filename, "w+");
  238.         fwrite($this->fpOutput, $header);
  239.         $objQuery->doCallbackAll(array(&$this, 'cbOutputCSV'), $sql, $arrVal);
  240.  
  241.         fclose($this->fpOutput);
  242.  
  243.         if($is_download) {
  244.             // CSVを送信する。
  245.             $this->lfDownloadCSVFile($tmp_filename, $file_head . "_");
  246.             $res = true;
  247.         }else{
  248.             $res = SC_Utils_Ex::sfReadFile($tmp_filename);
  249.         }
  250.  
  251.         //テンポラリファイル削除
  252.         unlink($tmp_filename);
  253.         return $res;
  254.     }
  255.  
  256.     /**
  257.      * 1次元配列を1行のCSVとして返す
  258.      * 参考: http://jp.php.net/fputcsv
  259.      *
  260.      * @param array $fields データ1次元配列
  261.      * @param string $delimiter 
  262.      * @param string $enclosure 
  263.      * @param string $arrayDelimiter 
  264.      * @return string 結果行
  265.      */
  266.     function sfArrayToCsv($fields, $delimiter = ',', $enclosure = '"', $arrayDelimiter = '|') {
  267.         if( strlen($delimiter) != 1 ) {
  268.             trigger_error('delimiter must be a single character', E_USER_WARNING);
  269.             return "";
  270.         }
  271.  
  272.         if( strlen($enclosure) < 1 ) {
  273.             trigger_error('enclosure must be a single character', E_USER_WARNING);
  274.             return "";
  275.         }
  276.  
  277.         foreach (array_keys($fields) as $key) {
  278.             $field =& $fields[$key];
  279.  
  280.             // 配列を「|」区切りの文字列に変換する
  281.             if (is_array($field)) {
  282.                 $field = implode($arrayDelimiter, $field);
  283.             }
  284.  
  285.             /* enclose a field that contains a delimiter, an enclosure character, or a newline */
  286.             if (
  287.                    is_string($field)
  288.                 && preg_match('/[' . preg_quote($delimiter) . preg_quote($enclosure) . '\\s]/', $field)
  289.             ) {
  290.                 $field = $enclosure . preg_replace('/' . preg_quote($enclosure) . '/', $enclosure . $enclosure, $field) . $enclosure;
  291.             }
  292.         }
  293.  
  294.         return implode($delimiter, $fields);
  295.     }
  296.  
  297.     /**
  298.      * 配列データのCSVを送信する。
  299.      *
  300.      * @param array $fields データ配列
  301.      * @param string $prefix 
  302.      * @return void 
  303.      */
  304.     function lfDownloadCsv($arrData, $prefix = ""){
  305.  
  306.         if($prefix == "") {
  307.             $dir_name = SC_Utils_Ex::sfUpDirName();
  308.             $file_name = $dir_name . date('ymdHis') .".csv";
  309.         } else {
  310.             $file_name = $prefix . date('ymdHis') .".csv";
  311.         }
  312.  
  313.         /* HTTPヘッダの出力 */
  314.         Header("Content-disposition: attachment; filename=${file_name}");
  315.         Header("Content-type: application/octet-stream; name=${file_name}");
  316.         Header("Cache-Control: ");
  317.         Header("Pragma: ");
  318.  
  319.         /* データを出力 */
  320.         foreach ($arrData as $lineArray) {
  321.             $lineString = $this->sfArrayToCsv($lineArray);
  322.             $lineString = mb_convert_encoding($lineString, 'SJIS-Win');
  323.             echo $lineString . "\r\n";
  324.         }
  325.     }
  326.  
  327.     /**
  328.      * CSVファイルを送信する。
  329.      *
  330.      * @param string $filepath 送信するファイルのフルパス
  331.      * @param string $prefix 
  332.      * @return void 
  333.      */
  334.     function lfDownloadCSVFile($filepath, $prefix = "") {
  335.         $file_name = $prefix . date('YmdHis') . ".csv";
  336.  
  337.         /* HTTPヘッダの出力 */
  338.         Header("Content-disposition: attachment; filename=${file_name}");
  339.         Header("Content-type: application/octet-stream; name=${file_name}");
  340.         Header("Cache-Control: ");
  341.         Header("Pragma: ");
  342.  
  343.         /* データを出力 */
  344.         // file_get_contentsはメモリマッピングも自動的に使ってくれるので高速&省メモリ
  345.         echo file_get_contents($filepath);
  346.     }
  347. }
  348. ?>

Documentation generated on Fri, 24 Feb 2012 14:02:38 +0900 by Seasoft