/** * saveAnswer * save the answer data * * @param array $questionnaire questionnaire data * @param int $userId user id * @param string $sessionId session id * @param array $data Postされた回答データ * @param array &$errors error messages * @throws $ex * @return bool */ public function saveAnswer($questionnaire, $userId, $sessionId, $data, &$errors) { $errors = array(); $this->loadModels(['QuestionnaireAnswerSummary' => 'Questionnaires.QuestionnaireAnswerSummary']); //トランザクションBegin $this->setDataSource('master'); //$dataSource = $this->getDataSource(); //$dataSource->begin(); try { // 初回回答か再回答かを確認している // 初めは「ID」がPOSTに入っているかどうかで判断しようと思っていたが // Cakeは簡単にブラウザの「戻る」で前画面を表示させたりするので、 // POSTのIDは再回答であるにもかかわらず空ってことがありうる // なので毎回DBチェックするしかないかと思う I think so. // サマリレコード取得 $summary = $this->QuestionnaireAnswerSummary->forceGetAnswerSummary($questionnaire, $userId, $sessionId, array('questionnaire_origin_id' => $questionnaire['Questionnaire']['origin_id'], 'answer_status' => QuestionnairesComponent::ACTION_NOT_ACT, 'session_value' => $sessionId, 'user_id' => $userId)); $summaryId = $summary['QuestionnaireAnswerSummary']['id']; // foreach ($data as $answer) { // 質問によってバリデーション動作が変わるので $targetQuestion = Hash::extract($questionnaire['QuestionnairePage'], '{n}.QuestionnaireQuestion.{n}[origin_id=' . $answer['questionnaire_question_origin_id'] . ']'); $this->validator()->getField('answer_value')->setRule('answerValidation', array('rule' => array('checkAnswerValue', $targetQuestion[0], $answer, 'message' => ''))); // データ保存 if (QuestionnairesComponent::isMatrixInputType($targetQuestion[0]['question_type'])) { foreach ($answer as $ans) { if (!$this->__saveAnswer($ans, $summaryId, $summary)) { $errors[$ans['questionnaire_question_origin_id']] = $this->validationErrors; } } } else { if (!$this->__saveAnswer($answer, $summaryId, $summary)) { $errors[$answer['questionnaire_question_origin_id']] = $this->validationErrors; } } } //$dataSource->commit(); } catch (Exception $ex) { //$dataSource->rollback(); CakeLog::error($ex); throw $ex; } if (count($errors) == 0) { return true; } else { return false; } }
/** * __aggrigateAnswer * 集計処理の実施 * * @param array $questionnaire アンケート情報 * @param bool $contentEditable 編集可能フラグ * @param array &$questions アンケート質問(集計結果を配列追加して返します) * @return void */ private function __aggrigateAnswer($questionnaire, $contentEditable, &$questions) { // 集計データを集める際の基本条件 $baseConditions = $this->QuestionnaireAnswerSummary->getResultCondition($questionnaire); //質問毎に、まとめあげる. //$questionsは、questionnaire_question_origin_idをキーとし、questionnaire_question配下が代入されている。 // foreach ($questions as &$question) { if ($question['is_result_display'] != QuestionnairesComponent::EXPRESSION_SHOW) { //集計表示をしない、なので飛ばす continue; } // 戻り値の、この質問の合計回答数を記録しておく。 // skip ロジックがあるため、単純にsummaryのcountじゃない.. $questionConditions = $baseConditions + array('QuestionnaireAnswer.questionnaire_question_origin_id' => $question['origin_id']); $question['answer_total_cnt'] = $this->QuestionnaireAnswer->getAnswerCount($questionConditions); if (QuestionnairesComponent::isMatrixInputType($question['question_type'])) { $this->__aggrigateAnswerForMatrix($question, $questionConditions); } else { $this->__aggrigateAnswerForNotMatrix($question, $questionConditions); } } }
/** * __getRow * * @param array $questionnaire questionnaire data * @param array $summary answer summary * @param array $answers answer data * @return array */ private function __getRows($questionnaire, $summary, $answers) { // ページ、質問のループから、取り出すべき質問のIDを順番に取り出す // question loop // 返却用配列にquestionのIDにマッチするAnswerを配列要素として追加、Answerがないときは空文字 // なお選択肢系のものはchoice_idが回答にくっついているのでそれを削除する // MatrixのものはMatrixの行数分返却行の列を加える // その他の選択肢の場合は、入力されたその他のテキストを入れる $cols = array(); $cols[] = $questionnaire['Questionnaire']['is_anonymity'] ? __d('questionnaires', 'Anonymity') : $summary['TrackableCreator']['username']; $cols[] = $summary['QuestionnaireAnswerSummaryCsv']['modified']; $cols[] = $summary['QuestionnaireAnswerSummaryCsv']['answer_number']; foreach ($questionnaire['QuestionnairePage'] as $page) { foreach ($page['QuestionnaireQuestion'] as $question) { if (QuestionnairesComponent::isMatrixInputType($question['question_type'])) { foreach ($question['QuestionnaireChoice'] as $choice) { if ($choice['matrix_type'] == QuestionnairesComponent::MATRIX_TYPE_ROW_OR_NO_MATRIX) { $cols[] = $this->__getMatrixAns($question, $choice, $answers); } } } else { $cols[] = $this->__getAns($question, $answers); } } } return array_map(array($this, 'convertCode'), $cols); }