ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.assMultipleChoiceGUI.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 require_once './Modules/TestQuestionPool/classes/class.assQuestionGUI.php';
5 require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiQuestionScoringAdjustable.php';
6 require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiAnswerScoringAdjustable.php';
7 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
8 
24 {
25  public $choiceKeys;
26 
35  public function __construct($id = -1)
36  {
37  parent::__construct();
38  include_once "./Modules/TestQuestionPool/classes/class.assMultipleChoice.php";
39  $this->object = new assMultipleChoice();
40  if ($id >= 0) {
41  $this->object->loadFromDb($id);
42  }
43  }
44 
48  public function hasInlineFeedback()
49  {
50  return $this->object->feedbackOBJ->isSpecificAnswerFeedbackAvailable($this->object->getId());
51  }
52 
56  protected function writePostData($always = false)
57  {
58  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
59  if (!$hasErrors) {
60  $form = $this->buildEditForm();
61  $form->setValuesByPost();
62  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
66  $this->saveTaxonomyAssignments();
67  return 0;
68  }
69  return 1;
70  }
71 
79  protected function getEditAnswersSingleLine($checkonly = false)
80  {
81  if ($checkonly) {
82  // form posting is checked
83  return ($_POST['types'] == 0) ? true : false;
84  }
85 
86  $lastChange = $this->object->getLastChange();
87  if (empty($lastChange) && !isset($_POST['types'])) {
88  // a new question is edited
89  return $this->object->getMultilineAnswerSetting() ? false : true;
90  } else {
91  // a saved question is edited
92  return $this->object->isSingleline;
93  }
94  }
95 
103  public function editQuestion($checkonly = false)
104  {
105  $save = $this->isSaveCommand();
106  $this->getQuestionTemplate();
107 
108  $form = $this->buildEditForm();
109 
110  $isSingleline = $this->getEditAnswersSingleLine($checkonly);
111  if ($isSingleline) {
112  $form->setMultipart(true);
113  } else {
114  $form->setMultipart(false);
115  }
116 
117  $errors = false;
118 
119  if ($save) {
120  $form->getItemByPostVar('selection_limit')->setMaxValue(count((array) $_POST['choice']['answer']));
121 
122  $form->setValuesByPost();
123  $errors = !$form->checkInput();
124  $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
125  if ($errors) {
126  $checkonly = false;
127  }
128  }
129 
130  if (!$checkonly) {
131  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
132  }
133  return $errors;
134  }
135 
137  {
138  parent::addBasicQuestionFormProperties($form);
139  $form->getItemByPostVar('question')->setInitialRteWidth('100');
140  }
141 
145  public function uploadchoice()
146  {
147  $this->writePostData(true);
148  $position = key($_POST['cmd']['uploadchoice']);
149  $this->editQuestion();
150  }
151 
155  public function removeimagechoice()
156  {
157  $this->writePostData(true);
158  $position = key($_POST['cmd']['removeimagechoice']);
159  $filename = $_POST['choice']['imagename'][$position];
160  $this->object->removeAnswerImage($position);
161  $this->editQuestion();
162  }
163 
167  public function addchoice()
168  {
169  $this->writePostData(true);
170  $position = key($_POST['cmd']['addchoice']);
171  $this->object->addAnswer("", 0, 0, $position + 1);
172  $this->editQuestion();
173  }
174 
178  public function removechoice()
179  {
180  $this->writePostData(true);
181  $position = key($_POST['cmd']['removechoice']);
182  $this->object->deleteAnswer($position);
183  $this->editQuestion();
184  }
185 
192  {
193  return true;
194  }
195 
211  public function getSolutionOutput(
212  $active_id,
213  $pass = null,
214  $graphicalOutput = false,
215  $result_output = false,
216  $show_question_only = true,
217  $show_feedback = false,
218  $show_correct_solution = false,
219  $show_manual_scoring = false,
220  $show_question_text = true
221  ) {
222  // shuffle output
223  $keys = $this->getChoiceKeys();
224 
225  // get the solution of the user for the active pass or from the last pass if allowed
226  $user_solution = array();
227  if (($active_id > 0) && (!$show_correct_solution)) {
228  $solutions = $this->object->getSolutionValues($active_id, $pass, !$this->getUseIntermediateSolution());
229  foreach ($solutions as $idx => $solution_value) {
230  array_push($user_solution, $solution_value["value1"]);
231  }
232  } else {
233  // take the correct solution instead of the user solution
234  foreach ($this->object->answers as $index => $answer) {
235  $points_checked = $answer->getPointsChecked();
236  $points_unchecked = $answer->getPointsUnchecked();
237  if ($points_checked > $points_unchecked) {
238  if ($points_checked > 0) {
239  array_push($user_solution, $index);
240  }
241  }
242  }
243  }
244 
245  // generate the question output
246  include_once "./Services/UICore/classes/class.ilTemplate.php";
247  $template = new ilTemplate("tpl.il_as_qpl_mc_mr_output_solution.html", true, true, "Modules/TestQuestionPool");
248  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
249  foreach ($keys as $answer_id) {
250  $answer = $this->object->answers[$answer_id];
251  if (($active_id > 0) && (!$show_correct_solution)) {
252  if ($graphicalOutput) {
253  // output of ok/not ok icons for user entered solutions
254  $ok = false;
255  $checked = false;
256  foreach ($user_solution as $mc_solution) {
257  if (strcmp($mc_solution, $answer_id) == 0) {
258  $checked = true;
259  }
260  }
261  if ($checked) {
262  if ($answer->getPointsChecked() > $answer->getPointsUnchecked()) {
263  $ok = true;
264  } else {
265  $ok = false;
266  }
267  } else {
268  if ($answer->getPointsChecked() > $answer->getPointsUnchecked()) {
269  $ok = false;
270  } else {
271  $ok = true;
272  }
273  }
274  if ($ok) {
275  $template->setCurrentBlock("icon_ok");
276  $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
277  $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
278  $template->parseCurrentBlock();
279  } else {
280  $template->setCurrentBlock("icon_ok");
281  $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
282  $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
283  $template->parseCurrentBlock();
284  }
285  }
286  }
287  if (strlen($answer->getImage())) {
288  $template->setCurrentBlock("answer_image");
289  if ($this->object->getThumbSize()) {
290  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
291  } else {
292  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $answer->getImage());
293  }
294  $alt = $answer->getImage();
295  if (strlen($answer->getAnswertext())) {
296  $alt = $answer->getAnswertext();
297  }
298  $alt = preg_replace("/<[^>]*?>/", "", $alt);
299  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
300  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
301  $template->parseCurrentBlock();
302  }
303 
304  if ($show_feedback) {
305  if ($this->object->getSpecificFeedbackSetting() == 2) {
306  foreach ($user_solution as $mc_solution) {
307  if (strcmp($mc_solution, $answer_id) == 0) {
308  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
309  $this->object->getId(),
310  0,
311  $answer_id
312  );
313  if (strlen($fb)) {
314  $template->setCurrentBlock("feedback");
315  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
316  $template->parseCurrentBlock();
317  }
318  }
319  }
320  }
321 
322  if ($this->object->getSpecificFeedbackSetting() == 1) {
323  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
324  $this->object->getId(),
325  0,
326  $answer_id
327  );
328  if (strlen($fb)) {
329  $template->setCurrentBlock("feedback");
330  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
331  $template->parseCurrentBlock();
332  }
333  }
334 
335  if ($this->object->getSpecificFeedbackSetting() == 3) {
336  $answer = $this->object->getAnswer($answer_id);
337 
338  if ($answer->getPoints() > 0) {
339  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
340  $this->object->getId(),
341  0,
342  $answer_id
343  );
344  if (strlen($fb)) {
345  $template->setCurrentBlock("feedback");
346  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
347  $template->parseCurrentBlock();
348  }
349  }
350  }
351  }
352  $template->setCurrentBlock("answer_row");
353  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), true));
354  $checked = false;
355  if ($result_output) {
356  $pointschecked = $this->object->answers[$answer_id]->getPointsChecked();
357  $pointsunchecked = $this->object->answers[$answer_id]->getPointsUnchecked();
358  $resulttextchecked = ($pointschecked == 1) || ($pointschecked == -1) ? "%s " . $this->lng->txt("point") : "%s " . $this->lng->txt("points");
359  $resulttextunchecked = ($pointsunchecked == 1) || ($pointsunchecked == -1) ? "%s " . $this->lng->txt("point") : "%s " . $this->lng->txt("points");
360  $template->setVariable("RESULT_OUTPUT", sprintf("(" . $this->lng->txt("checkbox_checked") . " = $resulttextchecked, " . $this->lng->txt("checkbox_unchecked") . " = $resulttextunchecked)", $pointschecked, $pointsunchecked));
361  }
362  foreach ($user_solution as $mc_solution) {
363  if (strcmp($mc_solution, $answer_id) == 0) {
364  if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
365  $template->setVariable("SOLUTION_IMAGE", ilUtil::getHtmlPath(ilUtil::getImagePath("checkbox_checked.png")));
366  $template->setVariable("SOLUTION_ALT", $this->lng->txt("checked"));
367  } else {
368  $template->setVariable('QID', $this->object->getId());
369  $template->setVariable('SUFFIX', $show_correct_solution ? 'bestsolution' : 'usersolution');
370  $template->setVariable('SOLUTION_VALUE', $answer_id);
371  $template->setVariable('SOLUTION_CHECKED', 'checked');
372  }
373  $checked = true;
374  }
375  }
376  if (!$checked) {
377  if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
378  $template->setVariable("SOLUTION_IMAGE", ilUtil::getHtmlPath(ilUtil::getImagePath("checkbox_unchecked.png")));
379  $template->setVariable("SOLUTION_ALT", $this->lng->txt("unchecked"));
380  } else {
381  $template->setVariable('QID', $this->object->getId());
382  $template->setVariable('SUFFIX', $show_correct_solution ? 'bestsolution' : 'usersolution');
383  $template->setVariable('SOLUTION_VALUE', $answer_id);
384  }
385  }
386  $template->parseCurrentBlock();
387  }
388  $questiontext = $this->object->getQuestion();
389  if ($show_question_text == true) {
390  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
391  }
392  $questionoutput = $template->get();
393  $feedback = ($show_feedback && !$this->isTestPresentationContext()) ? $this->getAnswerFeedbackOutput($active_id, $pass) : "";
394 
395  if (strlen($feedback)) {
396  $cssClass = (
397  $this->hasCorrectSolution($active_id, $pass) ?
399  );
400 
401  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
402  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
403  }
404  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
405 
406  $solutionoutput = $solutiontemplate->get();
407 
408  if ($show_feedback && $this->hasInlineFeedback()) {
409  $solutionoutput = $this->buildFocusAnchorHtml() . $solutionoutput;
410  }
411 
412  if (!$show_question_only) {
413  // get page object output
414  $solutionoutput = $this->getILIASPage($solutionoutput);
415  }
416  return $solutionoutput;
417  }
418 
419  public function getPreview($show_question_only = false, $showInlineFeedback = false)
420  {
421  $user_solution = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : array();
422  // shuffle output
423  $keys = $this->getChoiceKeys();
424 
425  // generate the question output
426  include_once "./Services/UICore/classes/class.ilTemplate.php";
427  $template = new ilTemplate("tpl.il_as_qpl_mc_mr_output.html", true, true, "Modules/TestQuestionPool");
428  foreach ($keys as $answer_id) {
429  $answer = $this->object->answers[$answer_id];
430  if (strlen($answer->getImage())) {
431  if ($this->object->getThumbSize()) {
432  $template->setCurrentBlock("preview");
433  $template->setVariable("URL_PREVIEW", $this->object->getImagePathWeb() . $answer->getImage());
434  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
435  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
436  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
437  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
438  $alt = $answer->getImage();
439  if (strlen($answer->getAnswertext())) {
440  $alt = $answer->getAnswertext();
441  }
442  $alt = preg_replace("/<[^>]*?>/", "", $alt);
443  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
444  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
445  $template->parseCurrentBlock();
446  } else {
447  $template->setCurrentBlock("answer_image");
448  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $answer->getImage());
449  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
450  $alt = $answer->getImage();
451  if (strlen($answer->getAnswertext())) {
452  $alt = $answer->getAnswertext();
453  }
454  $alt = preg_replace("/<[^>]*?>/", "", $alt);
455  $template->setVariable("ATTR", $attr);
456  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
457  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
458  $template->parseCurrentBlock();
459  }
460  }
461 
462  if ($showInlineFeedback) {
463  $this->populateSpecificFeedbackInline($user_solution, $answer_id, $template);
464  }
465 
466  $template->setCurrentBlock("answer_row");
467  $template->setVariable("QID", $this->object->getId());
468  $template->setVariable("ANSWER_ID", $answer_id);
469  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), true));
470  foreach ($user_solution as $mc_solution) {
471  if (strcmp($mc_solution, $answer_id) == 0) {
472  $template->setVariable("CHECKED_ANSWER", " checked=\"checked\"");
473  }
474  }
475  $template->parseCurrentBlock();
476  }
477  if ($this->object->getSelectionLimit()) {
478  $template->setVariable('SELECTION_LIMIT_HINT', sprintf(
479  $this->lng->txt('ass_mc_sel_lim_hint'),
480  $this->object->getSelectionLimit(),
481  $this->object->getAnswerCount()
482  ));
483 
484  $template->setVariable('SELECTION_LIMIT_VALUE', $this->object->getSelectionLimit());
485  } else {
486  $template->setVariable('SELECTION_LIMIT_VALUE', 'null');
487  }
488  $template->setVariable("QUESTION_ID", $this->object->getId());
489  $questiontext = $this->object->getQuestion();
490  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
491  $questionoutput = $template->get();
492  if (!$show_question_only) {
493  // get page object output
494  $questionoutput = $this->getILIASPage($questionoutput);
495  }
496  return $questionoutput;
497  }
498 
508  public function getTestOutput(
509  $active_id,
510  // hey: prevPassSolutions - will be always available from now on
511  $pass,
512  // hey.
513  $is_postponed = false,
514  $use_post_solutions = false,
515  $show_feedback = false
516  ) {
517  // shuffle output
518  $keys = $this->getChoiceKeys();
519 
520  // get the solution of the user for the active pass or from the last pass if allowed
521  $user_solution = array();
522  if ($active_id) {
523  // hey: prevPassSolutions - obsolete due to central check
524  #$solutions = NULL;
525  #include_once "./Modules/Test/classes/class.ilObjTest.php";
526  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
527  #{
528  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
529  #}
530  $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
531  // hey.
532  foreach ($solutions as $idx => $solution_value) {
533  // fau: testNav - don't add the dummy entry for 'none of the above' to the user options
534  if ($solution_value["value1"] == 'mc_none_above') {
535  $this->setUseEmptySolutionInputChecked(true);
536  continue;
537  }
538 
539  $user_solution[] = $solution_value["value1"];
540  // fau.
541  }
542 
543  if (empty($user_solution) && $this->object->getTestPresentationConfig()->isWorkedThrough()) {
544  $this->setUseEmptySolutionInputChecked(true);
545  }
546  }
547  // generate the question output
548  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilAssMultipleChoice.js');
549  include_once "./Services/UICore/classes/class.ilTemplate.php";
550  $template = new ilTemplate("tpl.il_as_qpl_mc_mr_output.html", true, true, "Modules/TestQuestionPool");
551  foreach ($keys as $answer_id) {
552  $answer = $this->object->answers[$answer_id];
553  if (strlen($answer->getImage())) {
554  if ($this->object->getThumbSize()) {
555  $template->setCurrentBlock("preview");
556  $template->setVariable("URL_PREVIEW", $this->object->getImagePathWeb() . $answer->getImage());
557  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
558  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
559  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
560  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
561  $alt = $answer->getImage();
562  if (strlen($answer->getAnswertext())) {
563  $alt = $answer->getAnswertext();
564  }
565  $alt = preg_replace("/<[^>]*?>/", "", $alt);
566  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
567  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
568  $template->parseCurrentBlock();
569  } else {
570  $template->setCurrentBlock("answer_image");
571  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $answer->getImage());
572  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
573  $alt = $answer->getImage();
574  if (strlen($answer->getAnswertext())) {
575  $alt = $answer->getAnswertext();
576  }
577  $alt = preg_replace("/<[^>]*?>/", "", $alt);
578  $template->setVariable("ATTR", $attr);
579  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
580  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
581  $template->parseCurrentBlock();
582  }
583  }
584 
585  if ($show_feedback) {
586  $this->populateSpecificFeedbackInline($user_solution, $answer_id, $template);
587  }
588 
589  $template->setCurrentBlock("answer_row");
590  $template->setVariable("QID", $this->object->getId());
591  $template->setVariable("ANSWER_ID", $answer_id);
592  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), true));
593  foreach ($user_solution as $mc_solution) {
594  if (strcmp($mc_solution, $answer_id) == 0) {
595  $template->setVariable("CHECKED_ANSWER", " checked=\"checked\"");
596  }
597  }
598  $template->parseCurrentBlock();
599  }
600 
601  $questiontext = $this->object->getQuestion();
602  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
603  $template->setVariable("QUESTION_ID", $this->object->getId());
604  if ($this->object->getSelectionLimit()) {
605  $template->setVariable('SELECTION_LIMIT_HINT', sprintf(
606  $this->lng->txt('ass_mc_sel_lim_hint'),
607  $this->object->getSelectionLimit(),
608  $this->object->getAnswerCount()
609  ));
610 
611  $template->setVariable('SELECTION_LIMIT_VALUE', $this->object->getSelectionLimit());
612  } else {
613  $template->setVariable('SELECTION_LIMIT_VALUE', 'null');
614  }
615  $questionoutput = $template->get();
616  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput, $show_feedback);
617  return $pageoutput;
618  }
619 
620  protected $useEmptySolutionInputChecked = false;
621 
623  {
625  }
626 
628  {
629  $this->useEmptySolutionInputChecked = $useEmptySolutionInputChecked;
630  }
631 
633  {
634  // hey: prevPassSolutions - use abstracted template to share with other purposes of this kind
635  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilAssMultipleChoice.js');
636 
637  $tpl = new ilTemplate('tpl.tst_question_additional_behaviour_checkbox.html', true, true, 'Modules/TestQuestionPool');
638 
639  // HEY: affects next if (!) /// noneAboveChecked repaired but disabled because the checked input ..
640  if (false) { // .. makes the qstEditController initialize the "edit" instead of the "answered" state
641  if ($this->isUseEmptySolutionInputChecked()) {
642  $tpl->setCurrentBlock('checked');
643  $tpl->touchBlock('checked');
644  $tpl->parseCurrentBlock();
645  }
646  }
647 
648  $tpl->setCurrentBlock('checkbox');
649  $tpl->setVariable('TXT_FORCE_FORM_DIFF_LABEL', $this->object->getTestPresentationConfig()->getUseUnchangedAnswerLabel());
650  $tpl->parseCurrentBlock();
651  // hey.
652  return $tpl->get();
653  }
654 
656  {
657  $tpl->addJavaScript('Modules/TestQuestionPool/js/ilAssMultipleChoice.js');
658  }
659 
665  public function setQuestionTabs()
666  {
667  global $DIC;
668  $rbacsystem = $DIC['rbacsystem'];
669  $ilTabs = $DIC['ilTabs'];
670 
671  $ilTabs->clearTargets();
672 
673  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
674  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
675  $q_type = $this->object->getQuestionType();
676 
677  if (strlen($q_type)) {
678  $classname = $q_type . "GUI";
679  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
680  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
681  }
682 
683  if ($_GET["q_id"]) {
684  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
685  // edit page
686  $ilTabs->addTarget(
687  "edit_page",
688  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
689  array("edit", "insert", "exec_pg"),
690  "",
691  "",
692  $force_active
693  );
694  }
695 
696  $this->addTab_QuestionPreview($ilTabs);
697  }
698  $force_active = false;
699  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
700  $url = "";
701  if ($classname) {
702  $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
703  }
704  $force_active = false;
705  // edit question properties
706  $ilTabs->addTarget(
707  "edit_question",
708  $url,
709  array("editQuestion", "save", "saveEdit", "addchoice", "removechoice", "removeimagechoice", "uploadchoice", "originalSyncForm"),
710  $classname,
711  "",
712  $force_active
713  );
714  }
715 
716  // add tab for question feedback within common class assQuestionGUI
717  $this->addTab_QuestionFeedback($ilTabs);
718 
719  // add tab for question hint within common class assQuestionGUI
720  $this->addTab_QuestionHints($ilTabs);
721 
722  // add tab for question's suggested solution within common class assQuestionGUI
723  $this->addTab_SuggestedSolution($ilTabs, $classname);
724 
725  // Assessment of questions sub menu entry
726  if ($_GET["q_id"]) {
727  $ilTabs->addTarget(
728  "statistics",
729  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
730  array("assessment"),
731  $classname,
732  ""
733  );
734  }
735 
736  $this->addBackTab($ilTabs);
737  }
738 
744  public function getChoiceKeys()
745  {
746  $choiceKeys = array_keys($this->object->answers);
747 
748  if ($this->object->getShuffle()) {
749  $choiceKeys = $this->object->getShuffler()->shuffle($choiceKeys);
750  }
751 
752  return $choiceKeys;
753  }
754 
755  public function getSpecificFeedbackOutput($userSolution)
756  {
757  // No return value, this question type supports inline specific feedback.
758  $output = "";
759  return $this->object->prepareTextareaOutput($output, true);
760  }
761 
763  {
764  $this->object->setShuffle($_POST["shuffle"]);
765 
766  $selectionLimit = (int) $form->getItemByPostVar('selection_limit')->getValue();
767  $this->object->setSelectionLimit($selectionLimit > 0 ? $selectionLimit : null);
768 
769  $this->object->setMultilineAnswerSetting($_POST["types"]);
770  if (is_array($_POST['choice']['imagename']) && $_POST["types"] == 1) {
771  $this->object->isSingleline = true;
772  ilUtil::sendInfo($this->lng->txt('info_answer_type_change'), true);
773  } else {
774  $this->object->isSingleline = ($_POST["types"] == 0) ? true : false;
775  }
776  $this->object->setThumbSize((strlen($_POST["thumb_size"])) ? $_POST["thumb_size"] : "");
777  }
778 
780  {
781  // Delete all existing answers and create new answers from the form data
782  $this->object->flushAnswers();
783  if ($this->object->isSingleline) {
784  foreach ($_POST['choice']['answer'] as $index => $answertext) {
785  $answertext = ilUtil::secureString($answertext);
786 
787  $picturefile = $_POST['choice']['imagename'][$index];
788  $file_org_name = $_FILES['choice']['name']['image'][$index];
789  $file_temp_name = $_FILES['choice']['tmp_name']['image'][$index];
790 
791  if (strlen($file_temp_name)) {
792  // check suffix
793  $suffix = strtolower(array_pop(explode(".", $file_org_name)));
794  if (in_array($suffix, array( "jpg", "jpeg", "png", "gif" ))) {
795  // upload image
796  $filename = $this->object->buildHashedImageFilename($file_org_name);
797  if ($this->object->setImageFile($filename, $file_temp_name) == 0) {
798  $picturefile = $filename;
799  }
800  }
801  }
802  $this->object->addAnswer(
803  $answertext,
804  $_POST['choice']['points'][$index],
805  $_POST['choice']['points_unchecked'][$index],
806  $index,
807  $picturefile
808  );
809  }
810  } else {
811  foreach ($_POST['choice']['answer'] as $index => $answer) {
812  $answertext = $answer;
813  $this->object->addAnswer(
814  $answertext,
815  $_POST['choice']['points'][$index],
816  $_POST['choice']['points_unchecked'][$index],
817  $index
818  );
819  }
820  }
821  }
822 
824  {
825  // shuffle
826  $shuffle = new ilCheckboxInputGUI($this->lng->txt("shuffle_answers"), "shuffle");
827  $shuffle->setValue(1);
828  $shuffle->setChecked($this->object->getShuffle());
829  $shuffle->setRequired(false);
830  $form->addItem($shuffle);
831 
832  require_once 'Services/Form/classes/class.ilNumberInputGUI.php';
833  $selLim = new ilNumberInputGUI($this->lng->txt('ass_mc_sel_lim_setting'), 'selection_limit');
834  $selLim->setInfo($this->lng->txt('ass_mc_sel_lim_setting_desc'));
835  $selLim->setSize(2);
836  $selLim->setRequired(false);
837  $selLim->allowDecimals(false);
838  $selLim->setMinvalueShouldBeGreater(false);
839  $selLim->setMaxvalueShouldBeLess(false);
840  $selLim->setMinValue(1);
841  $selLim->setMaxValue($this->object->getAnswerCount());
842  $selLim->setValue($this->object->getSelectionLimit());
843  $form->addItem($selLim);
844 
845  if ($this->object->getId()) {
846  $hidden = new ilHiddenInputGUI("", "ID");
847  $hidden->setValue($this->object->getId());
848  $form->addItem($hidden);
849  }
850 
851  $isSingleline = $this->getEditAnswersSingleLine();
852 
853  if (!$this->object->getSelfAssessmentEditingMode()) {
854  // Answer types
855  $types = new ilSelectInputGUI($this->lng->txt("answer_types"), "types");
856  $types->setRequired(false);
857  $types->setValue(($isSingleline) ? 0 : 1);
858  $types->setOptions(
859  array(
860  0 => $this->lng->txt('answers_singleline'),
861  1 => $this->lng->txt('answers_multiline'),
862  )
863  );
864  $form->addItem($types);
865  }
866 
867  if ($isSingleline) {
868  // thumb size
869  $thumb_size = new ilNumberInputGUI($this->lng->txt("thumb_size"), "thumb_size");
870  $thumb_size->setSuffix($this->lng->txt("thumb_size_unit_pixel"));
871  $thumb_size->setMinValue(20);
872  $thumb_size->setDecimals(0);
873  $thumb_size->setSize(6);
874  $thumb_size->setInfo($this->lng->txt('thumb_size_info'));
875  $thumb_size->setValue($this->object->getThumbSize());
876  $thumb_size->setRequired(false);
877  $form->addItem($thumb_size);
878  return $isSingleline;
879  }
880  return $isSingleline;
881  }
882 
884  {
885  // Choices
886  include_once "./Modules/TestQuestionPool/classes/class.ilMultipleChoiceWizardInputGUI.php";
887  $choices = new ilMultipleChoiceWizardInputGUI($this->lng->txt("answers"), "choice");
888  $choices->setRequired(true);
889  $choices->setQuestionObject($this->object);
890  $isSingleline = $this->getEditAnswersSingleLine();
891  $choices->setSingleline($isSingleline);
892  $choices->setAllowMove(false);
893  if ($this->object->getSelfAssessmentEditingMode()) {
894  $choices->setSize(40);
895  }
896  $choices->setMaxLength(800);
897  if ($this->object->getAnswerCount() == 0) {
898  $this->object->addAnswer("", 0, 0, 0);
899  }
900  $choices->setValues($this->object->getAnswers());
901  $form->addItem($choices);
902  }
903 
914  {
915  return array();
916  }
917 
928  {
929  return array();
930  }
931 
940  public function getAggregatedAnswersView($relevant_answers)
941  {
942  return $this->renderAggregateView(
943  $this->aggregateAnswers($relevant_answers, $this->object->getAnswers())
944  )->get();
945  }
946 
947  public function aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
948  {
949  $aggregate = array();
950  foreach ($answers_defined_on_question as $answer) {
951  $aggregated_info_for_answer = array();
952  $aggregated_info_for_answer['answertext'] = $answer->getAnswerText();
953  $aggregated_info_for_answer['count_checked'] = 0;
954 
955  foreach ($relevant_answers_chosen as $relevant_answer) {
956  if ($relevant_answer['value1'] == $answer->getOrder()) {
957  $aggregated_info_for_answer['count_checked']++;
958  }
959  }
960  $aggregated_info_for_answer['count_unchecked'] =
961  ceil(count($relevant_answers_chosen) / count($answers_defined_on_question))
962  - $aggregated_info_for_answer['count_checked'];
963 
964  $aggregate[] = $aggregated_info_for_answer;
965  }
966  return $aggregate;
967  }
968 
974  public function renderAggregateView($aggregate)
975  {
976  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
977 
978  $tpl->setCurrentBlock('headercell');
979  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_answer_header'));
980  $tpl->parseCurrentBlock();
981 
982  $tpl->setCurrentBlock('headercell');
983  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_frequency_header'));
984  $tpl->parseCurrentBlock();
985 
986  foreach ($aggregate as $line_data) {
987  $tpl->setCurrentBlock('aggregaterow');
988  $tpl->setVariable('OPTION', $line_data['answertext']);
989  $tpl->setVariable('COUNT', $line_data['count_checked']);
990  $tpl->parseCurrentBlock();
991  }
992  return $tpl;
993  }
994 
1001  private function populateSpecificFeedbackInline($user_solution, $answer_id, $template)
1002  {
1003  if ($this->object->getSpecificFeedbackSetting() == 2) {
1004  foreach ($user_solution as $mc_solution) {
1005  if (strcmp($mc_solution, $answer_id) == 0) {
1006  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), 0, $answer_id);
1007  if (strlen($fb)) {
1008  $template->setCurrentBlock("feedback");
1009  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
1010  $template->parseCurrentBlock();
1011  }
1012  }
1013  }
1014  }
1015 
1016  if ($this->object->getSpecificFeedbackSetting() == 1) {
1017  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), 0, $answer_id);
1018  if (strlen($fb)) {
1019  $template->setCurrentBlock("feedback");
1020  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
1021  $template->parseCurrentBlock();
1022  }
1023  }
1024 
1025  if ($this->object->getSpecificFeedbackSetting() == 3) {
1026  $answer = $this->object->getAnswer($answer_id);
1027 
1028  if ($answer->getPoints() > 0) {
1029  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), 0, $answer_id);
1030  if (strlen($fb)) {
1031  $template->setCurrentBlock("feedback");
1032  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
1033  $template->parseCurrentBlock();
1034  }
1035  }
1036  }
1037  }
1038 
1039  // fau: testNav - new functions setWithNoneAbove() and setIsAnswered()
1040  // moved functionality to ilTestQuestionPresentationConfig
1041  // fau.
1042 
1046  protected function buildEditForm()
1047  {
1048  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
1049  $form = new ilPropertyFormGUI();
1050  $form->setFormAction($this->ctrl->getFormAction($this));
1051  $form->setTitle($this->outQuestionType());
1052  $form->setTableWidth("100%");
1053  $form->setId("assmultiplechoice");
1054 
1055  // title, author, description, question, working time (assessment mode)
1061  return $form;
1062  }
1063 
1064  public function getAnswersFrequency($relevantAnswers, $questionIndex)
1065  {
1066  $agg = $this->aggregateAnswers($relevantAnswers, $this->object->getAnswers());
1067 
1068  $answers = array();
1069 
1070  foreach ($agg as $ans) {
1071  $answers[] = array(
1072  'answer' => $ans['answertext'],
1073  'frequency' => $ans['count_checked']
1074  );
1075  }
1076 
1077  return $answers;
1078  }
1079 
1081  {
1082  require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssMultipleChoiceCorrectionsInputGUI.php';
1083  $choices = new ilAssMultipleChoiceCorrectionsInputGUI($this->lng->txt("answers"), "choice");
1084  $choices->setRequired(true);
1085  $choices->setQuestionObject($this->object);
1086  $choices->setValues($this->object->getAnswers());
1087  $form->addItem($choices);
1088  }
1089 
1094  {
1095  $pointsChecked = $form->getInput('choice')['points'];
1096  $pointsUnchecked = $form->getInput('choice')['points_unchecked'];
1097 
1098  foreach ($this->object->getAnswers() as $index => $answer) {
1099  /* @var ASS_AnswerMultipleResponseImage $answer */
1100  $answer->setPointsChecked((float) $pointsChecked[$index]);
1101  $answer->setPointsUnchecked((float) $pointsUnchecked[$index]);
1102  }
1103  }
1104 }
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms public
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
getItemByPostVar($a_post_var)
Get Item by POST variable.
getAnswersFrequency($relevantAnswers, $questionIndex)
This class represents a selection list property in a property form.
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
$template
This class represents a property form user interface.
$type
global $DIC
Definition: saml.php:7
setUseEmptySolutionInputChecked($useEmptySolutionInputChecked)
$_GET["client_id"]
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getChoiceKeys()
Create the key index numbers for the array of choices.
populateJavascriptFilesRequiredForWorkForm(ilTemplate $tpl)
if(!array_key_exists('StateId', $_REQUEST)) $id
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
This class represents a checkbox property in a property form.
addItem($a_item)
Add Item (Property, SectionHeader).
$index
Definition: metadata.php:60
getQuestionTemplate()
get question template
$keys
Class for multiple choice tests.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
getUseIntermediateSolution()
Get if intermediate solution should be used for solution output.
removeimagechoice()
Remove an image.
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
setInfo($a_info)
Set Information Text.
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
This class represents a hidden form property in a property form.
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form)
setQuestionTabs()
Sets the ILIAS tabs for this question type.
setSuffix($a_value)
Set suffix.
if(isset($_POST['submit'])) $form
addJavaScript($a_js_file, $a_add_version_parameter=true, $a_batch=2)
Add a javascript file that should be included in the header.
getILIASPage($html="")
Returns the ILIAS Page around a question.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
This class represents a number property in a property form.
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
setValue($a_value)
Set Value.
special template class to simplify handling of ITX/PEAR
getPreview($show_question_only=false, $showInlineFeedback=false)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
getInput($a_post_var, $ensureValidation=true)
Returns the value of a HTTP-POST variable, identified by the passed id.
Basic GUI class for assessment questions.
static getHtmlPath($relative_path)
get url of path
aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
$filename
Definition: buildRTE.php:89
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getAnswerFeedbackOutput($active_id, $pass)
Returns the answer generic feedback depending on the results of the question.
Multiple choice question GUI representation.
getEditAnswersSingleLine($checkonly=false)
Get the single/multiline editing of answers.
__construct($id=-1)
assMultipleChoiceGUI constructor
This class represents a multiple choice wizard property in a property form.
$errors
Definition: index.php:6
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
output question page
addBackTab(ilTabsGUI $ilTabs)
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
static secureString($a_str, $a_strip_html=true, $a_allow="")
Remove unsecure tags.
getTestOutput( $active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
Interface ilGuiAnswerScoringAdjustable.
$url
Interface ilGuiQuestionScoringAdjustable.
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.
populateSpecificFeedbackInline($user_solution, $answer_id, $template)
$_POST["username"]
setRequired($a_required)
Set Required.
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.