PageRenderTime 49ms CodeModel.GetById 17ms app.highlight 25ms RepoModel.GetById 2ms app.codeStats 0ms

/question/type/calculatedsimple/edit_calculatedsimple_form.php

https://bitbucket.org/synergylearning/campusconnect
PHP | 617 lines | 471 code | 61 blank | 85 comment | 86 complexity | 383e16abbb1873b59dbfba8827a51c58 MD5 | raw file
  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
 27defined('MOODLE_INTERNAL') || die();
 28
 29require_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 */
 38class 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_FLOAT);
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_FLOAT);
173                    $calclength = optional_param_array('calclength', '', PARAM_INT);
174                    $calcmax = optional_param_array('calcmax', '', PARAM_FLOAT);
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_RAW);// This parameter will be validated in the form.
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'>&nbsp;</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 = array();
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('text', "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]", get_string(
509                                    'wildcard', 'qtype_calculatedsimple', $datasetdef->name));
510                        }
511                        $mform->setType("number[$j]", PARAM_RAW); // This parameter will be validated in validation().
512
513                        $mform->addElement('hidden', "itemid[$j]");
514                        $mform->setType("itemid[$j]", PARAM_INT);
515
516                        $mform->addElement('hidden', "definition[$j]");
517                        $mform->setType("definition[$j]", PARAM_NOTAGS);
518
519                        $j--;
520                    }
521                    if (!empty($strquestionlabel) && ($k > 0 ||  $this->outsidelimit ||
522                            !empty($this->numbererrors))) {
523                        $mform->addElement('static', "answercomment[$i]", "<b>" .
524                                get_string('setno', 'qtype_calculatedsimple', $i) .
525                                "</b>&nbsp;&nbsp;" . $strquestionlabel);
526
527                    }
528                    if ($k > 0 ||  $this->outsidelimit || !empty($this->numbererrors)) {
529                        $mform->addElement('static', "divider1[$j]", '', '<hr />');
530
531                    }
532                    $k--;
533                }
534            }
535        } else {
536            $mform->addElement('static', 'warningnowildcards', '', '<span class="error">' .
537                    get_string('atleastonewildcard', 'qtype_calculatedsimple') . '</span>');
538            $mform->closeHeaderBefore('warningnowildcards');
539        }
540
541        // ...----------------------------------------------------------------------.
542        // Non standard name for button element needed so not using add_action_buttons.
543        // Hidden elements.
544
545        $mform->addElement('hidden', 'id');
546        $mform->setType('id', PARAM_INT);
547
548        $mform->addElement('hidden', 'courseid');
549        $mform->setType('courseid', PARAM_INT);
550        $mform->setDefault('courseid', 0);
551
552        $mform->addElement('hidden', 'cmid');
553        $mform->setType('cmid', PARAM_INT);
554        $mform->setDefault('cmid', 0);
555        if (!empty($this->question->id)) {
556            if ($this->question->formoptions->cansaveasnew) {
557                $mform->addElement('header', 'additemhdr',
558                        get_string('converttocalculated', 'qtype_calculatedsimple'));
559                $mform->closeHeaderBefore('additemhdr');
560
561                $mform->addElement('checkbox', 'convert', '',
562                        get_string('willconverttocalculated', 'qtype_calculatedsimple'));
563                $mform->setDefault('convert', 0);
564
565            }
566        }
567    }
568
569    public function data_preprocessing($question) {
570        $question = parent::data_preprocessing($question);
571        $question = $this->data_preprocessing_answers($question);
572        $question = $this->data_preprocessing_hints($question);
573        $question = $this->data_preprocessing_units($question);
574        $question = $this->data_preprocessing_unit_options($question);
575
576        // This is a bit ugly, but it loads all the dataset values.
577        $question = (object)((array)$question + $this->formdata);
578
579        return $question;
580    }
581
582    public function qtype() {
583        return 'calculatedsimple';
584    }
585
586    public function validation($data, $files) {
587        $errors = parent::validation($data, $files);
588
589        if (array_key_exists('number', $data)) {
590            $numbers = $data['number'];
591        } else {
592            $numbers = array();
593        }
594        foreach ($numbers as $key => $number) {
595            if (! is_numeric($number)) {
596                if (stristr($number, ',')) {
597                    $errors['number['.$key.']'] = get_string('nocommaallowed', 'qtype_calculated');
598                } else {
599                    $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated');
600                }
601            } else if (stristr($number, 'x')) {
602                $a = new stdClass();
603                $a->name = '';
604                $a->value = $number;
605                $errors['number['.$key.']'] = get_string('hexanotallowed', 'qtype_calculated', $a);
606            } else if (is_nan($number)) {
607                $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated');
608            }
609        }
610
611        if (empty($data['definition'])) {
612            $errors['selectadd'] = get_string('youmustaddatleastonevalue', 'qtype_calculatedsimple');
613        }
614
615        return $errors;
616    }
617}