ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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
23{
30 public function __construct($id = -1)
31 {
32 parent::__construct();
33 $this->object = new assFormulaQuestion();
34 $this->newUnitId = null;
35 if ($id >= 0) {
36 $this->object->loadFromDb($id);
37 }
38 }
39
45 public 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 $classname = $q_type . "GUI";
57 $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
58 $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
59 }
60
61 if ($_GET["q_id"]) {
62 if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
63 // edit page
64 $ilTabs->addTarget(
65 "edit_page",
66 $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
67 array("edit", "insert", "exec_pg"),
68 "",
69 "",
70 $force_active
71 );
72 }
73
74 $this->addTab_QuestionPreview($ilTabs);
75 }
76
77 $force_active = false;
78 if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
79 $url = "";
80
81 if ($classname) {
82 $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
83 }
84 $commands = $_POST["cmd"];
85 if (is_array($commands)) {
86 foreach ($commands as $key => $value) {
87 if (preg_match("/^suggestrange_.*/", $key, $matches)) {
88 $force_active = true;
89 }
90 }
91 }
92 // edit question properties
93 $ilTabs->addTarget(
94 "edit_properties",
95 $url,
96 array(
97 "editQuestion", "save", "cancel", "addSuggestedSolution",
98 "cancelExplorer", "linkChilds", "removeSuggestedSolution",
99 "parseQuestion", "saveEdit", "suggestRange"
100 ),
101 $classname,
102 "",
103 $force_active
104 );
105 }
106
107 if ($_GET["q_id"]) {
108 // add tab for question feedback within common class assQuestionGUI
109 $this->addTab_QuestionFeedback($ilTabs);
110 }
111
112 if ($_GET["q_id"]) {
113 // add tab for question hint within common class assQuestionGUI
114 $this->addTab_QuestionHints($ilTabs);
115 }
116
117 // Unit editor
118 if ($_GET['q_id']) {
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 $ilTabs->addTarget(
126 "statistics",
127 $this->ctrl->getLinkTargetByClass($classname, "assessment"),
128 array("assessment"),
129 $classname,
130 ""
131 );
132 }
133
134 $this->addBackTab($ilTabs);
135 }
136
137 public function getCommand($cmd)
138 {
139 if (preg_match("/suggestrange_(.*?)/", $cmd, $matches)) {
140 $cmd = "suggestRange";
141 }
142 return $cmd;
143 }
144
149 public function suggestRange()
150 {
151 if ($this->writePostData()) {
153 }
154 $this->editQuestion();
155 }
156
160 protected function writePostData($always = false)
161 {
162 $hasErrors = (!$always) ? $this->editQuestion(true) : false;
163 $checked = true;
164 if (!$hasErrors) {
165 $this->object->setTitle($_POST["title"]);
166 $this->object->setAuthor($_POST["author"]);
167 $this->object->setComment($_POST["comment"]);
168 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
169 $questiontext = ilUtil::stripOnlySlashes($_POST["question"]);
170 $this->object->setQuestion($questiontext);
171 $this->object->setEstimatedWorkingTime(
172 $_POST["Estimated"]["hh"],
173 $_POST["Estimated"]["mm"],
174 $_POST["Estimated"]["ss"]
175 );
176
177 $this->object->parseQuestionText();
178 $found_vars = array();
179 $found_results = array();
180
181
182 foreach ($_POST as $key => $value) {
183 if (preg_match("/^unit_(\\\$v\d+)$/", $key, $matches)) {
184 array_push($found_vars, $matches[1]);
185 }
186 if (preg_match("/^unit_(\\\$r\d+)$/", $key, $matches)) {
187 array_push($found_results, $matches[1]);
188 }
189 }
190
191 // if(!$this->object->checkForDuplicateVariables())
192 // {
193//
194 // $this->addErrorMessage($this->lng->txt("err_duplicate_variables"));
195 // $checked = FALSE;
196 // }
197 if (!$this->object->checkForDuplicateResults()) {
198 $this->addErrorMessage($this->lng->txt("err_duplicate_results"));
199 $checked = false;
200 }
201
202 foreach ($found_vars as $variable) {
203 if ($this->object->getVariable($variable) != null) {
204 $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"]);
205 $varObj->setRangeMinTxt($_POST["range_min_$variable"]);
206 $varObj->setRangeMaxTxt($_POST["range_max_$variable"]);
207 $this->object->addVariable($varObj);
208 }
209 }
210
211 $tmp_form_vars = array();
212 $tmp_quest_vars = array();
213 foreach ($found_results as $result) {
214 $tmp_res_match = preg_match_all("/([$][v][0-9]*)/", $_POST["formula_$result"], $form_vars);
215 $tmp_form_vars = array_merge($tmp_form_vars, $form_vars[0]);
216
217 $tmp_que_match = preg_match_all("/([$][v][0-9]*)/", $_POST['question'], $quest_vars);
218 $tmp_quest_vars= array_merge($tmp_quest_vars, $quest_vars[0]);
219 }
220 $result_has_undefined_vars = array_diff($tmp_form_vars, $found_vars);
221 $question_has_unused_vars = array_diff($tmp_quest_vars, $tmp_form_vars);
222
223 if (count($result_has_undefined_vars) > 0 || count($question_has_unused_vars) > 0) {
224 $error_message = '';
225 if (count($result_has_undefined_vars) > 0) {
226 $error_message .= $this->lng->txt("res_contains_undef_var") . '<br>';
227 }
228 if (count($question_has_unused_vars) > 0) {
229 $error_message .= $this->lng->txt("que_contains_unused_var");
230 }
231 $checked = false;
232 if ($this->isSaveCommand()) {
233 ilUtil::sendFailure($error_message);
234 }
235 }
236 foreach ($found_results as $result) {
237 if (is_object($this->object->getUnitrepository()->getUnit($_POST["unit_$result"]))) {
238 $tmp_result_unit = $this->object->getUnitrepository()->getUnit($_POST["unit_$result"]);
239 } else {
240 $tmp_result_unit = null;
241 }
242
243 if ($this->object->getResult($result) != null) {
244 $use_simple_rating = ($_POST["rating_advanced_$result"] == 1) ? false : true;
245 $resObj = new assFormulaQuestionResult(
246 $result,
247 $_POST["range_min_$result"],
248 $_POST["range_max_$result"],
249 $_POST["tolerance_$result"],
250 $tmp_result_unit,
251 $_POST["formula_$result"],
252 $_POST["points_$result"],
253 $_POST["precision_$result"],
254 $use_simple_rating,
255 ($_POST["rating_advanced_$result"] == 1) ? $_POST["rating_sign_$result"] : "",
256 ($_POST["rating_advanced_$result"] == 1) ? $_POST["rating_value_$result"] : "",
257 ($_POST["rating_advanced_$result"] == 1) ? $_POST["rating_unit_$result"] : "",
258 $_POST["result_type_$result"] != 0 ? $_POST["result_type_$result"] : 0
259 );
260 $resObj->setRangeMinTxt($_POST["range_min_$result"]);
261 $resObj->setRangeMaxTxt($_POST["range_max_$result"]);
262 $this->object->addResult($resObj);
263 $this->object->addResultUnits($resObj, $_POST["units_$result"]);
264 }
265 }
266 if ($checked == false) {
267 return 1;
268 } else {
270 return 0;
271 }
272 } else {
273 return 1;
274 }
275 }
276
277 public function resetSavedPreviewSession()
278 {
279 global $ilUser;
280 $user_id = $ilUser->getId();
281 $question_id = $this->object->getId();
282 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewSession.php';
283 $ilAssQuestionPreviewSession = new ilAssQuestionPreviewSession($user_id, $question_id);
284 $ilAssQuestionPreviewSession->setParticipantsSolution(array());
285 }
286
287 public function isSaveCommand()
288 {
289 return in_array($this->ctrl->getCmd(), array('saveFQ', 'saveEdit', 'saveReturnFQ'));
290 }
291
297 public function editQuestion($checkonly = false)
298 {
299 $save = $this->isSaveCommand();
300
301 $this->getQuestionTemplate();
302
303 include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
304 $form = new ilPropertyFormGUI();
305 $this->editForm = $form;
306
307 $form->setFormAction($this->ctrl->getFormAction($this));
308 $form->setTitle($this->outQuestionType());
309 $form->setMultipart(false);
310 $form->setTableWidth('100%');
311 $form->setId('assformulaquestion');
312
313 // title, author, description, question, working time (assessment mode)
315
316 // Add info text
317 $question = $form->getItemByPostVar('question');
318 $question->setInfo($this->lng->txt('fq_question_desc'));
319
320 $variables = $this->object->getVariables();
321 $categorized_units = $this->object->getUnitrepository()->getCategorizedUnits();
322 $result_units = $this->object->__get('resultunits');
323
324 $unit_options = array();
325 $category_name = '';
326 $new_category = false;
327 foreach ((array) $categorized_units as $item) {
331 if ($item instanceof assFormulaQuestionUnitCategory) {
332 if ($category_name != $item->getDisplayString()) {
333 $new_category = true;
334 $category_name = $item->getDisplayString();
335 }
336 continue;
337 }
338 $unit_options[$item->getId()] = $item->getDisplayString() . ($new_category ? ' (' . $category_name . ')' : '');
339 $new_category = false;
340 }
341
342 if (count($variables)) {
343 uasort($variables, function (assFormulaQuestionVariable $v1, assFormulaQuestionVariable $v2) {
344 $num_v1 = (int) substr($v1->getVariable(), 2);
345 $num_v2 = (int) substr($v2->getVariable(), 2);
346 if ($num_v1 > $num_v2) {
347 return 1;
348 } elseif ($num_v1 < $num_v2) {
349 return -1;
350 }
351
352 return 0;
353 });
354
355 foreach ($variables as $variable) {
359 $variable_header = new ilFormSectionHeaderGUI();
360 $variable_header->setTitle(sprintf($this->lng->txt('variable_x'), $variable->getVariable()));
361
362 $range_min = new ilNumberInputGUI($this->lng->txt('range_min'), 'range_min_' . $variable->getVariable());
363 $range_min->allowDecimals(true);
364 $range_min->setSize(3);
365 $range_min->setRequired(true);
366 $range_min->setValue($variable->getRangeMin());
367
368 $range_max = new ilNumberInputGUI($this->lng->txt('range_max'), 'range_max_' . $variable->getVariable());
369 $range_max->allowDecimals(true);
370 $range_max->setSize(3);
371 $range_max->setRequired(true);
372 $range_max->setValue($variable->getRangeMax());
373
374 $units = new ilSelectInputGUI($this->lng->txt('unit'), 'unit_' . $variable->getVariable());
375 $units->setOptions(array(0 => $this->lng->txt('no_selection')) + $unit_options);
376 if (is_object($variable->getUnit())) {
377 $units->setValue($variable->getUnit()->getId());
378 }
379
380 $precision = new ilNumberInputGUI($this->lng->txt('precision'), 'precision_' . $variable->getVariable());
381 $precision->setRequired(true);
382 $precision->setSize(3);
383 $precision->setMinValue(0);
384 $precision->setValue($variable->getPrecision());
385 $precision->setInfo($this->lng->txt('fq_precision_info'));
386
387 $intprecision = new ilNumberInputGUI($this->lng->txt('intprecision'), 'intprecision_' . $variable->getVariable());
388 $intprecision->setSize(3);
389 $intprecision->setMinValue(1);
390 $intprecision->setValue($variable->getIntprecision());
391 $intprecision->setInfo($this->lng->txt('intprecision_info'));
392
393 $form->addItem($variable_header);
394 $form->addItem($range_min);
395 $form->addItem($range_max);
396 $form->addItem($units);
397 $form->addItem($precision);
398 $form->addItem($intprecision);
399 }
400 }
401
402 $results = $this->object->getResults();
403 if (count($results)) {
404 require_once 'Services/Form/classes/class.ilMultiSelectInputGUI.php';
405
407 $num_r1 = (int) substr($r1->getResult(), 2);
408 $num_r2 = (int) substr($r2->getResult(), 2);
409 if ($num_r1 > $num_r2) {
410 return 1;
411 } elseif ($num_r1 < $num_r2) {
412 return -1;
413 }
414
415 return 0;
416 });
417
418 foreach ($results as $result) {
422 $result_header = new ilFormSectionHeaderGUI();
423 $result_header->setTitle(sprintf($this->lng->txt('result_x'), $result->getResult()));
424
425 $formula = new ilTextInputGUI($this->lng->txt('formula'), 'formula_' . $result->getResult());
426 $formula->setInfo($this->lng->txt('fq_formula_desc'));
427 $formula->setRequired(true);
428 $formula->setSize(50);
429 $formula->setValue($result->getFormula());
430 $formula->setSuffix(' = ' . $result->getResult());
431
432 if (
433 preg_match("/suggestrange_(.*)/", $this->ctrl->getCmd(), $matches) &&
434 strcmp($matches[1], $result->getResult()) == 0
435 ) {
436 // suggest a range for the result
437 if (strlen($result->substituteFormula($variables, $results))) {
438 $result->suggestRange($variables, $results);
439 }
440 }
441
442 $range_min = new ilNumberInputGUI($this->lng->txt('range_min'), 'range_min_' . $result->getResult());
443 $range_min->allowDecimals(true);
444 $range_min->setSize(3);
445 $range_min->setRequired(true);
446 $range_min->setValue($result->getRangeMin());
447
448 $range_max = new ilNumberInputGUI($this->lng->txt('range_max'), 'range_max_' . $result->getResult());
449 $range_max->allowDecimals(true);
450 $range_max->setSize(3);
451 $range_max->setRequired(true);
452 $range_max->setValue($result->getRangeMax());
453
454 $matches = array();
455
456 $precision = new ilNumberInputGUI($this->lng->txt('precision'), 'precision_' . $result->getResult());
457 $precision->setRequired(true);
458 $precision->setSize(3);
459 $precision->setMinValue(0);
460 $precision->setInfo($this->lng->txt('fq_precision_info'));
461 $precision->setValue($result->getPrecision());
462
463 $tolerance = new ilNumberInputGUI($this->lng->txt('tolerance'), 'tolerance_' . $result->getResult());
464 $tolerance->setSize(3);
465 $tolerance->setMinValue(0);
466 $tolerance->setMaxValue(100);
467 $tolerance->allowDecimals(false);
468 $tolerance->setInfo($this->lng->txt('tolerance_info'));
469 $tolerance->setValue($result->getTolerance());
470
471 $suggest_range_button = new ilCustomInputGUI('', '');
472 $suggest_range_button->setHtml('<input type="submit" class="btn btn-default" name="cmd[suggestrange_' . $result->getResult() . ']" value="' . $this->lng->txt("suggest_range") . '" />');
473
474 $sel_result_units = new ilSelectInputGUI($this->lng->txt('unit'), 'unit_' . $result->getResult());
475 $sel_result_units->setOptions(array(0 => $this->lng->txt('no_selection')) + $unit_options);
476 $sel_result_units->setInfo($this->lng->txt('result_unit_info'));
477 if (is_object($result->getUnit())) {
478 $sel_result_units->setValue($result->getUnit()->getId());
479 }
480
481 $mc_result_units = new ilMultiSelectInputGUI($this->lng->txt('result_units'), 'units_' . $result->getResult());
482 $mc_result_units->setOptions($unit_options);
483 $mc_result_units->setInfo($this->lng->txt('result_units_info'));
484 $selectedvalues = array();
485 foreach ($unit_options as $unit_id => $txt) {
486 if ($this->hasResultUnit($result, $unit_id, $result_units)) {
487 $selectedvalues[] = $unit_id;
488 }
489 }
490 $mc_result_units->setValue($selectedvalues);
491
492 $result_type = new ilRadioGroupInputGUI($this->lng->txt('result_type_selection'), 'result_type_' . $result->getResult());
493 $result_type->setRequired(true);
494
495 $no_type = new ilRadioOption($this->lng->txt('no_result_type'), 0);
496 $no_type->setInfo($this->lng->txt('fq_no_restriction_info'));
497
498 $result_dec = new ilRadioOption($this->lng->txt('result_dec'), 1);
499 $result_dec->setInfo($this->lng->txt('result_dec_info'));
500
501 $result_frac = new ilRadioOption($this->lng->txt('result_frac'), 2);
502 $result_frac->setInfo($this->lng->txt('result_frac_info'));
503
504 $result_co_frac = new ilRadioOption($this->lng->txt('result_co_frac'), 3);
505 $result_co_frac->setInfo($this->lng->txt('result_co_frac_info'));
506
507 $result_type->addOption($no_type);
508 $result_type->addOption($result_dec);
509 $result_type->addOption($result_frac);
510 $result_type->addOption($result_co_frac);
511 $result_type->setValue(strlen($result->getResultType()) ? $result->getResultType() : 0);
512
513 $points = new ilNumberInputGUI($this->lng->txt('points'), 'points_' . $result->getResult());
514 $points->allowDecimals(true);
515 $points->setRequired(true);
516 $points->setSize(3);
517 $points->setMinValue(0);
518 $points->setValue(strlen($result->getPoints()) ? $result->getPoints() : 1);
519
520 $rating_type = new ilCheckboxInputGUI($this->lng->txt('advanced_rating'), 'rating_advanced_' . $result->getResult());
521 $rating_type->setValue(1);
522 $rating_type->setInfo($this->lng->txt('advanced_rating_info'));
523
524 if (!$save) {
525 $advanced_rating = $this->canUseAdvancedRating($result);
526 if (!$advanced_rating) {
527 $rating_type->setDisabled(true);
528 $rating_type->setChecked(false);
529 } else {
530 $rating_type->setChecked(strlen($result->getRatingSimple()) && $result->getRatingSimple() ? false : true);
531 }
532 }
533
534 $sign = new ilNumberInputGUI($this->lng->txt('rating_sign'), 'rating_sign_' . $result->getResult());
535 $sign->setRequired(true);
536 $sign->setSize(3);
537 $sign->setMinValue(0);
538 $sign->setValue($result->getRatingSign());
539 $rating_type->addSubItem($sign);
540
541 $value = new ilNumberInputGUI($this->lng->txt('rating_value'), 'rating_value_' . $result->getResult());
542 $value->setRequired(true);
543 $value->setSize(3);
544 $value->setMinValue(0);
545 $value->setValue($result->getRatingValue());
546 $rating_type->addSubItem($value);
547
548 $unit = new ilNumberInputGUI($this->lng->txt('rating_unit'), 'rating_unit_' . $result->getResult());
549 $unit->setRequired(true);
550 $unit->setSize(3);
551 $unit->setMinValue(0);
552 $unit->setValue($result->getRatingUnit());
553 $rating_type->addSubItem($unit);
554
555 $info_text = new ilNonEditableValueGUI($this->lng->txt('additional_rating_info'));
556 $rating_type->addSubItem($info_text);
557
558 $form->addItem($result_header);
559 $form->addItem($formula);
560 $form->addItem($range_min);
561 $form->addItem($range_max);
562 $form->addItem($suggest_range_button);
563 $form->addItem($precision);
564 $form->addItem($tolerance);
565 $form->addItem($sel_result_units);
566 $form->addItem($mc_result_units);
567 $form->addItem($result_type);
568 $form->addItem($points);
569 $form->addItem($rating_type);
570 }
571
572 $defined_result_vars = array();
573 $quest_vars = array();
574
575 $defined_result_res = array();
576 $result_vars = array();
577
578 foreach ($variables as $key => $object) {
579 $quest_vars[$key] = $key;
580 }
581
582 foreach ($results as $key => $object) {
583 $result_vars[$key] = $key;
584 }
585
586 foreach ($results as $tmp_result) {
590 $formula = $tmp_result->getFormula();
591
592 preg_match_all("/([$][v][0-9]*)/", $formula, $form_vars);
593 preg_match_all("/([$][r][0-9]*)/", $formula, $form_res);
594 foreach ($form_vars[0] as $res_var) {
595 $defined_result_vars[$res_var] = $res_var;
596 }
597
598 foreach ($form_res[0] as $res_res) {
599 $defined_result_res[$res_res] = $res_res;
600 }
601 }
602 }
603
604 $result_has_undefined_vars = array();
605 $question_has_unused_vars = array();
606
607 if (is_array($quest_vars) && count($quest_vars) > 0) {
608 $result_has_undefined_vars = array_diff($defined_result_vars, $quest_vars);
609 $question_has_unused_vars = array_diff($quest_vars, $defined_result_vars);
610 }
611
612 if (is_array($result_vars) && count($result_vars) > 0) {
613 $result_has_undefined_res = array_diff($defined_result_res, $result_vars);
614 }
615 $error_message = '';
616
617 if (count($result_has_undefined_vars) > 0 || count($question_has_unused_vars) > 0) {
618 if (count($result_has_undefined_vars) > 0) {
619 $error_message .= $this->lng->txt("res_contains_undef_var") . '<br>';
620 }
621 if (count($question_has_unused_vars) > 0) {
622 $error_message .= $this->lng->txt("que_contains_unused_var") . '<br>';
623 }
624
625 $checked = false;
626 if ($save) {
627 ilUtil::sendFailure($error_message);
628 }
629 }
630
631 if (is_array($result_has_undefined_res) && count($result_has_undefined_res) > 0) {
632 $error_message .= $this->lng->txt("res_contains_undef_res") . '<br>';
633 $checked = false;
634 }
635
636 if ($save && !$checked) {
637 ilUtil::sendFailure($error_message);
638 }
639
640 if ($this->object->getId()) {
641 $hidden = new ilHiddenInputGUI("", "ID");
642 $hidden->setValue($this->object->getId());
643 $form->addItem($hidden);
644 }
645
647
648 $form->addCommandButton('parseQuestion', $this->lng->txt("parseQuestion"));
649 $form->addCommandButton('saveReturnFQ', $this->lng->txt("save_return"));
650 $form->addCommandButton('saveFQ', $this->lng->txt("save"));
651
652 $errors = $checked;
653
654 if ($save) {
655 $found_vars = array();
656 $found_results = array();
657 foreach ((array) $_POST as $key => $value) {
658 if (preg_match("/^unit_(\\\$v\d+)$/", $key, $matches)) {
659 array_push($found_vars, $matches[1]);
660 }
661 if (preg_match("/^unit_(\\\$r\d+)$/", $key, $matches)) {
662 array_push($found_results, $matches[1]);
663 }
664 }
665
666 $form->setValuesByPost();
667 $errors = !$form->checkInput();
668
669 $custom_errors = false;
670 if (count($variables)) {
671 foreach ($variables as $variable) {
675 $min_range = $form->getItemByPostVar('range_min_' . $variable->getVariable());
676 $max_range = $form->getItemByPostVar('range_max_' . $variable->getVariable());
677 if ($min_range->getValue() > $max_range->getValue()) {
678 $min_range->setAlert($this->lng->txt('err_range'));
679 $max_range->setAlert($this->lng->txt('err_range'));
680 $custom_errors = true;
681 }
682 }
683 }
684
685 if (count($results)) {
686 foreach ($results as $result) {
690 $min_range = $form->getItemByPostVar('range_min_' . $result->getResult());
691 $max_range = $form->getItemByPostVar('range_max_' . $result->getResult());
692 if ($min_range->getValue() > $max_range->getValue()) {
693 $min_range->setAlert($this->lng->txt('err_range'));
694 $max_range->setAlert($this->lng->txt('err_range'));
695 $custom_errors = true;
696 }
697
698
699 $formula = $form->getItemByPostVar('formula_' . $result->getResult());
700 if (strpos($formula->getValue(), $result->getResult()) !== false) {
701 $formula->setAlert($this->lng->txt('errRecursionInResult'));
702 $custom_errors = true;
703 }
704
705 $result_unit = $form->getItemByPostVar('unit_' . $result->getResult());
706 $rating_advanced = $form->getItemByPostVar('rating_advanced_' . $result->getResult());
707 if (((int) $result_unit->getValue() <= 0) && $rating_advanced->getChecked()) {
708 unset($_POST['rating_advanced_' . $result->getResult()]);
709 $rating_advanced->setDisabled(true);
710 $rating_advanced->setChecked(false);
711 $rating_advanced->setAlert($this->lng->txt('err_rating_advanced_not_allowed'));
712 $custom_errors = true;
713 } elseif ($rating_advanced->getChecked()) {
714 $rating_sign = $form->getItemByPostVar('rating_sign_' . $result->getResult());
715 $rating_value = $form->getItemByPostVar('rating_value_' . $result->getResult());
716 $rating_unit = $form->getItemByPostVar('rating_unit_' . $result->getResult());
717
718 $percentage = $rating_sign->getValue() + $rating_value->getValue() + $rating_unit->getValue();
719 if ($percentage != 100) {
720 $rating_advanced->setAlert($this->lng->txt('err_wrong_rating_advanced'));
721 $custom_errors = true;
722 }
723 }
724
725 preg_match_all("/([$][v][0-9]*)/", $formula->getValue(), $form_vars);
726 $result_has_undefined_vars = array_diff($form_vars[0], (array) $found_vars);
727 if (count($result_has_undefined_vars)) {
728 $errors = true;
729 ilUtil::sendInfo($this->lng->txt('res_contains_undef_var'));
730 }
731 }
732 }
733
734 if ($custom_errors && !$errors) {
735 $errors = true;
736 ilUtil::sendFailure($this->lng->txt('form_input_not_valid'));
737 }
738 $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
739 if ($errors) {
740 $checkonly = false;
741 }
742 }
743
744 if (!$checkonly) {
745 $this->tpl->setVariable('QUESTION_DATA', $form->getHTML());
746 }
747 return $errors;
748 }
749
750 private function hasResultUnit($result, $unit_id, $resultunits)
751 {
752 if (array_key_exists($result->getResult(), $resultunits)) {
753 if (array_key_exists($unit_id, $resultunits[$result->getResult()])) {
754 return true;
755 }
756 }
757 return false;
758 }
759
768 {
769 $resultunit = $result->getUnit();
770
771 /*
772 * if there is a result-unit (unit selectbox) selected it is possible to use advanced rating
773 * if there is no result-unit selected it is NOT possible to use advanced rating, because there is no
774 * definition if the result-value or the unit-value should be the correct solution!!
775 *
776 */
777 if (is_object($resultunit)) {
778 return true;
779 } else {
780 return false;
781 }
782 }
783
784 public function parseQuestion()
785 {
786 $this->writePostData();
787 $this->editQuestion();
788 }
789
790 public function saveReturnFQ()
791 {
792 global $ilUser;
793 $old_id = $_GET["q_id"];
794 $result = $this->writePostData();
795 if ($result == 0) {
796 $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
797 $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
799 $this->object->saveToDb();
800 $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
801 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
802 if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
803 $this->ctrl->redirect($this, "originalSyncForm");
804 return;
805 } elseif ($_GET["calling_test"]) {
806 require_once 'Modules/Test/classes/class.ilObjTest.php';
807 $test = new ilObjTest($_GET["calling_test"]);
808 #var_dump(assQuestion::_questionExistsInTest($this->object->getId(), $test->getTestId()));
809 $q_id = $this->object->getId();
810 if (!assQuestion::_questionExistsInTest($this->object->getId(), $test->getTestId())) {
811 global $tree, $ilDB, $ilPluginAdmin;
812
813 include_once("./Modules/Test/classes/class.ilObjTest.php");
814 $_GET["ref_id"] = $_GET["calling_test"];
815 $test = new ilObjTest($_GET["calling_test"], true);
816
817 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
818 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
819
820 $new_id = $test->insertQuestion(
821 $testQuestionSetConfigFactory->getQuestionSetConfig(),
822 $this->object->getId()
823 );
824
825 $q_id = $new_id;
826 if (isset($_REQUEST['prev_qid'])) {
827 $test->moveQuestionAfter($this->object->getId() + 1, $_REQUEST['prev_qid']);
828 }
829
830 $this->ctrl->setParameter($this, 'q_id', $new_id);
831 $this->ctrl->setParameter($this, 'calling_test', $_GET['calling_test']);
832 #$this->ctrl->setParameter($this, 'test_ref_id', false);
833 }
834 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
835 if ($_REQUEST['test_express_mode']) {
837 } else {
838 ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["calling_test"]);
839 }
840 } else {
841 if ($this->object->getId() != $old_id) {
842 $this->callNewIdListeners($this->object->getId());
843 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
844 $this->ctrl->redirectByClass("ilobjquestionpoolgui", "questions");
845 }
846 if (strcmp($_SESSION["info"], "") != 0) {
847 ilUtil::sendSuccess($_SESSION["info"] . "<br />" . $this->lng->txt("msg_obj_modified"), true);
848 } else {
849 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
850 }
851 $this->ctrl->redirectByClass("ilobjquestionpoolgui", "questions");
852 }
853 } else {
854 $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
855 $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
856 $this->object->saveToDb();
857 $this->editQuestion();
858 }
859 }
860
861 public function saveFQ()
862 {
863 $result = $this->writePostData();
864
865 if ($result == 1) {
866 $this->editQuestion();
867 } else {
869 $this->save();
870 }
871 }
875 public function checkInput()
876 {
877 if ((!$_POST["title"]) or (!$_POST["author"]) or (!$_POST["question"])) {
878 $this->addErrorMessage($this->lng->txt("fill_out_all_required_fields"));
879 return false;
880 }
881
882
883 return true;
884 }
885
898 public function getSolutionOutput(
899 $active_id,
900 $pass = null,
901 $graphicalOutput = false,
902 $result_output = false,
903 $show_question_only = true,
904 $show_feedback = false,
905 $show_correct_solution = false,
906 $show_manual_scoring = false,
907 $show_question_text = true
908 ) {
909 // get the solution of the user for the active pass or from the last pass if allowed
910 $user_solution = array();
911 if (($active_id > 0) && (!$show_correct_solution)) {
912 $solutions = array();
913 include_once "./Modules/Test/classes/class.ilObjTest.php";
914 if (!ilObjTest::_getUsePreviousAnswers($active_id, true)) {
915 if (is_null($pass)) {
916 $pass = ilObjTest::_getPass($active_id);
917 }
918 }
919 $user_solution["active_id"] = $active_id;
920 $user_solution["pass"] = $pass;
921 $solutions =&$this->object->getSolutionValues($active_id, $pass);
922 foreach ($solutions as $idx => $solution_value) {
923 if (preg_match("/^(\\\$v\\d+)$/", $solution_value["value1"], $matches)) {
924 $user_solution[$matches[1]] = $solution_value["value2"];
925 } elseif (preg_match("/^(\\\$r\\d+)$/", $solution_value["value1"], $matches)) {
926 if (!array_key_exists($matches[1], $user_solution)) {
927 $user_solution[$matches[1]] = array();
928 }
929 $user_solution[$matches[1]]["value"] = $solution_value["value2"];
930 } elseif (preg_match("/^(\\\$r\\d+)_unit$/", $solution_value["value1"], $matches)) {
931 if (!array_key_exists($matches[1], $user_solution)) {
932 $user_solution[$matches[1]] = array();
933 }
934 $user_solution[$matches[1]]["unit"] = $solution_value["value2"];
935 }
936 }
937 } elseif ($active_id) {
938 $solutions = null;
939 include_once "./Modules/Test/classes/class.ilObjTest.php";
940 if (!ilObjTest::_getUsePreviousAnswers($active_id, true)) {
941 if (is_null($pass)) {
942 $pass = ilObjTest::_getPass($active_id);
943 }
944 }
945 $user_solution = (array) $this->object->getBestSolution($this->object->getSolutionValues($active_id, $pass));
946 } elseif (is_object($this->getPreviewSession())) {
947 $solutionValues = array();
948
949 foreach ($this->getPreviewSession()->getParticipantsSolution() as $val1 => $val2) {
950 $solutionValues[] = array('value1' => $val1, 'value2' => $val2);
951 }
952
953 $user_solution = (array) $this->object->getBestSolution($solutionValues);
954 }
955
956 $template = new ilTemplate("tpl.il_as_qpl_formulaquestion_output_solution.html", true, true, 'Modules/TestQuestionPool');
957 $questiontext = $this->object->substituteVariables($user_solution, $graphicalOutput, true, $result_output);
958
959 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
960 $questionoutput = $template->get();
961 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
962 $feedback = ($show_feedback) ? $this->getGenericFeedbackOutput($active_id, $pass) : "";
963 if (strlen($feedback)) {
964 $cssClass = (
965 $this->hasCorrectSolution($active_id, $pass) ?
967 );
968
969 $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
970 $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
971 }
972 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
973
974 $solutionoutput = $solutiontemplate->get();
975 if (!$show_question_only) {
976 // get page object output
977 $solutionoutput = $this->getILIASPage($solutionoutput);
978 }
979 return $solutionoutput;
980 }
981
982 public function getPreview($show_question_only = false, $showInlineFeedback = false)
983 {
984 $user_solution = array();
985
986 if (is_object($this->getPreviewSession())) {
987 $solutions = (array) $this->getPreviewSession()->getParticipantsSolution();
988
989 foreach ($solutions as $val1 => $val2) {
990 if (preg_match("/^(\\\$v\\d+)$/", $val1, $matches)) {
991 $user_solution[$matches[1]] = $val2;
992 } elseif (preg_match("/^(\\\$r\\d+)$/", $val1, $matches)) {
993 if (!array_key_exists($matches[1], $user_solution)) {
994 $user_solution[$matches[1]] = array();
995 }
996 $user_solution[$matches[1]]["value"] = $val2;
997 } elseif (preg_match("/^(\\\$r\\d+)_unit$/", $val1, $matches)) {
998 if (!array_key_exists($matches[1], $user_solution)) {
999 $user_solution[$matches[1]] = array();
1000 }
1001 $user_solution[$matches[1]]["unit"] = $val2;
1002 }
1003
1004 if (preg_match("/^(\\\$r\\d+)/", $val1, $matches) && $user_solution[$matches[1]]["result_type"] == 0) {
1005 $user_solution[$matches[1]]["result_type"] = assFormulaQuestionResult::getResultTypeByQstId($this->object->getId(), $val1);
1006 }
1007 }
1008 }
1009
1010 if (!$this->object->hasRequiredVariableSolutionValues($user_solution)) {
1011 $user_solution = $this->object->getInitialVariableSolutionValues();
1012
1013 if (is_object($this->getPreviewSession())) {
1014 $this->getPreviewSession()->setParticipantsSolution($user_solution);
1015 }
1016 }
1017
1018 $template = new ilTemplate("tpl.il_as_qpl_formulaquestion_output.html", true, true, 'Modules/TestQuestionPool');
1019 if (is_object($this->getPreviewSession())) {
1020 $questiontext = $this->object->substituteVariables($user_solution, false, false, false);
1021 } else {
1022 $questiontext = $this->object->substituteVariables(array());
1023 }
1024 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
1025 $questionoutput = $template->get();
1026 if (!$show_question_only) {
1027 // get page object output
1028 $questionoutput = $this->getILIASPage($questionoutput);
1029 }
1030 return $questionoutput;
1031 }
1032
1033 // hey: prevPassSolutions - pass will be always available from now on
1034 public function getTestOutput($active_id, $pass, $is_postponed = false, $use_post_solutions = false, $show_feedback = false)
1035 // hey.
1036 {
1037 ilUtil::sendInfo($this->lng->txt('enter_valid_values'));
1038 // get the solution of the user for the active pass or from the last pass if allowed
1039 $user_solution = array();
1040 if ($active_id) {
1041 $solutions = (array) $this->object->getTestOutputSolutions($active_id, $pass);
1042
1043 $actualPassIndex = null;
1044 if ($this->object->getTestPresentationConfig()->isSolutionInitiallyPrefilled()) {
1045 require_once 'Modules/Test/classes/class.ilObjTest.php';
1046 $actualPassIndex = ilObjTest::_getPass($active_id);
1047 }
1048
1049 foreach ($solutions as $idx => $solution_value) {
1050 if (preg_match("/^(\\\$v\\d+)$/", $solution_value["value1"], $matches)) {
1051 if ($this->object->getTestPresentationConfig()->isSolutionInitiallyPrefilled()) {
1052 $this->object->saveCurrentSolution($active_id, $actualPassIndex, $matches[1], $solution_value["value2"], true);
1053 }
1054
1055 $user_solution[$matches[1]] = $solution_value["value2"];
1056 } elseif (preg_match("/^(\\\$r\\d+)$/", $solution_value["value1"], $matches)) {
1057 if (!array_key_exists($matches[1], $user_solution)) {
1058 $user_solution[$matches[1]] = array();
1059 }
1060 $user_solution[$matches[1]]["value"] = $solution_value["value2"];
1061 } elseif (preg_match("/^(\\\$r\\d+)_unit$/", $solution_value["value1"], $matches)) {
1062 if (!array_key_exists($matches[1], $user_solution)) {
1063 $user_solution[$matches[1]] = array();
1064 }
1065 $user_solution[$matches[1]]["unit"] = $solution_value["value2"];
1066 }
1067
1068 if (preg_match("/^(\\\$r\\d+)/", $solution_value["value1"], $matches) && $user_solution[$matches[1]]["result_type"] == 0) {
1069 $user_solution[$matches[1]]["result_type"] = assFormulaQuestionResult::getResultTypeByQstId($this->object->getId(), $solution_value["value1"]);
1070 }
1071 }
1072 }
1073
1074 // fau: testNav - take question variables always from authorized solution because they are saved with this flag, even if an authorized solution is not saved
1075 $solutions = $this->object->getSolutionValues($active_id, $pass, true);
1076 foreach ($solutions as $idx => $solution_value) {
1077 if (preg_match("/^(\\\$v\\d+)$/", $solution_value["value1"], $matches)) {
1078 $user_solution[$matches[1]] = $solution_value["value2"];
1079 }
1080 }
1081 // fau.
1082
1083 if (!$this->object->hasRequiredVariableSolutionValues($user_solution)) {
1084 foreach ($this->object->getInitialVariableSolutionValues() as $val1 => $val2) {
1085 $this->object->saveCurrentSolution($active_id, $pass, $val1, $val2, true);
1086 }
1087 }
1088
1089 // generate the question output
1090 $template = new ilTemplate("tpl.il_as_qpl_formulaquestion_output.html", true, true, 'Modules/TestQuestionPool');
1091
1092 $questiontext = $this->object->substituteVariables($user_solution);
1093
1094 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
1095
1096 $questionoutput = $template->get();
1097 $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1098 return $pageoutput;
1099 }
1100
1101 public function getSpecificFeedbackOutput($active_id, $pass)
1102 {
1103 return '';
1104 }
1105}
sprintf('%.4f', $callTime)
$result
$test
Definition: Utf8Test.php:84
$_GET["client_id"]
$_POST["username"]
$_SESSION["AccountId"]
An exception for terminatinating execution or to throw for unit testing.
Single choice question GUI representation The assFormulaQuestionGUI class encapsulates the GUI repres...
canUseAdvancedRating($result)
Check if advanced rating can be used for a result.
hasResultUnit($result, $unit_id, $resultunits)
getPreview($show_question_only=false, $showInlineFeedback=false)
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.integer A positive valu...
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
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.
static _questionExistsInTest($question_id, $test_id)
static _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.
static _getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
static _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)
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
$template
$key
Definition: croninfo.php:18
$txt
Definition: error.php:11
if(!array_key_exists('StateId', $_REQUEST)) $id
$errors
Definition: index.php:6
$url
if(isset($_POST['submit'])) $form
global $ilDB
$results
Definition: svg-scanner.php:47
$ilUser
Definition: imgupload.php:18