ILIAS  release_8 Revision v8.24
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
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();
1161 }
1162
1164 {
1165 $tableGUI = $this->buildPassDetailsOverviewTableGUI($this, 'outParticipantsPassDetails');
1166 $tableGUI->initFilter();
1167 $tableGUI->resetOffset();
1168 $tableGUI->resetFilter();
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
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}
$filename
Definition: buildRTE.php:78
const IL_CAL_UNIX
static instantiateQuestion(int $question_id)
static _updateTestResultCache(int $active_id, ilAssQuestionProcessLocker $processLocker=null)
@TODO Move this to a proper place.
Validates if an active certificate is stored in the database and can be downloaded by the user.
Just a wrapper class to create Unit Test for other classes.
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)
@classDescription Date and time handling
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 getASCIIFilename(string $a_filename)
static getInstance(ilTestSession $a_test_session)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static accessViolationRedirect()
static _getResultPass($active_id)
Retrieves the pass number that should be counted for a given user.
static lookupExamId($active_id, $pass)
static lookupLastTestPassAccess($activeId, $passIndex)
static lookupPassResultsUpdateTimestamp($active_id, $pass)
User class.
static _lookupName(int $a_user_id)
lookup user name
static _lookupFields(int $a_user_id)
lookup fields (deprecated; use more specific methods instead)
static prepareGenerationRequest(string $service, string $purpose)
Prepare the content processing for a PDF generation request This function should be called as in a re...
This class represents a property form user interface.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a selection list property in a property form.
static get(string $a_var)
static clear(string $a_var)
static set(string $a_var, $a_val)
Set a value.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
special template class to simplify handling of ITX/PEAR
This 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...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
exportFileUploadsForAllParticipants()
Creates a ZIP file containing all file uploads for a given question in a test.
outEvaluation()
Creates the evaluation output for the test.
outCertificate()
Output of a test certificate.
singleResults()
Creates user results for single questions.
outUserPassDetails()
Output of the pass details of an existing test pass for the active test participant.
passDetails()
Output of the learners view of an existing test pass.
__construct(ilObjTest $a_object)
ilTestEvaluationGUI constructor
exportCertificate()
Exports the user results as PDF certificates using XSL-FO via XML:RPC calls.
eval_a()
Output of anonymous aggregated results for the test.
exportAggregatedResults()
Exports the aggregated results.
detailedEvaluation()
Creates the detailed evaluation output for a selected participant.
outUserListOfAnswerPasses()
Output of the pass overview for a user when he/she wants to see his/her list of answers.
exportQuestionForAllParticipants()
Creates a PDF representation of the answers for a given question in a test.
ilTestProcessLockerFactory $processLockerFactory
outParticipantsPassDetails()
Output of the pass details of an existing test pass for the test statistics.
getEvaluationQuestionId($question_id, $original_id="")
Returns the ID of a question for evaluation purposes.
outUserResultsOverview()
Output of the pass overview for a test called by a test participant.
exportEvaluation()
Exports the evaluation data to a selected file format.
getFilteredTestResult($active_id, $pass, $considerHiddenQuestions, $considerOptionalQuestions)
outParticipantsResultsOverview()
Output of the pass overview for a test called from the statistics.
finishTestPass($active_id, $obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static generatePDF($pdf_output, $output_mode, $filename=null, $purpose=null)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Service GUI class for tests.
populateExamId(ilTemplate $tpl, int $activeId, int $pass)
getPassDetailsOverviewTableGUI( $result_array, $active_id, $pass, $targetGUI, $targetCMD, $questionDetailsCMD, $questionAnchorNav, ilTestQuestionRelatedObjectivesList $objectivesList=null, $multipleObjectivesInvolved=true)
populatePassFinishDate($tpl, $passFinishDate)
getResultsSignature()
Returns HTML code for a signature field.
buildPassOverviewTableGUI($targetGUI)
getQuestionResultForTestUsers($question_id, $test_id)
Creates a HTML representation for the results of a given question in a test.
setContextResultPresentation($contextResultPresentation)
buildQuestionRelatedObjectivesList(ilLOTestQuestionAdapter $objectivesAdapter, ilTestQuestionSequence $testSequence)
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...
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.
getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, $overwrite_anonymity=false)
Returns the user data for a test results output.
buildPassDetailsOverviewTableGUI($targetGUI, $targetCMD)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getStyleSheetLocation(string $mode="output", string $a_css_name="", string $a_css_location="")
get full style sheet file name (path inclusive) of current user
global $DIC
Definition: feed.php:28
$ilUser
Definition: imgupload.php:34
const SCORE_BEST_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...
if($format !==null) $name
Definition: metadata.php:247
$i
Definition: metadata.php:41
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Class ilPdfGeneratorConstantsTest.
$context
Definition: webdav.php:29
$rows
Definition: xhr_table.php:10