7 * LICENSE: This source file is licensed under the terms of the GNU General Public License.
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
16 require_once($gEnvManager->getCurrentWidgetContainerPath() . '/admin_m_quizkBaseWidgetContainer.php');
17 require_once($gEnvManager->getCurrentWidgetDbPath() . '/quizkDb.php');
19 class admin_m_quizkCsvWidgetContainer extends admin_m_quizkBaseWidgetContainer
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ファイル名
31 function __construct()
34 parent::__construct();
37 $this->db = new quizkDb();
40 $this->defaultSetId = $this->db->getConfig(self::CFG_DEFAULT_SET_ID_KEY); // 定義セットID
45 * _assign()でデータを埋め込むテンプレートファイルのファイル名を返す。
46 * 読み込むディレクトリは、「自ウィジェットディレクトリ/include/template」に固定。
48 * @param RequestManager $request HTTPリクエスト処理クラス
49 * @param object $param 任意使用パラメータ。そのまま_assign()に渡る
50 * @return string テンプレートファイル名。テンプレートライブラリを使用しない場合は空文字列「''」を返す。
52 function _setTemplate($request, &$param)
54 return 'admin_csv.tmpl.html';
59 * _setTemplate()で指定したテンプレートファイルにデータを埋め込む。
61 * @param RequestManager $request HTTPリクエスト処理クラス
62 * @param object $param 任意使用パラメータ。_setTemplate()と共有。
65 function _assign($request, &$param)
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']; // アップロードされたファイルのファイル名取得
74 $skipField = '項目ID'; // ヘッダ部認識用文字列
75 $badField = ''; // 不正なヘッダ文字列
77 if (is_uploaded_file($_FILES['upfile']['tmp_name'])) {
78 // ファイルを保存するサーバディレクトリを指定
79 $tmpFile = tempnam($this->gEnv->getWorkDirPath(), M3_SYSTEM_WORK_UPLOAD_FILENAME_HEAD);
81 // アップされたテンポラリファイルを保存ディレクトリにコピー
82 $ret = move_uploaded_file($_FILES['upfile']['tmp_name'], $tmpFile);
84 $addCount = 0; // 追加項目数
85 $updateCount = 0; // 更新項目数
86 $colCount = 0; // カラム数
88 $message = ''; // 追加メッセージ
91 $this->db->startTransaction();
93 if ($dataReplace){ // データ入れ替えの場合は既存データを削除
94 $this->db->deleteAllItems($this->setId);
97 $fp = fopen($tmpFile, "r");
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++; // 行番号更新
107 if (trim($data[0]) == $skipField){
109 } else if (trim($data[0]) == $badField){
110 $this->setAppErrorMsg('不正なヘッダを検出しました');
112 $newColCount = count($data);
113 if ($newColCount == 0 || ($newColCount == 1 && $data[0] == "")) continue; // 空行は読み飛ばす
114 if ($colCount != $newColCount){
115 $message .= $lineCount . '行目のカラム数が異常です。この行は読み飛ばしました。<br />';
116 continue; // カラム数が合わない行も読み飛ばす
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]); // 表示制御
131 if ($this->getMsgCount() == 0){
132 // フィールドIDを見て、新規登録か更新かを判断
133 $updateRecord = false;
134 if ($this->db->isExistsItem($this->setId, $id)) $updateRecord = true;
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++;
149 $ret = $this->db->endTransaction();
150 if ($ret && $this->getMsgCount() == 0){
151 $this->setGuidanceMsg('データを' . $addCount . '件追加しました');
152 $this->setGuidanceMsg('データを' . $updateCount . '件更新しました');
153 $this->setGuidanceMsg($message);
155 $this->setAppErrorMsg('データ追加に失敗しました');
161 $msg = 'アップロードファイルが見つかりません(要因:アップロード可能なファイルのMaxサイズを超えている可能性があります - ' . $gSystemManager->getMaxFileSizeForUpload() . 'バイト)';
162 $this->setAppErrorMsg($msg);
164 } else if ($act == 'download'){ // CSVダウンロード
165 // ダウンロード時のデフォルトファイル名
166 $down_file = self::CSV_QUIZ_DEF_HEAD . date("YmdHi") . $this->gEnv->getDefaultCsvFileSuffix();
179 $delim = $this->gEnv->getDefaultCsvDelimCode(); // CSV区切りコードを取得
180 $this->csvData[] = implode($delim, $buf) . $this->gEnv->getDefaultCsvNLCode();
183 $this->db->getAllItems($this->setId, array($this, 'fieldCsvLoop'));
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)));
192 $encoding = $this->gEnv->getCsvDownloadEncoding(); // デフォルトのダウンロードエンコーディング取得
193 foreach ($this->csvData as $mval){
194 echo mb_convert_encoding($mval, $encoding);
203 $this->db->getAllSetId(array($this, 'setIdListLoop'));
208 * @param int $index 行番号(0~)
209 * @param array $fetchedRow フェッチ取得した行
210 * @param object $param 未使用
211 * @return bool true=処理続行の場合、false=処理終了の場合
213 function fieldCsvLoop($index, $fetchedRow, $param)
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']; // 表示制御
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']); // 表示制御
236 $this->csvData[] = implode($delim, $buf) . $this->gEnv->getDefaultCsvNLCode();
240 * セットIDリスト、取得したデータをテンプレートに設定する
242 * @param int $index 行番号(0~)
243 * @param array $fetchedRow フェッチ取得した行
244 * @param object $param 未使用
245 * @return bool true=処理続行の場合、false=処理終了の場合
247 function setIdListLoop($index, $fetchedRow, $param)
249 $id = $fetchedRow['qs_id'];
250 $name = $fetchedRow['qs_name'];
253 if ($id == $this->setId) $selected = 'selected'; // 現在操作対象のセットID
254 if ($id == $this->defaultSetId) $name .= '(現在運用中)';
256 'value' => $this->convertToDispString($id), // セットID
257 'name' => $this->convertToDispString($name), // セットID名
258 'selected' => $selected // 選択中かどうか
260 $this->tmpl->addVars('set_id_list', $row);
261 $this->tmpl->parseTemplate('set_id_list', 'a');