ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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 {
26 
35  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  {
42  $this->object->loadFromDb($id);
43  }
44  }
45 
49  protected function writePostData($always = false)
50  {
51  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
52  if (!$hasErrors)
53  {
54  $form = $this->buildEditForm();
55  $form->setValuesByPost();
56  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
58  $this->writeQuestionSpecificPostData($form);
59  $this->writeAnswerSpecificPostData($form);
60  $this->saveTaxonomyAssignments();
61  return 0;
62  }
63  return 1;
64  }
65 
73  protected function getEditAnswersSingleLine($checkonly = false)
74  {
75  if ($checkonly)
76  {
77  // form posting is checked
78  return ($_POST['types'] == 0) ? true : false;
79  }
80 
81  $lastChange = $this->object->getLastChange();
82  if (empty($lastChange) && !isset($_POST['types']))
83  {
84  // a new question is edited
85  return $this->object->getMultilineAnswerSetting() ? false : true;
86  }
87  else
88  {
89  // a saved question is edited
90  return $this->object->isSingleline;
91  }
92  }
93 
101  public function editQuestion($checkonly = FALSE)
102  {
103  $save = $this->isSaveCommand();
104  $this->getQuestionTemplate();
105 
106  $form = $this->buildEditForm();
107 
108  $isSingleline = $this->getEditAnswersSingleLine($checkonly);
109  if ($isSingleline)
110  {
111  $form->setMultipart(TRUE);
112  }
113  else
114  {
115  $form->setMultipart(FALSE);
116  }
117 
118  $errors = false;
119 
120  if ($save)
121  {
122  $form->getItemByPostVar('selection_limit')->setMaxValue(count((array)$_POST['choice']['answer']));
123 
124  $form->setValuesByPost();
125  $errors = !$form->checkInput();
126  $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
127  if ($errors) $checkonly = false;
128  }
129 
130  if (!$checkonly) $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
131  return $errors;
132  }
133 
135  {
136  parent::addBasicQuestionFormProperties($form);
137  $form->getItemByPostVar('question')->setInitialRteWidth('100');
138  }
139 
143  public function uploadchoice()
144  {
145  $this->writePostData(true);
146  $position = key($_POST['cmd']['uploadchoice']);
147  $this->editQuestion();
148  }
149 
153  public function removeimagechoice()
154  {
155  $this->writePostData(true);
156  $position = key($_POST['cmd']['removeimagechoice']);
157  $filename = $_POST['choice']['imagename'][$position];
158  $this->object->removeAnswerImage($position);
159  $this->editQuestion();
160  }
161 
165  public function addchoice()
166  {
167  $this->writePostData(true);
168  $position = key($_POST['cmd']['addchoice']);
169  $this->object->addAnswer("", 0, 0, $position+1);
170  $this->editQuestion();
171  }
172 
176  public function removechoice()
177  {
178  $this->writePostData(true);
179  $position = key($_POST['cmd']['removechoice']);
180  $this->object->deleteAnswer($position);
181  $this->editQuestion();
182  }
183 
200  $active_id,
201  $pass = NULL,
202  $graphicalOutput = FALSE,
203  $result_output = FALSE,
204  $show_question_only = TRUE,
205  $show_feedback = FALSE,
206  $show_correct_solution = FALSE,
207  $show_manual_scoring = FALSE,
208  $show_question_text = TRUE
209  )
210  {
211  // shuffle output
212  $keys = $this->getChoiceKeys();
213 
214  // get the solution of the user for the active pass or from the last pass if allowed
215  $user_solution = array();
216  if (($active_id > 0) && (!$show_correct_solution))
217  {
218  $solutions =& $this->object->getSolutionValues($active_id, $pass);
219  foreach ($solutions as $idx => $solution_value)
220  {
221  array_push($user_solution, $solution_value["value1"]);
222  }
223  }
224  else
225  {
226  // take the correct solution instead of the user solution
227  foreach ($this->object->answers as $index => $answer)
228  {
229  $points_checked = $answer->getPointsChecked();
230  $points_unchecked = $answer->getPointsUnchecked();
231  if ($points_checked > $points_unchecked)
232  {
233  if ($points_checked > 0)
234  {
235  array_push($user_solution, $index);
236  }
237  }
238  }
239  }
240 
241  // generate the question output
242  include_once "./Services/UICore/classes/class.ilTemplate.php";
243  $template = new ilTemplate("tpl.il_as_qpl_mc_mr_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
244  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
245  foreach ($keys as $answer_id)
246  {
247  $answer = $this->object->answers[$answer_id];
248  if (($active_id > 0) && (!$show_correct_solution))
249  {
250  if ($graphicalOutput)
251  {
252  // output of ok/not ok icons for user entered solutions
253  $ok = FALSE;
254  $checked = FALSE;
255  foreach ($user_solution as $mc_solution)
256  {
257  if (strcmp($mc_solution, $answer_id) == 0)
258  {
259  $checked = TRUE;
260  }
261  }
262  if ($checked)
263  {
264  if ($answer->getPointsChecked() > $answer->getPointsUnchecked())
265  {
266  $ok = TRUE;
267  }
268  else
269  {
270  $ok = FALSE;
271  }
272  }
273  else
274  {
275  if ($answer->getPointsChecked() > $answer->getPointsUnchecked())
276  {
277  $ok = FALSE;
278  }
279  else
280  {
281  $ok = TRUE;
282  }
283  }
284  if ($ok)
285  {
286  $template->setCurrentBlock("icon_ok");
287  $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
288  $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
289  $template->parseCurrentBlock();
290  }
291  else
292  {
293  $template->setCurrentBlock("icon_ok");
294  $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
295  $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
296  $template->parseCurrentBlock();
297  }
298  }
299  }
300  if (strlen($answer->getImage()))
301  {
302  $template->setCurrentBlock("answer_image");
303  if ($this->object->getThumbSize())
304  {
305  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
306  }
307  else
308  {
309  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $answer->getImage());
310  }
311  $alt = $answer->getImage();
312  if (strlen($answer->getAnswertext()))
313  {
314  $alt = $answer->getAnswertext();
315  }
316  $alt = preg_replace("/<[^>]*?>/", "", $alt);
317  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
318  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
319  $template->parseCurrentBlock();
320  }
321 
322  if ($show_feedback)
323  {
324 
325  if ($this->object->getSpecificFeedbackSetting() == 2)
326  {
327  foreach ($user_solution as $mc_solution)
328  {
329  if (strcmp($mc_solution, $answer_id) == 0)
330  {
331  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
332  $this->object->getId(), $answer_id
333  );
334  if (strlen($fb))
335  {
336  $template->setCurrentBlock("feedback");
337  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $fb, true ));
338  $template->parseCurrentBlock();
339  }
340  }
341  }
342  }
343 
344  if ($this->object->getSpecificFeedbackSetting() == 1)
345  {
346  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
347  $this->object->getId(), $answer_id
348  );
349  if (strlen($fb))
350  {
351  $template->setCurrentBlock("feedback");
352  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $fb, true ));
353  $template->parseCurrentBlock();
354  }
355  }
356 
357  if ($this->object->getSpecificFeedbackSetting() == 3)
358  {
359  $answer = $this->object->getAnswer($answer_id);
360 
361  if ($answer->getPoints() > 0)
362  {
363  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
364  $this->object->getId(), $answer_id
365  );
366  if (strlen($fb))
367  {
368  $template->setCurrentBlock("feedback");
369  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $fb, true ));
370  $template->parseCurrentBlock();
371  }
372  }
373 
374  }
375  }
376  $template->setCurrentBlock("answer_row");
377  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), TRUE));
378  $checked = FALSE;
379  if ($result_output)
380  {
381  $pointschecked = $this->object->answers[$answer_id]->getPointsChecked();
382  $pointsunchecked = $this->object->answers[$answer_id]->getPointsUnchecked();
383  $resulttextchecked = ($pointschecked == 1) || ($pointschecked == -1) ? "%s " . $this->lng->txt("point") : "%s " . $this->lng->txt("points");
384  $resulttextunchecked = ($pointsunchecked == 1) || ($pointsunchecked == -1) ? "%s " . $this->lng->txt("point") : "%s " . $this->lng->txt("points");
385  $template->setVariable("RESULT_OUTPUT", sprintf("(" . $this->lng->txt("checkbox_checked") . " = $resulttextchecked, " . $this->lng->txt("checkbox_unchecked") . " = $resulttextunchecked)", $pointschecked, $pointsunchecked));
386  }
387  foreach ($user_solution as $mc_solution)
388  {
389  if (strcmp($mc_solution, $answer_id) == 0)
390  {
391  if( $this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf() )
392  {
393  $template->setVariable("SOLUTION_IMAGE", ilUtil::getHtmlPath(ilUtil::getImagePath("checkbox_checked.png")));
394  $template->setVariable("SOLUTION_ALT", $this->lng->txt("checked"));
395  }
396  else
397  {
398  $template->setVariable('QID', $this->object->getId());
399  $template->setVariable('SUFFIX', $show_correct_solution ? 'bestsolution' : 'usersolution');
400  $template->setVariable('SOLUTION_VALUE', $answer_id);
401  $template->setVariable('SOLUTION_CHECKED', 'checked');
402  }
403  $checked = TRUE;
404  }
405  }
406  if (!$checked)
407  {
408  if( $this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf() )
409  {
410  $template->setVariable("SOLUTION_IMAGE", ilUtil::getHtmlPath(ilUtil::getImagePath("checkbox_unchecked.png")));
411  $template->setVariable("SOLUTION_ALT", $this->lng->txt("unchecked"));
412  }
413  else
414  {
415  $template->setVariable('QID', $this->object->getId());
416  $template->setVariable('SUFFIX', $show_correct_solution ? 'bestsolution' : 'usersolution');
417  $template->setVariable('SOLUTION_VALUE', $answer_id);
418  }
419  }
420  $template->parseCurrentBlock();
421  }
422  $questiontext = $this->object->getQuestion();
423  if ($show_question_text==true)
424  {
425  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
426  }
427  $questionoutput = $template->get();
428  $feedback = ($show_feedback && !$this->isTestPresentationContext()) ? $this->getAnswerFeedbackOutput($active_id, $pass) : "";
429 
430  if (strlen($feedback))
431  {
432  $cssClass = ( $this->hasCorrectSolution($active_id, $pass) ?
434  );
435 
436  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
437  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $feedback , true ));
438  }
439  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
440 
441  $solutionoutput = $solutiontemplate->get();
442  if (!$show_question_only)
443  {
444  // get page object output
445  $solutionoutput = $this->getILIASPage($solutionoutput);
446  }
447  return $solutionoutput;
448  }
449 
450  function getPreview($show_question_only = FALSE, $showInlineFeedback = false)
451  {
452  $user_solution = is_object($this->getPreviewSession()) ? (array)$this->getPreviewSession()->getParticipantsSolution() : array();
453  // shuffle output
454  $keys = $this->getChoiceKeys();
455 
456  // generate the question output
457  include_once "./Services/UICore/classes/class.ilTemplate.php";
458  $template = new ilTemplate("tpl.il_as_qpl_mc_mr_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
459  foreach ($keys as $answer_id)
460  {
461  $answer = $this->object->answers[$answer_id];
462  if (strlen($answer->getImage()))
463  {
464  if ($this->object->getThumbSize())
465  {
466  $template->setCurrentBlock("preview");
467  $template->setVariable("URL_PREVIEW", $this->object->getImagePathWeb() . $answer->getImage());
468  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
469  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
470  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
471  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
472  $alt = $answer->getImage();
473  if (strlen($answer->getAnswertext()))
474  {
475  $alt = $answer->getAnswertext();
476  }
477  $alt = preg_replace("/<[^>]*?>/", "", $alt);
478  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
479  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
480  $template->parseCurrentBlock();
481  }
482  else
483  {
484  $template->setCurrentBlock("answer_image");
485  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $answer->getImage());
486  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
487  $alt = $answer->getImage();
488  if (strlen($answer->getAnswertext()))
489  {
490  $alt = $answer->getAnswertext();
491  }
492  $alt = preg_replace("/<[^>]*?>/", "", $alt);
493  $template->setVariable("ATTR", $attr);
494  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
495  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
496  $template->parseCurrentBlock();
497  }
498  }
499 
500  if( $showInlineFeedback )
501  {
502  $this->populateSpecificFeedbackInline($user_solution, $answer_id, $template);
503  }
504 
505  $template->setCurrentBlock("answer_row");
506  $template->setVariable("QID", $this->object->getId());
507  $template->setVariable("ANSWER_ID", $answer_id);
508  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), TRUE));
509  foreach ($user_solution as $mc_solution)
510  {
511  if (strcmp($mc_solution, $answer_id) == 0)
512  {
513  $template->setVariable("CHECKED_ANSWER", " checked=\"checked\"");
514  }
515  }
516  $template->parseCurrentBlock();
517  }
518  if($this->object->getSelectionLimit())
519  {
520  $template->setVariable('SELECTION_LIMIT_HINT', sprintf(
521  $this->lng->txt('ass_mc_sel_lim_hint'),
522  $this->object->getSelectionLimit(),
523  $this->object->getAnswerCount()
524  ));
525 
526  $template->setVariable('SELECTION_LIMIT_VALUE', $this->object->getSelectionLimit());
527  }
528  else
529  {
530  $template->setVariable('SELECTION_LIMIT_VALUE', 'null');
531  }
532  $template->setVariable("QUESTION_ID", $this->object->getId());
533  $questiontext = $this->object->getQuestion();
534  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
535  $questionoutput = $template->get();
536  if (!$show_question_only)
537  {
538  // get page object output
539  $questionoutput = $this->getILIASPage($questionoutput);
540  }
541  return $questionoutput;
542  }
543 
553  function getTestOutput(
554  $active_id,
555  // hey: prevPassSolutions - will be always available from now on
556  $pass,
557  // hey.
558  $is_postponed = FALSE,
559  $use_post_solutions = FALSE,
560  $show_feedback = FALSE
561  )
562  {
563  // shuffle output
564  $keys = $this->getChoiceKeys();
565 
566  // get the solution of the user for the active pass or from the last pass if allowed
567  $user_solution = array();
568  if ($active_id)
569  {
570  // hey: prevPassSolutions - obsolete due to central check
571  #$solutions = NULL;
572  #include_once "./Modules/Test/classes/class.ilObjTest.php";
573  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
574  #{
575  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
576  #}
577  $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
578  // hey.
579  foreach ($solutions as $idx => $solution_value)
580  {
581 // fau: testNav - don't add the dummy entry for 'none of the above' to the user options
582  if ( $solution_value["value1"] != 'mc_none_above')
583  {
584  array_push($user_solution, $solution_value["value1"]);
585  }
586 // fau.
587  }
588  }
589  // generate the question output
590  include_once "./Services/UICore/classes/class.ilTemplate.php";
591  $template = new ilTemplate("tpl.il_as_qpl_mc_mr_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
592  foreach ($keys as $answer_id)
593  {
594  $answer = $this->object->answers[$answer_id];
595  if (strlen($answer->getImage()))
596  {
597  if ($this->object->getThumbSize())
598  {
599  $template->setCurrentBlock("preview");
600  $template->setVariable("URL_PREVIEW", $this->object->getImagePathWeb() . $answer->getImage());
601  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
602  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
603  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
604  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
605  $alt = $answer->getImage();
606  if (strlen($answer->getAnswertext()))
607  {
608  $alt = $answer->getAnswertext();
609  }
610  $alt = preg_replace("/<[^>]*?>/", "", $alt);
611  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
612  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
613  $template->parseCurrentBlock();
614  }
615  else
616  {
617  $template->setCurrentBlock("answer_image");
618  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $answer->getImage());
619  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
620  $alt = $answer->getImage();
621  if (strlen($answer->getAnswertext()))
622  {
623  $alt = $answer->getAnswertext();
624  }
625  $alt = preg_replace("/<[^>]*?>/", "", $alt);
626  $template->setVariable("ATTR", $attr);
627  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
628  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
629  $template->parseCurrentBlock();
630  }
631  }
632 
633  if( $show_feedback )
634  {
635  $this->populateSpecificFeedbackInline($user_solution, $answer_id, $template);
636  }
637 
638  $template->setCurrentBlock("answer_row");
639  $template->setVariable("QID", $this->object->getId());
640  $template->setVariable("ANSWER_ID", $answer_id);
641  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), TRUE));
642  foreach ($user_solution as $mc_solution)
643  {
644  if (strcmp($mc_solution, $answer_id) == 0)
645  {
646  $template->setVariable("CHECKED_ANSWER", " checked=\"checked\"");
647  }
648  }
649  $template->parseCurrentBlock();
650  }
651 
652 // fau: testNav - add 'none of the above', if needed by the deprecated test setting to score empty answers
653  if ($this->withNoneAbove)
654  {
655  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilAssMultipleChoice.js');
656  $template->setCurrentBlock('none_above');
657  $template->setVariable('LABEL_NONE_ABOVE', $this->lng->txt('tst_mc_label_none_above'));
658  if ($this->isAnswered && empty($user_solution))
659  {
660  $template->setVariable('CHECKED_NONE_ABOVE', " checked=\"checked\"");
661  }
662  $template->parseCurrentBlock();
663  }
664 // fau.
665 
666  $questiontext = $this->object->getQuestion();
667  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
668  $template->setVariable("QUESTION_ID", $this->object->getId());
669  if($this->object->getSelectionLimit())
670  {
671  $template->setVariable('SELECTION_LIMIT_HINT', sprintf(
672  $this->lng->txt('ass_mc_sel_lim_hint'),
673  $this->object->getSelectionLimit(),
674  $this->object->getAnswerCount()
675  ));
676 
677  $template->setVariable('SELECTION_LIMIT_VALUE', $this->object->getSelectionLimit());
678  }
679  else
680  {
681  $template->setVariable('SELECTION_LIMIT_VALUE', 'null');
682  }
683  $questionoutput = $template->get();
684  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
685  return $pageoutput;
686  }
687 
689  {
690  $tpl->addJavaScript('Modules/TestQuestionPool/js/ilAssMultipleChoice.js');
691  }
692 
698  public function setQuestionTabs()
699  {
700  global $rbacsystem, $ilTabs;
701 
702  $ilTabs->clearTargets();
703 
704  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
705  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
706  $q_type = $this->object->getQuestionType();
707 
708  if (strlen($q_type))
709  {
710  $classname = $q_type . "GUI";
711  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
712  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
713  }
714 
715  if ($_GET["q_id"])
716  {
717  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
718  {
719  // edit page
720  $ilTabs->addTarget("edit_page",
721  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
722  array("edit", "insert", "exec_pg"),
723  "", "", $force_active);
724  }
725 
726  $this->addTab_QuestionPreview($ilTabs);
727  }
728  $force_active = false;
729  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
730  {
731  $url = "";
732  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
733  $force_active = false;
734  // edit question properties
735  $ilTabs->addTarget("edit_question",
736  $url,
737  array("editQuestion", "save", "saveEdit", "addchoice", "removechoice", "removeimagechoice", "uploadchoice", "originalSyncForm"),
738  $classname, "", $force_active);
739  }
740 
741  // add tab for question feedback within common class assQuestionGUI
742  $this->addTab_QuestionFeedback($ilTabs);
743 
744  // add tab for question hint within common class assQuestionGUI
745  $this->addTab_QuestionHints($ilTabs);
746 
747  // add tab for question's suggested solution within common class assQuestionGUI
748  $this->addTab_SuggestedSolution($ilTabs, $classname);
749 
750  // Assessment of questions sub menu entry
751  if ($_GET["q_id"])
752  {
753  $ilTabs->addTarget("statistics",
754  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
755  array("assessment"),
756  $classname, "");
757  }
758 
759  $this->addBackTab($ilTabs);
760  }
761 
767  function getChoiceKeys()
768  {
769  $choiceKeys = array_keys($this->object->answers);
770 
771  if( $this->object->getShuffle() )
772  {
773  $choiceKeys = $this->object->getShuffler()->shuffle($choiceKeys);
774  }
775 
776  return $choiceKeys;
777  }
778 
779  function getSpecificFeedbackOutput($active_id, $pass)
780  {
781  // No return value, this question type supports inline specific feedback.
782  $output = "";
783  return $this->object->prepareTextareaOutput($output, TRUE);
784  }
785 
787  {
788  $this->object->setShuffle( $_POST["shuffle"] );
789 
790  $selectionLimit = (int)$form->getItemByPostVar('selection_limit')->getValue();
791  $this->object->setSelectionLimit($selectionLimit > 0 ? $selectionLimit : null);
792 
793  $this->object->setMultilineAnswerSetting( $_POST["types"] );
794  if (is_array( $_POST['choice']['imagename'] ) && $_POST["types"] == 1)
795  {
796  $this->object->isSingleline = true;
797  ilUtil::sendInfo( $this->lng->txt( 'info_answer_type_change' ), true );
798  }
799  else
800  {
801  $this->object->isSingleline = ($_POST["types"] == 0) ? true : false;
802  }
803  $this->object->setThumbSize( (strlen( $_POST["thumb_size"] )) ? $_POST["thumb_size"] : "" );
804  }
805 
807  {
808  // Delete all existing answers and create new answers from the form data
809  $this->object->flushAnswers();
810  if ($this->object->isSingleline)
811  {
812  foreach ($_POST['choice']['answer'] as $index => $answertext)
813  {
814  $answertext = ilUtil::secureString($answertext);
815 
816  $picturefile = $_POST['choice']['imagename'][$index];
817  $file_org_name = $_FILES['choice']['name']['image'][$index];
818  $file_temp_name = $_FILES['choice']['tmp_name']['image'][$index];
819 
820  if (strlen( $file_temp_name ))
821  {
822  // check suffix
823  $suffix = strtolower( array_pop( explode( ".", $file_org_name ) ) );
824  if (in_array( $suffix, array( "jpg", "jpeg", "png", "gif" ) ))
825  {
826  // upload image
827  $filename = $this->object->buildHashedImageFilename( $file_org_name );
828  if ($this->object->setImageFile( $filename, $file_temp_name ) == 0)
829  {
830  $picturefile = $filename;
831  }
832  }
833  }
834  $this->object->addAnswer( $answertext,
835  $_POST['choice']['points'][$index],
836  $_POST['choice']['points_unchecked'][$index],
837  $index,
838  $picturefile
839  );
840  }
841  }
842  else
843  {
844  foreach ($_POST['choice']['answer'] as $index => $answer)
845  {
846  $answertext = $answer;
847  $this->object->addAnswer( $answertext,
848  $_POST['choice']['points'][$index],
849  $_POST['choice']['points_unchecked'][$index],
850  $index
851  );
852  }
853  }
854  }
855 
857  {
858  // shuffle
859  $shuffle = new ilCheckboxInputGUI($this->lng->txt( "shuffle_answers" ), "shuffle");
860  $shuffle->setValue( 1 );
861  $shuffle->setChecked( $this->object->getShuffle() );
862  $shuffle->setRequired( FALSE );
863  $form->addItem( $shuffle );
864 
865  require_once 'Services/Form/classes/class.ilNumberInputGUI.php';
866  $selLim = new ilNumberInputGUI($this->lng->txt('ass_mc_sel_lim_setting'), 'selection_limit');
867  $selLim->setInfo($this->lng->txt('ass_mc_sel_lim_setting_desc'));
868  $selLim->setSize(2);
869  $selLim->setRequired(false);
870  $selLim->allowDecimals(false);
871  $selLim->setMinvalueShouldBeGreater(false);
872  $selLim->setMaxvalueShouldBeLess(false);
873  $selLim->setMinValue(1);
874  $selLim->setMaxValue($this->object->getAnswerCount());
875  $selLim->setValue($this->object->getSelectionLimit());
876  $form->addItem($selLim);
877 
878  if ($this->object->getId())
879  {
880  $hidden = new ilHiddenInputGUI("", "ID");
881  $hidden->setValue( $this->object->getId() );
882  $form->addItem( $hidden );
883  }
884 
885  $isSingleline = $this->getEditAnswersSingleLine();
886 
887  if (!$this->object->getSelfAssessmentEditingMode())
888  {
889  // Answer types
890  $types = new ilSelectInputGUI($this->lng->txt( "answer_types" ), "types");
891  $types->setRequired( false );
892  $types->setValue( ($isSingleline) ? 0 : 1 );
893  $types->setOptions( array(
894  0 => $this->lng->txt( 'answers_singleline' ),
895  1 => $this->lng->txt( 'answers_multiline' ),
896  )
897  );
898  $form->addItem( $types );
899  }
900 
901  if ($isSingleline)
902  {
903  // thumb size
904  $thumb_size = new ilNumberInputGUI($this->lng->txt( "thumb_size" ), "thumb_size");
905  $thumb_size->setSuffix($this->lng->txt("thumb_size_unit_pixel"));
906  $thumb_size->setMinValue( 20 );
907  $thumb_size->setDecimals( 0 );
908  $thumb_size->setSize( 6 );
909  $thumb_size->setInfo( $this->lng->txt( 'thumb_size_info' ) );
910  $thumb_size->setValue( $this->object->getThumbSize() );
911  $thumb_size->setRequired( false );
912  $form->addItem( $thumb_size );
913  return $isSingleline;
914  }
915  return $isSingleline;
916  }
917 
919  {
920  // Choices
921  include_once "./Modules/TestQuestionPool/classes/class.ilMultipleChoiceWizardInputGUI.php";
922  $choices = new ilMultipleChoiceWizardInputGUI($this->lng->txt( "answers" ), "choice");
923  $choices->setRequired( true );
924  $choices->setQuestionObject( $this->object );
925  $isSingleline = $this->getEditAnswersSingleLine();
926  $choices->setSingleline( $isSingleline );
927  $choices->setAllowMove( false );
928  if ($this->object->getSelfAssessmentEditingMode())
929  {
930  $choices->setSize( 40 );
931  }
932  $choices->setMaxLength( 800 );
933  if ($this->object->getAnswerCount() == 0)
934  $this->object->addAnswer( "", 0, 0, 0 );
935  $choices->setValues( $this->object->getAnswers() );
936  $form->addItem( $choices );
937  }
938 
949  {
950  return array();
951  }
952 
963  {
964  return array();
965  }
966 
975  public function getAggregatedAnswersView($relevant_answers)
976  {
977  return $this->renderAggregateView(
978  $this->aggregateAnswers( $relevant_answers, $this->object->getAnswers() ) )->get();
979  }
980 
981  public function aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
982  {
983  $aggregate = array();
984  foreach ($answers_defined_on_question as $answer)
985  {
986  $aggregated_info_for_answer = array();
987  $aggregated_info_for_answer['answertext'] = $answer->getAnswerText();
988  $aggregated_info_for_answer['count_checked'] = 0;
989 
990  foreach ($relevant_answers_chosen as $relevant_answer)
991  {
992  if ($relevant_answer['value1'] == $answer->getOrder())
993  {
994  $aggregated_info_for_answer['count_checked']++;
995  }
996  }
997  $aggregated_info_for_answer['count_unchecked'] =
998  ceil(count($relevant_answers_chosen) / count($answers_defined_on_question))
999  - $aggregated_info_for_answer['count_checked'];
1000 
1001  $aggregate[] = $aggregated_info_for_answer;
1002  }
1003  return $aggregate;
1004  }
1005 
1011  public function renderAggregateView($aggregate)
1012  {
1013  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
1014 
1015  $tpl->setCurrentBlock('headercell');
1016  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_answer_header'));
1017  $tpl->parseCurrentBlock();
1018 
1019  $tpl->setCurrentBlock('headercell');
1020  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_frequency_header'));
1021  $tpl->parseCurrentBlock();
1022 
1023  foreach ($aggregate as $line_data)
1024  {
1025  $tpl->setCurrentBlock( 'aggregaterow' );
1026  $tpl->setVariable( 'OPTION', $line_data['answertext'] );
1027  $tpl->setVariable( 'COUNT', $line_data['count_checked'] );
1028  $tpl->parseCurrentBlock();
1029  }
1030  return $tpl;
1031  }
1032 
1039  private function populateSpecificFeedbackInline($user_solution, $answer_id, $template)
1040  {
1041  if($this->object->getSpecificFeedbackSetting() == 2)
1042  {
1043  foreach($user_solution as $mc_solution)
1044  {
1045  if(strcmp($mc_solution, $answer_id) == 0)
1046  {
1047  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
1048  if(strlen($fb))
1049  {
1050  $template->setCurrentBlock("feedback");
1051  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
1052  $template->parseCurrentBlock();
1053  }
1054  }
1055  }
1056  }
1057 
1058  if($this->object->getSpecificFeedbackSetting() == 1)
1059  {
1060  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
1061  if(strlen($fb))
1062  {
1063  $template->setCurrentBlock("feedback");
1064  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
1065  $template->parseCurrentBlock();
1066  }
1067  }
1068 
1069  if($this->object->getSpecificFeedbackSetting() == 3)
1070  {
1071  $answer = $this->object->getAnswer($answer_id);
1072 
1073  if($answer->getPoints() > 0)
1074  {
1075  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
1076  if(strlen($fb))
1077  {
1078  $template->setCurrentBlock("feedback");
1079  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
1080  $template->parseCurrentBlock();
1081  }
1082  }
1083  }
1084  }
1085 
1086  // fau: testNav - new functions setWithNoneAbove() and setIsAnswered()
1087 
1092  public function setWithNoneAbove($a_with_none_above)
1093  {
1094  $this->withNoneAbove = (bool) $a_with_none_above;
1095  }
1096 
1101  public function setIsAnswered($a_is_answered)
1102  {
1103  $this->isAnswered = (bool) $a_is_answered;
1104  }
1105  // fau.
1106 
1110  protected function buildEditForm()
1111  {
1112  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
1113  $form = new ilPropertyFormGUI();
1114  $form->setFormAction($this->ctrl->getFormAction($this));
1115  $form->setTitle($this->outQuestionType());
1116  $form->setTableWidth("100%");
1117  $form->setId("assmultiplechoice");
1118 
1119  // title, author, description, question, working time (assessment mode)
1120  $this->addBasicQuestionFormProperties($form);
1121  $this->populateQuestionSpecificFormPart($form);
1122  $this->populateAnswerSpecificFormPart($form);
1123  $this->populateTaxonomyFormSection($form);
1124  $this->addQuestionFormCommandButtons($form);
1125  return $form;
1126  }
1127 }
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.
This class represents a selection list property in a property form.
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
This class represents a property form user interface.
$_GET["client_id"]
editQuestion($checkonly=FALSE)
Creates an output of the edit form for the question.
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)
setIsAnswered($a_is_answered)
Show the question as answered in a test run.
getSpecificFeedbackOutput($active_id, $pass)
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
This class represents a checkbox property in a property form.
addItem($a_item)
Add Item (Property, SectionHeader).
$url
Definition: shib_logout.php:72
getQuestionTemplate()
get question template
getTestOutput( $active_id, $pass, $is_postponed=FALSE, $use_post_solutions=FALSE, $show_feedback=FALSE)
setWithNoneAbove($a_with_none_above)
Enable the &#39;None above&#39; addition in a test run.
Class for multiple choice tests.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
removeimagechoice()
Remove an image.
setInfo($a_info)
Set Information Text.
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\+" &#(? foreach( $entity_files as $file) $output
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.
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
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.
Basic GUI class for assessment questions.
static getHtmlPath($relative_path)
get url of path
aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
Create styles array
The data for the language used.
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
getPreview($show_question_only=FALSE, $showInlineFeedback=false)
Create new PHPExcel object
obj_idprivate
addBackTab(ilTabsGUI $ilTabs)
static secureString($a_str, $a_strip_html=true, $a_allow="")
Remove unsecure tags.
Interface ilGuiAnswerScoringAdjustable.
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
Interface ilGuiQuestionScoringAdjustable.
populateSpecificFeedbackInline($user_solution, $answer_id, $template)
$_POST["username"]
setRequired($a_required)
Set Required.
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.
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.