Search moodle.org's
Developer Documentation


  • Bug fixes for general core bugs in 2.8.x ended 9 November 2015 (12 months).
  • Bug fixes for security issues in 2.8.x ended 9 May 2016 (18 months).
  • minimum PHP 5.4.4 (always use latest PHP 5.4.x or 5.5.x on Windows - http://windows.php.net/download/), PHP 7 is NOT supported
  • Differences Between: [Versions 28 and 29] [Versions 28 and 30] [Versions 28 and 31] [Versions 28 and 32] [Versions 28 and 33] [Versions 28 and 34] [Versions 28 and 35] [Versions 28 and 36] [Versions 28 and 37]

       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 randomsamatch question type.
      19   *
      20   * @package    qtype_randomsamatch
      21   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
      22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      23   */
      24  
      25  
      26  defined('MOODLE_INTERNAL') || die();
      27  
      28  require_once($CFG->dirroot . '/question/type/questionbase.php');
      29  require_once($CFG->dirroot . '/question/type/numerical/question.php');
      30  
      31  /**
      32   * The randomsamatch question type class.
      33   *
      34   * TODO: Make sure short answer questions chosen by a randomsamatch question
      35   * can not also be used by a random question
      36   *
      37   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
      38   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      39   */
      40  class qtype_randomsamatch extends question_type {
      41      /**
      42       * Cache of available shortanswer question ids from a particular category.
      43       * @var array two-dimensional array. The first key is a category id, the
      44       * second key is wether subcategories should be included.
      45       */
      46      private $availablesaquestionsbycategory = array();
      47      const MAX_SUBQUESTIONS = 10;
      48  
      49      public function is_usable_by_random() {
      50          return false;
      51      }
      52  
      53      public function get_question_options($question) {
      54          global $DB;
      55          parent::get_question_options($question);
      56          $question->options = $DB->get_record('qtype_randomsamatch_options',
      57                  array('questionid' => $question->id));
      58  
      59          return true;
      60  
      61      }
      62  
      63      public function save_question_options($question) {
      64          global $DB;
      65  
      66          if (2 > $question->choose) {
      67              $result = new stdClass();
      68              $result->error = "At least two shortanswer questions need to be chosen!";
      69              return $result;
      70          }
      71  
      72          $context = $question->context;
      73  
      74          // Save the question options.
      75          $options = $DB->get_record('qtype_randomsamatch_options', array('questionid' => $question->id));
      76          if (!$options) {
      77              $options = new stdClass();
      78              $options->questionid = $question->id;
      79              $options->correctfeedback = '';
      80              $options->partiallycorrectfeedback = '';
      81              $options->incorrectfeedback = '';
      82              $options->id = $DB->insert_record('qtype_randomsamatch_options', $options);
      83          }
      84  
      85          $options->choose = $question->choose;
      86          $options->subcats = $question->subcats;
      87          $options = $this->save_combined_feedback_helper($options, $question, $context, true);
      88          $DB->update_record('qtype_randomsamatch_options', $options);
      89  
      90          $this->save_hints($question, true);
      91  
      92          return true;
      93      }
      94  
      95      protected function make_hint($hint) {
      96          return question_hint_with_parts::load_from_record($hint);
      97      }
      98  
      99      public function delete_question($questionid, $contextid) {
     100          global $DB;
     101          $DB->delete_records('qtype_randomsamatch_options', array('questionid' => $questionid));
     102  
     103          parent::delete_question($questionid, $contextid);
     104      }
     105  
     106      public function move_files($questionid, $oldcontextid, $newcontextid) {
     107          parent::move_files($questionid, $oldcontextid, $newcontextid);
     108  
     109          $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid);
     110          $this->move_files_in_hints($questionid, $oldcontextid, $newcontextid);
     111      }
     112  
     113      protected function delete_files($questionid, $contextid) {
     114          parent::delete_files($questionid, $contextid);
     115  
     116          $this->delete_files_in_combined_feedback($questionid, $contextid);
     117          $this->delete_files_in_hints($questionid, $contextid);
     118      }
     119  
     120      protected function initialise_question_instance(question_definition $question, $questiondata) {
     121          parent::initialise_question_instance($question, $questiondata);
     122          $availablesaquestions = $this->get_available_saquestions_from_category(
     123                  $question->category, $questiondata->options->subcats);
     124          $question->shufflestems = false;
     125          $question->stems = array();
     126          $question->choices = array();
     127          $question->right = array();
     128          $this->initialise_combined_feedback($question, $questiondata);
     129          $question->questionsloader = new qtype_randomsamatch_question_loader(
     130                  $availablesaquestions, $questiondata->options->choose);
     131      }
     132  
     133      public function can_analyse_responses() {
     134          return false;
     135      }
     136  
     137      /**
     138       * Get all the usable shortanswer questions from a particular question category.
     139       *
     140       * @param integer $categoryid the id of a question category.
     141       * @param bool $subcategories whether to include questions from subcategories.
     142       * @return array of question records.
     143       */
     144      public function get_available_saquestions_from_category($categoryid, $subcategories) {
     145          if (isset($this->availablesaquestionsbycategory[$categoryid][$subcategories])) {
     146              return $this->availablesaquestionsbycategory[$categoryid][$subcategories];
     147          }
     148  
     149          if ($subcategories) {
     150              $categoryids = question_categorylist($categoryid);
     151          } else {
     152              $categoryids = array($categoryid);
     153          }
     154  
     155          $questionids = question_bank::get_finder()->get_questions_from_categories(
     156                  $categoryids, "qtype = 'shortanswer'");
     157          $this->availablesaquestionsbycategory[$categoryid][$subcategories] = $questionids;
     158          return $questionids;
     159      }
     160  
     161      /**
     162       * @param object $question
     163       * @return mixed either a integer score out of 1 that the average random
     164       * guess by a student might give or an empty string which means will not
     165       * calculate.
     166       */
     167      public function get_random_guess_score($question) {
     168          return 1/$question->options->choose;
     169      }
     170  
     171      /**
     172       * Defines the table which extends the question table. This allows the base questiontype
     173       * to automatically save, backup and restore the extra fields.
     174       *
     175       * @return an array with the table name (first) and then the column names (apart from id and questionid)
     176       */
     177      public function extra_question_fields() {
     178          return array('qtype_randomsamatch_options',
     179                       'choose',        // Number of shortanswer questions to choose.
     180                       'subcats',       // Questions can be choosen from subcategories.
     181                       );
     182      }
     183  
     184      /**
     185       * Imports the question from Moodle XML format.
     186       *
     187       * @param array $xml structure containing the XML data
     188       * @param object $fromform question object to fill: ignored by this function (assumed to be null)
     189       * @param qformat_xml $format format class exporting the question
     190       * @param object $extra extra information (not required for importing this question in this format)
     191       * @return object question object
     192       */
     193      public function import_from_xml($xml, $fromform, qformat_xml $format, $extra=null) {
     194          // Return if data type is not our own one.
     195          if (!isset($xml['@']['type']) || $xml['@']['type'] != $this->name()) {
     196              return false;
     197          }
     198  
     199          // Import the common question headers and set the corresponding field.
     200          $fromform = $format->import_headers($xml);
     201          $fromform->qtype = $this->name();
     202          $format->import_combined_feedback($fromform, $xml, true);
     203          $format->import_hints($fromform, $xml, true);
     204  
     205          $extras = $this->extra_question_fields();
     206          array_shift($extras);
     207          foreach ($extras as $extra) {
     208              $fromform->$extra = $format->getpath($xml, array('#', $extra, 0, '#'), '', true);
     209          }
     210  
     211          return $fromform;
     212      }
     213  
     214      /**
     215       * Exports the question to Moodle XML format.
     216       *
     217       * @param object $question question to be exported into XML format
     218       * @param qformat_xml $format format class exporting the question
     219       * @param object $extra extra information (not required for exporting this question in this format)
     220       * @return string containing the question data in XML format
     221       */
     222      public function export_to_xml($question, qformat_xml $format, $extra=null) {
     223          $expout = '';
     224          $expout .= $format->write_combined_feedback($question->options,
     225                                                      $question->id,
     226                                                      $question->contextid);
     227          $extraquestionfields = $this->extra_question_fields();
     228          array_shift($extraquestionfields);
     229          foreach ($extraquestionfields as $extra) {
     230              $expout .= "    <{$extra}>" . $question->options->$extra . "</{$extra}>\n";
     231          }
     232          return $expout;
     233      }
     234  }
    

    Search This Site: