ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.assSingleChoiceGUI.php
Go to the documentation of this file.
1 <?php
2 
34 {
35  private bool $rebuild_thumbnails = false;
43  public function __construct(int $id = -1)
44  {
46  $this->object = new assSingleChoice();
47  if ($id >= 0) {
48  $this->object->loadFromDb($id);
49  }
50  }
51 
55  public function hasInlineFeedback(): bool
56  {
57  return $this->object->feedbackOBJ->isSpecificAnswerFeedbackAvailable($this->object->getId());
58  }
59 
63  protected function writePostData(bool $always = false): int
64  {
65  if ($always || !$this->editQuestion(true)) {
69  $this->saveTaxonomyAssignments();
70  return 0;
71  }
72  return 1;
73  }
74 
82  protected function getEditAnswersSingleLine(bool $checkonly = false): bool
83  {
84  if ($this->object->getSelfAssessmentEditingMode()) {
85  return $this->object->isSingleline();
86  }
87 
88  if ($checkonly) {
89  return $this->request_data_collector->int('types') === 0;
90  }
91 
92  if (empty($this->object->getLastChange())
93  && !$this->request_data_collector->isset('types')) {
94  // a new question is edited
95  return $this->object->getMultilineAnswerSetting() === 0;
96  }
97  // a saved question is edited
98  return $this->object->isSingleline();
99  }
100 
101  public function editQuestion(
102  bool $checkonly = false,
103  ?bool $is_save_cmd = null
104  ): bool {
105  $save = $is_save_cmd ?? $this->isSaveCommand();
106 
107  $form = new ilPropertyFormGUI();
108  $this->editForm = $form;
109 
110  $form->setFormAction($this->ctrl->getFormAction($this));
111  $form->setTitle($this->outQuestionType());
112  $is_singleline = $this->getEditAnswersSingleLine($checkonly);
113  if ($is_singleline) {
114  $form->setMultipart(true);
115  } else {
116  $form->setMultipart(false);
117  }
118  $form->setTableWidth('100%');
119  $form->setId('asssinglechoice');
120 
121  $this->addBasicQuestionFormProperties($form);
122  $this->populateQuestionSpecificFormPart($form, $is_singleline);
123  $this->populateAnswerSpecificFormPart($form, $is_singleline);
124 
125  $this->populateTaxonomyFormSection($form);
126 
127  $this->addQuestionFormCommandButtons($form);
128 
129  $errors = false;
130 
131  if ($save) {
132  foreach ($this->request_data_collector->getParsedBody() as $key => $value) {
133  $item = $form->getItemByPostVar($key);
134  if ($item === null) {
135  continue;
136  }
137  switch (get_class($item)) {
138  case 'ilDurationInputGUI':
139  $item->setHours($value['hh']);
140  $item->setMinutes($value['mm']);
141  $item->setSeconds($value['ss']);
142  break;
143  default:
144  $item->setValue($value);
145  }
146  }
147 
148  $errors = !$form->checkInput();
149  if ($errors) {
150  $checkonly = false;
151  }
152  }
153 
154  if (!$checkonly) {
155  $this->renderEditForm($form);
156  }
157  return $errors;
158  }
159 
160  public function uploadchoice(): void
161  {
163  $this->writePostData(true);
164  $this->editQuestion();
165  }
166 
167  public function removeimagechoice(): void
168  {
170  $this->writePostData(true);
171  $position = key($this->request_data_collector->raw('cmd')['removeimagechoice']);
172  $this->object->removeAnswerImage($position);
173  $this->editQuestion();
174  }
175 
176  public function addchoice(): void
177  {
178  $this->writePostData(true);
179  $position = key($this->request_data_collector->raw('cmd')['addchoice']);
180  $this->object->addAnswer('', 0, $position + 1);
181  $this->editQuestion();
182  }
183 
184  public function removechoice(): void
185  {
186  $this->writePostData(true);
187  $position = key($this->request_data_collector->raw('cmd')['removechoice']);
188  $this->object->deleteAnswer($position);
189  $this->editQuestion();
190  }
191 
192  public function getSolutionOutput(
193  int $active_id,
194  ?int $pass = null,
195  bool $graphical_output = false,
196  bool $result_output = false,
197  bool $show_question_only = true,
198  bool $show_feedback = false,
199  bool $show_correct_solution = false,
200  bool $show_manual_scoring = false,
201  bool $show_question_text = true,
202  bool $show_inline_feedback = true
203  ): string {
204 
205  if (($active_id > 0) && (!$show_correct_solution)) {
206  $user_solutions = $this->object->getSolutionValues($active_id, $pass);
207 
208  } else {
209  $found_index = -1;
210  $max_points = 0;
211  foreach ($this->object->answers as $index => $answer) {
212  if ($answer->getPoints() > $max_points) {
213  $max_points = $answer->getPoints();
214  $found_index = $index;
215  }
216  }
217  $user_solutions = [['value1' => $found_index]];
218  }
219 
220  return $this->renderSolutionOutput(
221  $user_solutions,
222  $active_id,
223  $pass,
224  $graphical_output,
225  $result_output,
226  $show_question_only,
227  $show_feedback,
228  $show_correct_solution,
229  $show_manual_scoring,
230  $show_question_text,
231  false,
232  $show_inline_feedback,
233  );
234  }
235 
236  public function renderSolutionOutput(
237  mixed $user_solutions,
238  int $active_id,
239  ?int $pass,
240  bool $graphical_output = false,
241  bool $result_output = false,
242  bool $show_question_only = true,
243  bool $show_feedback = false,
244  bool $show_correct_solution = false,
245  bool $show_manual_scoring = false,
246  bool $show_question_text = true,
247  bool $show_autosave_title = false,
248  bool $show_inline_feedback = false,
249  ): ?string {
250  $user_solution = '';
251  foreach ($user_solutions as $idx => $solution_value) {
252  $user_solution = $solution_value['value1'];
253  }
254 
255  $template = new ilTemplate('tpl.il_as_qpl_mc_sr_output_solution.html', true, true, 'components/ILIAS/TestQuestionPool');
256  $solutiontemplate = new ilTemplate('tpl.il_as_tst_solution_output.html', true, true, 'components/ILIAS/TestQuestionPool');
257 
258  $keys = $this->getChoiceKeys();
259  foreach ($keys as $answer_id) {
260  $answer = $this->object->answers[$answer_id];
261  if ($active_id > 0 && !$show_correct_solution && $graphical_output) {
262  $correctness = $this->generateCorrectness(
263  (string) $user_solution,
264  (string) $answer_id,
265  $answer->getPoints(),
266  $this->object->getMaximumPoints()
267  );
268  $template->setCurrentBlock('icon_ok');
269  $template->setVariable('ICON_OK', $this->generateCorrectnessIconsForCorrectness($correctness));
270  $template->parseCurrentBlock();
271  }
272  if ($answer->hasImage()) {
273  $template->setCurrentBlock('answer_image');
274  if ($this->object->getThumbSize()) {
275  $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
276  } else {
277  $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $answer->getImage());
278  }
279  $alt = $answer->getImage();
280  if (strlen($answer->getAnswertext())) {
281  $alt = $answer->getAnswertext();
282  }
283  $alt = preg_replace('/<[^>]*?>/', '', $alt);
284  $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
285  $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
286  $template->parseCurrentBlock();
287  }
288 
289  if (($show_feedback || !$this->isTestPresentationContext()) && $show_inline_feedback) {
290  $this->populateInlineFeedback($template, $answer_id, $user_solution);
291  }
292  $template->setCurrentBlock('answer_row');
293  $template->setVariable('ANSWER_TEXT', ilLegacyFormElementsUtil::prepareTextareaOutput($answer->getAnswertext(), true));
294 
295  if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
296  if ((string) $user_solution === (string) $answer_id) {
297  $template->setVariable('SOLUTION_IMAGE', ilUtil::getHtmlPath(ilUtil::getImagePath('object/radiobutton_checked.png')));
298  $template->setVariable('SOLUTION_ALT', $this->lng->txt('checked'));
299  } else {
300  $template->setVariable('SOLUTION_IMAGE', ilUtil::getHtmlPath(ilUtil::getImagePath('object/radiobutton_unchecked.png')));
301  $template->setVariable('SOLUTION_ALT', $this->lng->txt('unchecked'));
302  }
303  } else {
304  $template->setVariable('QID', $this->object->getId());
305  $template->setVariable('SUFFIX', $show_correct_solution ? 'bestsolution' : 'usersolution');
306  $template->setVariable('SOLUTION_VALUE', $answer_id);
307  if ((string) $user_solution === (string) $answer_id) {
308  $template->setVariable('SOLUTION_CHECKED', 'checked');
309  }
310  }
311 
312  if ($result_output) {
313  $points = $this->object->answers[$answer_id]->getPoints();
314  $resulttext = ($points == 1) ? "(%s {$this->lng->txt('point')})" : "(%s {$this->lng->txt('points')})";
315  $template->setVariable('RESULT_OUTPUT', sprintf($resulttext, $points));
316  }
317  $template->parseCurrentBlock();
318  }
319 
320  $questiontext = $this->object->getQuestionForHTMLOutput();
321  if ($show_inline_feedback && $this->hasInlineFeedback()) {
322  $questiontext .= $this->buildFocusAnchorHtml();
323  }
324  if ($show_question_text === true) {
325  $template->setVariable('QUESTIONTEXT', ilLegacyFormElementsUtil::prepareTextareaOutput($questiontext, true));
326  }
327  $questionoutput = $template->get();
328  $feedback = ($show_feedback && !$this->isTestPresentationContext()) ? $this->getGenericFeedbackOutput((int) $active_id, $pass) : '';
329  if ($feedback !== '') {
330  $cssClass = (
331  $this->hasCorrectSolution($active_id, $pass) ?
333  );
334 
335  $solutiontemplate->setVariable('ILC_FB_CSS_CLASS', $cssClass);
336  $solutiontemplate->setVariable('FEEDBACK', ilLegacyFormElementsUtil::prepareTextareaOutput($feedback, true));
337  }
338  $solutiontemplate->setVariable('SOLUTION_OUTPUT', $questionoutput);
339 
340  $solutionoutput = $solutiontemplate->get();
341 
342  if (!$show_question_only) {
343  // get page object output
344  $solutionoutput = $this->getILIASPage($solutionoutput);
345  }
346  return $solutionoutput;
347  }
348 
349  private function generateCorrectness(
350  string $user_solution,
351  string $answer_id,
352  float $answer_points,
353  float $maximum_points
354  ): int {
355  if ($user_solution === $answer_id
356  && $answer_points === $maximum_points
357  || $user_solution !== $answer_id
358  && $answer_points === 0.0
359  ) {
360  return self::CORRECTNESS_OK;
361  }
362 
363  if ($user_solution === $answer_id
364  && $answer_points > 0.0) {
365  return self::CORRECTNESS_MOSTLY_OK;
366  }
367 
368  return self::CORRECTNESS_NOT_OK;
369  }
370 
371  public function getPreview(
372  bool $show_question_only = false,
373  bool $show_inline_feedback = false
374  ): string {
375  $keys = $this->getChoiceKeys();
376 
377  $template = new ilTemplate('tpl.il_as_qpl_mc_sr_output.html', true, true, 'components/ILIAS/TestQuestionPool');
378  foreach ($keys as $answer_id) {
379  $answer = $this->object->answers[$answer_id];
380  if ($answer->hasImage()) {
381  if ($this->object->getThumbSize()) {
382  $template->setCurrentBlock('preview');
383  $template->setVariable('URL_PREVIEW', $this->object->getImagePathWeb() . $answer->getImage());
384  $template->setVariable('TEXT_PREVIEW', $this->lng->txt('preview'));
385  $template->setVariable('IMG_PREVIEW', ilUtil::getImagePath('media/enlarge.svg'));
386  $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
387  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
388  $alt = $answer->getImage();
389  if (strlen($answer->getAnswertext())) {
390  $alt = $answer->getAnswertext();
391  }
392  $alt = preg_replace('/<[^>]*?>/', '', $alt);
393  $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
394  $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
395  $template->parseCurrentBlock();
396  } else {
397  $template->setCurrentBlock('answer_image');
398  $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $answer->getImage());
399  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
400  $alt = $answer->getImage();
401  if (strlen($answer->getAnswertext())) {
402  $alt = $answer->getAnswertext();
403  }
404  $alt = preg_replace('/<[^>]*?>/', '', $alt);
405  $template->setVariable('ATTR', $attr);
406  $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
407  $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
408  $template->parseCurrentBlock();
409  }
410  }
411  if ($show_inline_feedback && is_object($this->getPreviewSession())) {
412  $this->populateInlineFeedback($template, $answer_id, $this->getPreviewSession()->getParticipantsSolution());
413  }
414  $template->setCurrentBlock('answer_row');
415  $template->setVariable('QID', $this->object->getId() . 'ID');
416  $template->setVariable('ANSWER_ID', $answer_id);
417  $template->setVariable('ANSWER_TEXT', ilLegacyFormElementsUtil::prepareTextareaOutput($answer->getAnswertext(), true));
418 
419  if (is_object($this->getPreviewSession())) {
420  $user_solution = $this->getPreviewSession()->getParticipantsSolution();
421  if ((string) $user_solution === (string) $answer_id) {
422  $template->setVariable('CHECKED_ANSWER', ' checked="checked"');
423  }
424  }
425 
426  $template->parseCurrentBlock();
427  }
428  $questiontext = $this->object->getQuestionForHTMLOutput();
429  if ($show_inline_feedback && $this->hasInlineFeedback()) {
430  $questiontext .= $this->buildFocusAnchorHtml();
431  }
432  $template->setVariable('QUESTIONTEXT', ilLegacyFormElementsUtil::prepareTextareaOutput($questiontext, true));
433  $questionoutput = $template->get();
434  if (!$show_question_only) {
435  // get page object output
436  $questionoutput = $this->getILIASPage($questionoutput);
437  }
438  return $questionoutput;
439  }
440 
441  public function getTestOutput(
442  int $active_id,
443  int $pass,
444  bool $is_question_postponed = false,
445  array|bool $user_post_solutions = false,
446  bool $show_specific_inline_feedback = false
447  ): string {
448  $keys = $this->getChoiceKeys();
449 
450  $user_solution = '';
451  if ($active_id !== 0) {
452  $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
453  foreach ($solutions as $solution_value) {
454  $user_solution = $solution_value['value1'];
455  }
456  }
457 
458  $template = new ilTemplate('tpl.il_as_qpl_mc_sr_output.html', true, true, 'components/ILIAS/TestQuestionPool');
459  foreach ($keys as $answer_id) {
460  $answer = $this->object->answers[$answer_id];
461  if ($answer->hasImage()) {
462  if ($this->object->getThumbSize()) {
463  $template->setCurrentBlock('preview');
464  $template->setVariable('URL_PREVIEW', $this->object->getImagePathWeb() . $answer->getImage());
465  $template->setVariable('TEXT_PREVIEW', $this->lng->txt('preview'));
466  $template->setVariable('IMG_PREVIEW', ilUtil::getImagePath('media/enlarge.svg'));
467  $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
468  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
469  $alt = $answer->getImage();
470  if (strlen($answer->getAnswertext())) {
471  $alt = $answer->getAnswertext();
472  }
473  $alt = preg_replace('/<[^>]*?>/', '', $alt);
474  $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
475  $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
476  $template->parseCurrentBlock();
477  } else {
478  $template->setCurrentBlock('answer_image');
479  $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $answer->getImage());
480  list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
481  $alt = $answer->getImage();
482  if (strlen($answer->getAnswertext())) {
483  $alt = $answer->getAnswertext();
484  }
485  $alt = preg_replace('/<[^>]*?>/', '', $alt);
486  $template->setVariable('ATTR', $attr);
487  $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
488  $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
489  $template->parseCurrentBlock();
490  }
491  }
492 
493  if ($show_specific_inline_feedback) {
494  $this->populateInlineFeedback($template, $answer_id, $user_solution);
495  }
496  $template->setCurrentBlock('answer_row');
497  $template->setVariable('ANSWER_ID', $answer_id);
498  $template->setVariable('ANSWER_TEXT', ilLegacyFormElementsUtil::prepareTextareaOutput($answer->getAnswertext(), true));
499  if ($user_solution === (string) $answer_id) {
500  $template->setVariable('CHECKED_ANSWER', ' checked="checked"');
501  }
502  $template->parseCurrentBlock();
503  }
504  $template->setVariable('QUESTIONTEXT', $this->object->getQuestionForHTMLOutput());
505  $questionoutput = $template->get();
506  $pageoutput = $this->outQuestionPage('', $is_question_postponed, $active_id, $questionoutput, $show_specific_inline_feedback);
507  return $pageoutput;
508  }
509 
510  /*
511  * Create the key index numbers for the array of choices
512  *
513  * @return array
514  */
515  public function getChoiceKeys()
516  {
517  $choice_keys = array_keys($this->object->answers);
518 
519  if ($this->object->getShuffle()) {
520  $choice_keys = $this->object->getShuffler()->transform($choice_keys);
521  }
522 
523  return $choice_keys;
524  }
525 
526  public function getSpecificFeedbackOutput(array $user_solution): string
527  {
528  // No return value, this question type supports inline specific feedback.
529  $output = '';
531  }
532 
534  {
535  $is_multi_line = $this->request_data_collector->string('types');
536  if ($is_multi_line === '') {
537  $is_multi_line = '0';
538  }
539  $this->object->setMultilineAnswerSetting($is_multi_line);
540  $this->object->setShuffle($this->request_data_collector->bool('shuffle') ?? false);
541 
542  $choice = $this->request_data_collector->raw('choice');
543  if (isset($choice['imagename']) && is_array($choice['imagename']) && $is_multi_line === '1') {
544  $this->object->setIsSingleline(true);
545  $this->tpl->setOnScreenMessage('info', $this->lng->txt('info_answer_type_change'), true);
546  } else {
547  $this->object->setIsSingleline($is_multi_line === '0');
548  }
549 
550  $object_thumb_size = $this->object->getThumbSize();
551  $thumb_size = $this->request_data_collector->int('thumb_size') ?? $object_thumb_size;
552  if ($thumb_size !== $object_thumb_size) {
553  $this->object->setThumbSize($thumb_size);
554  $this->rebuild_thumbnails = true;
555  }
556  }
557 
558  public function populateQuestionSpecificFormPart(\ilPropertyFormGUI $form, bool $is_singleline = false): ilPropertyFormGUI
559  {
560  // shuffle
561  $shuffle = new ilCheckboxInputGUI($this->lng->txt('shuffle_answers'), 'shuffle');
562  $shuffle->setValue(1);
563  $shuffle->setChecked($this->object->getShuffle());
564  $shuffle->setRequired(false);
565  $form->addItem($shuffle);
566 
567  if (!$this->object->getSelfAssessmentEditingMode()) {
568  // Answer types
569  $types = new ilSelectInputGUI($this->lng->txt('answer_types'), 'types');
570  $types->setRequired(false);
571  $types->setOptions(
572  [
573  0 => $this->lng->txt('answers_singleline'),
574  1 => $this->lng->txt('answers_multiline'),
575  ]
576  );
577  $types->setValue($is_singleline ? 0 : 1);
578  $form->addItem($types);
579  }
580 
581  if ($is_singleline) {
582  // thumb size
583  $thumb_size = new ilNumberInputGUI($this->lng->txt('thumb_size'), 'thumb_size');
584  $thumb_size->setSuffix($this->lng->txt('thumb_size_unit_pixel'));
585  $thumb_size->setMinValue($this->object->getMinimumThumbSize());
586  $thumb_size->setMaxValue($this->object->getMaximumThumbSize());
587  $thumb_size->setDecimals(0);
588  $thumb_size->setSize(6);
589  $thumb_size->setInfo($this->lng->txt('thumb_size_info'));
590  $thumb_size->setValue($this->object->getThumbSize());
591  $thumb_size->setRequired(true);
592  } else {
593  $thumb_size = new ilHiddenInputGUI('thumb_size');
594  $thumb_size->setValue($this->object->getThumbSize());
595  }
596  $form->addItem($thumb_size);
597 
598  return $form;
599  }
600 
611  {
612  return [];
613  }
614 
615  public function writeAnswerSpecificPostData(ilPropertyFormGUI $form): void
616  {
617  // Delete all existing answers and create new answers from the form data
618  $this->object->flushAnswers();
619  $choice = $this->cleanupAnswerText(
620  $this->request_data_collector->raw('choice') ?? [],
621  $this->object->isSingleline() === false
622  );
623 
624  if ($choice === []) {
625  return;
626  }
627 
628  if (!$this->object->isSingleline()) {
629  foreach ($choice['answer'] as $index => $answer) {
630  $answertext = $answer;
631  $this->object->addAnswer(
632  $answertext,
633  $this->refinery->kindlyTo()->float()->transform($choice['points'][$index]),
634  $index,
635  null,
636  $choice['answer_id'][$index]
637  );
638  }
639 
640  return;
641  }
642 
643  foreach ($choice['answer'] as $index => $answertext) {
644  $answertext = htmlentities($answertext);
645  $picturefile = $choice['imagename'][$index] ?? null;
646  $file_org_name = $_FILES['choice']['name']['image'][$index] ?? '';
647  $file_temp_name = $_FILES['choice']['tmp_name']['image'][$index] ?? '';
648 
649  if ($file_temp_name !== '') {
650  // check suffix
651  $file_name_parts = explode('.', $file_org_name);
652  $suffix = strtolower(array_pop($file_name_parts));
653  if (in_array($suffix, ['jpg', 'jpeg', 'png', 'gif'])) {
654  // upload image
655  $filename = $this->object->buildHashedImageFilename($file_org_name);
656  if ($this->object->setImageFile($filename, $file_temp_name) == 0) {
657  $picturefile = $filename;
658  }
659  }
660  }
661 
662  $points = (float) str_replace(',', '.', $choice['points'][$index]);
663  $this->object->addAnswer(
664  $answertext,
665  $points,
666  $index,
667  $picturefile,
668  $choice['answer_id'][$index]
669  );
670  }
671 
672  if ($this->rebuild_thumbnails) {
673  $this->object->setAnswers(
674  $this->object->rebuildThumbnails(
675  $this->object->isSingleline(),
676  $this->object->getThumbSize(),
677  $this->object->getImagePath(),
678  $this->object->getAnswers()
679  )
680  );
681  }
682  }
683 
684  public function populateAnswerSpecificFormPart(\ilPropertyFormGUI $form, bool $is_singleline = false): ilPropertyFormGUI
685  {
686  $choices = new ilSingleChoiceWizardInputGUI($this->lng->txt('answers'), 'choice');
687  $choices->setRequired(true);
688  $choices->setQuestionObject($this->object);
689  $choices->setSingleline($is_singleline);
690  $choices->setAllowMove(false);
691  if ($this->object->getSelfAssessmentEditingMode()) {
692  $choices->setSize(40);
693  }
694  if ($this->object->getAnswerCount() == 0) {
695  $this->object->addAnswer('', 0, 0);
696  }
697  $choices->setValues(array_map(
698  function (ASS_AnswerBinaryStateImage $value) {
699  $value->setAnswerText(html_entity_decode($value->getAnswerText()));
700  return $value;
701  },
702  $this->object->getAnswers()
703  ));
704  $form->addItem($choices);
705  return $form;
706  }
707 
718  {
719  return [];
720  }
721 
722  private function aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question): array
723  {
724  $aggregate = [];
725  foreach ($answers_defined_on_question as $answer) {
726  $aggregated_info_for_answer = [];
727  $aggregated_info_for_answer['answertext'] = $answer->getAnswerText();
728  $aggregated_info_for_answer['count_checked'] = 0;
729 
730  foreach ($relevant_answers_chosen as $relevant_answer) {
731  if ($relevant_answer['value1'] == $answer->getOrder()) {
732  $aggregated_info_for_answer['count_checked']++;
733  }
734  }
735  $aggregated_info_for_answer['count_unchecked'] =
736  ceil(count($relevant_answers_chosen) / count($answers_defined_on_question))
737  - $aggregated_info_for_answer['count_checked'];
738 
739  $aggregate[] = $aggregated_info_for_answer;
740  }
741  return $aggregate;
742  }
743 
749  public function renderAggregateView($aggregate): ilTemplate
750  {
751  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, 'components/ILIAS/TestQuestionPool');
752 
753  $tpl->setCurrentBlock('headercell');
754  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_answer_header'));
756 
757  $tpl->setCurrentBlock('headercell');
758  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_frequency_header'));
760 
761  foreach ($aggregate as $line_data) {
762  $tpl->setCurrentBlock('aggregaterow');
763  $tpl->setVariable('OPTION', $line_data['answertext']);
764  $tpl->setVariable('COUNT', $line_data['count_checked']);
766  }
767  return $tpl;
768  }
769 
770  private function populateInlineFeedback($template, $answer_id, $user_solution): void
771  {
772  $feedbackOutputRequired = false;
773 
774  switch ($this->object->getSpecificFeedbackSetting()) {
775  case 1:
776  $feedbackOutputRequired = true;
777  break;
778 
779  case 2:
780  if ((string) $user_solution === (string) $answer_id) {
781  $feedbackOutputRequired = true;
782  }
783  break;
784 
785  case 3:
786  if ($this->object->getAnswer($answer_id)->getPoints() > 0) {
787  $feedbackOutputRequired = true;
788  }
789  break;
790  }
791 
792  if ($feedbackOutputRequired) {
793  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), 0, $answer_id);
794  if (strlen($fb)) {
795  $template->setCurrentBlock('feedback');
796  $template->setVariable('FEEDBACK', ilLegacyFormElementsUtil::prepareTextareaOutput($fb, true));
797  $template->parseCurrentBlock();
798  }
799  }
800  }
801 
802  public function getAnswersFrequency($relevantAnswers, $questionIndex): array
803  {
804  $agg = $this->aggregateAnswers($relevantAnswers, $this->object->getAnswers());
805 
806  $answers = [];
807 
808  foreach ($agg as $ans) {
809  $answers[] = [
810  'answer' => $ans['answertext'],
811  'frequency' => $ans['count_checked']
812  ];
813  }
814 
815  return $answers;
816  }
817 
819  {
820  $choices = new ilAssSingleChoiceCorrectionsInputGUI($this->lng->txt('answers'), 'choice');
821  $choices->setRequired(true);
822  $choices->setQuestionObject($this->object);
823  $choices->setValues($this->object->getAnswers());
824  $form->addItem($choices);
825  }
826 
831  {
832  $input = $form->getItemByPostVar('choice');
833  $values = $input->getValues();
834 
835  foreach ($this->object->getAnswers() as $index => $answer) {
836  /* @var ASS_AnswerMultipleResponseImage $answer */
837  $points = (float) str_replace(',', '.', $values[$index]->getPoints());
838  $answer->setPoints($points);
839  }
840  }
841 }
hasCorrectSolution($activeId, $passIndex)
__construct(int $id=-1)
assSingleChoiceGUI constructor
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form, bool $is_singleline=false)
generateCorrectnessIconsForCorrectness(int $correctness)
aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
setCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Sets the template to the given block.
This class represents a selection list property in a property form.
editQuestion(bool $checkonly=false, ?bool $is_save_cmd=null)
getItemByPostVar(string $a_post_var)
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from the request and applies them to the data object...
Class for answers with a binary state indicator.
getTestOutput(int $active_id, int $pass, bool $is_question_postponed=false, array|bool $user_post_solutions=false, bool $show_specific_inline_feedback=false)
populateInlineFeedback($template, $answer_id, $user_solution)
addBasicQuestionFormProperties(ilPropertyFormGUI $form)
parseCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Parses the given block.
ilGlobalPageTemplate $tpl
getSolutionOutput(int $active_id, ?int $pass=null, bool $graphical_output=false, bool $result_output=false, bool $show_question_only=true, bool $show_feedback=false, bool $show_correct_solution=false, bool $show_manual_scoring=false, bool $show_question_text=true, bool $show_inline_feedback=true)
static prepareFormOutput($a_str, bool $a_strip=false)
getSpecificFeedbackOutput(array $user_solution)
getAnswersFrequency($relevantAnswers, $questionIndex)
populateTaxonomyFormSection(ilPropertyFormGUI $form)
generateCorrectness(string $user_solution, string $answer_id, float $answer_points, float $maximum_points)
addQuestionFormCommandButtons(ilPropertyFormGUI $form)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
Class for single choice questions.
writePostData(bool $always=false)
{}
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form, bool $is_singleline=false)
static getHtmlPath(string $relative_path)
get url of path
setRequired(bool $a_required)
getEditAnswersSingleLine(bool $checkonly=false)
Get the single/multiline editing of answers.
$filename
Definition: buildRTE.php:78
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
This class represents a single choice wizard property in a property form.
getILIASPage(string $html="")
Returns the ILIAS Page around a question.
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:24
__construct(Container $dic, ilPlugin $plugin)
cleanupAnswerText(array $answer_text, bool $is_rte)
sk - 12.05.2023: This is one more of those that we need, but don&#39;t want.
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 file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static prepareTextareaOutput(string $txt_output, bool $prepare_for_latex_output=false, bool $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output where latex code may be in it If the text is HTML-free...
setVariable(string $variable, $value='')
Sets the given variable to the given value.
renderSolutionOutput(mixed $user_solutions, int $active_id, ?int $pass, bool $graphical_output=false, bool $result_output=false, bool $show_question_only=true, bool $show_feedback=false, bool $show_correct_solution=false, bool $show_manual_scoring=false, bool $show_question_text=true, bool $show_autosave_title=false, bool $show_inline_feedback=false,)
getPreview(bool $show_question_only=false, bool $show_inline_feedback=false)
renderEditForm(ilPropertyFormGUI $form)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from the request and applies them to the data object...
getGenericFeedbackOutput(int $active_id, ?int $pass)