ILIAS  release_8 Revision v8.24
class.assErrorTextGUI.php
Go to the documentation of this file.
1<?php
2
19require_once './Modules/Test/classes/inc.AssessmentConstants.php';
20
36{
37 private const DEFAULT_POINTS_WRONG = -1;
38
40
41 public function __construct($id = -1)
42 {
43 global $DIC;
44 $this->tabs = $DIC->tabs();
45
47 include_once "./Modules/TestQuestionPool/classes/class.assErrorText.php";
48 $this->object = new assErrorText();
49 $this->setErrorMessage($this->lng->txt("msg_form_save_error"));
50 if ($id >= 0) {
51 $this->object->loadFromDb($id);
52 }
53 }
54
58 protected function writePostData(bool $always = false): int
59 {
60 $hasErrors = (!$always) ? $this->editQuestion(true) : false;
61 if (!$hasErrors) {
62 require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
67 return 0;
68 }
69 return 1;
70 }
71
73 {
74 $errordata = $this->restructurePostDataForSaving($this->request->raw('errordata') ?? []);
75 $this->object->setErrorData($errordata);
76 $this->object->removeErrorDataWithoutPosition();
77 }
78
79 private function restructurePostDataForSaving(array $post): array
80 {
81 $keys = $post['key'] ?? [];
82 $restructured_array = [];
83 foreach ($keys as $key => $text_wrong) {
84 $restructured_array[] = new assAnswerErrorText(
85 $text_wrong,
86 $post['value'][$key],
87 (float) str_replace(',', '.', $post['points'][$key])
88 );
89 }
90 return $restructured_array;
91 }
92
94 {
95 $this->object->setQuestion(
96 $this->request->raw('question')
97 );
98
99 $this->object->setErrorText(
100 $this->request->raw('errortext')
101 );
102
103 $this->object->parseErrorText();
104
105 $points_wrong = str_replace(",", ".", $this->request->raw('points_wrong') ?? '');
106 if (mb_strlen($points_wrong) == 0) {
107 $points_wrong = self::DEFAULT_POINTS_WRONG;
108 }
109 $this->object->setPointsWrong((float) $points_wrong);
110
111 if (!$this->object->getSelfAssessmentEditingMode()) {
112 $this->object->setTextSize($this->request->int('textsize'));
113 }
114 }
115
123 public function editQuestion($checkonly = false): bool
124 {
125 $this->tabs->setTabActive('edit_question');
126 $save = $this->isSaveCommand();
127 $this->getQuestionTemplate();
128
129 include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
130 $form = new ilPropertyFormGUI();
131 $this->editForm = $form;
132
133 $form->setFormAction($this->ctrl->getFormAction($this));
134 $form->setTitle($this->outQuestionType());
135 $form->setMultipart(false);
136 $form->setTableWidth("100%");
137 $form->setId("orderinghorizontal");
138
139 $this->addBasicQuestionFormProperties($form);
140
142
143 if (count($this->object->getErrorData()) || $checkonly) {
144 $this->populateAnswerSpecificFormPart($form);
145 }
146
147 $this->populateTaxonomyFormSection($form);
148
149 $form->addCommandButton("analyze", $this->lng->txt('analyze_errortext'));
150 $this->addQuestionFormCommandButtons($form);
151
152 $errors = false;
153
154 if ($save) {
155 $form->setValuesByPost();
156 $errors = !$form->checkInput();
157 $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
158 if ($errors) {
159 $checkonly = false;
160 }
161 }
162
163 if (!$checkonly) {
164 $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
165 }
166 return $errors;
167 }
168
174 {
175 $header = new ilFormSectionHeaderGUI();
176 $header->setTitle($this->lng->txt("errors_section"));
177 $form->addItem($header);
178
179 include_once "./Modules/TestQuestionPool/classes/class.ilErrorTextWizardInputGUI.php";
180 $errordata = new ilErrorTextWizardInputGUI($this->lng->txt("errors"), "errordata");
181 $errordata->setKeyName($this->lng->txt('text_wrong'));
182 $errordata->setValueName($this->lng->txt('text_correct'));
183 $errordata->setValues($this->object->getErrorData());
184 $form->addItem($errordata);
185
186 // points for wrong selection
187 $points_wrong = new ilNumberInputGUI($this->lng->txt("points_wrong"), "points_wrong");
188 $points_wrong->allowDecimals(true);
189 $points_wrong->setMaxValue(0);
190 $points_wrong->setMaxvalueShouldBeLess(true);
191 $points_wrong->setValue($this->object->getPointsWrong());
192 $points_wrong->setInfo($this->lng->txt("points_wrong_info"));
193 $points_wrong->setSize(6);
194 $points_wrong->setRequired(true);
195 $form->addItem($points_wrong);
196 return $form;
197 }
198
204 {
205 // errortext
206 $errortext = new ilTextAreaInputGUI($this->lng->txt("errortext"), "errortext");
207 $errortext->setValue($this->object->getErrorText());
208 $errortext->setRequired(true);
209 $errortext->setInfo($this->lng->txt("errortext_info"));
210 $errortext->setRows(10);
211 $errortext->setCols(80);
212 $form->addItem($errortext);
213
214 if (!$this->object->getSelfAssessmentEditingMode()) {
215 // textsize
216 $textsize = new ilNumberInputGUI($this->lng->txt("textsize"), "textsize");
217 $textsize->setValue(mb_strlen($this->object->getTextSize()) ? $this->object->getTextSize() : 100.0);
218 $textsize->setInfo($this->lng->txt("textsize_errortext_info"));
219 $textsize->setSize(6);
220 $textsize->setSuffix("%");
221 $textsize->setMinValue(10);
222 $textsize->setRequired(true);
223 $form->addItem($textsize);
224 }
225 return $form;
226 }
227
231 public function analyze(): void
232 {
233 $this->writePostData(true);
235 $this->object->setErrorsFromParsedErrorText();
236 $this->editQuestion();
237 }
238
254 public function getSolutionOutput(
255 $active_id,
256 $pass = null,
257 $graphical_output = false,
258 $result_output = false,
259 $show_question_only = true,
260 $show_feedback = false,
261 $show_correct_solution = false,
262 $show_manual_scoring = false,
263 $show_question_text = true
264 ): string {
265 // get the solution of the user for the active pass or from the last pass if allowed
266 $template = new ilTemplate("tpl.il_as_qpl_errortext_output_solution.html", true, true, "Modules/TestQuestionPool");
267
268
269 $selections = [
270 'user' => $this->getUsersSolutionFromPreviewOrDatabase($active_id, $pass)
271 ];
272 $selections['best'] = $this->object->getBestSelection();
273
274 $reached_points = $this->object->getPoints();
275 if ($active_id > 0 && !$show_correct_solution) {
276 $reached_points = $this->object->getReachedPoints($active_id, $pass);
277 }
278
279 if ($result_output === true) {
280 $resulttext = ($reached_points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
281 $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $reached_points));
282 }
283
284 if ($this->object->getTextSize() >= 10) {
285 $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
286 }
287
288 if ($show_question_text === true) {
289 $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
290 }
291
292 $correctness_icons = [
293 'correct' => $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK),
294 'not_correct' => $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK)
295 ];
296 $errortext = $this->object->assembleErrorTextOutput($selections, $graphical_output, $show_correct_solution, false, $correctness_icons);
297
298 $template->setVariable("ERRORTEXT", $errortext);
299 $questionoutput = $template->get();
300
301 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
302
303 $feedback = '';
304 if ($show_feedback) {
305 if (!$this->isTestPresentationContext()) {
306 $fb = $this->getGenericFeedbackOutput((int) $active_id, $pass);
307 $feedback .= mb_strlen($fb) ? $fb : '';
308 }
309
310 $fb = $this->getSpecificFeedbackOutput(array());
311 $feedback .= mb_strlen($fb) ? $fb : '';
312 }
313 if (mb_strlen($feedback)) {
314 $cssClass = (
315 $this->hasCorrectSolution($active_id, $pass) ?
317 );
318
319 $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
320 $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
321 }
322
323 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
324
325 $solutionoutput = $solutiontemplate->get();
326 if (!$show_question_only) {
327 // get page object output
328 $solutionoutput = $this->getILIASPage($solutionoutput);
329 }
330 return $solutionoutput;
331 }
332
333 public function getPreview($show_question_only = false, $showInlineFeedback = false): string
334 {
335 $selections = [
336 'user' => $this->getUsersSolutionFromPreviewOrDatabase()
337 ];
338
339 return $this->generateQuestionOutput($selections, $show_question_only);
340 }
341
342 public function getTestOutput(
343 $active_id,
344 $pass,
345 $is_postponed = false,
346 $use_post_solutions = false,
347 $show_feedback = false
348 ): string {
349 $selections = [
350 'user' => $this->getUsersSolutionFromPreviewOrDatabase($active_id, $pass)
351 ];
352
353 return $this->outQuestionPage(
354 '',
355 $is_postponed,
356 $active_id,
357 $this->generateQuestionOutput($selections, false)
358 );
359 }
360
361 private function generateQuestionOutput($selections, $show_question_only): string
362 {
363 $template = new ilTemplate("tpl.il_as_qpl_errortext_output.html", true, true, "Modules/TestQuestionPool");
364
365 if ($this->object->getTextSize() >= 10) {
366 $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
367 }
368 $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
369 $errortext = $this->object->assembleErrorTextOutput($selections);
370 if ($this->getTargetGuiClass() !== null) {
371 $this->ctrl->setParameterByClass($this->getTargetGuiClass(), 'errorvalue', '');
372 }
373 $template->setVariable("ERRORTEXT", $errortext);
374 $template->setVariable("ERRORTEXT_ID", "qst_" . $this->object->getId());
375 $template->setVariable("ERRORTEXT_VALUE", join(',', $selections['user']));
376
377 $this->tpl->addOnLoadCode('il.test.player.errortext.init()');
378 $this->tpl->addJavascript('./Modules/TestQuestionPool/templates/default/errortext.js');
379 $questionoutput = $template->get();
380
381 if ($show_question_only) {
382 return $questionoutput;
383 }
384
385 return $this->getILIASPage($questionoutput);
386 }
387
388 private function getUsersSolutionFromPreviewOrDatabase(int $active_id = 0, ?int $pass = null): array
389 {
390 if (is_object($this->getPreviewSession())) {
391 return (array) $this->getPreviewSession()->getParticipantsSolution();
392 }
393
394 if ($active_id > 0) {
395 $selections = [];
396 $solutions = $this->object->getSolutionValues($active_id, $pass ?? 0, true);
397 foreach ($solutions as $solution) {
398 $selections[] = $solution['value1'];
399 }
400 return $selections;
401 }
402
403 return [];
404 }
405
406 public function getSpecificFeedbackOutput(array $user_solution): string
407 {
408 if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
409 return '';
410 }
411
412 $feedback = '<table class="test_specific_feedback"><tbody>';
413 $elements = $this->object->getErrorData();
414 foreach ($elements as $index => $element) {
415 $feedback .= '<tr>';
416 $feedback .= '<td class="text-nowrap">' . $index . '. ' . $element->getTextWrong() . ':</td>';
417 $feedback .= '<td>' . $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
418 $this->object->getId(),
419 0,
420 $index
421 ) . '</td>';
422
423 $feedback .= '</tr>';
424 }
425 $feedback .= '</tbody></table>';
426
427 return $this->object->prepareTextareaOutput($feedback, true);
428 }
429
440 {
441 return [];
442 }
443
454 {
455 return [];
456 }
457
464 public function getAggregatedAnswersView(array $relevant_answers): string
465 {
466 $errortext = $this->object->getErrorText();
467
468 $passdata = []; // Regroup answers into units of passes.
469 foreach ($relevant_answers as $answer_chosen) {
470 $passdata[$answer_chosen['active_fi'] . '-' . $answer_chosen['pass']][$answer_chosen['value2']][] = $answer_chosen['value1'];
471 }
472
473 $html = '';
474 foreach ($passdata as $key => $pass) {
475 $passdata[$key] = $this->object->createErrorTextOutput($pass);
476 $html .= $passdata[$key] . '<hr /><br />';
477 }
478
479 return $html;
480 }
481
482 public function getAnswersFrequency($relevant_answers, $question_index): array
483 {
484 $answers_by_active_and_pass = [];
485
486 foreach ($relevant_answers as $row) {
487 $key = $row['active_fi'] . ':' . $row['pass'];
488
489 if (!isset($answers_by_active_and_pass[$key])) {
490 $answers_by_active_and_pass[$key] = ['user' => []];
491 }
492
493 $answers_by_active_and_pass[$key]['user'][] = $row['value1'];
494 }
495
496 $answers = [];
497
498 foreach ($answers_by_active_and_pass as $answer) {
499 $error_text = '<div class="errortext">' . $this->object->assembleErrorTextOutput($answer) . '</div>';
500 $error_text_hashed = md5($error_text);
501
502 if (!isset($answers[$error_text_hashed])) {
503 $answers[$error_text_hashed] = [
504 'answer' => $error_text, 'frequency' => 0
505 ];
506 }
507
508 $answers[$error_text_hashed]['frequency']++;
509 }
510
511 return array_values($answers);
512 }
513
515 {
516 // error terms
517 include_once "./Modules/TestQuestionPool/classes/forms/class.ilAssErrorTextCorrectionsInputGUI.php";
518 $errordata = new ilAssErrorTextCorrectionsInputGUI($this->lng->txt('errors'), 'errordata');
519 $errordata->setKeyName($this->lng->txt('text_wrong'));
520 $errordata->setValueName($this->lng->txt('text_correct'));
521 $errordata->setValues($this->object->getErrorData());
522 $form->addItem($errordata);
523
524 // points for wrong selection
525 $points_wrong = new ilNumberInputGUI($this->lng->txt('points_wrong'), 'points_wrong');
526 $points_wrong->allowDecimals(true);
527 $points_wrong->setMaxValue(0);
528 $points_wrong->setMaxvalueShouldBeLess(true);
529 $points_wrong->setValue($this->object->getPointsWrong());
530 $points_wrong->setInfo($this->lng->txt('points_wrong_info'));
531 $points_wrong->setSize(6);
532 $points_wrong->setRequired(true);
533 $form->addItem($points_wrong);
534 }
535
540 {
541 $existing_errordata = $this->object->getErrorData();
542 $this->object->flushErrorData();
543 $new_errordata = $this->request->raw('errordata');
544 $errordata = [];
545 foreach ($new_errordata['points'] as $index => $points) {
546 $errordata[$index] = $existing_errordata[$index]->withPoints(
547 (float) str_replace(',', '.', $points)
548 );
549 }
550 $this->object->setErrorData($errordata);
551 $this->object->setPointsWrong((float) str_replace(',', '.', $form->getInput('points_wrong')));
552 }
553}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
return true
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getAggregatedAnswersView(array $relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
getPreview($show_question_only=false, $showInlineFeedback=false)
getSolutionOutput( $active_id, $pass=null, $graphical_output=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 The getSolutionOutput() method is used to print either the user's pa...
getAnswersFrequency($relevant_answers, $question_index)
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)
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)
getSpecificFeedbackOutput(array $user_solution)
Returns the answer specific feedback for the question.
getUsersSolutionFromPreviewOrDatabase(int $active_id=0, ?int $pass=null)
generateQuestionOutput($selections, $show_question_only)
getTestOutput( $active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
writePostData(bool $always=false)
{Evaluates a posted edit form and writes the form data in the question object.integer A positive valu...
restructurePostDataForSaving(array $post)
analyze()
Parse the error text.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
populateTaxonomyFormSection(ilPropertyFormGUI $form)
getILIASPage(string $html="")
Returns the ILIAS Page around a question.
addBasicQuestionFormProperties(ilPropertyFormGUI $form)
getGenericFeedbackOutput(int $active_id, ?int $pass)
addQuestionFormCommandButtons(ilPropertyFormGUI $form)
setErrorMessage(string $errormessage)
hasCorrectSolution($activeId, $passIndex)
generateCorrectnessIconsForCorrectness(int $correctness)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a number property in a property form.
This class represents a property form user interface.
getInput(string $a_post_var, bool $ensureValidation=true)
Returns the input of an item, if item provides getInput method and as fallback the value of the HTTP-...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
special template class to simplify handling of ITX/PEAR
This class represents a text area property in a property form.
global $DIC
Definition: feed.php:28
$errors
Definition: imgupload.php:65
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$post
Definition: ltitoken.php:49
$index
Definition: metadata.php:145
$keys
Definition: metadata.php:204
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
string $key
Consumer key/client ID value.
Definition: System.php:193