MDL-19937 workshop: migration of comments (no grading) strategy
[moodle.git] / question / type / multianswer / edit_multianswer_form.php
CommitLineData
aeb15530 1<?php
271ffe3f 2/**
3 * Defines the editing form for the multianswer question type.
4 *
5 * @copyright &copy; 2007 Jamie Pratt
6 * @author Jamie Pratt me@jamiep.org
7 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
830e47a8 8 * @package questionbank
9 * @subpackage questiontypes
271ffe3f 10 */
11
12/**
13 * multianswer editing form definition.
14 */
15class question_edit_multianswer_form extends question_edit_form {
16
705b5874 17 // $questiondisplay will contain the qtype_multianswer_extract_question from the questiontext
f34488b2 18 var $questiondisplay ;
d3e3bd6c 19 // $savedquestiondisplay will contain the qtype_multianswer_extract_question from the questiontext in database
20 var $savedquestion ;
21 var $savedquestiondisplay ;
22 var $used_in_quiz = false ;
23 var $qtype_change = false ;
24 var $negative_diff = false ;
25 var $nb_of_quiz = 0;
26 var $nb_of_attempts = 0;
27 public $confirm = 0 ;
28 public $reload = false ;
aeb15530 29
d3e3bd6c 30 function question_edit_multianswer_form(&$submiturl, &$question, &$category, &$contexts, $formeditable = true){
31 global $QTYPES, $SESSION, $CFG, $DB;
8e8f9f3d 32 /* $this->regenerate = true;
d3e3bd6c 33 if ( "1" == optional_param('reload','', PARAM_INT )) {
34 $this->reload = true ;
35 }else {
36 $this->reload = false ;
37 }
38 // $this->question = $question;
39 //$used_in_quiz =false;
8e8f9f3d 40 echo "<p> question <pre>";print_r($question);echo "</pre></p>";
d3e3bd6c 41 if(! empty($question->id)){
42 $this->savedquestiondisplay =fullclone($question ) ;
43 if ($list = $DB->get_records('quiz_question_instances', array( 'question'=> $question->id))){
44 foreach($list as $key => $li){
45 $this->nb_of_quiz ++;
46 if($att = $DB->get_records('quiz_attempts',array( 'quiz'=> $li->quiz, 'preview'=> '0'))){
47 $this->nb_of_attempts+= count($att);
48 $this->used_in_quiz = true;
49 }
50 }
51 }
52 }
53
aeb15530 54
8e8f9f3d 55*/
aeb15530
PS
56
57
d3e3bd6c 58 parent::question_edit_form($submiturl, $question, $category, $contexts, $formeditable);
59 }
60
aeb15530 61
705b5874 62
63 function definition_inner(&$mform) {
8e8f9f3d
PP
64 // $mform->addElement('hidden', 'reload', 1);
65 // $mform->setType('reload', PARAM_INT);
e2ae84a2 66 $question_type_names = question_type_menu();
120e5cbf 67 $mform->addRule('questiontext', null, 'required', null, 'client');
705b5874 68
fe648028 69 // Remove meaningless defaultgrade field.
70 $mform->removeElement('defaultgrade');
8e8f9f3d 71 /* $this->confirm = optional_param('confirm','0', PARAM_RAW);
f34488b2 72
705b5874 73 // display the questions from questiontext;
74 if ( "" != optional_param('questiontext','', PARAM_RAW)) {
f34488b2 75
705b5874 76 $this->questiondisplay = fullclone(qtype_multianswer_extract_question(optional_param('questiontext','', PARAM_RAW))) ;
f34488b2 77
705b5874 78 }else {
aeb15530
PS
79 if(!$this->reload && !empty($this->savedquestiondisplay->id)){
80 // use database data as this is first pass
d3e3bd6c 81 // question->id == 0 so no stored datasets
82 $this->questiondisplay = fullclone($this->savedquestiondisplay);
83 foreach($this->questiondisplay->options->questions as $subquestion){
84 if (!empty($subquestion)){
85 $subquestion->answer = array('');
86 foreach($subquestion->options->answers as $ans){
87 $subquestion->answer[]=$ans->answer ;
88 }
89 // $subquestion->answer = fullclone($subquestion->options->answers);
aeb15530
PS
90 }
91 }
92 }else {
d3e3bd6c 93 $this->questiondisplay = "";
94 }
f34488b2 95 }
705b5874 96
d3e3bd6c 97 if ( isset($this->savedquestiondisplay->options->questions) && is_array($this->savedquestiondisplay->options->questions) ) {
98 $countsavedsubquestions =0;
99 foreach($this->savedquestiondisplay->options->questions as $subquestion){
103a800d 100 if (!empty($subquestion)){
d3e3bd6c 101 $countsavedsubquestions++;
df79079f 102 }
f34488b2 103 }
705b5874 104 } else {
d3e3bd6c 105 $countsavedsubquestions =0;
705b5874 106 }
d3e3bd6c 107 if ($this->reload){
108 if ( isset($this->questiondisplay->options->questions) && is_array($this->questiondisplay->options->questions) ) {
109 $countsubquestions =0;
110 foreach($this->questiondisplay->options->questions as $subquestion){
111 if (!empty($subquestion)){
112 $countsubquestions++;
113 }
114 }
115 } else {
116 $countsubquestions =0;
117 }
118 }else{
119 $countsubquestions =$countsavedsubquestions ;
705b5874 120 }
d3e3bd6c 121 // echo "<p> saved question $countsavedsubquestions <pre>";print_r($this->savedquestiondisplay);echo "</pre></p>";
122 // echo "<p> saved question $countsubquestions <pre>";print_r($this->questiondisplay);echo "</pre></p>";
aeb15530
PS
123
124
d3e3bd6c 125 $mform->addElement('submit', 'analyzequestion', get_string('decodeverifyquestiontext','qtype_multianswer'));
126 $mform->registerNoSubmitButton('analyzequestion');
127 echo '<div class="ablock clearfix">';
128 echo '<div class=" clearfix">';
129 if ( $this->reload ){
130 for ($sub =1;$sub <=$countsubquestions ;$sub++) {
aeb15530 131
d3e3bd6c 132 $this->editas[$sub] = 'unknown type';
133 if (isset( $this->questiondisplay->options->questions[$sub]->qtype) ) {
134 $this->editas[$sub] = $this->questiondisplay->options->questions[$sub]->qtype ;
135 } else if (optional_param('sub_'.$sub."_".'qtype', '', PARAM_RAW) != '') {
136 $this->editas[$sub] = optional_param('sub_'.$sub."_".'qtype', '', PARAM_RAW);
fd97082c 137 }
d3e3bd6c 138 $storemess = '';
aeb15530 139 if(isset($this->savedquestiondisplay->options->questions[$sub]->qtype) &&
d3e3bd6c 140 $this->savedquestiondisplay->options->questions[$sub]->qtype != $this->questiondisplay->options->questions[$sub]->qtype ){
141 $this->type_change = true ;
142 $storemess = "<font class=\"error\"> STORED QTYPE ".$question_type_names[$this->savedquestiondisplay->options->questions[$sub]->qtype]."</font >";
f34488b2 143 }
aeb15530 144
d3e3bd6c 145 $mform->addElement('header', 'subhdr'.$sub, get_string('questionno', 'quiz',
146 '{#'.$sub.'}').'&nbsp;'.$question_type_names[$this->questiondisplay->options->questions[$sub]->qtype].$storemess);
aeb15530 147
d3e3bd6c 148 $mform->addElement('static', 'sub_'.$sub."_".'questiontext', get_string('questiondefinition','qtype_multianswer'),array('cols'=>60, 'rows'=>3));
aeb15530 149
d3e3bd6c 150 if (isset ( $this->questiondisplay->options->questions[$sub]->questiontext)) {
151 $mform->setDefault('sub_'.$sub."_".'questiontext', $this->questiondisplay->options->questions[$sub]->questiontext);
f34488b2 152 }
aeb15530 153
d3e3bd6c 154 $mform->addElement('static', 'sub_'.$sub."_".'defaultgrade', get_string('defaultgrade', 'quiz'));
155 $mform->setDefault('sub_'.$sub."_".'defaultgrade',$this->questiondisplay->options->questions[$sub]->defaultgrade);
aeb15530 156
d3e3bd6c 157 if ($this->questiondisplay->options->questions[$sub]->qtype =='shortanswer' ) {
158 $mform->addElement('static', 'sub_'.$sub."_".'usecase', get_string('casesensitive', 'quiz'));
159 }
aeb15530 160
d3e3bd6c 161 if ($this->questiondisplay->options->questions[$sub]->qtype =='multichoice' ) {
162 $mform->addElement('static', 'sub_'.$sub."_".'layout', get_string('layout', 'qtype_multianswer'),array('cols'=>60, 'rows'=>1)) ;//, $gradeoptions);
163 }
164 foreach ($this->questiondisplay->options->questions[$sub]->answer as $key =>$ans) {
aeb15530 165
d3e3bd6c 166 $mform->addElement('static', 'sub_'.$sub."_".'answer['.$key.']', get_string('answer', 'quiz'), array('cols'=>60, 'rows'=>1));
aeb15530 167
d3e3bd6c 168 if ($this->questiondisplay->options->questions[$sub]->qtype =='numerical' && $key == 0 ) {
169 $mform->addElement('static', 'sub_'.$sub."_".'tolerance['.$key.']', get_string('acceptederror', 'quiz')) ;//, $gradeoptions);
170 }
aeb15530 171
d3e3bd6c 172 $mform->addElement('static', 'sub_'.$sub."_".'fraction['.$key.']', get_string('grade')) ;//, $gradeoptions);
aeb15530 173
d3e3bd6c 174 $mform->addElement('static', 'sub_'.$sub."_".'feedback['.$key.']', get_string('feedback', 'quiz'));
175 }
aeb15530 176
f34488b2 177 }
d3e3bd6c 178 echo '</div>';
90a92bd0
PP
179 $this->negative_diff =$countsavedsubquestions - $countsubquestions ;
180 if ( ($this->negative_diff > 0 ) ||$this->type_change || ($this->used_in_quiz && $this->negative_diff != 0)){
d3e3bd6c 181 $mform->addElement('header', 'additemhdr', "WARNING");
182 }
90a92bd0 183 if($this->negative_diff > 0) {
d3e3bd6c 184 //$this->used_in_quiz
aeb15530 185
d3e3bd6c 186 $mform->addElement('static', 'alert1', "<strong>"."Question deleted"."</strong>","<strong>".$this->negative_diff.get_string(' questions less than in the multtianswer question stored in the database','qtype_multianswer')."</strong>");//$countsubquestions."-".$countsavedsubquestions
187 }
188 if($this->type_change )
189 {
190 //$this->used_in_quiz
aeb15530 191
d3e3bd6c 192 // $mform->addElement('header', 'additemhdr', "WARNING");
193 $mform->addElement('static', 'alert1', "<strong>"."Question type change "."</strong>","<strong>".get_string(' at least one question type has been changed. Did you add,delete or move a question ? Look ahead ','qtype_multianswer')."</strong>");//$countsubquestions."-".$countsavedsubquestions
194 }
195 echo '</div>';
196 }
197 if( $this->used_in_quiz){
90a92bd0 198 if($this->negative_diff < 0) {
d3e3bd6c 199 $diff = $countsubquestions - $countsavedsubquestions;
200 $mform->addElement('static', 'alert1', "<strong>"."Question added "."</strong>","<strong>".$diff.get_string(' questions more than in the multtianswer question stored in the database','qtype_multianswer')."</strong>");//$countsubquestions."-".$countsavedsubquestions
201 }
202 $mform->addElement('header', 'additemhdr2', "This question is used in $this->nb_of_quiz quiz(s), total attempt(s) : $this->nb_of_attempts ");
203 $mform->addElement('static', 'alertas', "<strong>"."YOU SHOULD NOT "."</strong>");//$countsubquestions."-".$countsavedsubquestions
204 }
90a92bd0 205 if ( ($this->negative_diff > 0 || $this->used_in_quiz && ($this->negative_diff > 0 ||$this->negative_diff < 0 || $this->type_change ) ) && $this->reload ){
aeb15530 206 $mform->addElement('header', 'additemhdr', get_string('The question will be saved as edited', 'qtype_calculatedsimple'));
d3e3bd6c 207 $mform->addElement('checkbox', 'confirm','' ,get_string('I confirm that I want the question be saved as edited', 'qtype_calculatedsimple'));
208 $mform->setDefault('confirm', 0);
aeb15530 209 }else {
d3e3bd6c 210 $mform->addElement('hidden', 'confirm',0);
705b5874 211 }
8e8f9f3d 212*/
120e5cbf 213 }
705b5874 214
f34488b2 215
32db0d42 216 function set_data($question) {
f34488b2 217 global $DB;
705b5874 218 $default_values =array();
120e5cbf 219 if (isset($question->id) and $question->id and $question->qtype and $question->questiontext) {
c6fc9988 220
221 foreach ($question->options->questions as $key => $wrapped) {
103a800d 222 if(!empty($wrapped)){
c6fc9988 223 // The old way of restoring the definitions is kept to gradually
224 // update all multianswer questions
225 if (empty($wrapped->questiontext)) {
226 $parsableanswerdef = '{' . $wrapped->defaultgrade . ':';
227 switch ($wrapped->qtype) {
228 case 'multichoice':
229 $parsableanswerdef .= 'MULTICHOICE:';
230 break;
231 case 'shortanswer':
232 $parsableanswerdef .= 'SHORTANSWER:';
233 break;
234 case 'numerical':
235 $parsableanswerdef .= 'NUMERICAL:';
236 break;
237 default:
2471ef86 238 print_error('unknownquestiontype', 'question', '', $wrapped->qtype);
c6fc9988 239 }
240 $separator= '';
241 foreach ($wrapped->options->answers as $subanswer) {
242 $parsableanswerdef .= $separator
243 . '%' . round(100*$subanswer->fraction) . '%';
244 $parsableanswerdef .= $subanswer->answer;
245 if (!empty($wrapped->options->tolerance)) {
246 // Special for numerical answers:
247 $parsableanswerdef .= ":{$wrapped->options->tolerance}";
248 // We only want tolerance for the first alternative, it will
249 // be applied to all of the alternatives.
250 unset($wrapped->options->tolerance);
251 }
252 if ($subanswer->feedback) {
253 $parsableanswerdef .= "#$subanswer->feedback";
254 }
255 $separator = '~';
256 }
257 $parsableanswerdef .= '}';
258 // Fix the questiontext fields of old questions
f34488b2 259 $DB->set_field('question', 'questiontext', $parsableanswerdef, array('id' => $wrapped->id));
c6fc9988 260 } else {
261 $parsableanswerdef = str_replace('&#', '&\#', $wrapped->questiontext);
262 }
263 $question->questiontext = str_replace("{#$key}", $parsableanswerdef, $question->questiontext);
264 }
265 }
df79079f 266 }
8e8f9f3d 267/*
705b5874 268 // set default to $questiondisplay questions elements
f34488b2 269 if (isset($this->questiondisplay->options->questions)) {
270 $subquestions = fullclone($this->questiondisplay->options->questions) ;
705b5874 271 if (count($subquestions)) {
f34488b2 272 $sub =1;
273 foreach ($subquestions as $subquestion) {
705b5874 274 $prefix = 'sub_'.$sub.'_' ;
275
276 // validate parameters
277 $answercount = 0;
278 $maxgrade = false;
279 $maxfraction = -1;
fd97082c 280 if ($subquestion->qtype =='shortanswer' ) {
281 switch ($subquestion->usecase) {
282 case '1':
283 $default_values[$prefix.'usecase']= get_string('caseyes', 'quiz');
aeb15530 284 break;
fd97082c 285 case '0':
286 default :
aeb15530 287 $default_values[$prefix.'usecase']= get_string('caseno', 'quiz');
fd97082c 288 }
289 }
290
e5ebbd53 291 if ($subquestion->qtype == 'multichoice' ) {
292 $default_values[$prefix.'layout'] = $subquestion->layout ;
293 switch ($subquestion->layout) {
294 case '0':
665e82f8 295 $default_values[$prefix.'layout']= get_string('layoutselectinline', 'qtype_multianswer');
e5ebbd53 296 break;
297 case '1':
665e82f8 298 $default_values[$prefix.'layout']= get_string('layoutvertical', 'qtype_multianswer');
aeb15530 299 break;
e5ebbd53 300 case '2':
665e82f8 301 $default_values[$prefix.'layout']= get_string('layouthorizontal', 'qtype_multianswer');
e5ebbd53 302 break;
303 default:
665e82f8 304 $default_values[$prefix.'layout']= get_string('layoutundefined', 'qtype_multianswer');
aeb15530 305 }
e5ebbd53 306 }
705b5874 307 foreach ($subquestion->answer as $key=>$answer) {
308 if ( $subquestion->qtype == 'numerical' && $key == 0 ) {
309 $default_values[$prefix.'tolerance['.$key.']'] = $subquestion->tolerance[0] ;
310 }
311 $trimmedanswer = trim($answer);
312 if ($trimmedanswer !== '') {
313 $answercount++;
314 if ($subquestion->qtype == 'numerical' && !(is_numeric($trimmedanswer) || $trimmedanswer == '*')) {
315 $this->_form->setElementError($prefix.'answer['.$key.']' , get_string('answermustbenumberorstar', 'qtype_numerical'));
316 }
317 if ($subquestion->fraction[$key] == 1) {
318 $maxgrade = true;
f34488b2 319 }
705b5874 320 if ($subquestion->fraction[$key] > $maxfraction) {
321 $maxfraction = $subquestion->fraction[$key] ;
322 }
323 }
f34488b2 324
665e82f8 325 $default_values[$prefix.'answer['.$key.']'] = htmlspecialchars ($answer);
f34488b2 326 }
705b5874 327 if ($answercount == 0) {
328 if ($subquestion->qtype == 'multichoice' ) {
329 $this->_form->setElementError($prefix.'answer[0]' , get_string('notenoughanswers', 'qtype_multichoice', 2));
330 } else {
331 $this->_form->setElementError($prefix.'answer[0]' , get_string('notenoughanswers', 'quiz', 1));
332 }
333 }
334 if ($maxgrade == false) {
335 $this->_form->setElementError($prefix.'fraction[0]' ,get_string('fractionsnomax', 'question'));
f34488b2 336 }
705b5874 337 foreach ($subquestion->feedback as $key=>$answer) {
f34488b2 338
665e82f8 339 $default_values[$prefix.'feedback['.$key.']'] = htmlspecialchars ($answer);
f34488b2 340 }
705b5874 341 foreach ( $subquestion->fraction as $key=>$answer) {
342 $default_values[$prefix.'fraction['.$key.']'] = $answer;
f34488b2 343 }
344
345
346 $sub++;
705b5874 347 }
348 }
349 }
03adfa13 350 if (( $this->negative_diff || $this->used_in_quiz && ($this->negative_diff > 0 ||$this->negative_diff < 0 || $this->type_change ))&& $this->confirm == 0 ){
d3e3bd6c 351 $this->_form->setElementError('confirm',"confirm then save");
aeb15530
PS
352 }
353 $default_values['alertas']= "<strong>".get_string("
354
d3e3bd6c 355<ul>
356 <li>add or delete questions, </li>
357 <li>change the questions order in the text,</li>
358 <li>change their question type (numerical, shortanswer, multiple choice). </li></ul>
359",'qtype_multianswer')."</strong>";
8e8f9f3d 360*/
d3e3bd6c 361 if( $default_values != "") {
705b5874 362 $question = (object)((array)$question + $default_values);
363 }
120e5cbf 364 parent::set_data($question);
365 }
366
a78890d5 367 function validation($data, $files) {
368 $errors = parent::validation($data, $files);
8e8f9f3d
PP
369/* echo "<p> errors<pre>";print_r($errors);echo "</pre></p>";
370
705b5874 371 if (isset($this->questiondisplay->options->questions)) {
f34488b2 372
373 $subquestions = fullclone($this->questiondisplay->options->questions) ;
705b5874 374 if (count($subquestions)) {
f34488b2 375 $sub =1;
376 foreach ($subquestions as $subquestion) {
705b5874 377 $prefix = 'sub_'.$sub.'_' ;
378 $answercount = 0;
379 $maxgrade = false;
380 $maxfraction = -1;
aeb15530 381 if(isset($this->savedquestiondisplay->options->questions[$sub]->qtype) &&
d3e3bd6c 382 $this->savedquestiondisplay->options->questions[$sub]->qtype != $this->questiondisplay->options->questions[$sub]->qtype ){
383 $storemess = " STORED QTYPE ".$question_type_names[$this->savedquestiondisplay->options->questions[$sub]->qtype];
384 }
385 // $errors['subhdr'.$sub]=$storemess ;
705b5874 386 foreach ( $subquestion->answer as $key=>$answer) {
387 $trimmedanswer = trim($answer);
388 if ($trimmedanswer !== '') {
389 $answercount++;
390 if ($subquestion->qtype =='numerical' && !(is_numeric($trimmedanswer) || $trimmedanswer == '*')) {
391 $errors[$prefix.'answer['.$key.']']= get_string('answermustbenumberorstar', 'qtype_numerical');
392 }
393 if ($subquestion->fraction[$key] == 1) {
394 $maxgrade = true;
f34488b2 395 }
705b5874 396 if ($subquestion->fraction[$key] > $maxfraction) {
397 $maxfraction = $subquestion->fraction[$key] ;
398 }
f34488b2 399 }
400 }
705b5874 401 if ($answercount==0) {
402 if ( $subquestion->qtype =='multichoice' ) {
403 $errors[$prefix.'answer[0]']= get_string('notenoughanswers', 'qtype_multichoice', 2);
404 }else {
405 $errors[$prefix.'answer[0]'] = get_string('notenoughanswers', 'quiz', 1);
406 }
407 }
408 if ($maxgrade == false) {
409 $errors[$prefix.'fraction[0]']=get_string('fractionsnomax', 'question');
f34488b2 410 }
411 $sub++;
705b5874 412 }
413 } else {
f34488b2 414 $errors['questiontext']=get_string('questionsmissing', 'qtype_multianswer');
705b5874 415 }
120e5cbf 416 }
705b5874 417
8e8f9f3d
PP
418 echo "<p> errors<pre>";print_r($errors);echo "</pre></p>";
419*/
420 return $errors;
c6fc9988 421 }
271ffe3f 422
423 function qtype() {
424 return 'multianswer';
425 }
426}
aeb15530 427