Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [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 if ($this->maxnumber != -1) { 321 $this->noofitems = $this->maxnumber; 322 } else { 323 $this->noofitems = 0; 324 } 325 if (!empty($this->datasetdefs)) {// So there are some datadefs. 326 // We put them on the page. 327 $key = 0; 328 $mform->addElement('header', 'additemhdr', 329 get_string('wildcardparam', 'qtype_calculatedsimple')); 330 $idx = 1; 331 if (!empty($this->datasetdefs)) {// Unnecessary test. 332 $j = (($this->noofitems) * count($this->datasetdefs))+1;// 333 foreach ($this->datasetdefs as $defkey => $datasetdef) { 334 $mform->addElement('static', "na[{$j}]", 335 get_string('param', 'qtype_calculated', $datasetdef->name)); 336 $this->qtypeobj->custom_generator_tools_part($mform, $idx, $j); 337 $mform->addElement('hidden', "datasetdef[{$idx}]"); 338 $mform->setType("datasetdef[{$idx}]", PARAM_RAW); 339 $mform->addElement('hidden', "defoptions[{$idx}]"); 340 $mform->setType("defoptions[{$idx}]", PARAM_RAW); 341 $idx++; 342 $mform->addElement('static', "divider[{$j}]", '', '<hr />'); 343 $j++; 344 } 345 } 346 // This should be done before the elements are created and stored as $this->formdata. 347 // Fill out all data sets and also the fields for the next item to add. 348 /*Here we do already the values error analysis so that 349 * we could force all wild cards values display if there is an error in values. 350 * as using a , in a number */ 351 $this->numbererrors = array(); 352 if (!empty($this->datasetdefs)) { 353 $j = $this->noofitems * count($this->datasetdefs); 354 for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--) { 355 $data = array(); 356 $numbererrors = ''; 357 $comment = new stdClass(); 358 $comment->stranswers = array(); 359 $comment->outsidelimit = false; 360 $comment->answers = array(); 361 362 foreach ($this->datasetdefs as $defid => $datasetdef) { 363 if (isset($datasetdef->items[$itemnumber])) { 364 $this->formdata["definition[{$j}]"] = $defid; 365 $this->formdata["itemid[{$j}]"] = 366 $datasetdef->items[$itemnumber]->id; 367 $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value; 368 $this->formdata["number[{$j}]"] = $number = 369 $datasetdef->items[$itemnumber]->value; 370 if (! is_numeric($number)) { 371 $a = new stdClass(); 372 $a->name = '{'.$datasetdef->name.'}'; 373 $a->value = $datasetdef->items[$itemnumber]->value; 374 if (stristr($number, ',')) { 375 $this->numbererrors["number[{$j}]"] = 376 get_string('nocommaallowed', 'qtype_calculated'); 377 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />"; 378 379 } else { 380 $this->numbererrors["number[{$j}]"] = 381 get_string('notvalidnumber', 'qtype_calculated', $a); 382 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />"; 383 } 384 } else if (stristr($number, 'x')) { // Hexa will pass the test. 385 $a = new stdClass(); 386 $a->name = '{'.$datasetdef->name.'}'; 387 $a->value = $datasetdef->items[$itemnumber]->value; 388 $this->numbererrors['number['.$j.']'] = 389 get_string('hexanotallowed', 'qtype_calculated', $a); 390 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />"; 391 } else if (is_nan($number)) { 392 $a = new stdClass(); 393 $a->name = '{'.$datasetdef->name.'}'; 394 $a->value = $datasetdef->items[$itemnumber]->value; 395 $this->numbererrors["number[{$j}]"] = 396 get_string('notvalidnumber', 'qtype_calculated', $a); 397 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />"; 398 } 399 } 400 $j--; 401 } 402 if ($this->noofitems != 0) { 403 if (empty($numbererrors)) { 404 if (!isset($this->question->id)) { 405 $this->question->id = 0; 406 } 407 $this->question->questiontext = !empty($this->question->questiontext) ? 408 $this->question->questiontext : ''; 409 $comment = $this->qtypeobj->comment_on_datasetitems( 410 $this->qtypeobj, $this->question->id, 411 $this->question->questiontext, $this->nonemptyanswer, 412 $data, $itemnumber); 413 if ($comment->outsidelimit) { 414 $this->outsidelimit = $comment->outsidelimit; 415 } 416 $totalcomment = ''; 417 418 foreach ($this->nonemptyanswer as $key => $answer) { 419 $totalcomment .= $comment->stranswers[$key].'<br/>'; 420 } 421 422 $this->formdata['answercomment['.$itemnumber.']'] = $totalcomment; 423 } 424 } 425 } 426 $this->formdata['selectdelete'] = '1'; 427 $this->formdata['selectadd'] = '1'; 428 $j = $this->noofitems * count($this->datasetdefs)+1; 429 $data = array(); // Data for comment_on_datasetitems later. 430 $idx = 1; 431 foreach ($this->datasetdefs as $defid => $datasetdef) { 432 $this->formdata["datasetdef[{$idx}]"] = $defid; 433 $idx++; 434 } 435 $this->formdata = $this->qtypeobj->custom_generator_set_data( 436 $this->datasetdefs, $this->formdata); 437 } 438 439 $addoptions = Array(); 440 $addoptions['1'] = '1'; 441 for ($i = 10; $i <= 100; $i += 10) { 442 $addoptions["{$i}"] = "{$i}"; 443 } 444 $showoptions = Array(); 445 $showoptions['1'] = '1'; 446 $showoptions['2'] = '2'; 447 $showoptions['5'] = '5'; 448 for ($i = 10; $i <= 100; $i += 10) { 449 $showoptions["{$i}"] = "{$i}"; 450 } 451 $mform->closeHeaderBefore('additemhdr'); 452 $addgrp = array(); 453 $addgrp[] = $mform->createElement('submit', 'addbutton', 454 get_string('generatenewitemsset', 'qtype_calculatedsimple')); 455 $addgrp[] = $mform->createElement('select', "selectadd", '', $addoptions); 456 $addgrp[] = $mform->createElement('static', "stat", '', 457 get_string('newsetwildcardvalues', 'qtype_calculatedsimple')); 458 $mform->addGroup($addgrp, 'addgrp', '', ' ', false); 459 $mform->registerNoSubmitButton('addbutton'); 460 $mform->closeHeaderBefore('addgrp'); 461 $addgrp1 = array(); 462 $addgrp1[] = $mform->createElement('submit', 'showbutton', 463 get_string('showitems', 'qtype_calculatedsimple')); 464 $addgrp1[] = $mform->createElement('select', "selectshow", '', $showoptions); 465 $addgrp1[] = $mform->createElement('static', "stat", '', 466 get_string('setwildcardvalues', 'qtype_calculatedsimple')); 467 $mform->addGroup($addgrp1, 'addgrp1', '', ' ', false); 468 $mform->registerNoSubmitButton('showbutton'); 469 $mform->closeHeaderBefore('addgrp1'); 470 $mform->addElement('static', "divideradd", '', ''); 471 if ($this->noofitems == 0) { 472 $mform->addElement('static', 'warningnoitems', '', '<span class="error">' . 473 get_string('youmustaddatleastonevalue', 'qtype_calculatedsimple') . 474 '</span>'); 475 $mform->closeHeaderBefore('warningnoitems'); 476 } else { 477 $mform->addElement('header', 'additemhdr1', 478 get_string('wildcardvalues', 'qtype_calculatedsimple')); 479 $mform->closeHeaderBefore('additemhdr1'); 480 if (!empty($this->numbererrors) || $this->outsidelimit) { 481 $mform->addElement('static', "alert", '', '<span class="error">' . 482 get_string('useadvance', 'qtype_calculatedsimple').'</span>'); 483 } 484 485 $mform->addElement('submit', 'updatedatasets', 486 get_string('updatewildcardvalues', 'qtype_calculatedsimple')); 487 $mform->registerNoSubmitButton('updatedatasets'); 488 $mform->setAdvanced("updatedatasets", true); 489 490 // ...--------------------------------------------------------------. 491 $j = $this->noofitems * count($this->datasetdefs); 492 $k = optional_param('selectshow', 1, PARAM_INT); 493 494 for ($i = $this->noofitems; $i >= 1; $i--) { 495 foreach ($this->datasetdefs as $defkey => $datasetdef) { 496 if ($k > 0 || $this->outsidelimit || !empty($this->numbererrors)) { 497 $mform->addElement('float', "number[{$j}]", get_string( 498 'wildcard', 'qtype_calculatedsimple', $datasetdef->name)); 499 $mform->setAdvanced("number[{$j}]", true); 500 if (!empty($this->numbererrors['number['.$j.']'])) { 501 $mform->addElement('static', "numbercomment[{$j}]", '', 502 '<span class="error">' . 503 $this->numbererrors['number['.$j.']'] . '</span>'); 504 $mform->setAdvanced("numbercomment[{$j}]", true); 505 } 506 } else { 507 $mform->addElement('hidden', "number[{$j}]", ''); 508 $mform->setType("number[{$j}]", PARAM_LOCALISEDFLOAT); // Localisation handling has to be done manually. 509 if (isset($this->formdata["number[{$j}]"])) { 510 $this->formdata["number[{$j}]"] = format_float($this->formdata["number[{$j}]"], -1); 511 } 512 } 513 514 $mform->addElement('hidden', "itemid[{$j}]"); 515 $mform->setType("itemid[{$j}]", PARAM_INT); 516 517 $mform->addElement('hidden', "definition[{$j}]"); 518 $mform->setType("definition[{$j}]", PARAM_NOTAGS); 519 520 $j--; 521 } 522 if (!empty($strquestionlabel) && ($k > 0 || $this->outsidelimit || 523 !empty($this->numbererrors))) { 524 $mform->addElement('static', "answercomment[{$i}]", "<b>" . 525 get_string('setno', 'qtype_calculatedsimple', $i) . 526 "</b> " . $strquestionlabel); 527 528 } 529 if ($k > 0 || $this->outsidelimit || !empty($this->numbererrors)) { 530 $mform->addElement('static', "divider1[{$j}]", '', '<hr />'); 531 532 } 533 $k--; 534 } 535 } 536 } else { 537 $mform->addElement('static', 'warningnowildcards', '', '<span class="error">' . 538 get_string('atleastonewildcard', 'qtype_calculatedsimple') . '</span>'); 539 $mform->closeHeaderBefore('warningnowildcards'); 540 } 541 542 // ...----------------------------------------------------------------------. 543 // Non standard name for button element needed so not using add_action_buttons. 544 // Hidden elements. 545 546 $mform->addElement('hidden', 'id'); 547 $mform->setType('id', PARAM_INT); 548 549 $mform->addElement('hidden', 'courseid'); 550 $mform->setType('courseid', PARAM_INT); 551 $mform->setDefault('courseid', 0); 552 553 $mform->addElement('hidden', 'cmid'); 554 $mform->setType('cmid', PARAM_INT); 555 $mform->setDefault('cmid', 0); 556 if (!empty($this->question->id)) { 557 if ($this->question->formoptions->cansaveasnew) { 558 $mform->addElement('header', 'additemhdr', 559 get_string('converttocalculated', 'qtype_calculatedsimple')); 560 $mform->closeHeaderBefore('additemhdr'); 561 562 $mform->addElement('checkbox', 'convert', '', 563 get_string('willconverttocalculated', 'qtype_calculatedsimple')); 564 $mform->setDefault('convert', 0); 565 566 } 567 } 568 } 569 570 protected function can_preview() { 571 return empty($this->question->beingcopied) && !empty($this->question->id) && 572 $this->question->formoptions->canedit && $this->noofitems > 0; 573 } 574 575 public function data_preprocessing($question) { 576 $question = parent::data_preprocessing($question); 577 $question = $this->data_preprocessing_answers($question); 578 $question = $this->data_preprocessing_hints($question); 579 $question = $this->data_preprocessing_units($question); 580 $question = $this->data_preprocessing_unit_options($question); 581 582 // This is a bit ugly, but it loads all the dataset values. 583 $question = (object)((array)$question + $this->formdata); 584 585 return $question; 586 } 587 588 public function qtype() { 589 return 'calculatedsimple'; 590 } 591 592 public function validation($data, $files) { 593 $errors = parent::validation($data, $files); 594 595 if (array_key_exists('number', $data)) { 596 $numbers = $data['number']; 597 } else { 598 $numbers = array(); 599 } 600 foreach ($numbers as $key => $number) { 601 if (! is_numeric($number)) { 602 if (stristr($number, ',')) { 603 $errors['number['.$key.']'] = get_string('nocommaallowed', 'qtype_calculated'); 604 } else { 605 $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated'); 606 } 607 } else if (stristr($number, 'x')) { 608 $a = new stdClass(); 609 $a->name = ''; 610 $a->value = $number; 611 $errors['number['.$key.']'] = get_string('hexanotallowed', 'qtype_calculated', $a); 612 } else if (is_nan($number)) { 613 $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated'); 614 } 615 } 616 617 if (empty($data['definition'])) { 618 $errors['selectadd'] = get_string('youmustaddatleastonevalue', 'qtype_calculatedsimple'); 619 } 620 621 return $errors; 622 } 623 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body