ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
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
4require_once './Modules/TestQuestionPool/classes/class.assQuestionGUI.php';
5require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiQuestionScoringAdjustable.php';
6require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiAnswerScoringAdjustable.php';
7
8require_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';
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 $save = $this->isSaveCommand();
102 $this->getQuestionTemplate();
103
104 include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
105 $form = new ilPropertyFormGUI();
106 $this->editForm = $form;
107
108 $form->setFormAction($this->ctrl->getFormAction($this));
109 $form->setTitle($this->outQuestionType());
110 $form->setMultipart(false);
111 $form->setTableWidth("100%");
112 $form->setId("orderinghorizontal");
113
114 $this->addBasicQuestionFormProperties($form);
115
117
118 if (count($this->object->getErrorData()) || $checkonly) {
119 $this->populateAnswerSpecificFormPart($form);
120 }
121
122 $this->populateTaxonomyFormSection($form);
123
124 $form->addCommandButton("analyze", $this->lng->txt('analyze_errortext'));
125 $this->addQuestionFormCommandButtons($form);
126
127 $errors = false;
128
129 if ($save) {
130 $form->setValuesByPost();
131 $errors = !$form->checkInput();
132 $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
133 if ($errors) {
134 $checkonly = false;
135 }
136 }
137
138 if (!$checkonly) {
139 $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
140 }
141 return $errors;
142 }
143
149 {
150 $header = new ilFormSectionHeaderGUI();
151 $header->setTitle($this->lng->txt("errors_section"));
152 $form->addItem($header);
153
154 include_once "./Modules/TestQuestionPool/classes/class.ilErrorTextWizardInputGUI.php";
155 $errordata = new ilErrorTextWizardInputGUI($this->lng->txt("errors"), "errordata");
156 $errordata->setKeyName($this->lng->txt('text_wrong'));
157 $errordata->setValueName($this->lng->txt('text_correct'));
158 $errordata->setValues($this->object->getErrorData());
159 $form->addItem($errordata);
160
161 // points for wrong selection
162 $points_wrong = new ilNumberInputGUI($this->lng->txt("points_wrong"), "points_wrong");
163 $points_wrong->allowDecimals(true);
164 $points_wrong->setMaxValue(0);
165 $points_wrong->setMaxvalueShouldBeLess(true);
166 $points_wrong->setValue($this->object->getPointsWrong());
167 $points_wrong->setInfo($this->lng->txt("points_wrong_info"));
168 $points_wrong->setSize(6);
169 $points_wrong->setRequired(true);
170 $form->addItem($points_wrong);
171 return $form;
172 }
173
179 {
180 // errortext
181 $errortext = new ilTextAreaInputGUI($this->lng->txt("errortext"), "errortext");
182 $errortext->setValue($this->object->getErrorText());
183 $errortext->setRequired(true);
184 $errortext->setInfo($this->lng->txt("errortext_info"));
185 $errortext->setRows(10);
186 $errortext->setCols(80);
187 $form->addItem($errortext);
188
189 if (!$this->object->getSelfAssessmentEditingMode()) {
190 // textsize
191 $textsize = new ilNumberInputGUI($this->lng->txt("textsize"), "textsize");
192 $textsize->setValue(strlen($this->object->getTextSize()) ? $this->object->getTextSize() : 100.0);
193 $textsize->setInfo($this->lng->txt("textsize_errortext_info"));
194 $textsize->setSize(6);
195 $textsize->setSuffix("%");
196 $textsize->setMinValue(10);
197 $textsize->setRequired(true);
198 $form->addItem($textsize);
199 }
200 }
201
205 public function analyze()
206 {
207 $this->writePostData(true);
208 $this->object->setErrorData($this->object->getErrorsFromText($_POST['errortext']));
209 $this->editQuestion();
210 }
211
218 {
219 return true;
220 }
221
240 public function getSolutionOutput(
241 $active_id,
242 $pass = null,
243 $graphicalOutput = false,
244 $result_output = false,
245 $show_question_only = true,
246 $show_feedback = false,
247 $show_correct_solution = false,
248 $show_manual_scoring = false,
249 $show_question_text = true
250 ) {
251 // get the solution of the user for the active pass or from the last pass if allowed
252 $template = new ilTemplate("tpl.il_as_qpl_errortext_output_solution.html", true, true, "Modules/TestQuestionPool");
253
254 $selections = array();
255 if (($active_id > 0) && (!$show_correct_solution)) {
256
257 /* Retrieve tst_solutions entries. */
258 $reached_points = $this->object->getReachedPoints($active_id, $pass);
259 $solutions = $this->object->getSolutionValues($active_id, $pass, !$this->getUseIntermediateSolution());
260 if (is_array($solutions)) {
261 foreach ($solutions as $solution) {
262 array_push($selections, (int) $solution['value1']);
263 }
264 $errortext_value = join(",", $selections);
265 }
266 } else {
267 $selections = $this->object->getBestSelection();
268 $reached_points = $this->object->getPoints();
269 }
270
271 if ($result_output) {
272 $resulttext = ($reached_points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
273 $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $reached_points));
274 }
275
276 if ($this->object->getTextSize() >= 10) {
277 $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
278 }
279
280 if ($show_question_text == true) {
281 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
282 }
283
284 $errortext = $this->object->createErrorTextOutput($selections, $graphicalOutput, $show_correct_solution, false);
285
286 $template->setVariable("ERRORTEXT", $errortext);
287 $questionoutput = $template->get();
288
289 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
290
291 $feedback = '';
292 if ($show_feedback) {
293 if (!$this->isTestPresentationContext()) {
294 $fb = $this->getGenericFeedbackOutput($active_id, $pass);
295 $feedback .= strlen($fb) ? $fb : '';
296 }
297
298 $fb = $this->getSpecificFeedbackOutput(array());
299 $feedback .= strlen($fb) ? $fb : '';
300 }
301 if (strlen($feedback)) {
302 $cssClass = (
303 $this->hasCorrectSolution($active_id, $pass) ?
305 );
306
307 $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
308 $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
309 }
310
311 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
312
313 $solutionoutput = $solutiontemplate->get();
314 if (!$show_question_only) {
315 // get page object output
316 $solutionoutput = $this->getILIASPage($solutionoutput);
317 }
318 return $solutionoutput;
319 }
320
321 public function getPreview($show_question_only = false, $showInlineFeedback = false)
322 {
323 $selections = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : array();
324
325 $template = new ilTemplate("tpl.il_as_qpl_errortext_output.html", true, true, "Modules/TestQuestionPool");
326 if ($this->object->getTextSize() >= 10) {
327 $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
328 }
329 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
330 $errortext = $this->object->createErrorTextOutput($selections);
331 $template->setVariable("ERRORTEXT", $errortext);
332 $template->setVariable("ERRORTEXT_ID", "qst_" . $this->object->getId());
333 $questionoutput = $template->get();
334 if (!$show_question_only) {
335 // get page object output
336 $questionoutput = $this->getILIASPage($questionoutput);
337 }
338 $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/errortext.js");
339 return $questionoutput;
340 }
341
342 public function getTestOutput(
343 $active_id,
344 // hey: prevPassSolutions - will be always available from now on
345 $pass,
346 // hey.
347 $is_postponed = false,
348 $use_post_solutions = false,
349 $show_feedback = false
350 ) {
351 // generate the question output
352 $template = new ilTemplate("tpl.il_as_qpl_errortext_output.html", true, true, "Modules/TestQuestionPool");
353 if ($active_id) {
354 // hey: prevPassSolutions - obsolete due to central check
355 #$solutions = NULL;
356 #include_once "./Modules/Test/classes/class.ilObjTest.php";
357 #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
358 #{
359 # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
360 #}
361 $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
362 // hey.
363 }
364 $errortext_value = "";
365 $selections = array();
366 if (is_array($solutions)) {
367 foreach ($solutions as $solution) {
368 array_push($selections, $solution['value1']);
369 }
370 $errortext_value = join(",", $selections);
371 }
372 if ($this->object->getTextSize() >= 10) {
373 $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
374 }
375 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
376 $errortext = $this->object->createErrorTextOutput($selections);
377 $this->ctrl->setParameterByClass($this->getTargetGuiClass(), 'errorvalue', '');
378 $template->setVariable("ERRORTEXT", $errortext);
379 $template->setVariable("ERRORTEXT_ID", "qst_" . $this->object->getId());
380 $template->setVariable("ERRORTEXT_VALUE", $errortext_value);
381
382 $questionoutput = $template->get();
383 if (!$show_question_only) {
384 // get page object output
385 $questionoutput = $this->getILIASPage($questionoutput);
386 }
387 $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/errortext.js");
388 $questionoutput = $template->get();
389 $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
390 return $pageoutput;
391 }
392
400 public function setQuestionTabs()
401 {
402 global $DIC;
403 $rbacsystem = $DIC['rbacsystem'];
404 $ilTabs = $DIC['ilTabs'];
405
406 $ilTabs->clearTargets();
407
408 $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
409 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
410 $q_type = $this->object->getQuestionType();
411
412 if (strlen($q_type)) {
413 $classname = $q_type . "GUI";
414 $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
415 $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
416 }
417
418 if ($_GET["q_id"]) {
419 if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
420 // edit page
421 $ilTabs->addTarget(
422 "edit_page",
423 $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
424 array("edit", "insert", "exec_pg"),
425 "",
426 "",
427 $force_active
428 );
429 }
430
431 $this->addTab_QuestionPreview($ilTabs);
432 }
433
434 $force_active = false;
435 if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
436 $url = "";
437 if ($classname) {
438 $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
439 }
440 // edit question properties
441 $ilTabs->addTarget(
442 "edit_question",
443 $url,
444 array("editQuestion", "save", "saveEdit", "analyze", "originalSyncForm"),
445 $classname,
446 "",
447 $force_active
448 );
449 }
450
451 // add tab for question feedback within common class assQuestionGUI
452 $this->addTab_QuestionFeedback($ilTabs);
453
454 // add tab for question hint within common class assQuestionGUI
455 $this->addTab_QuestionHints($ilTabs);
456
457 // add tab for question's suggested solution within common class assQuestionGUI
458 $this->addTab_SuggestedSolution($ilTabs, $classname);
459
460 // Assessment of questions sub menu entry
461 if ($_GET["q_id"]) {
462 $ilTabs->addTarget(
463 "statistics",
464 $this->ctrl->getLinkTargetByClass($classname, "assessment"),
465 array("assessment"),
466 $classname,
467 ""
468 );
469 }
470
471 $this->addBackTab($ilTabs);
472 }
473
474 public function getSpecificFeedbackOutput($userSolution)
475 {
476 $selection = $this->object->getBestSelection(false);
477
478 if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
479 return '';
480 }
481
482 $feedback = '<table class="test_specific_feedback"><tbody>';
483
484 $elements = array();
485 foreach (preg_split("/[\n\r]+/", $this->object->errortext) as $line) {
486 $elements = array_merge($elements, preg_split("/\s+/", $line));
487 }
488
489 $matchedIndexes = array();
490
491 $i = 0;
492 foreach ($selection as $index => $answer) {
493 $element = array();
494 foreach ($answer as $answerPartIndex) {
495 $element[] = $elements[$answerPartIndex];
496 }
497
498 $element = implode(' ', $element);
499 $element = str_replace(array('((', '))', '#'), array('', '', ''), $element);
500
501 $ordinal = $index + 1;
502
503 $feedback .= '<tr>';
504
505 $feedback .= '<td class="text-nowrap">' . $ordinal . '. ' . $element . ':</td>';
506
507 foreach ($this->object->getErrorData() as $idx => $ans) {
508 if (isset($matchedIndexes[$idx])) {
509 continue;
510 }
511
512 if (preg_match('/' . preg_quote($ans->text_wrong, '/') . '/', $element)) {
513 $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
514 $this->object->getId(),
515 0,
516 $idx
517 );
518
519 $feedback .= '<td>' . $fb . '</td>';
520
521 $matchedIndexes[$idx] = $idx;
522
523 break;
524 }
525 }
526
527 $feedback .= '</tr>';
528 }
529
530 $feedback .= '</tbody></table>';
531
532 return $this->object->prepareTextareaOutput($feedback, true);
533 }
534
545 {
546 return array();
547 }
548
559 {
560 return array();
561 }
562
571 public function getAggregatedAnswersView($relevant_answers)
572 {
573 $errortext = $this->object->getErrorText();
574
575 $passdata = array(); // Regroup answers into units of passes.
576 foreach ($relevant_answers as $answer_chosen) {
577 $passdata[$answer_chosen['active_fi'] . '-' . $answer_chosen['pass']][$answer_chosen['value2']][] = $answer_chosen['value1'];
578 }
579
580 $html = '';
581 foreach ($passdata as $key => $pass) {
582 $passdata[$key] = $this->object->createErrorTextOutput($pass);
583 $html .= $passdata[$key] . '<hr /><br />';
584 }
585
586 return $html;
587 }
588
589 public function getAnswersFrequency($relevantAnswers, $questionIndex)
590 {
591 $answersByActiveAndPass = array();
592
593 foreach ($relevantAnswers as $row) {
594 $key = $row['active_fi'] . ':' . $row['pass'];
595
596 if (!isset($answersByActiveAndPass[$key])) {
597 $answersByActiveAndPass[$key] = array();
598 }
599
600 if (!isset($answersByActiveAndPass[$key][$row['value2']])) {
601 $answersByActiveAndPass[$key][$row['value2']] = array();
602 }
603
604 $answersByActiveAndPass[$key][$row['value2']][] = $row['value1'];
605 }
606
607 $answers = array();
608
609 foreach ($answersByActiveAndPass as $ans) {
610 $errorText = $this->object->createErrorTextOutput($ans);
611 $errorMd5 = md5($errorText);
612
613 if (!isset($answers[$errorMd5])) {
614 $answers[$errorMd5] = array(
615 'answer' => $errorText, 'frequency' => 0
616 );
617 }
618
619 $answers[$errorMd5]['frequency']++;
620 }
621
622 return array_values($answers);
623 }
624
626 {
627 // error terms
628 include_once "./Modules/TestQuestionPool/classes/forms/class.ilAssErrorTextCorrectionsInputGUI.php";
629 $errordata = new ilAssErrorTextCorrectionsInputGUI($this->lng->txt("errors"), "errordata");
630 $errordata->setKeyName($this->lng->txt('text_wrong'));
631 $errordata->setValueName($this->lng->txt('text_correct'));
632 $errordata->setValues($this->object->getErrorData());
633 $form->addItem($errordata);
634
635 // points for wrong selection
636 $points_wrong = new ilNumberInputGUI($this->lng->txt("points_wrong"), "points_wrong");
637 $points_wrong->allowDecimals(true);
638 $points_wrong->setMaxValue(0);
639 $points_wrong->setMaxvalueShouldBeLess(true);
640 $points_wrong->setValue($this->object->getPointsWrong());
641 $points_wrong->setInfo($this->lng->txt("points_wrong_info"));
642 $points_wrong->setSize(6);
643 $points_wrong->setRequired(true);
644 $form->addItem($points_wrong);
645
646 return $form;
647 }
648
653 {
654 $this->object->flushErrorData();
655 foreach ($form->getItemByPostVar('errordata')->getValues() as $idx => $errAnswer) {
656 $this->object->addErrorData(
657 $errAnswer->text_wrong,
658 $errAnswer->text_correct,
659 $errAnswer->points
660 );
661 }
662
663 $this->object->setPointsWrong((float) $form->getInput('points_wrong'));
664 }
665}
$_GET["client_id"]
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
The assErrorTextGUI class encapsulates the GUI representation for error text questions.
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
setQuestionTabs()
Sets the ILIAS tabs for this question type.
getAnswersFrequency($relevantAnswers, $questionIndex)
getPreview($show_question_only=false, $showInlineFeedback=false)
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.
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
populateQuestionSpecificFormPart(ilPropertyFormGUI $form)
getSpecificFeedbackOutput($userSolution)
Returns the answer specific feedback for the question.
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
populateAnswerSpecificFormPart(ilPropertyFormGUI $form)
writePostData($always=false)
{Evaluates a posted edit form and writes the form data in the question object.integer A positive valu...
__construct($id=-1)
assErrorTextGUI constructor
getTestOutput( $active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
analyze()
Parse the error text.
Class for error text questions.
Basic GUI class for assessment questions.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
setErrorMessage($errormessage)
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.
getILIASPage($html="")
Returns the ILIAS Page around a question.
getQuestionTemplate()
get question template
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
output question page
getUseIntermediateSolution()
Get if intermediate solution should be used for solution output.
addBackTab(ilTabsGUI $ilTabs)
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question,...
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
This class represents a key value pair wizard property in a property form.
This class represents a section header in a property form.
This class represents a number property in a property form.
This class represents a property form user interface.
addItem($a_item)
Add Item (Property, SectionHeader).
getInput($a_post_var, $ensureValidation=true)
Returns the value of a HTTP-POST variable, identified by the passed id.
getItemByPostVar($a_post_var)
Get Item by POST variable.
special template class to simplify handling of ITX/PEAR
This class represents a text area property in a property form.
Interface ilGuiAnswerScoringAdjustable.
Interface ilGuiQuestionScoringAdjustable.
$index
Definition: metadata.php:128
$i
Definition: metadata.php:24
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
$url
$errors
$DIC
Definition: xapitoken.php:46