OSDN Git Service

8a45e07770dfecaebee054b8deb066d54fa044eb
[magic3/magic3.git] / widgets / m / quizk / include / container / admin_m_quizkCsvWidgetContainer.php
1 <?php
2 /**
3  * コンテナクラス
4  *
5  * PHP versions 5
6  *
7  * LICENSE: This source file is licensed under the terms of the GNU General Public License.
8  *
9  * @package    Magic3 Framework
10  * @author     平田直毅(Naoki Hirata) <naoki@aplo.co.jp>
11  * @copyright  Copyright 2006-2009 Magic3 Project.
12  * @license    http://www.gnu.org/copyleft/gpl.html  GPL License
13  * @version    SVN: $Id: admin_m_quizkCsvWidgetContainer.php 1931 2009-05-28 08:43:03Z fishbone $
14  * @link       http://www.magic3.org
15  */
16 require_once($gEnvManager->getCurrentWidgetContainerPath() .    '/admin_m_quizkBaseWidgetContainer.php');
17 require_once($gEnvManager->getCurrentWidgetDbPath() .   '/quizkDb.php');
18
19 class admin_m_quizkCsvWidgetContainer extends admin_m_quizkBaseWidgetContainer
20 {
21         private $db;    // DB接続オブジェクト
22         private $csvData;               // CSV作成用
23         private $setId;                 // 現在選択中のセットID
24         private $defaultSetId;          // 現在運用中のセットID
25         const CFG_DEFAULT_SET_ID_KEY = 'current_set_id';                // 現在の選択中のセットID取得用キー
26         const CSV_QUIZ_DEF_HEAD = 'quiz_def_';                          // CSVファイル名
27         
28         /**
29          * コンストラクタ
30          */
31         function __construct()
32         {
33                 // 親クラスを呼び出す
34                 parent::__construct();
35                 
36                 // DBオブジェクト作成
37                 $this->db = new quizkDb();
38                 
39                 // デフォルト値取得
40                 $this->defaultSetId = $this->db->getConfig(self::CFG_DEFAULT_SET_ID_KEY);               // 定義セットID
41         }
42         /**
43          * テンプレートファイルを設定
44          *
45          * _assign()でデータを埋め込むテンプレートファイルのファイル名を返す。
46          * 読み込むディレクトリは、「自ウィジェットディレクトリ/include/template」に固定。
47          *
48          * @param RequestManager $request               HTTPリクエスト処理クラス
49          * @param object         $param                 任意使用パラメータ。そのまま_assign()に渡る
50          * @return string                                               テンプレートファイル名。テンプレートライブラリを使用しない場合は空文字列「''」を返す。
51          */
52         function _setTemplate($request, &$param)
53         {
54                 return 'admin_csv.tmpl.html';
55         }
56         /**
57          * テンプレートにデータ埋め込む
58          *
59          * _setTemplate()で指定したテンプレートファイルにデータを埋め込む。
60          *
61          * @param RequestManager $request               HTTPリクエスト処理クラス
62          * @param object         $param                 任意使用パラメータ。_setTemplate()と共有。
63          * @param                                                               なし
64          */
65         function _assign($request, &$param)
66         {
67                 $dataReplace = ($request->trimValueOf('item_replace') == 'on') ? 1 : 0;         // データの入れ替えを行うかどうか
68                 $this->setId = $request->trimValueOf('setid');          // 定義セットID
69                 $act = $request->trimValueOf('act');
70                 if ($act == 'upload'){          // CSVアップロード
71                         // ファイル名からアップロードするデータの種別を判断
72                         $uploadFilename = $_FILES['upfile']['name'];            // アップロードされたファイルのファイル名取得
73
74                         $skipField      = '項目ID';   // ヘッダ部認識用文字列
75                         $badField       = '';                           // 不正なヘッダ文字列
76
77                         if (is_uploaded_file($_FILES['upfile']['tmp_name'])) {
78                                 // ファイルを保存するサーバディレクトリを指定
79                                 $tmpFile = tempnam($this->gEnv->getWorkDirPath(), M3_SYSTEM_WORK_UPLOAD_FILENAME_HEAD);
80
81                                 // アップされたテンポラリファイルを保存ディレクトリにコピー
82                                 $ret = move_uploaded_file($_FILES['upfile']['tmp_name'], $tmpFile);
83                                 if ($ret){
84                                         $addCount = 0;          // 追加項目数
85                                         $updateCount = 0;       // 更新項目数
86                                         $colCount = 0;          // カラム数
87                                         $lineCount = 0;         // 行数
88                                         $message = '';          // 追加メッセージ
89
90                                         // トランザクションスタート
91                                         $this->db->startTransaction();
92                                 
93                                         if ($dataReplace){              // データ入れ替えの場合は既存データを削除
94                                                 $this->db->deleteAllItems($this->setId);
95                                         }
96                                         // ファイルオープン
97                                         $fp = fopen($tmpFile, "r");
98                                 
99                                         // データ読み込み
100                                         $delimType = 0;         // カンマ区切り
101                                         if ($this->gEnv->getDefaultCsvDelimCode() == "\t") $delimType = 1;              // タブ区切り
102                                         while (($data = fgetByCsv($fp, $delimType)) !== false){
103                                                 if ($colCount == 0) $colCount = count($data);           // カラム数取得
104                                                 $lineCount++;           // 行番号更新
105                                         
106                                                 // ヘッダ読み飛ばし
107                                                 if (trim($data[0]) == $skipField){
108                                                         continue;
109                                                 } else if (trim($data[0]) == $badField){
110                                                         $this->setAppErrorMsg('不正なヘッダを検出しました');
111                                                 }
112                                                 $newColCount = count($data);
113                                                 if ($newColCount == 0 || ($newColCount == 1 && $data[0] == "")) continue;               // 空行は読み飛ばす
114                                                 if ($colCount != $newColCount){
115                                                         $message .= $lineCount . '行目のカラム数が異常です。この行は読み飛ばしました。<br />';
116                                                         continue;               // カラム数が合わない行も読み飛ばす
117                                                 }
118                                         
119                                                 // データをDBに格納する
120                                                 $id                     = trim($data[0]);                               // 項目ID
121                                                 $type           = trim($data[1]);                       // 項目タイプ
122                                                 $index          = trim($data[2]);                       // 項目順
123                                                 $selAnswer      = trim($data[3]);               // 選択用回答
124                                                 $answer         = trim($data[4]);                       // 回答値
125                                                 $title          = trim($data[5]);                       // タイトル
126                                                 $content        = trim($data[6]);                       // 内容
127                                                 $visible        = trim($data[7]);                       // 表示制御
128                                         
129                                                 // データのエラーチェック
130                                                 // エラーなしの場合は、データを登録
131                                                 if ($this->getMsgCount() == 0){
132                                                         // フィールドIDを見て、新規登録か更新かを判断
133                                                         $updateRecord = false;
134                                                         if ($this->db->isExistsItem($this->setId, $id)) $updateRecord = true;
135                                                 
136                                                         // データを更新
137                                                         $ret = $this->db->updateItem($this->setId, $id, $type, $index, $selAnswer, $answer, $title, $content, $visible, $serial);
138                                                         if ($updateRecord){             // 既存項目の更新のとき
139                                                                 if ($ret) $updateCount++;       // 更新項目数
140                                                         } else {                        // 新規項目の追加のとき
141                                                                 if ($ret) $addCount++;
142                                                         }
143                                                 }
144                                         }
145                                         // ファイルを閉じる
146                                         fclose($fp);
147                                 
148                                         // トランザクション終了
149                                         $ret = $this->db->endTransaction();
150                                         if ($ret && $this->getMsgCount() == 0){
151                                                 $this->setGuidanceMsg('データを' . $addCount . '件追加しました');
152                                                 $this->setGuidanceMsg('データを' . $updateCount . '件更新しました');
153                                                 $this->setGuidanceMsg($message);
154                                         } else {
155                                                 $this->setAppErrorMsg('データ追加に失敗しました');
156                                         }
157                                 }
158                                 // テンポラリファイル削除
159                                 unlink($tmpFile);
160                         } else {
161                                 $msg = 'アップロードファイルが見つかりません(要因:アップロード可能なファイルのMaxサイズを超えている可能性があります - ' . $gSystemManager->getMaxFileSizeForUpload() . 'バイト)';
162                                 $this->setAppErrorMsg($msg);
163                         }
164                 } else if ($act == 'download'){         // CSVダウンロード
165                         // ダウンロード時のデフォルトファイル名
166                         $down_file = self::CSV_QUIZ_DEF_HEAD . date("YmdHi") . $this->gEnv->getDefaultCsvFileSuffix();
167                 
168                         // ヘッダ部を作成
169                         $buf = array();
170                         $buf[] = '項目ID';
171                         $buf[] = '項目タイプ';
172                         $buf[] = '項目順';
173                         $buf[] = '選択用回答ID';
174                         $buf[] = '正解回答ID';
175                         $buf[] = 'タイトル';
176                         $buf[] = '内容';
177                         $buf[] = '表示制御';
178
179                         $delim = $this->gEnv->getDefaultCsvDelimCode();         // CSV区切りコードを取得
180                         $this->csvData[] = implode($delim, $buf) . $this->gEnv->getDefaultCsvNLCode();
181                 
182                         // クイズ定義データを取得
183                         $this->db->getAllItems($this->setId, array($this, 'fieldCsvLoop'));
184                         
185                         // CSVの出力
186                         ob_end_clean();
187                         header("Content-Type: application/force-download");
188                         header("Content-Disposition: attachment; filename=" . $down_file);
189                         header("Content-Description: File Transfer");
190                         header("Content-Length: " . strlen(join("", $this->csvData)));
191                         
192                         $encoding = $this->gEnv->getCsvDownloadEncoding();              // デフォルトのダウンロードエンコーディング取得
193                         foreach ($this->csvData as $mval){
194                             echo mb_convert_encoding($mval, $encoding);
195                             flush();
196                             ob_flush();
197                             usleep(10000);
198                         }
199                         ob_end_flush();
200                         exit();         // スクリプト終了
201                 }
202                 // 定義セットIDの選択メニュー作成
203                 $this->db->getAllSetId(array($this, 'setIdListLoop'));
204         }
205         /**
206          * 取得したデータをCSV形式で出力する
207          *
208          * @param int $index                    行番号(0~)
209          * @param array $fetchedRow             フェッチ取得した行
210          * @param object $param                 未使用
211          * @return bool                                 true=処理続行の場合、false=処理終了の場合
212          */
213         function fieldCsvLoop($index, $fetchedRow, $param)
214         {
215                 $buf = array();
216                 $delim = $this->gEnv->getDefaultCsvDelimCode();         // CSV区切りコードを取得
217                 if ($delim == "\t"){    // タブ区切りのCSVフォーマットのとき
218                         $buf[] = $fetchedRow['qd_id'];                          // 項目ID
219                         $buf[] = $fetchedRow['qd_type'];                        // 項目タイプ
220                         $buf[] = $fetchedRow['qd_index'];                       // 項目順
221                         $buf[] = $fetchedRow['qd_select_answer_id'];    // 選択用回答
222                         $buf[] = $fetchedRow['qd_answer_id'];                   // 回答ID
223                         $buf[] = $fetchedRow['qd_title'];                       // タイトル
224                         $buf[] = $fetchedRow['qd_content'];                     // 内容
225                         $buf[] = $fetchedRow['qd_visible'];                     // 表示制御
226                 } else {
227                         $buf[] = $this->convertToEscapedCsv($fetchedRow['qd_id']);                              // 項目ID
228                         $buf[] = $this->convertToEscapedCsv($fetchedRow['qd_type']);                    // 項目タイプ
229                         $buf[] = $this->convertToEscapedCsv($fetchedRow['qd_index']);                   // 項目順
230                         $buf[] = $this->convertToEscapedCsv($fetchedRow['qd_select_answer_id']);        // 選択用回答
231                         $buf[] = $this->convertToEscapedCsv($fetchedRow['qd_answer_id']);                       // 回答ID
232                         $buf[] = $this->convertToEscapedCsv($fetchedRow['qd_title']);                   // タイトル
233                         $buf[] = $this->convertToEscapedCsv($fetchedRow['qd_content']);                 // 内容
234                         $buf[] = $this->convertToEscapedCsv($fetchedRow['qd_visible']);                 // 表示制御
235                 }
236                 $this->csvData[] = implode($delim, $buf) . $this->gEnv->getDefaultCsvNLCode();
237                 return true;
238         }
239         /**
240          * セットIDリスト、取得したデータをテンプレートに設定する
241          *
242          * @param int $index                    行番号(0~)
243          * @param array $fetchedRow             フェッチ取得した行
244          * @param object $param                 未使用
245          * @return bool                                 true=処理続行の場合、false=処理終了の場合
246          */
247         function setIdListLoop($index, $fetchedRow, $param)
248         {
249                 $id = $fetchedRow['qs_id'];
250                 $name = $fetchedRow['qs_name'];
251                 
252                 $selected = '';
253                 if ($id == $this->setId) $selected = 'selected';                // 現在操作対象のセットID
254                 if ($id == $this->defaultSetId) $name .= '(現在運用中)';
255                 $row = array(
256                         'value'    => $this->convertToDispString($id),                  // セットID
257                         'name'     => $this->convertToDispString($name),                        // セットID名
258                         'selected' => $selected                                                                                                         // 選択中かどうか
259                 );
260                 $this->tmpl->addVars('set_id_list', $row);
261                 $this->tmpl->parseTemplate('set_id_list', 'a');
262                 return true;
263         }
264 }
265 ?>