See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 401]
1 <?php 2 3 // This file is part of Moodle - http://moodle.org/ 4 // 5 // Moodle is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Moodle is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 17 18 /** 19 * True/false 20 * 21 * @package mod_lesson 22 * @copyright 2009 Sam Hemelryk 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 **/ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** True/False question type */ 29 define("LESSON_PAGE_TRUEFALSE", "2"); 30 31 class lesson_page_type_truefalse extends lesson_page { 32 33 protected $type = lesson_page::TYPE_QUESTION; 34 protected $typeidstring = 'truefalse'; 35 protected $typeid = LESSON_PAGE_TRUEFALSE; 36 protected $string = null; 37 38 public function get_typeid() { 39 return $this->typeid; 40 } 41 public function get_typestring() { 42 if ($this->string===null) { 43 $this->string = get_string($this->typeidstring, 'lesson'); 44 } 45 return $this->string; 46 } 47 public function get_idstring() { 48 return $this->typeidstring; 49 } 50 public function display($renderer, $attempt) { 51 global $USER, $CFG, $PAGE; 52 $answers = $this->get_answers(); 53 foreach ($answers as $key => $answer) { 54 $answers[$key] = parent::rewrite_answers_urls($answer); 55 } 56 shuffle($answers); 57 58 $params = array('answers'=>$answers, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents(), 'attempt'=>$attempt); 59 $mform = new lesson_display_answer_form_truefalse($CFG->wwwroot.'/mod/lesson/continue.php', $params); 60 $data = new stdClass; 61 $data->id = $PAGE->cm->id; 62 $data->pageid = $this->properties->id; 63 $mform->set_data($data); 64 65 // Trigger an event question viewed. 66 $eventparams = array( 67 'context' => context_module::instance($PAGE->cm->id), 68 'objectid' => $this->properties->id, 69 'other' => array( 70 'pagetype' => $this->get_typestring() 71 ) 72 ); 73 74 $event = \mod_lesson\event\question_viewed::create($eventparams); 75 $event->trigger(); 76 return $mform->display(); 77 } 78 public function check_answer() { 79 global $DB, $CFG; 80 $formattextdefoptions = new stdClass(); 81 $formattextdefoptions->noclean = true; 82 $formattextdefoptions->para = false; 83 84 $answers = $this->get_answers(); 85 shuffle($answers); 86 $params = array('answers'=>$answers, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents()); 87 $mform = new lesson_display_answer_form_truefalse($CFG->wwwroot.'/mod/lesson/continue.php', $params); 88 $data = $mform->get_data(); 89 require_sesskey(); 90 91 $result = parent::check_answer(); 92 93 if (empty($data->answerid)) { 94 $result->noanswer = true; 95 return $result; 96 } 97 $result->answerid = $data->answerid; 98 $answer = $DB->get_record("lesson_answers", array("id" => $result->answerid), '*', MUST_EXIST); 99 $answer = parent::rewrite_answers_urls($answer); 100 if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { 101 $result->correctanswer = true; 102 } 103 if ($this->lesson->custom) { 104 if ($answer->score > 0) { 105 $result->correctanswer = true; 106 } else { 107 $result->correctanswer = false; 108 } 109 } 110 $result->newpageid = $answer->jumpto; 111 $result->response = format_text($answer->response, $answer->responseformat, $formattextdefoptions); 112 $result->studentanswer = $result->userresponse = $answer->answer; 113 return $result; 114 } 115 116 public function display_answers(html_table $table) { 117 $answers = $this->get_answers(); 118 $options = new stdClass(); 119 $options->noclean = true; 120 $options->para = false; 121 $i = 1; 122 foreach ($answers as $answer) { 123 $answer = parent::rewrite_answers_urls($answer); 124 $cells = array(); 125 if ($this->lesson->custom && $answer->score > 0) { 126 // if the score is > 0, then it is correct 127 $cells[] = '<label class="correct">' . get_string('answer', 'lesson') . " {$i}</label>: \n"; 128 } else if ($this->lesson->custom) { 129 $cells[] = '<label>' . get_string('answer', 'lesson') . " {$i}</label>: \n"; 130 } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { 131 // underline correct answers 132 $cells[] = '<span class="correct">' . get_string('answer', 'lesson') . " {$i}</span>: \n"; 133 } else { 134 $cells[] = '<label class="correct">' . get_string('answer', 'lesson') . " {$i}</label>: \n"; 135 } 136 $cells[] = format_text($answer->answer, $answer->answerformat, $options); 137 $table->data[] = new html_table_row($cells); 138 139 $cells = array(); 140 $cells[] = '<label>' . get_string('response', 'lesson') . ' ' . $i . '</label>:'; 141 $cells[] = format_text($answer->response, $answer->responseformat, $options); 142 $table->data[] = new html_table_row($cells); 143 144 $cells = array(); 145 $cells[] = '<label>' . get_string('score', 'lesson') . '</label>:'; 146 $cells[] = $answer->score; 147 $table->data[] = new html_table_row($cells); 148 149 $cells = array(); 150 $cells[] = '<label>' . get_string('jump', 'lesson') . '</label>:'; 151 $cells[] = $this->get_jump_name($answer->jumpto); 152 $table->data[] = new html_table_row($cells); 153 154 if ($i === 1){ 155 $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; 156 } 157 158 $i++; 159 } 160 return $table; 161 } 162 163 /** 164 * Updates the page and its answers 165 * 166 * @global moodle_database $DB 167 * @global moodle_page $PAGE 168 * @param stdClass $properties 169 * @return bool 170 */ 171 public function update($properties, $context = null, $maxbytes = null) { 172 global $DB, $PAGE; 173 $answers = $this->get_answers(); 174 $properties->id = $this->properties->id; 175 $properties->lessonid = $this->lesson->id; 176 $properties->timemodified = time(); 177 $properties = file_postupdate_standard_editor($properties, 'contents', array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes), context_module::instance($PAGE->cm->id), 'mod_lesson', 'page_contents', $properties->id); 178 $DB->update_record("lesson_pages", $properties); 179 180 // Trigger an event: page updated. 181 \mod_lesson\event\page_updated::create_from_lesson_page($this, $context)->trigger(); 182 183 // need to reset offset for correct and wrong responses 184 $this->lesson->maxanswers = 2; 185 for ($i = 0; $i < $this->lesson->maxanswers; $i++) { 186 if (!array_key_exists($i, $this->answers)) { 187 $this->answers[$i] = new stdClass; 188 $this->answers[$i]->lessonid = $this->lesson->id; 189 $this->answers[$i]->pageid = $this->id; 190 $this->answers[$i]->timecreated = $this->timecreated; 191 } 192 193 if (!empty($properties->answer_editor[$i]) && is_array($properties->answer_editor[$i])) { 194 $this->answers[$i]->answer = $properties->answer_editor[$i]['text']; 195 $this->answers[$i]->answerformat = $properties->answer_editor[$i]['format']; 196 } 197 198 if (!empty($properties->response_editor[$i]) && is_array($properties->response_editor[$i])) { 199 $this->answers[$i]->response = $properties->response_editor[$i]['text']; 200 $this->answers[$i]->responseformat = $properties->response_editor[$i]['format']; 201 } 202 203 // we don't need to check for isset here because properties called it's own isset method. 204 if ($this->answers[$i]->answer != '') { 205 if (isset($properties->jumpto[$i])) { 206 $this->answers[$i]->jumpto = $properties->jumpto[$i]; 207 } 208 if ($this->lesson->custom && isset($properties->score[$i])) { 209 $this->answers[$i]->score = $properties->score[$i]; 210 } 211 if (!isset($this->answers[$i]->id)) { 212 $this->answers[$i]->id = $DB->insert_record("lesson_answers", $this->answers[$i]); 213 } else { 214 $DB->update_record("lesson_answers", $this->answers[$i]->properties()); 215 } 216 // Save files in answers and responses. 217 $this->save_answers_files($context, $maxbytes, $this->answers[$i], 218 $properties->answer_editor[$i], $properties->response_editor[$i]); 219 } else if (isset($this->answers[$i]->id)) { 220 $DB->delete_records('lesson_answers', array('id'=>$this->answers[$i]->id)); 221 unset($this->answers[$i]); 222 } 223 } 224 return true; 225 } 226 227 public function stats(array &$pagestats, $tries) { 228 $temp = $this->lesson->get_last_attempt($tries); 229 if ($this->properties->qoption) { 230 $userresponse = explode(",", $temp->useranswer); 231 foreach ($userresponse as $response) { 232 if (isset($pagestats[$temp->pageid][$response])) { 233 $pagestats[$temp->pageid][$response]++; 234 } else { 235 $pagestats[$temp->pageid][$response] = 1; 236 } 237 } 238 } else { 239 if (isset($pagestats[$temp->pageid][$temp->answerid])) { 240 $pagestats[$temp->pageid][$temp->answerid]++; 241 } else { 242 $pagestats[$temp->pageid][$temp->answerid] = 1; 243 } 244 } 245 if (isset($pagestats[$temp->pageid]["total"])) { 246 $pagestats[$temp->pageid]["total"]++; 247 } else { 248 $pagestats[$temp->pageid]["total"] = 1; 249 } 250 return true; 251 } 252 253 public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { 254 $answers = $this->get_answers(); 255 $formattextdefoptions = new stdClass(); //I'll use it widely in this page 256 $formattextdefoptions->para = false; 257 $formattextdefoptions->noclean = true; 258 $formattextdefoptions->context = $answerpage->context; 259 260 foreach ($answers as $answer) { 261 $answer = parent::rewrite_answers_urls($answer); 262 $answertext = format_text($answer->answer, $answer->answerformat, $formattextdefoptions); 263 $correctresponsetext = html_writer::div(get_string('correctresponse', 'lesson'), 'badge badge-success'); 264 if ($this->properties->qoption) { 265 if ($useranswer == null) { 266 $userresponse = array(); 267 } else { 268 $userresponse = explode(",", $useranswer->useranswer); 269 } 270 if (in_array($answer->id, $userresponse)) { 271 // make checked 272 $checkboxelement = "<input readonly=\"readonly\" disabled=\"disabled\" name=\"answer[$i]\" checked=\"checked\" type=\"checkbox\" value=\"1\" />"; 273 if (!isset($answerdata->response)) { 274 if ($answer->response == null) { 275 if ($useranswer->correct) { 276 $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); 277 } else { 278 $answerdata->response = get_string("thatsthewronganswer", "lesson"); 279 } 280 } else { 281 $answerdata->response = format_text($answer->response, $answer->responseformat, $formattextdefoptions); 282 } 283 } 284 if (!isset($answerdata->score)) { 285 if ($this->lesson->custom) { 286 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; 287 } elseif ($useranswer->correct) { 288 $answerdata->score = get_string("receivedcredit", "lesson"); 289 } else { 290 $answerdata->score = get_string("didnotreceivecredit", "lesson"); 291 } 292 } 293 } else { 294 // unchecked 295 $checkboxelement = "<input type=\"checkbox\" readonly=\"readonly\" name=\"answer[$i]\" value=\"0\" disabled=\"disabled\" />"; 296 } 297 $answercontent = html_writer::label($checkboxelement . ' ' . $answertext, null); 298 if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { 299 $data = html_writer::div($answercontent, 'text-success') . $correctresponsetext; 300 } else { 301 $data = $answercontent; 302 } 303 } else { 304 if ($useranswer != null and $answer->id == $useranswer->answerid) { 305 // make checked 306 $checkboxelement = "<input readonly=\"readonly\" disabled=\"disabled\" name=\"answer[$i]\" checked=\"checked\" type=\"checkbox\" value=\"1\" />"; 307 if ($answer->response == null) { 308 if ($useranswer->correct) { 309 $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); 310 } else { 311 $answerdata->response = get_string("thatsthewronganswer", "lesson"); 312 } 313 } else { 314 $answerdata->response = format_text($answer->response, $answer->responseformat, $formattextdefoptions); 315 } 316 if ($this->lesson->custom) { 317 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; 318 } elseif ($useranswer->correct) { 319 $answerdata->score = get_string("receivedcredit", "lesson"); 320 } else { 321 $answerdata->score = get_string("didnotreceivecredit", "lesson"); 322 } 323 } else { 324 // unchecked 325 $checkboxelement = "<input type=\"checkbox\" readonly=\"readonly\" name=\"answer[$i]\" value=\"0\" disabled=\"disabled\" />"; 326 } 327 $answercontent = html_writer::label($checkboxelement . ' ' . $answertext, null); 328 if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { 329 $data = html_writer::div($answercontent, 'text-success') . $correctresponsetext; 330 } else { 331 $data = $answercontent; 332 } 333 } 334 if (isset($pagestats[$this->properties->id][$answer->id])) { 335 $percent = $pagestats[$this->properties->id][$answer->id] / $pagestats[$this->properties->id]["total"] * 100; 336 $percent = round($percent, 2); 337 $percent .= "% ".get_string("checkedthisone", "lesson"); 338 } else { 339 $percent = get_string("noonecheckedthis", "lesson"); 340 } 341 342 $answerdata->answers[] = array($data, $percent); 343 $answerpage->answerdata = $answerdata; 344 } 345 return $answerpage; 346 } 347 } 348 349 class lesson_add_page_form_truefalse extends lesson_add_page_form_base { 350 351 public $qtype = 'truefalse'; 352 public $qtypestring = 'truefalse'; 353 protected $answerformat = LESSON_ANSWER_HTML; 354 protected $responseformat = LESSON_ANSWER_HTML; 355 356 public function custom_definition() { 357 $this->_form->addElement('header', 'answertitle0', get_string('correctresponse', 'lesson')); 358 $this->add_answer(0, null, true, $this->get_answer_format()); 359 $this->add_response(0); 360 $this->add_jumpto(0, get_string('correctanswerjump', 'lesson'), LESSON_NEXTPAGE); 361 $this->add_score(0, get_string('correctanswerscore', 'lesson'), 1); 362 363 $this->_form->addElement('header', 'answertitle1', get_string('wrongresponse', 'lesson')); 364 $this->add_answer(1, null, true, $this->get_answer_format()); 365 $this->add_response(1); 366 $this->add_jumpto(1, get_string('wronganswerjump', 'lesson'), LESSON_THISPAGE); 367 $this->add_score(1, get_string('wronganswerscore', 'lesson'), 0); 368 } 369 } 370 371 class lesson_display_answer_form_truefalse extends moodleform { 372 373 public function definition() { 374 global $USER, $OUTPUT; 375 $mform = $this->_form; 376 $answers = $this->_customdata['answers']; 377 $lessonid = $this->_customdata['lessonid']; 378 $contents = $this->_customdata['contents']; 379 if (array_key_exists('attempt', $this->_customdata)) { 380 $attempt = $this->_customdata['attempt']; 381 } else { 382 $attempt = new stdClass(); 383 $attempt->answerid = null; 384 } 385 386 // Disable shortforms. 387 $mform->setDisableShortforms(); 388 389 $mform->addElement('header', 'pageheader'); 390 391 $mform->addElement('html', $OUTPUT->container($contents, 'contents')); 392 393 $hasattempt = false; 394 $disabled = ''; 395 if (isset($USER->modattempts[$lessonid]) && !empty($USER->modattempts[$lessonid])) { 396 $hasattempt = true; 397 $disabled = array('disabled' => 'disabled'); 398 } 399 400 $options = new stdClass(); 401 $options->para = false; 402 $options->noclean = true; 403 404 $mform->addElement('hidden', 'id'); 405 $mform->setType('id', PARAM_INT); 406 407 $mform->addElement('hidden', 'pageid'); 408 $mform->setType('pageid', PARAM_INT); 409 410 $i = 0; 411 $radiobuttons = array(); 412 foreach ($answers as $answer) { 413 $ansid = 'answerid'; 414 if ($hasattempt) { 415 $ansid = 'answer_id'; 416 } 417 418 $answer = lesson_page_type_truefalse::rewrite_answers_urls($answer); 419 $radiobuttons[] = $mform->createElement('radio', $ansid, null, 420 format_text($answer->answer, $answer->answerformat, $options), $answer->id, $disabled); 421 422 $mform->setType($ansid, PARAM_INT); 423 if ($hasattempt && $answer->id == $USER->modattempts[$lessonid]->answerid) { 424 $mform->setDefault($ansid, $attempt->answerid); 425 $mform->addElement('hidden', 'answerid', $answer->id); 426 $mform->setType('answerid', PARAM_INT); 427 } 428 $i++; 429 } 430 431 $radiogroup = $mform->addGroup($radiobuttons, $ansid, '', array(''), false); 432 $radiogroup->setAttributes(array('class' => 'answeroptiongroup')); 433 434 if ($hasattempt) { 435 $this->add_action_buttons(null, get_string("nextpage", "lesson")); 436 } else { 437 $this->add_action_buttons(null, get_string("submit", "lesson")); 438 } 439 440 } 441 442 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body