|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00027 defined('MOODLE_INTERNAL') || die(); 00028 00029 require_once($CFG->dirroot . '/question/type/edit_question_form.php'); 00030 00031 00038 class question_dataset_dependent_items_form extends question_wizard_form { 00046 public $question; 00052 public $qtypeobj; 00053 00054 public $datasetdefs; 00055 00056 public $maxnumber = -1; 00057 00058 public $regenerate; 00059 00060 public $noofitems; 00061 00062 public $outsidelimit = false; 00063 00064 public $commentanswers = array(); 00065 00071 public function __construct($submiturl, $question, $regenerate) { 00072 global $SESSION, $CFG, $DB; 00073 $this->regenerate = $regenerate; 00074 $this->question = $question; 00075 $this->qtypeobj = question_bank::get_qtype($this->question->qtype); 00076 // Validate the question category. 00077 if (!$category = $DB->get_record('question_categories', 00078 array('id' => $question->category))) { 00079 print_error('categorydoesnotexist', 'question', $returnurl); 00080 } 00081 $this->category = $category; 00082 $this->categorycontext = get_context_instance_by_id($category->contextid); 00083 //get the dataset defintions for this question 00084 if (empty($question->id)) { 00085 $this->datasetdefs = $this->qtypeobj->get_dataset_definitions( 00086 $question->id, $SESSION->calculated->definitionform->dataset); 00087 } else { 00088 if (empty($question->options)) { 00089 $this->get_question_options($question); 00090 } 00091 $this->datasetdefs = $this->qtypeobj->get_dataset_definitions( 00092 $question->id, array()); 00093 } 00094 00095 foreach ($this->datasetdefs as $datasetdef) { 00096 // Get maxnumber 00097 if ($this->maxnumber == -1 || $datasetdef->itemcount < $this->maxnumber) { 00098 $this->maxnumber = $datasetdef->itemcount; 00099 } 00100 } 00101 foreach ($this->datasetdefs as $defid => $datasetdef) { 00102 if (isset($datasetdef->id)) { 00103 $this->datasetdefs[$defid]->items = 00104 $this->qtypeobj->get_database_dataset_items($datasetdef->id); 00105 } 00106 } 00107 parent::__construct($submiturl); 00108 } 00109 00110 protected function definition() { 00111 $labelsharedwildcard = get_string("sharedwildcard", "qtype_calculated"); 00112 00113 $mform =& $this->_form; 00114 $strquestionlabel = $this->qtypeobj->comment_header($this->question); 00115 if ($this->maxnumber != -1 ) { 00116 $this->noofitems = $this->maxnumber; 00117 } else { 00118 $this->noofitems = 0; 00119 } 00120 $label = get_string("sharedwildcards", "qtype_calculated"); 00121 00122 $html2 = $this->qtypeobj->print_dataset_definitions_category_shared( 00123 $this->question, $this->datasetdefs); 00124 $mform->addElement('static', 'listcategory', $label, $html2); 00125 //---------------------------------------------------------------------- 00126 $mform->addElement('submit', 'updatedatasets', 00127 get_string('updatedatasetparam', 'qtype_calculated')); 00128 $mform->registerNoSubmitButton('updatedatasets'); 00129 $mform->addElement('header', 'additemhdr', 00130 get_string('itemtoadd', 'qtype_calculated')); 00131 $idx = 1; 00132 $data = array(); 00133 $j = (($this->noofitems) * count($this->datasetdefs))+1; 00134 foreach ($this->datasetdefs as $defkey => $datasetdef) { 00135 if ($datasetdef->category |= 0 ) { 00136 $name = get_string('sharedwildcard', 'qtype_calculated', $datasetdef->name); 00137 } else { 00138 $name = get_string('wildcard', 'qtype_calculated', $datasetdef->name); 00139 } 00140 $mform->addElement('text', "number[$j]", $name); 00141 $mform->setType("number[$j]", PARAM_NUMBER); 00142 $this->qtypeobj->custom_generator_tools_part($mform, $idx, $j); 00143 $idx++; 00144 $mform->addElement('hidden', "definition[$j]"); 00145 $mform->setType("definition[$j]", PARAM_RAW); 00146 $mform->addElement('hidden', "itemid[$j]"); 00147 $mform->setType("itemid[$j]", PARAM_RAW); 00148 $mform->addElement('static', "divider[$j]", '', '<hr />'); 00149 $mform->setType("divider[$j]", PARAM_RAW); 00150 $j++; 00151 } 00152 00153 $mform->addElement('header', 'updateanswershdr', 00154 get_string('answerstoleranceparam', 'qtype_calculated')); 00155 $mform->addElement('submit', 'updateanswers', 00156 get_string('updatetolerancesparam', 'qtype_calculated')); 00157 $mform->setAdvanced('updateanswers', true); 00158 $mform->registerNoSubmitButton('updateanswers'); 00159 00160 $answers = fullclone($this->question->options->answers); 00161 $key1 =1; 00162 foreach ($answers as $key => $answer) { 00163 if ('' === $answer->answer) { 00164 // Do nothing. 00165 } else if ('*' === $answer->answer) { 00166 $mform->addElement('static', 00167 'answercomment[' . ($this->noofitems+$key1) . ']', $answer->answer); 00168 $mform->addElement('hidden', 'tolerance['.$key.']', ''); 00169 $mform->setType('tolerance['.$key.']', PARAM_RAW); 00170 $mform->setAdvanced('tolerance['.$key.']', true); 00171 $mform->addElement('hidden', 'tolerancetype['.$key.']', ''); 00172 $mform->setType('tolerancetype['.$key.']', PARAM_RAW); 00173 $mform->setAdvanced('tolerancetype['.$key.']', true); 00174 $mform->addElement('hidden', 'correctanswerlength['.$key.']', ''); 00175 $mform->setType('correctanswerlength['.$key.']', PARAM_RAW); 00176 $mform->setAdvanced('correctanswerlength['.$key.']', true); 00177 $mform->addElement('hidden', 'correctanswerformat['.$key.']', ''); 00178 $mform->setType('correctanswerformat['.$key.']', PARAM_RAW); 00179 $mform->setAdvanced('correctanswerformat['.$key.']', true); 00180 } else { 00181 $mform->addElement('static', 'answercomment[' . ($this->noofitems+$key1) . ']', 00182 $answer->answer); 00183 $mform->addElement('text', 'tolerance['.$key.']', 00184 get_string('tolerance', 'qtype_calculated')); 00185 $mform->setAdvanced('tolerance['.$key.']', true); 00186 $mform->addElement('select', 'tolerancetype['.$key.']', 00187 get_string('tolerancetype', 'qtype_numerical'), 00188 $this->qtypeobj->tolerance_types()); 00189 $mform->setAdvanced('tolerancetype['.$key.']', true); 00190 00191 $mform->addElement('select', 'correctanswerlength['.$key.']', 00192 get_string('correctanswershows', 'qtype_calculated'), range(0, 9)); 00193 $mform->setAdvanced('correctanswerlength['.$key.']', true); 00194 00195 $answerlengthformats = array( 00196 '1' => get_string('decimalformat', 'qtype_numerical'), 00197 '2' => get_string('significantfiguresformat', 'qtype_calculated') 00198 ); 00199 $mform->addElement('select', 'correctanswerformat['.$key.']', 00200 get_string('correctanswershowsformat', 'qtype_calculated'), 00201 $answerlengthformats); 00202 $mform->setAdvanced('correctanswerformat['.$key.']', true); 00203 $mform->addElement('static', 'dividertolerance', '', '<hr />'); 00204 $mform->setAdvanced('dividertolerance', true); 00205 } 00206 $key1++; 00207 } 00208 00209 $addremoveoptions = array(); 00210 $addremoveoptions['1']='1'; 00211 for ($i=10; $i<=100; $i+=10) { 00212 $addremoveoptions["$i"]="$i"; 00213 } 00214 $showoptions = Array(); 00215 $showoptions['1']='1'; 00216 $showoptions['2']='2'; 00217 $showoptions['5']='5'; 00218 for ($i=10; $i<=100; $i+=10) { 00219 $showoptions["$i"]="$i"; 00220 } 00221 $mform->addElement('header', 'additemhdr', get_string('add', 'moodle')); 00222 $mform->closeHeaderBefore('additemhdr'); 00223 00224 if ($this->qtypeobj->supports_dataset_item_generation()) { 00225 $radiogrp = array(); 00226 $radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]', 00227 null, get_string('reuseifpossible', 'qtype_calculated'), 0); 00228 $radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]', 00229 null, get_string('forceregenerationshared', 'qtype_calculated'), 1); 00230 $radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]', 00231 null, get_string('forceregenerationall', 'qtype_calculated'), 2); 00232 $mform->addGroup($radiogrp, 'forceregenerationgrp', 00233 get_string('nextitemtoadd', 'qtype_calculated'), "<br/>", false); 00234 } 00235 00236 $mform->addElement('submit', 'getnextbutton', get_string('getnextnow', 'qtype_calculated')); 00237 $mform->addElement('static', "dividera", '', '<hr />'); 00238 $addgrp = array(); 00239 $addgrp[] =& $mform->createElement('submit', 'addbutton', get_string('add', 'moodle')); 00240 $addgrp[] =& $mform->createElement('select', "selectadd", 00241 get_string('additem', 'qtype_calculated'), $addremoveoptions); 00242 $addgrp[] = & $mform->createElement('static', "stat", "Items", 00243 get_string('newsetwildcardvalues', 'qtype_calculatedsimple')); 00244 $mform->addGroup($addgrp, 'addgrp', get_string('additem', 'qtype_calculated'), ' ', false); 00245 $mform->addElement('static', "divideradd", '', ''); 00246 if ($this->noofitems > 0) { 00247 $mform->addElement('header', 'additemhdr', get_string('delete', 'moodle')); 00248 $deletegrp = array(); 00249 $deletegrp[] = $mform->createElement('submit', 'deletebutton', 00250 get_string('delete', 'moodle')); 00251 $deletegrp[] = $mform->createElement('select', 'selectdelete', 00252 get_string('deleteitem', 'qtype_calculated')."1", $addremoveoptions); 00253 $deletegrp[] = $mform->createElement('static', "stat", "Items", 00254 get_string('setwildcardvalues', 'qtype_calculatedsimple')); 00255 $mform->addGroup($deletegrp, 'deletegrp', '', ' ', false); 00256 } else { 00257 $mform->addElement('static', 'warning', '', '<span class="error">' . 00258 get_string('youmustaddatleastoneitem', 'qtype_calculated').'</span>'); 00259 } 00260 00261 $addgrp1 = array(); 00262 $addgrp1[] = $mform->createElement('submit', 'showbutton', 00263 get_string('showitems', 'qtype_calculated')); 00264 $addgrp1[] = $mform->createElement('select', "selectshow", '' , $showoptions); 00265 $addgrp1[] = $mform->createElement('static', "stat", '', 00266 get_string('setwildcardvalues', 'qtype_calculated')); 00267 $mform->addGroup($addgrp1, 'addgrp1', '', ' ', false); 00268 $mform->registerNoSubmitButton('showbutton'); 00269 $mform->closeHeaderBefore('addgrp1'); 00270 //---------------------------------------------------------------------- 00271 $j = $this->noofitems * count($this->datasetdefs); 00272 $k = optional_param('selectshow', 1, PARAM_INT); 00273 for ($i = $this->noofitems; $i >= 1; $i--) { 00274 if ($k > 0) { 00275 $mform->addElement('header', '', "<b>" . 00276 get_string('setno', 'qtype_calculated', $i)."</b> "); 00277 } 00278 foreach ($this->datasetdefs as $defkey => $datasetdef) { 00279 if ($k > 0) { 00280 if ($datasetdef->category == 0 ) { 00281 $mform->addElement('text', "number[$j]", 00282 get_string('wildcard', 'qtype_calculated', $datasetdef->name)); 00283 } else { 00284 $mform->addElement('text', "number[$j]", get_string( 00285 'sharedwildcard', 'qtype_calculated', $datasetdef->name)); 00286 } 00287 00288 } else { 00289 $mform->addElement('hidden', "number[$j]" , ''); 00290 } 00291 $mform->setType("number[$j]", PARAM_NUMBER); 00292 $mform->addElement('hidden', "itemid[$j]"); 00293 $mform->setType("itemid[$j]", PARAM_INT); 00294 00295 $mform->addElement('hidden', "definition[$j]"); 00296 $mform->setType("definition[$j]", PARAM_NOTAGS); 00297 $data[$datasetdef->name] =$datasetdef->items[$i]->value; 00298 00299 $j--; 00300 } 00301 if ('' != $strquestionlabel && ($k > 0 )) { 00302 //|| $this->outsidelimit || !empty($this->numbererrors ) 00303 $repeated[] = $mform->addElement('static', "answercomment[$i]", $strquestionlabel); 00304 // decode equations in question text 00305 $qtext = $this->qtypeobj->substitute_variables( 00306 $this->question->questiontext, $data); 00307 $textequations = $this->qtypeobj->find_math_equations($qtext); 00308 if ($textequations != '' && count($textequations) > 0 ) { 00309 $mform->addElement('static', "divider1[$j]", '', 00310 'Formulas {=..} in question text'); 00311 foreach ($textequations as $key => $equation) { 00312 if ($formulaerrors = qtype_calculated_find_formula_errors($equation)) { 00313 $str=$formulaerrors; 00314 } else { 00315 eval('$str = '.$equation.';'); 00316 } 00317 00318 $mform->addElement('static', "textequation", "{=$equation}", "=".$str); 00319 } 00320 } 00321 00322 } 00323 $k--; 00324 00325 } 00326 $mform->addElement('static', 'outsidelimit', '', ''); 00327 //---------------------------------------------------------------------- 00328 // Non standard name for button element needed so not using add_action_buttons 00329 if (!($this->noofitems==0) ) { 00330 $mform->addElement('submit', 'savechanges', get_string('savechanges')); 00331 $mform->closeHeaderBefore('savechanges'); 00332 } 00333 00334 $this->add_hidden_fields(); 00335 00336 $mform->addElement('hidden', 'category'); 00337 $mform->setType('category', PARAM_SEQUENCE); 00338 00339 $mform->addElement('hidden', 'wizard', 'datasetitems'); 00340 $mform->setType('wizard', PARAM_ALPHA); 00341 } 00342 00343 public function set_data($question) { 00344 $formdata = array(); 00345 $fromform = new stdClass(); 00346 if (isset($question->options)) { 00347 $answers = $question->options->answers; 00348 if (count($answers)) { 00349 if (optional_param('updateanswers', false, PARAM_BOOL) || 00350 optional_param('updatedatasets', false, PARAM_BOOL)) { 00351 foreach ($answers as $key => $answer) { 00352 $fromform->tolerance[$key]= $this->_form->getElementValue( 00353 'tolerance['.$key.']'); 00354 $answer->tolerance = $fromform->tolerance[$key]; 00355 $fromform->tolerancetype[$key]= $this->_form->getElementValue( 00356 'tolerancetype['.$key.']'); 00357 if (is_array($fromform->tolerancetype[$key])) { 00358 $fromform->tolerancetype[$key]= $fromform->tolerancetype[$key][0]; 00359 } 00360 $answer->tolerancetype = $fromform->tolerancetype[$key]; 00361 $fromform->correctanswerlength[$key]= $this->_form->getElementValue( 00362 'correctanswerlength['.$key.']'); 00363 if (is_array($fromform->correctanswerlength[$key])) { 00364 $fromform->correctanswerlength[$key] = 00365 $fromform->correctanswerlength[$key][0]; 00366 } 00367 $answer->correctanswerlength = $fromform->correctanswerlength[$key]; 00368 $fromform->correctanswerformat[$key] = $this->_form->getElementValue( 00369 'correctanswerformat['.$key.']'); 00370 if (is_array($fromform->correctanswerformat[$key])) { 00371 $fromform->correctanswerformat[$key] = 00372 $fromform->correctanswerformat[$key][0]; 00373 } 00374 $answer->correctanswerformat = $fromform->correctanswerformat[$key]; 00375 } 00376 $this->qtypeobj->save_question_calculated($question, $fromform); 00377 00378 } else { 00379 foreach ($answers as $key => $answer) { 00380 $formdata['tolerance['.$key.']'] = $answer->tolerance; 00381 $formdata['tolerancetype['.$key.']'] = $answer->tolerancetype; 00382 $formdata['correctanswerlength['.$key.']'] = $answer->correctanswerlength; 00383 $formdata['correctanswerformat['.$key.']'] = $answer->correctanswerformat; 00384 } 00385 } 00386 } 00387 } 00388 //fill out all data sets and also the fields for the next item to add. 00389 $j = $this->noofitems * count($this->datasetdefs); 00390 for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--) { 00391 $data = array(); 00392 foreach ($this->datasetdefs as $defid => $datasetdef) { 00393 if (isset($datasetdef->items[$itemnumber])) { 00394 $formdata["number[$j]"] = $datasetdef->items[$itemnumber]->value; 00395 $formdata["definition[$j]"] = $defid; 00396 $formdata["itemid[$j]"] = $datasetdef->items[$itemnumber]->id; 00397 $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value; 00398 } 00399 $j--; 00400 } 00401 $comment = $this->qtypeobj->comment_on_datasetitems($this->qtypeobj, $question->id, 00402 $question->questiontext, $answers, $data, $itemnumber); 00403 if ($comment->outsidelimit) { 00404 $this->outsidelimit=$comment->outsidelimit; 00405 } 00406 $totalcomment=''; 00407 foreach ($question->options->answers as $key => $answer) { 00408 $totalcomment .= $comment->stranswers[$key].'<br/>'; 00409 } 00410 $formdata['answercomment['.$itemnumber.']'] = $totalcomment; 00411 } 00412 00413 $formdata['nextpageparam[forceregeneration]'] = $this->regenerate; 00414 $formdata['selectdelete'] = '1'; 00415 $formdata['selectadd'] = '1'; 00416 $j = $this->noofitems * count($this->datasetdefs)+1; 00417 $data = array(); // data for comment_on_datasetitems later 00418 //dataset generation dafaults 00419 if ($this->qtypeobj->supports_dataset_item_generation()) { 00420 $itemnumber = $this->noofitems+1; 00421 foreach ($this->datasetdefs as $defid => $datasetdef) { 00422 if (!optional_param('updatedatasets', false, PARAM_BOOL) && 00423 !optional_param('updateanswers', false, PARAM_BOOL)) { 00424 $formdata["number[$j]"] = $this->qtypeobj->generate_dataset_item( 00425 $datasetdef->options); 00426 } else { 00427 $formdata["number[$j]"] = $this->_form->getElementValue("number[$j]"); 00428 } 00429 $formdata["definition[$j]"] = $defid; 00430 $formdata["itemid[$j]"] = isset($datasetdef->items[$itemnumber]) ? 00431 $datasetdef->items[$itemnumber]->id : 0; 00432 $data[$datasetdef->name] = $formdata["number[$j]"]; 00433 $j++; 00434 } 00435 } 00436 00437 //existing records override generated data depending on radio element 00438 $j = $this->noofitems * count($this->datasetdefs) + 1; 00439 if (!$this->regenerate && !optional_param('updatedatasets', false, PARAM_BOOL) && 00440 !optional_param('updateanswers', false, PARAM_BOOL)) { 00441 $idx = 1; 00442 $itemnumber = $this->noofitems + 1; 00443 foreach ($this->datasetdefs as $defid => $datasetdef) { 00444 if (isset($datasetdef->items[$itemnumber])) { 00445 $formdata["number[$j]"] = $datasetdef->items[$itemnumber]->value; 00446 $formdata["definition[$j]"] = $defid; 00447 $formdata["itemid[$j]"] = $datasetdef->items[$itemnumber]->id; 00448 $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value; 00449 } 00450 $j++; 00451 } 00452 } 00453 00454 $comment = $this->qtypeobj->comment_on_datasetitems($this->qtypeobj, $question->id, 00455 $question->questiontext, $answers, $data, ($this->noofitems + 1)); 00456 if (isset($comment->outsidelimit) && $comment->outsidelimit) { 00457 $this->outsidelimit=$comment->outsidelimit; 00458 } 00459 $key1 = 1; 00460 foreach ($question->options->answers as $key => $answer) { 00461 $formdata['answercomment['.($this->noofitems+$key1).']'] = $comment->stranswers[$key]; 00462 $key1++; 00463 } 00464 00465 if ($this->outsidelimit) { 00466 $formdata['outsidelimit']= '<span class="error">' . 00467 get_string('oneanswertrueansweroutsidelimits', 'qtype_calculated') . '</span>'; 00468 } 00469 $formdata = $this->qtypeobj->custom_generator_set_data($this->datasetdefs, $formdata); 00470 00471 parent::set_data((object)($formdata + (array)$question)); 00472 } 00473 00474 public function validation($data, $files) { 00475 $errors = array(); 00476 if (isset($data['savechanges']) && ($this->noofitems==0) ) { 00477 $errors['warning'] = get_string('warning', 'mnet'); 00478 } 00479 if ($this->outsidelimit) { 00480 $errors['outsidelimits'] = 00481 get_string('oneanswertrueansweroutsidelimits', 'qtype_calculated'); 00482 } 00483 $numbers = $data['number']; 00484 foreach ($numbers as $key => $number) { 00485 if (! is_numeric($number)) { 00486 if (stristr($number, ', ')) { 00487 $errors['number['.$key.']'] = get_string( 00488 'The , cannot be used, use . as in 0.013 or 1.3e-2', 'qtype_calculated'); 00489 } else { 00490 $errors['number['.$key.']'] = get_string( 00491 'This is not a valid number', 'qtype_calculated'); 00492 } 00493 } else if (stristr($number, 'x')) { 00494 $errors['number['.$key.']'] = get_string( 00495 'Hexadecimal format (i.e. 0X12d) is not allowed', 'qtype_calculated'); 00496 } else if (is_nan($number)) { 00497 $errors['number['.$key.']'] = get_string( 00498 'is a NAN number', 'qtype_calculated'); 00499 } 00500 } 00501 return $errors; 00502 } 00503 }