ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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  protected function writePostData($always = false)
49  {
50  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
51  if (!$hasErrors) {
52  $form = $this->buildEditForm();
53  $form->setValuesByPost();
54  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
58  $this->saveTaxonomyAssignments();
59  return 0;
60  }
61  return 1;
62  }
63 
71  protected function getEditAnswersSingleLine($checkonly = false)
72  {
73  if ($checkonly) {
74  // form posting is checked
75  return ($_POST['types'] == 0) ? true : false;
76  }
77 
78  $lastChange = $this->object->getLastChange();
79  if (empty($lastChange) && !isset($_POST['types'])) {
80  // a new question is edited
81  return $this->object->getMultilineAnswerSetting() ? false : true;
82  } else {
83  // a saved question is edited
84  return $this->object->isSingleline;
85  }
86  }
87 
95  public function editQuestion($checkonly = false)
96  {
97  $save = $this->isSaveCommand();
98  $this->getQuestionTemplate();
99 
100  $form = $this->buildEditForm();
101 
102  $isSingleline = $this->getEditAnswersSingleLine($checkonly);
103  if ($isSingleline) {
104  $form->setMultipart(true);
105  } else {
106  $form->setMultipart(false);
107  }
108 
109  $errors = false;
110 
111  if ($save) {
112  $form->getItemByPostVar('selection_limit')->setMaxValue(count((array) $_POST['choice']['answer']));
113 
114  $form->setValuesByPost();
115  $errors = !$form->checkInput();
116  $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
117  if ($errors) {
118  $checkonly = false;
119  }
120  }
121 
122  if (!$checkonly) {
123  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
124  }
125  return $errors;
126  }
127 
129  {
130  parent::addBasicQuestionFormProperties($form);
131  $form->getItemByPostVar('question')->setInitialRteWidth('100');
132  }
133 
137  public function uploadchoice()
138  {
139  $this->writePostData(true);
140  $position = key($_POST['cmd']['uploadchoice']);
141  $this->editQuestion();
142  }
143 
147  public function removeimagechoice()
148  {
149  $this->writePostData(true);
150  $position = key($_POST['cmd']['removeimagechoice']);
151  $filename = $_POST['choice']['imagename'][$position];
152  $this->object->removeAnswerImage($position);
153  $this->editQuestion();
154  }
155 
159  public function addchoice()
160  {
161  $this->writePostData(true);
162  $position = key($_POST['cmd']['addchoice']);
163  $this->object->addAnswer("", 0, 0, $position+1);
164  $this->editQuestion();
165  }
166 
170  public function removechoice()
171  {
172  $this->writePostData(true);
173  $position = key($_POST['cmd']['removechoice']);
174  $this->object->deleteAnswer($position);
175  $this->editQuestion();
176  }
177 
193  public function getSolutionOutput(
194  $active_id,
195  $pass = null,
196  $graphicalOutput = false,
197  $result_output = false,
198  $show_question_only = true,
199  $show_feedback = false,
200  $show_correct_solution = false,
201  $show_manual_scoring = false,
202  $show_question_text = true
203  ) {
204  // shuffle output
205  $keys = $this->getChoiceKeys();
206 
207  // get the solution of the user for the active pass or from the last pass if allowed
208  $user_solution = array();
209  if (($active_id > 0) && (!$show_correct_solution)) {
210  $solutions =&$this->object->getSolutionValues($active_id, $pass);
211  foreach ($solutions as $idx => $solution_value) {
212  array_push($user_solution, $solution_value["value1"]);
213  }
214  } else {
215  // take the correct solution instead of the user solution
216  foreach ($this->object->answers as $index => $answer) {
217  $points_checked = $answer->getPointsChecked();
218  $points_unchecked = $answer->getPointsUnchecked();
219  if ($points_checked > $points_unchecked) {
220  if ($points_checked > 0) {
221  array_push($user_solution, $index);
222  }
223  }
224  }
225  }
226 
227  // generate the question output
228  include_once "./Services/UICore/classes/class.ilTemplate.php";
229  $template = new ilTemplate("tpl.il_as_qpl_mc_mr_output_solution.html", true, true, "Modules/TestQuestionPool");
230  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
231  foreach ($keys as $answer_id) {
232  $answer = $this->object->answers[$answer_id];
233  if (($active_id > 0) && (!$show_correct_solution)) {
234  if ($graphicalOutput) {
235  // output of ok/not ok icons for user entered solutions
236  $ok = false;
237  $checked = false;
238  foreach ($user_solution as $mc_solution) {
239  if (strcmp($mc_solution, $answer_id) == 0) {
240  $checked = true;
241  }
242  }
243  if ($checked) {
244  if ($answer->getPointsChecked() > $answer->getPointsUnchecked()) {
245  $ok = true;
246  } else {
247  $ok = false;
248  }
249  } else {
250  if ($answer->getPointsChecked() > $answer->getPointsUnchecked()) {
251  $ok = false;
252  } else {
253  $ok = true;
254  }
255  }
256  if ($ok) {
257  $template->setCurrentBlock("icon_ok");
258  $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
259  $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
260  $template->parseCurrentBlock();
261  } else {
262  $template->setCurrentBlock("icon_ok");
263  $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
264  $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
265  $template->parseCurrentBlock();
266  }
267  }
268  }
269  if (strlen($answer->getImage())) {
270  $template->setCurrentBlock("answer_image");
271  if ($this->object->getThumbSize()) {
272  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
273  } else {
274  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $answer->getImage());
275  }
276  $alt = $answer->getImage();
277  if (strlen($answer->getAnswertext())) {
278  $alt = $answer->getAnswertext();
279  }
280  $alt = preg_replace("/<[^>]*?>/", "", $alt);
281  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
282  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
283  $template->parseCurrentBlock();
284  }
285 
286  if ($show_feedback) {
287  if ($this->object->getSpecificFeedbackSetting() == 2) {
288  foreach ($user_solution as $mc_solution) {
289  if (strcmp($mc_solution, $answer_id) == 0) {
290  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
291  $this->object->getId(),
292  $answer_id
293  );
294  if (strlen($fb)) {
295  $template->setCurrentBlock("feedback");
296  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
297  $template->parseCurrentBlock();
298  }
299  }
300  }
301  }
302 
303  if ($this->object->getSpecificFeedbackSetting() == 1) {
304  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
305  $this->object->getId(),
306  $answer_id
307  );
308  if (strlen($fb)) {
309  $template->setCurrentBlock("feedback");
310  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
311  $template->parseCurrentBlock();
312  }
313  }
314 
315  if ($this->object->getSpecificFeedbackSetting() == 3) {
316  $answer = $this->object->getAnswer($answer_id);
317 
318  if ($answer->getPoints() > 0) {
319  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
320  $this->object->getId(),
321  $answer_id
322  );
323  if (strlen($fb)) {
324  $template->setCurrentBlock("feedback");
325  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
326  $template->parseCurrentBlock();
327  }
328  }
329  }
330  }
331  $template->setCurrentBlock("answer_row");
332  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), true));
333  $checked = false;
334  if ($result_output) {
335  $pointschecked = $this->object->answers[$answer_id]->getPointsChecked();
336  $pointsunchecked = $this->object->answers[$answer_id]->getPointsUnchecked();
337  $resulttextchecked = ($pointschecked == 1) || ($pointschecked == -1) ? "%s " . $this->lng->txt("point") : "%s " . $this->lng->txt("points");
338  $resulttextunchecked = ($pointsunchecked == 1) || ($pointsunchecked == -1) ? "%s " . $this->lng->txt("point") : "%s " . $this->lng->txt("points");
339  $template->setVariable("RESULT_OUTPUT", sprintf("(" . $this->lng->txt("checkbox_checked") . " = $resulttextchecked, " . $this->lng->txt("checkbox_unchecked") . " = $resulttextunchecked)", $pointschecked, $pointsunchecked));
340  }
341  foreach ($user_solution as $mc_solution) {
342  if (strcmp($mc_solution, $answer_id) == 0) {
343  if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
344  $template->setVariable("SOLUTION_IMAGE", ilUtil::getHtmlPath(ilUtil::getImagePath("checkbox_checked.png")));
345  $template->setVariable("SOLUTION_ALT", $this->lng->txt("checked"));
346  } else {
347  $template->setVariable('QID', $this->object->getId());
348  $template->setVariable('SUFFIX', $show_correct_solution ? 'bestsolution' : 'usersolution');
349  $template->setVariable('SOLUTION_VALUE', $answer_id);
350  $template->setVariable('SOLUTION_CHECKED', 'checked');
351  }
352  $checked = true;
353  }
354  }
355  if (!$checked) {
356  if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
357  $template->setVariable("SOLUTION_IMAGE", ilUtil::getHtmlPath(ilUtil::getImagePath("checkbox_unchecked.png")));
358  $template->setVariable("SOLUTION_ALT", $this->lng->txt("unchecked"));
359  } else {
360  $template->setVariable('QID', $this->object->getId());
361  $template->setVariable('SUFFIX', $show_correct_solution ? 'bestsolution' : 'usersolution');
362  $template->setVariable('SOLUTION_VALUE', $answer_id);
363  }
364  }
365  $template->parseCurrentBlock();
366  }
367  $questiontext = $this->object->getQuestion();
368  if ($show_question_text==true) {
369  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
370  }
371  $questionoutput = $template->get();
372  $feedback = ($show_feedback && !$this->isTestPresentationContext()) ? $this->getAnswerFeedbackOutput($active_id, $pass) : "";
373 
374  if (strlen($feedback)) {
375  $cssClass = (
376  $this->hasCorrectSolution($active_id, $pass) ?
378  );
379 
380  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
381  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
382  }
383  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
384 
385  $solutionoutput = $solutiontemplate->get();
386  if (!$show_question_only) {
387  // get page object output
388  $solutionoutput = $this->getILIASPage($solutionoutput);
389  }
390  return $solutionoutput;
391  }
392 
393  public function getPreview($show_question_only = false, $showInlineFeedback = false)
394  {
395  $user_solution = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : array();
396  // shuffle output
397  $keys = $this->getChoiceKeys();
398 
399  // generate the question output
400  include_once "./Services/UICore/classes/class.ilTemplate.php";
401  $template = new ilTemplate("tpl.il_as_qpl_mc_mr_output.html", true, true, "Modules/TestQuestionPool");
402  foreach ($keys as $answer_id) {
403  $answer = $this->object->answers[$answer_id];
404  if (strlen($answer->getImage())) {
405  if ($this->object->getThumbSize()) {
406  $template->setCurrentBlock("preview");
407  $template->setVariable("URL_PREVIEW", $this->object->getImagePathWeb() . $answer->getImage());
408  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
409  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
410  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
411  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
412  $alt = $answer->getImage();
413  if (strlen($answer->getAnswertext())) {
414  $alt = $answer->getAnswertext();
415  }
416  $alt = preg_replace("/<[^>]*?>/", "", $alt);
417  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
418  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
419  $template->parseCurrentBlock();
420  } else {
421  $template->setCurrentBlock("answer_image");
422  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $answer->getImage());
423  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
424  $alt = $answer->getImage();
425  if (strlen($answer->getAnswertext())) {
426  $alt = $answer->getAnswertext();
427  }
428  $alt = preg_replace("/<[^>]*?>/", "", $alt);
429  $template->setVariable("ATTR", $attr);
430  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
431  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
432  $template->parseCurrentBlock();
433  }
434  }
435 
436  if ($showInlineFeedback) {
437  $this->populateSpecificFeedbackInline($user_solution, $answer_id, $template);
438  }
439 
440  $template->setCurrentBlock("answer_row");
441  $template->setVariable("QID", $this->object->getId());
442  $template->setVariable("ANSWER_ID", $answer_id);
443  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), true));
444  foreach ($user_solution as $mc_solution) {
445  if (strcmp($mc_solution, $answer_id) == 0) {
446  $template->setVariable("CHECKED_ANSWER", " checked=\"checked\"");
447  }
448  }
449  $template->parseCurrentBlock();
450  }
451  if ($this->object->getSelectionLimit()) {
452  $template->setVariable('SELECTION_LIMIT_HINT', sprintf(
453  $this->lng->txt('ass_mc_sel_lim_hint'),
454  $this->object->getSelectionLimit(),
455  $this->object->getAnswerCount()
456  ));
457 
458  $template->setVariable('SELECTION_LIMIT_VALUE', $this->object->getSelectionLimit());
459  } else {
460  $template->setVariable('SELECTION_LIMIT_VALUE', 'null');
461  }
462  $template->setVariable("QUESTION_ID", $this->object->getId());
463  $questiontext = $this->object->getQuestion();
464  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
465  $questionoutput = $template->get();
466  if (!$show_question_only) {
467  // get page object output
468  $questionoutput = $this->getILIASPage($questionoutput);
469  }
470  return $questionoutput;
471  }
472 
482  public function getTestOutput(
483  $active_id,
484  // hey: prevPassSolutions - will be always available from now on
485  $pass,
486  // hey.
487  $is_postponed = false,
488  $use_post_solutions = false,
489  $show_feedback = false
490  ) {
491  // shuffle output
492  $keys = $this->getChoiceKeys();
493 
494  // get the solution of the user for the active pass or from the last pass if allowed
495  $user_solution = array();
496  if ($active_id) {
497  // hey: prevPassSolutions - obsolete due to central check
498  #$solutions = NULL;
499  #include_once "./Modules/Test/classes/class.ilObjTest.php";
500  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
501  #{
502  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
503  #}
504  $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
505  // hey.
506  foreach ($solutions as $idx => $solution_value) {
507  // fau: testNav - don't add the dummy entry for 'none of the above' to the user options
508  if ($solution_value["value1"] == 'mc_none_above') {
509  $this->setUseEmptySolutionInputChecked(true);
510  continue;
511  }
512 
513  $user_solution[] = $solution_value["value1"];
514  // fau.
515  }
516 
517  if (empty($user_solution) && $this->object->getTestPresentationConfig()->isWorkedThrough()) {
518  $this->setUseEmptySolutionInputChecked(true);
519  }
520  }
521  // generate the question output
522  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilAssMultipleChoice.js');
523  include_once "./Services/UICore/classes/class.ilTemplate.php";
524  $template = new ilTemplate("tpl.il_as_qpl_mc_mr_output.html", true, true, "Modules/TestQuestionPool");
525  foreach ($keys as $answer_id) {
526  $answer = $this->object->answers[$answer_id];
527  if (strlen($answer->getImage())) {
528  if ($this->object->getThumbSize()) {
529  $template->setCurrentBlock("preview");
530  $template->setVariable("URL_PREVIEW", $this->object->getImagePathWeb() . $answer->getImage());
531  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
532  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
533  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
534  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
535  $alt = $answer->getImage();
536  if (strlen($answer->getAnswertext())) {
537  $alt = $answer->getAnswertext();
538  }
539  $alt = preg_replace("/<[^>]*?>/", "", $alt);
540  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
541  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
542  $template->parseCurrentBlock();
543  } else {
544  $template->setCurrentBlock("answer_image");
545  $template->setVariable("ANSWER_IMAGE_URL", $this->object->getImagePathWeb() . $answer->getImage());
546  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
547  $alt = $answer->getImage();
548  if (strlen($answer->getAnswertext())) {
549  $alt = $answer->getAnswertext();
550  }
551  $alt = preg_replace("/<[^>]*?>/", "", $alt);
552  $template->setVariable("ATTR", $attr);
553  $template->setVariable("ANSWER_IMAGE_ALT", ilUtil::prepareFormOutput($alt));
554  $template->setVariable("ANSWER_IMAGE_TITLE", ilUtil::prepareFormOutput($alt));
555  $template->parseCurrentBlock();
556  }
557  }
558 
559  if ($show_feedback) {
560  $this->populateSpecificFeedbackInline($user_solution, $answer_id, $template);
561  }
562 
563  $template->setCurrentBlock("answer_row");
564  $template->setVariable("QID", $this->object->getId());
565  $template->setVariable("ANSWER_ID", $answer_id);
566  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), true));
567  foreach ($user_solution as $mc_solution) {
568  if (strcmp($mc_solution, $answer_id) == 0) {
569  $template->setVariable("CHECKED_ANSWER", " checked=\"checked\"");
570  }
571  }
572  $template->parseCurrentBlock();
573  }
574 
575  $questiontext = $this->object->getQuestion();
576  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
577  $template->setVariable("QUESTION_ID", $this->object->getId());
578  if ($this->object->getSelectionLimit()) {
579  $template->setVariable('SELECTION_LIMIT_HINT', sprintf(
580  $this->lng->txt('ass_mc_sel_lim_hint'),
581  $this->object->getSelectionLimit(),
582  $this->object->getAnswerCount()
583  ));
584 
585  $template->setVariable('SELECTION_LIMIT_VALUE', $this->object->getSelectionLimit());
586  } else {
587  $template->setVariable('SELECTION_LIMIT_VALUE', 'null');
588  }
589  $questionoutput = $template->get();
590  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
591  return $pageoutput;
592  }
593 
594  protected $useEmptySolutionInputChecked = false;
595 
597  {
599  }
600 
602  {
603  $this->useEmptySolutionInputChecked = $useEmptySolutionInputChecked;
604  }
605 
607  {
608  // hey: prevPassSolutions - use abstracted template to share with other purposes of this kind
609  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilAssMultipleChoice.js');
610 
611  $tpl = new ilTemplate('tpl.tst_question_additional_behaviour_checkbox.html', true, true, 'Modules/TestQuestionPool');
612 
613  // HEY: affects next if (!) /// noneAboveChecked repaired but disabled because the checked input ..
614  if (false) { // .. makes the qstEditController initialize the "edit" instead of the "answered" state
615  if ($this->isUseEmptySolutionInputChecked()) {
616  $tpl->setCurrentBlock('checked');
617  $tpl->touchBlock('checked');
618  $tpl->parseCurrentBlock();
619  }
620  }
621 
622  $tpl->setCurrentBlock('checkbox');
623  $tpl->setVariable('TXT_FORCE_FORM_DIFF_LABEL', $this->object->getTestPresentationConfig()->getUseUnchangedAnswerLabel());
624  $tpl->parseCurrentBlock();
625  // hey.
626  return $tpl->get();
627  }
628 
630  {
631  $tpl->addJavaScript('Modules/TestQuestionPool/js/ilAssMultipleChoice.js');
632  }
633 
639  public function setQuestionTabs()
640  {
641  global $rbacsystem, $ilTabs;
642 
643  $ilTabs->clearTargets();
644 
645  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
646  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
647  $q_type = $this->object->getQuestionType();
648 
649  if (strlen($q_type)) {
650  $classname = $q_type . "GUI";
651  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
652  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
653  }
654 
655  if ($_GET["q_id"]) {
656  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
657  // edit page
658  $ilTabs->addTarget(
659  "edit_page",
660  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
661  array("edit", "insert", "exec_pg"),
662  "",
663  "",
664  $force_active
665  );
666  }
667 
668  $this->addTab_QuestionPreview($ilTabs);
669  }
670  $force_active = false;
671  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
672  $url = "";
673  if ($classname) {
674  $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
675  }
676  $force_active = false;
677  // edit question properties
678  $ilTabs->addTarget(
679  "edit_question",
680  $url,
681  array("editQuestion", "save", "saveEdit", "addchoice", "removechoice", "removeimagechoice", "uploadchoice", "originalSyncForm"),
682  $classname,
683  "",
684  $force_active
685  );
686  }
687 
688  // add tab for question feedback within common class assQuestionGUI
689  $this->addTab_QuestionFeedback($ilTabs);
690 
691  // add tab for question hint within common class assQuestionGUI
692  $this->addTab_QuestionHints($ilTabs);
693 
694  // add tab for question's suggested solution within common class assQuestionGUI
695  $this->addTab_SuggestedSolution($ilTabs, $classname);
696 
697  // Assessment of questions sub menu entry
698  if ($_GET["q_id"]) {
699  $ilTabs->addTarget(
700  "statistics",
701  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
702  array("assessment"),
703  $classname,
704  ""
705  );
706  }
707 
708  $this->addBackTab($ilTabs);
709  }
710 
716  public function getChoiceKeys()
717  {
718  $choiceKeys = array_keys($this->object->answers);
719 
720  if ($this->object->getShuffle()) {
721  $choiceKeys = $this->object->getShuffler()->shuffle($choiceKeys);
722  }
723 
724  return $choiceKeys;
725  }
726 
727  public function getSpecificFeedbackOutput($active_id, $pass)
728  {
729  // No return value, this question type supports inline specific feedback.
730  $output = "";
731  return $this->object->prepareTextareaOutput($output, true);
732  }
733 
735  {
736  $this->object->setShuffle($_POST["shuffle"]);
737 
738  $selectionLimit = (int) $form->getItemByPostVar('selection_limit')->getValue();
739  $this->object->setSelectionLimit($selectionLimit > 0 ? $selectionLimit : null);
740 
741  $this->object->setMultilineAnswerSetting($_POST["types"]);
742  if (is_array($_POST['choice']['imagename']) && $_POST["types"] == 1) {
743  $this->object->isSingleline = true;
744  ilUtil::sendInfo($this->lng->txt('info_answer_type_change'), true);
745  } else {
746  $this->object->isSingleline = ($_POST["types"] == 0) ? true : false;
747  }
748  $this->object->setThumbSize((strlen($_POST["thumb_size"])) ? $_POST["thumb_size"] : "");
749  }
750 
752  {
753  // Delete all existing answers and create new answers from the form data
754  $this->object->flushAnswers();
755  if ($this->object->isSingleline) {
756  foreach ($_POST['choice']['answer'] as $index => $answertext) {
757  $answertext = ilUtil::secureString($answertext);
758 
759  $picturefile = $_POST['choice']['imagename'][$index];
760  $file_org_name = $_FILES['choice']['name']['image'][$index];
761  $file_temp_name = $_FILES['choice']['tmp_name']['image'][$index];
762 
763  if (strlen($file_temp_name)) {
764  // check suffix
765  $suffix = strtolower(array_pop(explode(".", $file_org_name)));
766  if (in_array($suffix, array( "jpg", "jpeg", "png", "gif" ))) {
767  // upload image
768  $filename = $this->object->buildHashedImageFilename($file_org_name);
769  if ($this->object->setImageFile($filename, $file_temp_name) == 0) {
770  $picturefile = $filename;
771  }
772  }
773  }
774  $this->object->addAnswer(
775  $answertext,
776  $_POST['choice']['points'][$index],
777  $_POST['choice']['points_unchecked'][$index],
778  $index,
779  $picturefile
780  );
781  }
782  } else {
783  foreach ($_POST['choice']['answer'] as $index => $answer) {
784  $answertext = $answer;
785  $this->object->addAnswer(
786  $answertext,
787  $_POST['choice']['points'][$index],
788  $_POST['choice']['points_unchecked'][$index],
789  $index
790  );
791  }
792  }
793  }
794 
796  {
797  // shuffle
798  $shuffle = new ilCheckboxInputGUI($this->lng->txt("shuffle_answers"), "shuffle");
799  $shuffle->setValue(1);
800  $shuffle->setChecked($this->object->getShuffle());
801  $shuffle->setRequired(false);
802  $form->addItem($shuffle);
803 
804  require_once 'Services/Form/classes/class.ilNumberInputGUI.php';
805  $selLim = new ilNumberInputGUI($this->lng->txt('ass_mc_sel_lim_setting'), 'selection_limit');
806  $selLim->setInfo($this->lng->txt('ass_mc_sel_lim_setting_desc'));
807  $selLim->setSize(2);
808  $selLim->setRequired(false);
809  $selLim->allowDecimals(false);
810  $selLim->setMinvalueShouldBeGreater(false);
811  $selLim->setMaxvalueShouldBeLess(false);
812  $selLim->setMinValue(1);
813  $selLim->setMaxValue($this->object->getAnswerCount());
814  $selLim->setValue($this->object->getSelectionLimit());
815  $form->addItem($selLim);
816 
817  if ($this->object->getId()) {
818  $hidden = new ilHiddenInputGUI("", "ID");
819  $hidden->setValue($this->object->getId());
820  $form->addItem($hidden);
821  }
822 
823  $isSingleline = $this->getEditAnswersSingleLine();
824 
825  if (!$this->object->getSelfAssessmentEditingMode()) {
826  // Answer types
827  $types = new ilSelectInputGUI($this->lng->txt("answer_types"), "types");
828  $types->setRequired(false);
829  $types->setValue(($isSingleline) ? 0 : 1);
830  $types->setOptions(
831  array(
832  0 => $this->lng->txt('answers_singleline'),
833  1 => $this->lng->txt('answers_multiline'),
834  )
835  );
836  $form->addItem($types);
837  }
838 
839  if ($isSingleline) {
840  // thumb size
841  $thumb_size = new ilNumberInputGUI($this->lng->txt("thumb_size"), "thumb_size");
842  $thumb_size->setSuffix($this->lng->txt("thumb_size_unit_pixel"));
843  $thumb_size->setMinValue(20);
844  $thumb_size->setDecimals(0);
845  $thumb_size->setSize(6);
846  $thumb_size->setInfo($this->lng->txt('thumb_size_info'));
847  $thumb_size->setValue($this->object->getThumbSize());
848  $thumb_size->setRequired(false);
849  $form->addItem($thumb_size);
850  return $isSingleline;
851  }
852  return $isSingleline;
853  }
854 
856  {
857  // Choices
858  include_once "./Modules/TestQuestionPool/classes/class.ilMultipleChoiceWizardInputGUI.php";
859  $choices = new ilMultipleChoiceWizardInputGUI($this->lng->txt("answers"), "choice");
860  $choices->setRequired(true);
861  $choices->setQuestionObject($this->object);
862  $isSingleline = $this->getEditAnswersSingleLine();
863  $choices->setSingleline($isSingleline);
864  $choices->setAllowMove(false);
865  if ($this->object->getSelfAssessmentEditingMode()) {
866  $choices->setSize(40);
867  }
868  $choices->setMaxLength(800);
869  if ($this->object->getAnswerCount() == 0) {
870  $this->object->addAnswer("", 0, 0, 0);
871  }
872  $choices->setValues($this->object->getAnswers());
873  $form->addItem($choices);
874  }
875 
886  {
887  return array();
888  }
889 
900  {
901  return array();
902  }
903 
912  public function getAggregatedAnswersView($relevant_answers)
913  {
914  return $this->renderAggregateView(
915  $this->aggregateAnswers($relevant_answers, $this->object->getAnswers())
916  )->get();
917  }
918 
919  public function aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
920  {
921  $aggregate = array();
922  foreach ($answers_defined_on_question as $answer) {
923  $aggregated_info_for_answer = array();
924  $aggregated_info_for_answer['answertext'] = $answer->getAnswerText();
925  $aggregated_info_for_answer['count_checked'] = 0;
926 
927  foreach ($relevant_answers_chosen as $relevant_answer) {
928  if ($relevant_answer['value1'] == $answer->getOrder()) {
929  $aggregated_info_for_answer['count_checked']++;
930  }
931  }
932  $aggregated_info_for_answer['count_unchecked'] =
933  ceil(count($relevant_answers_chosen) / count($answers_defined_on_question))
934  - $aggregated_info_for_answer['count_checked'];
935 
936  $aggregate[] = $aggregated_info_for_answer;
937  }
938  return $aggregate;
939  }
940 
946  public function renderAggregateView($aggregate)
947  {
948  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
949 
950  $tpl->setCurrentBlock('headercell');
951  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_answer_header'));
952  $tpl->parseCurrentBlock();
953 
954  $tpl->setCurrentBlock('headercell');
955  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_frequency_header'));
956  $tpl->parseCurrentBlock();
957 
958  foreach ($aggregate as $line_data) {
959  $tpl->setCurrentBlock('aggregaterow');
960  $tpl->setVariable('OPTION', $line_data['answertext']);
961  $tpl->setVariable('COUNT', $line_data['count_checked']);
962  $tpl->parseCurrentBlock();
963  }
964  return $tpl;
965  }
966 
973  private function populateSpecificFeedbackInline($user_solution, $answer_id, $template)
974  {
975  if ($this->object->getSpecificFeedbackSetting() == 2) {
976  foreach ($user_solution as $mc_solution) {
977  if (strcmp($mc_solution, $answer_id) == 0) {
978  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
979  if (strlen($fb)) {
980  $template->setCurrentBlock("feedback");
981  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
982  $template->parseCurrentBlock();
983  }
984  }
985  }
986  }
987 
988  if ($this->object->getSpecificFeedbackSetting() == 1) {
989  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
990  if (strlen($fb)) {
991  $template->setCurrentBlock("feedback");
992  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
993  $template->parseCurrentBlock();
994  }
995  }
996 
997  if ($this->object->getSpecificFeedbackSetting() == 3) {
998  $answer = $this->object->getAnswer($answer_id);
999 
1000  if ($answer->getPoints() > 0) {
1001  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
1002  if (strlen($fb)) {
1003  $template->setCurrentBlock("feedback");
1004  $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true));
1005  $template->parseCurrentBlock();
1006  }
1007  }
1008  }
1009  }
1010 
1011  // fau: testNav - new functions setWithNoneAbove() and setIsAnswered()
1012  // moved functionality to ilTestQuestionPresentationConfig
1013  // fau.
1014 
1018  protected function buildEditForm()
1019  {
1020  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
1021  $form = new ilPropertyFormGUI();
1022  $form->setFormAction($this->ctrl->getFormAction($this));
1023  $form->setTitle($this->outQuestionType());
1024  $form->setTableWidth("100%");
1025  $form->setId("assmultiplechoice");
1026 
1027  // title, author, description, question, working time (assessment mode)
1033  return $form;
1034  }
1035 }
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
$template
This class represents a property form user interface.
$type
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)
getSpecificFeedbackOutput($active_id, $pass)
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...
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)
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.
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.
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.
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
Definition: index.php:6
Create new PHPExcel object
obj_idprivate
addBackTab(ilTabsGUI $ilTabs)
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.
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
$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.