* @author Allcreator * @link http://www.netcommons.org NetCommons Project * @license http://www.netcommons.org/license.txt NetCommons License * @copyright Copyright 2014, NetCommons Project */ App::uses('QuestionnairesAppController', 'Questionnaires.Controller'); App::uses('TemporaryFolder', 'Files.Utility'); App::uses('CsvFileWriter', 'Files.Utility'); App::uses('ZipDownloader', 'Files.Utility'); /** * BlocksController * * @author AllCreator * @package NetCommons\Questionnaires\Controller */ class QuestionnaireBlocksController extends QuestionnairesAppController { /** * csv download item count handling unit * * @var int */ const QUESTIONNAIRE_CSV_UNIT_NUMBER = 1000; /** * layout * * @var array */ public $layout = 'NetCommons.setting'; /** * use models * * @var array */ public $uses = array( 'Questionnaires.Questionnaire', 'Questionnaires.QuestionnaireFrameSetting', 'Questionnaires.QuestionnaireFrameDisplayQuestionnaire', 'Questionnaires.QuestionnaireAnswerSummary', 'Questionnaires.QuestionnaireAnswerSummaryCsv', 'Blocks.Block', 'Questionnaires.QuestionnaireExport', ); /** * use components * * @var array */ public $components = array( 'NetCommons.Permission' => array( //アクセスの権限 'allow' => array( 'index,download,export' => 'block_editable', ), ), 'Paginator', ); /** * use helpers * * @var array */ public $helpers = array( 'Session', 'Blocks.BlockForm', 'Blocks.BlockTabs' => array( 'mainTabs' => array( 'block_index' => array( 'url' => array('controller' => 'questionnaire_blocks') ), 'role_permissions' => array( 'url' => array('controller' => 'questionnaire_block_role_permissions') ), 'frame_settings' => array( 'url' => array('controller' => 'questionnaire_frame_settings') ), 'mail_settings' => array( 'url' => array('controller' => 'questionnaire_mail_settings') ), ), ), 'Blocks.BlockIndex', 'NetCommons.NetCommonsForm', 'NetCommons.Date', 'NetCommons.TitleIcon', 'AuthorizationKeys.AuthKeyPopupButton', ); /** * beforeFilter * * @return void * @throws NotFoundException */ public function beforeFilter() { parent::beforeFilter(); $this->Auth->deny('index'); // 設定画面を表示する前にこのルームのアンケートブロックがあるか確認 // 万が一、まだ存在しない場合には作成しておく // afterFrameSaveが呼ばれないような状況の想定 $frame['Frame'] = Current::read('Frame'); // 設定系画面でフレームが存在しないということはない、ということを前提にする if (! $frame['Frame']) { throw new NotFoundException(); } $this->Questionnaire->afterFrameSave($frame); } /** * index * * @return void */ public function index() { // 条件設定値取得 // 条件設定値取得 $conditions = $this->Questionnaire->getBaseCondition(); // データ取得 $this->paginate = array( 'conditions' => $conditions, 'page' => 1, 'order' => array('Questionnaire.modified' => 'DESC'), //'limit' => QuestionnairesComponent::QUESTIONNAIRE_DEFAULT_DISPLAY_NUM_PER_PAGE, 'recursive' => 0, ); $questionnaire = $this->paginate('Questionnaire'); if (! $questionnaire) { $this->view = 'not_found'; return; } $frame = $this->QuestionnaireFrameDisplayQuestionnaire->find('all', array( 'conditions' => array( 'frame_key' => Current::read('Frame.key'), ), 'recursive' => -1, )); $frameInfo = []; foreach ($frame as $item) { $item = $item['QuestionnaireFrameDisplayQuestionnaire']; $frameInfo[$item['questionnaire_key']] = $item['questionnaire_key']; } $this->request->data['QuestionnaireFrameDisplayQuestionnaire'] = $frameInfo; $this->set('questionnaires', $questionnaire); } /** * download * * @return void * @throws InternalErrorException */ public function download() { // NetCommonsお約束:コンテンツ操作のためのURLには対象のコンテンツキーが必ず含まれている // まずは、そのキーを取り出す // アンケートキー $questionnaireKey = $this->_getQuestionnaireKeyFromPass(); // キー情報をもとにデータを取り出す $questionnaire = $this->QuestionnaireAnswerSummaryCsv->getQuestionnaireForAnswerCsv( $questionnaireKey); if (! $questionnaire) { $this->_setFlashMessageAndRedirect( __d('questionnaires', 'Designation of the questionnaire does not exist.')); return; } // 圧縮用パスワードキーを求める if (! empty($this->request->data['AuthorizationKey']['authorization_key'])) { $zipPassword = $this->request->data['AuthorizationKey']['authorization_key']; } else { $this->_setFlashMessageAndRedirect( __d('questionnaires', 'Setting of password is required always to download answers.')); return; } try { $tmpFolder = new TemporaryFolder(); $csvFile = new CsvFileWriter(array( 'folder' => $tmpFolder->path )); // 回答データを一気に全部取得するのは、データ爆発の可能性があるので // QUESTIONNAIRE_CSV_UNIT_NUMBER分に制限して取得する $offset = 0; do { $datas = $this->QuestionnaireAnswerSummaryCsv->getAnswerSummaryCsv( $questionnaire, self::QUESTIONNAIRE_CSV_UNIT_NUMBER, $offset); // CSV形式で書きこみ foreach ($datas as $data) { $csvFile->add($data); } $dataCount = count($datas); // データ数カウント $offset += $dataCount; // 次の取得開始位置をずらす } while ($dataCount == self::QUESTIONNAIRE_CSV_UNIT_NUMBER); // データ取得数が制限値分だけとれている間は繰り返す } catch (Exception $e) { // NetCommonsお約束:エラーメッセージのFlash表示 $this->_setFlashMessageAndRedirect(__d('questionnaires', 'download error')); return; } // Downloadの時はviewを使用しない $this->autoRender = false; // ダウンロードファイル名決定 アンケート名称をつける $zipFileName = $questionnaire['Questionnaire']['title'] . '.zip'; $downloadFileName = trim($questionnaire['Questionnaire']['title']) . '.csv'; // 出力 return $csvFile->zipDownload(rawurlencode($zipFileName), $downloadFileName, $zipPassword); } /** * _setFlashMessageAndRedirect * * @param string $message flash error message * * @return void */ protected function _setFlashMessageAndRedirect($message) { $this->NetCommons->setFlashNotification( $message, array( 'interval' => NetCommonsComponent::ALERT_VALIDATE_ERROR_INTERVAL )); $this->redirect(NetCommonsUrl::actionUrl(array( 'controller' => 'questionnaire_blocks', 'action' => 'index', 'frame_id' => Current::read('Frame.id') ))); } /** * export * * template file about questionnaire export action * * @return void */ public function export() { // NetCommonsお約束:コンテンツ操作のためのURLには対象のコンテンツキーが必ず含まれている // まずは、そのキーを取り出す // アンケートキー $questionnaireKey = $this->_getQuestionnaireKeyFromPass(); // キー情報をもとにデータを取り出す $questionnaire = $this->QuestionnaireAnswerSummaryCsv->getQuestionnaireForAnswerCsv( $questionnaireKey); if (! $questionnaire) { $this->_setFlashMessageAndRedirect( __d('questionnaires', 'Designation of the questionnaire does not exist.')); return; } try { // zipファイル準備 $zipFile = new ZipDownloader(); // Export用のデータ配列を取得する $zipData = $this->QuestionnaireExport->getExportData($questionnaireKey); // Export用ファイルデータをZIPファイルに出力する // ※この中でWYSISWYGエディタデータは適宜処理されている $this->QuestionnaireExport->putToZip($zipFile, $zipData); // アーカイブ閉じる $zipFile->close(); } catch(Exception $e) { $this->_setFlashMessageAndRedirect( __d('questionnaires', 'export error' . $e->getMessage())); return; } // 大外枠zipファイル準備 $zipWrapperFile = new ZipDownloader(); // アンケートデータファイルのフィンガープリントを得る $fingerPrint = sha1_file($zipFile->path, false); // フィンガープリントをアーカイブに加える $zipWrapperFile->addFromString( QuestionnairesComponent::QUESTIONNAIRE_FINGER_PRINT_FILENAME, $fingerPrint); // 本体ファイルを $zipWrapperFile->addFile( $zipFile->path, QuestionnairesComponent::QUESTIONNAIRE_TEMPLATE_FILENAME); // export-key 設定 $this->Questionnaire->saveExportKey($questionnaire['Questionnaire']['id'], $fingerPrint); // viewを使用しない $this->autoRender = false; // ダウンロード出力ファイル名確定 $exportFileName = $questionnaire['Questionnaire']['title'] . '.zip'; // 出力 return $zipWrapperFile->download(rawurlencode($exportFileName)); } }