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