ILIAS  release_7 Revision v7.30-3-g800a261c036
class.assQuestionGUI.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4use Psr\Http\Message\RequestInterface;
5use Psr\Http\Message\ServerRequestInterface;
6
7require_once './Modules/Test/classes/inc.AssessmentConstants.php';
8require_once 'Modules/Test/classes/class.ilTestExpressPage.php';
9require_once 'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
10require_once 'Modules/Test/classes/class.ilTestExpressPage.php';
11require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
12
23abstract class assQuestionGUI
24{
25 const FORM_MODE_EDIT = 'edit';
26 const FORM_MODE_ADJUST = 'adjust';
27
28 const FORM_ENCODING_URLENCODE = 'application/x-www-form-urlencoded';
29 const FORM_ENCODING_MULTIPART = 'multipart/form-data';
30
31 const SESSION_PREVIEW_DATA_BASE_INDEX = 'ilAssQuestionPreviewAnswers';
32
33 protected const HAS_SPECIAL_QUESTION_COMMANDS = false;
34
42 public $object;
43
45 public $tpl;
46 public $lng;
47 public $error;
49
53 public $request;
54
63
64 private $taxonomyIds = array();
65
66 private $targetGuiClass = null;
67
68 private $questionActionCmd = 'handleQuestionAction';
69
74
79
80 const PRESENTATION_CONTEXT_TEST = 'pContextTest';
81 const PRESENTATION_CONTEXT_RESULTS = 'pContextResults';
82
86 private $presentationContext = null;
87
88 const RENDER_PURPOSE_PLAYBACK = 'renderPurposePlayback';
89 const RENDER_PURPOSE_DEMOPLAY = 'renderPurposeDemoplay';
90 const RENDER_PURPOSE_PREVIEW = 'renderPurposePreview';
91 const RENDER_PURPOSE_PRINT_PDF = 'renderPurposePrintPdf';
92 const RENDER_PURPOSE_INPUT_VALUE = 'renderPurposeInputValue';
93
98
99 const EDIT_CONTEXT_AUTHORING = 'authoring';
100 const EDIT_CONTEXT_ADJUSTMENT = 'adjustment';
101
106
107 // hey: prevPassSolutions - flag to indicate that a previous answer is shown
112 // hey.
113
117 protected $ctrl;
118
122 protected $editForm;
123
128 protected $use_intermediate_solution = false;
129
133 public function __construct()
134 {
135 global $DIC;
136 $lng = $DIC['lng'];
137 $tpl = $DIC['tpl'];
138 $ilCtrl = $DIC['ilCtrl'];
139
140 $this->lng = &$lng;
141 $this->tpl = &$tpl;
142 $this->ctrl = &$ilCtrl;
143 $this->request = $DIC->http()->request();
144
145 $this->ctrl->saveParameter($this, "q_id");
146 $this->ctrl->saveParameter($this, "prev_qid");
147 $this->ctrl->saveParameter($this, "calling_test");
148 $this->ctrl->saveParameter($this, "calling_consumer");
149 $this->ctrl->saveParameter($this, "consumer_context");
150 $this->ctrl->saveParameterByClass('ilAssQuestionPageGUI', 'test_express_mode');
151 $this->ctrl->saveParameterByClass('ilAssQuestionPageGUI', 'calling_consumer');
152 $this->ctrl->saveParameterByClass('ilAssQuestionPageGUI', 'consumer_context');
153 $this->ctrl->saveParameterByClass('ilobjquestionpoolgui', 'test_express_mode');
154 $this->ctrl->saveParameterByClass('ilobjquestionpoolgui', 'calling_consumer');
155 $this->ctrl->saveParameterByClass('ilobjquestionpoolgui', 'consumer_context');
156
157 $this->errormessage = $this->lng->txt("fill_out_all_required_fields");
158 $this->selfassessmenteditingmode = false;
159 $this->new_id_listeners = array();
160 $this->new_id_listener_cnt = 0;
161 $this->navigationGUI = null;
162 }
163
169 public function hasInlineFeedback()
170 {
171 return false;
172 }
173
174 public function addHeaderAction()
175 {
176 }
177
178 public function redrawHeaderAction()
179 {
180 global $DIC; /* @var ILIAS\DI\Container $DIC */
181 echo $this->getHeaderAction() . $DIC->ui()->mainTemplate()->getOnLoadCodeForAsynch();
182 exit;
183 }
184
185 public function getHeaderAction()
186 {
187 global $DIC; /* @var ILIAS\DI\Container $DIC */
188 /* @var ilObjectDataCache $ilObjDataCache */
189 $ilObjDataCache = $DIC['ilObjDataCache'];
190
191 $parentObjType = $ilObjDataCache->lookupType($this->object->getObjId());
192
193 $dispatcher = new ilCommonActionDispatcherGUI(
195 $DIC->access(),
196 $parentObjType,
197 $_GET["ref_id"],
198 $this->object->getObjId()
199 );
200
201 $dispatcher->setSubObject("quest", $this->object->getId());
202
203 $ha = $dispatcher->initHeaderAction();
204 $ha->enableComments(true, false);
205
206 return $ha->getHeaderAction($DIC->ui()->mainTemplate());
207 }
208
209 public function getNotesHTML()
210 {
211 $notesGUI = new ilNoteGUI($this->object->getObjId(), $this->object->getId(), 'quest');
212 $notesGUI->enablePublicNotes(true);
213 $notesGUI->enablePublicNotesDeletion(true);
214
215 return $notesGUI->getNotesHTML();
216 }
217
221 public function executeCommand()
222 {
223 global $DIC;
224 $DIC['ilHelp']->setScreenIdComponent('qpl');
225
226 $next_class = $this->ctrl->getNextClass($this);
227
228 switch ($next_class) {
229 case 'ilformpropertydispatchgui':
230 $form = $this->buildEditForm();
231 $form_prop_dispatch = new ilFormPropertyDispatchGUI();
232 $form_prop_dispatch->setItem($form->getItemByPostVar(ilUtil::stripSlashes($_GET['postvar'])));
233 $this->ctrl->forwardCommand($form_prop_dispatch);
234 break;
235
236 default:
237 $cmd = $this->ctrl->getCmd('editQuestion');
238
239 if (in_array($cmd, ['save', 'saveReturn','saveFQ', 'saveReturnFQ', 'editQuestion'])) {
241 $this->$cmd();
242 return;
243 }
244
245 if (method_exists($this, $cmd)) {
246 $this->$cmd();
247 return;
248 }
249
250 if ($this->hasSpecialQuestionCommands() === true) {
251 $this->callSpecialQuestionCommands($cmd);
252 }
253 }
254 }
255
256 protected function hasSpecialQuestionCommands() : bool
257 {
258 return static::HAS_SPECIAL_QUESTION_COMMANDS;
259 }
260
264 public function getType()
265 {
266 return $this->getQuestionType();
267 }
268
272 public function getPresentationContext()
273 {
275 }
276
281 {
282 $this->presentationContext = $presentationContext;
283 }
284
286 {
288 }
289
290 // hey: previousPassSolutions - setter/getter for Previous Solution Prefilled flag
295 {
297 }
298
303 {
304 $this->previousSolutionPrefilled = $previousSolutionPrefilled;
305 }
306 // hey.
307
311 public function getRenderPurpose()
312 {
314 }
315
320 {
321 $this->renderPurpose = $renderPurpose;
322 }
323
324 public function isRenderPurposePrintPdf()
325 {
327 }
328
329 public function isRenderPurposePreview()
330 {
332 }
333
335 {
337 }
338
339 public function isRenderPurposePlayback()
340 {
342 }
343
344 public function isRenderPurposeDemoplay()
345 {
347 }
348
350 {
351 if ($this->isRenderPurposePrintPdf()) {
352 return false;
353 }
354
355 if ($this->isRenderPurposeInputValue()) {
356 return false;
357 }
358
359 return true;
360 }
361
365 public function getEditContext()
366 {
367 return $this->editContext;
368 }
369
374 {
375 $this->editContext = $editContext;
376 }
377
381 public function isAuthoringEditContext()
382 {
384 }
385
389 public function isAdjustmentEditContext()
390 {
392 }
393
394 public function setAdjustmentEditContext()
395 {
396 return $this->setEditContext(self::EDIT_CONTEXT_ADJUSTMENT);
397 }
398
402 public function getNavigationGUI()
403 {
405 }
406
411 {
412 $this->navigationGUI = $navigationGUI;
413 }
414
416 {
417 $this->taxonomyIds = $taxonomyIds;
418 }
419
420 public function getTaxonomyIds()
421 {
422 return $this->taxonomyIds;
423 }
424
425 public function setTargetGui($linkTargetGui)
426 {
427 $this->setTargetGuiClass(get_class($linkTargetGui));
428 }
429
431 {
432 $this->targetGuiClass = $targetGuiClass;
433 }
434
435 public function getTargetGuiClass()
436 {
438 }
439
444 {
445 $this->questionHeaderBlockBuilder = $questionHeaderBlockBuilder;
446 }
447
448 // fau: testNav - get the question header block bulder (for tweaking)
453 {
455 }
456 // fau.
457
459 {
460 $this->questionActionCmd = $questionActionCmd;
461
462 if (is_object($this->object)) {
463 $this->object->questionActionCmd = $questionActionCmd;
464 }
465 }
466
467 public function getQuestionActionCmd()
468 {
470 }
471
476 protected function writePostData($always = false)
477 {
478 }
479
483 public function assessment()
484 {
488 global $DIC;
489 $tpl = $DIC['tpl'];
490
491 $stats_table = new ilQuestionCumulatedStatisticsTableGUI($this, 'assessment', '', $this->object);
492 $usage_table = new ilQuestionUsagesTableGUI($this, 'assessment', '', $this->object);
493
494 $tpl->setContent(implode('<br />', array(
495 $stats_table->getHTML(),
496 $usage_table->getHTML()
497 )));
498 }
499
509 public static function _getQuestionGUI($question_type, $question_id = -1)
510 {
511 global $DIC;
512 $ilCtrl = $DIC['ilCtrl'];
513 $ilDB = $DIC['ilDB'];
514 $lng = $DIC['lng'];
515
516 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
517
518 if ((!$question_type) and ($question_id > 0)) {
519 $question_type = assQuestion::getQuestionTypeFromDb($question_id);
520 }
521
522 if (strlen($question_type) == 0) {
523 return null;
524 }
525
526 assQuestion::_includeClass($question_type, 1);
527
528 $question_type_gui = assQuestion::getGuiClassNameByQuestionType($question_type);
529 $question = new $question_type_gui();
530
531 $feedbackObjectClassname = assQuestion::getFeedbackClassNameByQuestionType($question_type);
532 $question->object->feedbackOBJ = new $feedbackObjectClassname($question->object, $ilCtrl, $ilDB, $lng);
533
534 if ($question_id > 0) {
535 $question->object->loadFromDb($question_id);
536 }
537
538 return $question;
539 }
540
544 public static function _getGUIClassNameForId($a_q_id)
545 {
546 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
547 include_once "./Modules/TestQuestionPool/classes/class.assQuestionGUI.php";
548 $q_type = assQuestion::getQuestionTypeFromDb($a_q_id);
549 $class_name = assQuestionGUI::_getClassNameForQType($q_type);
550 return $class_name;
551 }
552
556 public static function _getClassNameForQType($q_type)
557 {
558 return $q_type . "GUI";
559 }
560
573 public function &createQuestionGUI($question_type, $question_id = -1)
574 {
575 include_once "./Modules/TestQuestionPool/classes/class.assQuestionGUI.php";
576 $this->question = &assQuestionGUI::_getQuestionGUI($question_type, $question_id);
577 }
578
580 {
581 foreach ($this->getPresentationJavascripts() as $jsFile) {
582 $tpl->addJavaScript($jsFile);
583 }
584 }
585
587 {
588 return array();
589 }
590
594 public function getQuestionTemplate()
595 {
596 // @todo Björn: Maybe this has to be changed for PHP 7/ILIAS 5.2.x (ilObjTestGUI::executeCommand, switch -> default case -> $this->prepareOutput(); already added a template to the CONTENT variable wrapped in a block named content)
597 if (!$this->tpl->blockExists('content')) {
598 $this->tpl->addBlockFile("CONTENT", "content", "tpl.il_as_qpl_content.html", "Modules/TestQuestionPool");
599 }
600 // @todo Björn: Maybe this has to be changed for PHP 7/ILIAS 5.2.x (ilObjTestGUI::executeCommand, switch -> default case -> $this->prepareOutput(); already added a template to the STATUSLINE variable wrapped in a block named statusline)
601 if (!$this->tpl->blockExists('statusline')) {
602 $this->tpl->addBlockFile("STATUSLINE", "statusline", "tpl.statusline.html");
603 }
604 // @todo Björn: Maybe this has to be changed for PHP 7/ILIAS 5.2.x because ass[XYZ]QuestionGUI::editQuestion is called multiple times
605 if (!$this->tpl->blockExists('adm_content')) {
606 $this->tpl->addBlockFile("ADM_CONTENT", "adm_content", "tpl.il_as_question.html", "Modules/TestQuestionPool");
607 }
608 }
609
613 protected function renderEditForm($form)
614 {
615 $this->getQuestionTemplate();
616 $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
617 }
618
625 public function getILIASPage($html = "")
626 {
627 include_once("./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php");
628 $page_gui = new ilAssQuestionPageGUI($this->object->getId());
629 $page_gui->setQuestionHTML(array($this->object->getId() => $html));
630 $presentation = $page_gui->presentation();
631 $presentation = preg_replace("/src=\"\\.\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $presentation);
632 return $presentation;
633 }
634
638 public function outQuestionPage($a_temp_var, $a_postponed = false, $active_id = "", $html = "", $inlineFeedbackEnabled = false)
639 {
640 // hey: prevPassSolutions - add the "use previous answer"
641 // hey: prevPassSolutions - refactored identifiers
642 if ($this->object->getTestPresentationConfig()->isSolutionInitiallyPrefilled()) {
643 // hey
646 } elseif // (!) --> if ($this->object->getTestQuestionConfig()->isUnchangedAnswerPossible())
647 // hey.
648// fau: testNav - add the "use unchanged answer checkbox"
649 // hey: prevPassSolutions - refactored identifiers
650 ($this->object->getTestPresentationConfig()->isUnchangedAnswerPossible()) {
651 // hey.
652 $html .= $this->getUseUnchangedAnswerCheckboxHtml();
653 }
654 // fau.
655
656 $this->lng->loadLanguageModule("content");
657
658 // fau: testNav - add question buttons below question, add actions menu
659 include_once("./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php");
660 $page_gui = new ilAssQuestionPageGUI($this->object->getId());
661 $page_gui->setOutputMode("presentation");
662 $page_gui->setTemplateTargetVar($a_temp_var);
663
664 if ($this->getNavigationGUI()) {
665 $html .= $this->getNavigationGUI()->getHTML();
666 $page_gui->setQuestionActionsHTML($this->getNavigationGUI()->getActionsHTML());
667 }
668 // fau.
669
670 if (strlen($html)) {
671 $page_gui->setQuestionHTML(array($this->object->getId() => $html));
672 }
673
674 // fau: testNav - fill the header with subtitle blocks for question info an actions
675 $page_gui->setPresentationTitle($this->questionHeaderBlockBuilder->getPresentationTitle());
676 $page_gui->setQuestionInfoHTML($this->questionHeaderBlockBuilder->getQuestionInfoHTML());
677 // fau.
678
679 return $page_gui->presentation();
680 }
681
682 // fau: testNav - get the html of the "use unchanged answer checkbox"
684 {
685 // hey: prevPassSolutions - use abstracted template to share with other purposes of this kind
686 $tpl = new ilTemplate('tpl.tst_question_additional_behaviour_checkbox.html', true, true, 'Modules/TestQuestionPool');
687 $tpl->setVariable('TXT_FORCE_FORM_DIFF_LABEL', $this->object->getTestPresentationConfig()->getUseUnchangedAnswerLabel());
688 // hey.
689 return $tpl->get();
690 }
691 // fau.
692
693 // hey: prevPassSolutions - build prev solution message / build "use previous answer checkbox" html
695 {
696 return $this->lng->txt('use_previous_solution_advice');
697 }
698
700 {
701 $tpl = new ilTemplate('tpl.tst_question_additional_behaviour_checkbox.html', true, true, 'Modules/TestQuestionPool');
702 // hey: prevPassSolutions - use abtract template
703 $tpl->setVariable('TXT_FORCE_FORM_DIFF_LABEL', $this->lng->txt('use_previous_solution'));
704 // hey.
705 return $tpl->get();
706 }
707 // hey.
708
712 public function cancel()
713 {
714 if ($_GET["calling_test"]) {
715 $_GET["ref_id"] = $_GET["calling_test"];
716 ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["calling_test"]);
717 } elseif ($_GET["test_ref_id"]) {
718 $_GET["ref_id"] = $_GET["test_ref_id"];
719 ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["test_ref_id"]);
720 } else {
721 if ($_GET["q_id"] > 0) {
722 $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
723 $this->ctrl->redirectByClass("ilAssQuestionPageGUI", "edit");
724 } else {
725 $this->ctrl->redirectByClass("ilobjquestionpoolgui", "questions");
726 }
727 }
728 }
729
734 public function originalSyncForm($return_to = "", $return_to_feedback = '')
735 {
736 if (strlen($return_to)) {
737 $this->ctrl->setParameter($this, "return_to", $return_to);
738 } elseif ($_REQUEST['return_to']) {
739 $this->ctrl->setParameter($this, "return_to", $_REQUEST['return_to']);
740 }
741 if (strlen($return_to_feedback)) {
742 $this->ctrl->setParameter($this, 'return_to_fb', 'true');
743 }
744
745 $this->ctrl->saveParameter($this, 'test_express_mode');
746
747 $template = new ilTemplate("tpl.il_as_qpl_sync_original.html", true, true, "Modules/TestQuestionPool");
748 $template->setVariable("BUTTON_YES", $this->lng->txt("yes"));
749 $template->setVariable("BUTTON_NO", $this->lng->txt("no"));
750 $template->setVariable("FORM_ACTION", $this->ctrl->getFormAction($this));
751 $template->setVariable("TEXT_SYNC", $this->lng->txt("confirm_sync_questions"));
752 $this->tpl->setVariable("ADM_CONTENT", $template->get());
753 }
754
755 public function sync()
756 {
757 $original_id = $this->object->original_id;
758 if ($original_id) {
759 $this->object->syncWithOriginal();
760 }
761 if (strlen($_GET["return_to"])) {
762 $this->ctrl->redirect($this, $_GET["return_to"]);
763 }
764 if (strlen($_REQUEST["return_to_fb"])) {
765 $this->ctrl->redirectByClass('ilAssQuestionFeedbackEditingGUI', 'showFeedbackForm');
766 } else {
767 if (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer']) {
768 $ref_id = (int) $_GET['calling_consumer'];
769 $consumer = ilObjectFactory::getInstanceByRefId($ref_id);
770 if ($consumer instanceof ilQuestionEditingFormConsumer) {
771 ilUtil::redirect($consumer->getQuestionEditingFormBackTarget($_GET['consumer_context']));
772 }
773 require_once 'Services/Link/classes/class.ilLink.php';
775 }
776 $_GET["ref_id"] = $_GET["calling_test"];
777
778 if ($_REQUEST['test_express_mode']) {
780 } else {
781 $this->ctrl->redirectByClass('ilAssQuestionPreviewGUI', ilAssQuestionPreviewGUI::CMD_SHOW);
782 }
783 }
784 }
785
786 public function cancelSync()
787 {
788 if (strlen($_GET["return_to"])) {
789 $this->ctrl->redirect($this, $_GET["return_to"]);
790 }
791 if (strlen($_REQUEST['return_to_fb'])) {
792 $this->ctrl->redirectByClass('ilAssQuestionFeedbackEditingGUI', 'showFeedbackForm');
793 } else {
794 if (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer']) {
795 $ref_id = (int) $_GET['calling_consumer'];
796 $consumer = ilObjectFactory::getInstanceByRefId($ref_id);
797 if ($consumer instanceof ilQuestionEditingFormConsumer) {
798 ilUtil::redirect($consumer->getQuestionEditingFormBackTarget($_GET['consumer_context']));
799 }
800 require_once 'Services/Link/classes/class.ilLink.php';
802 }
803 $_GET["ref_id"] = $_GET["calling_test"];
804
805 if ($_REQUEST['test_express_mode']) {
807 } else {
808 $this->ctrl->redirectByClass('ilAssQuestionPreviewGUI', ilAssQuestionPreviewGUI::CMD_SHOW);
809 }
810 }
811 }
812
816 public function saveEdit()
817 {
818 global $DIC;
819 $ilUser = $DIC['ilUser'];
820
821 $result = $this->writePostData();
822 if ($result == 0) {
823 $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
824 $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
825 $this->object->saveToDb();
826 $originalexists = $this->object->_questionExists($this->object->original_id);
827 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
828 if ($_GET["calling_test"] && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
829 $this->ctrl->redirect($this, "originalSyncForm");
830 } elseif ($_GET["calling_test"]) {
831 $_GET["ref_id"] = $_GET["calling_test"];
832 ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["calling_test"]);
833 return;
834 } elseif ($_GET["test_ref_id"]) {
835 global $DIC;
836 $tree = $DIC['tree'];
837 $ilDB = $DIC['ilDB'];
838 $ilPluginAdmin = $DIC['ilPluginAdmin'];
839
840 include_once("./Modules/Test/classes/class.ilObjTest.php");
841 $_GET["ref_id"] = $_GET["test_ref_id"];
842 $test = new ilObjTest($_GET["test_ref_id"], true);
843
844 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
845 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
846
847 $test->insertQuestion($testQuestionSetConfigFactory->getQuestionSetConfig(), $this->object->getId());
848
849 ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["test_ref_id"]);
850 } else {
851 $this->ctrl->setParameter($this, "q_id", $this->object->getId());
852 $this->editQuestion();
853 if (strcmp($_SESSION["info"], "") != 0) {
854 ilUtil::sendSuccess($_SESSION["info"] . "<br />" . $this->lng->txt("msg_obj_modified"), false);
855 } else {
856 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), false);
857 }
858 $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $this->object->getId());
859 $this->ctrl->redirectByClass("ilAssQuestionPageGUI", "edit");
860 }
861 }
862 }
863
867 public function save()
868 {
869 global $DIC;
870 $ilUser = $DIC['ilUser'];
871 $old_id = $_GET["q_id"];
872 $result = $this->writePostData();
873
874 if ($result == 0) {
875 $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
876 $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
877 $this->object->saveToDb();
878 $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
879
880
881 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
882 if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
883 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
884 $this->ctrl->setParameter($this, 'return_to', 'editQuestion');
885 $this->ctrl->redirect($this, "originalSyncForm");
886 return;
887 } elseif ($_GET["calling_test"]) {
888 require_once 'Modules/Test/classes/class.ilObjTest.php';
889 $test = new ilObjTest($_GET["calling_test"]);
890 if (!assQuestion::_questionExistsInTest($this->object->getId(), $test->getTestId())) {
891 $tree = $DIC['tree'];
892 $ilDB = $DIC['ilDB'];
893 $ilPluginAdmin = $DIC['ilPluginAdmin'];
894
895 include_once("./Modules/Test/classes/class.ilObjTest.php");
896 $_GET["ref_id"] = $_GET["calling_test"];
897 $test = new ilObjTest($_GET["calling_test"], true);
898
899 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
900 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
901
902 $new_id = $test->insertQuestion(
903 $testQuestionSetConfigFactory->getQuestionSetConfig(),
904 $this->object->getId()
905 );
906
907 if (isset($_REQUEST['prev_qid'])) {
908 $test->moveQuestionAfter($this->object->getId() + 1, $_REQUEST['prev_qid']);
909 }
910
911 $this->ctrl->setParameter($this, 'q_id', $new_id);
912 $this->ctrl->setParameter($this, 'calling_test', $_GET['calling_test']);
913 #$this->ctrl->setParameter($this, 'test_ref_id', false);
914 }
915 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
916 $this->ctrl->redirect($this, 'editQuestion');
917 } else {
918 $this->callNewIdListeners($this->object->getId());
919
920 if ($this->object->getId() != $old_id) {
921 // first save
922 $this->ctrl->setParameterByClass($_GET["cmdClass"], "q_id", $this->object->getId());
923 $this->ctrl->setParameterByClass($_GET["cmdClass"], "sel_question_types", $_GET["sel_question_types"]);
924 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
925
926 //global $___test_express_mode;
930 if ($_REQUEST['prev_qid']) {
931 // @todo: bheyser/mbecker wtf? ..... thx@jposselt ....
932 // mbecker: Possible fix: Just instantiate the obj?
933 include_once("./Modules/Test/classes/class.ilObjTest.php");
934 $test = new ilObjTest($_GET["ref_id"], true);
935 $test->moveQuestionAfter($_REQUEST['prev_qid'], $this->object->getId());
936 }
937 if ( /*$___test_express_mode || */ $_REQUEST['express_mode']) {
938 $tree = $DIC['tree'];
939 $ilDB = $DIC['ilDB'];
940 $ilPluginAdmin = $DIC['ilPluginAdmin'];
941
942 include_once("./Modules/Test/classes/class.ilObjTest.php");
943 $test = new ilObjTest($_GET["ref_id"], true);
944
945 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
946 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
947
948 $test->insertQuestion(
949 $testQuestionSetConfigFactory->getQuestionSetConfig(),
950 $this->object->getId()
951 );
952
953 require_once 'Modules/Test/classes/class.ilTestExpressPage.php';
954 $_REQUEST['q_id'] = $this->object->getId();
956 }
957
958 $this->ctrl->redirectByClass($_GET["cmdClass"], "editQuestion");
959 }
960 if (strcmp($_SESSION["info"], "") != 0) {
961 ilUtil::sendSuccess($_SESSION["info"] . "<br />" . $this->lng->txt("msg_obj_modified"), true);
962 } else {
963 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
964 }
965 $this->ctrl->redirect($this, 'editQuestion');
966 }
967 }
968 $tabs = $DIC['ilTabs'];
969 $tabs->setTabActive('edit_question');
970 }
971
975 public function saveReturn()
976 {
977 global $DIC;
978 $ilUser = $DIC['ilUser'];
979 $old_id = $_GET["q_id"];
980 $result = $this->writePostData();
981 if ($result == 0) {
982 $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
983 $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
984 $this->object->saveToDb();
985 $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
986
987 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
988 if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
989 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
990 $this->ctrl->setParameter($this, 'test_express_mode', $_REQUEST['test_express_mode']);
991 $this->ctrl->redirect($this, "originalSyncForm");
992 return;
993 } elseif ($_GET["calling_test"]) {
994 require_once 'Modules/Test/classes/class.ilObjTest.php';
995 $test = new ilObjTest($_GET["calling_test"]);
996 $q_id = $this->object->getId();
997 if (!assQuestion::_questionExistsInTest($this->object->getId(), $test->getTestId())) {
998 $tree = $DIC['tree'];
999 $ilDB = $DIC['ilDB'];
1000 $ilPluginAdmin = $DIC['ilPluginAdmin'];
1001
1002 include_once("./Modules/Test/classes/class.ilObjTest.php");
1003 $_GET["ref_id"] = $_GET["calling_test"];
1004 $test = new ilObjTest($_GET["calling_test"], true);
1005
1006 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1007 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
1008
1009 $new_id = $test->insertQuestion(
1010 $testQuestionSetConfigFactory->getQuestionSetConfig(),
1011 $this->object->getId()
1012 );
1013
1014 $q_id = $new_id;
1015 if (isset($_REQUEST['prev_qid'])) {
1016 $test->moveQuestionAfter($this->object->getId() + 1, $_REQUEST['prev_qid']);
1017 }
1018
1019 $this->ctrl->setParameter($this, 'q_id', $new_id);
1020 $this->ctrl->setParameter($this, 'calling_test', $_GET['calling_test']);
1021 }
1022 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1023 $this->ctrl->setParameterByClass('ilAssQuestionPreviewGUI', 'q_id', $q_id);
1024 $this->ctrl->redirectByClass('ilAssQuestionPreviewGUI', ilAssQuestionPreviewGUI::CMD_SHOW);
1025 } else {
1026 if ($this->object->getId() != $old_id) {
1027 $this->callNewIdListeners($this->object->getId());
1028 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1029 $this->ctrl->redirectByClass("ilobjquestionpoolgui", "questions");
1030 }
1031 if (strcmp($_SESSION["info"], "") != 0) {
1032 ilUtil::sendSuccess($_SESSION["info"] . "<br />" . $this->lng->txt("msg_obj_modified"), true);
1033 } else {
1034 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1035 }
1036 $this->ctrl->redirectByClass('ilAssQuestionPreviewGUI', ilAssQuestionPreviewGUI::CMD_SHOW);
1037 }
1038 }
1039 $tabs = $DIC['ilTabs'];
1040 $tabs->setTabActive('edit_question');
1041 }
1042
1046 public function apply()
1047 {
1048 $this->writePostData();
1049 $this->object->saveToDb();
1050 $this->ctrl->setParameter($this, "q_id", $this->object->getId());
1051 $this->editQuestion();
1052 }
1053
1060 public function getContextPath($cont_obj, $a_endnode_id, $a_startnode_id = 1)
1061 {
1062 $path = "";
1063
1064 $tmpPath = $cont_obj->getLMTree()->getPathFull($a_endnode_id, $a_startnode_id);
1065
1066 // count -1, to exclude the learning module itself
1067 for ($i = 1; $i < (count($tmpPath) - 1); $i++) {
1068 if ($path != "") {
1069 $path .= " > ";
1070 }
1071
1072 $path .= $tmpPath[$i]["title"];
1073 }
1074
1075 return $path;
1076 }
1077
1078 public function setSequenceNumber($nr)
1079 {
1080 $this->sequence_no = $nr;
1081 }
1082
1083 public function getSequenceNumber()
1084 {
1085 return $this->sequence_no;
1086 }
1087
1088 public function setQuestionCount($a_question_count)
1089 {
1090 $this->question_count = $a_question_count;
1091 }
1092
1093 public function getQuestionCount()
1094 {
1095 return $this->question_count;
1096 }
1097
1098 public function getErrorMessage()
1099 {
1100 return $this->errormessage;
1101 }
1102
1104 {
1105 $this->errormessage = $errormessage;
1106 }
1107
1109 {
1110 $this->errormessage .= ((strlen($this->errormessage)) ? "<br />" : "") . $errormessage;
1111 }
1112
1113 public function outAdditionalOutput()
1114 {
1115 }
1116
1125 public function getQuestionType()
1126 {
1127 return $this->object->getQuestionType();
1128 }
1129
1137 public function getAsValueAttribute($a_value)
1138 {
1139 $result = "";
1140 if (strlen($a_value)) {
1141 $result = " value=\"$a_value\" ";
1142 }
1143 return $result;
1144 }
1145
1146 // scorm2004-start
1151 public function addNewIdListener(&$a_object, $a_method, $a_parameters = "")
1152 {
1153 $cnt = $this->new_id_listener_cnt;
1154 $this->new_id_listeners[$cnt]["object"] = &$a_object;
1155 $this->new_id_listeners[$cnt]["method"] = $a_method;
1156 $this->new_id_listeners[$cnt]["parameters"] = $a_parameters;
1157 $this->new_id_listener_cnt++;
1158 }
1159
1163 public function callNewIdListeners($a_new_id)
1164 {
1165 for ($i = 0; $i < $this->new_id_listener_cnt; $i++) {
1166 $this->new_id_listeners[$i]["parameters"]["new_id"] = $a_new_id;
1167 $object = &$this->new_id_listeners[$i]["object"];
1168 $method = $this->new_id_listeners[$i]["method"];
1169 $parameters = $this->new_id_listeners[$i]["parameters"];
1170 //var_dump($object);
1171 //var_dump($method);
1172 //var_dump($parameters);
1173
1174 $object->$method($parameters);
1175 }
1176 }
1177
1181 public function addQuestionFormCommandButtons($form)
1182 {
1183 //if (!$this->object->getSelfAssessmentEditingMode() && !$_GET["calling_test"]) $form->addCommandButton("saveEdit", $this->lng->txt("save_edit"));
1184 if (!$this->object->getSelfAssessmentEditingMode()) {
1185 $form->addCommandButton("saveReturn", $this->lng->txt("save_return"));
1186 }
1187 $form->addCommandButton("save", $this->lng->txt("save"));
1188 }
1189
1196 public function addBasicQuestionFormProperties($form)
1197 {
1198 // title
1199 $title = new ilTextInputGUI($this->lng->txt("title"), "title");
1200 $title->setMaxLength(100);
1201 $title->setValue($this->object->getTitle());
1202 $title->setRequired(true);
1203 $form->addItem($title);
1204
1205 if (!$this->object->getSelfAssessmentEditingMode()) {
1206 // author
1207 $author = new ilTextInputGUI($this->lng->txt("author"), "author");
1208 $author->setValue($this->object->getAuthor());
1209 $author->setRequired(true);
1210 $form->addItem($author);
1211
1212 // description
1213 $description = new ilTextInputGUI($this->lng->txt("description"), "comment");
1214 $description->setValue($this->object->getComment());
1215 $description->setRequired(false);
1216 $form->addItem($description);
1217 } else {
1218 // author as hidden field
1219 $hi = new ilHiddenInputGUI("author");
1220 $author = ilUtil::prepareFormOutput($this->object->getAuthor());
1221 if (trim($author) == "") {
1222 $author = "-";
1223 }
1224 $hi->setValue($author);
1225 $form->addItem($hi);
1226 }
1227
1228 // lifecycle
1229 $lifecycle = new ilSelectInputGUI($this->lng->txt('qst_lifecycle'), 'lifecycle');
1230 $lifecycle->setOptions($this->object->getLifecycle()->getSelectOptions($this->lng));
1231 $lifecycle->setValue($this->object->getLifecycle()->getIdentifier());
1232 $form->addItem($lifecycle);
1233
1234 // questiontext
1235 $question = new ilTextAreaInputGUI($this->lng->txt("question"), "question");
1236 $question->setValue($this->object->getQuestion());
1237 $question->setRequired(true);
1238 $question->setRows(10);
1239 $question->setCols(80);
1240
1241 if (!$this->object->getSelfAssessmentEditingMode()) {
1242 if ($this->object->getAdditionalContentEditingMode() != assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_IPE) {
1243 $question->setUseRte(true);
1244 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
1245 $question->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
1246 $question->addPlugin("latex");
1247 $question->addButton("latex");
1248 $question->addButton("pastelatex");
1249 $question->setRTESupport($this->object->getId(), "qpl", "assessment");
1250 }
1251 } else {
1252 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
1254 $question->setUseTagsForRteOnly(false);
1255 }
1256 $form->addItem($question);
1257
1258 if (!$this->object->getSelfAssessmentEditingMode()) {
1259 // duration
1260 $duration = new ilDurationInputGUI($this->lng->txt("working_time"), "Estimated");
1261 $duration->setShowHours(true);
1262 $duration->setShowMinutes(true);
1263 $duration->setShowSeconds(true);
1264 $ewt = $this->object->getEstimatedWorkingTime();
1265 $duration->setHours($ewt["h"]);
1266 $duration->setMinutes($ewt["m"]);
1267 $duration->setSeconds($ewt["s"]);
1268 $duration->setRequired(false);
1269 $form->addItem($duration);
1270 } else {
1271 // number of tries
1272 if (strlen($this->object->getNrOfTries())) {
1273 $nr_tries = $this->object->getNrOfTries();
1274 } else {
1275 $nr_tries = $this->object->getDefaultNrOfTries();
1276 }
1277 if ($nr_tries < 1) {
1278 $nr_tries = "";
1279 }
1280
1281 $ni = new ilNumberInputGUI($this->lng->txt("qst_nr_of_tries"), "nr_of_tries");
1282 $ni->setValue($nr_tries);
1283 $ni->setMinValue(0);
1284 $ni->setSize(5);
1285 $ni->setMaxLength(5);
1286 $form->addItem($ni);
1287 }
1288 }
1289
1290 protected function saveTaxonomyAssignments()
1291 {
1292 if (count($this->getTaxonomyIds())) {
1293 require_once 'Services/Taxonomy/classes/class.ilTaxAssignInputGUI.php';
1294
1295 foreach ($this->getTaxonomyIds() as $taxonomyId) {
1296 $postvar = "tax_node_assign_$taxonomyId";
1297
1298 $tax_node_assign = new ilTaxAssignInputGUI($taxonomyId, true, '', $postvar);
1299 // TODO: determine tst/qpl when tax assigns become maintainable within tests
1300 $tax_node_assign->saveInput("qpl", $this->object->getObjId(), "quest", $this->object->getId());
1301 }
1302 }
1303 }
1304
1306 {
1307 if ($this->getTaxonomyIds() !== []) {
1308 // this is needed by ilTaxSelectInputGUI in some cases
1309 require_once 'Services/UIComponent/Overlay/classes/class.ilOverlayGUI.php';
1310 ilOverlayGUI::initJavaScript();
1311
1312 $sectHeader = new ilFormSectionHeaderGUI();
1313 $sectHeader->setTitle($this->lng->txt('qpl_qst_edit_form_taxonomy_section'));
1314 $form->addItem($sectHeader);
1315
1316 require_once 'Services/Taxonomy/classes/class.ilTaxSelectInputGUI.php';
1317
1318 foreach ($this->getTaxonomyIds() as $taxonomyId) {
1319 $taxonomy = new ilObjTaxonomy($taxonomyId);
1320 $label = sprintf($this->lng->txt('qpl_qst_edit_form_taxonomy'), $taxonomy->getTitle());
1321 $postvar = "tax_node_assign_$taxonomyId";
1322
1323 $taxSelect = new ilTaxSelectInputGUI($taxonomy->getId(), $postvar, true);
1324 $taxSelect->setTitle($label);
1325
1326 require_once 'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
1327 $taxNodeAssignments = new ilTaxNodeAssignment(ilObject::_lookupType($this->object->getObjId()), $this->object->getObjId(), 'quest', $taxonomyId);
1328 $assignedNodes = $taxNodeAssignments->getAssignmentsOfItem($this->object->getId());
1329
1330 $taxSelect->setValue(array_map(function ($assignedNode) {
1331 return $assignedNode['node_id'];
1332 }, $assignedNodes));
1333 $form->addItem($taxSelect);
1334 }
1335 }
1336 }
1337
1347 public function getAnswerFeedbackOutput($active_id, $pass)
1348 {
1349 return $this->getGenericFeedbackOutput($active_id, $pass);
1350 }
1351
1361 public function getGenericFeedbackOutput($active_id, $pass)
1362 {
1363 $output = "";
1364 include_once "./Modules/Test/classes/class.ilObjTest.php";
1365 $manual_feedback = ilObjTest::getManualFeedback($active_id, $this->object->getId(), $pass);
1366 if (strlen($manual_feedback)) {
1367 return $manual_feedback;
1368 }
1369
1370 $correct_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true);
1371 $incorrect_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false);
1372 if (strlen($correct_feedback . $incorrect_feedback)) {
1373 $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
1374 $max_points = $this->object->getMaximumPoints();
1375 if ($reached_points == $max_points) {
1376 $output = $correct_feedback;
1377 } else {
1378 $output = $incorrect_feedback;
1379 }
1380 }
1381
1382 if ($this->object->isAdditionalContentEditingModePageObject()) {
1383 return $output;
1384 }
1385 return $this->object->prepareTextareaOutput($output, true);
1386 }
1387
1389 {
1390 return $this->object->prepareTextareaOutput(
1391 $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true),
1392 true
1393 );
1394 }
1395
1397 {
1398 return $this->object->prepareTextareaOutput(
1399 $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false),
1400 true
1401 );
1402 }
1403
1414 abstract public function getSpecificFeedbackOutput($userSolution);
1415
1416 public function outQuestionType()
1417 {
1418 $count = $this->object->isInUse();
1419
1420 if ($this->object->_questionExistsInPool($this->object->getId()) && $count) {
1421 global $DIC;
1422 $rbacsystem = $DIC['rbacsystem'];
1423 if ($rbacsystem->checkAccess("write", $_GET["ref_id"])) {
1424 ilUtil::sendInfo(sprintf($this->lng->txt("qpl_question_is_in_use"), $count));
1425 }
1426 }
1427
1428 return assQuestion::_getQuestionTypeName($this->object->getQuestionType());
1429 }
1430
1431 public function showSuggestedSolution()
1432 {
1433 $this->suggestedsolution();
1434 }
1435
1441 public function suggestedsolution()
1442 {
1443 global $DIC;
1444 $ilUser = $DIC['ilUser'];
1445 $ilAccess = $DIC['ilAccess'];
1446
1447 $save = (is_array($_POST["cmd"]) && array_key_exists("suggestedsolution", $_POST["cmd"])) ? true : false;
1448
1449 if ($save && $_POST["deleteSuggestedSolution"] == 1) {
1450 $this->object->deleteSuggestedSolutions();
1451 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1452 $this->ctrl->redirect($this, "suggestedsolution");
1453 }
1454
1455 $output = "";
1456 $solution_array = $this->object->getSuggestedSolution(0);
1457 $options = array(
1458 "lm" => $this->lng->txt("obj_lm"),
1459 "st" => $this->lng->txt("obj_st"),
1460 "pg" => $this->lng->txt("obj_pg"),
1461 "git" => $this->lng->txt("glossary_term"),
1462 "file" => $this->lng->txt("fileDownload"),
1463 "text" => $this->lng->txt("solutionText")
1464 );
1465
1466 if ((strcmp($_POST["solutiontype"], "file") == 0) && (strcmp($solution_array["type"], "file") != 0)) {
1467 $solution_array = array(
1468 "type" => "file"
1469 );
1470 } elseif ((strcmp($_POST["solutiontype"], "text") == 0) && (strcmp($solution_array["type"], "text") != 0)) {
1471 $oldOutputMode = $this->getRenderPurpose();
1472 $this->setRenderPurpose(self::RENDER_PURPOSE_INPUT_VALUE);
1473
1474 $solution_array = array(
1475 "type" => "text",
1476 "value" => $this->getSolutionOutput(0, null, false, false, true, false, true)
1477 );
1478 $this->setRenderPurpose($oldsaveSuggestedSolutionOutputMode);
1479 }
1480 if ($save && strlen($_POST["filename"])) {
1481 $solution_array["value"]["filename"] = $_POST["filename"];
1482 }
1483 if ($save && strlen($_POST["solutiontext"])) {
1484 $solution_array["value"] = $_POST["solutiontext"];
1485 }
1486 include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
1487 if (count($solution_array)) {
1488 $form = new ilPropertyFormGUI();
1489 $form->setFormAction($this->ctrl->getFormAction($this));
1490 $form->setTitle($this->lng->txt("solution_hint"));
1491 $form->setMultipart(true);
1492 $form->setTableWidth("100%");
1493 $form->setId("suggestedsolutiondisplay");
1494
1495 // suggested solution output
1496 include_once "./Modules/TestQuestionPool/classes/class.ilSolutionTitleInputGUI.php";
1497 $title = new ilSolutionTitleInputGUI($this->lng->txt("showSuggestedSolution"), "solutiontype");
1498 $template = new ilTemplate("tpl.il_as_qpl_suggested_solution_input_presentation.html", true, true, "Modules/TestQuestionPool");
1499 if (strlen($solution_array["internal_link"])) {
1500 $href = assQuestion::_getInternalLinkHref($solution_array["internal_link"]);
1501 $template->setCurrentBlock("preview");
1502 $template->setVariable("TEXT_SOLUTION", $this->lng->txt("suggested_solution"));
1503 $template->setVariable("VALUE_SOLUTION", " <a href=\"$href\" target=\"content\">" . $this->lng->txt("view") . "</a> ");
1504 $template->parseCurrentBlock();
1505 } elseif ((strcmp($solution_array["type"], "file") == 0) && (is_array($solution_array["value"]))) {
1506 $href = $this->object->getSuggestedSolutionPathWeb() . $solution_array["value"]["name"];
1507 $template->setCurrentBlock("preview");
1508 $template->setVariable("TEXT_SOLUTION", $this->lng->txt("suggested_solution"));
1509 $template->setVariable("VALUE_SOLUTION", " <a href=\"$href\" target=\"content\">" . ilUtil::prepareFormOutput((strlen($solution_array["value"]["filename"])) ? $solution_array["value"]["filename"] : $solution_array["value"]["name"]) . "</a> ");
1510 $template->parseCurrentBlock();
1511 }
1512 $template->setVariable("TEXT_TYPE", $this->lng->txt("type"));
1513 $template->setVariable("VALUE_TYPE", $options[$solution_array["type"]]);
1514 $title->setHtml($template->get());
1515 $deletesolution = new ilCheckboxInputGUI("", "deleteSuggestedSolution");
1516 $deletesolution->setOptionTitle($this->lng->txt("deleteSuggestedSolution"));
1517 $title->addSubItem($deletesolution);
1518 $form->addItem($title);
1519
1520 if (strcmp($solution_array["type"], "file") == 0) {
1521 // file
1522 $file = new ilFileInputGUI($this->lng->txt("fileDownload"), "file");
1523 $file->setRequired(true);
1524 $file->enableFileNameSelection("filename");
1525 //$file->setSuffixes(array("doc","xls","png","jpg","gif","pdf"));
1526 if ($_FILES["file"]["tmp_name"] && $file->checkInput()) {
1527 if (!file_exists($this->object->getSuggestedSolutionPath())) {
1528 ilUtil::makeDirParents($this->object->getSuggestedSolutionPath());
1529 }
1530
1531 $res = ilUtil::moveUploadedFile($_FILES["file"]["tmp_name"], $_FILES["file"]["name"], $this->object->getSuggestedSolutionPath() . $_FILES["file"]["name"]);
1532 if ($res) {
1533 ilUtil::renameExecutables($this->object->getSuggestedSolutionPath());
1534
1535 // remove an old file download
1536 if (is_array($solution_array["value"])) {
1537 @unlink($this->object->getSuggestedSolutionPath() . $solution_array["value"]["name"]);
1538 }
1539 $file->setValue($_FILES["file"]["name"]);
1540 $this->object->saveSuggestedSolution("file", "", 0, array("name" => $_FILES["file"]["name"], "type" => $_FILES["file"]["type"], "size" => $_FILES["file"]["size"], "filename" => $_POST["filename"]));
1541 $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
1542 if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
1543 return $this->originalSyncForm("suggestedsolution");
1544 } else {
1545 ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1546 $this->ctrl->redirect($this, "suggestedsolution");
1547 }
1548 } else {
1549 // BH: $res as info string? wtf? it holds a bool or something else!!?
1551 }
1552 } else {
1553 if (is_array($solution_array["value"])) {
1554 $file->setValue($solution_array["value"]["name"]);
1555 $file->setFilename((strlen($solution_array["value"]["filename"])) ? $solution_array["value"]["filename"] : $solution_array["value"]["name"]);
1556 }
1557 }
1558 $form->addItem($file);
1559 $hidden = new ilHiddenInputGUI("solutiontype");
1560 $hidden->setValue("file");
1561 $form->addItem($hidden);
1562 } elseif (strcmp($solution_array["type"], "text") == 0) {
1563 $solutionContent = $solution_array['value'];
1564 $solutionContent = $this->object->fixSvgToPng($solutionContent);
1565 $solutionContent = $this->object->fixUnavailableSkinImageSources($solutionContent);
1566 $question = new ilTextAreaInputGUI($this->lng->txt("solutionText"), "solutiontext");
1567 $question->setValue($this->object->prepareTextareaOutput($solutionContent));
1568 $question->setRequired(true);
1569 $question->setRows(10);
1570 $question->setCols(80);
1571 $question->setUseRte(true);
1572 $question->addPlugin("latex");
1573 $question->addButton("latex");
1574 $question->setRTESupport($this->object->getId(), "qpl", "assessment");
1575 $hidden = new ilHiddenInputGUI("solutiontype");
1576 $hidden->setValue("text");
1577 $form->addItem($hidden);
1578 $form->addItem($question);
1579 }
1580 if ($ilAccess->checkAccess("write", "", $_GET['ref_id'])) {
1581 $form->addCommandButton('showSuggestedSolution', $this->lng->txt('cancel'));
1582 $form->addCommandButton('suggestedsolution', $this->lng->txt('save'));
1583 }
1584
1585 if ($save) {
1586 if ($form->checkInput()) {
1587 switch ($solution_array["type"]) {
1588 case "file":
1589 $this->object->saveSuggestedSolution("file", "", 0, array(
1590 "name" => $solution_array["value"]["name"],
1591 "type" => $solution_array["value"]["type"],
1592 "size" => $solution_array["value"]["size"],
1593 "filename" => $_POST["filename"]
1594 ));
1595 break;
1596 case "text":
1597 $this->object->saveSuggestedSolution("text", "", 0, $solution_array["value"]);
1598 break;
1599 }
1600 $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
1601 if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
1602 return $this->originalSyncForm("suggestedsolution");
1603 } else {
1604 ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1605 $this->ctrl->redirect($this, "suggestedsolution");
1606 }
1607 }
1608 }
1609
1610 $output = $form->getHTML();
1611 }
1612
1613 $savechange = (strcmp($this->ctrl->getCmd(), "saveSuggestedSolution") == 0) ? true : false;
1614
1615 $changeoutput = "";
1616 if ($ilAccess->checkAccess("write", "", $_GET['ref_id'])) {
1617 $formchange = new ilPropertyFormGUI();
1618 $formchange->setFormAction($this->ctrl->getFormAction($this));
1619 $formchange->setTitle((count($solution_array)) ? $this->lng->txt("changeSuggestedSolution") : $this->lng->txt("addSuggestedSolution"));
1620 $formchange->setMultipart(false);
1621 $formchange->setTableWidth("100%");
1622 $formchange->setId("suggestedsolution");
1623
1624 $solutiontype = new ilRadioGroupInputGUI($this->lng->txt("suggestedSolutionType"), "solutiontype");
1625 foreach ($options as $opt_value => $opt_caption) {
1626 $solutiontype->addOption(new ilRadioOption($opt_caption, $opt_value));
1627 }
1628 if (count($solution_array)) {
1629 $solutiontype->setValue($solution_array["type"]);
1630 }
1631 $solutiontype->setRequired(true);
1632 $formchange->addItem($solutiontype);
1633
1634 $formchange->addCommandButton("saveSuggestedSolution", $this->lng->txt("select"));
1635
1636 if ($savechange) {
1637 $formchange->checkInput();
1638 }
1639 $changeoutput = $formchange->getHTML();
1640 }
1641
1642 $this->tpl->setVariable("ADM_CONTENT", $changeoutput . $output);
1643 }
1644
1645 public function outSolutionExplorer()
1646 {
1647 global $DIC;
1648 $tree = $DIC['tree'];
1649
1650 include_once("./Modules/TestQuestionPool/classes/class.ilSolutionExplorer.php");
1651 $type = $_GET["link_new_type"];
1652 $search = $_GET["search_link_type"];
1653 $this->ctrl->setParameter($this, "link_new_type", $type);
1654 $this->ctrl->setParameter($this, "search_link_type", $search);
1655 $this->ctrl->saveParameter($this, array("subquestion_index", "link_new_type", "search_link_type"));
1656
1657 ilUtil::sendInfo($this->lng->txt("select_object_to_link"));
1658
1659 $parent_ref_id = $tree->getParentId($_GET["ref_id"]);
1660 $exp = new ilSolutionExplorer($this->ctrl->getLinkTarget($this, 'suggestedsolution'), get_class($this));
1661 $exp->setExpand($_GET['expand_sol'] ? $_GET['expand_sol'] : $parent_ref_id);
1662 $exp->setExpandTarget($this->ctrl->getLinkTarget($this, 'outSolutionExplorer'));
1663 $exp->setTargetGet("ref_id");
1664 $exp->setRefId($_GET["ref_id"]);
1665 $exp->addFilter($type);
1666 $exp->setSelectableType($type);
1667 if (isset($_GET['expandCurrentPath']) && $_GET['expandCurrentPath']) {
1668 $exp->expandPathByRefId($parent_ref_id);
1669 }
1670
1671 // build html-output
1672 $exp->setOutput(0);
1673
1674 $template = new ilTemplate("tpl.il_as_qpl_explorer.html", true, true, "Modules/TestQuestionPool");
1675 $template->setVariable("EXPLORER_TREE", $exp->getOutput());
1676 $template->setVariable("BUTTON_CANCEL", $this->lng->txt("cancel"));
1677 $template->setVariable("FORMACTION", $this->ctrl->getFormAction($this, "suggestedsolution"));
1678 $this->tpl->setVariable("ADM_CONTENT", $template->get());
1679 }
1680
1681 public function saveSuggestedSolution()
1682 {
1683 global $DIC;
1684 $tree = $DIC['tree'];
1685
1686 include_once("./Modules/TestQuestionPool/classes/class.ilSolutionExplorer.php");
1687 switch ($_POST["solutiontype"]) {
1688 case "lm":
1689 $type = "lm";
1690 $search = "lm";
1691 break;
1692 case "git":
1693 $type = "glo";
1694 $search = "glo";
1695 break;
1696 case "st":
1697 $type = "lm";
1698 $search = "st";
1699 break;
1700 case "pg":
1701 $type = "lm";
1702 $search = "pg";
1703 break;
1704 case "file":
1705 case "text":
1706 return $this->suggestedsolution();
1707 break;
1708 default:
1709 return $this->suggestedsolution();
1710 break;
1711 }
1712 if (isset($_POST['solutiontype'])) {
1713 $this->ctrl->setParameter($this, 'expandCurrentPath', 1);
1714 }
1715 $this->ctrl->setParameter($this, "link_new_type", $type);
1716 $this->ctrl->setParameter($this, "search_link_type", $search);
1717 $this->ctrl->redirect($this, "outSolutionExplorer");
1718 }
1719
1720 public function cancelExplorer()
1721 {
1722 $this->ctrl->redirect($this, "suggestedsolution");
1723 }
1724
1725 public function outPageSelector()
1726 {
1727 require_once 'Modules/TestQuestionPool/classes/tables/class.ilQuestionInternalLinkSelectionTableGUI.php';
1728 require_once 'Modules/LearningModule/classes/class.ilLMPageObject.php';
1729 require_once 'Modules/LearningModule/classes/class.ilObjContentObjectGUI.php';
1730
1731 $this->ctrl->setParameter($this, 'q_id', $this->object->getId());
1732
1733 $cont_obj_gui = new ilObjContentObjectGUI('', $_GET['source_id'], true);
1734 $cont_obj = $cont_obj_gui->object;
1735 $pages = ilLMPageObject::getPageList($cont_obj->getId());
1736 $shownpages = array();
1737 $tree = $cont_obj->getLMTree();
1738 $chapters = $tree->getSubtree($tree->getNodeData($tree->getRootId()));
1739
1740 $rows = array();
1741
1742 foreach ($chapters as $chapter) {
1743 $chapterpages = $tree->getChildsByType($chapter['obj_id'], 'pg');
1744 foreach ($chapterpages as $page) {
1745 if ($page['type'] == $_GET['search_link_type']) {
1746 array_push($shownpages, $page['obj_id']);
1747
1748 if ($tree->isInTree($page['obj_id'])) {
1749 $path_str = $this->getContextPath($cont_obj, $page['obj_id']);
1750 } else {
1751 $path_str = '---';
1752 }
1753
1754 $this->ctrl->setParameter($this, $page['type'], $page['obj_id']);
1755 $rows[] = array(
1756 'title' => $page['title'],
1757 'description' => ilUtil::prepareFormOutput($path_str),
1758 'text_add' => $this->lng->txt('add'),
1759 'href_add' => $this->ctrl->getLinkTarget($this, 'add' . strtoupper($page['type']))
1760 );
1761 }
1762 }
1763 }
1764 foreach ($pages as $page) {
1765 if (!in_array($page['obj_id'], $shownpages)) {
1766 $this->ctrl->setParameter($this, $page['type'], $page['obj_id']);
1767 $rows[] = array(
1768 'title' => $page['title'],
1769 'description' => '---',
1770 'text_add' => $this->lng->txt('add'),
1771 'href_add' => $this->ctrl->getLinkTarget($this, 'add' . strtoupper($page['type']))
1772 );
1773 }
1774 }
1775
1776 require_once 'Modules/TestQuestionPool/classes/tables/class.ilQuestionInternalLinkSelectionTableGUI.php';
1777 $table = new ilQuestionInternalLinkSelectionTableGUI($this, 'cancelExplorer', __METHOD__);
1778 $table->setTitle($this->lng->txt('obj_' . ilUtil::stripSlashes($_GET['search_link_type'])));
1779 $table->setData($rows);
1780
1781 $this->tpl->setContent($table->getHTML());
1782 }
1783
1784 public function outChapterSelector()
1785 {
1786 require_once 'Modules/TestQuestionPool/classes/tables/class.ilQuestionInternalLinkSelectionTableGUI.php';
1787 require_once 'Modules/LearningModule/classes/class.ilObjContentObjectGUI.php';
1788
1789 $this->ctrl->setParameter($this, 'q_id', $this->object->getId());
1790
1791 $cont_obj_gui = new ilObjContentObjectGUI('', $_GET['source_id'], true);
1792 $cont_obj = $cont_obj_gui->object;
1793 $ctree = $cont_obj->getLMTree();
1794 $nodes = $ctree->getSubtree($ctree->getNodeData($ctree->getRootId()));
1795
1796 $rows = array();
1797
1798 foreach ($nodes as $node) {
1799 if ($node['type'] == $_GET['search_link_type']) {
1800 $this->ctrl->setParameter($this, $node['type'], $node['obj_id']);
1801 $rows[] = array(
1802 'title' => $node['title'],
1803 'description' => '',
1804 'text_add' => $this->lng->txt('add'),
1805 'href_add' => $this->ctrl->getLinkTarget($this, 'add' . strtoupper($node['type']))
1806 );
1807 }
1808 }
1809
1810 $table = new ilQuestionInternalLinkSelectionTableGUI($this, 'cancelExplorer', __METHOD__);
1811 $table->setTitle($this->lng->txt('obj_' . ilUtil::stripSlashes($_GET['search_link_type'])));
1812 $table->setData($rows);
1813
1814 $this->tpl->setContent($table->getHTML());
1815 }
1816
1817 public function outGlossarySelector()
1818 {
1819 $this->ctrl->setParameter($this, 'q_id', $this->object->getId());
1820
1821 $glossary = new ilObjGlossary($_GET['source_id'], true);
1822 $terms = $glossary->getTermList();
1823
1824 $rows = array();
1825
1826 foreach ($terms as $term) {
1827 $this->ctrl->setParameter($this, 'git', $term['id']);
1828 $rows[] = array(
1829 'title' => $term['term'],
1830 'description' => '',
1831 'text_add' => $this->lng->txt('add'),
1832 'href_add' => $this->ctrl->getLinkTarget($this, 'addGIT')
1833 );
1834 }
1835
1836 $table = new ilQuestionInternalLinkSelectionTableGUI($this, 'cancelExplorer', __METHOD__);
1837 $table->setTitle($this->lng->txt('glossary_term'));
1838 $table->setData($rows);
1839
1840 $this->tpl->setContent($table->getHTML());
1841 }
1842
1843 public function linkChilds()
1844 {
1845 $this->ctrl->saveParameter($this, array("subquestion_index", "link_new_type", "search_link_type"));
1846 switch ($_GET["search_link_type"]) {
1847 case "pg":
1848 return $this->outPageSelector();
1849 break;
1850 case "st":
1851 return $this->outChapterSelector();
1852 break;
1853 case "glo":
1854 return $this->outGlossarySelector();
1855 break;
1856 case "lm":
1857 $subquestion_index = ($_GET["subquestion_index"] > 0) ? $_GET["subquestion_index"] : 0;
1858 $this->object->saveSuggestedSolution("lm", "il__lm_" . $_GET["source_id"], $subquestion_index);
1859 ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1860 $this->ctrl->redirect($this, "suggestedsolution");
1861 break;
1862 }
1863 }
1864
1865 public function addPG()
1866 {
1867 $subquestion_index = 0;
1868 if (strlen($_GET["subquestion_index"]) && $_GET["subquestion_index"] >= 0) {
1869 $subquestion_index = $_GET["subquestion_index"];
1870 }
1871 $this->object->saveSuggestedSolution("pg", "il__pg_" . $_GET["pg"], $subquestion_index);
1872 ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1873 $this->ctrl->redirect($this, "suggestedsolution");
1874 }
1875
1876 public function addST()
1877 {
1878 $subquestion_index = 0;
1879 if (strlen($_GET["subquestion_index"]) && $_GET["subquestion_index"] >= 0) {
1880 $subquestion_index = $_GET["subquestion_index"];
1881 }
1882 $this->object->saveSuggestedSolution("st", "il__st_" . $_GET["st"], $subquestion_index);
1883 ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1884 $this->ctrl->redirect($this, "suggestedsolution");
1885 }
1886
1887 public function addGIT()
1888 {
1889 $subquestion_index = 0;
1890 if (strlen($_GET["subquestion_index"]) && $_GET["subquestion_index"] >= 0) {
1891 $subquestion_index = $_GET["subquestion_index"];
1892 }
1893 $this->object->saveSuggestedSolution("git", "il__git_" . $_GET["git"], $subquestion_index);
1894 ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1895 $this->ctrl->redirect($this, "suggestedsolution");
1896 }
1897
1898 public function isSaveCommand()
1899 {
1900 return in_array($this->ctrl->getCmd(), array('save', 'saveEdit', 'saveReturn'));
1901 }
1902
1911 public static function getCommandsFromClassConstants($guiClassName, $cmdConstantNameBegin = 'CMD_')
1912 {
1913 $reflectionClass = new ReflectionClass($guiClassName);
1914
1915 $commands = null;
1916
1917 if ($reflectionClass instanceof ReflectionClass) {
1918 $commands = array();
1919
1920 foreach ($reflectionClass->getConstants() as $constName => $constValue) {
1921 if (substr($constName, 0, strlen($cmdConstantNameBegin)) == $cmdConstantNameBegin) {
1922 $commands[] = $constValue;
1923 }
1924 }
1925 }
1926
1927 return $commands;
1928 }
1929
1930 public function setQuestionTabs()
1931 {
1932 global $DIC;
1933 $ilTabs = $DIC['ilTabs'];
1934
1935 $ilTabs->clearTargets();
1936 $this->setDefaultTabs($ilTabs);
1937 $this->setQuestionSpecificTabs($ilTabs);
1938 $this->addBackTab($ilTabs);
1939 }
1940
1941 protected function setDefaultTabs(ilTabsGUI $ilTabs)
1942 {
1943 $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
1944 $q_type = $this->object->getQuestionType();
1945
1946 if (strlen($q_type)) {
1947 $classname = $q_type . "GUI";
1948 $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
1949 $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
1950 }
1951
1952 if ($_GET["q_id"]) {
1953 $this->addTab_Question($ilTabs);
1954 }
1955
1956 // add tab for question feedback within common class assQuestionGUI
1957 $this->addTab_QuestionFeedback($ilTabs);
1958
1959 // add tab for question hint within common class assQuestionGUI
1960 $this->addTab_QuestionHints($ilTabs);
1961
1962 // add tab for question's suggested solution within common class assQuestionGUI
1963 $this->addTab_SuggestedSolution($ilTabs, $classname);
1964 }
1965
1966 protected function setQuestionSpecificTabs(ilTabsGUI $ilTabs)
1967 {
1968 }
1969
1970 public function addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
1971 {
1972 if ($_GET["q_id"]) {
1973 $tabs->addTarget(
1974 "suggested_solution",
1975 $this->ctrl->getLinkTargetByClass($classname, "suggestedsolution"),
1976 array("suggestedsolution", "saveSuggestedSolution", "outSolutionExplorer", "cancel",
1977 "addSuggestedSolution","cancelExplorer", "linkChilds", "removeSuggestedSolution"
1978 ),
1979 $classname,
1980 ""
1981 );
1982 }
1983 }
1984
1985 final public function getEditQuestionTabCommands()
1986 {
1987 return array_merge($this->getBasicEditQuestionTabCommands(), $this->getAdditionalEditQuestionCommands());
1988 }
1989
1991 {
1992 return array('editQuestion', 'save', 'saveEdit', 'originalSyncForm');
1993 }
1994
1996 {
1997 return array();
1998 }
1999
2006 protected function addTab_QuestionFeedback(ilTabsGUI $tabs)
2007 {
2008 global $DIC;
2009 $ilCtrl = $DIC['ilCtrl'];
2010
2011 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionFeedbackEditingGUI.php';
2012 $tabCommands = self::getCommandsFromClassConstants('ilAssQuestionFeedbackEditingGUI');
2013
2014 $tabLink = $ilCtrl->getLinkTargetByClass('ilAssQuestionFeedbackEditingGUI', ilAssQuestionFeedbackEditingGUI::CMD_SHOW);
2015
2016 $tabs->addTarget('tst_feedback', $tabLink, $tabCommands, $ilCtrl->getCmdClass(), '');
2017 }
2018
2025 protected function addTab_QuestionHints(ilTabsGUI $tabs)
2026 {
2027 global $DIC;
2028 $ilCtrl = $DIC['ilCtrl'];
2029
2030 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintsGUI.php';
2031
2032 switch ($ilCtrl->getCmdClass()) {
2033 case 'ilassquestionhintsgui':
2034
2035 $tabCommands = self::getCommandsFromClassConstants('ilAssQuestionHintsGUI');
2036 break;
2037
2038 case 'ilassquestionhintgui':
2039
2040 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintGUI.php';
2041 $tabCommands = self::getCommandsFromClassConstants('ilAssQuestionHintGUI');
2042 break;
2043
2044 default:
2045
2046 $tabCommands = array();
2047 }
2048
2049 $tabLink = $ilCtrl->getLinkTargetByClass('ilAssQuestionHintsGUI', ilAssQuestionHintsGUI::CMD_SHOW_LIST);
2050
2051 $tabs->addTarget('tst_question_hints_tab', $tabLink, $tabCommands, $ilCtrl->getCmdClass(), '');
2052 }
2053
2054 protected function addTab_Question(ilTabsGUI $tabsGUI)
2055 {
2056 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewGUI.php';
2057
2058 $tabsGUI->addTarget(
2059 'edit_question',
2060 $this->ctrl->getLinkTargetByClass(
2061 array('ilrepositorygui','ilobjquestionpoolgui', get_class($this)),
2062 'editQuestion'
2063 ),
2064 'editQuestion',
2065 '',
2066 '',
2067 false
2068 );
2069 }
2070
2071 abstract public function getSolutionOutput(
2072 $active_id,
2073 $pass = null,
2074 $graphicalOutput = false,
2075 $result_output = false,
2076 $show_question_only = true,
2077 $show_feedback = false,
2078 $show_correct_solution = false,
2079 $show_manual_scoring = false,
2080 $show_question_text = true
2081 );
2082
2089 {
2090 return false;
2091 }
2092
2099 public function hasIntermediateSolution($activeId, $passIndex)
2100 {
2101 $result = $this->object->lookupForExistingSolutions($activeId, $passIndex);
2102 return ($result['intermediate']);
2103 }
2104
2109 public function setUseIntermediateSolution($use)
2110 {
2111 $this->use_intermediate_solution = (bool) $use;
2112 }
2113
2119 {
2121 }
2122
2123 protected function hasCorrectSolution($activeId, $passIndex)
2124 {
2125 $reachedPoints = $this->object->getAdjustedReachedPoints($activeId, $passIndex, true);
2126 $maximumPoints = $this->object->getMaximumPoints();
2127
2128 return $reachedPoints == $maximumPoints;
2129 }
2130
2131 public function isAutosaveable()
2132 {
2133 return $this->object->isAutosaveable();
2134 }
2135
2136 protected function writeQuestionGenericPostData()
2137 {
2138 $this->object->setTitle($_POST["title"]);
2139 $this->object->setAuthor($_POST["author"]);
2140 $this->object->setComment($_POST["comment"]);
2141 if ($this->object->getSelfAssessmentEditingMode()) {
2142 $this->object->setNrOfTries($_POST['nr_of_tries']);
2143 }
2144
2145 try {
2146 $lifecycle = ilAssQuestionLifecycle::getInstance($_POST['lifecycle']);
2147 $this->object->setLifecycle($lifecycle);
2149 }
2150
2151 $this->object->setQuestion(ilUtil::stripOnlySlashes($_POST['question'])); // ?
2152 $this->object->setEstimatedWorkingTime(
2153 $_POST["Estimated"]["hh"],
2154 $_POST["Estimated"]["mm"],
2155 $_POST["Estimated"]["ss"]
2156 );
2157 }
2158
2159 abstract public function getPreview($show_question_only = false, $showInlineFeedback = false);
2160
2169 final public function outQuestionForTest(
2170 $formaction,
2171 $active_id,
2172 // hey: prevPassSolutions - pass will be always available from now on
2173 $pass,
2174 // hey.
2175 $is_question_postponed = false,
2176 $user_post_solutions = false,
2177 $show_specific_inline_feedback = false
2178 ) {
2179 $formaction = $this->completeTestOutputFormAction($formaction, $active_id, $pass);
2180
2181 $test_output = $this->getTestOutput(
2182 $active_id,
2183 $pass,
2184 $is_question_postponed,
2185 $user_post_solutions,
2186 $show_specific_inline_feedback
2187 );
2188
2189 $this->magicAfterTestOutput();
2190
2191 $this->tpl->setVariable("QUESTION_OUTPUT", $test_output);
2192 $this->tpl->setVariable("FORMACTION", $formaction);
2193 $this->tpl->setVariable("ENCTYPE", 'enctype="' . $this->getFormEncodingType() . '"');
2194 $this->tpl->setVariable("FORM_TIMESTAMP", time());
2195 }
2196
2197 // hey: prevPassSolutions - $pass will be passed always from now on
2198 protected function completeTestOutputFormAction($formAction, $active_id, $pass)
2199 // hey.
2200 {
2201 return $formAction;
2202 }
2203
2204 public function magicAfterTestOutput()
2205 {
2206 return;
2207 }
2208
2209 abstract public function getTestOutput(
2210 $active_id,
2211 $pass,
2212 $is_question_postponed,
2213 $user_post_solutions,
2214 $show_specific_inline_feedback
2215 );
2216
2217 public function getFormEncodingType()
2218 {
2220 }
2221
2225 protected function addBackTab(ilTabsGUI $ilTabs)
2226 {
2227 $this->ctrl->saveParameterByClass(ilAssQuestionPreviewGUI::class, 'prev_qid');
2228 $ilTabs->setBackTarget(
2229 $this->lng->txt('backtocallingpage'),
2230 $this->ctrl->getLinkTargetByClass(ilAssQuestionPreviewGUI::class, ilAssQuestionPreviewGUI::CMD_SHOW)
2231 );
2232 }
2233
2238
2243 {
2244 $this->previewSession = $previewSession;
2245 }
2246
2250 public function getPreviewSession()
2251 {
2252 return $this->previewSession;
2253 }
2254
2258 protected function buildBasicEditFormObject()
2259 {
2260 require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
2261 $form = new ilPropertyFormGUI();
2262
2263 $form->setFormAction($this->ctrl->getFormAction($this));
2264
2265 $form->setId($this->getType());
2266 $form->setTitle($this->outQuestionType());
2267
2268 $form->setTableWidth('100%');
2269
2270 $form->setMultipart(true);
2271
2272 return $form;
2273 }
2274
2275 public function showHints()
2276 {
2277 global $DIC;
2278 $ilCtrl = $DIC['ilCtrl'];
2279 $ilCtrl->redirectByClass('ilAssQuestionHintsGUI', ilAssQuestionHintsGUI::CMD_SHOW_LIST);
2280 }
2281
2282 protected function escapeTemplatePlaceholders(string $text) : string
2283 {
2284 return str_replace(['{','}'], ['&#123;','&#125;'], $text);
2285 }
2286
2290 protected function buildEditForm()
2291 {
2292 $errors = $this->editQuestion(true); // TODO bheyser: editQuestion should be added to the abstract base class with a unified signature
2293 return $this->editForm;
2294 }
2295
2299 public function buildFocusAnchorHtml()
2300 {
2301 return '<div id="focus"></div>';
2302 }
2303
2305 {
2306 return true;
2307 }
2308
2309 public function getSubQuestionsIndex()
2310 {
2311 return array(0);
2312 }
2313
2314 public function getAnswersFrequency($relevantAnswers, $questionIndex)
2315 {
2316 return array();
2317 }
2318
2326 public function getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex)
2327 {
2328 require_once 'Modules/TestQuestionPool/classes/tables/class.ilAnswerFrequencyStatisticTableGUI.php';
2329
2330 $table = new ilAnswerFrequencyStatisticTableGUI($parentGui, $parentCmd, $this->object);
2331 $table->setQuestionIndex($questionIndex);
2332 $table->setData($this->getAnswersFrequency($relevantAnswers, $questionIndex));
2333 $table->initColumns();
2334
2335 return $table;
2336 }
2337
2342 {
2343 }
2344
2349 {
2350 }
2351
2356 {
2357 }
2358
2359 protected function addSaveOnEnterOnLoadCode() : void
2360 {
2361 $this->tpl->addOnloadCode("
2362 let form = document.querySelector('#ilContentContainer form');
2363 let button = form.querySelector('input[name=\"cmd[save]\"]');
2364 if (button === null) {
2365 button = form.querySelector('input[name=\"cmd[saveFQ]\"]');
2366 };
2367 if (form && button) {
2368 form.addEventListener('keydown', function (e) {
2369 if (e.key === 'Enter'
2370 && e.target.type !== 'textarea'
2371 && e.target.type !== 'submit'
2372 && e.target.type !== 'file'
2373 ) {
2374 e.preventDefault();
2375 form.requestSubmit(button);
2376 }
2377 })
2378 }
2379 ");
2380 }
2381}
$result
$test
Definition: Utf8Test.php:84
$_GET["client_id"]
$_POST["username"]
$_SESSION["AccountId"]
An exception for terminatinating execution or to throw for unit testing.
Basic GUI class for assessment questions.
static _getQuestionGUI($question_type, $question_id=-1)
Creates a question gui representation and returns the alias to the question gui note: please do not u...
populateTaxonomyFormSection(ilPropertyFormGUI $form)
addNewIdListener(&$a_object, $a_method, $a_parameters="")
Add a listener that is notified with the new question ID, when a new question is saved.
callNewIdListeners($a_new_id)
Call the new id listeners.
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
const SESSION_PREVIEW_DATA_BASE_INDEX
writePostData($always=false)
Evaluates a posted edit form and writes the form data in the question object.
getContextPath($cont_obj, $a_endnode_id, $a_startnode_id=1)
get context path in content object tree
setErrorMessage($errormessage)
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)
getQuestionType()
Returns the question type string.
static _getClassNameForQType($q_type)
getType()
needed for page editor compliance
setEditContext($editContext)
cancel()
cancel action
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
setNavigationGUI($navigationGUI)
hasIntermediateSolution($activeId, $passIndex)
Check if the question has an intermediate solution.
addTab_Question(ilTabsGUI $tabsGUI)
setTargetGuiClass($targetGuiClass)
setQuestionSpecificTabs(ilTabsGUI $ilTabs)
setQuestionCount($a_question_count)
getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex)
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.
escapeTemplatePlaceholders(string $text)
getILIASPage($html="")
Returns the ILIAS Page around a question.
getQuestionTemplate()
get question template
& createQuestionGUI($question_type, $question_id=-1)
Creates a question gui representation.
setTaxonomyIds($taxonomyIds)
originalSyncForm($return_to="", $return_to_feedback='')
getAsValueAttribute($a_value)
Returns a HTML value attribute.
setPreviewSession($previewSession)
setTargetGui($linkTargetGui)
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
saveReturn()
save question
prepareReprintableCorrectionsForm(ilPropertyFormGUI $form)
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
outQuestionForTest( $formaction, $active_id, $pass, $is_question_postponed=false, $user_post_solutions=false, $show_specific_inline_feedback=false)
getTestOutput( $active_id, $pass, $is_question_postponed, $user_post_solutions, $show_specific_inline_feedback)
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.
static _getGUIClassNameForId($a_q_id)
setPresentationContext($presentationContext)
getAnswersFrequency($relevantAnswers, $questionIndex)
populateJavascriptFilesRequiredForWorkForm(ilGlobalTemplateInterface $tpl)
setQuestionHeaderBlockBuilder($questionHeaderBlockBuilder)
addErrorMessage($errormessage)
suggestedsolution()
Allows to add suggested solutions for questions.
saveEdit()
save question
setDefaultTabs(ilTabsGUI $ilTabs)
completeTestOutputFormAction($formAction, $active_id, $pass)
getSpecificFeedbackOutput($userSolution)
Returns the answer specific feedback for the question.
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
addBackTab(ilTabsGUI $ilTabs)
setPreviousSolutionPrefilled($previousSolutionPrefilled)
__construct()
assQuestionGUI constructor
setRenderPurpose($renderPurpose)
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question,...
static getCommandsFromClassConstants($guiClassName, $cmdConstantNameBegin='CMD_')
extracts values of all constants of given class with given prefix as array can be used to get all pos...
setQuestionActionCmd($questionActionCmd)
executeCommand()
execute command
getPreview($show_question_only=false, $showInlineFeedback=false)
hasInlineFeedback()
this method can be overwritten per question type
$sequence_no
sequence number in test
$question_count
question count in test
getAnswerFeedbackOutput($active_id, $pass)
Returns the answer generic feedback depending on the results of the question.
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
static getFeedbackClassNameByQuestionType($questionType)
const ADDITIONAL_CONTENT_EDITING_MODE_IPE
constant for additional content editing mode "pageobject"
static _getQuestionTypeName($type_tag)
Return the translation for a given question type tag.
static _questionExistsInTest($question_id, $test_id)
static _getInternalLinkHref($target="")
static getGuiClassNameByQuestionType($questionType)
static _includeClass($question_type, $gui=0)
Include the php class file for a given question type.
static getQuestionTypeFromDb($question_id)
get question type for question id
static _isWriteable($question_id, $user_id)
Returns true if the question is writeable by a certain user.
const CMD_SHOW_LIST
command constants
Question page GUI class.
static getSelfAssessmentTags()
Get tags allowed in question tags in self assessment mode.
This class represents a checkbox property in a property form.
Class ilCommonActionDispatcherGUI.
This class represents a duration (typical hh:mm:ss) property in a property form.
This class represents a file property in a property form.
This class represents a section header in a property form.
This class represents a hidden form property in a property form.
static getPageList($lm_id)
static
Notes GUI class.
This class represents a number property in a property form.
static _getUsedHTMLTags($a_module="")
Returns an array of all allowed HTML tags for text editing.
Class ilObjContentObjectGUI.
Class ilObjGlossary.
static getManualFeedback($active_id, $question_id, $pass)
Retrieves the feedback comment for a question in a test if it is finalized.
static getInstanceByRefId($a_ref_id, $stop_on_error=true)
get an instance of an Ilias object by reference id
static _lookupType($a_id, $a_reference=false)
lookup object type
This class represents a property form user interface.
addItem($a_item)
Add Item (Property, SectionHeader).
Class ilQuestionUsagesTableGUI.
This class represents a property in a property form.
This class represents an option in a radio group.
This class represents a selection list property in a property form.
This class represents a custom property in a property form.
Tabs GUI.
addTarget( $a_text, $a_link, $a_cmd="", $a_cmdClass="", $a_frame="", $a_activate=false, $a_dir_text=false)
setBackTarget($a_title, $a_target, $a_frame="")
back target for upper context
Input GUI class for taxonomy assignments.
Taxonomy node <-> item assignment.
Select taxonomy nodes input GUI.
special template class to simplify handling of ITX/PEAR
static getReturnToPageLink($q_id=null)
This class represents a text area property in a property form.
This class represents a text property in a property form.
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
static stripOnlySlashes($a_str)
strip slashes if magic qoutes is enabled
static redirect($a_script)
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
static makeDirParents($a_dir)
Create a new directory and all parent directories.
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms @access public
static renameExecutables($a_dir)
Rename uploaded executables for security reasons.
global $DIC
Definition: goto.php:24
$errors
Definition: imgupload.php:49
$ilUser
Definition: imgupload.php:18
exit
Definition: login.php:29
$i
Definition: metadata.php:24
QTI assessment class.
$type
foreach($_POST as $key=> $value) $res
global $ilDB
$rows
Definition: xhr_table.php:10