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
4require_once './Modules/TestQuestionPool/classes/class.assQuestionGUI.php';
5require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiQuestionScoringAdjustable.php';
6require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiAnswerScoringAdjustable.php';
7require_once './Modules/Test/classes/inc.AssessmentConstants.php';
8
24{
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';
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) {
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) {
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') {
536 continue;
537 }
538
539 $user_solution[] = $solution_value["value1"];
540 // fau.
541 }
542
543 if (empty($user_solution) && $this->object->getTestPresentationConfig()->isWorkedThrough()) {
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
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}
$filename
Definition: buildRTE.php:89
$_GET["client_id"]
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
Multiple choice question GUI representation.
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
setUseEmptySolutionInputChecked($useEmptySolutionInputChecked)
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question,...
getTestOutput( $active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
getChoiceKeys()
Create the key index numbers for the array of choices.
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
populateSpecificFeedbackInline($user_solution, $answer_id, $template)
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
getPreview($show_question_only=false, $showInlineFeedback=false)
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
getSpecificFeedbackOutput($userSolution)
Returns the answer specific feedback for the question.
getEditAnswersSingleLine($checkonly=false)
Get the single/multiline editing of answers.
populateJavascriptFilesRequiredForWorkForm(ilTemplate $tpl)
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
__construct($id=-1)
assMultipleChoiceGUI constructor
getAnswersFrequency($relevantAnswers, $questionIndex)
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form)
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
setQuestionTabs()
Sets the ILIAS tabs for this question type.
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.
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
writePostData($always=false)
{Evaluates a posted edit form and writes the form data in the question object.integer A positive valu...
Class for multiple choice tests.
Basic GUI class for assessment questions.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.
getILIASPage($html="")
Returns the ILIAS Page around a question.
getQuestionTemplate()
get question template
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
output question page
getUseIntermediateSolution()
Get if intermediate solution should be used for solution output.
addBackTab(ilTabsGUI $ilTabs)
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
getAnswerFeedbackOutput($active_id, $pass)
Returns the answer generic feedback depending on the results of the question.
This class represents a checkbox property in a property form.
This class represents a hidden form property in a property form.
This class represents a multiple choice wizard property in a property form.
This class represents a number property in a property form.
This class represents a property form user interface.
This class represents a selection list property in a property form.
special template class to simplify handling of ITX/PEAR
static secureString($a_str, $a_strip_html=true, $a_allow="")
Remove unsecure tags.
static getHtmlPath($relative_path)
get url of path
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms @access public
$template
if(!array_key_exists('StateId', $_REQUEST)) $id
Interface ilGuiAnswerScoringAdjustable.
Interface ilGuiQuestionScoringAdjustable.
$index
Definition: metadata.php:60
$errors
Definition: index.php:6
$keys
$type
$url
if(isset($_POST['submit'])) $form
global $DIC
Definition: saml.php:7