[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/question/type/calculatedmulti/ -> questiontype.php (source)

   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 calculated multiple-choice question type.
  19   *
  20   * @package    qtype
  21   * @subpackage calculatedmulti
  22   * @copyright  2009 Pierre Pichet
  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->dirroot . '/question/type/multichoice/questiontype.php');
  30  require_once($CFG->dirroot . '/question/type/calculated/questiontype.php');
  31  
  32  
  33  /**
  34   * The calculated multiple-choice question type.
  35   *
  36   * @copyright  2009 Pierre Pichet
  37   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38   */
  39  class qtype_calculatedmulti extends qtype_calculated {
  40  
  41      public function save_question_options($question) {
  42          global $CFG, $DB;
  43          $context = $question->context;
  44  
  45          // Make it impossible to save bad formulas anywhere.
  46          $this->validate_question_data($question);
  47  
  48          // Calculated options.
  49          $update = true;
  50          $options = $DB->get_record('question_calculated_options',
  51                  array('question' => $question->id));
  52          if (!$options) {
  53              $options = new stdClass();
  54              $options->question = $question->id;
  55              $options->correctfeedback = '';
  56              $options->partiallycorrectfeedback = '';
  57              $options->incorrectfeedback = '';
  58              $options->id = $DB->insert_record('question_calculated_options', $options);
  59          }
  60          $options->synchronize = $question->synchronize;
  61          $options->single = $question->single;
  62          $options->answernumbering = $question->answernumbering;
  63          $options->shuffleanswers = $question->shuffleanswers;
  64          $options = $this->save_combined_feedback_helper($options, $question, $context, true);
  65          $DB->update_record('question_calculated_options', $options);
  66  
  67          // Get old versions of the objects.
  68          if (!$oldanswers = $DB->get_records('question_answers',
  69                  array('question' => $question->id), 'id ASC')) {
  70              $oldanswers = array();
  71          }
  72          if (!$oldoptions = $DB->get_records('question_calculated',
  73                  array('question' => $question->id), 'answer ASC')) {
  74              $oldoptions = array();
  75          }
  76  
  77          // Insert all the new answers.
  78          foreach ($question->answer as $key => $answerdata) {
  79              if (is_array($answerdata)) {
  80                  $answerdata = $answerdata['text'];
  81              }
  82              if (trim($answerdata) == '') {
  83                  continue;
  84              }
  85  
  86              // Update an existing answer if possible.
  87              $answer = array_shift($oldanswers);
  88              if (!$answer) {
  89                  $answer = new stdClass();
  90                  $answer->question = $question->id;
  91                  $answer->answer   = '';
  92                  $answer->feedback = '';
  93                  $answer->id       = $DB->insert_record('question_answers', $answer);
  94              }
  95  
  96              if (is_array($answerdata)) {
  97                  // Doing an import.
  98                  $answer->answer = $this->import_or_save_files($answerdata,
  99                          $context, 'question', 'answer', $answer->id);
 100                  $answer->answerformat = $answerdata['format'];
 101              } else {
 102                  // Saving the form.
 103                  $answer->answer = $answerdata;
 104                  $answer->answerformat = FORMAT_HTML;
 105              }
 106              $answer->fraction = $question->fraction[$key];
 107              $answer->feedback = $this->import_or_save_files($question->feedback[$key],
 108                      $context, 'question', 'answerfeedback', $answer->id);
 109              $answer->feedbackformat = $question->feedback[$key]['format'];
 110  
 111              $DB->update_record("question_answers", $answer);
 112  
 113              // Set up the options object.
 114              if (!$options = array_shift($oldoptions)) {
 115                  $options = new stdClass();
 116              }
 117              $options->question            = $question->id;
 118              $options->answer              = $answer->id;
 119              $options->tolerance           = trim($question->tolerance[$key]);
 120              $options->tolerancetype       = trim($question->tolerancetype[$key]);
 121              $options->correctanswerlength = trim($question->correctanswerlength[$key]);
 122              $options->correctanswerformat = trim($question->correctanswerformat[$key]);
 123  
 124              // Save options.
 125              if (isset($options->id)) {
 126                  // Reusing existing record.
 127                  $DB->update_record('question_calculated', $options);
 128              } else {
 129                  // New options.
 130                  $DB->insert_record('question_calculated', $options);
 131              }
 132          }
 133  
 134          // Delete old answer records.
 135          if (!empty($oldanswers)) {
 136              foreach ($oldanswers as $oa) {
 137                  $DB->delete_records('question_answers', array('id' => $oa->id));
 138              }
 139          }
 140          if (!empty($oldoptions)) {
 141              foreach ($oldoptions as $oo) {
 142                  $DB->delete_records('question_calculated', array('id' => $oo->id));
 143              }
 144          }
 145  
 146          $this->save_hints($question, true);
 147  
 148          if (isset($question->import_process) && $question->import_process) {
 149              $this->import_datasets($question);
 150          }
 151          // Report any problems.
 152          if (!empty($result->notice)) {
 153              return $result;
 154          }
 155  
 156          return true;
 157      }
 158  
 159      protected function validate_answer($answer) {
 160          $error = qtype_calculated_find_formula_errors_in_text($answer);
 161          if ($error) {
 162              throw new coding_exception($error);
 163          }
 164      }
 165  
 166      protected function validate_question_data($question) {
 167          parent::validate_question_data($question);
 168          $this->validate_text($question->correctfeedback['text']);
 169          $this->validate_text($question->partiallycorrectfeedback['text']);
 170          $this->validate_text($question->incorrectfeedback['text']);
 171      }
 172  
 173      protected function make_question_instance($questiondata) {
 174          question_bank::load_question_definition_classes($this->name());
 175          if ($questiondata->options->single) {
 176              $class = 'qtype_calculatedmulti_single_question';
 177          } else {
 178              $class = 'qtype_calculatedmulti_multi_question';
 179          }
 180          return new $class();
 181      }
 182  
 183      protected function initialise_question_instance(question_definition $question, $questiondata) {
 184          question_type::initialise_question_instance($question, $questiondata);
 185  
 186          $question->shuffleanswers = $questiondata->options->shuffleanswers;
 187          $question->answernumbering = $questiondata->options->answernumbering;
 188          if (!empty($questiondata->options->layout)) {
 189              $question->layout = $questiondata->options->layout;
 190          } else {
 191              $question->layout = qtype_multichoice_single_question::LAYOUT_VERTICAL;
 192          }
 193  
 194          $question->synchronised = $questiondata->options->synchronize;
 195  
 196          $this->initialise_combined_feedback($question, $questiondata, true);
 197          $this->initialise_question_answers($question, $questiondata);
 198  
 199          foreach ($questiondata->options->answers as $a) {
 200              $question->answers[$a->id]->correctanswerlength = $a->correctanswerlength;
 201              $question->answers[$a->id]->correctanswerformat = $a->correctanswerformat;
 202          }
 203  
 204          $question->datasetloader = new qtype_calculated_dataset_loader($questiondata->id);
 205      }
 206  
 207      /**
 208       * Public override method, created so that make_answer will be available
 209       * for use by classes which extend qtype_multichoice_base.
 210       *
 211       * @param stdClass $answer  Moodle DB question_answers object.
 212       * @return question_answer
 213       */
 214      public function make_answer($answer) {
 215          return parent::make_answer($answer);
 216      }
 217  
 218      public function comment_header($question) {
 219          $strheader = '';
 220          $delimiter = '';
 221  
 222          $answers = $question->options->answers;
 223  
 224          foreach ($answers as $key => $answer) {
 225              $ans = shorten_text($answer->answer, 17, true);
 226              $strheader .= $delimiter.$ans;
 227              $delimiter = '<br/><br/>';
 228          }
 229          return $strheader;
 230      }
 231  
 232      public function comment_on_datasetitems($qtypeobj, $questionid, $questiontext,
 233              $answers, $data, $number) {
 234          global $DB;
 235          $comment = new stdClass();
 236          $comment->stranswers = array();
 237          $comment->outsidelimit = false;
 238          $comment->answers = array();
 239  
 240          $answers = fullclone($answers);
 241          $errors = '';
 242          $delimiter = ': ';
 243          foreach ($answers as $key => $answer) {
 244              $anssubstituted = $this->substitute_variables($answer->answer, $data);
 245              // Evaluate the equations i.e {=5+4).
 246              $anstext = '';
 247              $anstextremaining = $anssubstituted;
 248              while (preg_match('~\{=([^[:space:]}]*)}~', $anstextremaining, $regs1)) {
 249                  $anstextsplits = explode($regs1[0], $anstextremaining, 2);
 250                  $anstext =$anstext.$anstextsplits[0];
 251                  $anstextremaining = $anstextsplits[1];
 252                  if (empty($regs1[1])) {
 253                      $str = '';
 254                  } else {
 255                      if ($formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
 256                          $str=$formulaerrors;
 257                      } else {
 258                          eval('$str = '.$regs1[1].';');
 259                      }
 260                  }
 261                  $anstext = $anstext.$str;
 262              }
 263              $anstext .= $anstextremaining;
 264              $comment->stranswers[$key] = $anssubstituted.'<br/>'.$anstext;
 265          }
 266          return fullclone($comment);
 267      }
 268  
 269      public function get_virtual_qtype() {
 270          return question_bank::get_qtype('multichoice');
 271      }
 272  
 273      public function get_possible_responses($questiondata) {
 274          if ($questiondata->options->single) {
 275              $responses = array();
 276  
 277              foreach ($questiondata->options->answers as $aid => $answer) {
 278                  $responses[$aid] = new question_possible_response($answer->answer,
 279                          $answer->fraction);
 280              }
 281  
 282              $responses[null] = question_possible_response::no_response();
 283              return array($questiondata->id => $responses);
 284          } else {
 285              $parts = array();
 286  
 287              foreach ($questiondata->options->answers as $aid => $answer) {
 288                  $parts[$aid] = array($aid =>
 289                          new question_possible_response($answer->answer, $answer->fraction));
 290              }
 291  
 292              return $parts;
 293          }
 294      }
 295  
 296      public function move_files($questionid, $oldcontextid, $newcontextid) {
 297          $fs = get_file_storage();
 298  
 299          parent::move_files($questionid, $oldcontextid, $newcontextid);
 300          $this->move_files_in_answers($questionid, $oldcontextid, $newcontextid, true);
 301          $this->move_files_in_hints($questionid, $oldcontextid, $newcontextid);
 302  
 303          $fs->move_area_files_to_new_context($oldcontextid,
 304                  $newcontextid, 'qtype_calculatedmulti', 'correctfeedback', $questionid);
 305          $fs->move_area_files_to_new_context($oldcontextid,
 306                  $newcontextid, 'qtype_calculatedmulti', 'partiallycorrectfeedback', $questionid);
 307          $fs->move_area_files_to_new_context($oldcontextid,
 308                  $newcontextid, 'qtype_calculatedmulti', 'incorrectfeedback', $questionid);
 309      }
 310  
 311      protected function delete_files($questionid, $contextid) {
 312          $fs = get_file_storage();
 313  
 314          parent::delete_files($questionid, $contextid);
 315          $this->delete_files_in_answers($questionid, $contextid, true);
 316          $this->delete_files_in_hints($questionid, $contextid);
 317  
 318          $fs->delete_area_files($contextid, 'qtype_calculatedmulti',
 319                  'correctfeedback', $questionid);
 320          $fs->delete_area_files($contextid, 'qtype_calculatedmulti',
 321                  'partiallycorrectfeedback', $questionid);
 322          $fs->delete_area_files($contextid, 'qtype_calculatedmulti',
 323                  'incorrectfeedback', $questionid);
 324      }
 325  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1