-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathQuizQuestionValidateBehavior.php
More file actions
173 lines (166 loc) · 5.54 KB
/
QuizQuestionValidateBehavior.php
File metadata and controls
173 lines (166 loc) · 5.54 KB
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
<?php
/**
* QuizQuestionValidate 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('ModelBehavior', 'Model');
/**
* QuizQuestionChoice Behavior
*
* @package Quizzes\Quizzes\Model\Befavior\QuizQuestionChoice
* @author Allcreator <info@allcreator.net>
*/
class QuizQuestionValidateBehavior extends ModelBehavior {
/**
* setup
*
* @param Model $Model モデル
* @param array $settings 設定値
* @return void
*/
public function setup(Model $Model, $settings = array()) {
$this->settings[$Model->alias] = $settings;
}
/**
* 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()) {
// 付属の選択肢以下のvalidate
if ($this->_checkChoiceExists($model)) {
$this->_checkChoiceIsUnique($model);
// この質問種別に必要な選択肢データがちゃんとあるなら選択肢をバリデート
$validationErrors = array();
foreach ($model->data['QuizChoice'] as $cIndex => $choice) {
// 選択肢データ確認
$model->QuizChoice->create();
$model->QuizChoice->set($choice);
$options['choiceIndex'] = $cIndex;
if (! $model->QuizChoice->validates($options)) {
$validationErrors['QuizChoice'][$cIndex] = $model->QuizChoice->validationErrors;
}
}
$model->validationErrors += $validationErrors;
}
if ($this->_checkCorrectExists($model)) {
$this->_checkCorrectInChoice($model);
foreach ($model->data['QuizCorrect'] as $correct) {
$model->QuizCorrect->create();
$model->QuizCorrect->set($correct);
if (! $model->QuizCorrect->validates()) {
$model->validationErrors['question_pickup_error'][] =
__d('quizzes', 'please set at least one correct.');
}
}
}
// このPickupErrorはAngularのng-repeatで処理するので、
// 同じメッセージがあるとエラーになっちゃう
if (! empty($model->validationErrors['question_pickup_error'])) {
$pickupError = array_flip($model->validationErrors['question_pickup_error']);
$model->validationErrors['question_pickup_error'] = array_flip($pickupError);
}
}
/**
* _checkChoiceExists
*
* 適正な選択肢を持っているか
*
* @param Model $model Model using this behavior
* @return bool
*/
protected function _checkChoiceExists($model) {
$questionType = $model->data['QuizQuestion']['question_type'];
// 単語系、記述式の時は選択肢不要
if (! QuizzesComponent::isSelectionInputType($questionType)) {
return false;
}
// 上記以外の場合は最低1つは必要
if (! Hash::check($model->data, 'QuizChoice.{n}')) {
$model->validationErrors['question_pickup_error'][] =
__d('quizzes', 'please set at least one choice.');
return false;
}
return true;
}
/**
* _checkChoiceIsUnique
*
* 選択肢はユニークになっているか
*
* @param Model $model Model using this behavior
* @return bool
*/
protected function _checkChoiceIsUnique($model) {
$questionType = $model->data['QuizQuestion']['question_type'];
// 択一、複数以外の時はチェック不要
if (! QuizzesComponent::isSelectionInputType($questionType)) {
return true;
}
$choices = Hash::extract($model->data, 'QuizChoice.{n}.choice_label');
$uniqueChoices = array_unique($choices);
if ($uniqueChoices != $choices) {
$model->validationErrors['question_pickup_error'][] =
__d('quizzes', 'There is a choice of the same value.');
return false;
}
return true;
}
/**
* _checkCorrectExists
*
* 適正な正解を持っているか
*
* @param Model $model Model using this behavior
* @return bool
*/
protected function _checkCorrectExists($model) {
$questionType = $model->data['QuizQuestion']['question_type'];
// 記述式の時は正解不要
if ($questionType == QuizzesComponent::TYPE_TEXT_AREA) {
return false;
}
// 上記以外の場合は最低1つは必要
if (! Hash::check($model->data, 'QuizCorrect.{n}')) {
$model->validationErrors['question_pickup_error'][] =
__d('quizzes', 'please set at least one correct.');
return false;
}
return true;
}
/**
* _checkCorrectInChoice
*
* 正解は選択肢の中のものが設定されているか
*
* @param Model $model Model using this behavior
* @return bool
*/
protected function _checkCorrectInChoice($model) {
$questionType = $model->data['QuizQuestion']['question_type'];
// 択一、複数の時は正解データが選択肢の中にあることが前提
if (QuizzesComponent::isSelectionInputType($questionType)) {
// 択一、複数選択のときは、正解は必ず「0」番目のものしかありませんので0から取得
$corrects = Hash::extract($model->data, 'QuizCorrect.0.correct');
$choices = Hash::extract($model->data, 'QuizChoice.{n}.choice_label');
foreach ($corrects as $correct) {
if (! in_array($correct, $choices)) {
$model->validationErrors['question_pickup_error'][] =
__d('quizzes', 'Please set correct answer.');
return false;
}
}
}
return true;
}
}