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 
4 include_once "./Modules/TestQuestionPool/classes/class.assQuestionGUI.php";
5 include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestion.php";
6 include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestionResult.php";
7 include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestionVariable.php";
8 include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestionUnit.php";
9 include_once "./Modules/TestQuestionPool/classes/class.assFormulaQuestionUnitCategory.php";
10 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
11 require_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 {
269  $this->resetSavedPreviewSession();
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 
406  uasort($results, function (assFormulaQuestionResult $r1, assFormulaQuestionResult $r2) {
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 
767  private function canUseAdvancedRating($result)
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());
798  $this->saveTaxonomyAssignments();
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 {
868  $this->saveTaxonomyAssignments();
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 }
static sendSuccess($a_info="", $a_keep=false)
Send Success Message to Screen.
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
This class represents an option in a radio group.
setOptions($a_options)
Set Options.
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question, working time.
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
$_SESSION["AccountId"]
This class represents a selection list property in a property form.
$result
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
$template
This class represents a property form user interface.
Single choice question GUI representation The assFormulaQuestionGUI class encapsulates the GUI repres...
getSpecificFeedbackOutput($active_id, $pass)
addErrorMessage($errormessage)
$_GET["client_id"]
This class represents a section header in a property form.
suggestRange()
Suggest a range for a result public.
if(!array_key_exists('StateId', $_REQUEST)) $id
This class represents a checkbox property in a property form.
Class for single choice questions assFormulaQuestion is a class for single choice questions...
getPreview($show_question_only=false, $showInlineFeedback=false)
canUseAdvancedRating($result)
Check if advanced rating can be used for a result.
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.
callNewIdListeners($a_new_id)
Call the new id listeners.
getQuestionTemplate()
get question template
setInfo($a_info)
Set Info.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
static getResultTypeByQstId($a_qst_id, $a_result)
static stripOnlySlashes($a_str)
strip slashes if magic qoutes is enabled
allowDecimals($a_value)
Toggle Decimals.
setInfo($a_info)
Set Information Text.
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
setQuestionTabs()
Sets the ILIAS tabs for this question type Sets the ILIAS tabs for this question type public...
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 property in a property form.
static getReturnToPageLink($q_id=null)
if(isset($_POST['submit'])) $form
getILIASPage($html="")
Returns the ILIAS Page around a question.
This class represents a number property in a property form.
setValue($a_value)
Set Value.
special template class to simplify handling of ITX/PEAR
This class represents a text property in a property form.
getTestOutput($active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
$ilUser
Definition: imgupload.php:18
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
setOptions($a_options)
Set Options.
Basic GUI class for assessment questions.
$txt
Definition: error.php:11
Create styles array
The data for the language used.
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
__construct($id=-1)
assFormulaQuestionGUI constructor The constructor takes possible arguments an creates an instance of ...
static _questionExistsInTest($question_id, $test_id)
setSize($a_size)
Set Size.
This class represents a custom property in a property form.
$errors
Definition: index.php:6
This class represents a non editable value in a property form.
Create new PHPExcel object
obj_idprivate
$results
Definition: svg-scanner.php:47
addBackTab(ilTabsGUI $ilTabs)
global $ilDB
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
$url
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
static _getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
static redirect($a_script)
save()
save question
$key
Definition: croninfo.php:18
hasResultUnit($result, $unit_id, $resultunits)
$_POST["username"]
setRequired($a_required)
Set Required.
$test
Definition: Utf8Test.php:84
static _isWriteable($question_id, $user_id)
Returns true if the question is writeable by a certain user.