ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.assFormulaQuestionGUI.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4include_once "./Modules/TestQuestionPool/classes/class.assQuestionGUI.php";
5include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestion.php";
6include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestionResult.php";
7include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestionVariable.php";
8include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestionUnit.php";
9include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestionUnitCategory.php";
10include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
11require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiAnswerScoringAdjustable.php';
12
22{
29 function __construct($id = -1)
30 {
31 parent::__construct();
32 $this->object = new assFormulaQuestion();
33 $this->newUnitId = null;
34 if($id >= 0)
35 {
36 $this->object->loadFromDb($id);
37 }
38 }
39
45 function setQuestionTabs()
46 {
47 global $rbacsystem, $ilTabs;
48
49 $ilTabs->clearTargets();
50
51 $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
52 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
53 $q_type = $this->object->getQuestionType();
54
55 if(strlen($q_type))
56 {
57 $classname = $q_type . "GUI";
58 $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
59 $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
60 }
61
62 if($_GET["q_id"])
63 {
64 if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
65 {
66 // edit page
67 $ilTabs->addTarget("edit_page",
68 $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
69 array("edit", "insert", "exec_pg"),
70 "", "", $force_active);
71 }
72
73 $this->addTab_QuestionPreview($ilTabs);
74 }
75
76 $force_active = false;
77 if($rbacsystem->checkAccess('write', $_GET["ref_id"]))
78 {
79 $url = "";
80
81 if($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
82 $commands = $_POST["cmd"];
83 if(is_array($commands))
84 {
85 foreach($commands as $key => $value)
86 {
87 if(preg_match("/^suggestrange_.*/", $key, $matches))
88 {
89 $force_active = true;
90 }
91 }
92 }
93 // edit question properties
94 $ilTabs->addTarget("edit_properties",
95 $url,
96 array(
97 "editQuestion", "save", "cancel", "addSuggestedSolution",
98 "cancelExplorer", "linkChilds", "removeSuggestedSolution",
99 "parseQuestion", "saveEdit", "suggestRange"
100 ),
101 $classname, "", $force_active);
102 }
103
104 if($_GET["q_id"])
105 {
106 // add tab for question feedback within common class assQuestionGUI
107 $this->addTab_QuestionFeedback($ilTabs);
108 }
109
110 if($_GET["q_id"])
111 {
112 // add tab for question hint within common class assQuestionGUI
113 $this->addTab_QuestionHints($ilTabs);
114 }
115
116 // Unit editor
117 if($_GET['q_id'])
118 {
119 // add tab for question hint within common class assQuestionGUI
120 $this->addTab_Units($ilTabs);
121 }
122
123 // Assessment of questions sub menu entry
124 if($_GET["q_id"])
125 {
126 $ilTabs->addTarget("statistics",
127 $this->ctrl->getLinkTargetByClass($classname, "assessment"),
128 array("assessment"),
129 $classname, "");
130 }
131
132 $this->addBackTab($ilTabs);
133 }
134
135 function getCommand($cmd)
136 {
137 if(preg_match("/suggestrange_(.*?)/", $cmd, $matches))
138 {
139 $cmd = "suggestRange";
140 }
141 return $cmd;
142 }
143
148 function suggestRange()
149 {
150 if($this->writePostData())
151 {
153 }
154 $this->editQuestion();
155 }
156
161 public function writePostData($always = false)
162 {
163 $hasErrors = (!$always) ? $this->editQuestion(true) : false;
164 $checked = true;
165 if(!$hasErrors)
166 {
167 $this->object->setTitle($_POST["title"]);
168 $this->object->setAuthor($_POST["author"]);
169 $this->object->setComment($_POST["comment"]);
170 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
171 $questiontext = ilUtil::stripOnlySlashes($_POST["question"]);
172 $this->object->setQuestion($questiontext);
173 $this->object->setEstimatedWorkingTime(
174 $_POST["Estimated"]["hh"],
175 $_POST["Estimated"]["mm"],
176 $_POST["Estimated"]["ss"]
177 );
178
179 $this->object->parseQuestionText();
180 $found_vars = array();
181 $found_results = array();
182
183
184 foreach($_POST as $key => $value)
185 {
186 if(preg_match("/^unit_(\\\$v\d+)$/", $key, $matches))
187 {
188 array_push($found_vars, $matches[1]);
189 }
190 if(preg_match("/^unit_(\\\$r\d+)$/", $key, $matches))
191 {
192 array_push($found_results, $matches[1]);
193 }
194 }
195
196// if(!$this->object->checkForDuplicateVariables())
197// {
198//
199// $this->addErrorMessage($this->lng->txt("err_duplicate_variables"));
200// $checked = FALSE;
201// }
202 if(!$this->object->checkForDuplicateResults())
203 {
204 $this->addErrorMessage($this->lng->txt("err_duplicate_results"));
205 $checked = FALSE;
206 }
207
208 foreach($found_vars as $variable)
209 {
210 if($this->object->getVariable($variable) != null)
211 {
212 $varObj = new assFormulaQuestionVariable($variable, $_POST["range_min_$variable"], $_POST["range_max_$variable"], $this->object->getUnitrepository()->getUnit($_POST["unit_$variable"]), $_POST["precision_$variable"], $_POST["intprecision_$variable"]);
213 $varObj->setRangeMinTxt($_POST["range_min_$variable"]);
214 $varObj->setRangeMaxTxt($_POST["range_max_$variable"]);
215 $this->object->addVariable($varObj);
216 }
217 }
218
219 $tmp_form_vars = array();
220 $tmp_quest_vars = array();
221 foreach($found_results as $result)
222 {
223 $tmp_res_match = preg_match_all("/([$][v][0-9]*)/", $_POST["formula_$result"], $form_vars);
224 $tmp_form_vars = array_merge($tmp_form_vars,$form_vars[0]);
225
226 $tmp_que_match = preg_match_all("/([$][v][0-9]*)/", $_POST['question'] , $quest_vars);
227 $tmp_quest_vars= array_merge($tmp_quest_vars,$quest_vars[0]);
228 }
229 $result_has_undefined_vars = array_diff($tmp_form_vars, $found_vars);
230 $question_has_unused_vars = array_diff($tmp_quest_vars, $tmp_form_vars);
231
232 if(count($result_has_undefined_vars) > 0 || count($question_has_unused_vars) > 0)
233 {
234 $error_message = '';
235 if(count($result_has_undefined_vars) > 0)
236 {
237 $error_message .= $this->lng->txt("res_contains_undef_var"). '<br>';
238 }
239 if(count($question_has_unused_vars) > 0)
240 {
241 $error_message .= $this->lng->txt("que_contains_unused_var");
242 }
243 $checked = false;
244 if($this->isSaveCommand())
245 {
246 ilUtil::sendFailure($error_message);
247 }
248 }
249 foreach($found_results as $result)
250 {
251 if(is_object($this->object->getUnitrepository()->getUnit($_POST["unit_$result"])))
252 {
253 $tmp_result_unit = $this->object->getUnitrepository()->getUnit($_POST["unit_$result"]);
254 }
255 else
256 {
257 $tmp_result_unit = NULL;
258 }
259
260 if($this->object->getResult($result) != null)
261 {
262 $use_simple_rating = ($_POST["rating_advanced_$result"] == 1) ? FALSE : TRUE;
263 $resObj = new assFormulaQuestionResult(
264 $result,
265 $_POST["range_min_$result"],
266 $_POST["range_max_$result"],
267 $_POST["tolerance_$result"],
268
269 $tmp_result_unit,
270 $_POST["formula_$result"],
271 $_POST["points_$result"],
272 $_POST["precision_$result"],
273 $use_simple_rating,
274 ($_POST["rating_advanced_$result"] == 1) ? $_POST["rating_sign_$result"] : "",
275 ($_POST["rating_advanced_$result"] == 1) ? $_POST["rating_value_$result"] : "",
276 ($_POST["rating_advanced_$result"] == 1) ? $_POST["rating_unit_$result"] : "",
277 $_POST["result_type_$result"] != 0 ? $_POST["result_type_$result"] : 0
278 );
279 $resObj->setRangeMinTxt($_POST["range_min_$result"]);
280 $resObj->setRangeMaxTxt($_POST["range_max_$result"]);
281 $this->object->addResult($resObj);
282 $this->object->addResultUnits($resObj, $_POST["units_$result"]);
283 }
284 }
285 if($checked == false)
286 {
287 return 1;
288 }
289 else
290 {
291 $this->resetSavedPreviewSession();
292 return 0;
293 }
294 }
295 else
296 {
297 return 1;
298 }
299 }
300
302 {
303 global $ilUser;
304 $user_id = $ilUser->getId();
305 $question_id = $this->object->getId();
306 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewSession.php';
307 $ilAssQuestionPreviewSession = new ilAssQuestionPreviewSession($user_id, $question_id);
308 $ilAssQuestionPreviewSession->setParticipantsSolution(array());
309 }
310
311 function isSaveCommand()
312 {
313 return in_array($this->ctrl->getCmd(), array('saveFQ', 'saveEdit', 'saveReturnFQ'));
314 }
315
321 function editQuestion($checkonly = FALSE)
322 {
323 $save = $this->isSaveCommand();
324
325 $this->getQuestionTemplate();
326
327 include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
328 $form = new ilPropertyFormGUI();
329 $form->setFormAction($this->ctrl->getFormAction($this));
330 $form->setTitle($this->outQuestionType());
331 $form->setMultipart(FALSE);
332 $form->setTableWidth('100%');
333 $form->setId('assformulaquestion');
334
335 // title, author, description, question, working time (assessment mode)
336 $this->addBasicQuestionFormProperties($form);
337
338 // Add info text
339 $question = $form->getItemByPostVar('question');
340 $question->setInfo($this->lng->txt('fq_question_desc'));
341
342 $variables = $this->object->getVariables();
343 $categorized_units = $this->object->getUnitrepository()->getCategorizedUnits();
344 $result_units = $this->object->__get('resultunits');
345
346 $unit_options = array();
347 $category_name = '';
348 $new_category = false;
349 foreach((array)$categorized_units as $item)
350 {
354 if($item instanceof assFormulaQuestionUnitCategory)
355 {
356 if($category_name != $item->getDisplayString())
357 {
358 $new_category = true;
359 $category_name = $item->getDisplayString();
360 }
361 continue;
362 }
363 $unit_options[$item->getId()] = $item->getDisplayString() . ($new_category ? ' (' . $category_name . ')' : '');
364 $new_category = false;
365 }
366
367 if(count($variables))
368 {
369 uasort($variables, function(assFormulaQuestionVariable $v1, assFormulaQuestionVariable $v2) {
370 $num_v1 = (int)substr($v1->getVariable(), 2);
371 $num_v2 = (int)substr($v2->getVariable(), 2);
372 if($num_v1 > $num_v2)
373 {
374 return 1;
375 }
376 else if($num_v1 < $num_v2)
377 {
378 return -1;
379 }
380
381 return 0;
382 });
383
384 foreach($variables as $variable)
385 {
389 $variable_header = new ilFormSectionHeaderGUI();
390 $variable_header->setTitle(sprintf($this->lng->txt('variable_x'), $variable->getVariable()));
391
392 $range_min = new ilNumberInputGUI($this->lng->txt('range_min'), 'range_min_' . $variable->getVariable());
393 $range_min->allowDecimals(true);
394 $range_min->setSize(3);
395 $range_min->setRequired(true);
396 $range_min->setValue($variable->getRangeMin());
397
398 $range_max = new ilNumberInputGUI($this->lng->txt('range_max'), 'range_max_' . $variable->getVariable());
399 $range_max->allowDecimals(true);
400 $range_max->setSize(3);
401 $range_max->setRequired(true);
402 $range_max->setValue($variable->getRangeMax());
403
404 $units = new ilSelectInputGUI($this->lng->txt('unit'), 'unit_' . $variable->getVariable());
405 $units->setOptions(array(0 => $this->lng->txt('no_selection')) + $unit_options);
406 if(is_object($variable->getUnit()))
407 {
408 $units->setValue($variable->getUnit()->getId());
409 }
410
411 $precision = new ilNumberInputGUI($this->lng->txt('precision'), 'precision_' . $variable->getVariable());
412 $precision->setRequired(true);
413 $precision->setSize(3);
414 $precision->setMinValue(0);
415 $precision->setValue($variable->getPrecision());
416 $precision->setInfo($this->lng->txt('fq_precision_info'));
417
418 $intprecision = new ilNumberInputGUI($this->lng->txt('intprecision'), 'intprecision_' . $variable->getVariable());
419 $intprecision->setSize(3);
420 $intprecision->setMinValue(1);
421 $intprecision->setValue($variable->getIntprecision());
422 $intprecision->setInfo($this->lng->txt('intprecision_info'));
423
424 $form->addItem($variable_header);
425 $form->addItem($range_min);
426 $form->addItem($range_max);
427 $form->addItem($units);
428 $form->addItem($precision);
429 $form->addItem($intprecision);
430 }
431 }
432
433 $results = $this->object->getResults();
434 if(count($results))
435 {
436 require_once 'Services/Form/classes/class.ilMultiSelectInputGUI.php';
437
439 $num_r1 = (int)substr($r1->getResult(), 2);
440 $num_r2 = (int)substr($r2->getResult(), 2);
441 if($num_r1 > $num_r2)
442 {
443 return 1;
444 }
445 else if($num_r1 < $num_r2)
446 {
447 return -1;
448 }
449
450 return 0;
451 });
452
453 foreach($results as $result)
454 {
458 $result_header = new ilFormSectionHeaderGUI();
459 $result_header->setTitle(sprintf($this->lng->txt('result_x'), $result->getResult()));
460
461 $formula = new ilTextInputGUI($this->lng->txt('formula'), 'formula_' . $result->getResult());
462 $formula->setInfo($this->lng->txt('fq_formula_desc'));
463 $formula->setRequired(true);
464 $formula->setSize(50);
465 $formula->setValue($result->getFormula());
466 $formula->setSuffix(' = ' . $result->getResult());
467
468 if(
469 preg_match("/suggestrange_(.*)/", $this->ctrl->getCmd(), $matches) &&
470 strcmp($matches[1], $result->getResult()) == 0
471 )
472 {
473 // suggest a range for the result
474 if(strlen($result->substituteFormula($variables, $results)))
475 {
476 $result->suggestRange($variables, $results);
477 }
478 }
479
480 $range_min = new ilNumberInputGUI($this->lng->txt('range_min'), 'range_min_' . $result->getResult());
481 $range_min->allowDecimals(true);
482 $range_min->setSize(3);
483 $range_min->setRequired(true);
484 $range_min->setValue($result->getRangeMin());
485
486 $range_max = new ilNumberInputGUI($this->lng->txt('range_max'), 'range_max_' . $result->getResult());
487 $range_max->allowDecimals(true);
488 $range_max->setSize(3);
489 $range_max->setRequired(true);
490 $range_max->setValue($result->getRangeMax());
491
492 $matches = array();
493
494 $precision = new ilNumberInputGUI($this->lng->txt('precision'), 'precision_' . $result->getResult());
495 $precision->setRequired(true);
496 $precision->setSize(3);
497 $precision->setMinValue(0);
498 $precision->setInfo($this->lng->txt('fq_precision_info'));
499 $precision->setValue($result->getPrecision());
500
501 $tolerance = new ilNumberInputGUI($this->lng->txt('tolerance'), 'tolerance_' . $result->getResult());
502 $tolerance->setSize(3);
503 $tolerance->setMinValue(0);
504 $tolerance->setMaxValue(100);
505 $tolerance->allowDecimals(false);
506 $tolerance->setInfo($this->lng->txt('tolerance_info'));
507 $tolerance->setValue($result->getTolerance());
508
509 $suggest_range_button = new ilCustomInputGUI('', '');
510 $suggest_range_button->setHtml('<input type="submit" class="btn btn-default" name="cmd[suggestrange_'.$result->getResult().']" value="'.$this->lng->txt("suggest_range").'" />');
511
512 $sel_result_units = new ilSelectInputGUI($this->lng->txt('unit'), 'unit_' . $result->getResult());
513 $sel_result_units->setOptions(array(0 => $this->lng->txt('no_selection')) + $unit_options);
514 $sel_result_units->setInfo($this->lng->txt('result_unit_info'));
515 if(is_object($result->getUnit()))
516 {
517 $sel_result_units->setValue($result->getUnit()->getId());
518 }
519
520 $mc_result_units = new ilMultiSelectInputGUI($this->lng->txt('result_units'), 'units_' . $result->getResult());
521 $mc_result_units->setOptions($unit_options);
522 $mc_result_units->setInfo($this->lng->txt('result_units_info'));
523 $selectedvalues = array();
524 foreach($unit_options as $unit_id => $txt)
525 {
526 if($this->hasResultUnit($result, $unit_id, $result_units))
527 {
528 $selectedvalues[] = $unit_id;
529 }
530 }
531 $mc_result_units->setValue($selectedvalues);
532
533 $result_type = new ilRadioGroupInputGUI($this->lng->txt('result_type_selection'), 'result_type_' . $result->getResult());
534 $result_type->setRequired(true);
535
536 $no_type = new ilRadioOption($this->lng->txt('no_result_type'), 0);
537 $no_type->setInfo($this->lng->txt('fq_no_restriction_info'));
538
539 $result_dec = new ilRadioOption($this->lng->txt('result_dec'), 1);
540 $result_dec->setInfo($this->lng->txt('result_dec_info'));
541
542 $result_frac = new ilRadioOption($this->lng->txt('result_frac'), 2);
543 $result_frac->setInfo($this->lng->txt('result_frac_info'));
544
545 $result_co_frac = new ilRadioOption($this->lng->txt('result_co_frac'), 3);
546 $result_co_frac->setInfo($this->lng->txt('result_co_frac_info'));
547
548 $result_type->addOption($no_type);
549 $result_type->addOption($result_dec);
550 $result_type->addOption($result_frac);
551 $result_type->addOption($result_co_frac);
552 $result_type->setValue(strlen($result->getResultType()) ? $result->getResultType() : 0);
553
554 $points = new ilNumberInputGUI($this->lng->txt('points'), 'points_' . $result->getResult());
555 $points->allowDecimals(true);
556 $points->setRequired(true);
557 $points->setSize(3);
558 $points->setMinValue(0);
559 $points->setValue(strlen($result->getPoints()) ? $result->getPoints() : 1);
560
561 $rating_type = new ilCheckboxInputGUI($this->lng->txt('advanced_rating'), 'rating_advanced_' . $result->getResult());
562 $rating_type->setValue(1);
563 $rating_type->setInfo($this->lng->txt('advanced_rating_info'));
564
565 if(!$save)
566 {
567 $advanced_rating = $this->canUseAdvancedRating($result);
568 if(!$advanced_rating)
569 {
570 $rating_type->setDisabled(true);
571 $rating_type->setChecked(false);
572 }
573 else
574 {
575 $rating_type->setChecked(strlen($result->getRatingSimple()) && $result->getRatingSimple() ? false : true);
576 }
577 }
578
579 $sign = new ilNumberInputGUI($this->lng->txt('rating_sign'), 'rating_sign_' . $result->getResult());
580 $sign->setRequired(true);
581 $sign->setSize(3);
582 $sign->setMinValue(0);
583 $sign->setValue($result->getRatingSign());
584 $rating_type->addSubItem($sign);
585
586 $value = new ilNumberInputGUI($this->lng->txt('rating_value'), 'rating_value_' . $result->getResult());
587 $value->setRequired(true);
588 $value->setSize(3);
589 $value->setMinValue(0);
590 $value->setValue($result->getRatingValue());
591 $rating_type->addSubItem($value);
592
593 $unit = new ilNumberInputGUI($this->lng->txt('rating_unit'), 'rating_unit_' . $result->getResult());
594 $unit->setRequired(true);
595 $unit->setSize(3);
596 $unit->setMinValue(0);
597 $unit->setValue($result->getRatingUnit());
598 $rating_type->addSubItem($unit);
599
600 $info_text = new ilNonEditableValueGUI($this->lng->txt('additional_rating_info'));
601 $rating_type->addSubItem($info_text);
602
603 $form->addItem($result_header);
604 $form->addItem($formula);
605 $form->addItem($range_min);
606 $form->addItem($range_max);
607 $form->addItem($suggest_range_button);
608 $form->addItem($precision);
609 $form->addItem($tolerance);
610 $form->addItem($sel_result_units);
611 $form->addItem($mc_result_units);
612 $form->addItem($result_type);
613 $form->addItem($points);
614 $form->addItem($rating_type);
615 }
616
617 $defined_result_vars = array();
618 $quest_vars = array();
619
620 $defined_result_res = array();
621 $result_vars = array();
622
623 foreach($variables as $key => $object)
624 {
625 $quest_vars[$key] = $key;
626 }
627
628 foreach($results as $key => $object)
629 {
630 $result_vars[$key] = $key;
631 }
632
633 foreach($results as $tmp_result)
634 {
638 $formula = $tmp_result->getFormula();
639
640 preg_match_all("/([$][v][0-9]*)/", $formula, $form_vars);
641 preg_match_all("/([$][r][0-9]*)/", $formula, $form_res);
642 foreach($form_vars[0] as $res_var)
643 {
644 $defined_result_vars[$res_var] = $res_var;
645 }
646
647 foreach($form_res[0] as $res_res)
648 {
649 $defined_result_res[$res_res] = $res_res;
650 }
651 }
652 }
653
654 $result_has_undefined_vars = array();
655 $question_has_unused_vars = array();
656
657 if(is_array($quest_vars) && count($quest_vars) > 0)
658 {
659 $result_has_undefined_vars = array_diff($defined_result_vars, $quest_vars);
660 $question_has_unused_vars = array_diff($quest_vars, $defined_result_vars);
661 }
662
663 if(is_array($result_vars) && count($result_vars) > 0)
664 {
665 $result_has_undefined_res = array_diff($defined_result_res, $result_vars);
666
667 }
668 $error_message = '';
669
670 if(count($result_has_undefined_vars) > 0 || count($question_has_unused_vars) > 0)
671 {
672 if(count($result_has_undefined_vars) > 0)
673 {
674 $error_message .= $this->lng->txt("res_contains_undef_var"). '<br>';
675 }
676 if(count($question_has_unused_vars) > 0)
677 {
678 $error_message .= $this->lng->txt("que_contains_unused_var"). '<br>';
679 }
680
681 $checked = false;
682 if($save)
683 {
684 ilUtil::sendFailure($error_message);
685 }
686 }
687
688 if(count($result_has_undefined_res) > 0)
689 {
690 $error_message .= $this->lng->txt("res_contains_undef_res"). '<br>';
691 $checked = false;
692 }
693
694 if($save && !$checked)
695 {
696 ilUtil::sendFailure($error_message);
697 }
698
699 if($this->object->getId())
700 {
701 $hidden = new ilHiddenInputGUI("", "ID");
702 $hidden->setValue($this->object->getId());
703 $form->addItem($hidden);
704 }
705
706 $this->populateTaxonomyFormSection($form);
707
708 $form->addCommandButton('parseQuestion', $this->lng->txt("parseQuestion"));
709 $form->addCommandButton('saveReturnFQ', $this->lng->txt("save_return"));
710 $form->addCommandButton('saveFQ', $this->lng->txt("save"));
711
712 $errors = $checked;
713
714 if($save)
715 {
716 $found_vars = array();
717 $found_results = array();
718 foreach((array)$_POST as $key => $value)
719 {
720 if(preg_match("/^unit_(\\\$v\d+)$/", $key, $matches))
721 {
722 array_push($found_vars, $matches[1]);
723 }
724 if(preg_match("/^unit_(\\\$r\d+)$/", $key, $matches))
725 {
726 array_push($found_results, $matches[1]);
727 }
728 }
729
730 $form->setValuesByPost();
731 $errors = !$form->checkInput();
732
733 $custom_errors = false;
734 if(count($variables))
735 {
736 foreach($variables as $variable)
737 {
741 $min_range = $form->getItemByPostVar('range_min_' . $variable->getVariable());
742 $max_range = $form->getItemByPostVar('range_max_' . $variable->getVariable());
743 if($min_range->getValue() > $max_range->getValue())
744 {
745 $min_range->setAlert($this->lng->txt('err_range'));
746 $max_range->setAlert($this->lng->txt('err_range'));
747 $custom_errors = true;
748 }
749 }
750 }
751
752 if(count($results))
753 {
754 foreach($results as $result)
755 {
759 $min_range = $form->getItemByPostVar('range_min_' . $result->getResult());
760 $max_range = $form->getItemByPostVar('range_max_' . $result->getResult());
761 if($min_range->getValue() > $max_range->getValue())
762 {
763 $min_range->setAlert($this->lng->txt('err_range'));
764 $max_range->setAlert($this->lng->txt('err_range'));
765 $custom_errors = true;
766 }
767
768
769 $formula = $form->getItemByPostVar('formula_' . $result->getResult());
770 if(strpos($formula->getValue(), $result->getResult()) !== FALSE)
771 {
772 $formula->setAlert($this->lng->txt('errRecursionInResult'));
773 $custom_errors = true;
774 }
775
776 $result_unit = $form->getItemByPostVar('unit_' . $result->getResult());
777 $rating_advanced = $form->getItemByPostVar('rating_advanced_' . $result->getResult());
778 if(((int)$result_unit->getValue() <= 0) && $rating_advanced->getChecked())
779 {
780 unset($_POST['rating_advanced_' . $result->getResult()]);
781 $rating_advanced->setDisabled(true);
782 $rating_advanced->setChecked(false);
783 $rating_advanced->setAlert($this->lng->txt('err_rating_advanced_not_allowed'));
784 $custom_errors = true;
785 }
786 else if($rating_advanced->getChecked())
787 {
788 $rating_sign = $form->getItemByPostVar('rating_sign_' . $result->getResult());
789 $rating_value = $form->getItemByPostVar('rating_value_' . $result->getResult());
790 $rating_unit = $form->getItemByPostVar('rating_unit_' . $result->getResult());
791
792 $percentage = $rating_sign->getValue() + $rating_value->getValue() + $rating_unit->getValue();
793 if($percentage != 100)
794 {
795 $rating_advanced->setAlert($this->lng->txt('err_wrong_rating_advanced'));
796 $custom_errors = true;
797 }
798 }
799
800 preg_match_all("/([$][v][0-9]*)/", $formula->getValue(), $form_vars);
801 $result_has_undefined_vars = array_diff($form_vars[0], (array)$found_vars);
802 if(count($result_has_undefined_vars))
803 {
804 $errors = true;
805 ilUtil::sendInfo($this->lng->txt('res_contains_undef_var'));
806 }
807 }
808 }
809
810 if($custom_errors && !$errors)
811 {
812 $errors = true;
813 ilUtil::sendFailure($this->lng->txt('form_input_not_valid'));
814 }
815 $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we need this if we don't want to have duplication of backslashes
816 if($errors)
817 {
818 $checkonly = false;
819 }
820 }
821
822 if(!$checkonly)
823 {
824 $this->tpl->setVariable('QUESTION_DATA', $form->getHTML());
825 }
826 return $errors;
827 }
828
829 private function hasResultUnit($result, $unit_id, $resultunits)
830 {
831 if (array_key_exists($result->getResult(), $resultunits))
832 {
833 if (array_key_exists($unit_id, $resultunits[$result->getResult()])) return TRUE;
834 }
835 return FALSE;
836 }
837
846 {
847 $resultunit = $result->getUnit();
848
849 /*
850 * if there is a result-unit (unit selectbox) selected it is possible to use advanced rating
851 * if there is no result-unit selected it is NOT possible to use advanced rating, because there is no
852 * definition if the result-value or the unit-value should be the correct solution!!
853 *
854 */
855 if(is_object($resultunit))
856 {
857 return true;
858 }
859 else
860 {
861 return false;
862 }
863 }
864
865 public function parseQuestion()
866 {
867 $this->writePostData();
868 $this->editQuestion();
869 }
870
871 public function saveReturnFQ()
872 {
873 global $ilUser;
874 $old_id = $_GET["q_id"];
875 $result = $this->writePostData();
876 if ($result == 0)
877 {
878 $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
879 $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
881 $this->object->saveToDb();
882 $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
883 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
884 if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int)$_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId()))
885 {
886 $this->ctrl->redirect($this, "originalSyncForm");
887 return;
888 }
889 elseif ($_GET["calling_test"])
890 {
891 require_once 'Modules/Test/classes/class.ilObjTest.php';
892 $test = new ilObjTest($_GET["calling_test"]);
893 #var_dump(assQuestion::_questionExistsInTest($this->object->getId(), $test->getTestId()));
894 $q_id = $this->object->getId();
895 if(!assQuestion::_questionExistsInTest($this->object->getId(), $test->getTestId()))
896 {
897 global $tree, $ilDB, $ilPluginAdmin;
898
899 include_once("./Modules/Test/classes/class.ilObjTest.php");
900 $_GET["ref_id"] = $_GET["calling_test"];
901 $test = new ilObjTest($_GET["calling_test"], true);
902
903 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
904 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
905
906 $new_id = $test->insertQuestion(
907 $testQuestionSetConfigFactory->getQuestionSetConfig(), $this->object->getId()
908 );
909
910 $q_id = $new_id;
911 if(isset($_REQUEST['prev_qid']))
912 {
913 $test->moveQuestionAfter($this->object->getId() + 1, $_REQUEST['prev_qid']);
914 }
915
916 $this->ctrl->setParameter($this, 'q_id', $new_id);
917 $this->ctrl->setParameter($this, 'calling_test', $_GET['calling_test']);
918 #$this->ctrl->setParameter($this, 'test_ref_id', false);
919
920 }
921 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
922 if($_REQUEST['test_express_mode'])
923 {
925 }
926 else
927 {
928 ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["calling_test"]);
929 }
930 }
931 else
932 {
933 if ($this->object->getId() != $old_id)
934 {
935 $this->callNewIdListeners($this->object->getId());
936 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
937 $this->ctrl->redirectByClass("ilobjquestionpoolgui", "questions");
938 }
939 if (strcmp($_SESSION["info"], "") != 0)
940 {
941 ilUtil::sendSuccess($_SESSION["info"] . "<br />" . $this->lng->txt("msg_obj_modified"), true);
942 }
943 else
944 {
945 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
946 }
947 $this->ctrl->redirectByClass("ilobjquestionpoolgui", "questions");
948 }
949 }
950 else
951 {
952 $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
953 $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
954 $this->object->saveToDb();
955 $this->editQuestion();
956 }
957 }
958
959 public function saveFQ()
960 {
961 $result = $this->writePostData();
962
963 if($result == 1)
964 {
965 $this->editQuestion();
966 }
967 else
968 {
970 $this->save();
971 }
972 }
976 function checkInput()
977 {
978 if((!$_POST["title"]) or (!$_POST["author"]) or (!$_POST["question"]))
979 {
980 $this->addErrorMessage($this->lng->txt("fill_out_all_required_fields"));
981 return FALSE;
982 }
983
984
985 return TRUE;
986 }
987
1001 $active_id,
1002 $pass = NULL,
1003 $graphicalOutput = FALSE,
1004 $result_output = FALSE,
1005 $show_question_only = TRUE,
1006 $show_feedback = FALSE,
1007 $show_correct_solution = FALSE,
1008 $show_manual_scoring = FALSE,
1009 $show_question_text = TRUE
1010 )
1011 {
1012 // get the solution of the user for the active pass or from the last pass if allowed
1013 $user_solution = array();
1014 if(($active_id > 0) && (!$show_correct_solution))
1015 {
1016 $solutions = array();
1017 include_once "./Modules/Test/classes/class.ilObjTest.php";
1018 if(!ilObjTest::_getUsePreviousAnswers($active_id, true))
1019 {
1020 if(is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1021 }
1022 $user_solution["active_id"] = $active_id;
1023 $user_solution["pass"] = $pass;
1024 $solutions =& $this->object->getSolutionValues($active_id, $pass);
1025 foreach($solutions as $idx => $solution_value)
1026 {
1027 if(preg_match("/^(\\\$v\\d+)$/", $solution_value["value1"], $matches))
1028 {
1029 $user_solution[$matches[1]] = $solution_value["value2"];
1030 }
1031 else if(preg_match("/^(\\\$r\\d+)$/", $solution_value["value1"], $matches))
1032 {
1033 if(!array_key_exists($matches[1], $user_solution)) $user_solution[$matches[1]] = array();
1034 $user_solution[$matches[1]]["value"] = $solution_value["value2"];
1035 }
1036 else if(preg_match("/^(\\\$r\\d+)_unit$/", $solution_value["value1"], $matches))
1037 {
1038 if(!array_key_exists($matches[1], $user_solution)) $user_solution[$matches[1]] = array();
1039 $user_solution[$matches[1]]["unit"] = $solution_value["value2"];
1040 }
1041 }
1042 }
1043 else if($active_id)
1044 {
1045 $solutions = NULL;
1046 include_once "./Modules/Test/classes/class.ilObjTest.php";
1047 if(!ilObjTest::_getUsePreviousAnswers($active_id, true))
1048 {
1049 if(is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1050 }
1051 $user_solution = (array)$this->object->getBestSolution($this->object->getSolutionValues($active_id, $pass));
1052 }
1053 elseif( is_object($this->getPreviewSession()) )
1054 {
1055 $solutionValues = array();
1056
1057 foreach($this->getPreviewSession()->getParticipantsSolution() as $val1 => $val2)
1058 {
1059 $solutionValues[] = array('value1' => $val1, 'value2' => $val2);
1060 }
1061
1062 $user_solution = (array)$this->object->getBestSolution($solutionValues);
1063 }
1064
1065 $template = new ilTemplate("tpl.il_as_qpl_formulaquestion_output_solution.html", true, true, 'Modules/TestQuestionPool');
1066 $questiontext = $this->object->substituteVariables($user_solution, $graphicalOutput, TRUE, $result_output);
1067
1068 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
1069 $questionoutput = $template->get();
1070 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
1071 $feedback = ($show_feedback) ? $this->getGenericFeedbackOutput($active_id, $pass) : "";
1072 if (strlen($feedback))
1073 {
1074 $cssClass = ( $this->hasCorrectSolution($active_id, $pass) ?
1076 );
1077
1078 $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
1079 $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $feedback, true ));
1080 }
1081 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
1082
1083 $solutionoutput = $solutiontemplate->get();
1084 if(!$show_question_only)
1085 {
1086 // get page object output
1087 $solutionoutput = $this->getILIASPage($solutionoutput);
1088 }
1089 return $solutionoutput;
1090 }
1091
1092 function getPreview($show_question_only = FALSE, $showInlineFeedback = false)
1093 {
1094 $user_solution = array();
1095
1096 if( is_object($this->getPreviewSession()) )
1097 {
1098 $solutions = (array)$this->getPreviewSession()->getParticipantsSolution();
1099
1100 foreach($solutions as $val1 => $val2)
1101 {
1102 if(preg_match("/^(\\\$v\\d+)$/", $val1, $matches))
1103 {
1104 $user_solution[$matches[1]] = $val2;
1105 }
1106 else if(preg_match("/^(\\\$r\\d+)$/", $val1, $matches))
1107 {
1108
1109 if(!array_key_exists($matches[1], $user_solution)) $user_solution[$matches[1]] = array();
1110 $user_solution[$matches[1]]["value"] = $val2;
1111 }
1112 else if(preg_match("/^(\\\$r\\d+)_unit$/", $val1, $matches))
1113 {
1114 if(!array_key_exists($matches[1], $user_solution)) $user_solution[$matches[1]] = array();
1115 $user_solution[$matches[1]]["unit"] = $val2;
1116 }
1117
1118 if(preg_match("/^(\\\$r\\d+)/", $val1, $matches) && $user_solution[$matches[1]]["result_type"] == 0)
1119 {
1120 $user_solution[$matches[1]]["result_type"] = assFormulaQuestionResult::getResultTypeByQstId($this->object->getId(), $val1);
1121 }
1122 }
1123 }
1124
1125 if( !$this->object->hasRequiredVariableSolutionValues($user_solution) )
1126 {
1127 $user_solution = $this->object->getInitialVariableSolutionValues();
1128
1129 if( is_object($this->getPreviewSession()) )
1130 {
1131 $this->getPreviewSession()->setParticipantsSolution($user_solution);
1132 }
1133 }
1134
1135 $template = new ilTemplate("tpl.il_as_qpl_formulaquestion_output.html", true, true, 'Modules/TestQuestionPool');
1136 if( is_object($this->getPreviewSession()) )
1137 {
1138 $questiontext = $this->object->substituteVariables($user_solution, false, false, false);
1139 }
1140 else
1141 {
1142 $questiontext = $this->object->substituteVariables(array());
1143 }
1144 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
1145 $questionoutput = $template->get();
1146 if(!$show_question_only)
1147 {
1148 // get page object output
1149 $questionoutput = $this->getILIASPage($questionoutput);
1150 }
1151 return $questionoutput;
1152 }
1153
1154 // hey: prevPassSolutions - pass will be always available from now on
1155 function getTestOutput($active_id, $pass, $is_postponed = FALSE, $use_post_solutions = FALSE, $show_feedback = FALSE)
1156 // hey.
1157 {
1158 ilUtil::sendInfo($this->lng->txt('enter_valid_values'));
1159 // get the solution of the user for the active pass or from the last pass if allowed
1160 $user_solution = array();
1161 if($active_id)
1162 {
1163 $solutions = (array)$this->getTestOutputSolutions($active_id, $pass);
1164
1165 $actualPassIndex = null;
1166 if( $this->isPreviousSolutionPrefilled() )
1167 {
1168 require_once 'Modules/Test/classes/class.ilObjTest.php';
1169 $actualPassIndex = ilObjTest::_getPass($active_id);
1170 }
1171
1172 foreach($solutions as $idx => $solution_value)
1173 {
1174 if(preg_match("/^(\\\$v\\d+)$/", $solution_value["value1"], $matches))
1175 {
1176 if( $this->isPreviousSolutionPrefilled() )
1177 {
1178 $this->object->saveCurrentSolution($active_id, $actualPassIndex, $matches[1], $solution_value["value2"], true);
1179 }
1180
1181 $user_solution[$matches[1]] = $solution_value["value2"];
1182 }
1183 else if(preg_match("/^(\\\$r\\d+)$/", $solution_value["value1"], $matches))
1184 {
1185
1186 if(!array_key_exists($matches[1], $user_solution)) $user_solution[$matches[1]] = array();
1187 $user_solution[$matches[1]]["value"] = $solution_value["value2"];
1188 }
1189 else if(preg_match("/^(\\\$r\\d+)_unit$/", $solution_value["value1"], $matches))
1190 {
1191 if(!array_key_exists($matches[1], $user_solution)) $user_solution[$matches[1]] = array();
1192 $user_solution[$matches[1]]["unit"] = $solution_value["value2"];
1193 }
1194
1195 if(preg_match("/^(\\\$r\\d+)/", $solution_value["value1"], $matches) && $user_solution[$matches[1]]["result_type"] == 0)
1196 {
1197 $user_solution[$matches[1]]["result_type"] = assFormulaQuestionResult::getResultTypeByQstId($this->object->getId(), $solution_value["value1"]);
1198 }
1199 }
1200 }
1201
1202 // fau: testNav - take question variables always from authorized solution because they are saved with this flag, even if an authorized solution is not saved
1203 $solutions = $this->object->getSolutionValues($active_id, $pass, true);
1204 foreach($solutions as $idx => $solution_value)
1205 {
1206 if (preg_match("/^(\\\$v\\d+)$/", $solution_value["value1"], $matches))
1207 {
1208 $user_solution[$matches[1]] = $solution_value["value2"];
1209 }
1210 }
1211
1212 if( !$this->object->hasRequiredVariableSolutionValues($user_solution) )
1213 {
1214 foreach($this->object->getInitialVariableSolutionValues() as $val1 => $val2)
1215 {
1216 $this->object->saveCurrentSolution($active_id, $pass, $val1, $val2, true);
1217 }
1218 }
1219
1220 // generate the question output
1221 $template = new ilTemplate("tpl.il_as_qpl_formulaquestion_output.html", true, true, 'Modules/TestQuestionPool');
1222
1223 $questiontext = $this->object->substituteVariables($user_solution);
1224
1225 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
1226
1227 $questionoutput = $template->get();
1228 $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1229 return $pageoutput;
1230 }
1231
1232 public function getSpecificFeedbackOutput($active_id, $pass)
1233 {
1234 return '';
1235 }
1236}
$result
$test
Definition: Utf8Test.php:85
$_GET["client_id"]
$_SESSION["AccountId"]
Single choice question GUI representation The assFormulaQuestionGUI class encapsulates the GUI repres...
getPreview($show_question_only=FALSE, $showInlineFeedback=false)
canUseAdvancedRating($result)
Check if advanced rating can be used for a result.
hasResultUnit($result, $unit_id, $resultunits)
suggestRange()
Suggest a range for a result @access public.
setQuestionTabs()
Sets the ILIAS tabs for this question type Sets the ILIAS tabs for this question type @access public.
getSolutionOutput( $active_id, $pass=NULL, $graphicalOutput=FALSE, $result_output=FALSE, $show_question_only=TRUE, $show_feedback=FALSE, $show_correct_solution=FALSE, $show_manual_scoring=FALSE, $show_question_text=TRUE)
Get the question solution output.
getSpecificFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
getTestOutput($active_id, $pass, $is_postponed=FALSE, $use_post_solutions=FALSE, $show_feedback=FALSE)
__construct($id=-1)
assFormulaQuestionGUI constructor The constructor takes possible arguments an creates an instance of ...
writePostData($always=false)
Evaluates a posted edit form and writes the form data in the question object.
static getResultTypeByQstId($a_qst_id, $a_result)
Class for single choice questions assFormulaQuestion is a class for single choice questions.
Basic GUI class for assessment questions.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
callNewIdListeners($a_new_id)
Call the new id listeners.
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
getILIASPage($html="")
Returns the ILIAS Page around a question.
getQuestionTemplate()
get question template
writePostData()
Evaluates a posted edit form and writes the form data in the question object.
getTestOutputSolutions($activeId, $pass)
addErrorMessage($errormessage)
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
addBackTab(ilTabsGUI $ilTabs)
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question,...
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
_questionExistsInTest($question_id, $test_id)
_isWriteable($question_id, $user_id)
Returns true if the question is writeable by a certain user.
This class represents a checkbox property in a property form.
This class represents a custom property in a property form.
This class represents a section header in a property form.
This class represents a hidden form property in a property form.
This class represents a multi selection list property in a property form.
This class represents a non editable value in a property form.
This class represents a number property in a property form.
_getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
_getPass($active_id)
Retrieves the actual pass of a given user for a given test.
This class represents a property form user interface.
This class represents a property in a property form.
This class represents an option in a radio group.
This class represents a selection list property in a property form.
special template class to simplify handling of ITX/PEAR
static getReturnToPageLink($q_id=null)
This class represents a text property in a property form.
static stripOnlySlashes($a_str)
strip slashes if magic qoutes is enabled
static sendSuccess($a_info="", $a_keep=false)
Send Success Message to Screen.
static redirect($a_script)
http redirect to other script
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
$_POST['username']
Definition: cron.php:12
$txt
Definition: error.php:12
$cmd
Definition: sahs_server.php:35
$results
$url
Definition: shib_logout.php:72
if($_REQUEST['ilias_path']) define('ILIAS_HTTP_PATH' $_REQUEST['ilias_path']
Definition: index.php:7
global $ilDB
$errors
global $ilUser
Definition: imgupload.php:15