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