ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 
4 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
5 require_once 'Modules/Test/classes/class.ilTestExpressPage.php';
6 require_once 'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
7 require_once 'Modules/Test/classes/class.ilTestExpressPage.php';
8 require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
9 
20 abstract class assQuestionGUI
21 {
22  const FORM_MODE_EDIT = 'edit';
23  const FORM_MODE_ADJUST = 'adjust';
24 
25  const FORM_ENCODING_URLENCODE = 'application/x-www-form-urlencoded';
26  const FORM_ENCODING_MULTIPART = 'multipart/form-data';
27 
28  const SESSION_PREVIEW_DATA_BASE_INDEX = 'ilAssQuestionPreviewAnswers';
29 
37  public $object;
38 
39  public $tpl;
40  public $lng;
41  public $error;
42  public $errormessage;
43 
47  public $sequence_no;
52 
53  private $taxonomyIds = array();
54 
55  private $targetGuiClass = null;
56 
57  private $questionActionCmd = 'handleQuestionAction';
58 
63 
67  private $navigationGUI;
68 
69  const PRESENTATION_CONTEXT_TEST = 'pContextTest';
70  const PRESENTATION_CONTEXT_RESULTS = 'pContextResults';
71 
75  private $presentationContext = null;
76 
77  const RENDER_PURPOSE_PLAYBACK = 'renderPurposePlayback';
78  const RENDER_PURPOSE_DEMOPLAY = 'renderPurposeDemoplay';
79  const RENDER_PURPOSE_PREVIEW = 'renderPurposePreview';
80  const RENDER_PURPOSE_PRINT_PDF = 'renderPurposePrintPdf';
81  const RENDER_PURPOSE_INPUT_VALUE = 'renderPurposeInputValue';
82 
86  private $renderPurpose = self::RENDER_PURPOSE_PLAYBACK;
87 
88  const EDIT_CONTEXT_AUTHORING = 'authoring';
89  const EDIT_CONTEXT_ADJUSTMENT = 'adjustment';
90 
94  private $editContext = self::EDIT_CONTEXT_AUTHORING;
95 
96  // hey: prevPassSolutions - flag to indicate that a previous answer is shown
100  private $previousSolutionPrefilled = false;
101  // hey.
102 
106  protected $editForm;
107 
111  public function __construct()
112  {
113  global $lng, $tpl, $ilCtrl;
114 
115  $this->lng =&$lng;
116  $this->tpl =&$tpl;
117  $this->ctrl =&$ilCtrl;
118  $this->ctrl->saveParameter($this, "q_id");
119  $this->ctrl->saveParameter($this, "prev_qid");
120  $this->ctrl->saveParameter($this, "calling_test");
121  $this->ctrl->saveParameter($this, "calling_consumer");
122  $this->ctrl->saveParameter($this, "consumer_context");
123  $this->ctrl->saveParameterByClass('ilAssQuestionPageGUI', 'test_express_mode');
124  $this->ctrl->saveParameterByClass('ilAssQuestionPageGUI', 'calling_consumer');
125  $this->ctrl->saveParameterByClass('ilAssQuestionPageGUI', 'consumer_context');
126  $this->ctrl->saveParameterByClass('ilobjquestionpoolgui', 'test_express_mode');
127  $this->ctrl->saveParameterByClass('ilobjquestionpoolgui', 'calling_consumer');
128  $this->ctrl->saveParameterByClass('ilobjquestionpoolgui', 'consumer_context');
129 
130  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
131  $this->errormessage = $this->lng->txt("fill_out_all_required_fields");
132 
133  $this->selfassessmenteditingmode = false;
134  $this->new_id_listeners = array();
135  $this->new_id_listener_cnt = 0;
136 
137  $this->navigationGUI = null;
138  }
139 
143  public function executeCommand()
144  {
145  global $DIC; /* @var \ILIAS\DI\Container $DIC */
146  $ilHelp = $DIC['ilHelp']; /* @var ilHelpGUI $ilHelp */
147  $ilHelp->setScreenIdComponent('qpl');
148 
149  $cmd = $this->ctrl->getCmd("editQuestion");
150  $next_class = $this->ctrl->getNextClass($this);
151 
152  $cmd = $this->getCommand($cmd);
153 
154  switch ($next_class) {
155  case 'ilformpropertydispatchgui':
156  $form = $this->buildEditForm();
157 
158  require_once 'Services/Form/classes/class.ilFormPropertyDispatchGUI.php';
159  $form_prop_dispatch = new ilFormPropertyDispatchGUI();
160  $form_prop_dispatch->setItem($form->getItemByPostVar(ilUtil::stripSlashes($_GET['postvar'])));
161  return $this->ctrl->forwardCommand($form_prop_dispatch);
162  break;
163 
164  default:
165  $ret = $this->$cmd();
166  break;
167  }
168  return $ret;
169  }
170 
171  public function getCommand($cmd)
172  {
173  return $cmd;
174  }
175 
179  public function getType()
180  {
181  return $this->getQuestionType();
182  }
183 
187  public function getPresentationContext()
188  {
190  }
191 
196  {
197  $this->presentationContext = $presentationContext;
198  }
199 
200  public function isTestPresentationContext()
201  {
202  return $this->getPresentationContext() == self::PRESENTATION_CONTEXT_TEST;
203  }
204 
205  // hey: previousPassSolutions - setter/getter for Previous Solution Prefilled flag
209  public function isPreviousSolutionPrefilled()
210  {
212  }
213 
218  {
219  $this->previousSolutionPrefilled = $previousSolutionPrefilled;
220  }
221  // hey.
222 
226  public function getRenderPurpose()
227  {
228  return $this->renderPurpose;
229  }
230 
235  {
236  $this->renderPurpose = $renderPurpose;
237  }
238 
239  public function isRenderPurposePrintPdf()
240  {
241  return $this->getRenderPurpose() == self::RENDER_PURPOSE_PRINT_PDF;
242  }
243 
244  public function isRenderPurposePreview()
245  {
246  return $this->getRenderPurpose() == self::RENDER_PURPOSE_PREVIEW;
247  }
248 
249  public function isRenderPurposeInputValue()
250  {
251  return $this->getRenderPurpose() == self::RENDER_PURPOSE_INPUT_VALUE;
252  }
253 
254  public function isRenderPurposePlayback()
255  {
256  return $this->getRenderPurpose() == self::RENDER_PURPOSE_PLAYBACK;
257  }
258 
259  public function isRenderPurposeDemoplay()
260  {
261  return $this->getRenderPurpose() == self::RENDER_PURPOSE_DEMOPLAY;
262  }
263 
265  {
266  if ($this->isRenderPurposePrintPdf()) {
267  return false;
268  }
269 
270  if ($this->isRenderPurposeInputValue()) {
271  return false;
272  }
273 
274  return true;
275  }
276 
280  public function getEditContext()
281  {
282  return $this->editContext;
283  }
284 
288  public function setEditContext($editContext)
289  {
290  $this->editContext = $editContext;
291  }
292 
296  public function isAuthoringEditContext()
297  {
298  return $this->getEditContext() == self::EDIT_CONTEXT_AUTHORING;
299  }
300 
304  public function isAdjustmentEditContext()
305  {
306  return $this->getEditContext() == self::EDIT_CONTEXT_ADJUSTMENT;
307  }
308 
309  public function setAdjustmentEditContext()
310  {
311  return $this->setEditContext(self::EDIT_CONTEXT_ADJUSTMENT);
312  }
313 
317  public function getNavigationGUI()
318  {
319  return $this->navigationGUI;
320  }
321 
326  {
327  $this->navigationGUI = $navigationGUI;
328  }
329 
330  public function setTaxonomyIds($taxonomyIds)
331  {
332  $this->taxonomyIds = $taxonomyIds;
333  }
334 
335  public function getTaxonomyIds()
336  {
337  return $this->taxonomyIds;
338  }
339 
340  public function setTargetGui($linkTargetGui)
341  {
342  $this->setTargetGuiClass(get_class($linkTargetGui));
343  }
344 
346  {
347  $this->targetGuiClass = $targetGuiClass;
348  }
349 
350  public function getTargetGuiClass()
351  {
352  return $this->targetGuiClass;
353  }
354 
359  {
360  $this->questionHeaderBlockBuilder = $questionHeaderBlockBuilder;
361  }
362 
363  // fau: testNav - get the question header block bulder (for tweaking)
368  {
370  }
371  // fau.
372 
374  {
375  $this->questionActionCmd = $questionActionCmd;
376 
377  if (is_object($this->object)) {
378  $this->object->questionActionCmd = $questionActionCmd;
379  }
380  }
381 
382  public function getQuestionActionCmd()
383  {
385  }
386 
391  protected function writePostData($always = false)
392  {
393  }
394 
398  public function assessment()
399  {
403  global $tpl;
404 
405  require_once 'Modules/TestQuestionPool/classes/tables/class.ilQuestionCumulatedStatisticsTableGUI.php';
406  $stats_table = new ilQuestionCumulatedStatisticsTableGUI($this, 'assessment', '', $this->object);
407 
408  require_once 'Modules/TestQuestionPool/classes/tables/class.ilQuestionUsagesTableGUI.php';
409  $usage_table = new ilQuestionUsagesTableGUI($this, 'assessment', '', $this->object);
410 
411  $tpl->setContent(implode('<br />', array(
412  $stats_table->getHTML(),
413  $usage_table->getHTML()
414  )));
415  }
416 
426  public static function _getQuestionGUI($question_type, $question_id = -1)
427  {
428  global $ilCtrl, $ilDB, $lng;
429 
430  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
431 
432  if ((!$question_type) and ($question_id > 0)) {
433  $question_type = assQuestion::getQuestionTypeFromDb($question_id);
434  }
435 
436  if (strlen($question_type) == 0) {
437  return null;
438  }
439 
440  assQuestion::_includeClass($question_type, 1);
441 
442  $question_type_gui = assQuestion::getGuiClassNameByQuestionType($question_type);
443  $question = new $question_type_gui();
444 
445  $feedbackObjectClassname = assQuestion::getFeedbackClassNameByQuestionType($question_type);
446  $question->object->feedbackOBJ = new $feedbackObjectClassname($question->object, $ilCtrl, $ilDB, $lng);
447 
448  if ($question_id > 0) {
449  $question->object->loadFromDb($question_id);
450  }
451 
452  return $question;
453  }
454 
458  public static function _getGUIClassNameForId($a_q_id)
459  {
460  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
461  include_once "./Modules/TestQuestionPool/classes/class.assQuestionGUI.php";
462  $q_type = assQuestion::getQuestionTypeFromDb($a_q_id);
463  $class_name = assQuestionGUI::_getClassNameForQType($q_type);
464  return $class_name;
465  }
466 
470  public static function _getClassNameForQType($q_type)
471  {
472  return $q_type . "GUI";
473  }
474 
487  public function &createQuestionGUI($question_type, $question_id = -1)
488  {
489  include_once "./Modules/TestQuestionPool/classes/class.assQuestionGUI.php";
490  $this->question =&assQuestionGUI::_getQuestionGUI($question_type, $question_id);
491  }
492 
494  {
495  $tpl->addJavaScript('Modules/TestQuestionPool/js/ilAssMultipleChoice.js');
496  }
497 
501  public function getQuestionTemplate()
502  {
503  // @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)
504  if (!$this->tpl->blockExists('content')) {
505  $this->tpl->addBlockFile("CONTENT", "content", "tpl.il_as_qpl_content.html", "Modules/TestQuestionPool");
506  }
507  // @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)
508  if (!$this->tpl->blockExists('statusline')) {
509  $this->tpl->addBlockFile("STATUSLINE", "statusline", "tpl.statusline.html");
510  }
511  // @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
512  if (!$this->tpl->blockExists('adm_content')) {
513  $this->tpl->addBlockFile("ADM_CONTENT", "adm_content", "tpl.il_as_question.html", "Modules/TestQuestionPool");
514  }
515  }
516 
520  protected function renderEditForm($form)
521  {
522  $this->getQuestionTemplate();
523  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
524  }
525 
532  public function getILIASPage($html = "")
533  {
534  include_once("./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php");
535  $page_gui = new ilAssQuestionPageGUI($this->object->getId());
536  $page_gui->setQuestionHTML(array($this->object->getId() => $html));
537  $page_gui->setOutputMode("presentation");
538  $presentation = $page_gui->presentation();
539  $presentation = preg_replace("/src=\"\\.\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $presentation);
540  return $presentation;
541  }
542 
546  public function outQuestionPage($a_temp_var, $a_postponed = false, $active_id = "", $html = "")
547  {
548  // hey: prevPassSolutions - add the "use previous answer"
549  // hey: prevPassSolutions - refactored identifiers
550  if ($this->object->getTestPresentationConfig()->isSolutionInitiallyPrefilled()) {
551  // hey
554  } elseif // (!) --> if ($this->object->getTestQuestionConfig()->isUnchangedAnswerPossible())
555  // hey.
556 // fau: testNav - add the "use unchanged answer checkbox"
557  // hey: prevPassSolutions - refactored identifiers
558  ($this->object->getTestPresentationConfig()->isUnchangedAnswerPossible()) {
559  // hey.
561  }
562  // fau.
563 
564  $this->lng->loadLanguageModule("content");
565 
566  // fau: testNav - add question buttons below question, add actions menu
567  include_once("./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php");
568  $page_gui = new ilAssQuestionPageGUI($this->object->getId());
569  $page_gui->setOutputMode("presentation");
570  $page_gui->setTemplateTargetVar($a_temp_var);
571 
572  if ($this->getNavigationGUI()) {
573  $html .= $this->getNavigationGUI()->getHTML();
574  $page_gui->setQuestionActionsHTML($this->getNavigationGUI()->getActionsHTML());
575  }
576  // fau.
577 
578  if (strlen($html)) {
579  $page_gui->setQuestionHTML(array($this->object->getId() => $html));
580  }
581 
582  // fau: testNav - fill the header with subtitle blocks for question info an actions
583  $page_gui->setPresentationTitle($this->questionHeaderBlockBuilder->getPresentationTitle());
584  $page_gui->setQuestionInfoHTML($this->questionHeaderBlockBuilder->getQuestionInfoHTML());
585  // fau.
586 
587  return $page_gui->presentation();
588  }
589 
590  // fau: testNav - get the html of the "use unchanged answer checkbox"
592  {
593  // hey: prevPassSolutions - use abstracted template to share with other purposes of this kind
594  $tpl = new ilTemplate('tpl.tst_question_additional_behaviour_checkbox.html', true, true, 'Modules/TestQuestionPool');
595  $tpl->setVariable('TXT_FORCE_FORM_DIFF_LABEL', $this->object->getTestPresentationConfig()->getUseUnchangedAnswerLabel());
596  // hey.
597  return $tpl->get();
598  }
599  // fau.
600 
601  // hey: prevPassSolutions - build prev solution message / build "use previous answer checkbox" html
603  {
604  return $this->lng->txt('use_previous_solution_advice');
605  }
606 
608  {
609  $tpl = new ilTemplate('tpl.tst_question_additional_behaviour_checkbox.html', true, true, 'Modules/TestQuestionPool');
610  // hey: prevPassSolutions - use abtract template
611  $tpl->setVariable('TXT_FORCE_FORM_DIFF_LABEL', $this->lng->txt('use_previous_solution'));
612  // hey.
613  return $tpl->get();
614  }
615  // hey.
616 
620  public function cancel()
621  {
622  if ($_GET["calling_test"]) {
623  $_GET["ref_id"] = $_GET["calling_test"];
624  ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["calling_test"]);
625  } elseif ($_GET["test_ref_id"]) {
626  $_GET["ref_id"] = $_GET["test_ref_id"];
627  ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["test_ref_id"]);
628  } else {
629  if ($_GET["q_id"] > 0) {
630  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
631  $this->ctrl->redirectByClass("ilAssQuestionPageGUI", "edit");
632  } else {
633  $this->ctrl->redirectByClass("ilobjquestionpoolgui", "questions");
634  }
635  }
636  }
637 
642  public function originalSyncForm($return_to = "", $return_to_feedback = '')
643  {
644  if (strlen($return_to)) {
645  $this->ctrl->setParameter($this, "return_to", $return_to);
646  } elseif ($_REQUEST['return_to']) {
647  $this->ctrl->setParameter($this, "return_to", $_REQUEST['return_to']);
648  }
649  if (strlen($return_to_feedback)) {
650  $this->ctrl->setParameter($this, 'return_to_fb', 'true');
651  }
652 
653  $this->ctrl->saveParameter($this, 'test_express_mode');
654 
655  $template = new ilTemplate("tpl.il_as_qpl_sync_original.html", true, true, "Modules/TestQuestionPool");
656  $template->setVariable("BUTTON_YES", $this->lng->txt("yes"));
657  $template->setVariable("BUTTON_NO", $this->lng->txt("no"));
658  $template->setVariable("FORM_ACTION", $this->ctrl->getFormAction($this));
659  $template->setVariable("TEXT_SYNC", $this->lng->txt("confirm_sync_questions"));
660  $this->tpl->setVariable("ADM_CONTENT", $template->get());
661  }
662 
663  public function sync()
664  {
665  $original_id = $this->object->original_id;
666  if ($original_id) {
667  $this->object->syncWithOriginal();
668  }
669  if (strlen($_GET["return_to"])) {
670  $this->ctrl->redirect($this, $_GET["return_to"]);
671  }
672  if (strlen($_REQUEST["return_to_fb"])) {
673  $this->ctrl->redirectByClass('ilAssQuestionFeedbackEditingGUI', 'showFeedbackForm');
674  } else {
675  if (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer']) {
676  $ref_id = (int) $_GET['calling_consumer'];
678  if ($consumer instanceof ilQuestionEditingFormConsumer) {
679  ilUtil::redirect($consumer->getQuestionEditingFormBackTarget($_GET['consumer_context']));
680  }
681  require_once 'Services/Link/classes/class.ilLink.php';
683  }
684  $_GET["ref_id"] = $_GET["calling_test"];
685 
686  if ($_REQUEST['test_express_mode']) {
688  } else {
689  ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["calling_test"]);
690  }
691  }
692  }
693 
694  public function cancelSync()
695  {
696  if (strlen($_GET["return_to"])) {
697  $this->ctrl->redirect($this, $_GET["return_to"]);
698  }
699  if (strlen($_REQUEST['return_to_fb'])) {
700  $this->ctrl->redirectByClass('ilAssQuestionFeedbackEditingGUI', 'showFeedbackForm');
701  } else {
702  if (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer']) {
703  $ref_id = (int) $_GET['calling_consumer'];
705  if ($consumer instanceof ilQuestionEditingFormConsumer) {
706  ilUtil::redirect($consumer->getQuestionEditingFormBackTarget($_GET['consumer_context']));
707  }
708  require_once 'Services/Link/classes/class.ilLink.php';
710  }
711  $_GET["ref_id"] = $_GET["calling_test"];
712 
713  if ($_REQUEST['test_express_mode']) {
715  } else {
716  ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["calling_test"]);
717  }
718  }
719  }
720 
724  public function saveEdit()
725  {
726  global $ilUser;
727 
728  $result = $this->writePostData();
729  if ($result == 0) {
730  $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
731  $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
732  $this->object->saveToDb();
733  $originalexists = $this->object->_questionExists($this->object->original_id);
734  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
735  if ($_GET["calling_test"] && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
736  $this->ctrl->redirect($this, "originalSyncForm");
737  } elseif ($_GET["calling_test"]) {
738  $_GET["ref_id"] = $_GET["calling_test"];
739  ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["calling_test"]);
740  return;
741  } elseif ($_GET["test_ref_id"]) {
742  global $tree, $ilDB, $ilPluginAdmin;
743 
744  include_once("./Modules/Test/classes/class.ilObjTest.php");
745  $_GET["ref_id"] = $_GET["test_ref_id"];
746  $test = new ilObjTest($_GET["test_ref_id"], true);
747 
748  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
749  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
750 
751  $test->insertQuestion($testQuestionSetConfigFactory->getQuestionSetConfig(), $this->object->getId());
752 
753  ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["test_ref_id"]);
754  } else {
755  $this->ctrl->setParameter($this, "q_id", $this->object->getId());
756  $this->editQuestion();
757  if (strcmp($_SESSION["info"], "") != 0) {
758  ilUtil::sendSuccess($_SESSION["info"] . "<br />" . $this->lng->txt("msg_obj_modified"), false);
759  } else {
760  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), false);
761  }
762  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $this->object->getId());
763  $this->ctrl->redirectByClass("ilAssQuestionPageGUI", "edit");
764  }
765  }
766  }
767 
771  public function save()
772  {
773  global $ilUser;
774  $old_id = $_GET["q_id"];
775  $result = $this->writePostData();
776 
777  if ($result == 0) {
778  $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
779  $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
780  $this->object->saveToDb();
781  $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
782 
783 
784  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
785  if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
786  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
787  $this->ctrl->setParameter($this, 'return_to', 'editQuestion');
788  $this->ctrl->redirect($this, "originalSyncForm");
789  return;
790  } elseif ($_GET["calling_test"]) {
791  require_once 'Modules/Test/classes/class.ilObjTest.php';
792  $test = new ilObjTest($_GET["calling_test"]);
793  if (!assQuestion::_questionExistsInTest($this->object->getId(), $test->getTestId())) {
794  global $tree, $ilDB, $ilPluginAdmin;
795 
796  include_once("./Modules/Test/classes/class.ilObjTest.php");
797  $_GET["ref_id"] = $_GET["calling_test"];
798  $test = new ilObjTest($_GET["calling_test"], true);
799 
800  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
801  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
802 
803  $new_id = $test->insertQuestion(
804  $testQuestionSetConfigFactory->getQuestionSetConfig(),
805  $this->object->getId()
806  );
807 
808  if (isset($_REQUEST['prev_qid'])) {
809  $test->moveQuestionAfter($this->object->getId() + 1, $_REQUEST['prev_qid']);
810  }
811 
812  $this->ctrl->setParameter($this, 'q_id', $new_id);
813  $this->ctrl->setParameter($this, 'calling_test', $_GET['calling_test']);
814  #$this->ctrl->setParameter($this, 'test_ref_id', false);
815  }
816  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
817  $this->ctrl->redirect($this, 'editQuestion');
818  } else {
819  $this->callNewIdListeners($this->object->getId());
820 
821  if ($this->object->getId() != $old_id) {
822  // first save
823  $this->ctrl->setParameterByClass($_GET["cmdClass"], "q_id", $this->object->getId());
824  $this->ctrl->setParameterByClass($_GET["cmdClass"], "sel_question_types", $_GET["sel_question_types"]);
825  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
826 
827  //global $___test_express_mode;
831  if ($_REQUEST['prev_qid']) {
832  // @todo: bheyser/mbecker wtf? ..... thx@jposselt ....
833  // mbecker: Possible fix: Just instantiate the obj?
834  include_once("./Modules/Test/classes/class.ilObjTest.php");
835  $test = new ilObjTest($_GET["ref_id"], true);
836  $test->moveQuestionAfter($_REQUEST['prev_qid'], $this->object->getId());
837  }
838  if ( /*$___test_express_mode || */ $_REQUEST['express_mode']) {
839  global $tree, $ilDB, $ilPluginAdmin;
840 
841  include_once("./Modules/Test/classes/class.ilObjTest.php");
842  $test = new ilObjTest($_GET["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(
848  $testQuestionSetConfigFactory->getQuestionSetConfig(),
849  $this->object->getId()
850  );
851 
852  require_once 'Modules/Test/classes/class.ilTestExpressPage.php';
853  $_REQUEST['q_id'] = $this->object->getId();
855  }
856 
857  $this->ctrl->redirectByClass($_GET["cmdClass"], "editQuestion");
858  }
859  if (strcmp($_SESSION["info"], "") != 0) {
860  ilUtil::sendSuccess($_SESSION["info"] . "<br />" . $this->lng->txt("msg_obj_modified"), true);
861  } else {
862  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
863  }
864  $this->ctrl->redirect($this, 'editQuestion');
865  }
866  }
867  }
868 
872  public function saveReturn()
873  {
874  global $ilUser;
875  $old_id = $_GET["q_id"];
876  $result = $this->writePostData();
877  if ($result == 0) {
878  $ilUser->setPref("tst_lastquestiontype", $this->object->getQuestionType());
879  $ilUser->writePref("tst_lastquestiontype", $this->object->getQuestionType());
880  $this->object->saveToDb();
881  $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
882  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
883  if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
884  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
885  $this->ctrl->setParameter($this, 'test_express_mode', $_REQUEST['test_express_mode']);
886  $this->ctrl->redirect($this, "originalSyncForm");
887  return;
888  } elseif ($_GET["calling_test"]) {
889  require_once 'Modules/Test/classes/class.ilObjTest.php';
890  $test = new ilObjTest($_GET["calling_test"]);
891  #var_dump(assQuestion::_questionExistsInTest($this->object->getId(), $test->getTestId()));
892  $q_id = $this->object->getId();
893  if (!assQuestion::_questionExistsInTest($this->object->getId(), $test->getTestId())) {
894  global $tree, $ilDB, $ilPluginAdmin;
895 
896  include_once("./Modules/Test/classes/class.ilObjTest.php");
897  $_GET["ref_id"] = $_GET["calling_test"];
898  $test = new ilObjTest($_GET["calling_test"], true);
899 
900  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
901  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
902 
903  $new_id = $test->insertQuestion(
904  $testQuestionSetConfigFactory->getQuestionSetConfig(),
905  $this->object->getId()
906  );
907 
908  $q_id = $new_id;
909  if (isset($_REQUEST['prev_qid'])) {
910  $test->moveQuestionAfter($this->object->getId() + 1, $_REQUEST['prev_qid']);
911  }
912 
913  $this->ctrl->setParameter($this, 'q_id', $new_id);
914  $this->ctrl->setParameter($this, 'calling_test', $_GET['calling_test']);
915  #$this->ctrl->setParameter($this, 'test_ref_id', false);
916  }
917  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
918  if ( /*$___test_express_mode || */
919  $_REQUEST['test_express_mode']
920  ) {
922  } else {
923  ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=" . $_GET["calling_test"]);
924  }
925  } else {
926  if ($this->object->getId() != $old_id) {
927  $this->callNewIdListeners($this->object->getId());
928  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
929  $this->ctrl->redirectByClass("ilobjquestionpoolgui", "questions");
930  }
931  if (strcmp($_SESSION["info"], "") != 0) {
932  ilUtil::sendSuccess($_SESSION["info"] . "<br />" . $this->lng->txt("msg_obj_modified"), true);
933  } else {
934  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
935  }
936  $this->ctrl->redirectByClass("ilobjquestionpoolgui", "questions");
937  }
938  }
939  }
940 
944  public function apply()
945  {
946  $this->writePostData();
947  $this->object->saveToDb();
948  $this->ctrl->setParameter($this, "q_id", $this->object->getId());
949  $this->editQuestion();
950  }
951 
958  public function getContextPath($cont_obj, $a_endnode_id, $a_startnode_id = 1)
959  {
960  $path = "";
961 
962  $tmpPath = $cont_obj->getLMTree()->getPathFull($a_endnode_id, $a_startnode_id);
963 
964  // count -1, to exclude the learning module itself
965  for ($i = 1; $i < (count($tmpPath) - 1); $i++) {
966  if ($path != "") {
967  $path .= " > ";
968  }
969 
970  $path .= $tmpPath[$i]["title"];
971  }
972 
973  return $path;
974  }
975 
976  public function setSequenceNumber($nr)
977  {
978  $this->sequence_no = $nr;
979  }
980 
981  public function getSequenceNumber()
982  {
983  return $this->sequence_no;
984  }
985 
986  public function setQuestionCount($a_question_count)
987  {
988  $this->question_count = $a_question_count;
989  }
990 
991  public function getQuestionCount()
992  {
993  return $this->question_count;
994  }
995 
996  public function getErrorMessage()
997  {
998  return $this->errormessage;
999  }
1000 
1002  {
1003  $this->errormessage = $errormessage;
1004  }
1005 
1007  {
1008  $this->errormessage .= ((strlen($this->errormessage)) ? "<br />" : "") . $errormessage;
1009  }
1010 
1011  public function outAdditionalOutput()
1012  {
1013  }
1014 
1023  public function getQuestionType()
1024  {
1025  return $this->object->getQuestionType();
1026  }
1027 
1035  public function getAsValueAttribute($a_value)
1036  {
1037  $result = "";
1038  if (strlen($a_value)) {
1039  $result = " value=\"$a_value\" ";
1040  }
1041  return $result;
1042  }
1043 
1044  // scorm2004-start
1049  public function addNewIdListener(&$a_object, $a_method, $a_parameters = "")
1050  {
1051  $cnt = $this->new_id_listener_cnt;
1052  $this->new_id_listeners[$cnt]["object"] =&$a_object;
1053  $this->new_id_listeners[$cnt]["method"] = $a_method;
1054  $this->new_id_listeners[$cnt]["parameters"] = $a_parameters;
1055  $this->new_id_listener_cnt++;
1056  }
1057 
1061  public function callNewIdListeners($a_new_id)
1062  {
1063  for ($i=0; $i<$this->new_id_listener_cnt; $i++) {
1064  $this->new_id_listeners[$i]["parameters"]["new_id"] = $a_new_id;
1065  $object =&$this->new_id_listeners[$i]["object"];
1066  $method = $this->new_id_listeners[$i]["method"];
1067  $parameters = $this->new_id_listeners[$i]["parameters"];
1068  //var_dump($object);
1069  //var_dump($method);
1070  //var_dump($parameters);
1071 
1072  $object->$method($parameters);
1073  }
1074  }
1075 
1080  {
1081  //if (!$this->object->getSelfAssessmentEditingMode() && !$_GET["calling_test"]) $form->addCommandButton("saveEdit", $this->lng->txt("save_edit"));
1082  if (!$this->object->getSelfAssessmentEditingMode()) {
1083  $form->addCommandButton("saveReturn", $this->lng->txt("save_return"));
1084  }
1085  $form->addCommandButton("save", $this->lng->txt("save"));
1086  }
1087 
1095  {
1096  // title
1097  $title = new ilTextInputGUI($this->lng->txt("title"), "title");
1098  $title->setMaxLength(100);
1099  $title->setValue($this->object->getTitle());
1100  $title->setRequired(true);
1101  $form->addItem($title);
1102 
1103  if (!$this->object->getSelfAssessmentEditingMode()) {
1104  // author
1105  $author = new ilTextInputGUI($this->lng->txt("author"), "author");
1106  $author->setValue($this->object->getAuthor());
1107  $author->setRequired(true);
1108  $form->addItem($author);
1109 
1110  // description
1111  $description = new ilTextInputGUI($this->lng->txt("description"), "comment");
1112  $description->setValue($this->object->getComment());
1113  $description->setRequired(false);
1114  $form->addItem($description);
1115  } else {
1116  // author as hidden field
1117  $hi = new ilHiddenInputGUI("author");
1118  $author = ilUtil::prepareFormOutput($this->object->getAuthor());
1119  if (trim($author) == "") {
1120  $author = "-";
1121  }
1122  $hi->setValue($author);
1123  $form->addItem($hi);
1124  }
1125 
1126  // questiontext
1127  $question = new ilTextAreaInputGUI($this->lng->txt("question"), "question");
1128  $question->setValue($this->object->getQuestion());
1129  $question->setRequired(true);
1130  $question->setRows(10);
1131  $question->setCols(80);
1132 
1133  if (!$this->object->getSelfAssessmentEditingMode()) {
1134  if ($this->object->getAdditionalContentEditingMode() != assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_PAGE_OBJECT) {
1135  $question->setUseRte(true);
1136  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
1137  $question->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
1138  $question->addPlugin("latex");
1139  $question->addButton("latex");
1140  $question->addButton("pastelatex");
1141  $question->setRTESupport($this->object->getId(), "qpl", "assessment");
1142  }
1143  } else {
1144  require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
1146  $question->setUseTagsForRteOnly(false);
1147  }
1148  $form->addItem($question);
1149 
1150  if (!$this->object->getSelfAssessmentEditingMode()) {
1151  // duration
1152  $duration = new ilDurationInputGUI($this->lng->txt("working_time"), "Estimated");
1153  $duration->setShowHours(true);
1154  $duration->setShowMinutes(true);
1155  $duration->setShowSeconds(true);
1156  $ewt = $this->object->getEstimatedWorkingTime();
1157  $duration->setHours($ewt["h"]);
1158  $duration->setMinutes($ewt["m"]);
1159  $duration->setSeconds($ewt["s"]);
1160  $duration->setRequired(false);
1161  $form->addItem($duration);
1162  } else {
1163  // number of tries
1164  if (strlen($this->object->getNrOfTries())) {
1165  $nr_tries = $this->object->getNrOfTries();
1166  } else {
1167  $nr_tries = $this->object->getDefaultNrOfTries();
1168  }
1169  if ($nr_tries < 1) {
1170  $nr_tries = "";
1171  }
1172 
1173  $ni = new ilNumberInputGUI($this->lng->txt("qst_nr_of_tries"), "nr_of_tries");
1174  $ni->setValue($nr_tries);
1175  $ni->setMinValue(0);
1176  $ni->setSize(5);
1177  $ni->setMaxLength(5);
1178  $form->addItem($ni);
1179  }
1180  }
1181 
1182  protected function saveTaxonomyAssignments()
1183  {
1184  if (count($this->getTaxonomyIds())) {
1185  require_once 'Services/Taxonomy/classes/class.ilTaxAssignInputGUI.php';
1186 
1187  foreach ($this->getTaxonomyIds() as $taxonomyId) {
1188  $postvar = "tax_node_assign_$taxonomyId";
1189 
1190  $tax_node_assign = new ilTaxAssignInputGUI($taxonomyId, true, '', $postvar);
1191  // TODO: determine tst/qpl when tax assigns become maintainable within tests
1192  $tax_node_assign->saveInput("qpl", $this->object->getObjId(), "quest", $this->object->getId());
1193  }
1194  }
1195  }
1196 
1198  {
1199  if (count($this->getTaxonomyIds())) {
1200  // this is needed by ilTaxSelectInputGUI in some cases
1201  require_once 'Services/UIComponent/Overlay/classes/class.ilOverlayGUI.php';
1202  ilOverlayGUI::initJavaScript();
1203 
1204  $sectHeader = new ilFormSectionHeaderGUI();
1205  $sectHeader->setTitle($this->lng->txt('qpl_qst_edit_form_taxonomy_section'));
1206  $form->addItem($sectHeader);
1207 
1208  require_once 'Services/Taxonomy/classes/class.ilTaxSelectInputGUI.php';
1209 
1210  foreach ($this->getTaxonomyIds() as $taxonomyId) {
1211  $taxonomy = new ilObjTaxonomy($taxonomyId);
1212  $label = sprintf($this->lng->txt('qpl_qst_edit_form_taxonomy'), $taxonomy->getTitle());
1213  $postvar = "tax_node_assign_$taxonomyId";
1214 
1215  $taxSelect = new ilTaxSelectInputGUI($taxonomy->getId(), $postvar, true);
1216  $taxSelect->setTitle($label);
1217 
1218  require_once 'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
1219  $taxNodeAssignments = new ilTaxNodeAssignment(ilObject::_lookupType($this->object->getObjId()), $this->object->getObjId(), 'quest', $taxonomyId);
1220  $assignedNodes = $taxNodeAssignments->getAssignmentsOfItem($this->object->getId());
1221 
1222  $taxSelect->setValue(array_map(function ($assignedNode) {
1223  return $assignedNode['node_id'];
1224  }, $assignedNodes));
1225  $form->addItem($taxSelect);
1226  }
1227  }
1228  }
1229 
1239  public function getAnswerFeedbackOutput($active_id, $pass)
1240  {
1241  return $this->getGenericFeedbackOutput($active_id, $pass);
1242  }
1243 
1253  public function getGenericFeedbackOutput($active_id, $pass)
1254  {
1255  $output = "";
1256  include_once "./Modules/Test/classes/class.ilObjTest.php";
1257  $manual_feedback = ilObjTest::getManualFeedback($active_id, $this->object->getId(), $pass);
1258  if (strlen($manual_feedback)) {
1259  return $manual_feedback;
1260  }
1261  $correct_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true);
1262  $incorrect_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false);
1263  if (strlen($correct_feedback . $incorrect_feedback)) {
1264  $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
1265  $max_points = $this->object->getMaximumPoints();
1266  if ($reached_points == $max_points) {
1267  $output = $correct_feedback;
1268  } else {
1269  $output = $incorrect_feedback;
1270  }
1271  }
1272  return $this->object->prepareTextareaOutput($output, true);
1273  }
1274 
1276  {
1277  return $this->object->prepareTextareaOutput(
1278  $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true),
1279  true
1280  );
1281  }
1282 
1284  {
1285  return $this->object->prepareTextareaOutput(
1286  $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false),
1287  true
1288  );
1289  }
1290 
1302  abstract public function getSpecificFeedbackOutput($active_id, $pass);
1303 
1304  public function outQuestionType()
1305  {
1306  $count = $this->object->isInUse();
1307 
1308  if ($this->object->_questionExistsInPool($this->object->getId()) && $count) {
1309  global $rbacsystem;
1310  if ($rbacsystem->checkAccess("write", $_GET["ref_id"])) {
1311  ilUtil::sendInfo(sprintf($this->lng->txt("qpl_question_is_in_use"), $count));
1312  }
1313  }
1314 
1315  return assQuestion::_getQuestionTypeName($this->object->getQuestionType());
1316  }
1317 
1318  public function showSuggestedSolution()
1319  {
1320  $this->suggestedsolution();
1321  }
1322 
1328  public function suggestedsolution()
1329  {
1330  global $ilUser;
1331  global $ilAccess;
1332 
1333  $save = (is_array($_POST["cmd"]) && array_key_exists("suggestedsolution", $_POST["cmd"])) ? true : false;
1334 
1335  if ($save && $_POST["deleteSuggestedSolution"] == 1) {
1336  $this->object->deleteSuggestedSolutions();
1337  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1338  $this->ctrl->redirect($this, "suggestedsolution");
1339  }
1340 
1341  $output = "";
1342  $solution_array = $this->object->getSuggestedSolution(0);
1343  $options = array(
1344  "lm" => $this->lng->txt("obj_lm"),
1345  "st" => $this->lng->txt("obj_st"),
1346  "pg" => $this->lng->txt("obj_pg"),
1347  "git" => $this->lng->txt("glossary_term"),
1348  "file" => $this->lng->txt("fileDownload"),
1349  "text" => $this->lng->txt("solutionText")
1350  );
1351 
1352  if ((strcmp($_POST["solutiontype"], "file") == 0) && (strcmp($solution_array["type"], "file") != 0)) {
1353  $solution_array = array(
1354  "type" => "file"
1355  );
1356  } elseif ((strcmp($_POST["solutiontype"], "text") == 0) && (strcmp($solution_array["type"], "text") != 0)) {
1357  $oldOutputMode = $this->getRenderPurpose();
1358  $this->setRenderPurpose(self::RENDER_PURPOSE_INPUT_VALUE);
1359 
1360  $solution_array = array(
1361  "type" => "text",
1362  "value" => $this->getSolutionOutput(0, null, false, false, true, false, true)
1363  );
1364  $this->setRenderPurpose($oldsaveSuggestedSolutionOutputMode);
1365  }
1366  if ($save && strlen($_POST["filename"])) {
1367  $solution_array["value"]["filename"] = $_POST["filename"];
1368  }
1369  if ($save && strlen($_POST["solutiontext"])) {
1370  $solution_array["value"] = $_POST["solutiontext"];
1371  }
1372  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
1373  if (count($solution_array)) {
1374  $form = new ilPropertyFormGUI();
1375  $form->setFormAction($this->ctrl->getFormAction($this));
1376  $form->setTitle($this->lng->txt("solution_hint"));
1377  $form->setMultipart(true);
1378  $form->setTableWidth("100%");
1379  $form->setId("suggestedsolutiondisplay");
1380 
1381  // suggested solution output
1382  include_once "./Modules/TestQuestionPool/classes/class.ilSolutionTitleInputGUI.php";
1383  $title = new ilSolutionTitleInputGUI($this->lng->txt("showSuggestedSolution"), "solutiontype");
1384  $template = new ilTemplate("tpl.il_as_qpl_suggested_solution_input_presentation.html", true, true, "Modules/TestQuestionPool");
1385  if (strlen($solution_array["internal_link"])) {
1386  $href = assQuestion::_getInternalLinkHref($solution_array["internal_link"]);
1387  $template->setCurrentBlock("preview");
1388  $template->setVariable("TEXT_SOLUTION", $this->lng->txt("suggested_solution"));
1389  $template->setVariable("VALUE_SOLUTION", " <a href=\"$href\" target=\"content\">" . $this->lng->txt("view") . "</a> ");
1390  $template->parseCurrentBlock();
1391  } elseif ((strcmp($solution_array["type"], "file") == 0) && (is_array($solution_array["value"]))) {
1392  $href = $this->object->getSuggestedSolutionPathWeb() . $solution_array["value"]["name"];
1393  $template->setCurrentBlock("preview");
1394  $template->setVariable("TEXT_SOLUTION", $this->lng->txt("suggested_solution"));
1395  $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> ");
1396  $template->parseCurrentBlock();
1397  }
1398  $template->setVariable("TEXT_TYPE", $this->lng->txt("type"));
1399  $template->setVariable("VALUE_TYPE", $options[$solution_array["type"]]);
1400  $title->setHtml($template->get());
1401  $deletesolution = new ilCheckboxInputGUI("", "deleteSuggestedSolution");
1402  $deletesolution->setOptionTitle($this->lng->txt("deleteSuggestedSolution"));
1403  $title->addSubItem($deletesolution);
1404  $form->addItem($title);
1405 
1406  if (strcmp($solution_array["type"], "file") == 0) {
1407  // file
1408  $file = new ilFileInputGUI($this->lng->txt("fileDownload"), "file");
1409  $file->setRequired(true);
1410  $file->enableFileNameSelection("filename");
1411  //$file->setSuffixes(array("doc","xls","png","jpg","gif","pdf"));
1412  if ($_FILES["file"]["tmp_name"] && $file->checkInput()) {
1413  if (!file_exists($this->object->getSuggestedSolutionPath())) {
1414  ilUtil::makeDirParents($this->object->getSuggestedSolutionPath());
1415  }
1416 
1417  $res = ilUtil::moveUploadedFile($_FILES["file"]["tmp_name"], $_FILES["file"]["name"], $this->object->getSuggestedSolutionPath() . $_FILES["file"]["name"]);
1418  if ($res) {
1419  ilUtil::renameExecutables($this->object->getSuggestedSolutionPath());
1420 
1421  // remove an old file download
1422  if (is_array($solution_array["value"])) {
1423  @unlink($this->object->getSuggestedSolutionPath() . $solution_array["value"]["name"]);
1424  }
1425  $file->setValue($_FILES["file"]["name"]);
1426  $this->object->saveSuggestedSolution("file", "", 0, array("name" => $_FILES["file"]["name"], "type" => $_FILES["file"]["type"], "size" => $_FILES["file"]["size"], "filename" => $_POST["filename"]));
1427  $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
1428  if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
1429  return $this->originalSyncForm("suggestedsolution");
1430  } else {
1431  ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1432  $this->ctrl->redirect($this, "suggestedsolution");
1433  }
1434  } else {
1435  // BH: $res as info string? wtf? it holds a bool or something else!!?
1436  ilUtil::sendInfo($res);
1437  }
1438  } else {
1439  if (is_array($solution_array["value"])) {
1440  $file->setValue($solution_array["value"]["name"]);
1441  $file->setFilename((strlen($solution_array["value"]["filename"])) ? $solution_array["value"]["filename"] : $solution_array["value"]["name"]);
1442  }
1443  }
1444  $form->addItem($file);
1445  $hidden = new ilHiddenInputGUI("solutiontype");
1446  $hidden->setValue("file");
1447  $form->addItem($hidden);
1448  } elseif (strcmp($solution_array["type"], "text") == 0) {
1449  $solutionContent = $solution_array['value'];
1450  $solutionContent = $this->object->fixSvgToPng($solutionContent);
1451  $solutionContent = $this->object->fixUnavailableSkinImageSources($solutionContent);
1452  $question = new ilTextAreaInputGUI($this->lng->txt("solutionText"), "solutiontext");
1453  $question->setValue($this->object->prepareTextareaOutput($solutionContent));
1454  $question->setRequired(true);
1455  $question->setRows(10);
1456  $question->setCols(80);
1457  $question->setUseRte(true);
1458  $question->addPlugin("latex");
1459  $question->addButton("latex");
1460  $question->setRTESupport($this->object->getId(), "qpl", "assessment");
1461  $hidden = new ilHiddenInputGUI("solutiontype");
1462  $hidden->setValue("text");
1463  $form->addItem($hidden);
1464  $form->addItem($question);
1465  }
1466  if ($ilAccess->checkAccess("write", "", $_GET['ref_id'])) {
1467  $form->addCommandButton('showSuggestedSolution', $this->lng->txt('cancel'));
1468  $form->addCommandButton('suggestedsolution', $this->lng->txt('save'));
1469  }
1470 
1471  if ($save) {
1472  if ($form->checkInput()) {
1473  switch ($solution_array["type"]) {
1474  case "file":
1475  $this->object->saveSuggestedSolution("file", "", 0, array(
1476  "name" => $solution_array["value"]["name"],
1477  "type" => $solution_array["value"]["type"],
1478  "size" => $solution_array["value"]["size"],
1479  "filename" => $_POST["filename"]
1480  ));
1481  break;
1482  case "text":
1483  $this->object->saveSuggestedSolution("text", "", 0, $solution_array["value"]);
1484  break;
1485  }
1486  $originalexists = $this->object->_questionExistsInPool($this->object->original_id);
1487  if (($_GET["calling_test"] || (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer'])) && $originalexists && assQuestion::_isWriteable($this->object->original_id, $ilUser->getId())) {
1488  return $this->originalSyncForm("suggestedsolution");
1489  } else {
1490  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1491  $this->ctrl->redirect($this, "suggestedsolution");
1492  }
1493  }
1494  }
1495 
1496  $output = $form->getHTML();
1497  }
1498 
1499  $savechange = (strcmp($this->ctrl->getCmd(), "saveSuggestedSolution") == 0) ? true : false;
1500 
1501  $changeoutput = "";
1502  if ($ilAccess->checkAccess("write", "", $_GET['ref_id'])) {
1503  $formchange = new ilPropertyFormGUI();
1504  $formchange->setFormAction($this->ctrl->getFormAction($this));
1505  $formchange->setTitle((count($solution_array)) ? $this->lng->txt("changeSuggestedSolution") : $this->lng->txt("addSuggestedSolution"));
1506  $formchange->setMultipart(false);
1507  $formchange->setTableWidth("100%");
1508  $formchange->setId("suggestedsolution");
1509 
1510  $solutiontype = new ilRadioGroupInputGUI($this->lng->txt("suggestedSolutionType"), "solutiontype");
1511  foreach ($options as $opt_value => $opt_caption) {
1512  $solutiontype->addOption(new ilRadioOption($opt_caption, $opt_value));
1513  }
1514  if (count($solution_array)) {
1515  $solutiontype->setValue($solution_array["type"]);
1516  }
1517  $solutiontype->setRequired(true);
1518  $formchange->addItem($solutiontype);
1519 
1520  $formchange->addCommandButton("saveSuggestedSolution", $this->lng->txt("select"));
1521 
1522  if ($savechange) {
1523  $formchange->checkInput();
1524  }
1525  $changeoutput = $formchange->getHTML();
1526  }
1527 
1528  $this->tpl->setVariable("ADM_CONTENT", $changeoutput . $output);
1529  }
1530 
1531  public function outSolutionExplorer()
1532  {
1533  global $tree;
1534 
1535  include_once("./Modules/TestQuestionPool/classes/class.ilSolutionExplorer.php");
1536  $type = $_GET["link_new_type"];
1537  $search = $_GET["search_link_type"];
1538  $this->ctrl->setParameter($this, "link_new_type", $type);
1539  $this->ctrl->setParameter($this, "search_link_type", $search);
1540  $this->ctrl->saveParameter($this, array("subquestion_index", "link_new_type", "search_link_type"));
1541 
1542  ilUtil::sendInfo($this->lng->txt("select_object_to_link"));
1543 
1544  $parent_ref_id = $tree->getParentId($_GET["ref_id"]);
1545  $exp = new ilSolutionExplorer($this->ctrl->getLinkTarget($this, 'suggestedsolution'), get_class($this));
1546  $exp->setExpand($_GET['expand_sol'] ? $_GET['expand_sol'] : $parent_ref_id);
1547  $exp->setExpandTarget($this->ctrl->getLinkTarget($this, 'outSolutionExplorer'));
1548  $exp->setTargetGet("ref_id");
1549  $exp->setRefId($_GET["ref_id"]);
1550  $exp->addFilter($type);
1551  $exp->setSelectableType($type);
1552  if (isset($_GET['expandCurrentPath']) && $_GET['expandCurrentPath']) {
1553  $exp->expandPathByRefId($parent_ref_id);
1554  }
1555 
1556  // build html-output
1557  $exp->setOutput(0);
1558 
1559  $template = new ilTemplate("tpl.il_as_qpl_explorer.html", true, true, "Modules/TestQuestionPool");
1560  $template->setVariable("EXPLORER_TREE", $exp->getOutput());
1561  $template->setVariable("BUTTON_CANCEL", $this->lng->txt("cancel"));
1562  $template->setVariable("FORMACTION", $this->ctrl->getFormAction($this, "suggestedsolution"));
1563  $this->tpl->setVariable("ADM_CONTENT", $template->get());
1564  }
1565 
1566  public function saveSuggestedSolution()
1567  {
1568  global $tree;
1569 
1570  include_once("./Modules/TestQuestionPool/classes/class.ilSolutionExplorer.php");
1571  switch ($_POST["solutiontype"]) {
1572  case "lm":
1573  $type = "lm";
1574  $search = "lm";
1575  break;
1576  case "git":
1577  $type = "glo";
1578  $search = "glo";
1579  break;
1580  case "st":
1581  $type = "lm";
1582  $search = "st";
1583  break;
1584  case "pg":
1585  $type = "lm";
1586  $search = "pg";
1587  break;
1588  case "file":
1589  case "text":
1590  return $this->suggestedsolution();
1591  break;
1592  default:
1593  return $this->suggestedsolution();
1594  break;
1595  }
1596  if (isset($_POST['solutiontype'])) {
1597  $this->ctrl->setParameter($this, 'expandCurrentPath', 1);
1598  }
1599  $this->ctrl->setParameter($this, "link_new_type", $type);
1600  $this->ctrl->setParameter($this, "search_link_type", $search);
1601  $this->ctrl->redirect($this, "outSolutionExplorer");
1602  }
1603 
1604  public function cancelExplorer()
1605  {
1606  $this->ctrl->redirect($this, "suggestedsolution");
1607  }
1608 
1609  public function outPageSelector()
1610  {
1611  require_once 'Modules/TestQuestionPool/classes/tables/class.ilQuestionInternalLinkSelectionTableGUI.php';
1612  require_once 'Modules/LearningModule/classes/class.ilLMPageObject.php';
1613  require_once 'Modules/LearningModule/classes/class.ilObjContentObjectGUI.php';
1614 
1615  $this->ctrl->setParameter($this, 'q_id', $this->object->getId());
1616 
1617  $cont_obj_gui = new ilObjContentObjectGUI('', $_GET['source_id'], true);
1618  $cont_obj = $cont_obj_gui->object;
1619  $pages = ilLMPageObject::getPageList($cont_obj->getId());
1620  $shownpages = array();
1621  $tree = $cont_obj->getLMTree();
1622  $chapters = $tree->getSubtree($tree->getNodeData($tree->getRootId()));
1623 
1624  $rows = array();
1625 
1626  foreach ($chapters as $chapter) {
1627  $chapterpages = $tree->getChildsByType($chapter['obj_id'], 'pg');
1628  foreach ($chapterpages as $page) {
1629  if ($page['type'] == $_GET['search_link_type']) {
1630  array_push($shownpages, $page['obj_id']);
1631 
1632  if ($tree->isInTree($page['obj_id'])) {
1633  $path_str = $this->getContextPath($cont_obj, $page['obj_id']);
1634  } else {
1635  $path_str = '---';
1636  }
1637 
1638  $this->ctrl->setParameter($this, $page['type'], $page['obj_id']);
1639  $rows[] = array(
1640  'title' => $page['title'],
1641  'description' => ilUtil::prepareFormOutput($path_str),
1642  'text_add' => $this->lng->txt('add'),
1643  'href_add' => $this->ctrl->getLinkTarget($this, 'add' . strtoupper($page['type']))
1644  );
1645  }
1646  }
1647  }
1648  foreach ($pages as $page) {
1649  if (!in_array($page['obj_id'], $shownpages)) {
1650  $this->ctrl->setParameter($this, $page['type'], $page['obj_id']);
1651  $rows[] = array(
1652  'title' => $page['title'],
1653  'description' => '---',
1654  'text_add' => $this->lng->txt('add'),
1655  'href_add' => $this->ctrl->getLinkTarget($this, 'add' . strtoupper($page['type']))
1656  );
1657  }
1658  }
1659 
1660  require_once 'Modules/TestQuestionPool/classes/tables/class.ilQuestionInternalLinkSelectionTableGUI.php';
1661  $table = new ilQuestionInternalLinkSelectionTableGUI($this, 'cancelExplorer', __METHOD__);
1662  $table->setTitle($this->lng->txt('obj_' . ilUtil::stripSlashes($_GET['search_link_type'])));
1663  $table->setData($rows);
1664 
1665  $this->tpl->setContent($table->getHTML());
1666  }
1667 
1668  public function outChapterSelector()
1669  {
1670  require_once 'Modules/TestQuestionPool/classes/tables/class.ilQuestionInternalLinkSelectionTableGUI.php';
1671  require_once 'Modules/LearningModule/classes/class.ilObjContentObjectGUI.php';
1672 
1673  $this->ctrl->setParameter($this, 'q_id', $this->object->getId());
1674 
1675  $cont_obj_gui = new ilObjContentObjectGUI('', $_GET['source_id'], true);
1676  $cont_obj = $cont_obj_gui->object;
1677  $ctree = $cont_obj->getLMTree();
1678  $nodes = $ctree->getSubtree($ctree->getNodeData($ctree->getRootId()));
1679 
1680  $rows = array();
1681 
1682  foreach ($nodes as $node) {
1683  if ($node['type'] == $_GET['search_link_type']) {
1684  $this->ctrl->setParameter($this, $node['type'], $node['obj_id']);
1685  $rows[] = array(
1686  'title' => $node['title'],
1687  'description' => '',
1688  'text_add' => $this->lng->txt('add'),
1689  'href_add' => $this->ctrl->getLinkTarget($this, 'add' . strtoupper($node['type']))
1690  );
1691  }
1692  }
1693 
1694  $table = new ilQuestionInternalLinkSelectionTableGUI($this, 'cancelExplorer', __METHOD__);
1695  $table->setTitle($this->lng->txt('obj_' . ilUtil::stripSlashes($_GET['search_link_type'])));
1696  $table->setData($rows);
1697 
1698  $this->tpl->setContent($table->getHTML());
1699  }
1700 
1701  public function outGlossarySelector()
1702  {
1703  require_once 'Modules/TestQuestionPool/classes/tables/class.ilQuestionInternalLinkSelectionTableGUI.php';
1704  require_once 'Modules/Glossary/classes/class.ilObjGlossary.php';
1705 
1706  $this->ctrl->setParameter($this, 'q_id', $this->object->getId());
1707 
1708  $glossary = new ilObjGlossary($_GET['source_id'], true);
1709  $terms = $glossary->getTermList();
1710 
1711  $rows = array();
1712 
1713  foreach ($terms as $term) {
1714  $this->ctrl->setParameter($this, 'git', $term['id']);
1715  $rows[] = array(
1716  'title' => $term['term'],
1717  'description' => '',
1718  'text_add' => $this->lng->txt('add'),
1719  'href_add' => $this->ctrl->getLinkTarget($this, 'addGIT')
1720  );
1721  }
1722 
1723  $table = new ilQuestionInternalLinkSelectionTableGUI($this, 'cancelExplorer', __METHOD__);
1724  $table->setTitle($this->lng->txt('glossary_term'));
1725  $table->setData($rows);
1726 
1727  $this->tpl->setContent($table->getHTML());
1728  }
1729 
1730  public function linkChilds()
1731  {
1732  $this->ctrl->saveParameter($this, array("subquestion_index", "link_new_type", "search_link_type"));
1733  switch ($_GET["search_link_type"]) {
1734  case "pg":
1735  return $this->outPageSelector();
1736  break;
1737  case "st":
1738  return $this->outChapterSelector();
1739  break;
1740  case "glo":
1741  return $this->outGlossarySelector();
1742  break;
1743  case "lm":
1744  $subquestion_index = ($_GET["subquestion_index"] > 0) ? $_GET["subquestion_index"] : 0;
1745  $this->object->saveSuggestedSolution("lm", "il__lm_" . $_GET["source_id"], $subquestion_index);
1746  ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1747  $this->ctrl->redirect($this, "suggestedsolution");
1748  break;
1749  }
1750  }
1751 
1752  public function addPG()
1753  {
1754  $subquestion_index = 0;
1755  if (strlen($_GET["subquestion_index"]) && $_GET["subquestion_index"] >= 0) {
1756  $subquestion_index = $_GET["subquestion_index"];
1757  }
1758  $this->object->saveSuggestedSolution("pg", "il__pg_" . $_GET["pg"], $subquestion_index);
1759  ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1760  $this->ctrl->redirect($this, "suggestedsolution");
1761  }
1762 
1763  public function addST()
1764  {
1765  $subquestion_index = 0;
1766  if (strlen($_GET["subquestion_index"]) && $_GET["subquestion_index"] >= 0) {
1767  $subquestion_index = $_GET["subquestion_index"];
1768  }
1769  $this->object->saveSuggestedSolution("st", "il__st_" . $_GET["st"], $subquestion_index);
1770  ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1771  $this->ctrl->redirect($this, "suggestedsolution");
1772  }
1773 
1774  public function addGIT()
1775  {
1776  $subquestion_index = 0;
1777  if (strlen($_GET["subquestion_index"]) && $_GET["subquestion_index"] >= 0) {
1778  $subquestion_index = $_GET["subquestion_index"];
1779  }
1780  $this->object->saveSuggestedSolution("git", "il__git_" . $_GET["git"], $subquestion_index);
1781  ilUtil::sendSuccess($this->lng->txt("suggested_solution_added_successfully"), true);
1782  $this->ctrl->redirect($this, "suggestedsolution");
1783  }
1784 
1785  public function isSaveCommand()
1786  {
1787  return in_array($this->ctrl->getCmd(), array('save', 'saveEdit', 'saveReturn'));
1788  }
1789 
1798  public static function getCommandsFromClassConstants($guiClassName, $cmdConstantNameBegin = 'CMD_')
1799  {
1800  $reflectionClass = new ReflectionClass($guiClassName);
1801 
1802  $commands = null;
1803 
1804  if ($reflectionClass instanceof ReflectionClass) {
1805  $commands = array();
1806 
1807  foreach ($reflectionClass->getConstants() as $constName => $constValue) {
1808  if (substr($constName, 0, strlen($cmdConstantNameBegin)) == $cmdConstantNameBegin) {
1809  $commands[] = $constValue;
1810  }
1811  }
1812  }
1813 
1814  return $commands;
1815  }
1816 
1817  public function setQuestionTabs()
1818  {
1819  global $rbacsystem, $ilTabs;
1820 
1821  $ilTabs->clearTargets();
1822 
1823  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
1824  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1825  $q_type = $this->object->getQuestionType();
1826 
1827  if (strlen($q_type)) {
1828  $classname = $q_type . "GUI";
1829  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
1830  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
1831  }
1832 
1833  if ($_GET["q_id"]) {
1834  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
1835  // edit page
1836  $ilTabs->addTarget(
1837  "edit_page",
1838  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
1839  array("edit", "insert", "exec_pg"),
1840  "",
1841  "",
1842  $force_active
1843  );
1844  }
1845 
1846  $this->addTab_QuestionPreview($ilTabs);
1847  }
1848  $force_active = false;
1849  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
1850  $url = "";
1851  if ($classname) {
1852  $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
1853  }
1854  $force_active = false;
1855  // edit question properties
1856  $ilTabs->addTarget(
1857  "edit_question",
1858  $url,
1859  $this->getEditQuestionTabCommands(),
1860  $classname,
1861  "",
1862  $force_active
1863  );
1864  }
1865 
1866  // add tab for question feedback within common class assQuestionGUI
1867  $this->addTab_QuestionFeedback($ilTabs);
1868 
1869  // add tab for question hint within common class assQuestionGUI
1870  $this->addTab_QuestionHints($ilTabs);
1871 
1872  // add tab for question's suggested solution within common class assQuestionGUI
1873  $this->addTab_SuggestedSolution($ilTabs, $classname);
1874 
1875  // Assessment of questions sub menu entry
1876  if ($_GET["q_id"]) {
1877  $ilTabs->addTarget(
1878  "statistics",
1879  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1880  array("assessment"),
1881  $classname,
1882  ""
1883  );
1884  }
1885 
1886  $this->addBackTab($ilTabs);
1887  }
1888 
1889  public function addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
1890  {
1891  if ($_GET["q_id"]) {
1892  $tabs->addTarget(
1893  "suggested_solution",
1894  $this->ctrl->getLinkTargetByClass($classname, "suggestedsolution"),
1895  array("suggestedsolution", "saveSuggestedSolution", "outSolutionExplorer", "cancel",
1896  "addSuggestedSolution","cancelExplorer", "linkChilds", "removeSuggestedSolution"
1897  ),
1898  $classname,
1899  ""
1900  );
1901  }
1902  }
1903 
1904  final public function getEditQuestionTabCommands()
1905  {
1906  return array_merge($this->getBasicEditQuestionTabCommands(), $this->getAdditionalEditQuestionCommands());
1907  }
1908 
1909  protected function getBasicEditQuestionTabCommands()
1910  {
1911  return array('editQuestion', 'save', 'saveEdit', 'originalSyncForm');
1912  }
1913 
1915  {
1916  return array();
1917  }
1918 
1926  {
1927  global $ilCtrl;
1928 
1929  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionFeedbackEditingGUI.php';
1930  $tabCommands = self::getCommandsFromClassConstants('ilAssQuestionFeedbackEditingGUI');
1931 
1932  $tabLink = $ilCtrl->getLinkTargetByClass('ilAssQuestionFeedbackEditingGUI', ilAssQuestionFeedbackEditingGUI::CMD_SHOW);
1933 
1934  $tabs->addTarget('tst_feedback', $tabLink, $tabCommands, $ilCtrl->getCmdClass(), '');
1935  }
1936 
1940  protected function addTab_Units(ilTabsGUI $tabs)
1941  {
1945  global $ilCtrl;
1946 
1947  $tabs->addTarget('units', $ilCtrl->getLinkTargetByClass('ilLocalUnitConfigurationGUI', ''), '', 'illocalunitconfigurationgui');
1948  }
1949 
1956  protected function addTab_QuestionHints(ilTabsGUI $tabs)
1957  {
1958  global $ilCtrl;
1959 
1960  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintsGUI.php';
1961 
1962  switch ($ilCtrl->getCmdClass()) {
1963  case 'ilassquestionhintsgui':
1964 
1965  $tabCommands = self::getCommandsFromClassConstants('ilAssQuestionHintsGUI');
1966  break;
1967 
1968  case 'ilassquestionhintgui':
1969 
1970  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintGUI.php';
1971  $tabCommands = self::getCommandsFromClassConstants('ilAssQuestionHintGUI');
1972  break;
1973 
1974  default:
1975 
1976  $tabCommands = array();
1977  }
1978 
1979  $tabLink = $ilCtrl->getLinkTargetByClass('ilAssQuestionHintsGUI', ilAssQuestionHintsGUI::CMD_SHOW_LIST);
1980 
1981  $tabs->addTarget('tst_question_hints_tab', $tabLink, $tabCommands, $ilCtrl->getCmdClass(), '');
1982  }
1983 
1984  protected function addTab_QuestionPreview(ilTabsGUI $tabsGUI)
1985  {
1986  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewGUI.php';
1987 
1988  $tabsGUI->addTarget(
1990  $this->ctrl->getLinkTargetByClass('ilAssQuestionPreviewGUI', ilAssQuestionPreviewGUI::CMD_SHOW),
1991  array(),
1992  array('ilAssQuestionPreviewGUI')
1993  );
1994  }
1995 
1996  abstract public function getSolutionOutput(
1997  $active_id,
1998  $pass = null,
1999  $graphicalOutput = false,
2000  $result_output = false,
2001  $show_question_only = true,
2002  $show_feedback = false,
2003  $show_correct_solution = false,
2004  $show_manual_scoring = false,
2005  $show_question_text = true
2006  );
2007 
2008  protected function hasCorrectSolution($activeId, $passIndex)
2009  {
2010  $reachedPoints = $this->object->getAdjustedReachedPoints($activeId, $passIndex, true);
2011  $maximumPoints = $this->object->getMaximumPoints();
2012 
2013  return $reachedPoints == $maximumPoints;
2014  }
2015 
2016  public function isAutosaveable()
2017  {
2018  return $this->object->isAutosaveable();
2019  }
2020 
2021  protected function writeQuestionGenericPostData()
2022  {
2023  $this->object->setTitle($_POST["title"]);
2024  $this->object->setAuthor($_POST["author"]);
2025  $this->object->setComment($_POST["comment"]);
2026  if ($this->object->getSelfAssessmentEditingMode()) {
2027  $this->object->setNrOfTries($_POST['nr_of_tries']);
2028  }
2029  $this->object->setQuestion(ilUtil::stripOnlySlashes($_POST['question'])); // ?
2030  $this->object->setEstimatedWorkingTime(
2031  $_POST["Estimated"]["hh"],
2032  $_POST["Estimated"]["mm"],
2033  $_POST["Estimated"]["ss"]
2034  );
2035  }
2036 
2037  abstract public function getPreview($show_question_only = false, $showInlineFeedback = false);
2038 
2047  final public function outQuestionForTest(
2048  $formaction,
2049  $active_id,
2050  // hey: prevPassSolutions - pass will be always available from now on
2051  $pass,
2052  // hey.
2053  $is_question_postponed = false,
2054  $user_post_solutions = false,
2055  $show_specific_inline_feedback = false
2056  ) {
2057  $formaction = $this->completeTestOutputFormAction($formaction, $active_id, $pass);
2058 
2059  $test_output = $this->getTestOutput(
2060  $active_id,
2061  $pass,
2062  $is_question_postponed,
2063  $user_post_solutions,
2064  $show_specific_inline_feedback
2065  );
2066 
2067  $this->magicAfterTestOutput();
2068 
2069  $this->tpl->setVariable("QUESTION_OUTPUT", $test_output);
2070  $this->tpl->setVariable("FORMACTION", $formaction);
2071  $this->tpl->setVariable("ENCTYPE", 'enctype="' . $this->getFormEncodingType() . '"');
2072  $this->tpl->setVariable("FORM_TIMESTAMP", time());
2073  }
2074 
2075  // hey: prevPassSolutions - $pass will be passed always from now on
2076  protected function completeTestOutputFormAction($formAction, $active_id, $pass)
2077  // hey.
2078  {
2079  return $formAction;
2080  }
2081 
2082  public function magicAfterTestOutput()
2083  {
2084  return;
2085  }
2086 
2087  abstract public function getTestOutput(
2088  $active_id,
2089  $pass,
2090  $is_question_postponed,
2091  $user_post_solutions,
2092  $show_specific_inline_feedback
2093  );
2094 
2095  public function getFormEncodingType()
2096  {
2097  return self::FORM_ENCODING_URLENCODE;
2098  }
2099 
2103  protected function addBackTab(ilTabsGUI $ilTabs)
2104  {
2105  if (($_GET["calling_test"] > 0) || ($_GET["test_ref_id"] > 0)) {
2106  $ref_id = $_GET["calling_test"];
2107  if (strlen($ref_id) == 0) {
2108  $ref_id = $_GET["test_ref_id"];
2109  }
2110 
2111  if (!$_GET['test_express_mode'] && !$GLOBALS['___test_express_mode']) {
2112  $ilTabs->setBackTarget($this->lng->txt("backtocallingtest"), "ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=$ref_id");
2113  } else {
2115  $ilTabs->setBackTarget($this->lng->txt("backtocallingtest"), $link);
2116  }
2117  } elseif (isset($_GET['calling_consumer']) && (int) $_GET['calling_consumer']) {
2118  $ref_id = (int) $_GET['calling_consumer'];
2120  if ($consumer instanceof ilQuestionEditingFormConsumer) {
2121  $ilTabs->setBackTarget($consumer->getQuestionEditingFormBackTargetLabel(), $consumer->getQuestionEditingFormBackTarget($_GET['consumer_context']));
2122  } else {
2123  require_once 'Services/Link/classes/class.ilLink.php';
2124  $ilTabs->setBackTarget($this->lng->txt("qpl"), ilLink::_getLink($ref_id));
2125  }
2126  } else {
2127  $ilTabs->setBackTarget($this->lng->txt("qpl"), $this->ctrl->getLinkTargetByClass("ilobjquestionpoolgui", "questions"));
2128  }
2129  }
2130 
2135 
2140  {
2141  $this->previewSession = $previewSession;
2142  }
2143 
2147  public function getPreviewSession()
2148  {
2149  return $this->previewSession;
2150  }
2151 
2155  protected function buildBasicEditFormObject()
2156  {
2157  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
2158  $form = new ilPropertyFormGUI();
2159 
2160  $form->setFormAction($this->ctrl->getFormAction($this));
2161 
2162  $form->setId($this->getType());
2163  $form->setTitle($this->outQuestionType());
2164 
2165  $form->setTableWidth('100%');
2166 
2167  $form->setMultipart(true);
2168 
2169  return $form;
2170  }
2171 
2172  public function showHints()
2173  {
2174  global $ilCtrl;
2175  $ilCtrl->redirectByClass('ilAssQuestionHintsGUI', ilAssQuestionHintsGUI::CMD_SHOW_LIST);
2176  }
2177 
2181  protected function buildEditForm()
2182  {
2183  $errors = $this->editQuestion(true); // TODO bheyser: editQuestion should be added to the abstract base class with a unified signature
2184  return $this->editForm;
2185  }
2186 }
QTI assessment class.
static sendSuccess($a_info="", $a_keep=false)
Send Success Message to Screen.
static makeDirParents($a_dir)
Create a new directory and all parent directories.
static getSelfAssessmentTags()
Get tags allowed in question tags in self assessment mode.
setQuestionActionCmd($questionActionCmd)
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms public
This class represents a duration (typical hh:mm:ss) property in a property form.
hasCorrectSolution($activeId, $passIndex)
getAssignmentsOfItem($a_item_id)
Get assignments for item.
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
This class represents an option in a radio group.
getTestOutput( $active_id, $pass, $is_question_postponed, $user_post_solutions, $show_specific_inline_feedback)
Taxonomy node <-> item assignment.
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
getPreview($show_question_only=false, $showInlineFeedback=false)
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question, working time.
Select taxonomy nodes input GUI.
setValue($a_value)
Set Value.
$_SESSION["AccountId"]
$result
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
Tabs GUI.
suggestedsolution()
Allows to add suggested solutions for questions.
$template
This class represents a property form user interface.
static _getGUIClassNameForId($a_q_id)
writePostData($always=false)
Evaluates a posted edit form and writes the form data in the question object.
$type
global $DIC
Definition: saml.php:7
$question_count
question count in test
addErrorMessage($errormessage)
const ADDITIONAL_CONTENT_EDITING_MODE_PAGE_OBJECT
constant for additional content editing mode "pageobject"
__construct()
assQuestionGUI constructor
$_GET["client_id"]
setShowHours($a_showhours)
Set Show Hours.
This class represents a section header in a property form.
This class represents a file property in a property form.
Class ilObjGlossary.
const SESSION_PREVIEW_DATA_BASE_INDEX
setPresentationContext($presentationContext)
setPreviousSolutionPrefilled($previousSolutionPrefilled)
static _getUsedHTMLTags($a_module="")
Returns an array of all allowed HTML tags for text editing.
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
static _getQuestionTypeName($type_tag)
Return the translation for a given question type tag.
setValue($a_value)
Set Value.
setQuestionHeaderBlockBuilder($questionHeaderBlockBuilder)
This class represents a checkbox property in a property form.
addItem($a_item)
Add Item (Property, SectionHeader).
setTaxonomyIds($taxonomyIds)
setRenderPurpose($renderPurpose)
callNewIdListeners($a_new_id)
Call the new id listeners.
addTarget( $a_text, $a_link, $a_cmd="", $a_cmdClass="", $a_frame="", $a_activate=false, $a_dir_text=false)
This class represents a custom property in a property form.
getQuestionTemplate()
get question template
Class ilQuestionUsagesTableGUI.
setEditContext($editContext)
setBackTarget($a_title, $a_target, $a_frame="")
back target for upper context
Question page GUI class.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
apply()
apply changes
const CMD_SHOW_LIST
command constants
saveEdit()
save question
static stripOnlySlashes($a_str)
strip slashes if magic qoutes is enabled
global $ilCtrl
Definition: ilias.php:18
$sequence_no
sequence number in test
static _getInternalLinkHref($target="")
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
populateJavascriptFilesRequiredForWorkForm(ilTemplate $tpl)
cancel()
cancel action
getType()
needed for page editor compliance
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...
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\+" &#(? foreach( $entity_files as $file) $output
This class represents a hidden form property in a property form.
& createQuestionGUI($question_type, $question_id=-1)
Creates a question gui representation.
This class represents a property in a property form.
addOption($a_option)
Add Option.
foreach($_POST as $key=> $value) $res
static getReturnToPageLink($q_id=null)
if(isset($_POST['submit'])) $form
addJavaScript($a_js_file, $a_add_version_parameter=true, $a_batch=2)
Add a javascript file that should be included in the header.
getILIASPage($html="")
Returns the ILIAS Page around a question.
This class represents a number property in a property form.
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...
static getManualFeedback($active_id, $question_id, $pass)
Retrieves the manual feedback for a question in a test.
special template class to simplify handling of ITX/PEAR
setTitle($a_title)
Set Title.
This class represents a text property in a property form.
originalSyncForm($return_to="", $return_to_feedback='')
addNewIdListener(&$a_object, $a_method, $a_parameters="")
Add a listener that is notified with the new question ID, when a new question is saved.
$ilUser
Definition: imgupload.php:18
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
setTargetGui($linkTargetGui)
getContextPath($cont_obj, $a_endnode_id, $a_startnode_id=1)
get context path in content object tree
getQuestionType()
Returns the question type string.
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
setTargetGuiClass($targetGuiClass)
Basic GUI class for assessment questions.
$consumer
Definition: demo.php:30
setErrorMessage($errormessage)
Create styles array
The data for the language used.
static _lookupType($a_id, $a_reference=false)
lookup object type
static _getClassNameForQType($q_type)
Input GUI class for taxonomy assignments.
completeTestOutputFormAction($formAction, $active_id, $pass)
$rows
Definition: xhr_table.php:10
executeCommand()
execute command
static _questionExistsInTest($question_id, $test_id)
getAnswerFeedbackOutput($active_id, $pass)
Returns the answer generic feedback depending on the results of the question.
if(!empty($this->data['faventry'])) $tabs
Definition: disco.tpl.php:124
$errors
Definition: index.php:6
Create new PHPExcel object
obj_idprivate
static renameExecutables($a_dir)
Rename uploaded executables for security reasons.
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)
This class represents a text area property in a property form.
addBackTab(ilTabsGUI $ilTabs)
outQuestionForTest( $formaction, $active_id, $pass, $is_question_postponed=false, $user_post_solutions=false, $show_specific_inline_feedback=false)
global $ilDB
$ret
Definition: parser.php:6
setPreviewSession($previewSession)
Class ilObjContentObjectGUI.
$i
Definition: disco.tpl.php:19
static getInstanceByRefId($a_ref_id, $stop_on_error=true)
get an instance of an Ilias object by reference id
static getGuiClassNameByQuestionType($questionType)
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
$url
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
if(empty($password)) $table
Definition: pwgen.php:24
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
static getPageList($lm_id)
static
getAsValueAttribute($a_value)
Returns a HTML value attribute.
setValue($a_value)
Set Value.
static redirect($a_script)
save()
save question
static getFeedbackClassNameByQuestionType($questionType)
$_POST["username"]
$html
Definition: example_001.php:87
saveReturn()
save question
getSpecificFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
setExpand($a_node_id)
set the expand option this value is stored in a SESSION variable to save it different view (lo view...
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
setOutputMode($a_mode=IL_PAGE_PRESENTATION)
Set Output Mode.
if(!isset($_REQUEST['ReturnTo'])) if(!isset($_REQUEST['AuthId'])) $options
Definition: as_login.php:20
$test
Definition: Utf8Test.php:84
setQuestionHTML($question_html)
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.
setQuestionCount($a_question_count)
static _isWriteable($question_id, $user_id)
Returns true if the question is writeable by a certain user.
setNavigationGUI($navigationGUI)