MDL-20636 Boilerplate and other cleanup in the question core code.
[moodle.git] / question / type / calculatedmulti / questiontype.php
CommitLineData
2d279432
PP
1<?php
2
fe6ce234
DC
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
2d279432
PP
18/////////////////
19// CALCULATED ///
20/////////////////
21
22/// QUESTION TYPE CLASS //////////////////
23
2d279432
PP
24class question_calculatedmulti_qtype extends question_calculated_qtype {
25
f5382dd2 26
2d279432 27 // Used by the function custom_generator_tools:
fe6ce234 28 public $calcgenerateidhasbeenadded = false;
2d279432
PP
29 public $virtualqtype = false;
30
31 function name() {
32 return 'calculatedmulti';
33 }
34
35 function has_wildcards_in_responses($question, $subqid) {
36 return true;
37 }
38
39 function requires_qtypes() {
40 return array('multichoice');
41 }
2d279432 42
2d279432
PP
43
44 function save_question_options($question) {
2d279432 45 global $CFG, $DB, $QTYPES ;
fe6ce234 46 $context = $question->context;
2d279432
PP
47 if (isset($question->answer) && !isset($question->answers)) {
48 $question->answers = $question->answer;
49 }
50 // calculated options
fe6ce234 51 $update = true ;
2d279432
PP
52 $options = $DB->get_record("question_calculated_options", array("question" => $question->id));
53 if (!$options) {
54 $update = false;
55 $options = new stdClass;
56 $options->question = $question->id;
57 }
58 $options->synchronize = $question->synchronize;
2d279432
PP
59 $options->single = $question->single;
60 $options->answernumbering = $question->answernumbering;
61 $options->shuffleanswers = $question->shuffleanswers;
fe6ce234
DC
62
63 // save question feedback files
64 foreach (array('correct', 'partiallycorrect', 'incorrect') as $feedbacktype) {
65 $feedbackname = $feedbacktype . 'feedback';
66 $feedbackformat = $feedbackname . 'format';
67 $feedback = $question->$feedbackname;
68 $options->$feedbackformat = $feedback['format'];
cde2709a
DC
69 if (isset($feedback['files'])) {
70 $options->$feedbackname = trim($feedback['text']);
71 $files = $feedback['files'];
72 foreach ($files as $file) {
73 $this->import_file($question->context, 'qtype_calculatedmulti', $feedbackname, $question->id, $file);
74 }
75 } else {
f5382dd2 76 $options->$feedbackname = file_save_draft_area_files($feedback['itemid'], $context->id, 'qtype_calculatedmulti', $feedbackname, $question->id, $this->fileoptionsa , trim($feedback['text']));
cde2709a 77 }
fe6ce234
DC
78 }
79
2d279432 80 if ($update) {
fe6ce234 81 $DB->update_record("question_calculated_options", $options);
2d279432 82 } else {
fe6ce234 83 $DB->insert_record("question_calculated_options", $options);
2d279432
PP
84 }
85
86 // Get old versions of the objects
87 if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
88 $oldanswers = array();
89 }
90
91 if (!$oldoptions = $DB->get_records('question_calculated', array('question' => $question->id), 'answer ASC')) {
92 $oldoptions = array();
93 }
94
95 // Save the units.
fe6ce234
DC
96 $virtualqtype = $this->get_virtual_qtype($question);
97 // TODO: What is this?
98 // $result = $virtualqtype->save_numerical_units($question);
2d279432
PP
99 if (isset($result->error)) {
100 return $result;
101 } else {
102 $units = &$result->units;
103 }
104 // Insert all the new answers
105 if (isset($question->answer) && !isset($question->answers)) {
fe6ce234 106 $question->answers = $question->answer;
2d279432
PP
107 }
108 foreach ($question->answers as $key => $dataanswer) {
cde2709a
DC
109 if (is_array($dataanswer)) {
110 $dataanswer = $dataanswer['text'];
111 }
fe6ce234 112 if ( trim($dataanswer) != '' ) {
2d279432
PP
113 $answer = new stdClass;
114 $answer->question = $question->id;
115 $answer->answer = trim($dataanswer);
116 $answer->fraction = $question->fraction[$key];
fe6ce234
DC
117 $answer->feedback = trim($question->feedback[$key]['text']);
118 $answer->feedbackformat = $question->feedback[$key]['format'];
cde2709a
DC
119 if (isset($question->feedback[$key]['files'])) {
120 $files = $question->feedback[$key]['files'];
121 }
2d279432
PP
122
123 if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
124 $answer->id = $oldanswer->id;
f5382dd2 125 $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, $this->fileoptionsa, $answer->feedback);
2d279432
PP
126 $DB->update_record("question_answers", $answer);
127 } else { // This is a completely new answer
128 $answer->id = $DB->insert_record("question_answers", $answer);
cde2709a
DC
129 if (isset($files)) {
130 $feedbacktext = $answer->feedback;
131 foreach ($files as $file) {
132 $this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
133 }
134 } else {
f5382dd2 135 $feedbacktext = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, $this->fileoptionsa, $answer->feedback);
cde2709a 136 }
fe6ce234 137 $DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$answer->id));
2d279432
PP
138 }
139
140 // Set up the options object
141 if (!$options = array_shift($oldoptions)) {
142 $options = new stdClass;
143 }
144 $options->question = $question->id;
145 $options->answer = $answer->id;
146 $options->tolerance = trim($question->tolerance[$key]);
147 $options->tolerancetype = trim($question->tolerancetype[$key]);
148 $options->correctanswerlength = trim($question->correctanswerlength[$key]);
149 $options->correctanswerformat = trim($question->correctanswerformat[$key]);
150
151 // Save options
152 if (isset($options->id)) { // reusing existing record
153 $DB->update_record('question_calculated', $options);
154 } else { // new options
155 $DB->insert_record('question_calculated', $options);
156 }
157 }
158 }
159 // delete old answer records
160 if (!empty($oldanswers)) {
161 foreach($oldanswers as $oa) {
162 $DB->delete_records('question_answers', array('id' => $oa->id));
163 }
164 }
165
166 // delete old answer records
167 if (!empty($oldoptions)) {
168 foreach($oldoptions as $oo) {
169 $DB->delete_records('question_calculated', array('id' => $oo->id));
170 }
171 }
2d279432
PP
172
173
174 if( isset($question->import_process)&&$question->import_process){
175 $this->import_datasets($question);
fe6ce234 176 }
2d279432
PP
177 // Report any problems.
178 if (!empty($result->notice)) {
179 return $result;
180 }
181 return true;
182 }
183
184 function create_session_and_responses(&$question, &$state, $cmoptions, $attempt) {
185 // Find out how many datasets are available
d90b016b 186 global $CFG, $DB, $QTYPES, $OUTPUT ;
fe6ce234
DC
187 $maxnumber = (int)$DB->get_field_sql(
188 "SELECT MIN(a.itemcount)
189 FROM {question_dataset_definitions} a, {question_datasets} b
190 WHERE b.question = ? AND a.id = b.datasetdefinition", array($question->id));
191 if (!$maxnumber) {
2d279432
PP
192 print_error('cannotgetdsforquestion', 'question', '', $question->id);
193 }
fe6ce234
DC
194 $sql = "SELECT i.*
195 FROM {question_datasets} d, {question_dataset_definitions} i
196 WHERE d.question = ? AND d.datasetdefinition = i.id AND i.category != 0";
2d279432 197 if (!$question->options->synchronize || !$records = $DB->get_records_sql($sql, array($question->id))) {
fe6ce234
DC
198 $synchronize_calculated = false ;
199 } else {
200 // i.e records is true so test coherence
201 $coherence = true ;
202 $a = new stdClass ;
203 $a->qid = $question->id ;
204 $a->qcat = $question->category ;
205 foreach($records as $def ){
d90b016b
PP
206 if ($def->category != $question->category){
207 $a->name = $def->name;
208 $a->sharedcat = $def->category ;
209 $coherence = false ;
210 break;
211 }
212 }
213 if(!$coherence){
fe6ce234
DC
214 echo $OUTPUT->notification(get_string('nocoherencequestionsdatyasetcategory','qtype_calculated',$a));
215 }
216
217 $synchronize_calculated = true ;
218 }
2d279432
PP
219
220 // Choose a random dataset
d90b016b
PP
221 // maxnumber sould not be breater than 100
222 if ($maxnumber > CALCULATEDQUESTIONMAXITEMNUMBER ){
223 $maxnumber = CALCULATEDQUESTIONMAXITEMNUMBER ;
224 }
2d279432
PP
225 if ( $synchronize_calculated === false ) {
226 $state->options->datasetitem = rand(1, $maxnumber);
227 }else{
fe6ce234 228 $state->options->datasetitem = intval( $maxnumber * substr($attempt->timestart,-2) /100 ) ;
2d279432
PP
229 if ($state->options->datasetitem < 1) {
230 $state->options->datasetitem =1 ;
231 } else if ($state->options->datasetitem > $maxnumber){
232 $state->options->datasetitem = $maxnumber ;
233 }
fe6ce234
DC
234
235 };
2d279432 236 $state->options->dataset =
fe6ce234
DC
237 $this->pick_question_dataset($question,$state->options->datasetitem);
238 // create an array of answerids ??? why so complicated ???
239 $answerids = array_values(array_map(create_function('$val',
240 'return $val->id;'), $question->options->answers));
241 // Shuffle the answers if required
242 if (!empty($cmoptions->shuffleanswers) and !empty($question->options->shuffleanswers)) {
243 $answerids = swapshuffle($answerids);
244 }
245 $state->options->order = $answerids;
246 // Create empty responses
247 if ($question->options->single) {
248 $state->responses = array('' => '');
249 } else {
250 $state->responses = array();
251 }
252 return true;
2d279432 253 }
fe6ce234 254
2d279432
PP
255 function save_session_and_responses(&$question, &$state) {
256 global $DB;
fe6ce234 257 $responses = 'dataset'.$state->options->datasetitem.'-' ;
2d279432
PP
258 $responses .= implode(',', $state->options->order) . ':';
259 $responses .= implode(',', $state->responses);
fe6ce234
DC
260
261 // Set the legacy answer field
f685e830 262 $DB->set_field('question_states', 'answer', $responses, array('id'=> $state->id));
2d279432
PP
263 return true;
264 }
265
266 function create_runtime_question($question, $form) {
78a6d0ba 267 $question = default_questiontype::create_runtime_question($question, $form);
2d279432
PP
268 $question->options->answers = array();
269 foreach ($form->answers as $key => $answer) {
270 $a->answer = trim($form->answer[$key]);
271 $a->fraction = $form->fraction[$key];//new
fe6ce234 272 $a->tolerance = $form->tolerance[$key];
2d279432
PP
273 $a->tolerancetype = $form->tolerancetype[$key];
274 $a->correctanswerlength = $form->correctanswerlength[$key];
275 $a->correctanswerformat = $form->correctanswerformat[$key];
276 $question->options->answers[] = clone($a);
277 }
278
279 return $question;
280 }
281
2d279432 282 function convert_answers (&$question, &$state){
fe6ce234
DC
283 foreach ($question->options->answers as $key => $answer) {
284 $answer->answer = $this->substitute_variables($answer->answer, $state->options->dataset);
285 //evaluate the equations i.e {=5+4)
286 $qtext = "";
287 $qtextremaining = $answer->answer ;
288 // while (preg_match('~\{(=)|%[[:digit]]\.=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
289 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
290
291 $qtextsplits = explode($regs1[0], $qtextremaining, 2);
292 $qtext = $qtext.$qtextsplits[0];
293 $qtextremaining = $qtextsplits[1];
294 if (empty($regs1[1])) {
295 $str = '';
296 } else {
297 if( $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])){
298 $str=$formulaerrors ;
299 }else {
300 eval('$str = '.$regs1[1].';');
301 $texteval= qtype_calculated_calculate_answer(
302 $str, $state->options->dataset, $answer->tolerance,
303 $answer->tolerancetype, $answer->correctanswerlength,
304 $answer->correctanswerformat, '');
2d279432 305 $str = $texteval->answer;
fe6ce234 306 }
2d279432 307 }
fe6ce234 308 $qtext = $qtext.$str ;
2d279432 309 }
fe6ce234 310 $answer->answer = $qtext.$qtextremaining ; ;
2d279432 311 }
fe6ce234 312 }
2d279432 313
fe6ce234
DC
314 function get_default_numerical_unit($question, $virtualqtype){
315 $unit = '';
316 return $unit ;
317 }
2d279432
PP
318 function grade_responses(&$question, &$state, $cmoptions) {
319 // Forward the grading to the virtual qtype
320 // We modify the question to look like a multichoice question
fe6ce234 321 // for grading nothing to do
2d279432
PP
322/* $numericalquestion = fullclone($question);
323 foreach ($numericalquestion->options->answers as $key => $answer) {
324 $answer = $numericalquestion->options->answers[$key]->answer; // for PHP 4.x
325 $numericalquestion->options->answers[$key]->answer = $this->substitute_variables_and_eval($answer,
326 $state->options->dataset);
fe6ce234
DC
327}*/
328 $virtualqtype = $this->get_virtual_qtype( $question);
2d279432
PP
329 return $virtualqtype->grade_responses($question, $state, $cmoptions) ;
330 }
331
2d279432 332
2d279432
PP
333
334 // ULPGC ecastro
335 function get_actual_response(&$question, &$state) {
336 // Substitute variables in questiontext before giving the data to the
337 // virtual type
338 $virtualqtype = $this->get_virtual_qtype( $question);
339 $unit = '' ;//$virtualqtype->get_default_numerical_unit($question);
340
341 // We modify the question to look like a multichoice question
342 $numericalquestion = clone($question);
343 $this->convert_answers ($numericalquestion, $state);
344 $this->convert_questiontext ($numericalquestion, $state);
345 /* $numericalquestion->questiontext = $this->substitute_variables_and_eval(
fe6ce234 346 $numericalquestion->questiontext, $state->options->dataset);*/
2d279432
PP
347 $responses = $virtualqtype->get_all_responses($numericalquestion, $state);
348 $response = reset($responses->responses);
349 $correct = $response->answer.' : ';
350
351 $responses = $virtualqtype->get_actual_response($numericalquestion, $state);
352
353 foreach ($responses as $key=>$response){
354 $responses[$key] = $correct.$response;
355 }
356
357 return $responses;
358 }
359
360 function create_virtual_qtype() {
361 global $CFG;
fe6ce234
DC
362 require_once("$CFG->dirroot/question/type/multichoice/questiontype.php");
363 return new question_multichoice_qtype();
2d279432
PP
364 }
365
366
367 function comment_header($question) {
368 //$this->get_question_options($question);
369 $strheader = '';
370 $delimiter = '';
371
372 $answers = $question->options->answers;
373
374 foreach ($answers as $key => $answer) {
375 if (is_string($answer)) {
376 $strheader .= $delimiter.$answer;
377 } else {
378 $strheader .= $delimiter.$answer->answer;
379 }
fe6ce234 380 $delimiter = '<br/>';
2d279432
PP
381 }
382 return $strheader;
383 }
384
385 function comment_on_datasetitems($qtypeobj,$questionid,$questiontext, $answers,$data, $number) { //multichoice_
386 global $DB;
387 $comment = new stdClass;
388 $comment->stranswers = array();
389 $comment->outsidelimit = false ;
390 $comment->answers = array();
391 /// Find a default unit:
392 /* if (!empty($questionid) && $unit = $DB->get_record('question_numerical_units', array('question'=> $questionid, 'multiplier' => 1.0))) {
393 $unit = $unit->unit;
394 } else {
395 $unit = '';
fe6ce234 396 }*/
2d279432
PP
397
398 $answers = fullclone($answers);
399 $strmin = get_string('min', 'quiz');
400 $strmax = get_string('max', 'quiz');
401 $errors = '';
402 $delimiter = ': ';
403 foreach ($answers as $key => $answer) {
fe6ce234
DC
404 $answer->answer = $this->substitute_variables($answer->answer, $data);
405 //evaluate the equations i.e {=5+4)
406 $qtext = "";
407 $qtextremaining = $answer->answer ;
408 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
409 $qtextsplits = explode($regs1[0], $qtextremaining, 2);
410 $qtext =$qtext.$qtextsplits[0];
411 $qtextremaining = $qtextsplits[1];
412 if (empty($regs1[1])) {
413 $str = '';
414 } else {
415 if( $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])){
416 $str=$formulaerrors ;
417 }else {
418 eval('$str = '.$regs1[1].';');
419 }
2d279432 420 }
fe6ce234
DC
421 $qtext = $qtext.$str ;
422 }
423 $answer->answer = $qtext.$qtextremaining;
424 $comment->stranswers[$key] = $answer->answer;
425
426
2d279432
PP
427 /* $formula = $this->substitute_variables($answer->answer,$data);
428 $formattedanswer = qtype_calculated_calculate_answer(
429 $answer->answer, $data, $answer->tolerance,
430 $answer->tolerancetype, $answer->correctanswerlength,
431 $answer->correctanswerformat, $unit);
432 if ( $formula === '*'){
433 $answer->min = ' ';
434 $formattedanswer->answer = $answer->answer ;
435 }else {
436 eval('$answer->answer = '.$formula.';') ;
437 $virtualqtype->get_tolerance_interval($answer);
fe6ce234 438 }
2d279432
PP
439 if ($answer->min === '') {
440 // This should mean that something is wrong
441 $comment->stranswers[$key] = " $formattedanswer->answer".'<br/><br/>';
442 } else if ($formula === '*'){
443 $comment->stranswers[$key] = $formula.' = '.get_string('anyvalue','qtype_calculated').'<br/><br/><br/>';
444 }else{
445 $comment->stranswers[$key]= $formula.' = '.$formattedanswer->answer.'<br/>' ;
446 $comment->stranswers[$key] .= $strmin. $delimiter.$answer->min.'---';
447 $comment->stranswers[$key] .= $strmax.$delimiter.$answer->max;
448 $comment->stranswers[$key] .='<br/>';
449 $correcttrue->correct = $formattedanswer->answer ;
450 $correcttrue->true = $answer->answer ;
451 if ($formattedanswer->answer < $answer->min || $formattedanswer->answer > $answer->max){
452 $comment->outsidelimit = true ;
453 $comment->answers[$key] = $key;
454 $comment->stranswers[$key] .=get_string('trueansweroutsidelimits','qtype_calculated',$correcttrue);//<span class="error">ERROR True answer '..' outside limits</span>';
455 }else {
456 $comment->stranswers[$key] .=get_string('trueanswerinsidelimits','qtype_calculated',$correcttrue);//' True answer :'.$calculated->trueanswer.' inside limits';
457 }
458 $comment->stranswers[$key] .='';
fe6ce234 459 }*/
2d279432
PP
460 }
461 return fullclone($comment);
462 }
463
2d279432
PP
464 function get_correct_responses1(&$question, &$state) {
465 $virtualqtype = $this->get_virtual_qtype( $question);
466 /* if ($question->options->multichoice != 1 ) {
467 if($unit = $virtualqtype->get_default_numerical_unit($question)){
468 $unit = $unit->unit;
469 } else {
470 $unit = '';
471 }
472 foreach ($question->options->answers as $answer) {
473 if (((int) $answer->fraction) === 1) {
474 $answernumerical = qtype_calculated_calculate_answer(
475 $answer->answer, $state->options->dataset, $answer->tolerance,
476 $answer->tolerancetype, $answer->correctanswerlength,
477 $answer->correctanswerformat, ''); // remove unit
478 $correct = array('' => $answernumerical->answer);
479 $correct['answer']= $correct[''];
480 if (isset($correct['']) && $correct[''] != '*' && $unit ) {
481 $correct[''] .= ' '.$unit;
482 $correct['unit']= $unit;
483 }
484 return $correct;
485 }
486 }
fe6ce234
DC
487 }else{**/
488 return $virtualqtype->get_correct_responses($question, $state) ;
489 // }
2d279432
PP
490 return null;
491 }
492
2d279432
PP
493 function get_virtual_qtype() {
494 global $QTYPES;
fe6ce234
DC
495 // if ( isset($question->options->multichoice) && $question->options->multichoice == '1'){
496 $this->virtualqtype =& $QTYPES['multichoice'];
497 // }else {
498 // $this->virtualqtype =& $QTYPES['numerical'];
499 // }
2d279432
PP
500 return $this->virtualqtype;
501 }
502
503
fe6ce234
DC
504 /**
505 * Runs all the code required to set up and save an essay question for testing purposes.
506 * Alternate DB table prefix may be used to facilitate data deletion.
507 */
508 function generate_test($name, $courseid = null) {
509 global $DB;
510 list($form, $question) = parent::generate_test($name, $courseid);
511 $form->feedback = 1;
512 $form->multiplier = array(1, 1);
513 $form->shuffleanswers = 1;
514 $form->noanswers = 1;
515 $form->qtype ='calculatedmulti';
516 $question->qtype ='calculatedmulti';
517 $form->answers = array('{a} + {b}');
518 $form->fraction = array(1);
519 $form->tolerance = array(0.01);
520 $form->tolerancetype = array(1);
521 $form->correctanswerlength = array(2);
522 $form->correctanswerformat = array(1);
523 $form->questiontext = "What is {a} + {b}?";
524
525 if ($courseid) {
526 $course = $DB->get_record('course', array('id'=> $courseid));
527 }
528
94dbfb3a 529 $new_question = $this->save_question($question, $form);
fe6ce234
DC
530
531 $dataset_form = new stdClass();
532 $dataset_form->nextpageparam["forceregeneration"]= 1;
533 $dataset_form->calcmin = array(1 => 1.0, 2 => 1.0);
534 $dataset_form->calcmax = array(1 => 10.0, 2 => 10.0);
535 $dataset_form->calclength = array(1 => 1, 2 => 1);
536 $dataset_form->number = array(1 => 5.4 , 2 => 4.9);
537 $dataset_form->itemid = array(1 => '' , 2 => '');
538 $dataset_form->calcdistribution = array(1 => 'uniform', 2 => 'uniform');
539 $dataset_form->definition = array(1 => "1-0-a",
540 2 => "1-0-b");
541 $dataset_form->nextpageparam = array('forceregeneration' => false);
542 $dataset_form->addbutton = 1;
543 $dataset_form->selectadd = 1;
544 $dataset_form->courseid = $courseid;
545 $dataset_form->cmid = 0;
546 $dataset_form->id = $new_question->id;
547 $this->save_dataset_items($new_question, $dataset_form);
548
549 return $new_question;
550 }
551
5d548d3e 552 function move_files($questionid, $oldcontextid, $newcontextid) {
fe6ce234 553 $fs = get_file_storage();
fe6ce234 554
5d548d3e
TH
555 parent::move_files($questionid, $oldcontextid, $newcontextid);
556 $this->move_files_in_answers($questionid, $oldcontextid, $newcontextid, true);
557
558 $fs->move_area_files_to_new_context($oldcontextid,
559 $newcontextid, 'qtype_calculatedmulti', 'correctfeedback', $questionid);
560 $fs->move_area_files_to_new_context($oldcontextid,
561 $newcontextid, 'qtype_calculatedmulti', 'partiallycorrectfeedback', $questionid);
562 $fs->move_area_files_to_new_context($oldcontextid,
563 $newcontextid, 'qtype_calculatedmulti', 'incorrectfeedback', $questionid);
fe6ce234
DC
564 }
565
9203b705
TH
566 protected function delete_files($questionid, $contextid) {
567 $fs = get_file_storage();
568
569 parent::delete_files($questionid, $contextid);
570 $this->delete_files_in_answers($questionid, $contextid, true);
571 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 'correctfeedback', $questionid);
572 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 'partiallycorrectfeedback', $questionid);
573 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 'incorrectfeedback', $questionid);
574 }
575
fe6ce234
DC
576 function check_file_access($question, $state, $options, $contextid, $component,
577 $filearea, $args) {
578 $itemid = reset($args);
579
580 if (empty($question->maxgrade)) {
581 $question->maxgrade = $question->defaultgrade;
582 }
583
584 if (in_array($filearea, array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'))) {
585 $result = $options->feedback && ($itemid == $question->id);
586 if (!$result) {
587 return false;
588 }
589 if ($state->raw_grade >= $question->maxgrade/1.01) {
590 $feedbacktype = 'correctfeedback';
591 } else if ($state->raw_grade > 0) {
592 $feedbacktype = 'partiallycorrectfeedback';
593 } else {
594 $feedbacktype = 'incorrectfeedback';
595 }
596 if ($feedbacktype != $filearea) {
597 return false;
598 }
599 return true;
600 } else if ($component == 'question' && $filearea == 'answerfeedback') {
601 return $options->feedback && (array_key_exists($itemid, $question->options->answers));
602 } else {
603 return parent::check_file_access($question, $state, $options, $contextid, $component,
604 $filearea, $args);
605 }
606 }
2d279432 607}
fe6ce234 608
2d279432
PP
609//// END OF CLASS ////
610
611//////////////////////////////////////////////////////////////////////////
612//// INITIATION - Without this line the question type is not in use... ///
613//////////////////////////////////////////////////////////////////////////
614question_register_questiontype(new question_calculatedmulti_qtype());
34e24cd3
PP
615
616if ( ! defined ("CALCULATEDMULTI")) {
617 define("CALCULATEDMULTI", "calculatedmulti");
618}