ILIAS  release_4-4 Revision
class.assErrorTextGUI.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once './Modules/TestQuestionPool/classes/class.assQuestionGUI.php';
5 require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiQuestionScoringAdjustable.php';
6 require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiAnswerScoringAdjustable.php';
7 
8 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
9 
24 class assErrorTextGUI extends assQuestionGUI //implements ilGuiQuestionScoringAdjustable, ilGuiAnswerScoringAdjustable
25 {
34  public function __construct($id = -1)
35  {
36  parent::__construct();
37  include_once "./Modules/TestQuestionPool/classes/class.assErrorText.php";
38  $this->object = new assErrorText();
39  $this->setErrorMessage($this->lng->txt("msg_form_save_error"));
40  if ($id >= 0)
41  {
42  $this->object->loadFromDb($id);
43  }
44  }
45 
54  function writePostData($always = false)
55  {
56  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
57  if (!$hasErrors)
58  {
62  $this->saveTaxonomyAssignments();
63  return 0;
64  }
65  return 1;
66  }
67 
68  public function writeAnswerSpecificPostData($always = false)
69  {
70  if (is_array( $_POST['errordata']['key'] ))
71  {
72  $this->object->flushErrorData();
73  foreach ($_POST['errordata']['key'] as $idx => $val)
74  {
75  $this->object->addErrorData( $val,
76  $_POST['errordata']['value'][$idx],
77  $_POST['errordata']['points'][$idx]
78  );
79  }
80  }
81  }
82 
83  public function writeQuestionSpecificPostData($always = false)
84  {
85  $questiontext = $_POST["question"];
86  $this->object->setQuestion( $questiontext );
87  $this->object->setErrorText( $_POST["errortext"] );
88  $points_wrong = str_replace( ",", ".", $_POST["points_wrong"] );
89  if (strlen( $points_wrong ) == 0)
90  $points_wrong = -1.0;
91  $this->object->setPointsWrong( $points_wrong );
92 
93  if (!$this->object->getSelfAssessmentEditingMode())
94  {
95  $this->object->setTextSize( $_POST["textsize"] );
96  }
97  }
98 
106  public function editQuestion($checkonly = FALSE)
107  {
108  $save = $this->isSaveCommand();
109  $this->getQuestionTemplate();
110 
111  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
112  $form = new ilPropertyFormGUI();
113  $form->setFormAction($this->ctrl->getFormAction($this));
114  $form->setTitle($this->outQuestionType());
115  $form->setMultipart(FALSE);
116  $form->setTableWidth("100%");
117  $form->setId("orderinghorizontal");
118 
119  $this->addBasicQuestionFormProperties( $form );
120 
121  $this->populateQuestionSpecificFormPart( $form );
122 
123  if (count($this->object->getErrorData()) || $checkonly)
124  {
125  $this->populateAnswerSpecificFormPart( $form );
126  }
127 
128  $this->populateTaxonomyFormSection($form);
129 
130  $form->addCommandButton("analyze", $this->lng->txt('analyze_errortext'));
131  $this->addQuestionFormCommandButtons($form);
132 
133  $errors = false;
134 
135  if ($save)
136  {
137  $form->setValuesByPost();
138  $errors = !$form->checkInput();
139  $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
140  if ($errors) $checkonly = false;
141  }
142 
143  if (!$checkonly) $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
144  return $errors;
145  }
146 
152  {
153  $header = new ilFormSectionHeaderGUI();
154  $header->setTitle( $this->lng->txt( "errors_section" ) );
155  $form->addItem( $header );
156 
157  include_once "./Modules/TestQuestionPool/classes/class.ilErrorTextWizardInputGUI.php";
158  $errordata = new ilErrorTextWizardInputGUI($this->lng->txt( "errors" ), "errordata");
159  $errordata->setKeyName( $this->lng->txt( 'text_wrong' ) );
160  $errordata->setValueName( $this->lng->txt( 'text_correct' ) );
161  $errordata->setValues( $this->object->getErrorData() );
162  $form->addItem( $errordata );
163 
164  // points for wrong selection
165  $points_wrong = new ilNumberInputGUI($this->lng->txt( "points_wrong" ), "points_wrong");
166  $points_wrong->allowDecimals(true);
167  $points_wrong->setValue( $this->object->getPointsWrong() );
168  $points_wrong->setInfo( $this->lng->txt( "points_wrong_info" ) );
169  $points_wrong->setSize( 6 );
170  $points_wrong->setRequired( true );
171  $form->addItem( $points_wrong );
172  return $form;
173  }
174 
180  {
181  // errortext
182  $errortext = new ilTextAreaInputGUI($this->lng->txt( "errortext" ), "errortext");
183  $errortext->setValue( $this->object->getErrorText() );
184  $errortext->setRequired( TRUE );
185  $errortext->setInfo( $this->lng->txt( "errortext_info" ) );
186  $errortext->setRows( 10 );
187  $errortext->setCols( 80 );
188  $form->addItem( $errortext );
189 
190  if (!$this->object->getSelfAssessmentEditingMode())
191  {
192  // textsize
193  $textsize = new ilNumberInputGUI($this->lng->txt( "textsize" ), "textsize");
194  $textsize->setValue( strlen( $this->object->getTextSize() ) ? $this->object->getTextSize() : 100.0 );
195  $textsize->setInfo( $this->lng->txt( "textsize_errortext_info" ) );
196  $textsize->setSize( 6 );
197  $textsize->setSuffix( "%" );
198  $textsize->setMinValue( 10 );
199  $textsize->setRequired( true );
200  $form->addItem( $textsize );
201  }
202  }
203 
207  public function analyze()
208  {
209  $this->writePostData(true);
210  $this->object->setErrorData($this->object->getErrorsFromText($_POST['errortext']));
211  $this->editQuestion();
212  }
213 
215  $formaction,
216  $active_id,
217  $pass = NULL,
218  $is_postponed = FALSE,
219  $use_post_solutions = FALSE,
220  $show_feedback = FALSE
221  )
222  {
223  $test_output = $this->getTestOutput($active_id, $pass, $is_postponed, $use_post_solutions, $show_feedback);
224  $this->tpl->setVariable("QUESTION_OUTPUT", $test_output);
225  $this->tpl->setVariable("FORMACTION", $formaction);
226  }
227 
247  $active_id, $pass = NULL,
248  $graphicalOutput = FALSE,
249  $result_output = FALSE,
250  $show_question_only = TRUE,
251  $show_feedback = FALSE,
252  $show_correct_solution = FALSE,
253  $show_manual_scoring = FALSE,
254  $show_question_text = TRUE
255  )
256  {
257  // get the solution of the user for the active pass or from the last pass if allowed
258  $template = new ilTemplate("tpl.il_as_qpl_errortext_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
259 
260  $selections = array();
261  if (($active_id > 0) && (!$show_correct_solution)) {
262 
263  /* Retrieve tst_solutions entries. */
264  $reached_points = $this->object->getReachedPoints($active_id, $pass);
265  $solutions =& $this->object->getSolutionValues($active_id, $pass);
266  if (is_array($solutions)) {
267  foreach ($solutions as $solution) {
268  array_push($selections, (int) $solution['value1']);
269  }
270  $errortext_value = join(",", $selections);
271  }
272  }
273  else {
274  $selections = $this->object->getBestSelection();
275  $reached_points = $this->object->getPoints();
276  }
277 
278  if ($result_output) {
279  $resulttext = ($reached_points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
280  $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $reached_points));
281  }
282 
283  if ($this->object->getTextSize() >= 10)
284  echo $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
285 
286  if ($show_question_text==true)
287  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
288 
289  $errortext = $this->object->createErrorTextOutput($selections, $graphicalOutput, $show_correct_solution);
290  $errortext = preg_replace("/#HREF\d+/is", "javascript:void(0);", $errortext);
291 
292  $template->setVariable("ERRORTEXT", $errortext);
293  $questionoutput = $template->get();
294 
295  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
296 
297  $feedback = '';
298  if($show_feedback)
299  {
300  $fb = $this->getGenericFeedbackOutput($active_id, $pass);
301  $feedback .= strlen($fb) ? $fb : '';
302 
303  $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
304  $feedback .= strlen($fb) ? $fb : '';
305  }
306  if (strlen($feedback)) $solutiontemplate->setVariable("FEEDBACK", $feedback);
307 
308  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
309 
310  $solutionoutput = $solutiontemplate->get();
311  if (!$show_question_only)
312  // get page object output
313  $solutionoutput = '<div class="ilc_question_Standard">'.$solutionoutput."</div>";
314 
315  return $solutionoutput;
316  }
317 
318  function getPreview($show_question_only = FALSE)
319  {
320  $template = new ilTemplate("tpl.il_as_qpl_errortext_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
321  if ($this->object->getTextSize() >= 10) echo $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
322  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
323  $errortext = $this->object->createErrorTextOutput($selections);
324  $errortext = preg_replace("/#HREF\d+/is", "javascript:void(0);", $errortext);
325  $template->setVariable("ERRORTEXT", $errortext);
326  $template->setVariable("ERRORTEXT_ID", "qst_" . $this->object->getId());
327  $questionoutput = $template->get();
328  if (!$show_question_only)
329  {
330  // get page object output
331  $questionoutput = $this->getILIASPage($questionoutput);
332  }
333  include_once "./Services/YUI/classes/class.ilYuiUtil.php";
335  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/errortext.js");
336  return $questionoutput;
337  }
338 
339  function getTestOutput(
340  $active_id,
341  $pass = NULL,
342  $is_postponed = FALSE,
343  $use_post_solutions = FALSE,
344  $show_feedback = FALSE
345  )
346  {
347  // generate the question output
348  $template = new ilTemplate("tpl.il_as_qpl_errortext_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
349  if ($active_id)
350  {
351  $solutions = NULL;
352  include_once "./Modules/Test/classes/class.ilObjTest.php";
353  if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
354  {
355  if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
356  }
357  $solutions =& $this->object->getSolutionValues($active_id, $pass);
358  }
359  $errortext_value = "";
360  if (strlen($_SESSION['qst_selection']))
361  {
362  $this->object->toggleSelection($_SESSION['qst_selection'], $active_id, $pass);
363  unset($_SESSION['qst_selection']);
364  $solutions =& $this->object->getSolutionValues($active_id, $pass);
365  }
366  $selections = array();
367  if (is_array($solutions))
368  {
369  foreach ($solutions as $solution)
370  {
371  array_push($selections, $solution['value1']);
372  }
373  $errortext_value = join(",", $selections);
374  }
375  if ($this->object->getTextSize() >= 10) echo $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
376  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
377  $errortext = $this->object->createErrorTextOutput($selections);
378  $errortext = preg_replace_callback("/#HREF(\d+)/is", array(&$this, 'exchangeURL'), $errortext);
379  $this->ctrl->setParameterByClass('iltestoutputgui', 'errorvalue', '');
380  $template->setVariable("ERRORTEXT", $errortext);
381  $template->setVariable("ERRORTEXT_ID", "qst_" . $this->object->getId());
382  $template->setVariable("ERRORTEXT_VALUE", $errortext_value);
383 
384  $questionoutput = $template->get();
385  if (!$show_question_only)
386  {
387  // get page object output
388  $questionoutput = $this->getILIASPage($questionoutput);
389  }
390  include_once "./Services/YUI/classes/class.ilYuiUtil.php";
392  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/errortext.js");
393  $questionoutput = $template->get();
394  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
395  return $pageoutput;
396  }
397 
398  public function exchangeURL($matches)
399  {
400  $this->ctrl->setParameterByClass('iltestoutputgui', 'qst_selection', $matches[1]);
401  return $this->ctrl->getLinkTargetByClass('iltestoutputgui', 'gotoQuestion');
402  }
403 
411  function setQuestionTabs()
412  {
413  global $rbacsystem, $ilTabs;
414 
415  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
416  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
417  $q_type = $this->object->getQuestionType();
418 
419  if (strlen($q_type))
420  {
421  $classname = $q_type . "GUI";
422  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
423  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
424  }
425 
426  if ($_GET["q_id"])
427  {
428  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
429  {
430  // edit page
431  $ilTabs->addTarget("edit_page",
432  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
433  array("edit", "insert", "exec_pg"),
434  "", "", $force_active);
435  }
436 
437  // edit page
438  $ilTabs->addTarget("preview",
439  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "preview"),
440  array("preview"),
441  "ilAssQuestionPageGUI", "", $force_active);
442  }
443 
444  $force_active = false;
445  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
446  {
447  $url = "";
448  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
449  // edit question properties
450  $ilTabs->addTarget("edit_question",
451  $url,
452  array("editQuestion", "save", "saveEdit", "analyze", "originalSyncForm"),
453  $classname, "", $force_active);
454  }
455 
456  // add tab for question feedback within common class assQuestionGUI
457  $this->addTab_QuestionFeedback($ilTabs);
458 
459  // add tab for question hint within common class assQuestionGUI
460  $this->addTab_QuestionHints($ilTabs);
461 
462  if ($_GET["q_id"])
463  {
464  $ilTabs->addTarget("solution_hint",
465  $this->ctrl->getLinkTargetByClass($classname, "suggestedsolution"),
466  array("suggestedsolution", "saveSuggestedSolution", "outSolutionExplorer", "cancel",
467  "addSuggestedSolution","cancelExplorer", "linkChilds", "removeSuggestedSolution"
468  ),
469  $classname,
470  ""
471  );
472  }
473 
474  // Assessment of questions sub menu entry
475  if ($_GET["q_id"])
476  {
477  $ilTabs->addTarget("statistics",
478  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
479  array("assessment"),
480  $classname, "");
481  }
482 
483  if (($_GET["calling_test"] > 0) || ($_GET["test_ref_id"] > 0))
484  {
485  $ref_id = $_GET["calling_test"];
486  if (strlen($ref_id) == 0) $ref_id = $_GET["test_ref_id"];
487 
488  global $___test_express_mode;
489 
490  if (!$_GET['test_express_mode'] && !$___test_express_mode) {
491  $ilTabs->setBackTarget($this->lng->txt("backtocallingtest"), "ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=$ref_id");
492  }
493  else {
495  $ilTabs->setBackTarget($this->lng->txt("backtocallingtest"), $link);
496  }
497  }
498  else
499  {
500  $ilTabs->setBackTarget($this->lng->txt("qpl"), $this->ctrl->getLinkTargetByClass("ilobjquestionpoolgui", "questions"));
501  }
502  }
503 
504  function getSpecificFeedbackOutput($active_id, $pass)
505  {
506  $feedback = '<table><tbody>';
507 
508  $selection = $this->object->getBestSelection(false);
509  $elements = array();
510  foreach(preg_split("/[\n\r]+/", $this->object->errortext) as $line)
511  {
512  $elements = array_merge( $elements, preg_split("/\s+/", $line));
513  }
514 
515  $matchedIndexes = array();
516 
517  $i = 0;
518  foreach ($selection as $index => $answer)
519  {
520  $element = array();
521  foreach($answer as $answerPartIndex)
522  {
523  $element[] = $elements[$answerPartIndex];
524  }
525 
526  $element = implode(' ', $element);
527  $element = str_replace(array('((', '))', '#'), array('', '', ''), $element);
528 
529  $ordinal = $index + 1;
530 
531  $feedback .= '<tr>';
532 
533  $feedback .= '<td>' . $ordinal . '. <i>' . $element . '</i>:</td>';
534 
535  foreach ($this->object->getErrorData() as $idx => $ans)
536  {
537  if( isset($matchedIndexes[$idx]) )
538  {
539  continue;
540  }
541 
542  if ( preg_match('/'.preg_quote($ans->text_wrong, '/').'/', $element) )
543  {
544  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
545  $this->object->getId(), $idx
546  );
547 
548  $feedback .= '<td>'. $fb . '</td>';
549 
550  $matchedIndexes[$idx] = $idx;
551 
552  break;
553  }
554  }
555 
556  $feedback .= '</tr>';
557  }
558 
559  $feedback .= '</tbody></table>';
560 
561  return $this->object->prepareTextareaOutput($feedback, TRUE);
562  }
563 
574  {
575  return array();
576  }
577 
588  {
589  return array();
590  }
591 
600  public function getAggregatedAnswersView($relevant_answers)
601  {
602  $errortext = $this->object->getErrorText();
603 
604  $passdata = array(); // Regroup answers into units of passes.
605  foreach($relevant_answers as $answer_chosen)
606  {
607  $passdata[$answer_chosen['active_fi'].'-'. $answer_chosen['pass']][$answer_chosen['value2']][] = $answer_chosen['value1'];
608  }
609 
610  $html = '';
611  foreach($passdata as $key => $pass)
612  {
613  $passdata[$key] = $this->object->createErrorTextOutput($pass);
614  $html .= $passdata[$key] . '<hr /><br />';
615  }
616 
617  return $html;
618  }
619 }
< a tabindex="-1" style="border-style: none;" href="#" title="Refresh Image" onclick="document.getElementById('siimage').src = './securimage_show.php?sid=' + Math.random(); this.blur(); return false">< img src="./images/refresh.png" alt="Reload Image" height="32" width="32" onclick="this.blur()" align="bottom" border="0"/></a >< br/>< strong > Enter Code *if($_SERVER['REQUEST_METHOD']=='POST' &&@ $_POST['do']=='contact') $_SESSION['ctform']['success']
editQuestion($checkonly=FALSE)
Creates an output of the edit form for the question.
writePostData()
Evaluates a posted edit form and writes the form data in the question object.
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question, working time.
$_POST['username']
Definition: cron.php:12
setValue($a_value)
Set Value.
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
This class represents a property form user interface.
$_GET["client_id"]
static initElementSelection()
init element selection
_getPass($active_id)
Retrieves the actual pass of a given user for a given test.
This class represents a section header in a property form.
populateQuestionSpecificFormPart(ilPropertyFormGUI $form)
$errors
setValue($a_value)
Set Value.
populateAnswerSpecificFormPart(ilPropertyFormGUI $form)
writeQuestionSpecificPostData($always=false)
writePostData($always=false)
Evaluates a posted edit form and writes the form data in the question object.
addItem($a_item)
Add Item (Property, SectionHeader).
getQuestionTemplate()
get question template
__construct($id=-1)
assErrorTextGUI constructor
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
populateTaxonomyFormSection(ilPropertyFormGUI $form)
writeAnswerSpecificPostData($always=false)
allowDecimals($a_value)
Toggle Decimals.
outQuestionForTest( $formaction, $active_id, $pass=NULL, $is_postponed=FALSE, $use_post_solutions=FALSE, $show_feedback=FALSE)
getTestOutput( $active_id, $pass=NULL, $is_postponed=FALSE, $use_post_solutions=FALSE, $show_feedback=FALSE)
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
static getReturnToPageLink($q_id=null)
getILIASPage($html="")
Returns the ILIAS Page around a question.
This class represents a number property in a property form.
getPreview($show_question_only=FALSE)
special template class to simplify handling of ITX/PEAR
Class for error text questions.
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
The assErrorTextGUI class encapsulates the GUI representation for error text questions.
Basic GUI class for assessment questions.
setErrorMessage($errormessage)
_getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
setQuestionTabs()
Sets the ILIAS tabs for this question type.
analyze()
Parse the error text.
$ref_id
Definition: sahs_server.php:39
This class represents a text area property in a property form.
This class represents a key value pair wizard property in a property form.
getSpecificFeedbackOutput($active_id, $pass)
getSolutionOutput( $active_id, $pass=NULL, $graphicalOutput=FALSE, $result_output=FALSE, $show_question_only=TRUE, $show_feedback=FALSE, $show_correct_solution=FALSE, $show_manual_scoring=FALSE, $show_question_text=TRUE)
Get the question solution output.
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.