-
Notifications
You must be signed in to change notification settings - Fork 3
/
QuestionnaireAnswerMatrixSingleChoiceBehavior.php
226 lines (211 loc) · 6.71 KB
/
QuestionnaireAnswerMatrixSingleChoiceBehavior.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
<?php
/**
* QuestionnaireValidate Behavior
*
* @author Noriko Arai <arai@nii.ac.jp>
* @author Allcreator <info@allcreator.net>
* @link http://www.netcommons.org NetCommons Project
* @license http://www.netcommons.org/license.txt NetCommons License
* @copyright Copyright 2014, NetCommons Project
*/
App::uses('QuestionnaireAnswerBehavior', 'Questionnaires.Model/Behavior');
/**
* SingleList Behavior
*
* @package Questionnaires\Questionnaires\Model\Befavior\Answer
* @author Allcreator <info@allcreator.net>
*/
class QuestionnaireAnswerMatrixSingleChoiceBehavior extends QuestionnaireAnswerBehavior {
/**
* this answer type
*
* @var int
*/
protected $_myType = QuestionnairesComponent::TYPE_MATRIX_SELECTION_LIST;
/**
* this answer type
* data in database must be changed to array
*
* @var int
*/
protected $_isTypeAnsChgArr = true;
/**
* this answer type
* data array must be shift up for post data array in screen
*
* @var int
*/
protected $_isTypeAnsArrShiftUp = true;
/**
* matrix validate check type
*
* @var array
*/
protected $_matrixValidateType = array(
QuestionnairesComponent::TYPE_MATRIX_SELECTION_LIST,
QuestionnairesComponent::TYPE_MATRIX_MULTIPLE,
);
/**
* beforeValidate is called before a model is validated, you can use this callback to
* add behavior validation rules into a models validate array. Returning false
* will allow you to make the validation fail.
*
* @param Model $model Model using this behavior
* @param array $options Options passed from Model::save().
* @return mixed False or null will abort the operation. Any other result will continue.
* @see Model::save()
*/
public function beforeValidate(Model $model, $options = array()) {
$question = $options['question'];
if ($question['question_type'] != $this->_myType) {
return;
}
$model->data['QuestionnaireAnswer']['matrix_answer_values'] = array();
$matrixChoiceId = $model->data['QuestionnaireAnswer']['matrix_choice_key'];
if (isset($model->data['QuestionnaireAnswer']['answer_value'])) {
$this->_decomposeAnswerValue(
$model->data['QuestionnaireAnswer']['answer_values'],
$model->data['QuestionnaireAnswer']['answer_value']);
$this->_decomposeAnswerValue(
$model->data['QuestionnaireAnswer']['matrix_answer_values'][$matrixChoiceId],
$model->data['QuestionnaireAnswer']['answer_value']);
}
$this->_setupOtherAnswerValue($model, $question);
}
/**
* answerValidation 回答内容の正当性
*
* @param object &$model use model
* @param array $data Validation対象データ
* @param array $question 回答データに対応する質問
* @param array $allAnswers 入力された回答すべて
* @return bool
*/
public function answerMatrixValidation(&$model, $data, $question, $allAnswers) {
if (! in_array($question['question_type'], $this->_matrixValidateType)) {
return true;
}
$ret = true;
if (isset($model->data['QuestionnaireAnswer']['matrix_answer_values'])) {
$list = [];
foreach ($question['QuestionnaireChoice'] as $item) {
$list[$item['key']] = $item['key'];
}
if (! $this->checkMatrixAnswerInList(
$model,
$model->data['QuestionnaireAnswer']['matrix_answer_values'],
$list)) {
$ret = false;
}
if (! $this->checkMatrixOtherAnswer(
$model,
$question,
$model->data['QuestionnaireAnswer']['matrix_answer_values'],
$model->data['QuestionnaireAnswer'])) {
$ret = false;
}
if (! $this->checkMatrixAnswerFill(
$model,
$question,
$model->data['QuestionnaireAnswer'],
$allAnswers)) {
$ret = false;
}
}
return $ret;
}
/**
* checkMatrixAnswerInList
*
* @param object &$model use model
* @param string $answers answer value
* @param array $list choice list ( choice key list)
* @return bool
*/
public function checkMatrixAnswerInList(&$model, $answers, $list) {
$ret = true;
foreach ($answers as $matrixRowId => $matrixColAns) {
if (!Validation::inList(strval($matrixRowId), $list)) {
$ret = false;
$model->validationErrors['answer_value'][] = __d('questionnaires', 'Invalid choice');
}
$choiceIds = array_keys($matrixColAns);
foreach ($choiceIds as $choiceId) {
if ($choiceId != '' && !Validation::inList(strval($choiceId), $list)) {
$ret = false;
$model->validationErrors['answer_value'][] = __d('questionnaires', 'Invalid choice');
}
}
}
return $ret;
}
/**
* checkMatrixOtherAnswer
*
* @param object &$model use model
* @param array $question question
* @param string $answers answer value
* @param string $otherAnswer other answer string
* @return bool
*/
public function checkMatrixOtherAnswer(&$model, $question, $answers, $otherAnswer) {
// このやり方だと、「その他」行がマトリクスにある時は必ず入力しなきゃいけなくなる?
// 選択肢を何も選択しなかったらAnswerデータが飛んでこないからチェックにかからないか?
$rowIds = array_keys($answers);
$checkOtherChoiceArr = [];
foreach ($question['QuestionnaireChoice'] as $choice) {
$hasOtherChoice = false;
if ($choice['other_choice_type'] != QuestionnairesComponent::OTHER_CHOICE_TYPE_NO_OTHER_FILED) {
$hasOtherChoice = true;
}
$checkOtherChoiceArr[$choice['key']] = $hasOtherChoice;
}
foreach ($rowIds as $matrixRowId) {
if (isset($checkOtherChoiceArr[$matrixRowId]) &&
$checkOtherChoiceArr[$matrixRowId]) {
if (empty($otherAnswer['other_answer_value'])) {
$model->validationErrors['answer_value'][] =
__d('questionnaires', 'Please enter something in other item');
return false;
}
}
}
return true;
}
/**
* checkMatrixAnswerFill
*
* @param object &$model use model
* @param array $question question
* @param string $answers all row answer value
* @param array $allAnswers 入力された回答すべて
* @return array error message
*/
public function checkMatrixAnswerFill(&$model, $question, $answers, $allAnswers) {
if ($model->oneTimeValidateFlag) { // チェック済
return true;
}
// マトリクスの場合は全行回答するか全行回答しないかでないと集計計算が狂うので
// 全行回答か全行無回答かを確認している
$answerCount = 0;
$noAnswerCount = 0;
$checkAnswer = $allAnswers[$question['key']];
foreach ($checkAnswer as $ans) {
if (!isset($ans['id'])) {
// id すらないのはblackhole対応のためのhidden要素であるので無視
continue;
}
if ($ans['answer_value'] == '') {
$noAnswerCount++;
}
$answerCount++;
}
$model->oneTimeValidateFlag = true; // チェックした
if ($noAnswerCount > 0 && $noAnswerCount < $answerCount) {
$model->validationErrors['answer_value'][] =
__d('questionnaires', 'Please answer about all rows.');
return false;
}
return true;
}
}