Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

   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   * Matching
  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  /** Matching question type */
  29  define("LESSON_PAGE_MATCHING",      "5");
  30  
  31  class lesson_page_type_matching extends lesson_page {
  32  
  33      protected $type = lesson_page::TYPE_QUESTION;
  34      protected $typeid = LESSON_PAGE_MATCHING;
  35      protected $typeidstring = 'matching';
  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          $mform = $this->make_answer_form($attempt);
  53          $data = new stdClass;
  54          $data->id = $PAGE->cm->id;
  55          $data->pageid = $this->properties->id;
  56          $mform->set_data($data);
  57  
  58          // Trigger an event question viewed.
  59          $eventparams = array(
  60              'context' => context_module::instance($PAGE->cm->id),
  61              'objectid' => $this->properties->id,
  62              'other' => array(
  63                      'pagetype' => $this->get_typestring()
  64                  )
  65              );
  66  
  67          $event = \mod_lesson\event\question_viewed::create($eventparams);
  68          $event->trigger();
  69          return $mform->display();
  70      }
  71  
  72      protected function make_answer_form($attempt=null) {
  73          global $USER, $CFG;
  74          // don't shuffle answers (could be an option??)
  75          $getanswers = array_slice($this->get_answers(), 2);
  76  
  77          $answers = array();
  78          foreach ($getanswers as $getanswer) {
  79              $answers[$getanswer->id] = $getanswer;
  80          }
  81  
  82          $responses = array();
  83          foreach ($answers as $answer) {
  84              // get all the response
  85              if ($answer->response != null) {
  86                  $responses[] = trim($answer->response);
  87              }
  88          }
  89  
  90          $responseoptions = array(''=>get_string('choosedots'));
  91          if (!empty($responses)) {
  92              shuffle($responses);
  93              foreach ($responses as  $response) {
  94                  $responseoptions[htmlspecialchars($response)] = $response;
  95              }
  96          }
  97          if (isset($USER->modattempts[$this->lesson->id]) && !empty($attempt->useranswer)) {
  98              $useranswers = explode(',', $attempt->useranswer);
  99              $t = 0;
 100          } else {
 101              $useranswers = array();
 102          }
 103  
 104          $action = $CFG->wwwroot.'/mod/lesson/continue.php';
 105          $params = array('answers'=>$answers, 'useranswers'=>$useranswers, 'responseoptions'=>$responseoptions, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents());
 106          $mform = new lesson_display_answer_form_matching($action, $params);
 107          return $mform;
 108      }
 109  
 110      public function create_answers($properties) {
 111          global $DB, $PAGE;
 112          // now add the answers
 113          $newanswer = new stdClass;
 114          $newanswer->lessonid = $this->lesson->id;
 115          $newanswer->pageid = $this->properties->id;
 116          $newanswer->timecreated = $this->properties->timecreated;
 117  
 118          $cm = get_coursemodule_from_instance('lesson', $this->lesson->id, $this->lesson->course);
 119          $context = context_module::instance($cm->id);
 120  
 121          // Check for duplicate response format.
 122          $duplicateresponse = array();
 123          if (is_array($properties->response_editor) &&             // If there are response_editors to iterate.
 124                  is_array(reset($properties->response_editor))) {  // And they come split into text & format array.
 125              foreach ($properties->response_editor as $response) { // Iterate over all them.
 126                  $duplicateresponse[] = $response['text'];         // Picking the text only. This pagetype is that way.
 127              }
 128              $properties->response_editor = $duplicateresponse;
 129          }
 130  
 131          $answers = array();
 132  
 133          // need to add two to offset correct response and wrong response
 134          $this->lesson->maxanswers = $this->lesson->maxanswers + 2;
 135          for ($i = 0; $i < $this->lesson->maxanswers; $i++) {
 136              $answer = clone($newanswer);
 137              if (!empty($properties->answer_editor[$i]) && is_array($properties->answer_editor[$i])) {
 138                  $answer->answer = $properties->answer_editor[$i]['text'];
 139                  $answer->answerformat = $properties->answer_editor[$i]['format'];
 140              }
 141              if (!empty($properties->response_editor[$i])) {
 142                  $answer->response = $properties->response_editor[$i];
 143                  $answer->responseformat = 0;
 144              }
 145  
 146              if (isset($properties->jumpto[$i])) {
 147                  $answer->jumpto = $properties->jumpto[$i];
 148              }
 149              if ($this->lesson->custom && isset($properties->score[$i])) {
 150                  $answer->score = $properties->score[$i];
 151              }
 152  
 153              if (isset($answer->answer) && $answer->answer != '') {
 154                  $answer->id = $DB->insert_record("lesson_answers", $answer);
 155                  $this->save_answers_files($context, $PAGE->course->maxbytes,
 156                          $answer, $properties->answer_editor[$i]);
 157                  $answers[$answer->id] = new lesson_page_answer($answer);
 158              } else if ($i < 2) {
 159                  $answer->id = $DB->insert_record("lesson_answers", $answer);
 160                  $answers[$answer->id] = new lesson_page_answer($answer);
 161              } else {
 162                  break;
 163              }
 164          }
 165          $this->answers = $answers;
 166          return $answers;
 167      }
 168  
 169      public function check_answer() {
 170          global $CFG, $PAGE;
 171  
 172          $formattextdefoptions = new stdClass();
 173          $formattextdefoptions->noclean = true;
 174          $formattextdefoptions->para = false;
 175  
 176          $result = parent::check_answer();
 177  
 178          $mform = $this->make_answer_form();
 179  
 180          $data = $mform->get_data();
 181          require_sesskey();
 182  
 183          if (!$data) {
 184              $result->inmediatejump = true;
 185              $result->newpageid = $this->properties->id;
 186              return $result;
 187          }
 188  
 189          $response = $data->response;
 190          $getanswers = $this->get_answers();
 191          foreach ($getanswers as $key => $answer) {
 192              $getanswers[$key] = parent::rewrite_answers_urls($answer);
 193          }
 194  
 195          $correct = array_shift($getanswers);
 196          $wrong   = array_shift($getanswers);
 197  
 198          $answers = array();
 199          foreach ($getanswers as $key => $answer) {
 200              if ($answer->answer !== '' or $answer->response !== '') {
 201                  $answers[$answer->id] = $answer;
 202              }
 203          }
 204  
 205          // get the user's exact responses for record keeping
 206          $hits = 0;
 207          $userresponse = array();
 208          $result->studentanswerformat = FORMAT_HTML;
 209          foreach ($response as $id => $value) {
 210              if ($value == '') {
 211                  $result->noanswer = true;
 212                  return $result;
 213              }
 214              $value = htmlspecialchars_decode($value);
 215              $userresponse[] = $value;
 216              // Make sure the user's answer exists in question's answer
 217              if (array_key_exists($id, $answers)) {
 218                  $answer = $answers[$id];
 219                  $result->studentanswer .= '<br />'.format_text($answer->answer, $answer->answerformat, $formattextdefoptions).' = '.$value;
 220                  if (trim($answer->response) == trim($value)) {
 221                      $hits++;
 222                  }
 223              }
 224          }
 225  
 226          $result->userresponse = implode(",", $userresponse);
 227  
 228          if ($hits == count($answers)) {
 229              $result->correctanswer = true;
 230              $result->response      = format_text($correct->answer, $correct->answerformat, $formattextdefoptions);
 231              $result->answerid      = $correct->id;
 232              $result->newpageid     = $correct->jumpto;
 233          } else {
 234              $result->correctanswer = false;
 235              $result->response      = format_text($wrong->answer, $wrong->answerformat, $formattextdefoptions);
 236              $result->answerid      = $wrong->id;
 237              $result->newpageid     = $wrong->jumpto;
 238          }
 239  
 240          return $result;
 241      }
 242  
 243      public function option_description_string() {
 244          return get_string("firstanswershould", "lesson");
 245      }
 246  
 247      public function display_answers(html_table $table) {
 248          $answers = $this->get_answers();
 249          $options = new stdClass;
 250          $options->noclean = true;
 251          $options->para = false;
 252          $i = 1;
 253          $n = 0;
 254  
 255          foreach ($answers as $answer) {
 256              $answer = parent::rewrite_answers_urls($answer);
 257              if ($n < 2) {
 258                  if ($answer->answer != null) {
 259                      $cells = array();
 260                      if ($n == 0) {
 261                          $cells[] = '<label>' . get_string('correctresponse', 'lesson') . '</label>';
 262                      } else {
 263                          $cells[] = '<label>' . get_string('wrongresponse', 'lesson') . '</label>';
 264                      }
 265                      $cells[] = format_text($answer->answer, $answer->answerformat, $options);
 266                      $table->data[] = new html_table_row($cells);
 267                  }
 268  
 269                  if ($n == 0) {
 270                      $cells = array();
 271                      $cells[] = '<label>' . get_string('correctanswerscore', 'lesson') . '</label>: ';
 272                      $cells[] = $answer->score;
 273                      $table->data[] = new html_table_row($cells);
 274  
 275                      $cells = array();
 276                      $cells[] = '<label>' . get_string('correctanswerjump', 'lesson') . '</label>: ';
 277                      $cells[] = $this->get_jump_name($answer->jumpto);
 278                      $table->data[] = new html_table_row($cells);
 279                  } elseif ($n == 1) {
 280                      $cells = array();
 281                      $cells[] = '<label>' . get_string('wronganswerscore', 'lesson') . '</label>: ';
 282                      $cells[] = $answer->score;
 283                      $table->data[] = new html_table_row($cells);
 284  
 285                      $cells = array();
 286                      $cells[] = '<label>' . get_string('wronganswerjump', 'lesson') . '</label>: ';
 287                      $cells[] = $this->get_jump_name($answer->jumpto);
 288                      $table->data[] = new html_table_row($cells);
 289                  }
 290  
 291                  if ($n === 0){
 292                      $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;';
 293                  }
 294                  $n++;
 295                  $i--;
 296              } else {
 297                  $cells = array();
 298                  if ($this->lesson->custom && $answer->score > 0) {
 299                      // if the score is > 0, then it is correct
 300                      $cells[] = '<label class="correct">' . get_string('answer', 'lesson') . " {$i}</label>: \n";
 301                  } else if ($this->lesson->custom) {
 302                      $cells[] = '<label>' . get_string('answer', 'lesson') . " {$i}</label>: \n";
 303                  } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) {
 304                      $cells[] = '<label class="correct">' . get_string('answer', 'lesson') . " {$i}</label>: \n";
 305                  } else {
 306                      $cells[] = '<label>' . get_string('answer', 'lesson') . " {$i}</label>: \n";
 307                  }
 308                  $cells[] = format_text($answer->answer, $answer->answerformat, $options);
 309                  $table->data[] = new html_table_row($cells);
 310  
 311                  $cells = array();
 312                  $cells[] = '<label>' . get_string('matchesanswer', 'lesson') . " {$i}</label>: \n";
 313                  $cells[] = format_text($answer->response, $answer->responseformat, $options);
 314                  $table->data[] = new html_table_row($cells);
 315              }
 316              $i++;
 317          }
 318          return $table;
 319      }
 320      /**
 321       * Updates the page and its answers
 322       *
 323       * @global moodle_database $DB
 324       * @global moodle_page $PAGE
 325       * @param stdClass $properties
 326       * @return bool
 327       */
 328      public function update($properties, $context = null, $maxbytes = null) {
 329          global $DB, $PAGE;
 330          $answers  = $this->get_answers();
 331          $properties->id = $this->properties->id;
 332          $properties->lessonid = $this->lesson->id;
 333          $properties->timemodified = time();
 334          $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);
 335          $DB->update_record("lesson_pages", $properties);
 336  
 337          // Trigger an event: page updated.
 338          \mod_lesson\event\page_updated::create_from_lesson_page($this, $context)->trigger();
 339  
 340          // need to add two to offset correct response and wrong response
 341          $this->lesson->maxanswers += 2;
 342          for ($i = 0; $i < $this->lesson->maxanswers; $i++) {
 343              if (!array_key_exists($i, $this->answers)) {
 344                  $this->answers[$i] = new stdClass;
 345                  $this->answers[$i]->lessonid = $this->lesson->id;
 346                  $this->answers[$i]->pageid = $this->id;
 347                  $this->answers[$i]->timecreated = $this->timecreated;
 348              }
 349  
 350              if (!empty($properties->answer_editor[$i]) && is_array($properties->answer_editor[$i])) {
 351                  $this->answers[$i]->answer = $properties->answer_editor[$i]['text'];
 352                  $this->answers[$i]->answerformat = $properties->answer_editor[$i]['format'];
 353              }
 354              if (!empty($properties->response_editor[$i])) {
 355                  $this->answers[$i]->response = $properties->response_editor[$i];
 356                  $this->answers[$i]->responseformat = 0;
 357              }
 358  
 359              if (isset($properties->jumpto[$i])) {
 360                  $this->answers[$i]->jumpto = $properties->jumpto[$i];
 361              }
 362              if ($this->lesson->custom && isset($properties->score[$i])) {
 363                  $this->answers[$i]->score = $properties->score[$i];
 364              }
 365  
 366              // we don't need to check for isset here because properties called it's own isset method.
 367              if ($this->answers[$i]->answer != '') {
 368                  if (!isset($this->answers[$i]->id)) {
 369                      $this->answers[$i]->id =  $DB->insert_record("lesson_answers", $this->answers[$i]);
 370                  } else {
 371                      $DB->update_record("lesson_answers", $this->answers[$i]->properties());
 372                  }
 373                  // Save files in answers (no response_editor for matching questions).
 374                  $this->save_answers_files($context, $maxbytes, $this->answers[$i], $properties->answer_editor[$i]);
 375              } else if ($i < 2) {
 376                  if (!isset($this->answers[$i]->id)) {
 377                      $this->answers[$i]->id =  $DB->insert_record("lesson_answers", $this->answers[$i]);
 378                  } else {
 379                      $DB->update_record("lesson_answers", $this->answers[$i]->properties());
 380                  }
 381  
 382                  // Save files in answers (no response_editor for matching questions).
 383                  $this->save_answers_files($context, $maxbytes, $this->answers[$i], $properties->answer_editor[$i]);
 384              } else if (isset($this->answers[$i]->id)) {
 385                  $DB->delete_records('lesson_answers', array('id'=>$this->answers[$i]->id));
 386                  unset($this->answers[$i]);
 387              }
 388          }
 389          return true;
 390      }
 391      public function stats(array &$pagestats, $tries) {
 392          if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt
 393              $temp = $tries[$this->lesson->maxattempts - 1];
 394          } else {
 395              // else, user attempted the question less than the max, so grab the last one
 396              $temp = end($tries);
 397          }
 398          if ($temp->correct) {
 399              if (isset($pagestats[$temp->pageid]["correct"])) {
 400                  $pagestats[$temp->pageid]["correct"]++;
 401              } else {
 402                  $pagestats[$temp->pageid]["correct"] = 1;
 403              }
 404          }
 405          if (isset($pagestats[$temp->pageid]["total"])) {
 406              $pagestats[$temp->pageid]["total"]++;
 407          } else {
 408              $pagestats[$temp->pageid]["total"] = 1;
 409          }
 410          return true;
 411      }
 412      public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) {
 413          $answers = array();
 414          foreach ($this->get_answers() as $answer) {
 415              $answers[$answer->id] = $answer;
 416          }
 417          $formattextdefoptions = new stdClass;
 418          $formattextdefoptions->para = false;  //I'll use it widely in this page
 419          foreach ($answers as $answer) {
 420              if ($n == 0 && $useranswer != null && $useranswer->correct) {
 421                  if ($answer->response == null && $useranswer != null) {
 422                      $answerdata->response = get_string("thatsthecorrectanswer", "lesson");
 423                  } else {
 424                      $answerdata->response = $answer->response;
 425                  }
 426                  if ($this->lesson->custom) {
 427                      $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score;
 428                  } else {
 429                      $answerdata->score = get_string("receivedcredit", "lesson");
 430                  }
 431              } elseif ($n == 1 && $useranswer != null && !$useranswer->correct) {
 432                  if ($answer->response == null && $useranswer != null) {
 433                      $answerdata->response = get_string("thatsthewronganswer", "lesson");
 434                  } else {
 435                      $answerdata->response = $answer->response;
 436                  }
 437                  if ($this->lesson->custom) {
 438                      $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score;
 439                  } else {
 440                      $answerdata->score = get_string("didnotreceivecredit", "lesson");
 441                  }
 442              } elseif ($n > 1) {
 443                  $data = '<label class="accesshide" for="answer_' . $n . '">' . get_string('answer', 'lesson') . '</label>';
 444                  $data .= strip_tags(format_string($answer->answer)) . ' ';
 445                  if ($useranswer != null) {
 446                      $userresponse = explode(",", $useranswer->useranswer);
 447                      $data .= '<label class="accesshide" for="stu_answer_response_' . $n . '">' . get_string('matchesanswer', 'lesson') . '</label>';
 448                      $data .= "<select class=\"custom-select\" id=\"stu_answer_response_" . $n . "\" " .
 449                               "disabled=\"disabled\"><option selected=\"selected\">";
 450                      if (array_key_exists($i, $userresponse)) {
 451                          $data .= $userresponse[$i];
 452                      }
 453                      $data .= "</option></select>";
 454                  } else {
 455                      $data .= '<label class="accesshide" for="answer_response_' . $n . '">' . get_string('matchesanswer', 'lesson') . '</label>';
 456                      $data .= "<select class=\"custom-select\" id=\"answer_response_" . $n . "\" " .
 457                               "disabled=\"disabled\"><option selected=\"selected\">".strip_tags(format_string($answer->response))."</option></select>";
 458                  }
 459  
 460                  if ($n == 2) {
 461                      if (isset($pagestats[$this->properties->id])) {
 462                          if (!array_key_exists('correct', $pagestats[$this->properties->id])) {
 463                              $pagestats[$this->properties->id]["correct"] = 0;
 464                          }
 465                          $percent = $pagestats[$this->properties->id]["correct"] / $pagestats[$this->properties->id]["total"] * 100;
 466                          $percent = round($percent, 2);
 467                          $percent .= "% ".get_string("answeredcorrectly", "lesson");
 468                      } else {
 469                          $percent = get_string("nooneansweredthisquestion", "lesson");
 470                      }
 471                  } else {
 472                      $percent = '';
 473                  }
 474  
 475                  $answerdata->answers[] = array($data, $percent);
 476                  $i++;
 477              }
 478              $n++;
 479              $answerpage->answerdata = $answerdata;
 480          }
 481          return $answerpage;
 482      }
 483      public function get_jumps() {
 484          global $DB;
 485          // The jumps for matching question type are stored in the 1st and 2nd answer record.
 486          $jumps = array();
 487          if ($answers = $DB->get_records("lesson_answers", array("lessonid" => $this->lesson->id, "pageid" => $this->properties->id), 'id', '*', 0, 2)) {
 488              foreach ($answers as $answer) {
 489                  $jumps[] = $this->get_jump_name($answer->jumpto);
 490              }
 491          } else {
 492              $jumps[] = $this->get_jump_name($this->properties->nextpageid);
 493          }
 494          return $jumps;
 495      }
 496  }
 497  
 498  class lesson_add_page_form_matching extends lesson_add_page_form_base {
 499  
 500      public $qtype = 'matching';
 501      public $qtypestring = 'matching';
 502      protected $answerformat = LESSON_ANSWER_HTML;
 503      protected $responseformat = '';
 504  
 505      public function custom_definition() {
 506  
 507          $this->_form->addElement('header', 'correctresponse', get_string('correctresponse', 'lesson'));
 508          $this->_form->addElement('editor', 'answer_editor[0]', get_string('correctresponse', 'lesson'),
 509                  array('rows' => '4', 'columns' => '80'),
 510                  array('noclean' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes' => $this->_customdata['maxbytes']));
 511          $this->_form->setType('answer_editor[0]', PARAM_RAW);
 512          $this->_form->setDefault('answer_editor[0]', array('text' => '', 'format' => FORMAT_HTML));
 513          $this->add_jumpto(0, get_string('correctanswerjump','lesson'), LESSON_NEXTPAGE);
 514          $this->add_score(0, get_string("correctanswerscore", "lesson"), 1);
 515  
 516          $this->_form->addElement('header', 'wrongresponse', get_string('wrongresponse', 'lesson'));
 517          $this->_form->addElement('editor', 'answer_editor[1]', get_string('wrongresponse', 'lesson'),
 518                  array('rows' => '4', 'columns' => '80'),
 519                  array('noclean' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes' => $this->_customdata['maxbytes']));
 520          $this->_form->setType('answer_editor[1]', PARAM_RAW);
 521          $this->_form->setDefault('answer_editor[1]', array('text' => '', 'format' => FORMAT_HTML));
 522  
 523          $this->add_jumpto(1, get_string('wronganswerjump','lesson'), LESSON_THISPAGE);
 524          $this->add_score(1, get_string("wronganswerscore", "lesson"), 0);
 525  
 526          for ($i = 2; $i < $this->_customdata['lesson']->maxanswers+2; $i++) {
 527              $this->_form->addElement('header', 'matchingpair'.($i-1), get_string('matchingpair', 'lesson', $i-1));
 528              $this->add_answer($i, null, ($i < 4), LESSON_ANSWER_HTML);
 529              $required = ($i < 4);
 530              $label = get_string('matchesanswer','lesson');
 531              $count = $i;
 532              $this->_form->addElement('text', 'response_editor['.$count.']', $label, array('size'=>'50'));
 533              $this->_form->setType('response_editor['.$count.']', PARAM_NOTAGS);
 534              $this->_form->setDefault('response_editor['.$count.']', '');
 535              if ($required) {
 536                  $this->_form->addRule('response_editor['.$count.']', get_string('required'), 'required', null, 'client');
 537              }
 538          }
 539      }
 540  }
 541  
 542  class lesson_display_answer_form_matching extends moodleform {
 543  
 544      public function definition() {
 545          global $USER, $OUTPUT, $PAGE;
 546          $mform = $this->_form;
 547          $answers = $this->_customdata['answers'];
 548          $useranswers = $this->_customdata['useranswers'];
 549          $responseoptions = $this->_customdata['responseoptions'];
 550          $lessonid = $this->_customdata['lessonid'];
 551          $contents = $this->_customdata['contents'];
 552  
 553          // Disable shortforms.
 554          $mform->setDisableShortforms();
 555  
 556          $mform->addElement('header', 'pageheader');
 557  
 558          $mform->addElement('html', $OUTPUT->container($contents, 'contents'));
 559  
 560          $hasattempt = false;
 561          $disabled = '';
 562          if (isset($useranswers) && !empty($useranswers)) {
 563              $hasattempt = true;
 564              $disabled = array('disabled' => 'disabled');
 565          }
 566  
 567          $options = new stdClass;
 568          $options->para = false;
 569          $options->noclean = true;
 570  
 571          $mform->addElement('hidden', 'id');
 572          $mform->setType('id', PARAM_INT);
 573  
 574          $mform->addElement('hidden', 'pageid');
 575          $mform->setType('pageid', PARAM_INT);
 576  
 577          $i = 0;
 578  
 579          foreach ($answers as $answer) {
 580              $mform->addElement('html', '<div class="answeroption">');
 581              if ($answer->response != null) {
 582                  $responseid = 'response['.$answer->id.']';
 583                  if ($hasattempt) {
 584                      $responseid = 'response_'.$answer->id;
 585                      $mform->addElement('hidden', 'response['.$answer->id.']', htmlspecialchars($useranswers[$i]));
 586                      // Temporary fixed until MDL-38885 gets integrated
 587                      $mform->setType('response', PARAM_TEXT);
 588                  }
 589                  $answer = lesson_page_type_matching::rewrite_answers_urls($answer);
 590                  $mform->addElement('select', $responseid, format_text($answer->answer,$answer->answerformat,$options), $responseoptions, $disabled);
 591                  $mform->setType($responseid, PARAM_TEXT);
 592                  if ($hasattempt) {
 593                      $mform->setDefault($responseid, htmlspecialchars(trim($useranswers[$i])));
 594                  } else {
 595                      $mform->setDefault($responseid, 'answeroption');
 596                  }
 597              }
 598              $mform->addElement('html', '</div>');
 599              $i++;
 600          }
 601          if ($hasattempt) {
 602              $this->add_action_buttons(null, get_string("nextpage", "lesson"));
 603          } else {
 604              $this->add_action_buttons(null, get_string("submit", "lesson"));
 605          }
 606      }
 607  
 608  }