curl now mandatory
[moodle.git] / question / type / calculated / edit_calculated_form.php
CommitLineData
aeb15530 1<?php
271ffe3f 2/**
3 * Defines the editing form for the calculated question type.
4 *
5 * @copyright &copy; 2007 Jamie Pratt
6 * @author Jamie Pratt me@jamiep.org
7 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
9e20fbc2 8 * @package questionbank
9 * @subpackage questiontypes
271ffe3f 10 */
11
12/**
13 * calculated editing form definition.
14 */
15class question_edit_calculated_form extends question_edit_form {
9aa022fe 16 /**
17 * Handle to the question type for this question.
18 *
19 * @var question_calculated_qtype
20 */
d90b016b
PP
21 public $qtypeobj;
22 public $questiondisplay ;
23 public $activecategory ;
24 public $categorychanged = false ;
25 public $initialname = '';
26 public $reload = false ;
27
28 function question_edit_calculated_form(&$submiturl, &$question, &$category, &$contexts, $formeditable = true){
29 global $QTYPES, $SESSION, $CFG, $DB;
30 $this->question = $question;
31 $this->qtypeobj =& $QTYPES[$this->question->qtype];
32 if ( "1" == optional_param('reload','', PARAM_INT )) {
33 $this->reload = true ;
34 }else {
35 $this->reload = false ;
36 }
2aef1fe5 37
d90b016b
PP
38 if(!$this->reload ){ // use database data as this is first pass
39 if(isset($this->question->id )){
40 // remove prefix #{..}# if exists
41 $this->initialname = $question->name ;
42 $regs= array();
43 if(preg_match('~#\{([^[:space:]]*)#~',$question->name , $regs)){
44 $question->name = str_replace($regs[0], '', $question->name);
45 };
46 }
47 }else {
48 }
49 parent::question_edit_form($submiturl, $question, $category, $contexts, $formeditable);
50 }
2aef1fe5 51 function get_per_answer_fields(&$mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
28a27ef1 52 // $repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
53 $repeated = array();
54 $repeated[] =& $mform->createElement('header', 'answerhdr', $label);
28a27ef1 55 $repeated[] =& $mform->createElement('text', 'answer', get_string('answer', 'quiz'), array('size' => 50));
56 $repeated[] =& $mform->createElement('select', 'fraction', get_string('grade'), $gradeoptions);
57 $repeated[] =& $mform->createElement('htmleditor', 'feedback', get_string('feedback', 'quiz'),
58 array('course' => $this->coursefilesid));
59 $repeatedoptions['answer']['type'] = PARAM_RAW;
60 $repeatedoptions['fraction']['default'] = 0;
61 $answersoption = 'answers';
62
2aef1fe5 63 $mform->setType('answer', PARAM_NOTAGS);
64
65 $addrepeated = array();
28a27ef1 66 $addrepeated[] =& $mform->createElement('text', 'tolerance', get_string('tolerance', 'qtype_calculated'));
67 $addrepeated[] =& $mform->createElement('select', 'tolerancetype', get_string('tolerancetype', 'quiz'), $this->qtypeobj->tolerance_types());
2aef1fe5 68 $repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
69 $repeatedoptions['tolerance']['default'] = 0.01;
2aef1fe5 70
71 $addrepeated[] =& $mform->createElement('select', 'correctanswerlength', get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
72 $repeatedoptions['correctanswerlength']['default'] = 2;
73
74 $answerlengthformats = array('1' => get_string('decimalformat', 'quiz'), '2' => get_string('significantfiguresformat', 'quiz'));
75 $addrepeated[] =& $mform->createElement('select', 'correctanswerformat', get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
76 array_splice($repeated, 3, 0, $addrepeated);
28a27ef1 77 $repeated[1]->setLabel(get_string('correctanswerformula', 'quiz').'=');
78
2aef1fe5 79 return $repeated;
80 }
81
271ffe3f 82 /**
83 * Add question-type specific form fields.
84 *
9aa022fe 85 * @param MoodleQuickForm $mform the form being built.
271ffe3f 86 */
87 function definition_inner(&$mform) {
9aa022fe 88 global $QTYPES;
92186abc 89 $this->qtypeobj =& $QTYPES[$this->qtype()];
aeb15530 90 // echo code left for testing period
99a77ee5 91 // echo "<p>question ".optional_param('multichoice', '', PARAM_RAW)." optional<pre>";print_r($this->question);echo "</pre></p>";
cf146692 92 $label = get_string('sharedwildcards', 'qtype_calculated');
a6d46515 93 $mform->addElement('hidden', 'initialcategory', 1);
d90b016b 94 $mform->addElement('hidden', 'reload', 1);
d18e0fe6 95 $mform->setType('initialcategory', PARAM_INT);
a6d46515 96 $html2 = $this->qtypeobj->print_dataset_definitions_category($this->question);
97 $mform->insertElementBefore($mform->createElement('static','listcategory',$label,$html2),'name');
d90b016b
PP
98 if(isset($this->question->id )){
99 $mform->insertElementBefore($mform->createElement('static','initialname',get_string('questionstoredname','qtype_calculated'),$this->initialname),'name');
100 };
a6d46515 101 $addfieldsname='updatecategory';
102 $addstring=get_string("updatecategory", "qtype_calculated");
103 $mform->registerNoSubmitButton($addfieldsname);
271e6dec 104
a6d46515 105 $mform->insertElementBefore( $mform->createElement('submit', $addfieldsname, $addstring),'listcategory');
28a27ef1 106 $mform->registerNoSubmitButton('createoptionbutton');
aeb15530 107
ab8b5142 108 //editing as regular
d18e0fe6 109 $mform->setType('single', PARAM_INT);
aeb15530 110
28a27ef1 111 $mform->addElement('hidden','shuffleanswers', '1');
d18e0fe6 112 $mform->setType('shuffleanswers', PARAM_INT);
113 $mform->addElement('hidden','answernumbering', 'abc');
114 $mform->setType('answernumbering', PARAM_SAFEDIR);
271ffe3f 115
271ffe3f 116 $creategrades = get_grade_options();
ab8b5142 117
28a27ef1 118 $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'),
2aef1fe5 119 $creategrades->gradeoptions, 1, 1);
aeb15530 120
92186abc 121
271e6dec 122 $repeated = array();
271ffe3f 123
cf146692
PP
124 $QTYPES['numerical']->add_units_options($mform,$this);
125 $QTYPES['numerical']->add_units_elements($mform,$this);
ab8b5142
PP
126 foreach (array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback') as $feedbackname) {
127 $mform->addElement('hidden', $feedbackname);
128 $mform->setType($feedbackname, PARAM_RAW);
28a27ef1 129 }
9aa022fe 130 //hidden elements
e593233a 131 $mform->addElement('hidden', 'synchronize', '');
d18e0fe6 132 $mform->setType('synchronize', PARAM_INT);
60b5ecd3 133 $mform->addElement('hidden', 'wizard', 'datasetdefinitions');
134 $mform->setType('wizard', PARAM_ALPHA);
92186abc 135
271ffe3f 136
137 }
138
32db0d42 139 function set_data($question) {
81053284
PP
140 global $QTYPES;
141
cf146692 142 $default_values = array();
271ffe3f 143 if (isset($question->options)){
144 $answers = $question->options->answers;
145 if (count($answers)) {
146 $key = 0;
147 foreach ($answers as $answer){
9af77e9d 148 $default_values['answer['.$key.']'] = $answer->answer;
92186abc 149 $default_values['fraction['.$key.']'] = $answer->fraction;
150 $default_values['tolerance['.$key.']'] = $answer->tolerance;
f7089b63 151 $default_values['tolerancetype['.$key.']'] = $answer->tolerancetype;
92186abc 152 $default_values['correctanswerlength['.$key.']'] = $answer->correctanswerlength;
9aa022fe 153 $default_values['correctanswerformat['.$key.']'] = $answer->correctanswerformat;
271ffe3f 154 $default_values['feedback['.$key.']'] = $answer->feedback;
155 $key++;
156 }
157 }
cf146692 158 $default_values['synchronize'] = $question->options->synchronize ;
bbfda343 159 $QTYPES['numerical']->set_numerical_unit_data($question,$default_values);
81053284 160 }
28a27ef1 161 if (isset($question->options->single)){
cf146692
PP
162 $default_values['single'] = $question->options->single;
163 $default_values['answernumbering'] = $question->options->answernumbering;
164 $default_values['shuffleanswers'] = $question->options->shuffleanswers;
165 $default_values['correctfeedback'] = $question->options->correctfeedback;
166 $default_values['partiallycorrectfeedback'] = $question->options->partiallycorrectfeedback;
167 $default_values['incorrectfeedback'] = $question->options->incorrectfeedback;
168 }
8fc3e643 169 $default_values['submitbutton'] = get_string('nextpage', 'qtype_calculated');
170 $default_values['makecopy'] = get_string('makecopynextpage', 'qtype_calculated');
271e6dec 171 /* set the wild cards category display given that on loading the category element is
172 unselected when processing this function but have a valid value when processing the
0dd3e11c 173 update category button. The value can be obtain by
174 $qu->category =$this->_form->_elements[$this->_form->_elementIndex['category']]->_values[0];
175 but is coded using existing functions
271e6dec 176 */
0dd3e11c 177 $qu = new stdClass;
178 $el = new stdClass;
271e6dec 179 /* no need to call elementExists() here */
79bb7202 180 if ($this->_form->elementExists('category')){
181 $el=$this->_form->getElement('category');
182 } else {
183 $el=$this->_form->getElement('categorymoveto');
184 }
0dd3e11c 185 if($value =$el->getSelected()) {
186 $qu->category =$value[0];
187 }else {
188 $qu->category=$question->category;// on load $question->category is set by question.php
271e6dec 189 }
0dd3e11c 190 $html2 = $this->qtypeobj->print_dataset_definitions_category($qu);
79bb7202 191 $this->_form->_elements[$this->_form->_elementIndex['listcategory']]->_text = $html2 ;
192 $question = (object)((array)$question + $default_values);
92186abc 193
32db0d42 194 parent::set_data($question);
271ffe3f 195 }
196
197 function qtype() {
198 return 'calculated';
199 }
200
a78890d5 201 function validation($data, $files) {
cf146692 202 global $QTYPES;
aeb15530 203 // echo code left for testing period
28a27ef1 204
205 // echo "<p>question <pre>";print_r($this->question);echo "</pre></p>";
206 // echo "<p>data <pre>";print_r($data);echo "</pre></p>";
207
fe93ba83 208 $errors = parent::validation($data, $files);
bfdc0bce 209 //verifying for errors in {=...} in question text;
210 $qtext = "";
211 $qtextremaining = $data['questiontext'] ;
212 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']);
213 foreach ($possibledatasets as $name => $value) {
214 $qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining);
215 }
271e6dec 216 // echo "numericalquestion qtextremaining <pre>";print_r($possibledatasets);
6dbcacee 217 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
bfdc0bce 218 $qtextsplits = explode($regs1[0], $qtextremaining, 2);
219 $qtext =$qtext.$qtextsplits[0];
220 $qtextremaining = $qtextsplits[1];
221 if (!empty($regs1[1]) && $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
222 if(!isset($errors['questiontext'])){
223 $errors['questiontext'] = $formulaerrors.':'.$regs1[1] ;
224 }else {
225 $errors['questiontext'] .= '<br/>'.$formulaerrors.':'.$regs1[1];
271e6dec 226 }
bfdc0bce 227 }
271e6dec 228 }
9af77e9d 229 $answers = $data['answer'];
271ffe3f 230 $answercount = 0;
a6d46515 231 $maxgrade = false;
f6232d58 232 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']);
233 $mandatorydatasets = array();
234 foreach ($answers as $key => $answer){
a6d46515 235 $mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
271e6dec 236 }
a6d46515 237 if ( count($mandatorydatasets )==0){
238 // $errors['questiontext']=get_string('atleastonewildcard', 'qtype_datasetdependent');
f6232d58 239 foreach ($answers as $key => $answer){
9af77e9d 240 $errors['answer['.$key.']'] = get_string('atleastonewildcard', 'qtype_datasetdependent');
271e6dec 241 }
242 }
ab8b5142 243 // regular calculated
99a77ee5 244 foreach ($answers as $key => $answer){
245 //check no of choices
246 // the * for everykind of answer not actually implemented
247 $trimmedanswer = trim($answer);
248 if (($trimmedanswer!='')||$answercount==0){
249 $eqerror = qtype_calculated_find_formula_errors($trimmedanswer);
250 if (FALSE !== $eqerror){
251 $errors['answer['.$key.']'] = $eqerror;
252 }
9aa022fe 253 }
99a77ee5 254 if ($trimmedanswer!=''){
255 if ('2' == $data['correctanswerformat'][$key]
256 && '0' == $data['correctanswerlength'][$key]) {
257 $errors['correctanswerlength['.$key.']'] = get_string('zerosignificantfiguresnotallowed','quiz');
258 }
259 if (!is_numeric($data['tolerance'][$key])){
260 $errors['tolerance['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
261 }
262 if ($data['fraction'][$key] == 1) {
263 $maxgrade = true;
264 }
aeb15530 265
99a77ee5 266 $answercount++;
a6d46515 267 }
99a77ee5 268 //check grades
aeb15530 269
99a77ee5 270 //TODO how should grade checking work here??
271 /*if ($answer != '') {
272 if ($data['fraction'][$key] > 0) {
273 $totalfraction += $data['fraction'][$key];
274 }
275 if ($data['fraction'][$key] > $maxfraction) {
276 $maxfraction = $data['fraction'][$key];
277 }
278 }*/
271ffe3f 279 }
aeb15530 280
99a77ee5 281 //grade checking :
282 /// Perform sanity checks on fractional grades
283 /*if ( ) {
284 if ($maxfraction != 1) {
285 $maxfraction = $maxfraction * 100;
286 $errors['fraction[0]'] = get_string('errfractionsnomax', 'qtype_multichoice', $maxfraction);
9aa022fe 287 }
99a77ee5 288 } else {
289 $totalfraction = round($totalfraction,2);
290 if ($totalfraction != 1) {
291 $totalfraction = $totalfraction * 100;
292 $errors['fraction[0]'] = get_string('errfractionsaddwrong', 'qtype_multichoice', $totalfraction);
9aa022fe 293 }
cf146692 294 }
99a77ee5 295 $units = $data['unit'];
296 if (count($units)) {
297 foreach ($units as $key => $unit){
298 if (is_numeric($unit)){
299 $errors['unit['.$key.']'] = get_string('mustnotbenumeric', 'qtype_calculated');
9aa022fe 300 }
99a77ee5 301 $trimmedunit = trim($unit);
302 $trimmedmultiplier = trim($data['multiplier'][$key]);
303 if (!empty($trimmedunit)){
304 if (empty($trimmedmultiplier)){
305 $errors['multiplier['.$key.']'] = get_string('youmustenteramultiplierhere', 'qtype_calculated');
306 }
307 if (!is_numeric($trimmedmultiplier)){
308 $errors['multiplier['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
309 }
aeb15530 310
9aa022fe 311 }
cf146692
PP
312 }
313 }*/
314 $QTYPES['numerical']->validate_numerical_options($data, $errors) ;
99a77ee5 315 if ($answercount==0){
316 $errors['answer[0]'] = get_string('atleastoneanswer', 'qtype_calculated');
317 }
318 if ($maxgrade == false) {
319 $errors['fraction[0]'] = get_string('fractionsnomax', 'question');
320 }
ab8b5142 321
9aa022fe 322
271ffe3f 323 return $errors;
324 }
325}
aeb15530 326