MDL-10110 Creating the calculatedmulti question type
[moodle.git] / question / type / calculated / datasetitems_form.php
CommitLineData
8fc3e643 1<?php
2class question_dataset_dependent_items_form extends moodleform {
3 /**
4 * Question object with options and answers already loaded by get_question_options
5 * Be careful how you use this it is needed sometimes to set up the structure of the
6 * form in definition_inner but data is always loaded into the form with set_defaults.
7 *
8 * @var object
9 */
f34488b2 10 public $question;
8fc3e643 11 /**
12 * Reference to question type object
13 *
14 * @var question_dataset_dependent_questiontype
15 */
f34488b2 16 public $qtypeobj;
60b5ecd3 17
f34488b2 18 public $datasetdefs;
60b5ecd3 19
f34488b2 20 public $maxnumber = -1;
60b5ecd3 21
f34488b2 22 public $regenerate;
60b5ecd3 23
f34488b2 24 public $noofitems;
aeb15530 25
450f1127 26 public $outsidelimit = false ;
aeb15530 27
450f1127 28 public $commentanswers = array();
8fc3e643 29 /**
30 * Add question-type specific form fields.
31 *
32 * @param MoodleQuickForm $mform the form being built.
33 */
60b5ecd3 34 function question_dataset_dependent_items_form($submiturl, $question, $regenerate){
f34488b2 35 global $QTYPES, $SESSION, $CFG, $DB;
60b5ecd3 36 $this->regenerate = $regenerate;
8fc3e643 37 $this->question = $question;
38 $this->qtypeobj =& $QTYPES[$this->question->qtype];
4454447d
PS
39 // Validate the question category.
40 if (!$category = $DB->get_record('question_categories', array('id' => $question->category))) {
41 print_error('categorydoesnotexist', 'question', $returnurl);
42 }
315efce7 43 $this->category = $category;
44 $this->categorycontext = get_context_instance_by_id($category->contextid);
60b5ecd3 45 //get the dataset defintions for this question
46 if (empty($question->id)) {
fbe2cfea 47 $this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, $SESSION->calculated->definitionform->dataset);
60b5ecd3 48 } else {
49 if (empty($question->options)) {
50 $this->get_question_options($question);
51 }
52 $this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, array());
53 }
54
55 foreach ($this->datasetdefs as $datasetdef) {
56
57 // Get maxnumber
58 if ($this->maxnumber == -1 || $datasetdef->itemcount < $this->maxnumber) {
59 $this->maxnumber = $datasetdef->itemcount;
60 }
61 }
62 foreach ($this->datasetdefs as $defid => $datasetdef) {
63 if (isset($datasetdef->id)) {
66d0a55c 64 $this->datasetdefs[$defid]->items = $this->qtypeobj->get_database_dataset_items($datasetdef->id);
60b5ecd3 65 }
66 }
8fc3e643 67 parent::moodleform($submiturl);
68 }
69 function definition() {
70 $mform =& $this->_form;
60b5ecd3 71 $strquestionlabel = $this->qtypeobj->comment_header($this->question);
60b5ecd3 72 if ($this->maxnumber != -1){
73 $this->noofitems = $this->maxnumber;
74 } else {
75 $this->noofitems = 0;
8fc3e643 76 }
60b5ecd3 77//------------------------------------------------------------------------------------------------------------------------------
38a2212c 78 $mform->addElement('submit', 'updatedatasets', get_string('updatedatasetparam', 'qtype_datasetdependent'));
5d0b1e40 79 $mform->registerNoSubmitButton('updatedatasets');
60b5ecd3 80 $mform->addElement('header', 'additemhdr', get_string('itemtoadd', 'qtype_datasetdependent'));
81 $idx = 1;
a8d2a373 82 $j = (($this->noofitems) * count($this->datasetdefs))+1;
60b5ecd3 83 foreach ($this->datasetdefs as $defkey => $datasetdef){
84 $mform->addElement('text', "number[$j]", get_string('param', 'qtype_datasetdependent', $datasetdef->name));
87cd4f54 85 $mform->setType("number[$j]", PARAM_NUMBER);
f34488b2 86 $this->qtypeobj->custom_generator_tools_part($mform, $idx, $j);
60b5ecd3 87 $idx++;
a8d2a373 88 $mform->addElement('hidden', "definition[$j]");
d18e0fe6 89 $mform->setType("definition[$j]", PARAM_RAW);
a8d2a373 90 $mform->addElement('hidden', "itemid[$j]");
d18e0fe6 91 $mform->setType("itemid[$j]", PARAM_RAW);
60b5ecd3 92 $mform->addElement('static', "divider[$j]", '', '<hr />');
d18e0fe6 93 $mform->setType("divider[$j]", PARAM_RAW);
a8d2a373 94 $j++;
60b5ecd3 95 }
450f1127 96 $mform->addElement('header', 'updateanswershdr', get_string('answerstoleranceparam', 'qtype_datasetdependent'));
97 $mform->addElement('submit', 'updateanswers', get_string('updatetolerancesparam', 'qtype_datasetdependent'));
98 $mform->setAdvanced('updateanswers',true);
5d0b1e40 99 $mform->registerNoSubmitButton('updateanswers');
aeb15530 100
450f1127 101 $answers = fullclone($this->question->options->answers);
102 $key1 =1;
103 foreach ($answers as $key => $answer) {
104 if ('' === $answer->answer){
105 }else if ('*' === $answer->answer){
106 $mform->addElement('static', 'answercomment['.($this->noofitems+$key1).']', $answer->answer);
107 $mform->addElement('hidden', 'tolerance['.$key.']', '');
d18e0fe6 108 $mform->setType('tolerance['.$key.']', PARAM_RAW);
450f1127 109 $mform->setAdvanced('tolerance['.$key.']',true);
110 $mform->addElement('hidden', 'tolerancetype['.$key.']', '');
d18e0fe6 111 $mform->setType('tolerancetype['.$key.']', PARAM_RAW);
450f1127 112 $mform->setAdvanced('tolerancetype['.$key.']',true);
113 $mform->addElement('hidden', 'correctanswerlength['.$key.']', '');
d18e0fe6 114 $mform->setType('correctanswerlength['.$key.']', PARAM_RAW);
450f1127 115 $mform->setAdvanced('correctanswerlength['.$key.']',true);
116 $mform->addElement('hidden', 'correctanswerformat['.$key.']', '');
d18e0fe6 117 $mform->setType('correctanswerformat['.$key.']', PARAM_RAW);
450f1127 118 $mform->setAdvanced('correctanswerformat['.$key.']',true);
119 }else {
120 $mform->addElement('static', 'answercomment['.($this->noofitems+$key1).']', $answer->answer);
121 $mform->addElement('text', 'tolerance['.$key.']', get_string('tolerance', 'qtype_calculated'));
122 $mform->setAdvanced('tolerance['.$key.']',true);
123 $mform->addElement('select', 'tolerancetype['.$key.']', get_string('tolerancetype', 'quiz'), $this->qtypeobj->tolerance_types());
124 $mform->setAdvanced('tolerancetype['.$key.']',true);
aeb15530 125
450f1127 126 $mform->addElement('select', 'correctanswerlength['.$key.']', get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
127 $mform->setAdvanced('correctanswerlength['.$key.']',true);
aeb15530 128
450f1127 129 $answerlengthformats = array('1' => get_string('decimalformat', 'quiz'), '2' => get_string('significantfiguresformat', 'quiz'));
130 $mform->addElement('select', 'correctanswerformat['.$key.']', get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
131 $mform->setAdvanced('correctanswerformat['.$key.']',true);
132 $mform->addElement('static', 'dividertolerance', '', '<hr />');
133 $mform->setAdvanced('dividertolerance',true);
134 }
135 $key1++;
aeb15530 136 }
60b5ecd3 137
28a27ef1 138 $addremoveoptions = array();
451373ed 139 $addremoveoptions['1']='1';
79bb7202 140 for ($i=10; $i<=100 ; $i+=10){
451373ed 141 $addremoveoptions["$i"]="$i";
142 }
87cd4f54 143 $mform->addElement('header', 'additemhdr', get_string('add', 'moodle'));
451373ed 144 $mform->closeHeaderBefore('additemhdr');
60b5ecd3 145
8fc3e643 146 if ($this->qtypeobj->supports_dataset_item_generation()){
147 $radiogrp = array();
60b5ecd3 148 $radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]', null, get_string('reuseifpossible', 'qtype_datasetdependent'), 0);
149 $radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]', null, get_string('forceregeneration', 'qtype_datasetdependent'), 1);
451373ed 150 $mform->addGroup($radiogrp, 'forceregenerationgrp', get_string('nextitemtoadd', 'qtype_calculated'), "<br/>", false);
8fc3e643 151 }
152
60b5ecd3 153 $mform->addElement('submit', 'getnextbutton', get_string('getnextnow', 'qtype_datasetdependent'));
451373ed 154 $mform->addElement('static', "dividera", '', '<hr />');
155 $addgrp = array();
156 $addgrp[] =& $mform->createElement('submit', 'addbutton', get_string('add', 'moodle'));
157 $addgrp[] =& $mform->createElement('select', "selectadd", get_string('additem', 'qtype_datasetdependent'), $addremoveoptions);
158 $addgrp[] = & $mform->createElement('static',"stat","Items",get_string('item(s)', 'qtype_datasetdependent'));
159 $mform->addGroup($addgrp, 'addgrp', '', ' ', false);
450f1127 160 $mform->addElement('static', "divideradd", '', '');
451373ed 161 // $mform->closeHeaderBefore('divideradd');
162 if ($this->noofitems > 0) {
163 $mform->addElement('header', 'additemhdr', get_string('delete', 'moodle'));
164 $deletegrp = array();
165 $deletegrp[] =& $mform->createElement('submit', 'deletebutton', get_string('delete', 'moodle'));
166 $deletegrp[] =& $mform->createElement('select', "selectdelete", get_string('deleteitem', 'qtype_datasetdependent')."1", $addremoveoptions);
167 $deletegrp[] = & $mform->createElement('static',"stat","Items",get_string('lastitem(s)', 'qtype_datasetdependent'));
168 $mform->addGroup($deletegrp, 'deletegrp', '', ' ', false);
169 // $mform->addElement('static', "dividerdelete", '', '<hr />');
170 // $mform->closeHeaderBefore('dividerdelete');
171 } else {
172 $mform->addElement('static','warning','','<span class="error">'.get_string('youmustaddatleastoneitem', 'qtype_datasetdependent').'</span>');
173 }
8fc3e643 174
a8d2a373 175//------------------------------------------------------------------------------------------------------------------------------
176 $j = $this->noofitems * count($this->datasetdefs);
177 for ($i = $this->noofitems; $i >= 1 ; $i--){
178 $mform->addElement('header', '', get_string('itemno', 'qtype_datasetdependent', $i));
179 foreach ($this->datasetdefs as $defkey => $datasetdef){
180 $mform->addElement('text', "number[$j]", get_string('param', 'qtype_datasetdependent', $datasetdef->name));
87cd4f54 181 $mform->setType("number[$j]", PARAM_NUMBER);
a8d2a373 182 $mform->addElement('hidden', "itemid[$j]");
87cd4f54 183 $mform->setType("itemid[$j]", PARAM_INT);
a8d2a373 184
185 $mform->addElement('hidden', "definition[$j]");
87cd4f54 186 $mform->setType("definition[$j]", PARAM_NOTAGS);
a8d2a373 187
188 $j--;
189 }
190 if ('' != $strquestionlabel){
191 $repeated[] =& $mform->addElement('static', "answercomment[$i]", $strquestionlabel);
192 }
a8d2a373 193 }
450f1127 194 // if ($this->outsidelimit){
195 $mform->addElement('static','outsidelimit','','');
196 // }
a8d2a373 197//------------------------------------------------------------------------------------------------------------------------------
60b5ecd3 198 //non standard name for button element needed so not using add_action_buttons
450f1127 199 if ( !($this->noofitems==0) ){
a8d2a373 200 $mform->addElement('submit', 'backtoquiz', get_string('savechanges'));
201 $mform->closeHeaderBefore('backtoquiz');
450f1127 202 }
60b5ecd3 203 //hidden elements
79bb7202 204 $mform->addElement('hidden', 'id');
205 $mform->setType('id', PARAM_INT);
206
271e6dec 207 $mform->addElement('hidden', 'courseid');
208 $mform->setType('courseid', PARAM_INT);
209 $mform->setDefault('courseid', 0);
79bb7202 210
315efce7 211 $mform->addElement('hidden', 'category');
212 $mform->setType('category', PARAM_RAW);
213 $mform->setDefault('category', array('contexts' => array($this->categorycontext)));
aeb15530 214
271e6dec 215 $mform->addElement('hidden', 'cmid');
216 $mform->setType('cmid', PARAM_INT);
217 $mform->setDefault('cmid', 0);
79bb7202 218
60b5ecd3 219 $mform->addElement('hidden', 'wizard', 'datasetitems');
220 $mform->setType('wizard', PARAM_ALPHA);
f34488b2 221
2dc8beaf 222 $mform->addElement('hidden', 'returnurl');
223 $mform->setType('returnurl', PARAM_LOCALURL);
224 $mform->setDefault('returnurl', 0);
60b5ecd3 225 }
8fc3e643 226
60b5ecd3 227 function set_data($question){
228 $formdata = array();
5d0b1e40 229 $fromform = new stdClass();
450f1127 230 if (isset($question->options)){
231 $answers = $question->options->answers;
232 if (count($answers)) {
5d0b1e40 233 if ( optional_param('updateanswers', '', PARAM_RAW) != '' || optional_param('updatedatasets', '', PARAM_RAW) != ''){
234 foreach ($answers as $key => $answer){
235 $fromform->tolerance[$key]= $this->_form->getElementValue('tolerance['.$key.']');
236 $answer->tolerance = $fromform->tolerance[$key];
237 $fromform->tolerancetype[$key]= $this->_form->getElementValue('tolerancetype['.$key.']');
238 if( is_array($fromform->tolerancetype[$key])) $fromform->tolerancetype[$key]= $fromform->tolerancetype[$key][0];
239 $answer->tolerancetype = $fromform->tolerancetype[$key];
240 $fromform->correctanswerlength[$key]= $this->_form->getElementValue('correctanswerlength['.$key.']');
241 if( is_array($fromform->correctanswerlength[$key])) $fromform->correctanswerlength[$key]= $fromform->correctanswerlength[$key][0];
242 $answer->correctanswerlength = $fromform->correctanswerlength[$key];
243 $fromform->correctanswerformat[$key]= $this->_form->getElementValue('correctanswerformat['.$key.']');
244 if( is_array($fromform->correctanswerformat[$key])) $fromform->correctanswerformat[$key]= $fromform->correctanswerformat[$key][0];
245 $answer->correctanswerformat = $fromform->correctanswerformat[$key];
246 }
aeb15530
PS
247 $this->qtypeobj->save_question_calculated($question,$fromform);
248 }else {
450f1127 249 foreach ($answers as $key => $answer){
aeb15530 250
450f1127 251 $formdata['tolerance['.$key.']'] = $answer->tolerance;
252 $formdata['tolerancetype['.$key.']'] = $answer->tolerancetype;
253 $formdata['correctanswerlength['.$key.']'] = $answer->correctanswerlength;
254 $formdata['correctanswerformat['.$key.']'] = $answer->correctanswerformat;
5d0b1e40 255 }
450f1127 256 }
5d0b1e40 257 }
258 }
60b5ecd3 259 //fill out all data sets and also the fields for the next item to add.
a8d2a373 260 $j = $this->noofitems * count($this->datasetdefs);
5d0b1e40 261 for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--){
60b5ecd3 262 $data = array();
263 foreach ($this->datasetdefs as $defid => $datasetdef){
264 if (isset($datasetdef->items[$itemnumber])){
265 $formdata["number[$j]"] = $datasetdef->items[$itemnumber]->value;
266 $formdata["definition[$j]"] = $defid;
267 $formdata["itemid[$j]"] = $datasetdef->items[$itemnumber]->id;
268 $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value;
269 }
a8d2a373 270 $j--;
60b5ecd3 271 }
28a27ef1 272 if($question->options->multichoice == 1 ){
273 $comment = $this->qtypeobj->multichoice_comment_on_datasetitems($question->id,$answers, $data, $itemnumber);
274 }else {
5d0b1e40 275 $comment = $this->qtypeobj->comment_on_datasetitems($question->id,$answers, $data, $itemnumber);
276 if ($comment->outsidelimit) {
450f1127 277 $this->outsidelimit=$comment->outsidelimit ;
450f1127 278 }
28a27ef1 279 }
450f1127 280 $totalcomment='';
281 foreach ($question->options->answers as $key => $answer) {
282 $totalcomment .= $comment->stranswers[$key].'<br/>';
283 }
284
285 $formdata['answercomment['.$itemnumber.']'] = $totalcomment ;
60b5ecd3 286 }
8fc3e643 287
60b5ecd3 288 $formdata['nextpageparam[forceregeneration]'] = $this->regenerate;
451373ed 289 $formdata['selectdelete'] = '1';
290 $formdata['selectadd'] = '1';
a8d2a373 291 $j = $this->noofitems * count($this->datasetdefs)+1;
60b5ecd3 292 $data = array(); // data for comment_on_datasetitems later
293 //dataset generation dafaults
294 if ($this->qtypeobj->supports_dataset_item_generation()) {
295 $itemnumber = $this->noofitems+1;
296 foreach ($this->datasetdefs as $defid => $datasetdef){
5d0b1e40 297 if( optional_param('updatedatasets', '', PARAM_RAW) == '' && optional_param('updateanswers', '', PARAM_RAW)== ''){
60b5ecd3 298 $formdata["number[$j]"] = $this->qtypeobj->generate_dataset_item($datasetdef->options);
5d0b1e40 299 }else {
300 $formdata["number[$j]"] = $this->_form->getElementValue("number[$j]") ;
301 }
60b5ecd3 302 $formdata["definition[$j]"] = $defid;
303 $formdata["itemid[$j]"] =
304 isset($datasetdef->items[$itemnumber])?$datasetdef->items[$itemnumber]->id:0;
305 $data[$datasetdef->name] = $formdata["number[$j]"];
306 $j++;
307 }
8fc3e643 308 }
60b5ecd3 309
310 //existing records override generated data depending on radio element
a8d2a373 311 $j = $this->noofitems * count($this->datasetdefs)+1;
5d0b1e40 312 if (!$this->regenerate && (optional_param('updatedatasets', '', PARAM_RAW) == '' && optional_param('updateanswers', '', PARAM_RAW)== '')){
60b5ecd3 313 $idx = 1;
314 $itemnumber = $this->noofitems+1;
315 foreach ($this->datasetdefs as $defid => $datasetdef){
316 if (isset($datasetdef->items[$itemnumber])){
317 $formdata["number[$j]"] = $datasetdef->items[$itemnumber]->value;
318 $formdata["definition[$j]"] = $defid;
319 $formdata["itemid[$j]"] = $datasetdef->items[$itemnumber]->id;
320 $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value;
321 }
322 $j++;
323 }
324
325 }
326 //default answercomment will get ignored if answer element is not in the form.
28a27ef1 327 if($question->options->multichoice == 1 ){
328 $comment = $this->qtypeobj->multichoice_comment_on_datasetitems($question->id,$answers, $data, $itemnumber);
329 }else {
330
5d0b1e40 331 $comment = $this->qtypeobj->comment_on_datasetitems($question->id,$answers, $data, ($this->noofitems+1));
450f1127 332 if ($comment->outsidelimit) {
333 $this->outsidelimit=$comment->outsidelimit ;
450f1127 334 }
28a27ef1 335 }
450f1127 336 $key1 = 1;
337 foreach ($question->options->answers as $key => $answer) {
338 $formdata['answercomment['.($this->noofitems+$key1).']'] = $comment->stranswers[$key];
339 $key1++;
340 }
60b5ecd3 341
450f1127 342 if ($this->outsidelimit){
343 $formdata['outsidelimit']= '<span class="error">'.get_string('oneanswertrueansweroutsidelimits', 'qtype_datasetdependent').'</span>';
344 }
60b5ecd3 345 $formdata = $this->qtypeobj->custom_generator_set_data($this->datasetdefs, $formdata);
346
347 parent::set_data((object)($formdata + (array)$question));
8fc3e643 348 }
349
a78890d5 350 function validation($data, $files) {
60b5ecd3 351 $errors = array();
450f1127 352 if (isset($data['backtoquiz']) && ($this->noofitems==0) ){
451373ed 353 $errors['warning'] = get_string('warning', 'mnet');
aeb15530 354 }
450f1127 355 if ($this->outsidelimit){
356 // if(!isset($errors['warning'])) $errors['warning']=' ';
5d0b1e40 357 $errors['outsidelimits'] = get_string('oneanswertrueansweroutsidelimits','qtype_calculated');
60b5ecd3 358 }
ac5230fe 359 $numbers = $data['number'];
360 foreach ($numbers as $key => $number){
361 if(! is_numeric($number)){
362 if (stristr($number,',')){
363 $errors['number['.$key.']'] = get_string('The , cannot be used, use . as in 0.013 or 1.3e-2', 'qtype_datasetdependent');
aeb15530 364 }else {
ac5230fe 365 $errors['number['.$key.']'] = get_string('This is not a valid number', 'qtype_datasetdependent');
366 }
367 }else if( stristr($number,'x')){
368 $errors['number['.$key.']'] = get_string('Hexadecimal format (i.e. 0X12d) is not allowed', 'qtype_datasetdependent');
369 } else if( is_nan($number)){
370 $errors['number['.$key.']'] = get_string('is a NAN number', 'qtype_datasetdependent');
aeb15530 371 }
ac5230fe 372 }
60b5ecd3 373 return $errors;
374 }
375
376
8fc3e643 377}
aeb15530 378