Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Question type class for the true-false question type.
  19   *
  20   * @package    qtype
  21   * @subpackage truefalse
  22   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  require_once($CFG->libdir . '/questionlib.php');
  30  
  31  
  32  /**
  33   * The true-false question type class.
  34   *
  35   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class qtype_truefalse extends question_type {
  39      public function save_question_options($question) {
  40          global $DB;
  41          $result = new stdClass();
  42          $context = $question->context;
  43  
  44          // Fetch old answer ids so that we can reuse them.
  45          $oldanswers = $DB->get_records('question_answers',
  46                  array('question' => $question->id), 'id ASC');
  47  
  48          // Save the true answer - update an existing answer if possible.
  49          $answer = array_shift($oldanswers);
  50          if (!$answer) {
  51              $answer = new stdClass();
  52              $answer->question = $question->id;
  53              $answer->answer = '';
  54              $answer->feedback = '';
  55              $answer->id = $DB->insert_record('question_answers', $answer);
  56          }
  57  
  58          $answer->answer   = get_string('true', 'qtype_truefalse');
  59          $answer->fraction = $question->correctanswer;
  60          $answer->feedback = $this->import_or_save_files($question->feedbacktrue,
  61                  $context, 'question', 'answerfeedback', $answer->id);
  62          $answer->feedbackformat = $question->feedbacktrue['format'];
  63          $DB->update_record('question_answers', $answer);
  64          $trueid = $answer->id;
  65  
  66          // Save the false answer - update an existing answer if possible.
  67          $answer = array_shift($oldanswers);
  68          if (!$answer) {
  69              $answer = new stdClass();
  70              $answer->question = $question->id;
  71              $answer->answer = '';
  72              $answer->feedback = '';
  73              $answer->id = $DB->insert_record('question_answers', $answer);
  74          }
  75  
  76          $answer->answer   = get_string('false', 'qtype_truefalse');
  77          $answer->fraction = 1 - (int)$question->correctanswer;
  78          $answer->feedback = $this->import_or_save_files($question->feedbackfalse,
  79                  $context, 'question', 'answerfeedback', $answer->id);
  80          $answer->feedbackformat = $question->feedbackfalse['format'];
  81          $DB->update_record('question_answers', $answer);
  82          $falseid = $answer->id;
  83  
  84          // Delete any left over old answer records.
  85          $fs = get_file_storage();
  86          foreach ($oldanswers as $oldanswer) {
  87              $fs->delete_area_files($context->id, 'question', 'answerfeedback', $oldanswer->id);
  88              $DB->delete_records('question_answers', array('id' => $oldanswer->id));
  89          }
  90  
  91          // Save question options in question_truefalse table.
  92          if ($options = $DB->get_record('question_truefalse', array('question' => $question->id))) {
  93              // No need to do anything, since the answer IDs won't have changed
  94              // But we'll do it anyway, just for robustness.
  95              $options->trueanswer  = $trueid;
  96              $options->falseanswer = $falseid;
  97              $DB->update_record('question_truefalse', $options);
  98          } else {
  99              $options = new stdClass();
 100              $options->question    = $question->id;
 101              $options->trueanswer  = $trueid;
 102              $options->falseanswer = $falseid;
 103              $DB->insert_record('question_truefalse', $options);
 104          }
 105  
 106          $this->save_hints($question);
 107  
 108          return true;
 109      }
 110  
 111      /**
 112       * Loads the question type specific options for the question.
 113       */
 114      public function get_question_options($question) {
 115          global $DB, $OUTPUT;
 116          parent::get_question_options($question);
 117          // Get additional information from database
 118          // and attach it to the question object.
 119          if (!$question->options = $DB->get_record('question_truefalse',
 120                  array('question' => $question->id))) {
 121              echo $OUTPUT->notification('Error: Missing question options!');
 122              return false;
 123          }
 124          // Load the answers.
 125          if (!$question->options->answers = $DB->get_records('question_answers',
 126                  array('question' =>  $question->id), 'id ASC')) {
 127              echo $OUTPUT->notification('Error: Missing question answers for truefalse question ' .
 128                      $question->id . '!');
 129              return false;
 130          }
 131  
 132          return true;
 133      }
 134  
 135      protected function initialise_question_instance(question_definition $question, $questiondata) {
 136          parent::initialise_question_instance($question, $questiondata);
 137          $answers = $questiondata->options->answers;
 138          if ($answers[$questiondata->options->trueanswer]->fraction > 0.99) {
 139              $question->rightanswer = true;
 140          } else {
 141              $question->rightanswer = false;
 142          }
 143          $question->truefeedback =  $answers[$questiondata->options->trueanswer]->feedback;
 144          $question->falsefeedback = $answers[$questiondata->options->falseanswer]->feedback;
 145          $question->truefeedbackformat =
 146                  $answers[$questiondata->options->trueanswer]->feedbackformat;
 147          $question->falsefeedbackformat =
 148                  $answers[$questiondata->options->falseanswer]->feedbackformat;
 149          $question->trueanswerid =  $questiondata->options->trueanswer;
 150          $question->falseanswerid = $questiondata->options->falseanswer;
 151      }
 152  
 153      public function delete_question($questionid, $contextid) {
 154          global $DB;
 155          $DB->delete_records('question_truefalse', array('question' => $questionid));
 156  
 157          parent::delete_question($questionid, $contextid);
 158      }
 159  
 160      public function move_files($questionid, $oldcontextid, $newcontextid) {
 161          parent::move_files($questionid, $oldcontextid, $newcontextid);
 162          $this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
 163      }
 164  
 165      protected function delete_files($questionid, $contextid) {
 166          parent::delete_files($questionid, $contextid);
 167          $this->delete_files_in_answers($questionid, $contextid);
 168      }
 169  
 170      public function get_random_guess_score($questiondata) {
 171          return 0.5;
 172      }
 173  
 174      public function get_possible_responses($questiondata) {
 175          return array(
 176              $questiondata->id => array(
 177                  0 => new question_possible_response(get_string('false', 'qtype_truefalse'),
 178                          $questiondata->options->answers[
 179                          $questiondata->options->falseanswer]->fraction),
 180                  1 => new question_possible_response(get_string('true', 'qtype_truefalse'),
 181                          $questiondata->options->answers[
 182                          $questiondata->options->trueanswer]->fraction),
 183                  null => question_possible_response::no_response()
 184              )
 185          );
 186      }
 187  }