ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assErrorTextGUI.php
Go to the documentation of this file.
1 <?php
2  /*
3  +----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +----------------------------------------------------------------------------+
22 */
23 
24 include_once "./Modules/TestQuestionPool/classes/class.assQuestionGUI.php";
25 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
26 
38 {
47  function __construct($id = -1)
48  {
50  include_once "./Modules/TestQuestionPool/classes/class.assErrorText.php";
51  $this->object = new assErrorText();
52  $this->setErrorMessage($this->lng->txt("msg_form_save_error"));
53  if ($id >= 0)
54  {
55  $this->object->loadFromDb($id);
56  }
57  }
58 
59  function getCommand($cmd)
60  {
61  return $cmd;
62  }
63 
70  function writePostData($always = false)
71  {
72  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
73  if (!$hasErrors)
74  {
75  $this->object->setTitle($_POST["title"]);
76  $this->object->setAuthor($_POST["author"]);
77  $this->object->setComment($_POST["comment"]);
78  if ($this->getSelfAssessmentEditingMode())
79  {
80  $this->object->setNrOfTries($_POST['nr_of_tries']);
81  }
82 
83  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
84  $questiontext = $_POST["question"];
85  $this->object->setQuestion($questiontext);
86  // adding estimated working time
87  $this->object->setEstimatedWorkingTime(
88  $_POST["Estimated"]["hh"],
89  $_POST["Estimated"]["mm"],
90  $_POST["Estimated"]["ss"]
91  );
92  $this->object->setErrorText($_POST["errortext"]);
93  $points_wrong = str_replace(",", ".", $_POST["points_wrong"]);
94  if (strlen($points_wrong) == 0) $points_wrong = -1.0;
95  $this->object->setPointsWrong($points_wrong);
96 
97  if (!$this->getSelfAssessmentEditingMode())
98  {
99  $this->object->setTextSize($_POST["textsize"]);
100  }
101 
102  $this->object->flushErrorData();
103  if (is_array($_POST['errordata']['key']))
104  {
105  foreach ($_POST['errordata']['key'] as $idx => $val)
106  {
107  $this->object->addErrorData($val, $_POST['errordata']['value'][$idx], $_POST['errordata']['points'][$idx]);
108  }
109  }
110  return 0;
111  }
112  else
113  {
114  return 1;
115  }
116  }
117 
123  public function editQuestion($checkonly = FALSE)
124  {
125  $save = $this->isSaveCommand();
126  $this->getQuestionTemplate();
127 
128  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
129  $form = new ilPropertyFormGUI();
130  $form->setFormAction($this->ctrl->getFormAction($this));
131  $form->setTitle($this->outQuestionType());
132  $form->setMultipart(FALSE);
133  $form->setTableWidth("100%");
134  $form->setId("orderinghorizontal");
135 
136  $this->addBasicQuestionFormProperties($form);
137 
138  // errortext
139  $errortext = new ilTextAreaInputGUI($this->lng->txt("errortext"), "errortext");
140  $errortext->setValue(ilUtil::prepareFormOutput($this->object->getErrorText()));
141  $errortext->setRequired(TRUE);
142  $errortext->setInfo($this->lng->txt("errortext_info"));
143  $errortext->setRows(10);
144  $errortext->setCols(80);
145  $form->addItem($errortext);
146 
147  if (!$this->getSelfAssessmentEditingMode())
148  {
149  // textsize
150  $textsize = new ilNumberInputGUI($this->lng->txt("textsize"), "textsize");
151  $textsize->setValue(strlen($this->object->getTextSize()) ? $this->object->getTextSize() : 100.0);
152  $textsize->setInfo($this->lng->txt("textsize_errortext_info"));
153  $textsize->setSize(6);
154  $textsize->setSuffix("%");
155  $textsize->setMinValue(10);
156  $textsize->setRequired(true);
157  $form->addItem($textsize);
158  }
159 
160  if (count($this->object->getErrorData()) || $checkonly)
161  {
162  $header = new ilFormSectionHeaderGUI();
163  $header->setTitle($this->lng->txt("errors_section"));
164  $form->addItem($header);
165 
166  include_once "./Modules/TestQuestionPool/classes/class.ilErrorTextWizardInputGUI.php";
167  $errordata = new ilErrorTextWizardInputGUI($this->lng->txt("errors"), "errordata");
168  $values = array();
169  $errordata->setKeyName($this->lng->txt('text_wrong'));
170  $errordata->setValueName($this->lng->txt('text_correct'));
171  $errordata->setValues($this->object->getErrorData());
172  $form->addItem($errordata);
173 
174  // points for wrong selection
175  $points_wrong = new ilNumberInputGUI($this->lng->txt("points_wrong"), "points_wrong");
176  $points_wrong->allowDecimals(true);
177  $points_wrong->setValue($this->object->getPointsWrong());
178  $points_wrong->setInfo($this->lng->txt("points_wrong_info"));
179  $points_wrong->setSize(6);
180  $points_wrong->setRequired(true);
181  $form->addItem($points_wrong);
182  }
183 
184  $form->addCommandButton("analyze", $this->lng->txt('analyze_errortext'));
185  $this->addQuestionFormCommandButtons($form);
186 
187  $errors = false;
188 
189  if ($save)
190  {
191  $form->setValuesByPost();
192  $errors = !$form->checkInput();
193  $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we need this if we don't want to have duplication of backslashes
194  if ($errors) $checkonly = false;
195  }
196 
197  if (!$checkonly) $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
198  return $errors;
199  }
200 
204  public function analyze()
205  {
206  $this->writePostData(true);
207  $this->object->setErrorData($this->object->getErrorsFromText($_POST['errortext']));
208  $this->editQuestion();
209  }
210 
211  function outQuestionForTest($formaction, $active_id, $pass = NULL, $is_postponed = FALSE, $use_post_solutions = FALSE, $show_feedback = FALSE)
212  {
213  $test_output = $this->getTestOutput($active_id, $pass, $is_postponed, $use_post_solutions, $show_feedback);
214  $this->tpl->setVariable("QUESTION_OUTPUT", $test_output);
215  $this->tpl->setVariable("FORMACTION", $formaction);
216  }
217 
232  $active_id,
233  $pass = NULL,
234  $graphicalOutput = FALSE,
235  $result_output = FALSE,
236  $show_question_only = TRUE,
237  $show_feedback = FALSE,
238  $show_correct_solution = FALSE,
239  $show_manual_scoring = FALSE,
240  $show_question_text = TRUE
241  )
242  {
243  // get the solution of the user for the active pass or from the last pass if allowed
244  $template = new ilTemplate("tpl.il_as_qpl_errortext_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
245 
246  $selections = array();
247  if (($active_id > 0) && (!$show_correct_solution))
248  {
249  $solutions =& $this->object->getSolutionValues($active_id, $pass);
250  if (is_array($solutions))
251  {
252  foreach ($solutions as $solution)
253  {
254  array_push($selections, $solution['value1']);
255  }
256  $errortext_value = join(",", $selections);
257  }
258  }
259  else
260  {
261  $selections = $this->object->getBestSelection();
262  }
263 
264  if (($active_id > 0) && (!$show_correct_solution))
265  {
266  $reached_points = $this->object->getReachedPoints($active_id, $pass);
267  }
268  else
269  {
270  $reached_points = $this->object->getPoints();
271  }
272 
273  if ($result_output)
274  {
275  $resulttext = ($reached_points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
276  $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $reached_points));
277  }
278  if ($this->object->getTextSize() >= 10) echo $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
279  if ($show_question_text==true)
280  {
281  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
282  }
283  $errortext = $this->object->createErrorTextOutput($selections, $graphicalOutput, $show_correct_solution);
284  $errortext = preg_replace("/#HREF\d+/is", "javascript:void(0);", $errortext);
285  $template->setVariable("ERRORTEXT", $errortext);
286  $questionoutput = $template->get();
287 
288  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
289 
290  $feedback = '';
291  if($show_feedback)
292  {
293  $fb = $this->getGenericFeedbackOutput($active_id, $pass);
294  $feedback .= strlen($fb) ? $fb : '';
295 
296  $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
297  $feedback .= strlen($fb) ? $fb : '';
298  }
299  if (strlen($feedback)) $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
300 
301  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
302 
303  $solutionoutput = $solutiontemplate->get();
304  if (!$show_question_only)
305  {
306  // get page object output
307  $solutionoutput = '<div class="ilc_question_Standard">'.$solutionoutput."</div>";
308  }
309  return $solutionoutput;
310  }
311 
312  function getPreview($show_question_only = FALSE)
313  {
314  $template = new ilTemplate("tpl.il_as_qpl_errortext_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
315  if ($this->object->getTextSize() >= 10) echo $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
316  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
317  $errortext = $this->object->createErrorTextOutput($selections);
318  $errortext = preg_replace("/#HREF\d+/is", "javascript:void(0);", $errortext);
319  $template->setVariable("ERRORTEXT", $errortext);
320  $template->setVariable("ERRORTEXT_ID", "qst_" . $this->object->getId());
321  $questionoutput = $template->get();
322  if (!$show_question_only)
323  {
324  // get page object output
325  $questionoutput = $this->getILIASPage($questionoutput);
326  }
327  include_once "./Services/YUI/classes/class.ilYuiUtil.php";
329  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/errortext.js");
330  return $questionoutput;
331  }
332 
333  function getTestOutput($active_id, $pass = NULL, $is_postponed = FALSE, $use_post_solutions = FALSE, $show_feedback = FALSE)
334  {
335  // generate the question output
336  $template = new ilTemplate("tpl.il_as_qpl_errortext_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
337  if ($active_id)
338  {
339  $solutions = NULL;
340  include_once "./Modules/Test/classes/class.ilObjTest.php";
341  if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
342  {
343  if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
344  }
345  $solutions =& $this->object->getSolutionValues($active_id, $pass);
346  }
347  $errortext_value = "";
348  if (strlen($_SESSION['qst_selection']))
349  {
350  $this->object->toggleSelection($_SESSION['qst_selection'], $active_id, $pass);
351  unset($_SESSION['qst_selection']);
352  $solutions =& $this->object->getSolutionValues($active_id, $pass);
353  }
354  $selections = array();
355  if (is_array($solutions))
356  {
357  foreach ($solutions as $solution)
358  {
359  array_push($selections, $solution['value1']);
360  }
361  $errortext_value = join(",", $selections);
362  }
363  if ($this->object->getTextSize() >= 10) echo $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
364  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
365  $errortext = $this->object->createErrorTextOutput($selections);
366  $errortext = preg_replace_callback("/#HREF(\d+)/is", array(&$this, 'exchangeURL'), $errortext);
367  $this->ctrl->setParameterByClass('iltestoutputgui', 'errorvalue', '');
368  $template->setVariable("ERRORTEXT", $errortext);
369  $template->setVariable("ERRORTEXT_ID", "qst_" . $this->object->getId());
370  $template->setVariable("ERRORTEXT_VALUE", $errortext_value);
371 
372  $questionoutput = $template->get();
373  if (!$show_question_only)
374  {
375  // get page object output
376  $questionoutput = $this->getILIASPage($questionoutput);
377  }
378  include_once "./Services/YUI/classes/class.ilYuiUtil.php";
380  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/errortext.js");
381  $questionoutput = $template->get();
382  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
383  return $pageoutput;
384  }
385 
386  public function exchangeURL($matches)
387  {
388  $this->ctrl->setParameterByClass('iltestoutputgui', 'qst_selection', $matches[1]);
389  return $this->ctrl->getLinkTargetByClass('iltestoutputgui', 'gotoQuestion');
390  }
391 
397  function saveFeedback()
398  {
399  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
400  $errors = $this->feedback(true);
401  $this->object->saveFeedbackGeneric(0, $_POST["feedback_incomplete"]);
402  $this->object->saveFeedbackGeneric(1, $_POST["feedback_complete"]);
403  foreach ($this->object->getErrorData() as $index => $answer)
404  {
405  $this->object->saveFeedbackSingleAnswer($index, $_POST["feedback_answer_$index"]);
406  }
407 
408  $this->object->cleanupMediaObjectUsage();
410  }
411 
419  function setQuestionTabs()
420  {
421  global $rbacsystem, $ilTabs;
422 
423  $this->ctrl->setParameterByClass("ilpageobjectgui", "q_id", $_GET["q_id"]);
424  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
425  $q_type = $this->object->getQuestionType();
426 
427  if (strlen($q_type))
428  {
429  $classname = $q_type . "GUI";
430  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
431  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
432  }
433 
434  if ($_GET["q_id"])
435  {
436  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
437  {
438  // edit page
439  $ilTabs->addTarget("edit_page",
440  $this->ctrl->getLinkTargetByClass("ilPageObjectGUI", "edit"),
441  array("edit", "insert", "exec_pg"),
442  "", "", $force_active);
443  }
444 
445  // edit page
446  $ilTabs->addTarget("preview",
447  $this->ctrl->getLinkTargetByClass("ilPageObjectGUI", "preview"),
448  array("preview"),
449  "ilPageObjectGUI", "", $force_active);
450  }
451 
452  $force_active = false;
453  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
454  {
455  $url = "";
456  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
457  // edit question properties
458  $ilTabs->addTarget("edit_question",
459  $url,
460  array("editQuestion", "save", "saveEdit", "analyze", "originalSyncForm"),
461  $classname, "", $force_active);
462  }
463 
464  if ($_GET["q_id"])
465  {
466  $ilTabs->addTarget("feedback",
467  $this->ctrl->getLinkTargetByClass($classname, "feedback"),
468  array("feedback", "saveFeedback"),
469  $classname, "");
470  }
471 
472  // add tab for question hint within common class assQuestionGUI
473  $this->addTab_QuestionHints($ilTabs);
474 
475  if ($_GET["q_id"])
476  {
477  $ilTabs->addTarget("solution_hint",
478  $this->ctrl->getLinkTargetByClass($classname, "suggestedsolution"),
479  array("suggestedsolution", "saveSuggestedSolution", "outSolutionExplorer", "cancel",
480  "addSuggestedSolution","cancelExplorer", "linkChilds", "removeSuggestedSolution"
481  ),
482  $classname,
483  ""
484  );
485  }
486 
487  // Assessment of questions sub menu entry
488  if ($_GET["q_id"])
489  {
490  $ilTabs->addTarget("statistics",
491  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
492  array("assessment"),
493  $classname, "");
494  }
495 
496  if (($_GET["calling_test"] > 0) || ($_GET["test_ref_id"] > 0))
497  {
498  $ref_id = $_GET["calling_test"];
499  if (strlen($ref_id) == 0) $ref_id = $_GET["test_ref_id"];
500 
501  global $___test_express_mode;
502 
503  if (!$_GET['test_express_mode'] && !$___test_express_mode) {
504  $ilTabs->setBackTarget($this->lng->txt("backtocallingtest"), "ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=$ref_id");
505  }
506  else {
508  $ilTabs->setBackTarget($this->lng->txt("backtocallingtest"), $link);
509  }
510  }
511  else
512  {
513  $ilTabs->setBackTarget($this->lng->txt("qpl"), $this->ctrl->getLinkTargetByClass("ilobjquestionpoolgui", "questions"));
514  }
515  }
516 
522  function feedback($checkonly = false)
523  {
524  $save = (strcmp($this->ctrl->getCmd(), "saveFeedback") == 0) ? TRUE : FALSE;
525  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
526  $form = new ilPropertyFormGUI();
527  $form->setFormAction($this->ctrl->getFormAction($this));
528  $form->setTitle($this->lng->txt('feedback_answers'));
529  $form->setTableWidth("98%");
530  $form->setId("feedback");
531 
532  $complete = new ilTextAreaInputGUI($this->lng->txt("feedback_complete_solution"), "feedback_complete");
533  $complete->setValue($this->object->prepareTextareaOutput($this->object->getFeedbackGeneric(1)));
534  $complete->setRequired(false);
535  $complete->setRows(10);
536  $complete->setCols(80);
537  if (!$this->getPreventRteUsage())
538  {
539  $complete->setUseRte(true);
540  }
541  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
542  $complete->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
543  $complete->addPlugin("latex");
544  $complete->addButton("latex");
545  $complete->addButton("pastelatex");
546  $complete->setRTESupport($this->object->getId(), "qpl", "assessment", null, false, '3.4.7');
547  $form->addItem($complete);
548 
549  $incomplete = new ilTextAreaInputGUI($this->lng->txt("feedback_incomplete_solution"), "feedback_incomplete");
550  $incomplete->setValue($this->object->prepareTextareaOutput($this->object->getFeedbackGeneric(0)));
551  $incomplete->setRequired(false);
552  $incomplete->setRows(10);
553  $incomplete->setCols(80);
554  if (!$this->getPreventRteUsage())
555  {
556  $incomplete->setUseRte(true);
557  }
558  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
559  $incomplete->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
560  $incomplete->addPlugin("latex");
561  $incomplete->addButton("latex");
562  $incomplete->addButton("pastelatex");
563  $incomplete->setRTESupport($this->object->getId(), "qpl", "assessment", null, false, '3.4.7');
564  $form->addItem($incomplete);
565 
566  if (!$this->getSelfAssessmentEditingMode())
567  {
568  foreach ($this->object->getErrorData() as $index => $answer)
569  {
570  $caption = $ordinal = $index+1;
571  $caption .= '. <br />"' . $answer->text_wrong . '" =&gt; ';
572  $caption .= '"' . $answer->text_correct . '"';
573  $caption .= '</i>';
574 
575  $answerobj = new ilTextAreaInputGUI($this->object->prepareTextareaOutput($caption, true), "feedback_answer_$index");
576  $answerobj->setValue($this->object->prepareTextareaOutput($this->object->getFeedbackSingleAnswer($index)));
577  $answerobj->setRequired(false);
578  $answerobj->setRows(10);
579  $answerobj->setCols(80);
580  $answerobj->setUseRte(true);
581  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
582  $answerobj->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
583  $answerobj->addPlugin("latex");
584  $answerobj->addButton("latex");
585  $answerobj->addButton("pastelatex");
586  $answerobj->setRTESupport($this->object->getId(), "qpl", "assessment", null, false, '3.4.7');
587  $form->addItem($answerobj);
588  }
589  }
590 
591  global $ilAccess;
592  if ($ilAccess->checkAccess("write", "", $_GET['ref_id']) || $this->getSelfAssessmentEditingMode())
593  {
594  $form->addCommandButton("saveFeedback", $this->lng->txt("save"));
595  }
596  if ($save)
597  {
598  $form->setValuesByPost();
599  $errors = !$form->checkInput();
600  $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we need this if we don't want to have duplication of backslashes
601  }
602  if (!$checkonly) $this->tpl->setVariable("ADM_CONTENT", $form->getHTML());
603  return $errors;
604  }
605 
606  function getSpecificFeedbackOutput($active_id, $pass)
607  {
608  $feedback = '<table><tbody>';
609  $selection = $this->object->getBestSelection(false);
610  $elements = array();
611  foreach(preg_split("/[\n\r]+/", $this->object->errortext) as $line)
612  {
613  $elements = array_merge( $elements, preg_split("/\s+/", $line));
614  }
615 
616  $matchedIndexes = array();
617 
618  $i = 0;
619  foreach ($selection as $index => $answer)
620  {
621  $caption = $ordinal = $index+1 .'.<i> ';
622  $caption .= $elements[$answer];
623  $caption = str_replace('#', '', $caption);
624  $caption .= '</i>:';
625 
626  $feedback .= '<tr><td>';
627 
628  $feedback .= $caption .'</td><td>';
629  foreach ($this->object->getErrorData() as $idx => $ans)
630  {
631  if( isset($matchedIndexes[$idx]) )
632  {
633  continue;
634  }
635 
636  $cand = '#'.$ans->text_wrong;
637  if ($elements[$answer] == $cand)
638  {
639  $feedback .= $this->object->getFeedbackSingleAnswer($idx) . '</td> </tr>';
640 
641  $matchedIndexes[$idx] = $idx;
642 
643  break;
644  }
645  }
646  #$feedback .= $this->object->getFeedbackSingleAnswer($answer) . '</td> </tr>';
647  }
648  $feedback .= '</tbody></table>';
649  return $this->object->prepareTextareaOutput($feedback, TRUE);
650  }
651 
652 }
653 ?>