ILIAS  release_7 Revision v7.30-3-g800a261c036
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 
25 {
34  public function __construct($id = -1)
35  {
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  $this->object->loadFromDb($id);
42  }
43  }
44 
48  protected function writePostData($always = false)
49  {
50  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
51  if (!$hasErrors) {
52  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
56  $this->saveTaxonomyAssignments();
57  return 0;
58  }
59  return 1;
60  }
61 
63  {
64  if (is_array($_POST['errordata']['key'])) {
65  $this->object->flushErrorData();
66  foreach ($_POST['errordata']['key'] as $idx => $val) {
67  $this->object->addErrorData(
68  $val,
69  $_POST['errordata']['value'][$idx],
70  $_POST['errordata']['points'][$idx]
71  );
72  }
73  }
74  }
75 
77  {
78  $questiontext = $_POST["question"];
79  $this->object->setQuestion($questiontext);
80  $this->object->setErrorText($_POST["errortext"]);
81  $points_wrong = str_replace(",", ".", $_POST["points_wrong"]);
82  if (strlen($points_wrong) == 0) {
83  $points_wrong = -1.0;
84  }
85  $this->object->setPointsWrong($points_wrong);
86 
87  if (!$this->object->getSelfAssessmentEditingMode()) {
88  $this->object->setTextSize($_POST["textsize"]);
89  }
90  }
91 
99  public function editQuestion($checkonly = false)
100  {
101  global $DIC;
102  $tabs = $DIC['ilTabs'];
103  $tabs->setTabActive('edit_question');
104  $save = $this->isSaveCommand();
105  $this->getQuestionTemplate();
106 
107  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
108  $form = new ilPropertyFormGUI();
109  $this->editForm = $form;
110 
111  $form->setFormAction($this->ctrl->getFormAction($this));
112  $form->setTitle($this->outQuestionType());
113  $form->setMultipart(false);
114  $form->setTableWidth("100%");
115  $form->setId("orderinghorizontal");
116 
117  $this->addBasicQuestionFormProperties($form);
118 
119  $this->populateQuestionSpecificFormPart($form);
120 
121  if (count($this->object->getErrorData()) || $checkonly) {
122  $this->populateAnswerSpecificFormPart($form);
123  }
124 
125  $this->populateTaxonomyFormSection($form);
126 
127  $form->addCommandButton("analyze", $this->lng->txt('analyze_errortext'));
128  $this->addQuestionFormCommandButtons($form);
129 
130  $errors = false;
131 
132  if ($save) {
133  $form->setValuesByPost();
134  $errors = !$form->checkInput();
135  $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
136  if ($errors) {
137  $checkonly = false;
138  }
139  }
140 
141  if (!$checkonly) {
142  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
143  }
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->setMaxValue(0);
168  $points_wrong->setMaxvalueShouldBeLess(true);
169  $points_wrong->setValue($this->object->getPointsWrong());
170  $points_wrong->setInfo($this->lng->txt("points_wrong_info"));
171  $points_wrong->setSize(6);
172  $points_wrong->setRequired(true);
173  $form->addItem($points_wrong);
174  return $form;
175  }
176 
182  {
183  // errortext
184  $errortext = new ilTextAreaInputGUI($this->lng->txt("errortext"), "errortext");
185  $errortext->setValue($this->object->getErrorText());
186  $errortext->setRequired(true);
187  $errortext->setInfo($this->lng->txt("errortext_info"));
188  $errortext->setRows(10);
189  $errortext->setCols(80);
190  $form->addItem($errortext);
191 
192  if (!$this->object->getSelfAssessmentEditingMode()) {
193  // textsize
194  $textsize = new ilNumberInputGUI($this->lng->txt("textsize"), "textsize");
195  $textsize->setValue(strlen($this->object->getTextSize()) ? $this->object->getTextSize() : 100.0);
196  $textsize->setInfo($this->lng->txt("textsize_errortext_info"));
197  $textsize->setSize(6);
198  $textsize->setSuffix("%");
199  $textsize->setMinValue(10);
200  $textsize->setRequired(true);
201  $form->addItem($textsize);
202  }
203  }
204 
208  public function analyze()
209  {
210  $this->writePostData(true);
211  $this->object->setErrorData($this->object->getErrorsFromText($_POST['errortext']));
212  $this->editQuestion();
213  }
214 
221  {
222  return true;
223  }
224 
243  public function getSolutionOutput(
244  $active_id,
245  $pass = null,
246  $graphicalOutput = false,
247  $result_output = false,
248  $show_question_only = true,
249  $show_feedback = false,
250  $show_correct_solution = false,
251  $show_manual_scoring = false,
252  $show_question_text = true
253  ) {
254  // get the solution of the user for the active pass or from the last pass if allowed
255  $template = new ilTemplate("tpl.il_as_qpl_errortext_output_solution.html", true, true, "Modules/TestQuestionPool");
256 
257  $selections = array();
258  if (($active_id > 0) && (!$show_correct_solution)) {
259 
260  /* Retrieve tst_solutions entries. */
261  $reached_points = $this->object->getReachedPoints($active_id, $pass);
262  $solutions = $this->object->getSolutionValues($active_id, $pass, !$this->getUseIntermediateSolution());
263  if (is_array($solutions)) {
264  foreach ($solutions as $solution) {
265  array_push($selections, (int) $solution['value1']);
266  }
267  $errortext_value = join(",", $selections);
268  }
269  } else {
270  $selections = $this->object->getBestSelection();
271  $reached_points = $this->object->getPoints();
272  }
273 
274  if ($result_output) {
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 
279  if ($this->object->getTextSize() >= 10) {
280  $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
281  }
282 
283  if ($show_question_text == true) {
284  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
285  }
286 
287  $errortext = $this->object->createErrorTextOutput($selections, $graphicalOutput, $show_correct_solution, false);
288 
289  $template->setVariable("ERRORTEXT", $errortext);
290  $questionoutput = $template->get();
291 
292  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
293 
294  $feedback = '';
295  if ($show_feedback) {
296  if (!$this->isTestPresentationContext()) {
297  $fb = $this->getGenericFeedbackOutput($active_id, $pass);
298  $feedback .= strlen($fb) ? $fb : '';
299  }
300 
301  $fb = $this->getSpecificFeedbackOutput(array());
302  $feedback .= strlen($fb) ? $fb : '';
303  }
304  if (strlen($feedback)) {
305  $cssClass = (
306  $this->hasCorrectSolution($active_id, $pass) ?
308  );
309 
310  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
311  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
312  }
313 
314  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
315 
316  $solutionoutput = $solutiontemplate->get();
317  if (!$show_question_only) {
318  // get page object output
319  $solutionoutput = $this->getILIASPage($solutionoutput);
320  }
321  return $solutionoutput;
322  }
323 
324  public function getPreview($show_question_only = false, $showInlineFeedback = false)
325  {
326  $selections = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : array();
327 
328  $template = new ilTemplate("tpl.il_as_qpl_errortext_output.html", true, true, "Modules/TestQuestionPool");
329  if ($this->object->getTextSize() >= 10) {
330  $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
331  }
332  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
333  $errortext = $this->object->createErrorTextOutput($selections);
334  $template->setVariable("ERRORTEXT", $errortext);
335  $template->setVariable("ERRORTEXT_ID", "qst_" . $this->object->getId());
336  $questionoutput = $template->get();
337  if (!$show_question_only) {
338  // get page object output
339  $questionoutput = $this->getILIASPage($questionoutput);
340  }
341  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/errortext.js");
342  return $questionoutput;
343  }
344 
345  public function getTestOutput(
346  $active_id,
347  // hey: prevPassSolutions - will be always available from now on
348  $pass,
349  // hey.
350  $is_postponed = false,
351  $use_post_solutions = false,
352  $show_feedback = false
353  ) {
354  // generate the question output
355  $template = new ilTemplate("tpl.il_as_qpl_errortext_output.html", true, true, "Modules/TestQuestionPool");
356  if ($active_id) {
357  // hey: prevPassSolutions - obsolete due to central check
358  #$solutions = NULL;
359  #include_once "./Modules/Test/classes/class.ilObjTest.php";
360  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
361  #{
362  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
363  #}
364  $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
365  // hey.
366  }
367  $errortext_value = "";
368  $selections = array();
369  if (is_array($solutions)) {
370  foreach ($solutions as $solution) {
371  array_push($selections, $solution['value1']);
372  }
373  $errortext_value = join(",", $selections);
374  }
375  if ($this->object->getTextSize() >= 10) {
376  $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
377  }
378  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
379  $errortext = $this->object->createErrorTextOutput($selections);
380  $this->ctrl->setParameterByClass($this->getTargetGuiClass(), 'errorvalue', '');
381  $template->setVariable("ERRORTEXT", $errortext);
382  $template->setVariable("ERRORTEXT_ID", "qst_" . $this->object->getId());
383  $template->setVariable("ERRORTEXT_VALUE", $errortext_value);
384 
385  $questionoutput = $template->get();
386  if (!$show_question_only) {
387  // get page object output
388  $questionoutput = $this->getILIASPage($questionoutput);
389  }
390  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/errortext.js");
391  $questionoutput = $template->get();
392  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
393  return $pageoutput;
394  }
395 
396  public function getSpecificFeedbackOutput($userSolution)
397  {
398  $selection = $this->object->getBestSelection(false);
399 
400  if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
401  return '';
402  }
403 
404  $feedback = '<table class="test_specific_feedback"><tbody>';
405 
406  $elements = array();
407  foreach (preg_split("/[\n\r]+/", $this->object->errortext) as $line) {
408  $elements = array_merge($elements, preg_split("/\s+/", $line));
409  }
410 
411  $matchedIndexes = array();
412 
413  $i = 0;
414  foreach ($selection as $index => $answer) {
415  $element = array();
416  foreach ($answer as $answerPartIndex) {
417  $element[] = $elements[$answerPartIndex];
418  }
419 
420  $element = implode(' ', $element);
421  $element = str_replace(array('((', '))', '#'), array('', '', ''), $element);
422 
423  $ordinal = $index + 1;
424 
425  $feedback .= '<tr>';
426 
427  $feedback .= '<td class="text-nowrap">' . $ordinal . '. ' . $element . ':</td>';
428 
429  foreach ($this->object->getErrorData() as $idx => $ans) {
430  if (isset($matchedIndexes[$idx])) {
431  continue;
432  }
433 
434  if (preg_match('/' . preg_quote($ans->text_wrong, '/') . '/', $element)) {
435  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
436  $this->object->getId(),
437  0,
438  $idx
439  );
440 
441  $feedback .= '<td>' . $fb . '</td>';
442 
443  $matchedIndexes[$idx] = $idx;
444 
445  break;
446  }
447  }
448 
449  $feedback .= '</tr>';
450  }
451 
452  $feedback .= '</tbody></table>';
453 
454  return $this->object->prepareTextareaOutput($feedback, true);
455  }
456 
467  {
468  return array();
469  }
470 
481  {
482  return array();
483  }
484 
493  public function getAggregatedAnswersView($relevant_answers)
494  {
495  $errortext = $this->object->getErrorText();
496 
497  $passdata = array(); // Regroup answers into units of passes.
498  foreach ($relevant_answers as $answer_chosen) {
499  $passdata[$answer_chosen['active_fi'] . '-' . $answer_chosen['pass']][$answer_chosen['value2']][] = $answer_chosen['value1'];
500  }
501 
502  $html = '';
503  foreach ($passdata as $key => $pass) {
504  $passdata[$key] = $this->object->createErrorTextOutput($pass);
505  $html .= $passdata[$key] . '<hr /><br />';
506  }
507 
508  return $html;
509  }
510 
511  public function getAnswersFrequency($relevantAnswers, $questionIndex)
512  {
513  $answersByActiveAndPass = array();
514 
515  foreach ($relevantAnswers as $row) {
516  $key = $row['active_fi'] . ':' . $row['pass'];
517 
518  if (!isset($answersByActiveAndPass[$key])) {
519  $answersByActiveAndPass[$key] = array();
520  }
521 
522  if (!isset($answersByActiveAndPass[$key][$row['value2']])) {
523  $answersByActiveAndPass[$key][$row['value2']] = array();
524  }
525 
526  $answersByActiveAndPass[$key][$row['value2']][] = $row['value1'];
527  }
528 
529  $answers = array();
530 
531  foreach ($answersByActiveAndPass as $ans) {
532  $errorText = $this->object->createErrorTextOutput($ans);
533  $errorMd5 = md5($errorText);
534 
535  if (!isset($answers[$errorMd5])) {
536  $answers[$errorMd5] = array(
537  'answer' => $errorText, 'frequency' => 0
538  );
539  }
540 
541  $answers[$errorMd5]['frequency']++;
542  }
543 
544  return array_values($answers);
545  }
546 
548  {
549  // error terms
550  include_once "./Modules/TestQuestionPool/classes/forms/class.ilAssErrorTextCorrectionsInputGUI.php";
551  $errordata = new ilAssErrorTextCorrectionsInputGUI($this->lng->txt("errors"), "errordata");
552  $errordata->setKeyName($this->lng->txt('text_wrong'));
553  $errordata->setValueName($this->lng->txt('text_correct'));
554  $errordata->setValues($this->object->getErrorData());
555  $form->addItem($errordata);
556 
557  // points for wrong selection
558  $points_wrong = new ilNumberInputGUI($this->lng->txt("points_wrong"), "points_wrong");
559  $points_wrong->allowDecimals(true);
560  $points_wrong->setMaxValue(0);
561  $points_wrong->setMaxvalueShouldBeLess(true);
562  $points_wrong->setValue($this->object->getPointsWrong());
563  $points_wrong->setInfo($this->lng->txt("points_wrong_info"));
564  $points_wrong->setSize(6);
565  $points_wrong->setRequired(true);
566  $form->addItem($points_wrong);
567 
568  return $form;
569  }
570 
575  {
576  $this->object->flushErrorData();
577  foreach ($form->getItemByPostVar('errordata')->getValues() as $idx => $errAnswer) {
578  $this->object->addErrorData(
579  $errAnswer->text_wrong,
580  $errAnswer->text_correct,
581  $errAnswer->points
582  );
583  }
584 
585  $this->object->setPointsWrong((float) $form->getInput('points_wrong'));
586  }
587 }
hasCorrectSolution($activeId, $passIndex)
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question, working time.
getItemByPostVar($a_post_var)
Get Item by POST variable.
setValue($a_value)
Set Value.
$errors
Definition: imgupload.php:49
This class represents a property form user interface.
getAnswersFrequency($relevantAnswers, $questionIndex)
This class represents a section header in a property form.
populateQuestionSpecificFormPart(ilPropertyFormGUI $form)
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
setValue($a_value)
Set Value.
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
populateAnswerSpecificFormPart(ilPropertyFormGUI $form)
writePostData($always=false)
{}
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)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
getSpecificFeedbackOutput($userSolution)
getUseIntermediateSolution()
Get if intermediate solution should be used for solution output.
getTestOutput( $active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
$index
Definition: metadata.php:128
allowDecimals($a_value)
Toggle Decimals.
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getILIASPage($html="")
Returns the ILIAS Page around a question.
This class represents a number property in a property form.
Class for error text questions.
global $DIC
Definition: goto.php:24
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
getPreview($show_question_only=false, $showInlineFeedback=false)
getInput($a_post_var, $ensureValidation=true)
Returns the value of a HTTP-POST variable, identified by the passed id.
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
The assErrorTextGUI class encapsulates the GUI representation for error text questions.
Basic GUI class for assessment questions.
setErrorMessage($errormessage)
analyze()
Parse the error text.
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.
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
output question page
__construct(Container $dic, ilPlugin $plugin)
This class represents a text area property in a property form.
This class represents a key value pair wizard property in a property form.
Interface ilGuiAnswerScoringAdjustable.
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
Interface ilGuiQuestionScoringAdjustable.
$_POST["username"]
$i
Definition: metadata.php:24
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.