Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 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   * Defines the editing form for the calculated question data set items.
  19   *
  20   * @package    qtype
  21   * @subpackage calculated
  22   * @copyright  2007 Jamie Pratt me@jamiep.org
  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/edit_question_form.php');
  30  
  31  
  32  /**
  33   * Calculated question data set items editing form definition.
  34   *
  35   * @copyright  2007 Jamie Pratt me@jamiep.org
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class question_dataset_dependent_items_form extends question_wizard_form {
  39      /**
  40       * Question object with options and answers already loaded by get_question_options
  41       * Be careful how you use this it is needed sometimes to set up the structure of the
  42       * form in definition_inner but data is always loaded into the form with set_defaults.
  43       *
  44       * @var object
  45       */
  46      public $question;
  47      /**
  48       * Reference to question type object
  49       *
  50       * @var question_dataset_dependent_questiontype
  51       */
  52      public $qtypeobj;
  53  
  54      /** @var stdClass the question category. */
  55      protected $category;
  56  
  57      /** @var context the context of the question category. */
  58      protected $categorycontext;
  59  
  60      public $datasetdefs;
  61  
  62      public $maxnumber = -1;
  63  
  64      public $regenerate;
  65  
  66      public $noofitems;
  67  
  68      public $outsidelimit = false;
  69  
  70      public $commentanswers = array();
  71  
  72      /**
  73       * Add question-type specific form fields.
  74       *
  75       * @param MoodleQuickForm $mform the form being built.
  76       */
  77      public function __construct($submiturl, $question, $regenerate) {
  78          global $SESSION;
  79  
  80          // Validate the question category.
  81          if (!isset($question->categoryobject)) {
  82              throw new moodle_exception('categorydoesnotexist', 'question');
  83          }
  84          $question->category = $question->categoryobject->id;
  85          $this->category = $question->categoryobject;
  86          $this->categorycontext = context::instance_by_id($this->category->contextid);
  87          $this->regenerate = $regenerate;
  88          $this->question = $question;
  89          $this->qtypeobj = question_bank::get_qtype($this->question->qtype);
  90          // Get the dataset defintions for this question.
  91          if (empty($question->id)) {
  92              $this->datasetdefs = $this->qtypeobj->get_dataset_definitions(
  93                      $question->id, $SESSION->calculated->definitionform->dataset);
  94          } else {
  95              if (empty($question->options)) {
  96                  $this->get_question_options($question);
  97              }
  98              $this->datasetdefs = $this->qtypeobj->get_dataset_definitions(
  99                      $question->id, array());
 100          }
 101  
 102          foreach ($this->datasetdefs as $datasetdef) {
 103              // Get maxnumber.
 104              if ($this->maxnumber == -1 || $datasetdef->itemcount < $this->maxnumber) {
 105                  $this->maxnumber = $datasetdef->itemcount;
 106              }
 107          }
 108          foreach ($this->datasetdefs as $defid => $datasetdef) {
 109              if (isset($datasetdef->id)) {
 110                  $this->datasetdefs[$defid]->items =
 111                          $this->qtypeobj->get_database_dataset_items($datasetdef->id);
 112              }
 113          }
 114          parent::__construct($submiturl);
 115      }
 116  
 117      protected function definition() {
 118          global $PAGE;
 119  
 120          $labelsharedwildcard = get_string("sharedwildcard", "qtype_calculated");
 121          $mform = $this->_form;
 122          $mform->setDisableShortforms();
 123  
 124          $strquestionlabel = $this->qtypeobj->comment_header($this->question);
 125          if ($this->maxnumber != -1 ) {
 126              $this->noofitems = $this->maxnumber;
 127          } else {
 128              $this->noofitems = 0;
 129          }
 130          $label = get_string("sharedwildcards", "qtype_calculated");
 131  
 132          $html2 = $this->qtypeobj->print_dataset_definitions_category_shared(
 133                  $this->question, $this->datasetdefs);
 134          $mform->addElement('static', 'listcategory', $label, $html2);
 135          // ...----------------------------------------------------------------------.
 136          $mform->addElement('submit', 'updatedatasets',
 137                  get_string('updatedatasetparam', 'qtype_calculated'));
 138          $mform->registerNoSubmitButton('updatedatasets');
 139          $mform->addElement('header', 'additemhdr',
 140                  get_string('itemtoadd', 'qtype_calculated'));
 141          $idx = 1;
 142          $data = array();
 143          $j = (($this->noofitems) * count($this->datasetdefs))+1;
 144          foreach ($this->datasetdefs as $defkey => $datasetdef) {
 145              if ($datasetdef->category |= 0 ) {
 146                  $name = get_string('sharedwildcard', 'qtype_calculated', $datasetdef->name);
 147              } else {
 148                  $name = get_string('wildcard', 'qtype_calculated', $datasetdef->name);
 149              }
 150              $mform->addElement('float', "number[{$j}]", $name);
 151              $this->qtypeobj->custom_generator_tools_part($mform, $idx, $j);
 152              $idx++;
 153              $mform->addElement('hidden', "definition[{$j}]");
 154              $mform->setType("definition[{$j}]", PARAM_RAW);
 155              $mform->addElement('hidden', "itemid[{$j}]");
 156              $mform->setType("itemid[{$j}]", PARAM_RAW);
 157              $mform->addElement('static', "divider[{$j}]", '', '<hr />');
 158              $mform->setType("divider[{$j}]", PARAM_RAW);
 159              $j++;
 160          }
 161  
 162          $mform->addElement('header', 'updateanswershdr',
 163                  get_string('answerstoleranceparam', 'qtype_calculated'));
 164          $mform->addElement('submit', 'updateanswers',
 165                  get_string('updatetolerancesparam', 'qtype_calculated'));
 166          $mform->setAdvanced('updateanswers', true);
 167          $mform->registerNoSubmitButton('updateanswers');
 168  
 169          $answers = fullclone($this->question->options->answers);
 170          $key1 =1;
 171          foreach ($answers as $key => $answer) {
 172              $ans = shorten_text($answer->answer, 17, true);
 173              if ($ans === '*') {
 174                  $mform->addElement('static',
 175                          'answercomment[' . ($this->noofitems+$key1) . ']', $ans);
 176                  $mform->addElement('hidden', 'tolerance['.$key.']', '');
 177                  $mform->setType('tolerance['.$key.']', PARAM_FLOAT); // No need to worry about localisation, as the value of this field will not be shown to users anymore.
 178                  $mform->setAdvanced('tolerance['.$key.']', true);
 179                  $mform->addElement('hidden', 'tolerancetype['.$key.']', '');
 180                  $mform->setType('tolerancetype['.$key.']', PARAM_RAW);
 181                  $mform->setAdvanced('tolerancetype['.$key.']', true);
 182                  $mform->addElement('hidden', 'correctanswerlength['.$key.']', '');
 183                  $mform->setType('correctanswerlength['.$key.']', PARAM_RAW);
 184                  $mform->setAdvanced('correctanswerlength['.$key.']', true);
 185                  $mform->addElement('hidden', 'correctanswerformat['.$key.']', '');
 186                  $mform->setType('correctanswerformat['.$key.']', PARAM_RAW);
 187                  $mform->setAdvanced('correctanswerformat['.$key.']', true);
 188              } else if ( $ans !== '' ) {
 189                  $mform->addElement('static', 'answercomment[' . ($this->noofitems+$key1) . ']',
 190                          $ans);
 191                  $mform->addElement('float', 'tolerance['.$key.']',
 192                          get_string('tolerance', 'qtype_calculated'));
 193                  $mform->setAdvanced('tolerance['.$key.']', true);
 194                  $mform->addElement('select', 'tolerancetype['.$key.']',
 195                          get_string('tolerancetype', 'qtype_numerical'),
 196                          $this->qtypeobj->tolerance_types());
 197                  $mform->setAdvanced('tolerancetype['.$key.']', true);
 198  
 199                  $mform->addElement('select', 'correctanswerlength['.$key.']',
 200                          get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
 201                  $mform->setAdvanced('correctanswerlength['.$key.']', true);
 202  
 203                  $answerlengthformats = array(
 204                      '1' => get_string('decimalformat', 'qtype_numerical'),
 205                      '2' => get_string('significantfiguresformat', 'qtype_calculated')
 206                  );
 207                  $mform->addElement('select', 'correctanswerformat['.$key.']',
 208                          get_string('correctanswershowsformat', 'qtype_calculated'),
 209                          $answerlengthformats);
 210                  $mform->setAdvanced('correctanswerformat['.$key.']', true);
 211                  $mform->addElement('static', 'dividertolerance', '', '<hr />');
 212                  $mform->setAdvanced('dividertolerance', true);
 213              }
 214              $key1++;
 215          }
 216  
 217          $addremoveoptions = array();
 218          $addremoveoptions['1']='1';
 219          for ($i=10; $i<=100; $i+=10) {
 220               $addremoveoptions["{$i}"] = "{$i}";
 221          }
 222          $showoptions = Array();
 223          $showoptions['1']='1';
 224          $showoptions['2']='2';
 225          $showoptions['5']='5';
 226          for ($i=10; $i<=100; $i+=10) {
 227               $showoptions["{$i}"] = "{$i}";
 228          }
 229          $mform->addElement('header', 'addhdr', get_string('add', 'moodle'));
 230          $mform->closeHeaderBefore('addhdr');
 231  
 232          if ($this->qtypeobj->supports_dataset_item_generation()) {
 233              $radiogrp = array();
 234              $radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]',
 235                      null, get_string('reuseifpossible', 'qtype_calculated'), 0);
 236              $radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]',
 237                      null, get_string('forceregenerationshared', 'qtype_calculated'), 1);
 238              $radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]',
 239                      null, get_string('forceregenerationall', 'qtype_calculated'), 2);
 240              $mform->addGroup($radiogrp, 'forceregenerationgrp',
 241                      get_string('nextitemtoadd', 'qtype_calculated'), "<br/>", false);
 242          }
 243  
 244          $mform->addElement('submit', 'getnextbutton', get_string('getnextnow', 'qtype_calculated'));
 245          $mform->addElement('static', "dividera", '', '<hr />');
 246          $addgrp = array();
 247          $addgrp[] =& $mform->createElement('submit', 'addbutton', get_string('add', 'moodle'));
 248          $addgrp[] =& $mform->createElement('select', "selectadd",
 249                  get_string('additem', 'qtype_calculated'), $addremoveoptions);
 250          $addgrp[] = & $mform->createElement('static', "stat", "Items",
 251                  get_string('newsetwildcardvalues', 'qtype_calculatedsimple'));
 252          $mform->addGroup($addgrp, 'addgrp', get_string('additem', 'qtype_calculated'), ' ', false);
 253          $mform->addElement('static', "divideradd", '', '');
 254          if ($this->noofitems > 0) {
 255              $mform->addElement('header', 'deleteitemhdr', get_string('delete', 'moodle'));
 256              $deletegrp = array();
 257              $deletegrp[] = $mform->createElement('submit', 'deletebutton',
 258                      get_string('delete', 'moodle'));
 259              $deletegrp[] = $mform->createElement('select', 'selectdelete',
 260                      get_string('deleteitem', 'qtype_calculated')."1", $addremoveoptions);
 261              $deletegrp[] = $mform->createElement('static', "stat", "Items",
 262                      get_string('setwildcardvalues', 'qtype_calculatedsimple'));
 263              $mform->addGroup($deletegrp, 'deletegrp', '', '   ', false);
 264          } else {
 265              $mform->addElement('static', 'warning', '', '<span class="error">' .
 266                      get_string('youmustaddatleastoneitem', 'qtype_calculated').'</span>');
 267          }
 268  
 269          $addgrp1 = array();
 270          $addgrp1[] = $mform->createElement('submit', 'showbutton',
 271                  get_string('showitems', 'qtype_calculated'));
 272          $addgrp1[] = $mform->createElement('select', "selectshow", '' , $showoptions);
 273          $addgrp1[] = $mform->createElement('static', "stat", '',
 274                  get_string('setwildcardvalues', 'qtype_calculated'));
 275          $mform->addGroup($addgrp1, 'addgrp1', '', '   ', false);
 276          $mform->registerNoSubmitButton('showbutton');
 277          $mform->closeHeaderBefore('addgrp1');
 278          // ...----------------------------------------------------------------------.
 279          $j = $this->noofitems * count($this->datasetdefs);
 280          $k = optional_param('selectshow', 1, PARAM_INT);
 281          for ($i = $this->noofitems; $i >= 1; $i--) {
 282              if ($k > 0) {
 283                  $mform->addElement('header', 'setnoheader' . $i, "<b>" .
 284                          get_string('setno', 'qtype_calculated', $i)."</b>&nbsp;&nbsp;");
 285              }
 286              foreach ($this->datasetdefs as $defkey => $datasetdef) {
 287                  if ($k > 0) {
 288                      if ($datasetdef->category == 0 ) {
 289                          $mform->addElement('float', "number[{$j}]",
 290                                  get_string('wildcard', 'qtype_calculated', $datasetdef->name));
 291                      } else {
 292                          $mform->addElement('float', "number[{$j}]", get_string(
 293                                  'sharedwildcard', 'qtype_calculated', $datasetdef->name));
 294                      }
 295  
 296                  } else {
 297                      $mform->addElement('hidden', "number[{$j}]" , '');
 298                      $mform->setType("number[{$j}]", PARAM_LOCALISEDFLOAT); // Localisation handling has to be done manually.
 299                  }
 300                  $mform->addElement('hidden', "itemid[{$j}]");
 301                  $mform->setType("itemid[{$j}]", PARAM_INT);
 302  
 303                  $mform->addElement('hidden', "definition[{$j}]");
 304                  $mform->setType("definition[{$j}]", PARAM_NOTAGS);
 305                  $data[$datasetdef->name] =$datasetdef->items[$i]->value;
 306  
 307                  $j--;
 308              }
 309              if ('' != $strquestionlabel && ($k > 0 )) {
 310                  // ... $this->outsidelimit || !empty($this->numbererrors ).
 311                  $repeated[] = $mform->addElement('static', "answercomment[{$i}]", $strquestionlabel);
 312                  // Decode equations in question text.
 313                  $qtext = $this->qtypeobj->substitute_variables(
 314                          $this->question->questiontext, $data);
 315                  $textequations = $this->qtypeobj->find_formulas($qtext);
 316                  if ($textequations != '' && count($textequations) > 0 ) {
 317                      $mform->addElement('static', "divider1[{$j}]", '',
 318                              'Formulas {=..} in question text');
 319                      foreach ($textequations as $key => $equation) {
 320                          if ($formulaerrors = qtype_calculated_find_formula_errors($equation)) {
 321                              $str = $formulaerrors;
 322                          } else {
 323                              eval('$str = '.$equation.';');
 324                          }
 325                          $equation = shorten_text($equation, 17, true);
 326                          $mform->addElement('static', "textequation", "{={$equation}}", "=".$str);
 327                      }
 328                  }
 329  
 330              }
 331              $k--;
 332  
 333          }
 334          $mform->addElement('static', 'outsidelimit', '', '');
 335  
 336          // Submit buttons.
 337          if ($this->noofitems > 0) {
 338              $buttonarray = [];
 339              $buttonarray[] = $mform->createElement(
 340                      'submit', 'savechanges', get_string('savechanges'));
 341              if (\core\plugininfo\qbank::is_plugin_enabled('qbank_previewquestion')) {
 342                  $previewlink = $PAGE->get_renderer('qbank_previewquestion')->question_preview_link($this->question->id,
 343                          $this->categorycontext, true);
 344              }
 345              $buttonarray[] = $mform->createElement('static', 'previewlink', '', $previewlink);
 346  
 347              $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
 348              $mform->closeHeaderBefore('buttonar');
 349          }
 350  
 351          $this->add_hidden_fields();
 352  
 353          $mform->addElement('hidden', 'category');
 354          $mform->setType('category', PARAM_SEQUENCE);
 355  
 356          $mform->addElement('hidden', 'wizard', 'datasetitems');
 357          $mform->setType('wizard', PARAM_ALPHA);
 358      }
 359  
 360      public function set_data($question) {
 361          $formdata = array();
 362          $fromform = new stdClass();
 363          if (isset($question->options)) {
 364              $answers = $question->options->answers;
 365              if (count($answers)) {
 366                  if (optional_param('updateanswers', false, PARAM_BOOL) ||
 367                          optional_param('updatedatasets', false, PARAM_BOOL)) {
 368                      foreach ($answers as $key => $answer) {
 369                          $fromform->tolerance[$key]= $this->_form->getElementValue(
 370                                  'tolerance['.$key.']');
 371                          $answer->tolerance = $fromform->tolerance[$key];
 372                          $fromform->tolerancetype[$key]= $this->_form->getElementValue(
 373                                  'tolerancetype['.$key.']');
 374                          if (is_array($fromform->tolerancetype[$key])) {
 375                              $fromform->tolerancetype[$key]= $fromform->tolerancetype[$key][0];
 376                          }
 377                          $answer->tolerancetype = $fromform->tolerancetype[$key];
 378                          $fromform->correctanswerlength[$key]= $this->_form->getElementValue(
 379                                  'correctanswerlength['.$key.']');
 380                          if (is_array($fromform->correctanswerlength[$key])) {
 381                              $fromform->correctanswerlength[$key] =
 382                                      $fromform->correctanswerlength[$key][0];
 383                          }
 384                          $answer->correctanswerlength = $fromform->correctanswerlength[$key];
 385                          $fromform->correctanswerformat[$key] = $this->_form->getElementValue(
 386                                  'correctanswerformat['.$key.']');
 387                          if (is_array($fromform->correctanswerformat[$key])) {
 388                              $fromform->correctanswerformat[$key] =
 389                                      $fromform->correctanswerformat[$key][0];
 390                          }
 391                          $answer->correctanswerformat = $fromform->correctanswerformat[$key];
 392                      }
 393                      $this->qtypeobj->save_question_calculated($question, $fromform);
 394  
 395                  } else {
 396                      foreach ($answers as $key => $answer) {
 397                          $formdata['tolerance['.$key.']'] = $answer->tolerance;
 398                          $formdata['tolerancetype['.$key.']'] = $answer->tolerancetype;
 399                          $formdata['correctanswerlength['.$key.']'] = $answer->correctanswerlength;
 400                          $formdata['correctanswerformat['.$key.']'] = $answer->correctanswerformat;
 401                      }
 402                  }
 403              }
 404          }
 405          // Fill out all data sets and also the fields for the next item to add.
 406          $j = $this->noofitems * count($this->datasetdefs);
 407          for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--) {
 408              $data = array();
 409              foreach ($this->datasetdefs as $defid => $datasetdef) {
 410                  if (isset($datasetdef->items[$itemnumber])) {
 411                      $value = $datasetdef->items[$itemnumber]->value;
 412                      if ($this->_form->getElementType("number[{$j}]") == 'hidden') {
 413                          // Some of the number elements are from the float type and some are from the hidden type.
 414                          // We need to manually handle localised floats for hidden elements.
 415                          $value = format_float($value, -1);
 416                      }
 417                      $formdata["number[{$j}]"] = $value;
 418                      $formdata["definition[{$j}]"] = $defid;
 419                      $formdata["itemid[{$j}]"] = $datasetdef->items[$itemnumber]->id;
 420                      $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value;
 421                  }
 422                  $j--;
 423              }
 424              $comment = $this->qtypeobj->comment_on_datasetitems($this->qtypeobj, $question->id,
 425                      $question->questiontext, $answers, $data, $itemnumber);
 426              if ($comment->outsidelimit) {
 427                  $this->outsidelimit=$comment->outsidelimit;
 428              }
 429              $totalcomment='';
 430              foreach ($question->options->answers as $key => $answer) {
 431                  $totalcomment .= $comment->stranswers[$key].'<br/>';
 432              }
 433              $formdata['answercomment['.$itemnumber.']'] = $totalcomment;
 434          }
 435  
 436          $formdata['nextpageparam[forceregeneration]'] = $this->regenerate;
 437          $formdata['selectdelete'] = '1';
 438          $formdata['selectadd'] = '1';
 439          $j = $this->noofitems * count($this->datasetdefs)+1;
 440          $data = array(); // Data for comment_on_datasetitems later.
 441          // Dataset generation defaults.
 442          if ($this->qtypeobj->supports_dataset_item_generation()) {
 443              $itemnumber = $this->noofitems+1;
 444              foreach ($this->datasetdefs as $defid => $datasetdef) {
 445                  if (!optional_param('updatedatasets', false, PARAM_BOOL) &&
 446                          !optional_param('updateanswers', false, PARAM_BOOL)) {
 447                      $value = $this->qtypeobj->generate_dataset_item($datasetdef->options);
 448                  } else {
 449                      $value = $this->_form->getElementValue("number[{$j}]");
 450                  }
 451                  if ($this->_form->getElementType("number[{$j}]") == 'hidden') {
 452                      // Some of the number elements are from the float type and some are from the hidden type.
 453                      // We need to manually handle localised floats for hidden elements.
 454                      $value = format_float($value, -1);
 455                  }
 456                  $formdata["number[{$j}]"] = $value;
 457                  $formdata["definition[{$j}]"] = $defid;
 458                  $formdata["itemid[{$j}]"] = isset($datasetdef->items[$itemnumber]) ?
 459                          $datasetdef->items[$itemnumber]->id : 0;
 460                  $data[$datasetdef->name] = $formdata["number[{$j}]"];
 461                  $j++;
 462              }
 463          }
 464  
 465          // Existing records override generated data depending on radio element.
 466          $j = $this->noofitems * count($this->datasetdefs) + 1;
 467          if (!$this->regenerate && !optional_param('updatedatasets', false, PARAM_BOOL) &&
 468                  !optional_param('updateanswers', false, PARAM_BOOL)) {
 469              $itemnumber = $this->noofitems + 1;
 470              foreach ($this->datasetdefs as $defid => $datasetdef) {
 471                  if (isset($datasetdef->items[$itemnumber])) {
 472                      $formdata["number[{$j}]"] = $datasetdef->items[$itemnumber]->value;
 473                      $formdata["definition[{$j}]"] = $defid;
 474                      $formdata["itemid[{$j}]"] = $datasetdef->items[$itemnumber]->id;
 475                      $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value;
 476                  }
 477                  $j++;
 478              }
 479          }
 480  
 481          $comment = $this->qtypeobj->comment_on_datasetitems($this->qtypeobj, $question->id,
 482                  $question->questiontext, $answers, $data, ($this->noofitems + 1));
 483          if (isset($comment->outsidelimit) && $comment->outsidelimit) {
 484              $this->outsidelimit=$comment->outsidelimit;
 485          }
 486          $key1 = 1;
 487          foreach ($question->options->answers as $key => $answer) {
 488              $formdata['answercomment['.($this->noofitems+$key1).']'] = $comment->stranswers[$key];
 489              $key1++;
 490          }
 491  
 492          if ($this->outsidelimit) {
 493              $formdata['outsidelimit']= '<span class="error">' .
 494                      get_string('oneanswertrueansweroutsidelimits', 'qtype_calculated') . '</span>';
 495          }
 496          $formdata = $this->qtypeobj->custom_generator_set_data($this->datasetdefs, $formdata);
 497  
 498          parent::set_data((object)($formdata + (array)$question));
 499      }
 500  
 501      public function validation($data, $files) {
 502          $errors = array();
 503          if (isset($data['savechanges']) && ($this->noofitems==0) ) {
 504              $errors['warning'] = get_string('warning', 'mnet');
 505          }
 506          if ($this->outsidelimit) {
 507              $errors['outsidelimits'] =
 508                      get_string('oneanswertrueansweroutsidelimits', 'qtype_calculated');
 509          }
 510          $numbers = $data['number'];
 511          foreach ($numbers as $key => $number) {
 512              if (! is_numeric($number)) {
 513                  if (stristr($number, ',')) {
 514                      $errors['number['.$key.']'] = get_string('nocommaallowed', 'qtype_calculated');
 515                  } else {
 516                      $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated');
 517                  }
 518              } else if (stristr($number, 'x')) {
 519                  $a = new stdClass();
 520                  $a->name = '';
 521                  $a->value = $number;
 522                  $errors['number['.$key.']'] = get_string('hexanotallowed', 'qtype_calculated', $a);
 523              } else if (is_nan($number)) {
 524                  $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated');
 525              }
 526          }
 527          return $errors;
 528      }
 529  }