ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilTestEvaluationGUI.php
Go to the documentation of this file.
1 <?php
2 
39 {
43 
52  public function __construct(ilObjTest $a_object)
53  {
54  parent::__construct($a_object);
55 
56  global $DIC;
57  $this->current_user = $DIC['ilUser'];
58 
59  $this->processLockerFactory = new ilTestProcessLockerFactory(
60  new ilSetting('assessment'),
61  $this->db
62  );
63  }
64 
68  public function getTestAccess(): ilTestAccess
69  {
70  return $this->testAccess;
71  }
72 
76  public function setTestAccess($testAccess)
77  {
78  $this->testAccess = $testAccess;
79  }
80 
84  public function executeCommand()
85  {
86  $cmd = $this->ctrl->getCmd();
87  $next_class = $this->ctrl->getNextClass($this);
88  $this->ctrl->saveParameter($this, "sequence");
89  $this->ctrl->saveParameter($this, "active_id");
90 
91  switch ($next_class) {
92  case 'iltestpassdetailsoverviewtablegui':
93  require_once 'Modules/Test/classes/tables/class.ilTestPassDetailsOverviewTableGUI.php';
94  $tableGUI = new ilTestPassDetailsOverviewTableGUI($this->ctrl, $this, 'outUserPassDetails');
95  $tableGUI->setIsPdfGenerationRequest($this->isPdfDeliveryRequest());
96  $tableGUI->initFilter();
97  $this->ctrl->forwardCommand($tableGUI);
98  break;
99 
100  default:
101  $ret = $this->$cmd();
102  break;
103  }
104  return $ret;
105  }
106 
110  public function filterEvaluation()
111  {
112  if (!$this->getTestAccess()->checkStatisticsAccess()) {
114  }
115 
116  include_once "./Modules/Test/classes/tables/class.ilEvaluationAllTableGUI.php";
117  $table_gui = new ilEvaluationAllTableGUI($this, 'outEvaluation');
118  $table_gui->writeFilterToSession();
119  $this->ctrl->redirect($this, "outEvaluation");
120  }
121 
125  public function resetfilterEvaluation()
126  {
127  if (!$this->getTestAccess()->checkStatisticsAccess()) {
129  }
130 
131  include_once "./Modules/Test/classes/tables/class.ilEvaluationAllTableGUI.php";
132  $table_gui = new ilEvaluationAllTableGUI($this, 'outEvaluation');
133  $table_gui->resetFilter();
134  $this->ctrl->redirect($this, "outEvaluation");
135  }
136 
142  public function outEvaluation()
143  {
144  global $DIC; /* @var ILIAS\DI\Container $DIC */
145  $ilToolbar = $DIC->toolbar();
146 
147  if (!$this->getTestAccess()->checkStatisticsAccess()) {
149  }
150 
151  $DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_STATISTICS);
152 
153  $table_gui = new ilEvaluationAllTableGUI(
154  $this,
155  'outEvaluation',
156  $this->object->getAnonymity(),
157  $this->object->isOfferingQuestionHintsEnabled()
158  );
159 
160  $data = [];
161  $filter_array = [];
162 
163  foreach ($table_gui->getFilterItems() as $item) {
164  if (!in_array($item->getValue(), [false, ''])) {
165  switch ($item->getPostVar()) {
166  case 'group':
167  case 'name':
168  case 'course':
169  $filter_array[$item->getPostVar()] = $item->getValue();
170  break;
171  case 'passed_only':
172  $passedonly = $item->getChecked();
173  break;
174  }
175  }
176  }
177 
178  $eval = new ilTestEvaluationData($this->object);
179  $eval->setFilterArray($filter_array);
180  $foundParticipants = $eval->getParticipants();
181 
182  $participantData = new ilTestParticipantData($DIC->database(), $DIC->language());
183  $participantData->setActiveIdsFilter($eval->getParticipantIds());
184 
185  $participantData->setParticipantAccessFilter(
187  );
188 
189  $participantData->load($this->object->getTestId());
190 
191  $counter = 1;
192  if (count($participantData->getActiveIds()) > 0) {
193  if ($this->object->getECTSOutput()) {
194  $passed_array = $this->object->getTotalPointsPassedArray();
195  }
196  foreach ($participantData->getActiveIds() as $active_id) {
197  if (!isset($foundParticipants[$active_id]) || !($foundParticipants[$active_id] instanceof ilTestEvaluationUserData)) {
198  continue;
199  }
200 
201  /* @var $userdata ilTestEvaluationUserData */
202  $userdata = $foundParticipants[$active_id];
203 
204  $remove = false;
205  if ($passedonly) {
206  $mark_obj = $this->object->getMarkSchema()->getMatchingMark($userdata->getReachedPointsInPercent());
207 
208  if ($mark_obj->getPassed() == false || !$userdata->areObligationsAnswered()) {
209  $remove = true;
210  }
211  }
212  if (!$remove) {
213  // build the evaluation row
214  $evaluationrow = array();
215  if ($this->object->getAnonymity()) {
216  $evaluationrow['name'] = $counter;
217  $evaluationrow['login'] = '';
218  } else {
219  $evaluationrow['name'] = $userdata->getName();
220  if (strlen($userdata->getLogin())) {
221  $evaluationrow['login'] = "[" . $userdata->getLogin() . "]";
222  } else {
223  $evaluationrow['login'] = '';
224  }
225  }
226 
227  $evaluationrow['reached'] = $userdata->getReached();
228  $evaluationrow['max'] = $userdata->getMaxpoints();
229  $evaluationrow['hint_count'] = $userdata->getRequestedHintsCountFromScoredPass();
230  $evaluationrow['exam_id'] = $userdata->getExamIdFromScoredPass();
231  $percentage = $userdata->getReachedPointsInPercent();
232  $mark = $this->object->getMarkSchema()->getMatchingMark($percentage);
233  if (is_object($mark)) {
234  $evaluationrow['mark'] = $mark->getShortName();
235  }
236  if ($this->object->getECTSOutput()) {
237  $ects_mark = $this->object->getECTSGrade($passed_array, $userdata->getReached(), $userdata->getMaxPoints());
238  $evaluationrow['ects_grade'] = $ects_mark;
239  }
240  $evaluationrow['answered'] = $userdata->getQuestionsWorkedThroughInPercent();
241  $evaluationrow['questions_worked_through'] = $userdata->getQuestionsWorkedThrough();
242  $evaluationrow['number_of_questions'] = $userdata->getNumberOfQuestions();
243  $time_seconds = $userdata->getTimeOfWork();
244  $time_hours = floor($time_seconds / 3600);
245  $time_seconds -= $time_hours * 3600;
246  $time_minutes = floor($time_seconds / 60);
247  $time_seconds -= $time_minutes * 60;
248  $evaluationrow['working_time'] = sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds);
249  $this->ctrl->setParameter($this, "active_id", $active_id);
250  $href = $this->ctrl->getLinkTarget($this, "detailedEvaluation");
251  $detailed_evaluation = $this->lng->txt("detailed_evaluation_show");
252  $evaluationrow['details'] = "<a class=\"il_ContainerItemCommand\" href=\"$href\">$detailed_evaluation</a>";
253  $userfields = [];
254  if ($userdata->getUserID() !== null) {
255  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
256  }
257  $evaluationrow['gender'] = $userfields['gender'] ?? '';
258  $evaluationrow['email'] = $userfields['email'] ?? '';
259  $evaluationrow['institution'] = $userfields['institution'] ?? '';
260  $evaluationrow['street'] = $userfields['street'] ?? '';
261  $evaluationrow['city'] = $userfields['city'] ?? '';
262  $evaluationrow['zipcode'] = $userfields['zipcode'] ?? '';
263  $evaluationrow['country'] = $userfields['country'] ?? '';
264  $evaluationrow['sel_country'] = $userfields['sel_country'] ?? '';
265  $evaluationrow['department'] = $userfields['department'] ?? '';
266  $evaluationrow['matriculation'] = $userfields['matriculation'] ?? '';
267  $counter++;
268  $data[] = $evaluationrow;
269  }
270  }
271  }
272 
273  $table_gui->setData($data);
274  if (count($participantData->getActiveIds()) > 0) {
275  $ilToolbar->setFormName('form_output_eval');
276  $ilToolbar->setFormAction($this->ctrl->getFormAction($this, 'exportEvaluation'));
277  require_once 'Services/Form/classes/class.ilSelectInputGUI.php';
278  $export_type = new ilSelectInputGUI($this->lng->txt('exp_eval_data'), 'export_type');
279  $options = array(
280  'excel' => $this->lng->txt('exp_type_excel'),
281  'csv' => $this->lng->txt('exp_type_spss')
282  );
283 
284  if (!$this->object->getAnonymity()) {
285  try {
286  $globalCertificatePrerequisites = new ilCertificateActiveValidator();
287  if ($globalCertificatePrerequisites->validate()) {
288  $options['certificate'] = $this->lng->txt('exp_type_certificate');
289  }
290  } catch (ilException $e) {
291  }
292  }
293 
294  $export_type->setOptions($options);
295 
296  $ilToolbar->addInputItem($export_type, true);
297  require_once 'Services/UIComponent/Button/classes/class.ilSubmitButton.php';
298  $button = ilSubmitButton::getInstance();
299  $button->setCommand('exportEvaluation');
300  $button->setCaption('export');
301  //$button->getOmitPreventDoubleSubmission();
302  $ilToolbar->addButtonInstance($button);
303  }
304 
305  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print");
306  if ($this->object->getShowSolutionAnswersOnly()) {
307  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
308  }
309 
310  $this->tpl->setContent($table_gui->getHTML());
311  }
312 
320  public function detailedEvaluation()
321  {
322  global $DIC; /* @var ILIAS\DI\Container $DIC */
323 
324  if (!$this->getTestAccess()->checkStatisticsAccess()) {
326  }
327 
328  $DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_STATISTICS);
329 
330  $active_id = $this->testrequest->raw('active_id');
331 
332  if (!$this->getTestAccess()->checkResultsAccessForActiveId($active_id)) {
334  }
335 
336  if (strlen($active_id) == 0) {
337  $this->tpl->setOnScreenMessage('info', $this->lng->txt('detailed_evaluation_missing_active_id'), true);
338  $this->ctrl->redirect($this, 'outEvaluation');
339  }
340 
341  $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_print.css', 'Modules/Test'), 'print');
342 
343  $toolbar = $DIC['ilToolbar'];
344 
345  require_once 'Services/UIComponent/Button/classes/class.ilLinkButton.php';
346  $backBtn = ilLinkButton::getInstance();
347  $backBtn->setCaption('back');
348  $backBtn->setUrl($this->ctrl->getLinkTarget($this, 'outEvaluation'));
349  $toolbar->addInputItem($backBtn);
350 
351  $this->object->setAccessFilteredParticipantList(
352  $this->object->buildStatisticsAccessFilteredParticipantList()
353  );
354 
355  $data = $this->object->getCompleteEvaluationData();
356 
357  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
358  $form = new ilPropertyFormGUI();
359  $form->setTitle(sprintf(
360  $this->lng->txt('detailed_evaluation_for'),
361  $data->getParticipant($active_id)->getName()
362  ));
363 
364  $resultPoints = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_resultspoints'));
365  $resultPoints->setValue($data->getParticipant($active_id)->getReached() . " " . strtolower($this->lng->txt("of")) . " " . $data->getParticipant($active_id)->getMaxpoints() . " (" . sprintf("%2.2f", $data->getParticipant($active_id)->getReachedPointsInPercent()) . " %" . ")");
366  $form->addItem($resultPoints);
367 
368  if (strlen($data->getParticipant($active_id)->getMark())) {
369  $resultMarks = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_resultsmarks'));
370  $resultMarks->setValue($data->getParticipant($active_id)->getMark());
371  $form->addItem($resultMarks);
372  if (strlen($data->getParticipant($active_id)->getECTSMark())) {
373  $ectsGrade = new ilNonEditableValueGUI($this->lng->txt('ects_grade'));
374  $ectsGrade->setValue($data->getParticipant($active_id)->getECTSMark());
375  $form->addItem($ectsGrade);
376  }
377  }
378 
379  if ($this->object->isOfferingQuestionHintsEnabled()) {
380  $requestHints = new ilNonEditableValueGUI($this->lng->txt('tst_question_hints_requested_hint_count_header'));
381  $requestHints->setValue($data->getParticipant($active_id)->getRequestedHintsCountFromScoredPass());
382  $form->addItem($requestHints);
383  }
384 
385  $time_seconds = $data->getParticipant($active_id)->getTimeOfWork();
386  $atime_seconds = $data->getParticipant($active_id)->getNumberOfQuestions() ? $time_seconds / $data->getParticipant($active_id)->getNumberOfQuestions() : 0;
387  $time_hours = floor($time_seconds / 3600);
388  $time_seconds -= $time_hours * 3600;
389  $time_minutes = floor($time_seconds / 60);
390  $time_seconds -= $time_minutes * 60;
391  $timeOfWork = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_timeofwork'));
392  $timeOfWork->setValue(sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds));
393  $form->addItem($timeOfWork);
394 
395  $this->tpl->setVariable("TXT_ATIMEOFWORK", $this->lng->txt(""));
396  $time_hours = floor($atime_seconds / 3600);
397  $atime_seconds -= $time_hours * 3600;
398  $time_minutes = floor($atime_seconds / 60);
399  $atime_seconds -= $time_minutes * 60;
400  $avgTimeOfWork = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_atimeofwork'));
401  $avgTimeOfWork->setValue(sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $atime_seconds));
402  $form->addItem($avgTimeOfWork);
403 
404  $firstVisit = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_firstvisit'));
405  $firstVisit->setValue(ilDatePresentation::formatDate(new ilDateTime($data->getParticipant($active_id)->getFirstVisit(), IL_CAL_UNIX)));
406  $form->addItem($firstVisit);
407 
408  $lastVisit = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_lastvisit'));
409  $lastVisit->setValue(ilDatePresentation::formatDate(new ilDateTime($data->getParticipant($active_id)->getLastVisit(), IL_CAL_UNIX)));
410  $form->addItem($lastVisit);
411 
412  $nrPasses = new ilNonEditableValueGUI($this->lng->txt('tst_nr_of_passes'));
413  $nrPasses->setValue($data->getParticipant($active_id)->getLastPass() + 1);
414  $form->addItem($nrPasses);
415 
416  $scoredPass = new ilNonEditableValueGUI($this->lng->txt('scored_pass'));
417  if ($this->object->getPassScoring() == SCORE_BEST_PASS) {
418  $scoredPass->setValue($data->getParticipant($active_id)->getBestPass() + 1);
419  } else {
420  $scoredPass->setValue($data->getParticipant($active_id)->getLastPass() + 1);
421  }
422  $form->addItem($scoredPass);
423 
424  $median = $data->getStatistics()->getStatistics()->median();
425  $pct = $data->getParticipant($active_id)->getMaxpoints() ? ($median / $data->getParticipant($active_id)->getMaxpoints()) * 100.0 : 0;
426  $mark = $this->object->mark_schema->getMatchingMark($pct);
427  if (is_object($mark)) {
428  $markMedian = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_mark_median'));
429  $markMedian->setValue($mark->getShortName());
430  $form->addItem($markMedian);
431  }
432 
433  $rankParticipant = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_rank_participant'));
434  $rankParticipant->setValue($data->getStatistics()->getStatistics()->rank($data->getParticipant($active_id)->getReached()));
435  $form->addItem($rankParticipant);
436 
437  $rankMedian = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_rank_median'));
438  $rankMedian->setValue($data->getStatistics()->getStatistics()->rank_median());
439  $form->addItem($rankMedian);
440 
441  $totalParticipants = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_total_participants'));
442  $totalParticipants->setValue($data->getStatistics()->getStatistics()->count());
443  $form->addItem($totalParticipants);
444 
445  $medianField = new ilNonEditableValueGUI($this->lng->txt('tst_stat_result_median'));
446  $medianField->setValue($median);
447  $form->addItem($medianField);
448 
449  $this->tpl->setContent($form->getHTML());
450 
451  $tables = array();
452 
453  for ($pass = 0; $pass <= $data->getParticipant($active_id)->getLastPass(); $pass++) {
454  $finishdate = ilObjTest::lookupPassResultsUpdateTimestamp($active_id, $pass);
455  if ($finishdate > 0) {
456  if (($DIC->access()->checkAccess('write', '', $this->testrequest->getRefId()))) {
457  $this->ctrl->setParameter($this, 'statistics', '1');
458  $this->ctrl->setParameter($this, 'active_id', $active_id);
459  $this->ctrl->setParameter($this, 'pass', $pass);
460  } else {
461  $this->ctrl->setParameter($this, 'statistics', '');
462  $this->ctrl->setParameter($this, 'active_id', '');
463  $this->ctrl->setParameter($this, 'pass', '');
464  }
465 
466  require_once 'Modules/Test/classes/tables/class.ilTestDetailedEvaluationStatisticsTableGUI.php';
467  $table = new ilTestDetailedEvaluationStatisticsTableGUI($this, 'detailedEvaluation', ($pass + 1) . '_' . $this->object->getId());
468  $table->setTitle(sprintf($this->lng->txt("tst_eval_question_points"), $pass + 1));
469  if (($DIC->access()->checkAccess('write', '', $this->testrequest->getRefId()))) {
470  $table->addCommandButton('outParticipantsPassDetails', $this->lng->txt('tst_show_answer_sheet'));
471  }
472 
473  $questions = $data->getParticipant($active_id)->getQuestions($pass);
474  if (!is_array($questions)) {
475  $questions = $data->getParticipant($active_id)->getQuestions(0);
476  }
477 
478  $tableData = array();
479 
480  $counter = 0;
481  foreach ((array) $questions as $question) {
482  $userDataData = array(
483  'counter' => ++$counter,
484  'id' => $question['id'],
485  'id_txt' => $this->lng->txt('question_id_short'),
486  'title' => $this->refinery->string()->stripTags()->transform(
487  $data->getQuestionTitle($question['id'])
488  )
489  );
490 
491  $answeredquestion = $data->getParticipant($active_id)->getPass($pass)->getAnsweredQuestionByQuestionId($question["id"]);
492  if (is_array($answeredquestion)) {
493  $percent = $answeredquestion['points'] ? $answeredquestion['reached'] / $answeredquestion['points'] * 100.0 : 0;
494  $userDataData['points'] = $answeredquestion['reached'] . ' ' . strtolower($this->lng->txt('of')) . " " . $answeredquestion['points'] . ' (' . sprintf("%.2f", $percent) . ' %)';
495  } else {
496  $userDataData['points'] = '0 ' . strtolower($this->lng->txt('of')) . ' ' . $question['points'] . ' (' . sprintf("%.2f", 0) . ' %) - ' . $this->lng->txt('question_not_answered');
497  }
498 
499  $tableData[] = $userDataData;
500  }
501  $table->setData($tableData);
502 
503  $tables[] = $table->getHTML();
504  }
505  }
506 
507  global $DIC; /* @var ILIAS\DI\Container $DIC */
508  $DIC['tpl']->setContent($form->getHTML() . implode('', $tables));
509  }
510 
516  {
517  $this->getQuestionResultForTestUsers($this->testrequest->raw("qid"), $this->object->getTestId());
518  }
519 
525  {
526  require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
527  $question_object = assQuestion::instantiateQuestion($this->testrequest->raw("qid"));
528  if ($question_object instanceof ilObjFileHandlingQuestionType) {
529  $question_object->deliverFileUploadZIPFile(
530  $this->ref_id,
531  $this->object->getTestId(),
532  $this->object->getTitle()
533  );
534  } else {
535  $this->ctrl->redirect($this, "singleResults");
536  }
537  }
538 
546  public function eval_a()
547  {
548  global $DIC; /* @var ILIAS\DI\Container $DIC */
549  $ilToolbar = $DIC->toolbar();
550 
551  if (!$this->getTestAccess()->checkStatisticsAccess()) {
553  }
554 
555  $DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_STATISTICS);
556 
557  $this->tpl->addBlockFile("ADM_CONTENT", "adm_content", "tpl.il_as_tst_eval_anonymous_aggregation.html", "Modules/Test");
558 
559  $this->object->setAccessFilteredParticipantList(
560  $this->object->buildStatisticsAccessFilteredParticipantList()
561  );
562 
563  $eval = $this->object->getCompleteEvaluationData();
564  $data = array();
565  $foundParticipants = $eval->getParticipants();
566  if (count($foundParticipants)) {
567  $ilToolbar->setFormName('form_output_eval');
568  $ilToolbar->setFormAction($this->ctrl->getFormAction($this, 'exportAggregatedResults'));
569  require_once 'Services/Form/classes/class.ilSelectInputGUI.php';
570  $export_type = new ilSelectInputGUI($this->lng->txt('exp_eval_data'), 'export_type');
571  $export_type->setOptions(array(
572  'excel' => $this->lng->txt('exp_type_excel'),
573  'csv' => $this->lng->txt('exp_type_spss')
574  ));
575  $ilToolbar->addInputItem($export_type, true);
576  require_once 'Services/UIComponent/Button/classes/class.ilSubmitButton.php';
577  $button = ilSubmitButton::getInstance();
578  $button->setCommand('exportAggregatedResults');
579  $button->setCaption('export');
580  //$button->getOmitPreventDoubleSubmission();
581  $ilToolbar->addButtonInstance($button);
582 
583  array_push($data, array(
584  'result' => $this->lng->txt("tst_eval_total_persons"),
585  'value' => count($foundParticipants)
586  ));
587  $total_finished = $eval->getTotalFinishedParticipants();
588  array_push($data, array(
589  'result' => $this->lng->txt("tst_eval_total_finished"),
590  'value' => $total_finished
591  ));
592  $average_time = $this->object->evalTotalStartedAverageTime(
593  $eval->getParticipantIds()
594  );
595  $diff_seconds = $average_time;
596  $diff_hours = floor($diff_seconds / 3600);
597  $diff_seconds -= $diff_hours * 3600;
598  $diff_minutes = floor($diff_seconds / 60);
599  $diff_seconds -= $diff_minutes * 60;
600  array_push($data, array(
601  'result' => $this->lng->txt("tst_eval_total_finished_average_time"),
602  'value' => sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds)
603  ));
604  $total_passed = 0;
605  $total_passed_reached = 0;
606  $total_passed_max = 0;
607  $total_passed_time = 0;
608  foreach ($foundParticipants as $userdata) {
609  if ($userdata->getPassed()) {
610  $total_passed++;
611  $total_passed_reached += $userdata->getReached();
612  $total_passed_max += $userdata->getMaxpoints();
613  $total_passed_time += $userdata->getTimeOfWork();
614  }
615  }
616  $average_passed_reached = $total_passed ? $total_passed_reached / $total_passed : 0;
617  $average_passed_max = $total_passed ? $total_passed_max / $total_passed : 0;
618  $average_passed_time = $total_passed ? $total_passed_time / $total_passed : 0;
619  array_push($data, array(
620  'result' => $this->lng->txt("tst_eval_total_passed"),
621  'value' => $total_passed
622  ));
623  array_push($data, array(
624  'result' => $this->lng->txt("tst_eval_total_passed_average_points"),
625  'value' => sprintf("%2.2f", $average_passed_reached) . " " . strtolower($this->lng->txt("of")) . " " . sprintf("%2.2f", $average_passed_max)
626  ));
627  $average_time = $average_passed_time;
628  $diff_seconds = $average_time;
629  $diff_hours = floor($diff_seconds / 3600);
630  $diff_seconds -= $diff_hours * 3600;
631  $diff_minutes = floor($diff_seconds / 60);
632  $diff_seconds -= $diff_minutes * 60;
633  array_push($data, array(
634  'result' => $this->lng->txt("tst_eval_total_passed_average_time"),
635  'value' => sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds)
636  ));
637  }
638 
639  include_once "./Modules/Test/classes/tables/class.ilTestAggregatedResultsTableGUI.php";
640  $table_gui = new ilTestAggregatedResultsTableGUI($this, 'eval_a');
641  $table_gui->setData($data);
642  $this->tpl->setVariable('AGGREGATED_RESULTS', $table_gui->getHTML());
643 
644  $rows = array();
645  $counter = 0;
646  foreach ($eval->getQuestionTitles() as $question_id => $question_title) {
647  $answered = 0;
648  $reached = 0;
649  $max = 0;
650  foreach ($foundParticipants as $userdata) {
651  for ($i = 0; $i <= $userdata->getLastPass(); $i++) {
652  if (is_object($userdata->getPass($i))) {
653  $question = $userdata->getPass($i)->getAnsweredQuestionByQuestionId($question_id);
654  if (is_array($question)) {
655  $answered++;
656  $reached += $question["reached"];
657  $max += $question["points"];
658  }
659  }
660  }
661  }
662  $percent = $max ? $reached / $max * 100.0 : 0;
663  $counter++;
664  $this->ctrl->setParameter($this, "qid", $question_id);
665 
666  $points_reached = ($answered ? $reached / $answered : 0);
667  $points_max = ($answered ? $max / $answered : 0);
668  array_push(
669  $rows,
670  array(
671  'qid' => $question_id,
672  'title' => $this->refinery->string()->stripTags()->transform($question_title),
673  'points' => $points_reached,
674  'points_reached' => $points_reached,
675  'points_max' => $points_max,
676  'percentage' => (float) $percent,
677  'answers' => $answered
678  )
679  );
680  }
681  include_once "./Modules/Test/classes/tables/class.ilTestAverageReachedPointsTableGUI.php";
682  $table_gui = new ilTestAverageReachedPointsTableGUI($this, 'eval_a');
683  $table_gui->setData($rows);
684  $this->tpl->setVariable('TBL_AVG_REACHED', $table_gui->getHTML());
685  }
686 
690  public function exportEvaluation()
691  {
692  $filterby = "";
693  if ($this->testrequest->isset("g_filterby")) {
694  $filterby = $this->testrequest->raw("g_filterby");
695  }
696 
697  $filtertext = "";
698  if ($this->testrequest->isset("g_userfilter")) {
699  $filtertext = $this->testrequest->raw("g_userfilter");
700  }
701 
702  $passedonly = false;
703  if ($this->testrequest->isset("g_passedonly")) {
704  if ($this->testrequest->raw("g_passedonly") == 1) {
705  $passedonly = true;
706  }
707  }
708 
709  require_once 'Modules/Test/classes/class.ilTestExportFactory.php';
710  $expFactory = new ilTestExportFactory($this->object);
711 
712  switch ($this->testrequest->raw("export_type")) {
713  case "excel":
714  $expFactory->getExporter('results')->exportToExcel(
715  $deliver = true,
716  $filterby,
717  $filtertext,
718  $passedonly
719  );
720  break;
721 
722  case "csv":
723  $expFactory->getExporter('results')->exportToCSV(
724  $deliver = true,
725  $filterby,
726  $filtertext,
727  $passedonly
728  );
729  break;
730 
731  case "certificate":
732  if ($passedonly) {
733  $this->ctrl->setParameterByClass("iltestcertificategui", "g_passedonly", "1");
734  }
735  if (strlen($filtertext)) {
736  $this->ctrl->setParameterByClass("iltestcertificategui", "g_userfilter", $filtertext);
737  }
738  $this->ctrl->redirect($this, "exportCertificate");
739  break;
740  }
741  }
742 
748  public function exportAggregatedResults()
749  {
750  require_once 'Modules/Test/classes/class.ilTestExportFactory.php';
751  $expFactory = new ilTestExportFactory($this->object);
752  $exportObj = $expFactory->getExporter('aggregated');
753 
754  switch ($_POST["export_type"]) {
755  case "excel":
756  $exportObj->exportToExcel($deliver = true);
757  break;
758  case "csv":
759  $exportObj->exportToCSV($deliver = true);
760  break;
761  }
762  }
763 
770  public function exportCertificate()
771  {
772  global $DIC;
773 
774  $globalCertificatePrerequisites = new ilCertificateActiveValidator();
775  if (!$globalCertificatePrerequisites->validate()) {
776  $DIC['ilErr']->raiseError($this->lng->txt('permission_denied'), $DIC['ilErr']->MESSAGE);
777  }
778 
779  $database = $DIC->database();
780  $logger = $DIC->logger()->root();
781 
782  $pathFactory = new ilCertificatePathFactory();
783  $objectId = $this->object->getId();
784  $zipAction = new ilUserCertificateZip(
785  $objectId,
786  $pathFactory->create($this->object)
787  );
788 
789  $archive_dir = $zipAction->createArchiveDirectory();
790  $total_users = array();
791 
792  $this->object->setAccessFilteredParticipantList(
793  $this->object->buildStatisticsAccessFilteredParticipantList()
794  );
795 
796  $ilUserCertificateRepository = new ilUserCertificateRepository($database, $logger);
797  $pdfGenerator = new ilPdfGenerator($ilUserCertificateRepository, $logger);
798 
799  $total_users = $this->object->evalTotalPersonsArray();
800  if (count($total_users)) {
801  $certValidator = new ilCertificateDownloadValidator();
802 
803  foreach ($total_users as $active_id => $name) {
804  $user_id = $this->object->_getUserIdFromActiveId($active_id);
805 
806  if (!$certValidator->isCertificateDownloadable($user_id, $objectId)) {
807  continue;
808  }
809 
810  $pdfAction = new ilCertificatePdfAction(
811  $logger,
812  $pdfGenerator,
814  $this->lng->txt('error_creating_certificate_pdf')
815  );
816 
817  $pdf = $pdfAction->createPDF($user_id, $objectId);
818  if (strlen($pdf)) {
819  $zipAction->addPDFtoArchiveDirectory($pdf, $archive_dir, $user_id . "_" . str_replace(
820  " ",
821  "_",
823  ) . ".pdf");
824  }
825  }
826  $zipArchive = $zipAction->zipCertificatesInArchiveDirectory($archive_dir, true);
827  }
828  }
829 
836  public function getEvaluationQuestionId($question_id, $original_id = "")
837  {
838  if ($original_id > 0) {
839  return $original_id;
840  } else {
841  return $question_id;
842  }
843  }
844 
852  public function outParticipantsPassDetails()
853  {
854  global $DIC;
855  $ilTabs = $DIC['ilTabs'];
856  $ilAccess = $DIC['ilAccess'];
857  $ilObjDataCache = $DIC['ilObjDataCache'];
858 
859  $active_id = (int) $this->testrequest->raw("active_id");
860 
861  if (!$this->getTestAccess()->checkResultsAccessForActiveId($active_id)) {
863  }
864 
865  $this->ctrl->saveParameter($this, "active_id");
866  $testSession = $this->testSessionFactory->getSession($active_id);
867 
868  // protect actives from other tests
869  if ($testSession->getTestId() != $this->object->getTestId()) {
871  }
872 
873  $this->ctrl->saveParameter($this, "pass");
874  $pass = (int) $this->testrequest->raw("pass");
875 
876  if ($this->testrequest->isset('statistics') && $this->testrequest->raw('statistics') == 1) {
877  $this->ctrl->setParameterByClass("ilTestEvaluationGUI", "active_id", $active_id);
878  $this->ctrl->saveParameter($this, 'statistics');
879 
880  $ilTabs->setBackTarget(
881  $this->lng->txt('back'),
882  $this->ctrl->getLinkTargetByClass('ilTestEvaluationGUI', 'detailedEvaluation')
883  );
884  } elseif ($this->object->getNrOfTries() == 1) {
885  $ilTabs->setBackTarget(
886  $this->lng->txt('back'),
887  $this->ctrl->getLinkTargetByClass('ilParticipantsTestResultsGUI')
888  );
889  } else {
890  $ilTabs->setBackTarget(
891  $this->lng->txt('tst_results_back_overview'),
892  $this->ctrl->getLinkTarget($this, 'outParticipantsResultsOverview')
893  );
894  }
895 
896  // prepare generation before contents are processed (for mathjax)
897  if ($this->isPdfDeliveryRequest()) {
899  }
900 
901  require_once 'Modules/Test/classes/class.ilTestResultHeaderLabelBuilder.php';
902  $testResultHeaderLabelBuilder = new ilTestResultHeaderLabelBuilder($this->lng, $ilObjDataCache);
903 
904  $objectivesList = null;
905 
906  if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
907  $testSequence = $this->testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $pass);
908  $testSequence->loadFromDb();
909  $testSequence->loadQuestions();
910 
911  require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php';
912  $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($testSession);
913 
914  $objectivesList = $this->buildQuestionRelatedObjectivesList($objectivesAdapter, $testSequence);
915  $objectivesList->loadObjectivesTitles();
916 
917  $testResultHeaderLabelBuilder->setObjectiveOrientedContainerId($testSession->getObjectiveOrientedContainerId());
918  $testResultHeaderLabelBuilder->setUserId($testSession->getUserId());
919  $testResultHeaderLabelBuilder->setTestObjId($this->object->getId());
920  $testResultHeaderLabelBuilder->setTestRefId($this->object->getRefId());
921  $testResultHeaderLabelBuilder->initObjectiveOrientedMode();
922  }
923 
924  $result_array = $this->getFilteredTestResult($active_id, $pass, false, !$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired());
925 
926  $overviewTableGUI = $this->getPassDetailsOverviewTableGUI(
927  $result_array,
928  $active_id,
929  $pass,
930  $this,
931  "outParticipantsPassDetails",
932  '',
933  true,
934  $objectivesList
935  );
936  $overviewTableGUI->setTitle($testResultHeaderLabelBuilder->getPassDetailsHeaderLabel($pass + 1));
937  $user_data = $this->getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, false);
938  $user_id = $this->object->_getUserIdFromActiveId($active_id);
939 
940  $template = new ilTemplate("tpl.il_as_tst_pass_details_overview_participants.html", true, true, "Modules/Test");
941 
942  $toolbar = $this->buildUserTestResultsToolbarGUI();
943 
944  $this->ctrl->setParameter($this, 'pdf', '1');
945  $toolbar->setPdfExportLinkTarget($this->ctrl->getLinkTarget($this, 'outParticipantsPassDetails'));
946  $this->ctrl->setParameter($this, 'pdf', '');
947 
948  if ($this->testrequest->isset('show_best_solutions')) {
949  ilSession::set('tst_results_show_best_solutions', true);
950  } elseif ($this->testrequest->isset('hide_best_solutions')) {
951  ilSession::set('tst_results_show_best_solutions', false);
952  } elseif (ilSession::get('tst_results_show_best_solutions') !== null) {
953  ilSession::clear('tst_results_show_best_solutions');
954  }
955 
956  if (ilSession::get('tst_results_show_best_solutions')) {
957  $this->ctrl->setParameter($this, 'hide_best_solutions', '1');
958  $toolbar->setHideBestSolutionsLinkTarget($this->ctrl->getLinkTarget($this, 'outParticipantsPassDetails'));
959  $this->ctrl->setParameter($this, 'hide_best_solutions', '');
960  } else {
961  $this->ctrl->setParameter($this, 'show_best_solutions', '1');
962  $toolbar->setShowBestSolutionsLinkTarget($this->ctrl->getLinkTarget($this, 'outParticipantsPassDetails'));
963  $this->ctrl->setParameter($this, 'show_best_solutions', '');
964  }
965 
966  $toolbar->build();
967  $template->setVariable('RESULTS_TOOLBAR', $this->ctrl->getHTML($toolbar));
968 
969  if ($this->isGradingMessageRequired() && $this->object->getNrOfTries() == 1) {
970  $gradingMessageBuilder = $this->getGradingMessageBuilder($active_id);
971  $gradingMessageBuilder->buildList();
972 
973  $template->setCurrentBlock('grading_message');
974  $template->setVariable('GRADING_MESSAGE', $gradingMessageBuilder->getList());
975  $template->parseCurrentBlock();
976  }
977 
978  $list_of_answers = $this->getPassListOfAnswers($result_array, $active_id, $pass, ilSession::get('tst_results_show_best_solutions'), false, false, false, true, $objectivesList, $testResultHeaderLabelBuilder);
979  $template->setVariable("LIST_OF_ANSWERS", $list_of_answers);
980  $template->setVariable("PASS_DETAILS", $this->ctrl->getHTML($overviewTableGUI));
981 
982  $data = $this->object->getCompleteEvaluationData();
983  $data->getParticipant($active_id)->setPassScoring($pass);
984  $result = $data->getParticipant($active_id)->getReached() . " " . strtolower($this->lng->txt("of")) . " " . $data->getParticipant($active_id)->getMaxpoints() . " (" . sprintf("%2.2f", $data->getParticipant($active_id)->getReachedPointsInPercent()) . " %" . ")";
985  $template->setCurrentBlock('total_score');
986  $template->setVariable("TOTAL_RESULT_TEXT", $this->lng->txt('tst_stat_result_resultspoints'));
987  $template->setVariable("TOTAL_RESULT", $result);
988  $template->parseCurrentBlock();
989 
990  if (!$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
991  $template->setVariable("USER_DATA", $user_data);
992 
993  $uname = $this->object->userLookupFullName($user_id);
994  $template->setVariable("TEXT_HEADING", sprintf($this->lng->txt("tst_result_user_name_pass"), $pass + 1, $uname));
995 
996  $template->setVariable("TEXT_RESULTS", $testResultHeaderLabelBuilder->getPassDetailsHeaderLabel($pass + 1));
997  }
998 
999  $template->setVariable("FORMACTION", $this->ctrl->getFormAction($this));
1000 
1001  $this->populateExamId($template, $active_id, $pass);
1002  $this->populatePassFinishDate($template, ilObjTest::lookupLastTestPassAccess($active_id, $pass));
1003 
1004  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print");
1005  if ($this->object->getShowSolutionAnswersOnly()) {
1006  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
1007  }
1008 
1009  if ($this->isPdfDeliveryRequest()) {
1010  //$this->object->deliverPDFfromHTML($template->get());
1011  ilTestPDFGenerator::generatePDF($template->get(), ilTestPDFGenerator::PDF_OUTPUT_DOWNLOAD, $this->object->getTitleFilenameCompliant(), PDF_USER_RESULT);
1012  } else {
1013  $this->tpl->setVariable("ADM_CONTENT", $template->get());
1014  }
1015  }
1016 
1023  {
1024  global $DIC;
1025  $ilTabs = $DIC['ilTabs'];
1026  $ilObjDataCache = $DIC['ilObjDataCache'];
1027 
1028  $active_id = (int) $this->testrequest->raw("active_id");
1029 
1030  if (!$this->getTestAccess()->checkResultsAccessForActiveId($active_id)) {
1032  }
1033 
1034  $testSession = $this->testSessionFactory->getSession($active_id);
1035 
1036  // protect actives from other tests
1037  if ($testSession->getTestId() != $this->object->getTestId()) {
1039  }
1040 
1041  if ($this->object->getNrOfTries() == 1) {
1042  $this->ctrl->setParameter($this, "active_id", $active_id);
1043  $this->ctrl->setParameter($this, "pass", ilObjTest::_getResultPass($active_id));
1044  $this->ctrl->redirect($this, "outParticipantsPassDetails");
1045  }
1046 
1047  $ilTabs->setBackTarget(
1048  $this->lng->txt('back'),
1049  $this->ctrl->getLinkTargetByClass(['ilObjTestGUI', 'ilTestResultsGUI', 'ilParticipantsTestResultsGUI'])
1050  );
1051 
1052  // prepare generation before contents are processed (for mathjax)
1053  if ($this->isPdfDeliveryRequest()) {
1055  }
1056 
1057  $template = new ilTemplate("tpl.il_as_tst_pass_overview_participants.html", true, true, "Modules/Test");
1058 
1059  $toolbar = $this->buildUserTestResultsToolbarGUI();
1060 
1061  $this->ctrl->setParameter($this, 'pdf', '1');
1062  $toolbar->setPdfExportLinkTarget($this->ctrl->getLinkTarget($this, __FUNCTION__));
1063  $this->ctrl->setParameter($this, 'pdf', '');
1064 
1065  $toolbar->build();
1066  $template->setVariable('RESULTS_TOOLBAR', $this->ctrl->getHTML($toolbar));
1067 
1068  require_once 'Modules/Test/classes/class.ilTestResultHeaderLabelBuilder.php';
1069  $testResultHeaderLabelBuilder = new ilTestResultHeaderLabelBuilder($this->lng, $ilObjDataCache);
1070  if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
1071  $testResultHeaderLabelBuilder->setObjectiveOrientedContainerId($testSession->getObjectiveOrientedContainerId());
1072  $testResultHeaderLabelBuilder->setUserId($testSession->getUserId());
1073  $testResultHeaderLabelBuilder->setTestObjId($this->object->getId());
1074  $testResultHeaderLabelBuilder->setTestRefId($this->object->getRefId());
1075  $testResultHeaderLabelBuilder->initObjectiveOrientedMode();
1076  }
1077 
1078  global $DIC; /* @var ILIAS\DI\Container $DIC */
1079  require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
1080  $testPassesSelector = new ilTestPassesSelector($DIC['ilDB'], $this->object);
1081  $testPassesSelector->setActiveId($testSession->getActiveId());
1082  $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
1083 
1084  $passOverViewTableGUI = $this->buildPassOverviewTableGUI($this);
1085  $passOverViewTableGUI->setActiveId($testSession->getActiveId());
1086  $passOverViewTableGUI->setResultPresentationEnabled(true);
1087  $passOverViewTableGUI->setPassDetailsCommand('outParticipantsPassDetails');
1088  $passOverViewTableGUI->init();
1089  $passOverViewTableGUI->setData($this->getPassOverviewTableData($testSession, $testPassesSelector->getExistingPasses(), true));
1090  $passOverViewTableGUI->setTitle($testResultHeaderLabelBuilder->getPassOverviewHeaderLabel());
1091  $template->setVariable("PASS_OVERVIEW", $passOverViewTableGUI->getHTML());
1092 
1093  if ($this->isGradingMessageRequired()) {
1094  $gradingMessageBuilder = $this->getGradingMessageBuilder($active_id);
1095  $gradingMessageBuilder->buildList();
1096 
1097  $template->setCurrentBlock('grading_message');
1098  $template->setVariable('GRADING_MESSAGE', $gradingMessageBuilder->getList());
1099  $template->parseCurrentBlock();
1100  }
1101 
1102  $user_data = $this->getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, true);
1103  $user_id = $this->object->_getUserIdFromActiveId($active_id);
1104 
1105  if (!$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
1106  if ($this->object->getAnonymity()) {
1107  $template->setVariable("TEXT_HEADING", $this->lng->txt("tst_result"));
1108  } else {
1109  $uname = $this->object->userLookupFullName($user_id, true);
1110  $template->setVariable("TEXT_HEADING", sprintf($this->lng->txt("tst_result_user_name"), $uname));
1111  $template->setVariable("USER_DATA", $user_data);
1112  }
1113  }
1114 
1115  $template->parseCurrentBlock();
1116 
1117 
1118  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print");
1119  if ($this->object->getShowSolutionAnswersOnly()) {
1120  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
1121  }
1122 
1123  if ($this->testrequest->isset("pdf") && ($this->testrequest->raw("pdf") == 1)) {
1124  //$this->object->deliverPDFfromHTML($template->get(), $this->object->getTitle());
1125 
1126  $name = ilObjUser::_lookupName($user_id);
1127  $filename = $name['lastname'] . '_' . $name['firstname'] . '_' . $name['login'] . '__' . $this->object->getTitleFilenameCompliant();
1129  //ilUtil::deliverData($file, ilUtil::getASCIIFilename($this->object->getTitle()) . ".pdf", "application/pdf", false, true);
1130  //$template->setVariable("PDF_FILE_LOCATION", $filename);
1131  } else {
1132  $this->tpl->setVariable("ADM_CONTENT", $template->get());
1133  }
1134  }
1135 
1137  {
1138  $tableGUI = $this->buildPassDetailsOverviewTableGUI($this, 'outUserPassDetails');
1139  $tableGUI->initFilter();
1140  $tableGUI->resetOffset();
1141  $tableGUI->writeFilterToSession();
1142  $this->outUserPassDetails();
1143  }
1144 
1146  {
1147  $tableGUI = $this->buildPassDetailsOverviewTableGUI($this, 'outUserPassDetails');
1148  $tableGUI->initFilter();
1149  $tableGUI->resetOffset();
1150  $tableGUI->resetFilter();
1151  $this->outUserPassDetails();
1152  }
1153 
1155  {
1156  $tableGUI = $this->buildPassDetailsOverviewTableGUI($this, 'outParticipantsPassDetails');
1157  $tableGUI->initFilter();
1158  $tableGUI->resetOffset();
1159  $tableGUI->writeFilterToSession();
1160  $this->outParticipantsPassDetails();
1161  }
1162 
1164  {
1165  $tableGUI = $this->buildPassDetailsOverviewTableGUI($this, 'outParticipantsPassDetails');
1166  $tableGUI->initFilter();
1167  $tableGUI->resetOffset();
1168  $tableGUI->resetFilter();
1169  $this->outParticipantsPassDetails();
1170  }
1171 
1177  public function outUserPassDetails()
1178  {
1179  $ilTabs = $this->tabs;
1180  $ilObjDataCache = $this->objCache;
1182 
1183  $ilTabs->clearSubTabs();
1184  $ilTabs->setBackTarget($this->lng->txt('tst_results_back_overview'), $this->ctrl->getLinkTarget($this));
1185 
1186  $testSession = $this->testSessionFactory->getSession();
1187 
1188  if (!$this->object->getShowPassDetails()) {
1189  $this->ctrl->redirectByClass("ilobjtestgui", "infoScreen");
1190  }
1191 
1192  $active_id = $testSession->getActiveId();
1193  $user_id = $testSession->getUserId();
1194 
1195  $this->ctrl->saveParameter($this, "pass");
1196  $pass = $this->testrequest->raw("pass");
1197 
1198  // prepare generation before contents are processed (for mathjax)
1199  if ($this->isPdfDeliveryRequest()) {
1201  }
1202 
1203  $testResultHeaderLabelBuilder = new ilTestResultHeaderLabelBuilder($this->lng, $ilObjDataCache);
1204 
1205  $objectivesList = null;
1206 
1207  $considerHiddenQuestions = true;
1208  $considerOptionalQuestions = true;
1209 
1210  if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
1211  $considerHiddenQuestions = false;
1212 
1213  $testSequence = $this->testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $pass);
1214  $testSequence->loadFromDb();
1215  $testSequence->loadQuestions();
1216 
1217  if ($this->object->isRandomTest() && !$testSequence->isAnsweringOptionalQuestionsConfirmed()) {
1218  $considerOptionalQuestions = false;
1219  }
1220 
1221  $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($testSession);
1222 
1223  $objectivesList = $this->buildQuestionRelatedObjectivesList($objectivesAdapter, $testSequence);
1224  $objectivesList->loadObjectivesTitles();
1225 
1226  $testResultHeaderLabelBuilder->setObjectiveOrientedContainerId($testSession->getObjectiveOrientedContainerId());
1227  $testResultHeaderLabelBuilder->setUserId($testSession->getUserId());
1228  $testResultHeaderLabelBuilder->setTestObjId($this->object->getId());
1229  $testResultHeaderLabelBuilder->setTestRefId($this->object->getRefId());
1230  $testResultHeaderLabelBuilder->initObjectiveOrientedMode();
1231  }
1232 
1233  $result_array = $this->getFilteredTestResult($active_id, $pass, $considerHiddenQuestions, $considerOptionalQuestions);
1234 
1235  $command_solution_details = "";
1236  if ($this->object->getShowSolutionDetails()) {
1237  $command_solution_details = "outCorrectSolution";
1238  }
1239 
1240  //$questionAnchorNav = $this->object->canShowSolutionPrintview();
1241  $questionAnchorNav =
1242  $this->object->getShowSolutionListOwnAnswers();
1243 
1244  $tpl = new ilTemplate('tpl.il_as_tst_pass_details_overview_participants.html', true, true, "Modules/Test");
1245 
1246  if (!$this->isPdfDeliveryRequest()) {
1247  $toolbar = $this->buildUserTestResultsToolbarGUI();
1248 
1249  $this->ctrl->setParameter($this, 'pdf', '1');
1250  $toolbar->setPdfExportLinkTarget($this->ctrl->getLinkTarget($this, 'outUserPassDetails'));
1251  $this->ctrl->setParameter($this, 'pdf', '');
1252 
1253  $validator = new ilCertificateDownloadValidator();
1254  if ($validator->isCertificateDownloadable($user_id, $this->object->getId())) {
1255  $toolbar->setCertificateLinkTarget($this->ctrl->getLinkTarget($this, 'outCertificate'));
1256  }
1257 
1258  $toolbar->build();
1259 
1260  $tpl->setVariable('RESULTS_TOOLBAR', $this->ctrl->getHTML($toolbar));
1261 
1262  $tpl->setCurrentBlock('signature');
1263  $tpl->setVariable("SIGNATURE", $this->getResultsSignature());
1264  $tpl->parseCurrentBlock();
1265 
1266  if ($this->object->isShowExamIdInTestResultsEnabled()) {
1267  $tpl->setVariable('EXAM_ID', ilObjTest::lookupExamId(
1268  $testSession->getActiveId(),
1269  $pass
1270  ));
1271  $tpl->setVariable('EXAM_ID_TXT', $this->lng->txt('exam_id'));
1272  }
1273  }
1274 
1275  if (!$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired() &&
1276  $this->isGradingMessageRequired() && $this->object->getNrOfTries() == 1) {
1277  $gradingMessageBuilder = $this->getGradingMessageBuilder($active_id);
1278  $gradingMessageBuilder->buildMessage();
1279  $gradingMessageBuilder->sendMessage();
1280  }
1281 
1282  $overviewTableGUI = $this->getPassDetailsOverviewTableGUI(
1283  $result_array,
1284  $active_id,
1285  $pass,
1286  $this,
1287  "outUserPassDetails",
1288  $command_solution_details,
1289  $questionAnchorNav,
1290  $objectivesList
1291  );
1292  $overviewTableGUI->setTitle($testResultHeaderLabelBuilder->getPassDetailsHeaderLabel($pass + 1));
1293  $tpl->setVariable("PASS_DETAILS", $this->ctrl->getHTML($overviewTableGUI));
1294 
1295  $data = $this->object->getCompleteEvaluationData();
1296  $reached = $data->getParticipant($active_id)->getPass($pass)->getReachedPoints();
1297  $max = $data->getParticipant($active_id)->getPass($pass)->getMaxPoints();
1298  $percent = $max ? $reached / $max * 100.0 : 0;
1299  $result = $data->getParticipant($active_id)->getPass($pass)->getReachedPoints() . " " . strtolower($this->lng->txt("of")) . " " . $data->getParticipant($active_id)->getPass($pass)->getMaxPoints() . " (" . sprintf("%2.2f", $percent) . " %" . ")";
1300  $tpl->setCurrentBlock('total_score');
1301  $tpl->setVariable("TOTAL_RESULT_TEXT", $this->lng->txt('tst_stat_result_resultspoints'));
1302  $tpl->setVariable("TOTAL_RESULT", $result);
1303  $tpl->parseCurrentBlock();
1304 
1305  if ($this->object->getShowSolutionListOwnAnswers()) {
1306  $list_of_answers = $this->getPassListOfAnswers(
1307  $result_array,
1308  $active_id,
1309  $pass,
1310  $this->object->getShowSolutionListComparison(),
1311  false,
1312  false,
1313  false,
1314  true,
1315  $objectivesList,
1316  $testResultHeaderLabelBuilder
1317  );
1318  $tpl->setVariable("LIST_OF_ANSWERS", $list_of_answers);
1319  }
1320 
1321  $tpl->setVariable("TEXT_RESULTS", $testResultHeaderLabelBuilder->getPassDetailsHeaderLabel($pass + 1));
1322  $tpl->setVariable("FORMACTION", $this->ctrl->getFormAction($this));
1323 
1324  $uname = $this->object->userLookupFullName($user_id, true);
1325  $user_data = $this->getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, true);
1326  if (!$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
1327  if ($this->object->getAnonymity()) {
1328  $tpl->setVariable("TEXT_HEADING", $this->lng->txt("tst_result_pass"));
1329  } else {
1330  $tpl->setVariable("TEXT_HEADING", sprintf($this->lng->txt("tst_result_user_name_pass"), $pass + 1, $uname));
1331  $tpl->setVariable("USER_DATA", $user_data);
1332  }
1333  }
1334 
1335  $this->populateExamId($tpl, $active_id, (int) $pass);
1337 
1338  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print");
1339  if ($this->object->getShowSolutionAnswersOnly()) {
1340  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
1341  }
1342 
1343  if ($this->isPdfDeliveryRequest()) {
1344  ilTestPDFGenerator::generatePDF($tpl->get(), ilTestPDFGenerator::PDF_OUTPUT_DOWNLOAD, $this->object->getTitleFilenameCompliant(), PDF_USER_RESULT);
1345  } else {
1346  $this->tpl->setContent($tpl->get());
1347  }
1348  }
1349 
1355  public function outUserResultsOverview()
1356  {
1357  global $DIC;
1358  $ilUser = $DIC['ilUser'];
1359  $ilObjDataCache = $DIC['ilObjDataCache'];
1360 
1361  $testSession = $this->testSessionFactory->getSession();
1362  $active_id = $testSession->getActiveId();
1363  $user_id = $ilUser->getId();
1364  $uname = $this->object->userLookupFullName($user_id, true);
1365 
1366  if (!$this->object->canShowTestResults($testSession)) {
1367  $this->ctrl->redirectByClass("ilobjtestgui", "infoScreen");
1368  }
1369 
1370  // prepare generation before contents are processed (for mathjax)
1371  if ($this->isPdfDeliveryRequest()) {
1373  }
1374 
1375  $templatehead = new ilTemplate("tpl.il_as_tst_results_participants.html", true, true, "Modules/Test");
1376  $template = new ilTemplate("tpl.il_as_tst_results_participant.html", true, true, "Modules/Test");
1377 
1378  $toolbar = $this->buildUserTestResultsToolbarGUI();
1379 
1380  $this->ctrl->setParameter($this, 'pdf', '1');
1381  $toolbar->setPdfExportLinkTarget($this->ctrl->getLinkTarget($this, 'outUserResultsOverview'));
1382  $this->ctrl->setParameter($this, 'pdf', '');
1383 
1384  $validator = new ilCertificateDownloadValidator();
1385  if ($validator->isCertificateDownloadable($user_id, $this->object->getId())) {
1386  $toolbar->setCertificateLinkTarget($this->ctrl->getLinkTarget($this, 'outCertificate'));
1387  }
1388 
1389  $toolbar->build();
1390 
1391  $templatehead->setVariable('RESULTS_TOOLBAR', $this->ctrl->getHTML($toolbar));
1392 
1393  $passDetailsEnabled = $this->object->getShowPassDetails();
1394  #if (!$passDetailsEnabled)
1395  #{
1396  # $executable = $this->object->isExecutable($testSession, $ilUser->getId());
1397  # if (!$executable["executable"]) $passDetailsEnabled = true;
1398  #}
1399 
1400  require_once 'Modules/Test/classes/class.ilTestResultHeaderLabelBuilder.php';
1401  $testResultHeaderLabelBuilder = new ilTestResultHeaderLabelBuilder($this->lng, $ilObjDataCache);
1402  if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
1403  $testResultHeaderLabelBuilder->setObjectiveOrientedContainerId($testSession->getObjectiveOrientedContainerId());
1404  $testResultHeaderLabelBuilder->setUserId($testSession->getUserId());
1405  $testResultHeaderLabelBuilder->setTestObjId($this->object->getId());
1406  $testResultHeaderLabelBuilder->setTestRefId($this->object->getRefId());
1407  $testResultHeaderLabelBuilder->initObjectiveOrientedMode();
1408  }
1409 
1410  $template->setCurrentBlock("pass_overview");
1411 
1412  global $DIC; /* @var ILIAS\DI\Container $DIC */
1413  require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
1414  $testPassesSelector = new ilTestPassesSelector($DIC['ilDB'], $this->object);
1415  $testPassesSelector->setActiveId($testSession->getActiveId());
1416  $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
1417 
1418  $passOverViewTableGUI = $this->buildPassOverviewTableGUI($this);
1419  $passOverViewTableGUI->setActiveId($testSession->getActiveId());
1420  $passOverViewTableGUI->setResultPresentationEnabled(true);
1421  if ($passDetailsEnabled) {
1422  $passOverViewTableGUI->setPassDetailsCommand('outUserPassDetails');
1423  }
1424  if ($this->object->isPassDeletionAllowed()) {
1425  $passOverViewTableGUI->setPassDeletionCommand('confirmDeletePass');
1426  }
1427  $passOverViewTableGUI->init();
1428  $passOverViewTableGUI->setData($this->getPassOverviewTableData($testSession, $testPassesSelector->getReportablePasses(), true));
1429  $passOverViewTableGUI->setTitle($testResultHeaderLabelBuilder->getPassOverviewHeaderLabel());
1430  $overview = $passOverViewTableGUI->getHTML();
1431  if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
1432  require_once 'Modules/Test/classes/class.ilTestLearningObjectivesStatusGUI.php';
1433  $loStatus = new ilTestLearningObjectivesStatusGUI($this->lng);
1434  $loStatus->setCrsObjId($this->getObjectiveOrientedContainer()->getObjId());
1435  $loStatus->setUsrId($testSession->getUserId());
1436  $overview .= "<br />" . $loStatus->getHTML();
1437  }
1438  $template->setVariable("PASS_OVERVIEW", $overview);
1439  $template->parseCurrentBlock();
1440 
1441  if ($this->isGradingMessageRequired()) {
1442  $gradingMessageBuilder = $this->getGradingMessageBuilder($active_id);
1443  $gradingMessageBuilder->buildMessage();
1444  $gradingMessageBuilder->sendMessage();
1445  }
1446 
1447  $user_data = $this->getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, true);
1448 
1449  if (!$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
1450  if ($this->object->getAnonymity()) {
1451  $template->setVariable("TEXT_HEADING", $this->lng->txt("tst_result"));
1452  } else {
1453  $template->setVariable("TEXT_HEADING", sprintf($this->lng->txt("tst_result_user_name"), $uname));
1454  $template->setVariable("USER_DATA", $user_data);
1455  }
1456  }
1457 
1458  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print");
1459  if ($this->object->getShowSolutionAnswersOnly()) {
1460  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
1461  }
1462  $templatehead->setVariable("RESULTS_PARTICIPANT", $template->get());
1463 
1464  if ($this->isPdfDeliveryRequest()) {
1465  ilTestPDFGenerator::generatePDF($template->get(), ilTestPDFGenerator::PDF_OUTPUT_DOWNLOAD, $this->object->getTitleFilenameCompliant(), PDF_USER_RESULT);
1466  } else {
1467  $this->tpl->setContent($templatehead->get());
1468  }
1469  }
1470 
1478  public function outUserListOfAnswerPasses()
1479  {
1480  global $DIC; /* @var ILIAS\DI\Container $DIC */
1481  $ilUser = $DIC['ilUser'];
1482  $ilObjDataCache = $DIC['ilObjDataCache'];
1483 
1484  if (!$this->object->getShowSolutionPrintview()) {
1485  $this->tpl->setOnScreenMessage('info', $this->lng->txt("no_permission"), true);
1486  $this->ctrl->redirectByClass("ilobjtestgui", "infoScreen");
1487  }
1488 
1489  $template = new ilTemplate("tpl.il_as_tst_info_list_of_answers.html", true, true, "Modules/Test");
1490 
1491  $pass = null;
1492  if ($this->testrequest->isset("pass")) {
1493  if (strlen($this->testrequest->raw("pass"))) {
1494  $pass = $this->testrequest->raw("pass");
1495  }
1496  }
1497  $user_id = $ilUser->getId();
1498 
1499  $testSession = $this->testSessionFactory->getSession();
1500  $active_id = $testSession->getActiveId();
1501 
1502  $template->setVariable("TEXT_RESULTS", $this->lng->txt("tst_passes"));
1503 
1504  $testPassesSelector = new ilTestPassesSelector($this->db, $this->object);
1505  $testPassesSelector->setActiveId($testSession->getActiveId());
1506  $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
1507 
1508  $passOverViewTableGUI = $this->buildPassOverviewTableGUI($this);
1509  $passOverViewTableGUI->setActiveId($testSession->getActiveId());
1510  $passOverViewTableGUI->setResultPresentationEnabled(false);
1511  $passOverViewTableGUI->setPassDetailsCommand('outUserListOfAnswerPasses');
1512  $passOverViewTableGUI->init();
1513  $passOverViewTableGUI->setData($this->getPassOverviewTableData($testSession, $testPassesSelector->getClosedPasses(), false));
1514  $template->setVariable("PASS_OVERVIEW", $passOverViewTableGUI->getHTML());
1515 
1516  $signature = "";
1517  if (strlen($pass)) {
1518  $testResultHeaderLabelBuilder = new ilTestResultHeaderLabelBuilder($this->lng, $ilObjDataCache);
1519 
1520  $objectivesList = null;
1521 
1522  if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) {
1523  $testSequence = $this->testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $pass);
1524  $testSequence->loadFromDb();
1525  $testSequence->loadQuestions();
1526 
1527  $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($testSession);
1528 
1529  $objectivesList = $this->buildQuestionRelatedObjectivesList($objectivesAdapter, $testSequence);
1530  $objectivesList->loadObjectivesTitles();
1531 
1532  $testResultHeaderLabelBuilder->setObjectiveOrientedContainerId($testSession->getObjectiveOrientedContainerId());
1533  $testResultHeaderLabelBuilder->setUserId($testSession->getUserId());
1534  $testResultHeaderLabelBuilder->setTestObjId($this->object->getId());
1535  $testResultHeaderLabelBuilder->setTestRefId($this->object->getRefId());
1536  $testResultHeaderLabelBuilder->initObjectiveOrientedMode();
1537  }
1538 
1539  $result_array = $this->object->getTestResult(
1540  $active_id,
1541  $pass,
1542  false,
1543  !$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()
1544  );
1545 
1546  $signature = $this->getResultsSignature();
1547  $user_id = $this->object->_getUserIdFromActiveId($active_id);
1548  $showAllAnswers = true;
1549  if ($this->object->isExecutable($testSession, $user_id)) {
1550  $showAllAnswers = false;
1551  }
1552  $this->setContextResultPresentation(false);
1553  $answers = $this->getPassListOfAnswers($result_array, $active_id, $pass, false, $showAllAnswers, false, false, false, $objectivesList, $testResultHeaderLabelBuilder);
1554  $template->setVariable("PASS_DETAILS", $answers);
1555  }
1556  $template->setVariable("FORMACTION", $this->ctrl->getFormAction($this));
1557  $template->setVariable("PRINT_TEXT", $this->lng->txt("print"));
1558  $template->setVariable("PRINT_URL", "javascript:window.print();");
1559 
1560  $user_data = $this->getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, true);
1561  $template->setVariable("USER_DATA", $user_data);
1562  $template->setVariable("TEXT_LIST_OF_ANSWERS", $this->lng->txt("tst_list_of_answers"));
1563  if (strlen($signature)) {
1564  $template->setVariable("SIGNATURE", $signature);
1565  }
1566  if (!is_null($pass) && $this->object->isShowExamIdInTestResultsEnabled()) {
1567  $template->setCurrentBlock('exam_id_footer');
1568  $template->setVariable('EXAM_ID_VAL', ilObjTest::lookupExamId(
1569  $testSession->getActiveId(),
1570  $pass
1571  ));
1572  $template->setVariable('EXAM_ID_TXT', $this->lng->txt('exam_id'));
1573  $template->parseCurrentBlock();
1574  }
1575  $this->tpl->setVariable("ADM_CONTENT", $template->get());
1576 
1577  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print");
1578  if ($this->object->getShowSolutionAnswersOnly()) {
1579  $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print");
1580  }
1581  }
1582 
1590  public function passDetails()
1591  {
1592  // @PHP8-CR: With this probably never working and no detectable usages, it would be a candidate for removal...
1593  // Second opinion here, please, if it can go away.
1594  if ($this->testrequest->isset("pass") && (strlen($this->testrequest->raw("pass")) > 0)) {
1595  $this->ctrl->saveParameter($this, "pass");
1596  $this->ctrl->saveParameter($this, "active_id");
1597  $this->outTestResults(false, $this->testrequest->raw("pass"));
1598  } else {
1599  $this->outTestResults(false);
1600  }
1601  }
1602 
1607  public function singleResults()
1608  {
1609  global $DIC; /* @var ILIAS\DI\Container $DIC */
1610 
1611  if (!$this->getTestAccess()->checkStatisticsAccess()) {
1613  }
1614 
1615  $this->object->setAccessFilteredParticipantList(
1616  $this->object->buildStatisticsAccessFilteredParticipantList()
1617  );
1618 
1619  $DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_STATISTICS);
1620 
1621  $data = $this->object->getCompleteEvaluationData();
1622  $color_class = array("tblrow1", "tblrow2");
1623  $counter = 0;
1624  $this->tpl->addBlockFile("ADM_CONTENT", "adm_content", "tpl.il_as_tst_eval_single_answers.html", "Modules/Test");
1625  $foundParticipants = $data->getParticipants();
1626  if (count($foundParticipants) == 0) {
1627  $this->tpl->setOnScreenMessage('info', $this->lng->txt("tst_no_evaluation_data"));
1628  return;
1629  } else {
1630  $rows = array();
1631  foreach ($data->getQuestionTitles() as $question_id => $question_title) {
1632  $answered = 0;
1633  $reached = 0;
1634  $max = 0;
1635  foreach ($foundParticipants as $userdata) {
1636  $pass = $userdata->getScoredPass();
1637  if (is_object($userdata->getPass($pass))) {
1638  $question = $userdata->getPass($pass)->getAnsweredQuestionByQuestionId($question_id);
1639  if (is_array($question)) {
1640  $answered++;
1641  }
1642  }
1643  }
1644  $counter++;
1645  $this->ctrl->setParameter($this, "qid", $question_id);
1646  require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
1647  $question_object = assQuestion::instantiateQuestion($question_id);
1648  $download = "";
1649  if ($question_object instanceof ilObjFileHandlingQuestionType) {
1650  if ($question_object->hasFileUploads($this->object->getTestId())) {
1651  $download = "<a href=\"" . $this->ctrl->getLinkTarget($this, "exportFileUploadsForAllParticipants") . "\">" . $this->lng->txt("download") . "</a>";
1652  }
1653  }
1654  array_push(
1655  $rows,
1656  array(
1657  'qid' => $question_id,
1658  'question_title' => $this->refinery->string()->stripTags()->transform($question_title),
1659  'number_of_answers' => $answered,
1660  'output' => "<a href=\"" . $this->ctrl->getLinkTarget($this, "exportQuestionForAllParticipants") . "\">" . $this->lng->txt("pdf_export") . "</a>",
1661  'file_uploads' => $download
1662  )
1663  );
1664  }
1665  if (count($rows)) {
1666  require_once './Modules/Test/classes/tables/class.ilResultsByQuestionTableGUI.php';
1667  $table_gui = new ilResultsByQuestionTableGUI($this, "singleResults");
1668  $table_gui->setTitle($this->lng->txt("tst_answered_questions_test"));
1669  $table_gui->setData($rows);
1670 
1671  $this->tpl->setVariable("TBL_SINGLE_ANSWERS", $table_gui->getHTML());
1672  } else {
1673  $this->tpl->setVariable("TBL_SINGLE_ANSWERS", $this->lng->txt("adm_no_special_users"));
1674  }
1675  }
1676  }
1677 
1681  public function outCertificate()
1682  {
1683  global $DIC;
1684 
1685  $user = $DIC->user();
1686  $database = $DIC->database();
1687  $logger = $DIC->logger()->root();
1688 
1689  $ilUserCertificateRepository = new ilUserCertificateRepository($database, $logger);
1690  $pdfGenerator = new ilPdfGenerator($ilUserCertificateRepository, $logger);
1691 
1692  $pdfAction = new ilCertificatePdfAction(
1693  $logger,
1694  $pdfGenerator,
1696  $this->lng->txt('error_creating_certificate_pdf')
1697  );
1698 
1699  $pdfAction->downloadPdf($user->getId(), $this->object->getId());
1700  }
1701 
1702  public function confirmDeletePass()
1703  {
1704  if ($this->testrequest->isset('context') && strlen($this->testrequest->raw('context'))) {
1705  $context = $this->testrequest->raw('context');
1706  } else {
1708  }
1709 
1710  if (!$this->object->isPassDeletionAllowed() && !$this->object->isDynamicTest()) {
1712  }
1713 
1714  require_once 'Modules/Test/classes/confirmations/class.ilTestPassDeletionConfirmationGUI.php';
1715 
1716  $confirm = new ilTestPassDeletionConfirmationGUI($this->ctrl, $this->lng, $this);
1717  $confirm->build((int) $this->testrequest->raw("active_id"), (int) $this->testrequest->raw("pass"), $context);
1718 
1719  global $DIC;
1720  $tpl = $DIC['tpl'];
1721  $tpl->setContent($this->ctrl->getHTML($confirm));
1722  }
1723 
1724  public function cancelDeletePass()
1725  {
1726  $this->redirectToPassDeletionContext($_POST['context']);
1727  }
1728 
1730  {
1731  require_once 'Modules/Test/classes/confirmations/class.ilTestPassDeletionConfirmationGUI.php';
1732 
1733  switch ($context) {
1735 
1736  $this->ctrl->redirect($this, 'outUserResultsOverview');
1737 
1738  // no break
1740 
1741  $this->ctrl->redirectByClass('ilObjTestGUI', 'infoScreen');
1742 
1743  // no break
1745 
1746  $this->ctrl->redirectByClass('ilTestPlayerDynamicQuestionSetGUI', 'startTest');
1747  }
1748  }
1749 
1750  public function performDeletePass()
1751  {
1752  if (isset($_POST['context']) && strlen($_POST['context'])) {
1753  $context = $_POST['context'];
1754  } else {
1756  }
1757 
1758  if (!$this->object->isPassDeletionAllowed() && !$this->object->isDynamicTest()) {
1760  }
1762  global $DIC;
1763  $ilDB = $DIC['ilDB'];
1764 
1765  $active_fi = null;
1766  $pass = null;
1767 
1768  if (isset($_POST['active_id']) && (int) $_POST['active_id']) {
1769  $active_fi = $_POST['active_id'];
1770  }
1771 
1772  if (isset($_POST['pass']) && is_numeric($_POST['pass'])) {
1773  $pass = $_POST['pass'];
1774  }
1775 
1776  if (is_null($active_fi) || is_null($pass)) {
1777  $this->ctrl->redirect($this, 'outUserResultsOverview');
1778  }
1779 
1780  if (!$this->object->isDynamicTest() && $pass == $this->object->_getResultPass($active_fi)) {
1781  $this->ctrl->redirect($this, 'outUserResultsOverview');
1782  }
1783 
1784  // Get information
1785  $result = $ilDB->query("
1786  SELECT tst_active.tries, tst_active.last_finished_pass, tst_sequence.pass
1787  FROM tst_active
1788  LEFT JOIN tst_sequence
1789  ON tst_sequence.active_fi = tst_active.active_id
1790  AND tst_sequence.pass = tst_active.tries
1791  WHERE tst_active.active_id = {$ilDB->quote($active_fi, 'integer')}
1792  ");
1793 
1794  $row = $ilDB->fetchAssoc($result);
1795 
1796  $tries = $row['tries'];
1797  $lastFinishedPass = is_numeric($row['last_finished_pass']) ? $row['last_finished_pass'] : -1;
1798 
1799  if ($pass < $lastFinishedPass) {
1800  $isActivePass = false;
1801  $must_renumber = true;
1802  } elseif ($pass == $lastFinishedPass) {
1803  $isActivePass = false;
1804 
1805  if ($tries == $row['pass']) {
1806  $must_renumber = true;
1807  } else {
1808  $must_renumber = false;
1809  }
1810  } elseif ($pass == $row['pass']) {
1811  $isActivePass = true;
1812  $must_renumber = false;
1813  } else {
1814  throw new ilTestException('This should not happen, please contact Bjoern Heyser to clean up this pass salad!');
1815  }
1816 
1817  if (!$this->object->isDynamicTest() && $isActivePass) {
1818  $this->ctrl->redirect($this, 'outUserResultsOverview');
1819  }
1820 
1821  if ($pass == 0 && (
1822  ($lastFinishedPass == 0 && $tries == 1 && $tries != $row['pass'])
1823  || ($isActivePass == true) // should be equal to || ($lastFinishedPass == -1 && $tries == 0)
1824  )) {
1825  $last_pass = true;
1826  } else {
1827  $last_pass = false;
1828  }
1829 
1830  // Work on tables:
1831  // tst_active
1832  if ($last_pass) {
1833  $ilDB->manipulate(
1834  'DELETE
1835  FROM tst_active
1836  WHERE active_id = ' . $ilDB->quote($active_fi, 'integer')
1837  );
1838  } elseif (!$isActivePass) {
1839  $ilDB->manipulate(
1840  'UPDATE tst_active
1841  SET tries = ' . $ilDB->quote($tries - 1, 'integer') . ',
1842  last_finished_pass = ' . $ilDB->quote($lastFinishedPass - 1, 'integer') . '
1843  WHERE active_id = ' . $ilDB->quote($active_fi, 'integer')
1844  );
1845  }
1846  // tst_manual_fb
1847  $ilDB->manipulate(
1848  'DELETE
1849  FROM tst_manual_fb
1850  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1851  AND pass = ' . $ilDB->quote($pass, 'integer')
1852  );
1853 
1854  if ($must_renumber) {
1855  $ilDB->manipulate(
1856  'UPDATE tst_manual_fb
1857  SET pass = pass - 1
1858  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1859  AND pass > ' . $ilDB->quote($pass, 'integer')
1860  );
1861  }
1862 
1863  // tst_mark -> nothing to do
1864  //
1865  // tst_pass_result
1866  $ilDB->manipulate(
1867  'DELETE
1868  FROM tst_pass_result
1869  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1870  AND pass = ' . $ilDB->quote($pass, 'integer')
1871  );
1872 
1873  if ($must_renumber) {
1874  $ilDB->manipulate(
1875  'UPDATE tst_pass_result
1876  SET pass = pass - 1
1877  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1878  AND pass > ' . $ilDB->quote($pass, 'integer')
1879  );
1880  }
1881 
1882  // tst_qst_solved -> nothing to do
1883 
1884  // tst_rnd_copy -> nothing to do
1885  // tst_rnd_qpl_title -> nothing to do
1886 
1887  // tst_sequence
1888  $ilDB->manipulate(
1889  'DELETE
1890  FROM tst_sequence
1891  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1892  AND pass = ' . $ilDB->quote($pass, 'integer')
1893  );
1894 
1895  if ($must_renumber) {
1896  $ilDB->manipulate(
1897  'UPDATE tst_sequence
1898  SET pass = pass - 1
1899  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1900  AND pass > ' . $ilDB->quote($pass, 'integer')
1901  );
1902  }
1903 
1904  if ($this->object->isDynamicTest()) {
1905  $tables = array(
1906  'tst_seq_qst_tracking', 'tst_seq_qst_answstatus', 'tst_seq_qst_postponed', 'tst_seq_qst_checked'
1907  );
1908 
1909  foreach ($tables as $table) {
1910  $ilDB->manipulate("
1911  DELETE FROM $table
1912  WHERE active_fi = {$ilDB->quote($active_fi, 'integer')}
1913  AND pass = {$ilDB->quote($pass, 'integer')}
1914  ");
1915 
1916  if ($must_renumber) {
1917  $ilDB->manipulate("
1918  UPDATE $table
1919  SET pass = pass - 1
1920  WHERE active_fi = {$ilDB->quote($active_fi, 'integer')}
1921  AND pass > {$ilDB->quote($pass, 'integer')}
1922  ");
1923  }
1924  }
1925  }
1926 
1927  // tst_solutions
1928  $ilDB->manipulate(
1929  'DELETE
1930  FROM tst_solutions
1931  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1932  AND pass = ' . $ilDB->quote($pass, 'integer')
1933  );
1934 
1935  if ($must_renumber) {
1936  $ilDB->manipulate(
1937  'UPDATE tst_solutions
1938  SET pass = pass - 1
1939  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1940  AND pass > ' . $ilDB->quote($pass, 'integer')
1941  );
1942  }
1943 
1944  // tst_test_result
1945  $ilDB->manipulate(
1946  'DELETE
1947  FROM tst_test_result
1948  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1949  AND pass = ' . $ilDB->quote($pass, 'integer')
1950  );
1951 
1952  if ($must_renumber) {
1953  $ilDB->manipulate(
1954  'UPDATE tst_test_result
1955  SET pass = pass - 1
1956  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1957  AND pass > ' . $ilDB->quote($pass, 'integer')
1958  );
1959  }
1960 
1961  // qpl_hint_tracking
1962  $ilDB->manipulate(
1963  'DELETE
1964  FROM qpl_hint_tracking
1965  WHERE qhtr_active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1966  AND qhtr_pass = ' . $ilDB->quote($pass, 'integer')
1967  );
1968 
1969  if ($must_renumber) {
1970  $ilDB->manipulate(
1971  'UPDATE qpl_hint_tracking
1972  SET qhtr_pass = qhtr_pass - 1
1973  WHERE qhtr_active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1974  AND qhtr_pass > ' . $ilDB->quote($pass, 'integer')
1975  );
1976  }
1977 
1978  // tst_test_rnd_qst -> nothing to do
1979 
1980  // tst_times
1981  $ilDB->manipulate(
1982  'DELETE
1983  FROM tst_times
1984  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1985  AND pass = ' . $ilDB->quote($pass, 'integer')
1986  );
1987 
1988  if ($must_renumber) {
1989  $ilDB->manipulate(
1990  'UPDATE tst_times
1991  SET pass = pass - 1
1992  WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
1993  AND pass > ' . $ilDB->quote($pass, 'integer')
1994  );
1995  }
1996 
1997  require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
1999  $this->object->logAction($this->lng->txtlng("assessment", "log_deleted_pass", ilObjAssessmentFolder::_getLogLanguage()));
2000  }
2001  // tst_result_cache
2002  // Ggfls. nur renumbern.
2003  require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
2005 
2006  if ($this->object->isDynamicTest()) {
2007  require_once 'Modules/Test/classes/tables/class.ilTestDynamicQuestionSetStatisticTableGUI.php';
2009  }
2010 
2012  }
2013 
2014  protected function getFilteredTestResult($active_id, $pass, $considerHiddenQuestions, $considerOptionalQuestions): array
2015  {
2016  global $DIC;
2017  $ilDB = $DIC['ilDB'];
2018  $component_repository = $DIC['component.repository'];
2019 
2020  $resultData = $this->object->getTestResult($active_id, $pass, false, $considerHiddenQuestions);
2021  $questionIds = array();
2022  foreach ($resultData as $resultItemKey => $resultItemValue) {
2023  if ($resultItemKey === 'test' || $resultItemKey === 'pass') {
2024  continue;
2025  }
2026 
2027  $questionIds[] = $resultItemValue['qid'];
2028  }
2029 
2030  $table_gui = $this->buildPassDetailsOverviewTableGUI($this, 'outUserPassDetails');
2031  $table_gui->initFilter();
2032 
2033  $questionList = new ilAssQuestionList($ilDB, $this->lng, $this->refinery, $component_repository);
2034  $questionList->setParentObjId($this->object->getId());
2035  $questionList->setParentObjectType($this->object->getType());
2036  $questionList->setIncludeQuestionIdsFilter($questionIds);
2037  $questionList->setQuestionInstanceTypeFilter(null);
2038 
2039  foreach ($table_gui->getFilterItems() as $item) {
2040  if (substr($item->getPostVar(), 0, strlen('tax_')) == 'tax_') {
2041  $v = $item->getValue();
2042 
2043  if (is_array($v) && count($v) && !(int) $v[0]) {
2044  continue;
2045  }
2046 
2047  $taxId = substr($item->getPostVar(), strlen('tax_'));
2048  $questionList->addTaxonomyFilter($taxId, $item->getValue(), $this->object->getId(), 'tst');
2049  } elseif ($item->getValue() !== false) {
2050  $questionList->addFieldFilter($item->getPostVar(), $item->getValue());
2051  }
2052  }
2053 
2054  $questionList->load();
2055 
2056  $filteredTestResult = array();
2057 
2058  foreach ($resultData as $resultItemKey => $resultItemValue) {
2059  if ($resultItemKey === 'test' || $resultItemKey === 'pass') {
2060  continue;
2061  }
2062 
2063  if (!$questionList->isInList($resultItemValue['qid'])) {
2064  continue;
2065  }
2066 
2067  $filteredTestResult[] = $resultItemValue;
2068  }
2069 
2070  return $filteredTestResult;
2071  }
2072 
2074  {
2075  $activeId = (int) $this->testrequest->raw("active_id");
2077 
2078  $participantData = new ilTestParticipantData($this->db, $this->lng);
2079  $participantData->setActiveIdsFilter(array($activeId));
2080  $participantData->setParticipantAccessFilter($accessFilter);
2081  $participantData->load($this->object->getTestId());
2082 
2083  if (!in_array($activeId, $participantData->getActiveIds())) {
2085  }
2086 
2087  $testSession = new ilTestSession();
2088  $testSession->loadFromDb($activeId);
2089 
2090  if ($testSession->isSubmitted()) {
2091  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('tst_already_submitted'), true);
2093  }
2094 
2095  if (($this->object->isEndingTimeEnabled() || $this->object->getEnableProcessingTime())
2096  && !$this->object->endingTimeReached()
2097  && !$this->object->isMaxProcessingTimeReached(
2098  $this->object->getStartingTimeOfUser($activeId),
2099  $activeId
2100  )) {
2101  $this->tpl->setOnScreenMessage('info', $this->lng->txt('finish_pass_for_user_in_processing_time'));
2102  }
2103 
2104  $cgui = new ilConfirmationGUI();
2105 
2106  $cgui->setHeaderText(sprintf(
2107  $this->lng->txt("finish_pass_for_user_confirmation"),
2108  $participantData->getFormatedFullnameByActiveId($activeId)
2109  ));
2110 
2111  $this->ctrl->setParameter($this, 'active_id', $activeId);
2112  $cgui->setFormAction($this->ctrl->getFormAction($this, "participants"));
2113 
2114  $cgui->setCancel($this->lng->txt("cancel"), "redirectBackToParticipantsScreen");
2115  $cgui->setConfirm($this->lng->txt("proceed"), "confirmFinishTestPassForUser");
2116 
2117  $this->tpl->setContent($cgui->getHTML());
2118  }
2119 
2121  {
2122  $activeId = (int) $this->testrequest->raw("active_id");
2123 
2124  require_once 'Modules/Test/classes/class.ilTestParticipantAccessFilter.php';
2126 
2127  require_once 'Modules/Test/classes/class.ilTestParticipantList.php';
2128  $participantData = new ilTestParticipantData($this->db, $this->lng);
2129  $participantData->setActiveIdsFilter(array($activeId));
2130  $participantData->setParticipantAccessFilter($accessFilter);
2131  $participantData->load($this->object->getTestId());
2132 
2133  if (!in_array($activeId, $participantData->getActiveIds())) {
2135  }
2136 
2137  $testSession = new ilTestSession();
2138  $testSession->loadFromDb($activeId);
2139 
2140  if ($testSession->isSubmitted()) {
2141  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('tst_already_submitted'), true);
2143  }
2144 
2145  assQuestion::_updateTestPassResults(
2146  $activeId,
2147  $testSession->getPass(),
2148  $this->object->areObligationsEnabled(),
2149  null,
2150  $this->object->getId()
2151  );
2152 
2153  $this->finishTestPass($activeId, $this->object->getId());
2154 
2156  }
2157 
2158  public function finishAllUserPasses()
2159  {
2160  if ($this->hasUsersWithWorkingTimeAvailable()) {
2161  $this->tpl->setOnScreenMessage(
2162  'failure',
2163  $this->lng->txt('finish_pass_for_all_users_in_processing_time'),
2164  true
2165  );
2167  }
2168 
2169  $cgui = new ilConfirmationGUI();
2170  $cgui->setFormAction($this->ctrl->getFormAction($this));
2171  $cgui->setHeaderText($this->lng->txt("finish_pass_for_all_users"));
2172  $cgui->setCancel($this->lng->txt("cancel"), "redirectBackToParticipantsScreen");
2173  $cgui->setConfirm($this->lng->txt("proceed"), "confirmFinishTestPassForAllUser");
2174  $this->tpl->setContent($cgui->getHTML());
2175  }
2176 
2177  private function hasUsersWithWorkingTimeAvailable(): bool
2178  {
2179  if (!$this->object->isEndingTimeEnabled() && !$this->object->getEnableProcessingTime()
2180  || $this->object->endingTimeReached()) {
2181  return false;
2182  }
2183 
2185  $participant_list = new ilTestParticipantList($this->object);
2186  $participant_list->initializeFromDbRows($this->object->getTestParticipants());
2187 
2188  foreach ($participant_list->getAccessFilteredList($access_filter) as $participant) {
2189  if ($participant->hasUnfinishedPasses()
2190  && !$this->object->isMaxProcessingTimeReached(
2191  $this->object->getStartingTimeOfUser($participant->getActiveId()),
2192  $participant->getActiveId()
2193  )) {
2194  return true;
2195  }
2196  }
2197 
2198  return false;
2199  }
2200 
2202  {
2203  require_once 'Modules/Test/classes/class.ilTestParticipantAccessFilter.php';
2205 
2206  require_once 'Modules/Test/classes/class.ilTestParticipantList.php';
2207  $participantList = new ilTestParticipantList($this->object);
2208  $participantList->initializeFromDbRows($this->object->getTestParticipants());
2209  $participantList = $participantList->getAccessFilteredList($accessFilter);
2210 
2211  foreach ($participantList as $participant) {
2212  if (!$participant->hasUnfinishedPasses()) {
2213  continue;
2214  }
2215 
2216  $testSession = new ilTestSession();
2217  $testSession->loadFromDb($participant->getActiveId());
2218 
2219  assQuestion::_updateTestPassResults(
2220  $participant->getActiveId(),
2221  $testSession->getPass(),
2222  $this->object->areObligationsEnabled(),
2223  null,
2224  $this->object->getId()
2225  );
2226 
2227  $this->finishTestPass($participant->getActiveId(), $this->object->getId());
2228  }
2229 
2230 
2232  }
2233 
2234  protected function finishTestPass($active_id, $obj_id)
2235  {
2236  $processLocker = $this->processLockerFactory->withContextId((int) $active_id)->getLocker();
2237 
2238  $test_pass_finisher = new ilTestPassFinishTasks($active_id, $obj_id);
2239  $test_pass_finisher->performFinishTasks($processLocker);
2240  }
2241 
2243  {
2244  $this->ctrl->redirectByClass("ilTestParticipantsGUI");
2245  }
2246 
2247  public function getObject(): ?ilObjTest
2248  {
2249  return $this->object;
2250  }
2251 }
setData(array $a_data)
static get(string $a_var)
Class ilPdfGeneratorConstantsTest.
ilTestProcessLockerFactory $processLockerFactory
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
singleResults()
Creates user results for single questions.
getFilteredTestResult($active_id, $pass, $considerHiddenQuestions, $considerOptionalQuestions)
getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, $overwrite_anonymity=false)
Returns the user data for a test results output.
$context
Definition: webdav.php:29
setContextResultPresentation($contextResultPresentation)
exportEvaluation()
Exports the evaluation data to a selected file format.
outCertificate()
Output of a test certificate.
exportCertificate()
Exports the user results as PDF certificates using XSL-FO via XML:RPC calls.
static _updateTestResultCache(int $active_id, ilAssQuestionProcessLocker $processLocker=null)
Move this to a proper place.
outParticipantsResultsOverview()
Output of the pass overview for a test called from the statistics.
static lookupPassResultsUpdateTimestamp($active_id, $pass)
passDetails()
Output of the learners view of an existing test pass.
const PDF_USER_RESULT
PDF Purposes.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false)
executeCommand()
execute command
static _lookupName(int $a_user_id)
lookup user name
exportAggregatedResults()
Exports the aggregated results.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
outUserResultsOverview()
Output of the pass overview for a test called by a test participant.
getResultsSignature()
Returns HTML code for a signature field.
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...
__construct(ilObjTest $a_object)
ilTestEvaluationGUI constructor
const IL_CAL_UNIX
static getStyleSheetLocation(string $mode="output", string $a_css_name="", string $a_css_location="")
get full style sheet file name (path inclusive) of current user
static accessViolationRedirect()
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getASCIIFilename(string $a_filename)
global $DIC
Definition: feed.php:28
buildQuestionRelatedObjectivesList(ilLOTestQuestionAdapter $objectivesAdapter, ilTestQuestionSequence $testSequence)
if($format !==null) $name
Definition: metadata.php:247
getEvaluationQuestionId($question_id, $original_id="")
Returns the ID of a question for evaluation purposes.
static instantiateQuestion(int $question_id)
static getInstance(ilTestSession $a_test_session)
finishTestPass($active_id, $obj_id)
outParticipantsPassDetails()
Output of the pass details of an existing test pass for the test statistics.
buildPassOverviewTableGUI($targetGUI)
static _getResultPass($active_id)
Retrieves the pass number that should be counted for a given user.
Validates if an active certificate is stored in the database and can be downloaded by the user...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static lookupLastTestPassAccess($activeId, $passIndex)
static _lookupFields(int $a_user_id)
lookup fields (deprecated; use more specific methods instead)
setTitle(string $a_title, string $a_icon="", string $a_icon_alt="")
$filename
Definition: buildRTE.php:78
exportFileUploadsForAllParticipants()
Creates a ZIP file containing all file uploads for a given question in a test.
$rows
Definition: xhr_table.php:10
Just a wrapper class to create Unit Test for other classes.
detailedEvaluation()
Creates the detailed evaluation output for a selected participant.
createPDF(int $userId, int $objectId)
buildPassDetailsOverviewTableGUI($targetGUI, $targetCMD)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(Container $dic, ilPlugin $plugin)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$ilUser
Definition: imgupload.php:34
exportQuestionForAllParticipants()
Creates a PDF representation of the answers for a given question in a test.
populatePassFinishDate($tpl, $passFinishDate)
populateExamId(ilTemplate $tpl, int $activeId, int $pass)
outUserPassDetails()
Output of the pass details of an existing test pass for the active test participant.
outEvaluation()
Creates the evaluation output for the test.
Service GUI class for tests.
static generatePDF($pdf_output, $output_mode, $filename=null, $purpose=null)
static prepareGenerationRequest(string $service, string $purpose)
Prepare the content processing for a PDF generation request This function should be called as in a re...
outUserListOfAnswerPasses()
Output of the pass overview for a user when he/she wants to see his/her list of answers.
static clear(string $a_var)
getPassDetailsOverviewTableGUI( $result_array, $active_id, $pass, $targetGUI, $targetCMD, $questionDetailsCMD, $questionAnchorNav, ilTestQuestionRelatedObjectivesList $objectivesList=null, $multipleObjectivesInvolved=true)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getPassListOfAnswers(&$result_array, $active_id, $pass, $show_solutions=false, $only_answered_questions=false, $show_question_only=false, $show_reached_points=false, $anchorNav=false, ilTestQuestionRelatedObjectivesList $objectivesList=null, ilTestResultHeaderLabelBuilder $testResultHeaderLabelBuilder=null)
Returns the list of answers of a users test pass.
static set(string $a_var, $a_val)
Set a value.
eval_a()
Output of anonymous aggregated results for the test.
const SCORE_BEST_PASS
getPassOverviewTableData(ilTestSession $testSession, $passes, $withResults)
This method uses the data of a given test pass to create an evaluation for displaying into a table us...
getQuestionResultForTestUsers($question_id, $test_id)
Creates a HTML representation for the results of a given question in a test.
$i
Definition: metadata.php:41
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static lookupExamId($active_id, $pass)
downloadPdf(int $userId, int $objectId)