See Release Notes
Long Term Support Release
Differences Between: [Versions 401 and 402] [Versions 401 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 simplequestion type. 19 * 20 * @package qtype 21 * @subpackage calculatedsimple 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/calculated/edit_calculated_form.php'); 30 31 32 /** 33 * Editing form for the calculated simplequestion type. 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 qtype_calculatedsimple_edit_form extends qtype_calculated_edit_form { 39 /** 40 * Handle to the question type for this question. 41 * 42 * @var question_calculatedsimple_qtype 43 */ 44 public $qtypeobj; 45 46 public $wildcarddisplay; 47 48 public $questiondisplay; 49 50 public $datasetdefs; 51 52 public $reload = false; 53 54 public $maxnumber = -1; 55 56 public $regenerate = true; 57 58 public $noofitems; 59 60 public $outsidelimit = false; 61 62 public $commentanswer = array(); 63 64 public $answer = array(); 65 66 public $nonemptyanswer = array(); 67 68 public $numbererrors = array(); 69 70 public $formdata = array(); 71 72 public function __construct($submiturl, $question, $category, $contexts, $formeditable = true) { 73 $this->regenerate = true; 74 $this->question = $question; 75 76 $this->qtypeobj = question_bank::get_qtype($this->question->qtype); 77 // Get the dataset definitions for this question. 78 // Coming here everytime even when using a NoSubmitButton. 79 // This will only set the values to the actual question database content 80 // which is not what we want, so this should be removed from here. 81 // Get priority to paramdatasets. 82 83 $this->reload = optional_param('reload', false, PARAM_BOOL); 84 if (!$this->reload) { // Use database data as this is first pass 85 // Question->id == 0 so no stored datasets. 86 if (!empty($question->id)) { 87 88 $this->datasetdefs = $this->qtypeobj->get_dataset_definitions( 89 $question->id, array()); 90 91 if (!empty($this->datasetdefs)) { 92 foreach ($this->datasetdefs as $defid => $datasetdef) { 93 // First get the items in case their number does not correspond to itemcount. 94 if (isset($datasetdef->id)) { 95 $this->datasetdefs[$defid]->items = 96 $this->qtypeobj->get_database_dataset_items($datasetdef->id); 97 if ($this->datasetdefs[$defid]->items != '') { 98 $datasetdef->itemcount = count($this->datasetdefs[$defid]->items); 99 } else { 100 $datasetdef->itemcount = 0; 101 } 102 } 103 // Get maxnumber. 104 if ($this->maxnumber == -1 || $datasetdef->itemcount < $this->maxnumber) { 105 $this->maxnumber = $datasetdef->itemcount; 106 } 107 } 108 } 109 110 $i = 0; 111 foreach ($this->question->options->answers as $answer) { 112 $this->answer[$i] = $answer; 113 $i++; 114 } 115 $this->nonemptyanswer = $this->answer; 116 } 117 $datasettoremove = false; 118 $newdatasetvalues = false; 119 $newdataset = false; 120 } else { 121 // Handle reload to get values from the form-elements 122 // answers, datasetdefs and data_items. In any case the validation 123 // step will warn the user of any error in settings the values. 124 // Verification for the specific dataset values as the other parameters 125 // units, feeedback etc are handled elsewhere. 126 // Handle request buttons : 127 // 'analyzequestion' (Identify the wild cards {x..} present in answers). 128 // 'addbutton' (create new set of datatitems). 129 // 'updatedatasets' is handled automatically on each reload. 130 // The analyzequestion is done every time on reload 131 // to detect any new wild cards so that the current display reflects 132 // the mandatory (i.e. in answers) datasets. 133 // To implement : don't do any changes if the question is used in a quiz. 134 // If new datadef, new properties should erase items. 135 // most of the data. 136 $datasettoremove = false; 137 $newdatasetvalues = false; 138 $newdataset = false; 139 $dummyform = new stdClass(); 140 $mandatorydatasets = array(); 141 // Should not test on adding a new answer. 142 // Should test if there are already olddatasets or if the 'analyzequestion'. 143 // submit button has been clicked. 144 if (optional_param_array('datasetdef', false, PARAM_BOOL) || 145 optional_param('analyzequestion', false, PARAM_BOOL)) { 146 147 if ($dummyform->answer = optional_param_array('answer', '', PARAM_NOTAGS)) { 148 // There is always at least one answer... 149 $fraction = optional_param_array('fraction', '', PARAM_FLOAT); 150 $tolerance = optional_param_array('tolerance', '', PARAM_LOCALISEDFLOAT); 151 $tolerancetype = optional_param_array('tolerancetype', '', PARAM_FLOAT); 152 $correctanswerlength = optional_param_array('correctanswerlength', '', PARAM_INT); 153 $correctanswerformat = optional_param_array('correctanswerformat', '', PARAM_INT); 154 155 foreach ($dummyform->answer as $key => $answer) { 156 if (trim($answer) != '') { // Just look for non-empty. 157 $this->answer[$key] = new stdClass(); 158 $this->answer[$key]->answer = $answer; 159 $this->answer[$key]->fraction = $fraction[$key]; 160 $this->answer[$key]->tolerance = $tolerance[$key]; 161 $this->answer[$key]->tolerancetype = $tolerancetype[$key]; 162 $this->answer[$key]->correctanswerlength = $correctanswerlength[$key]; 163 $this->answer[$key]->correctanswerformat = $correctanswerformat[$key]; 164 $this->nonemptyanswer[]= $this->answer[$key]; 165 $mandatorydatasets += $this->qtypeobj->find_dataset_names($answer); 166 } 167 } 168 } 169 $this->datasetdefs = array(); 170 // Rebuild datasetdefs from old values. 171 if ($olddef = optional_param_array('datasetdef', '', PARAM_RAW)) { 172 $calcmin = optional_param_array('calcmin', '', PARAM_LOCALISEDFLOAT); 173 $calclength = optional_param_array('calclength', '', PARAM_INT); 174 $calcmax = optional_param_array('calcmax', '', PARAM_LOCALISEDFLOAT); 175 $oldoptions = optional_param_array('defoptions', '', PARAM_RAW); 176 $newdatasetvalues = false; 177 $sizeofolddef = count($olddef); 178 for ($key = 1; $key <= $sizeofolddef; $key++) { 179 $def = $olddef[$key]; 180 $this->datasetdefs[$def]= new stdClass(); 181 $this->datasetdefs[$def]->type = 1; 182 $this->datasetdefs[$def]->category = 0; 183 $this->datasetdefs[$def]->options = $oldoptions[$key]; 184 $this->datasetdefs[$def]->calcmin = $calcmin[$key]; 185 $this->datasetdefs[$def]->calcmax = $calcmax[$key]; 186 $this->datasetdefs[$def]->calclength = $calclength[$key]; 187 // Then compare with new values. 188 if (preg_match('~^(uniform|loguniform):([^:]*):([^:]*):([0-9]*)$~', 189 $this->datasetdefs[$def]->options, $regs)) { 190 if ($this->datasetdefs[$def]->calcmin != $regs[2]|| 191 $this->datasetdefs[$def]->calcmax != $regs[3] || 192 $this->datasetdefs[$def]->calclength != $regs[4]) { 193 $newdatasetvalues = true; 194 } 195 } 196 $this->datasetdefs[$def]->options = "uniform:" . 197 $this->datasetdefs[$def]->calcmin . ":" . 198 $this->datasetdefs[$def]->calcmax . ":" . 199 $this->datasetdefs[$def]->calclength; 200 } 201 } 202 // Detect new datasets. 203 $newdataset = false; 204 foreach ($mandatorydatasets as $datasetname) { 205 if (!isset($this->datasetdefs["1-0-{$datasetname}"])) { 206 $key = "1-0-{$datasetname}"; 207 $this->datasetdefs[$key] = new stdClass(); 208 $this->datasetdefs[$key]->type = 1; 209 $this->datasetdefs[$key]->category = 0; 210 $this->datasetdefs[$key]->name = $datasetname; 211 $this->datasetdefs[$key]->options = "uniform:1.0:10.0:1"; 212 $newdataset = true; 213 } else { 214 $this->datasetdefs["1-0-{$datasetname}"]->name = $datasetname; 215 } 216 } 217 // Remove obsolete datasets. 218 $datasettoremove = false; 219 foreach ($this->datasetdefs as $defkey => $datasetdef) { 220 if (!isset($datasetdef->name)) { 221 $datasettoremove = true; 222 unset($this->datasetdefs[$defkey]); 223 } 224 } 225 } 226 } // Handle reload. 227 // Create items if $newdataset and noofitems > 0 and !$newdatasetvalues. 228 // Eliminate any items if $newdatasetvalues. 229 // Eliminate any items if $datasettoremove, $newdataset, $newdatasetvalues. 230 if ($datasettoremove ||$newdataset ||$newdatasetvalues) { 231 foreach ($this->datasetdefs as $defkey => $datasetdef) { 232 $datasetdef->itemcount = 0; 233 unset($datasetdef->items); 234 } 235 } 236 $maxnumber = -1; 237 if (optional_param('addbutton', false, PARAM_BOOL)) { 238 $maxnumber = optional_param('selectadd', '', PARAM_INT); // FIXME: sloppy coding. 239 foreach ($this->datasetdefs as $defid => $datasetdef) { 240 $datasetdef->itemcount = $maxnumber; 241 unset($datasetdef->items); 242 for ($numberadded = 1; $numberadded <= $maxnumber; $numberadded++) { 243 $datasetitem = new stdClass(); 244 $datasetitem->itemnumber = $numberadded; 245 $datasetitem->id = 0; 246 $datasetitem->value = $this->qtypeobj->generate_dataset_item( 247 $datasetdef->options); 248 $this->datasetdefs[$defid]->items[$numberadded] = $datasetitem; 249 } 250 } 251 $this->maxnumber = $maxnumber; 252 } else { 253 // Handle reload dataset items. 254 if (optional_param_array('definition', '', PARAM_NOTAGS) && 255 !($datasettoremove ||$newdataset ||$newdatasetvalues)) { 256 $i = 1; 257 $fromformdefinition = optional_param_array('definition', '', PARAM_NOTAGS); 258 $fromformnumber = optional_param_array('number', '', PARAM_LOCALISEDFLOAT); 259 $fromformitemid = optional_param_array('itemid', '', PARAM_INT); 260 ksort($fromformdefinition); 261 262 foreach ($fromformdefinition as $key => $defid) { 263 $addeditem = new stdClass(); 264 $addeditem->id = $fromformitemid[$i]; 265 $addeditem->value = $fromformnumber[$i]; 266 $addeditem->itemnumber = ceil($i / count($this->datasetdefs)); 267 $this->datasetdefs[$defid]->items[$addeditem->itemnumber] = $addeditem; 268 $this->datasetdefs[$defid]->itemcount = $i; 269 $i++; 270 } 271 } 272 if (isset($addeditem->itemnumber) && $this->maxnumber < $addeditem->itemnumber) { 273 $this->maxnumber = $addeditem->itemnumber; 274 if (!empty($this->datasetdefs)) { 275 foreach ($this->datasetdefs as $datasetdef) { 276 $datasetdef->itemcount = $this->maxnumber; 277 } 278 } 279 } 280 } 281 282 parent::__construct($submiturl, $question, $category, $contexts, $formeditable); 283 } 284 285 /** 286 * Add question-type specific form fields. 287 * 288 * @param MoodleQuickForm $mform the form being built. 289 */ 290 protected function definition_inner($mform) { 291 $strquestionlabel = $this->qtypeobj->comment_header($this->nonemptyanswer); 292 $label = get_string("sharedwildcards", "qtype_calculated"); 293 $mform->addElement('hidden', 'synchronize', 0); 294 $mform->addElement('hidden', 'initialcategory', 1); 295 $mform->setType('synchronize', PARAM_BOOL); 296 $mform->setType('initialcategory', PARAM_INT); 297 $mform->addElement('hidden', 'reload', 1); 298 $mform->setType('reload', PARAM_INT); 299 $addfieldsname = 'updatequestion value'; 300 $addstring = get_string("updatecategory", "qtype_calculated"); 301 $mform->registerNoSubmitButton($addfieldsname); 302 303 $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'), 304 question_bank::fraction_options(), 1, 1); 305 306 $this->add_unit_options($mform, $this); 307 $this->add_unit_fields($mform, $this); 308 $this->add_interactive_settings(); 309 310 $label = "<div class='mdl-align'></div><div class='mdl-align'>" . 311 get_string('wildcardrole', 'qtype_calculatedsimple') . "</div>"; 312 $mform->addElement('html', "<div class='mdl-align'> </div>"); 313 // Explaining the role of datasets so other strings can be shortened. 314 $mform->addElement('html', $label); 315 316 $mform->addElement('submit', 'analyzequestion', 317 get_string('findwildcards', 'qtype_calculatedsimple')); 318 $mform->registerNoSubmitButton('analyzequestion'); 319 $mform->closeHeaderBefore('analyzequestion'); 320 $this->wizarddisplay = optional_param('analyzequestion', false, PARAM_BOOL); 321 if ($this->maxnumber != -1) { 322 $this->noofitems = $this->maxnumber; 323 } else { 324 $this->noofitems = 0; 325 } 326 if (!empty($this->datasetdefs)) {// So there are some datadefs. 327 // We put them on the page. 328 $key = 0; 329 $mform->addElement('header', 'additemhdr', 330 get_string('wildcardparam', 'qtype_calculatedsimple')); 331 $idx = 1; 332 if (!empty($this->datasetdefs)) {// Unnecessary test. 333 $j = (($this->noofitems) * count($this->datasetdefs))+1;// 334 foreach ($this->datasetdefs as $defkey => $datasetdef) { 335 $mform->addElement('static', "na[{$j}]", 336 get_string('param', 'qtype_calculated', $datasetdef->name)); 337 $this->qtypeobj->custom_generator_tools_part($mform, $idx, $j); 338 $mform->addElement('hidden', "datasetdef[{$idx}]"); 339 $mform->setType("datasetdef[{$idx}]", PARAM_RAW); 340 $mform->addElement('hidden', "defoptions[{$idx}]"); 341 $mform->setType("defoptions[{$idx}]", PARAM_RAW); 342 $idx++; 343 $mform->addElement('static', "divider[{$j}]", '', '<hr />'); 344 $j++; 345 } 346 } 347 // This should be done before the elements are created and stored as $this->formdata. 348 // Fill out all data sets and also the fields for the next item to add. 349 /*Here we do already the values error analysis so that 350 * we could force all wild cards values display if there is an error in values. 351 * as using a , in a number */ 352 $this->numbererrors = array(); 353 if (!empty($this->datasetdefs)) { 354 $j = $this->noofitems * count($this->datasetdefs); 355 for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--) { 356 $data = array(); 357 $numbererrors = ''; 358 $comment = new stdClass(); 359 $comment->stranswers = array(); 360 $comment->outsidelimit = false; 361 $comment->answers = array(); 362 363 foreach ($this->datasetdefs as $defid => $datasetdef) { 364 if (isset($datasetdef->items[$itemnumber])) { 365 $this->formdata["definition[{$j}]"] = $defid; 366 $this->formdata["itemid[{$j}]"] = 367 $datasetdef->items[$itemnumber]->id; 368 $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value; 369 $this->formdata["number[{$j}]"] = $number = 370 $datasetdef->items[$itemnumber]->value; 371 if (! is_numeric($number)) { 372 $a = new stdClass(); 373 $a->name = '{'.$datasetdef->name.'}'; 374 $a->value = $datasetdef->items[$itemnumber]->value; 375 if (stristr($number, ',')) { 376 $this->numbererrors["number[{$j}]"] = 377 get_string('nocommaallowed', 'qtype_calculated'); 378 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />"; 379 380 } else { 381 $this->numbererrors["number[{$j}]"] = 382 get_string('notvalidnumber', 'qtype_calculated', $a); 383 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />"; 384 } 385 } else if (stristr($number, 'x')) { // Hexa will pass the test. 386 $a = new stdClass(); 387 $a->name = '{'.$datasetdef->name.'}'; 388 $a->value = $datasetdef->items[$itemnumber]->value; 389 $this->numbererrors['number['.$j.']'] = 390 get_string('hexanotallowed', 'qtype_calculated', $a); 391 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />"; 392 } else if (is_nan($number)) { 393 $a = new stdClass(); 394 $a->name = '{'.$datasetdef->name.'}'; 395 $a->value = $datasetdef->items[$itemnumber]->value; 396 $this->numbererrors["number[{$j}]"] = 397 get_string('notvalidnumber', 'qtype_calculated', $a); 398 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />"; 399 } 400 } 401 $j--; 402 } 403 if ($this->noofitems != 0) { 404 if (empty($numbererrors)) { 405 if (!isset($this->question->id)) { 406 $this->question->id = 0; 407 } 408 $this->question->questiontext = !empty($this->question->questiontext) ? 409 $this->question->questiontext : ''; 410 $comment = $this->qtypeobj->comment_on_datasetitems( 411 $this->qtypeobj, $this->question->id, 412 $this->question->questiontext, $this->nonemptyanswer, 413 $data, $itemnumber); 414 if ($comment->outsidelimit) { 415 $this->outsidelimit = $comment->outsidelimit; 416 } 417 $totalcomment = ''; 418 419 foreach ($this->nonemptyanswer as $key => $answer) { 420 $totalcomment .= $comment->stranswers[$key].'<br/>'; 421 } 422 423 $this->formdata['answercomment['.$itemnumber.']'] = $totalcomment; 424 } 425 } 426 } 427 $this->formdata['selectdelete'] = '1'; 428 $this->formdata['selectadd'] = '1'; 429 $j = $this->noofitems * count($this->datasetdefs)+1; 430 $data = array(); // Data for comment_on_datasetitems later. 431 $idx = 1; 432 foreach ($this->datasetdefs as $defid => $datasetdef) { 433 $this->formdata["datasetdef[{$idx}]"] = $defid; 434 $idx++; 435 } 436 $this->formdata = $this->qtypeobj->custom_generator_set_data( 437 $this->datasetdefs, $this->formdata); 438 } 439 440 $addoptions = Array(); 441 $addoptions['1'] = '1'; 442 for ($i = 10; $i <= 100; $i += 10) { 443 $addoptions["{$i}"] = "{$i}"; 444 } 445 $showoptions = Array(); 446 $showoptions['1'] = '1'; 447 $showoptions['2'] = '2'; 448 $showoptions['5'] = '5'; 449 for ($i = 10; $i <= 100; $i += 10) { 450 $showoptions["{$i}"] = "{$i}"; 451 } 452 $mform->closeHeaderBefore('additemhdr'); 453 $addgrp = array(); 454 $addgrp[] = $mform->createElement('submit', 'addbutton', 455 get_string('generatenewitemsset', 'qtype_calculatedsimple')); 456 $addgrp[] = $mform->createElement('select', "selectadd", '', $addoptions); 457 $addgrp[] = $mform->createElement('static', "stat", '', 458 get_string('newsetwildcardvalues', 'qtype_calculatedsimple')); 459 $mform->addGroup($addgrp, 'addgrp', '', ' ', false); 460 $mform->registerNoSubmitButton('addbutton'); 461 $mform->closeHeaderBefore('addgrp'); 462 $addgrp1 = array(); 463 $addgrp1[] = $mform->createElement('submit', 'showbutton', 464 get_string('showitems', 'qtype_calculatedsimple')); 465 $addgrp1[] = $mform->createElement('select', "selectshow", '', $showoptions); 466 $addgrp1[] = $mform->createElement('static', "stat", '', 467 get_string('setwildcardvalues', 'qtype_calculatedsimple')); 468 $mform->addGroup($addgrp1, 'addgrp1', '', ' ', false); 469 $mform->registerNoSubmitButton('showbutton'); 470 $mform->closeHeaderBefore('addgrp1'); 471 $mform->addElement('static', "divideradd", '', ''); 472 if ($this->noofitems == 0) { 473 $mform->addElement('static', 'warningnoitems', '', '<span class="error">' . 474 get_string('youmustaddatleastonevalue', 'qtype_calculatedsimple') . 475 '</span>'); 476 $mform->closeHeaderBefore('warningnoitems'); 477 } else { 478 $mform->addElement('header', 'additemhdr1', 479 get_string('wildcardvalues', 'qtype_calculatedsimple')); 480 $mform->closeHeaderBefore('additemhdr1'); 481 if (!empty($this->numbererrors) || $this->outsidelimit) { 482 $mform->addElement('static', "alert", '', '<span class="error">' . 483 get_string('useadvance', 'qtype_calculatedsimple').'</span>'); 484 } 485 486 $mform->addElement('submit', 'updatedatasets', 487 get_string('updatewildcardvalues', 'qtype_calculatedsimple')); 488 $mform->registerNoSubmitButton('updatedatasets'); 489 $mform->setAdvanced("updatedatasets", true); 490 491 // ...--------------------------------------------------------------. 492 $j = $this->noofitems * count($this->datasetdefs); 493 $k = optional_param('selectshow', 1, PARAM_INT); 494 495 for ($i = $this->noofitems; $i >= 1; $i--) { 496 foreach ($this->datasetdefs as $defkey => $datasetdef) { 497 if ($k > 0 || $this->outsidelimit || !empty($this->numbererrors)) { 498 $mform->addElement('float', "number[{$j}]", get_string( 499 'wildcard', 'qtype_calculatedsimple', $datasetdef->name)); 500 $mform->setAdvanced("number[{$j}]", true); 501 if (!empty($this->numbererrors['number['.$j.']'])) { 502 $mform->addElement('static', "numbercomment[{$j}]", '', 503 '<span class="error">' . 504 $this->numbererrors['number['.$j.']'] . '</span>'); 505 $mform->setAdvanced("numbercomment[{$j}]", true); 506 } 507 } else { 508 $mform->addElement('hidden', "number[{$j}]", ''); 509 $mform->setType("number[{$j}]", PARAM_LOCALISEDFLOAT); // Localisation handling has to be done manually. 510 if (isset($this->formdata["number[{$j}]"])) { 511 $this->formdata["number[{$j}]"] = format_float($this->formdata["number[{$j}]"], -1); 512 } 513 } 514 515 $mform->addElement('hidden', "itemid[{$j}]"); 516 $mform->setType("itemid[{$j}]", PARAM_INT); 517 518 $mform->addElement('hidden', "definition[{$j}]"); 519 $mform->setType("definition[{$j}]", PARAM_NOTAGS); 520 521 $j--; 522 } 523 if (!empty($strquestionlabel) && ($k > 0 || $this->outsidelimit || 524 !empty($this->numbererrors))) { 525 $mform->addElement('static', "answercomment[{$i}]", "<b>" . 526 get_string('setno', 'qtype_calculatedsimple', $i) . 527 "</b> " . $strquestionlabel); 528 529 } 530 if ($k > 0 || $this->outsidelimit || !empty($this->numbererrors)) { 531 $mform->addElement('static', "divider1[{$j}]", '', '<hr />'); 532 533 } 534 $k--; 535 } 536 } 537 } else { 538 $mform->addElement('static', 'warningnowildcards', '', '<span class="error">' . 539 get_string('atleastonewildcard', 'qtype_calculatedsimple') . '</span>'); 540 $mform->closeHeaderBefore('warningnowildcards'); 541 } 542 543 // ...----------------------------------------------------------------------. 544 // Non standard name for button element needed so not using add_action_buttons. 545 // Hidden elements. 546 547 $mform->addElement('hidden', 'id'); 548 $mform->setType('id', PARAM_INT); 549 550 $mform->addElement('hidden', 'courseid'); 551 $mform->setType('courseid', PARAM_INT); 552 $mform->setDefault('courseid', 0); 553 554 $mform->addElement('hidden', 'cmid'); 555 $mform->setType('cmid', PARAM_INT); 556 $mform->setDefault('cmid', 0); 557 if (!empty($this->question->id)) { 558 if ($this->question->formoptions->cansaveasnew) { 559 $mform->addElement('header', 'additemhdr', 560 get_string('converttocalculated', 'qtype_calculatedsimple')); 561 $mform->closeHeaderBefore('additemhdr'); 562 563 $mform->addElement('checkbox', 'convert', '', 564 get_string('willconverttocalculated', 'qtype_calculatedsimple')); 565 $mform->setDefault('convert', 0); 566 567 } 568 } 569 } 570 571 protected function can_preview() { 572 return empty($this->question->beingcopied) && !empty($this->question->id) && 573 $this->question->formoptions->canedit && $this->noofitems > 0; 574 } 575 576 public function data_preprocessing($question) { 577 $question = parent::data_preprocessing($question); 578 $question = $this->data_preprocessing_answers($question); 579 $question = $this->data_preprocessing_hints($question); 580 $question = $this->data_preprocessing_units($question); 581 $question = $this->data_preprocessing_unit_options($question); 582 583 // This is a bit ugly, but it loads all the dataset values. 584 $question = (object)((array)$question + $this->formdata); 585 586 return $question; 587 } 588 589 public function qtype() { 590 return 'calculatedsimple'; 591 } 592 593 public function validation($data, $files) { 594 $errors = parent::validation($data, $files); 595 596 if (array_key_exists('number', $data)) { 597 $numbers = $data['number']; 598 } else { 599 $numbers = array(); 600 } 601 foreach ($numbers as $key => $number) { 602 if (! is_numeric($number)) { 603 if (stristr($number, ',')) { 604 $errors['number['.$key.']'] = get_string('nocommaallowed', 'qtype_calculated'); 605 } else { 606 $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated'); 607 } 608 } else if (stristr($number, 'x')) { 609 $a = new stdClass(); 610 $a->name = ''; 611 $a->value = $number; 612 $errors['number['.$key.']'] = get_string('hexanotallowed', 'qtype_calculated', $a); 613 } else if (is_nan($number)) { 614 $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated'); 615 } 616 } 617 618 if (empty($data['definition'])) { 619 $errors['selectadd'] = get_string('youmustaddatleastonevalue', 'qtype_calculatedsimple'); 620 } 621 622 return $errors; 623 } 624 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body