ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ObjectiveRenderer.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
25
31{
32 public const MATERIALS_TESTS = 1;
33 public const MATERIALS_OTHER = 2;
34
35 public const CHECKBOX_NONE = 0;
36 public const CHECKBOX_ADMIN = 1;
37 public const CHECKBOX_DOWNLOAD = 2;
38 protected array $rendered_items;
39 protected \ilCourseObjectiveListGUI $objective_list_gui;
40 protected \ilLanguage $lng;
41 protected \ILIAS\Container\StandardGUIRequest $request;
42 protected \ILIAS\Style\Content\Object\ObjectFacade $content_style_domain;
43 protected \ilLOTestAssignments $test_assignments;
44 protected \ilContainerRenderer $renderer;
45 protected \ilLOSettings $loc_settings;
46
47 protected \ilContainerGUI $container_gui;
48 protected \ilContainer $container;
49 protected string $view_mode;
52 protected array $list_gui = [];
53 protected string $output_html = "";
54
55 public function __construct(
58 string $view_mode,
60 \ilContainerRenderer $container_renderer
61 ) {
62 global $DIC;
63
64 $this->domain = $domain; // setting and access (visible, read, write access)
65 $this->gui = $gui; // getting ilCtrl
68 $this->view_mode = $view_mode; // tile/list (of container)
69 $this->container_gui = $container_gui; // tile/list (of container)
72 $this->container = $container; // id, refid, other stuff
73 $this->loc_settings = \ilLOSettings::getInstanceByObjId($this->container->getId());
74 $this->test_assignments = \ilLOTestAssignments::getInstance($this->container->getId());
75 $this->renderer = $container_renderer;
76 $this->content_style_domain = $DIC
77 ->contentStyle()
78 ->domain()
79 ->styleForObjId(0);
80 $this->request = $gui
82 $this->lng = $domain->lng();
83 }
84
85
86 public function renderObjectives(): string
87 {
88 $mode = $this->domain->content()->mode($this->container);
89 $user = $this->domain->user();
90 $access = $this->domain->access();
91 $lng = $this->domain->lng();
92
93 $is_manage = $mode->isAdminMode();
94 $is_order = $mode->isOrderingMode();
95
96 if (!$is_manage) {
97
98 // render objectives
99 $this->showObjectives($is_order);
100
101 // check for results
102 $has_results = \ilLOUserResults::hasResults($this->container->getId(), $user->getId());
103
104 $tst_obj_id = \ilObject::_lookupObjId($this->loc_settings->getInitialTest());
105
106 // render initial/qualified test
107 if (
108 $this->loc_settings->getInitialTest() &&
109 $this->loc_settings->isGeneralInitialTestVisible() &&
110 !$this->loc_settings->isInitialTestStart() &&
112 $tst_obj_id,
114 '',
115 $user->getId()
116 )
117 ) {
118 $this->output_html .= $this->renderTest($this->loc_settings->getInitialTest(), null, true);
119 } elseif (
120 $this->loc_settings->getQualifiedTest() &&
121 $this->loc_settings->isGeneralQualifiedTestVisible()
122 ) {
123 $this->output_html .= $this->renderTest($this->loc_settings->getQualifiedTest(), null, false);
124 }
125
126 // render other materials
127 //$this->showMaterials(self::MATERIALS_OTHER, false, !$is_order);
128 } else {
129
130 // render all materials
131 // not needed anymore
132 //$this->showMaterials(null, true);
133 }
134
135 // reset results by setting or for admins
136 if (
137 \ilLOSettings::getInstanceByObjId($this->container->getId())->isResetResultsEnabled() or
138 $access->checkAccess('write', '', $this->container->getRefId())
139 ) {
140 if ($has_results) {
141 if (!$is_manage && !$is_order) {
142 $this->showButton('askReset', $lng->txt('crs_reset_results'));
143 }
144 }
145 }
146 return $this->output_html;
147 }
148
149 public function getContent(): string
150 {
151 return $this->output_html;
152 }
153
154 public function showObjectives(bool $a_is_order = false): void
155 {
156 $lng = $this->domain->lng();
157 $ilSetting = $this->domain->settings();
158 // All objectives
159 if (!count($objective_ids = \ilCourseObjective::_getObjectiveIds($this->container->getId(), true))) {
160 return;
161 }
162 $this->objective_list_gui = new \ilCourseObjectiveListGUI();
163 $this->objective_list_gui->setContainerObject($this->container_gui);
164 if ($ilSetting->get("icon_position_in_lists") === "item_rows") {
165 $this->objective_list_gui->enableIcon(true);
166 }
167
168 $acc = null;
169 if (!$a_is_order) {
170 $acc = new \ilAccordionGUI();
171 $acc->setUseSessionStorage(true);
172 $acc->setAllowMultiOpened(true);
173 $acc->setBehaviour(\ilAccordionGUI::FIRST_OPEN);
174 $acc->setId("crsobjtv_" . $this->container->getId());
175 } else {
176 $this->renderer->addCustomBlock('lobj', $lng->txt('crs_objectives'));
177 }
178
179 $lur_data = $this->parseLOUserResults();
180 $has_initial = \ilLOSettings::getInstanceByObjId($this->container->getId())->worksWithInitialTest();
181 $has_lo_page = false;
182 $obj_cnt = 0;
183 foreach ($objective_ids as $objective_id) {
184 if (
185 $has_initial &&
186 (
187 !isset($lur_data[$objective_id]) or
189 $this->container->getId(),
190 \ilLOSettings::getInstanceByObjId($this->container->getId())->getInitialTest(),
191 $objective_id
192 )
193 )
194 ) {
195 $lur_data[$objective_id] = array("type" => \ilLOSettings::TYPE_TEST_INITIAL);
196 }
197 if ($html = $this->renderObjective((int) $objective_id, $has_lo_page, $acc, $lur_data[$objective_id] ?? null)) {
198 $this->renderer->addItemToBlock('lobj', 'lobj', $objective_id, $html);
199 }
200 $obj_cnt++;
201 }
202
203 // buttons for showing/hiding all objectives
204 if (!$a_is_order && $obj_cnt > 1) {
205 $this->showButton("", $lng->txt("crs_show_all_obj"), "", "crs_show_all_obj_btn");
206 $this->showButton("", $lng->txt("crs_hide_all_obj"), "", "crs_hide_all_obj_btn");
207 $acc->setShowAllElement("crs_show_all_obj_btn");
208 $acc->setHideAllElement("crs_hide_all_obj_btn");
209 }
210
211 // order/block
212 if ($a_is_order) {
213 $this->output_html .= $this->renderer->getHTML();
214
215 $this->renderer->resetDetails();
216 }
217 // view/accordion
218 else {
219 $this->output_html .= "<div class='ilCrsObjAcc'>" . $acc->getHTML() . "</div>";
220 }
221 }
222
223 protected function renderTest(
224 int $a_test_ref_id,
225 ?int $a_objective_id,
226 bool $a_is_initial = false
227 ): string {
228 $tree = $this->domain->repositoryTree();
229 $lng = $this->domain->lng();
230
231 $node_data = [];
232 if ($a_test_ref_id) {
233 $node_data = $tree->getNodeData($a_test_ref_id);
234 }
235 if (!isset($node_data['child']) || !$node_data['child']) {
236 return '';
237 }
238
239 // update ti
240 if ($a_objective_id) {
241 if ($a_is_initial) {
242 $title = sprintf($lng->txt('crs_loc_itst_for_objective'), \ilCourseObjective::lookupObjectiveTitle($a_objective_id));
243 } else {
244 $title = sprintf($lng->txt('crs_loc_qtst_for_objective'), \ilCourseObjective::lookupObjectiveTitle($a_objective_id));
245 }
246 $node_data['objective_id'] = $a_objective_id;
247 $node_data['objective_status'] = false;
248 } else {
249 $obj_id = \ilObject::_lookupObjId($a_test_ref_id);
250 $title = \ilObject::_lookupTitle($obj_id);
251
252 $title .= (
253 ' (' .
254 (
255 $a_is_initial
256 ? $lng->txt('crs_loc_itest_info')
257 : $lng->txt('crs_loc_qtest_info')
258 ) .
259 ')'
260 );
261 $node_data['objective_id'] = 0;
262 }
263
264 $node_data['title'] = $title;
265 return "<div class='ilContObjectivesViewTestItem'>" . $this->renderer->getItemRenderer()->renderItem($node_data) . "</div>";
266 }
267
268 // Show all other (no assigned tests, no assigned materials) materials
269 /*
270 protected function showMaterials(
271 int $a_mode = null,
272 bool $a_is_manage = false,
273 bool $a_as_accordion = false
274 ) {
275 $lng = $this->domain->lng();
276
277 if (is_array($this->items["_all"])) {
278 $this->objective_map = $this->buildObjectiveMap();
279
280 // all rows
281 $item_r = array();
282
283 $position = 1;
284 foreach ($this->items["_all"] as $k => $item_data) {
285 if ($a_mode == self::MATERIALS_TESTS and $item_data['type'] != 'tst') {
286 continue;
287 }
288 if ($item_data['type'] == 'itgr') {
289 continue;
290 }
291 if (!$a_is_manage) {
292 // if test object is qualified or initial do not show here
293 $assignments = ilLOTestAssignments::getInstance($this->getContainerObject()->getId());
294 if ($assignments->getTypeByTest($item_data['child']) != ilLOSettings::TYPE_TEST_UNDEFINED) {
295 continue;
296 }
297 }
298
299 if ($this->rendered_items[$item_data["child"]] !== true &&
300 !$this->renderer->hasItem($item_data["child"])) {
301 $this->rendered_items[$item_data['child']] = true;
302
303 // TODO: Position (DONE ?)
304 $html = $this->renderItem($item_data, $position++, !($a_mode == self::MATERIALS_TESTS));
305 if ($html != "") {
306 $item_r[] = array("html" => $html, "id" => $item_data["child"], "type" => $item_data["type"]);
307 }
308 }
309 }
310
311 // if we have at least one item, output the block
312 if (count($item_r) > 0) {
313 if (!$a_as_accordion) {
314 $pos = 0;
315
316 switch ($a_mode) {
317 case self::MATERIALS_TESTS:
318 $block_id = "tst";
319 $this->renderer->addTypeBlock($block_id);
320 break;
321
322 case self::MATERIALS_OTHER:
323 $block_id = "oth";
324 $this->renderer->addCustomBlock($block_id, $lng->txt('crs_other_resources'));
325 break;
326
327 // manage
328 default:
329 $block_id = "all";
330 $this->renderer->addCustomBlock($block_id, $lng->txt('content'));
331 break;
332 }
333
334 // :TODO:
335 if ($a_mode != self::MATERIALS_TESTS) {
336 $pos = $this->getItemGroupsHTML();
337 }
338
339 foreach ($item_r as $h) {
340 if (!$this->renderer->hasItem($h["id"])) {
341 $this->renderer->addItemToBlock($block_id, $h["type"], $h["id"], $h["html"]);
342 }
343 }
344
345 $this->output_html .= $this->renderer->getHTML();
346 } else {
347 $txt = "";
348 switch ($a_mode) {
349 case self::MATERIALS_TESTS:
350 $txt = $lng->txt('objs_tst');
351 break;
352
353 case self::MATERIALS_OTHER:
354 $txt = $lng->txt('crs_other_resources');
355 break;
356 }
357
358 $acc = new ilAccordionGUI();
359 $acc->setId("crsobjtvmat" . $a_mode . "_" . $this->container_obj->getId());
360
361 $acc_content = array();
362 foreach ($item_r as $h) {
363 $acc_content[] = $h["html"];
364 }
365 $acc->addItem($txt, $this->buildAccordionContent($acc_content));
366
367 $this->output_html .= $acc->getHTML();
368 }
369 }
370 }
371 }*/
372
373
374 /* unsure where this one is called...
375 protected function updateResult(
376 array $a_res,
377 int $a_item_ref_id,
378 int $a_objective_id,
379 int $a_user_id
380 ) : array {
381 if ($this->loc_settings->getQualifiedTest() == $a_item_ref_id) {
382 // Check for existing test run, and decrease tries, reset final if run exists
383 $active = ilObjTest::isParticipantsLastPassActive(
384 $a_item_ref_id,
385 $a_user_id
386 );
387
388 if ($active) {
389 if (ilLOTestRun::lookupRunExistsForObjective(
390 ilObject::_lookupObjId($a_item_ref_id),
391 $a_objective_id,
392 $a_user_id
393 )) {
394 if ($a_res['tries'] > 0) {
395 --$a_res['tries'];
396 }
397 $a_res['is_final'] = 0;
398 }
399 }
400 }
401 return $a_res;
402 }*/
403
412 protected function renderObjective(
413 int $a_objective_id,
414 bool &$a_has_lo_page,
415 ?\ilAccordionGUI $a_accordion = null,
416 ?array $a_lo_result = null
417 ): string {
418 $ilUser = $this->domain->user();
419 $lng = $this->domain->lng();
420
421 $objective = new \ilCourseObjective($this->container, $a_objective_id);
422
423 $items = \ilObjectActivation::getItemsByObjective($a_objective_id);
424
425 // sorting is handled by ilCourseObjectiveMaterials
426 // $items = ilContainerSorting::_getInstance($this->getContainerObject()->getId())->sortSubItems('lobj',$a_objective_id,$items);
427
428 $objectives_lm_obj = new \ilCourseObjectiveMaterials($a_objective_id);
429
430 // #13381 - map material assignment to position
431 $sort_map = array();
432 foreach ($objectives_lm_obj->getMaterials() as $item) {
433 $sort_map[$item["lm_ass_id"]] = $item["position"];
434 }
435
436 $is_manage = $this->container_gui->isActiveAdministrationPanel();
437 $is_order = $this->container_gui->isActiveOrdering();
438
439 $sort_content = array();
440
441 $access = $this->domain->access();
442 foreach ($items as $item) {
443
444 if (!$access->checkAccess('visible', '', $item["ref_id"])) {
445 continue;
446 }
447 /*
448 if ($this->getDetailsLevel($a_objective_id) < self::DETAILS_ALL) {
449 continue;
450 }*/
451
452 $item_list_gui2 = $this->renderer->getItemRenderer()->getItemGUI($item);
453 $item_list_gui2->enableIcon(true);
454
455 if ($is_order || $a_accordion) {
456 $item_list_gui2->enableCommands(true, true);
457 $item_list_gui2->enableProperties(false);
458 }
459
460 $chapters = $objectives_lm_obj->getChapters();
461 if (count($chapters)) {
462 $has_sections = false;
463 foreach ($chapters as $chapter) {
464 if ($chapter['ref_id'] != $item['child']) {
465 continue;
466 }
467 $has_sections = true;
468
469 $title = $item['title'] .
470 " &rsaquo; " . \ilLMObject::_lookupTitle($chapter['obj_id']) .
471 " (" . $lng->txt('obj_' . $chapter['type']) . ")";
472
473 $item_list_gui2->setDefaultCommandParameters(array(
474 "obj_id" => $chapter['obj_id'],
475 "focus_id" => $chapter['obj_id'],
476 "focus_return" => $this->container->getRefId()));
477
478 if ($is_order) {
479 $item_list_gui2->setPositionInputField(
480 "[lobj][" . $a_objective_id . "][" . $chapter['lm_ass_id'] . "]",
481 sprintf('%d', $chapter['position'] * 10)
482 );
483 }
484
485 $sub_item_html = $item_list_gui2->getListItemHTML(
486 (int) $item['ref_id'],
487 (int) $item['obj_id'],
488 $title,
489 $item['description']
490 );
491
492 // #13381 - use materials order
493 $sort_key = str_pad(
494 (string) $chapter['position'],
495 5,
496 "0",
497 STR_PAD_LEFT
498 ) . "_" . strtolower($title) . "_" . $chapter['lm_ass_id'];
499 $sort_content[$sort_key] = $sub_item_html;
500 }
501 }
502
503 $this->rendered_items[$item['child']] = true;
504
505 if ($lm_ass_id = $objectives_lm_obj->isAssigned((int) $item['ref_id'], true)) {
506 if ($is_order) {
507 $item_list_gui2->setPositionInputField(
508 "[lobj][" . $a_objective_id . "][" . $lm_ass_id . "]",
509 sprintf('%d', $sort_map[$lm_ass_id] * 10)
510 );
511 }
512
513 $sub_item_html = $item_list_gui2->getListItemHTML(
514 $item['ref_id'],
515 $item['obj_id'],
516 $item['title'],
517 $item['description']
518 );
519
520 // #13381 - use materials order
521 $sort_key = str_pad((string) $sort_map[$lm_ass_id], 5, "0", STR_PAD_LEFT) . "_" . strtolower($item['title']) . "_" . $lm_ass_id;
522 $sort_content[$sort_key] = $sub_item_html;
523 }
524 }
525
526 //if ($this->getDetailsLevel($a_objective_id) == self::DETAILS_ALL) {
527 $this->objective_list_gui->enableCommands(false);
528 //} else {
529 // $this->objective_list_gui->enableCommands(true);
530 //}
531
532 if ($is_order) {
533 $this->objective_list_gui->setPositionInputField(
534 "[lobj][" . $a_objective_id . "][0]",
535 (string) ($objective->__getPosition() * 10)
536 );
537 }
538
539 ksort($sort_content);
540 if (!$a_accordion) {
541 foreach ($sort_content as $sub_item_html) {
542 $this->objective_list_gui->addSubItemHTML($sub_item_html);
543 }
544
545 return $this->objective_list_gui->getObjectiveListItemHTML(
546 0,
547 $a_objective_id,
548 $objective->getTitle(),
549 $objective->getDescription(),
550 ($is_manage || $is_order)
551 );
552 } else {
553 $acc_content = $sort_content;
554
555 $initial_shown = false;
556 $initial_test_ref_id = $this->test_assignments->getTestByObjective($a_objective_id, \ilLOSettings::TYPE_TEST_INITIAL);
557 $initial_test_obj_id = \ilObject::_lookupObjId($initial_test_ref_id);
558
559 if (
560 $initial_test_obj_id &&
561 $this->loc_settings->hasSeparateInitialTests() &&
562 !\ilObjTestAccess::checkCondition($initial_test_obj_id, \ilConditionHandler::OPERATOR_FINISHED, '', $ilUser->getId())
563 ) {
564 $acc_content[] = $this->renderTest(
565 $this->test_assignments->getTestByObjective($a_objective_id, \ilLOSettings::TYPE_TEST_INITIAL),
566 $a_objective_id,
567 true
568 );
569 $initial_shown = true;
570 } elseif ($this->loc_settings->hasSeparateQualifiedTests()) {
571 $acc_content[] = $this->renderTest(
572 $this->test_assignments->getTestByObjective($a_objective_id, \ilLOSettings::TYPE_TEST_QUALIFIED),
573 $a_objective_id,
574 false
575 );
576 }
577
578 $co_page = null;
579 if (\ilPageUtil::_existsAndNotEmpty("lobj", $objective->getObjectiveId())) {
580 $a_has_lo_page = true;
581
582 $page_gui = new \ilLOPageGUI($objective->getObjectiveId());
583
584 $page_gui->setStyleId(
585 $this->content_style_domain->getEffectiveStyleId()
586 );
587 $page_gui->setPresentationTitle("");
588 $page_gui->setTemplateOutput(false);
589 $page_gui->setHeader("");
590
591 $co_page = "<div class='ilContObjectiveIntro'>" . $page_gui->showPage() . "</div>";
592 }
593
594 $a_accordion->addItem(
595 $this->buildAccordionTitle($objective, $a_lo_result),
596 $co_page .
597 $this->buildAccordionContent($acc_content),
598 ($this->request->getObjectiveId() == $objective->getObjectiveId())
599 );
600 }
601 return "";
602 }
603
604 // Parse learning objective results.
605 protected function parseLOUserResults(): array
606 {
607 $ilUser = $this->domain->user();
608 $initial_status = null;
609
610 $res = array();
611
612 $lo_ass = \ilLOTestAssignments::getInstance($this->container->getId());
613
614 $lur = new \ilLOUserResults($this->container->getId(), $ilUser->getId());
615 foreach ($lur->getCourseResultsForUserPresentation() as $objective_id => $types) {
616 // show either initial or qualified for objective
617 if (isset($types[\ilLOUserResults::TYPE_INITIAL])) {
618 $initial_status = $types[\ilLOUserResults::TYPE_INITIAL]["status"];
619 }
620
621 // qualified test has priority
622 if (isset($types[\ilLOUserResults::TYPE_QUALIFIED])) {
623 $result = $types[\ilLOUserResults::TYPE_QUALIFIED];
624 $result["type"] = \ilLOUserResults::TYPE_QUALIFIED;
625 $result["initial"] = $types[\ilLOUserResults::TYPE_INITIAL] ?? null;
626 } else {
627 $result = $types[\ilLOUserResults::TYPE_INITIAL];
628 $result["type"] = \ilLOUserResults::TYPE_INITIAL;
629 }
630
631 $result["initial_status"] = $initial_status;
632
633 $result["itest"] = $lo_ass->getTestByObjective($objective_id, \ilLOSettings::TYPE_TEST_INITIAL);
634 $result["qtest"] = $lo_ass->getTestByObjective($objective_id, \ilLOSettings::TYPE_TEST_QUALIFIED);
635
636 $res[$objective_id] = $result;
637 }
638
639 return $res;
640 }
641
642
659 public static function renderProgressMeter(
660 ?int $a_perc_result = null,
661 ?int $a_perc_limit = null,
662 ?int $a_compare_value = null,
663 ?string $a_caption = null,
664 ?string $a_url = null,
665 ?string $a_tt_id = null,
666 ?string $a_tt_txt = null,
667 ?string $a_next_step = null,
668 bool $a_sub = false,
669 int $a_sub_style = 30,
670 string $a_main_text = '',
671 string $a_required_text = ''
672 ): string {
673 global $DIC;
674
675 $tpl = new \ilTemplate("tpl.objective_progressmeter.html", true, true, "components/ILIAS/Container");
676
677 $lng = $DIC->language();
678 $lng->loadLanguageModule('crs');
679
680
681
682 if (is_numeric($a_perc_result)) {
683 $uiFactory = $DIC->ui()->factory();
684 $uiRenderer = $DIC->ui()->renderer();
685
686 $pMeter = $uiFactory->chart()->progressMeter()->standard(
687 100,
688 (int) $a_perc_result,
689 (int) $a_perc_limit,
690 (int) $a_compare_value
691 );
692 $tpl->setVariable('PROGRESS_METER', $uiRenderer->render($pMeter));
693 }
694
695 if ($a_caption) {
696 if ($a_url) {
697 $button = \ilLinkButton::getInstance();
698 $button->setCaption($a_caption, false);
699 $button->setUrl($a_url);
700
701 $tpl->setCurrentBlock("statustxt_bl");
702 $tpl->setVariable("TXT_PROGRESS_STATUS", $button->render());
703 } else {
704 $tpl->setCurrentBlock("statustxt_no_link_bl");
705 $tpl->setVariable("TXT_PROGRESS_STATUS_NO_LINK", $a_caption);
706 }
707 $tpl->parseCurrentBlock();
708 }
709
710 if ($a_next_step) {
711 //$tpl->setCurrentBlock("nstep_bl");
712 $tpl->setVariable("TXT_NEXT_STEP", $a_next_step);
713 //$tpl->parseCurrentBlock();
714 }
715
716 if ($a_sub) {
717 $tpl->setVariable("SUB_STYLE", ' style="padding-left: ' . $a_sub_style . 'px;"');
718 $tpl->setVariable("SUB_INIT", $a_sub);
719 }
720
721 return $tpl->get();
722 }
723
727 public static function getObjectiveResultSummary(
728 bool $a_has_initial_test,
729 int $a_objective_id,
730 array $a_lo_result
731 ): string {
732 global $DIC;
733
734 if ($a_lo_result === null) {
735 $a_lo_result["type"] = null;
736 }
737 if (!isset($a_lo_result["type"])) {
738 $a_lo_result["type"] = null;
739 }
740
741 $lng = $DIC->language();
742 $lng->loadLanguageModule('crs');
743
744 $is_qualified =
745 ($a_lo_result["type"] == \ilLOUserResults::TYPE_QUALIFIED);
746 $is_qualified_initial =
747 (
748 $a_lo_result['type'] == \ilLOUserResults::TYPE_INITIAL &&
749 \ilLOSettings::getInstanceByObjId($a_lo_result['course_id'] ?? 0)->isInitialTestQualifying()
750 );
751 $has_completed = (int) ($a_lo_result["status"] ?? 0) === \ilLOUserResults::STATUS_COMPLETED;
752
753 $next_step = $progress_txt = $bar_color = $test_url = $initial_sub = null;
754
755 if (
756 $is_qualified ||
757 $is_qualified_initial) {
758 if ($has_completed) {
759 $next_step = $lng->txt("crs_loc_progress_objective_complete");
760 } else {
761 $next_step = $lng->txt("crs_loc_progress_do_qualifying_again");
762 }
763 } // initial test
764 else {
765 if ($a_lo_result["status"] ?? 0) {
766 $next_step =
767 $has_completed ?
768 $lng->txt("crs_loc_progress_do_qualifying") :
769 $lng->txt("crs_loc_suggested");
770 } else {
771 $next_step = $a_has_initial_test ?
772 $lng->txt("crs_loc_progress_no_result_do_initial") :
773 $lng->txt("crs_loc_progress_no_result_no_initial");
774 }
775 }
776 return $next_step;
777 }
778
782 public static function buildObjectiveProgressBar(
783 bool $a_has_initial_test,
784 int $a_objective_id,
785 array $a_lo_result,
786 bool $a_list_mode = false,
787 bool $a_sub = false,
788 ?string $a_tt_suffix = null
789 ): string {
790 global $DIC;
791
792 $lng = $DIC->language();
793 $lng->loadLanguageModule('crs');
794
795 // tooltip (has to be unique!)
796
797 $tooltip_id = "crsobjtvusr_" . $a_objective_id . "_" . $a_lo_result["type"] . "_" . ((int) $a_sub);
798 if ($a_tt_suffix !== null) {
799 $tooltip_id .= "_" . $a_tt_suffix;
800 }
801
802 $tt_txt = sprintf(
803 $lng->txt("crs_loc_tt_info"),
804 $a_lo_result["result_perc"] ?? '0',
805 $a_lo_result["limit_perc"] ?? '0'
806 );
807
808
809 $is_qualified = ($a_lo_result["type"] == \ilLOUserResults::TYPE_QUALIFIED);
810 $is_qualified_initial = ($a_lo_result['type'] == \ilLOUserResults::TYPE_INITIAL &&
811 \ilLOSettings::getInstanceByObjId($a_lo_result['course_id'] ?? 0)->isInitialTestQualifying());
812 $has_completed = (($a_lo_result["status"] ?? 0) == \ilLOUserResults::STATUS_COMPLETED);
813
814 $next_step = $progress_txt = $bar_color = $test_url = $initial_sub = null;
815 $compare_value = null;
816
817 if ($is_qualified ||
818 $is_qualified_initial) {
819 $progress_txt = $lng->txt("crs_loc_progress_result_qtest");
820 $tt_txt = $lng->txt("crs_loc_tab_qtest") . ": " . $tt_txt;
821
822 if ($has_completed) {
823 $next_step = $lng->txt("crs_loc_progress_objective_complete");
824 $bar_color = "ilCourseObjectiveProgressBarCompleted";
825
826 // render 2nd progressbar if there is also an initial test
827 if ($is_qualified &&
828 $a_has_initial_test &&
829 is_array($a_lo_result["initial"])) {
830 $a_lo_result["initial"]["itest"] = $a_lo_result["itest"];
831
832 // force list mode to get rid of next step
833 #$initial_sub = self::buildObjectiveProgressBar(true, $a_objective_id, $a_lo_result["initial"], true, true, $a_tt_suffix);
834 $compare_value = $a_lo_result['initial']['result_perc'];
835 }
836 } else {
837 $next_step = $lng->txt("crs_loc_progress_do_qualifying_again");
838 $bar_color = "ilCourseObjectiveProgressBarFailed";
839 }
840 }
841 // initial test
842 else {
843 if ($a_lo_result["status"] ?? 0) {
844 $progress_txt = $lng->txt("crs_loc_progress_result_itest");
845 $tt_txt = $lng->txt("crs_loc_tab_itest") . ": " . $tt_txt;
846
847 $bar_color = "ilCourseObjectiveProgressBarNeutral";
848 $next_step = $has_completed
849 ? $lng->txt("crs_loc_progress_do_qualifying")
850 : $lng->txt("crs_loc_suggested");
851 }
852 // not attempted: no progress bar
853 else {
854 $next_step = $a_has_initial_test
855 ? $lng->txt("crs_loc_progress_no_result_do_initial")
856 : $lng->txt("crs_loc_progress_no_result_no_initial");
857 }
858 }
859
860 // link to test statistics
861 $relevant_test_id = ($a_lo_result["qtest"] ?? 0)
862 ?: ($a_lo_result["itest"] ?? 0);
863 if ($relevant_test_id) {
864 $test_url = \ilLOUtils::getTestResultLinkForUser($relevant_test_id, $a_lo_result["user_id"] ?? 0);
865 }
866
867 $main_text = $lng->txt('crs_loc_itest_info');
868 if ($a_lo_result['type'] == \ilLOSettings::TYPE_TEST_QUALIFIED) {
869 $main_text = $lng->txt('crs_loc_qtest_info');
870 }
871
872
873
874 return self::renderProgressMeter(
875 $a_lo_result["result_perc"] ?? null,
876 $a_lo_result["limit_perc"] ?? null,
877 $compare_value,
878 $progress_txt,
879 $test_url,
880 $tooltip_id,
881 $tt_txt,
882 $a_list_mode
883 ? null
884 : $next_step,
885 (bool) $initial_sub,
886 $a_list_mode
887 ? 30
888 : 10,
889 $main_text,
890 $lng->txt('crs_lobj_pm_min_goal')
891 );
892 }
893
894 protected function buildAccordionTitle(
895 \ilCourseObjective $a_objective,
896 ?array $a_lo_result = null
897 ): string {
898 global $DIC;
899
900 $renderer = $DIC->ui()->renderer();
901 $ui_factory = $DIC->ui()->factory();
902
903 $tpl = new \ilTemplate("tpl.objective_accordion_title.html", true, true, "components/ILIAS/Container");
904
905 if ($a_lo_result) {
906 $tpl->setVariable(
907 "PROGRESS_BAR",
908 self::buildObjectiveProgressBar(
909 $this->loc_settings->worksWithInitialTest(),
910 $a_objective->getObjectiveId(),
911 $a_lo_result
912 )
913 );
914 }
915
916 $tpl->setVariable("TITLE", $this->lng->txt("crs_loc_learning_objective") . ": " . trim($a_objective->getTitle()));
917 $tpl->setVariable("DESCRIPTION", nl2br(trim($a_objective->getDescription())));
918
919 $initial_res = null;
920 $initial_lim = null;
921 if ($this->loc_settings->worksWithInitialTest()) {
922 if (array_key_exists('initial', $a_lo_result)) {
923 $initial_res = (int) ($a_lo_result['initial']['result_perc'] ?? 0);
924 $initial_lim = (int) ($a_lo_result['initial']['limit_perc'] ?? 100);
925 }
926 if (
928 isset($a_lo_result['result_perc'])
929 ) {
930 $initial_res = (int) $a_lo_result['result_perc'];
931 $initial_lim = (int) $a_lo_result['limit_perc'];
932 }
933 }
934
935 if ($initial_res !== null) {
937 $a_lo_result["itest"],
938 $a_lo_result["user_id"]
939 );
940
941 if (strlen($link)) {
942 $tpl->setCurrentBlock('i_with_link');
943 $tpl->setVariable(
944 'IBTN',
945 $renderer->render(
946 $ui_factory->button()->shy(
947 $this->lng->txt('crs_objective_result_details'),
948 $link
949 )
950 )
951 );
952 $tpl->parseCurrentBlock();
953 }
954
955 $tpl->setCurrentBlock('res_initial');
956 $tpl->setVariable(
957 'IRESULT',
958 sprintf(
959 $this->lng->txt('crs_objective_result_summary_initial'),
960 $initial_res . '%',
961 (int) $initial_lim . '%'
962 )
963 );
964 $tpl->parseCurrentBlock();
965 }
966
967 $qual_res = null;
968 $qual_lim = null;
969
970 if (($a_lo_result['type'] ?? \ilLOUserResults::TYPE_UNDEFINED) == \ilLOUserResults::TYPE_QUALIFIED) {
971 $qual_res = (int) $a_lo_result['result_perc'];
972 $qual_lim = (int) $a_lo_result['limit_perc'];
973 }
974
975 if ($qual_res !== null) {
977 $a_lo_result["qtest"],
978 $a_lo_result["user_id"]
979 );
980
981 if (strlen($link)) {
982 $tpl->setCurrentBlock('q_with_link');
983 $tpl->setVariable(
984 'QBTN',
985 $renderer->render(
986 $ui_factory->button()->shy(
987 $this->lng->txt('crs_objective_result_details'),
988 $link
989 )
990 )
991 );
992 $tpl->parseCurrentBlock();
993 }
994 $tpl->setCurrentBlock('res_qualifying');
995 $tpl->setVariable(
996 'QRESULT',
997 sprintf(
998 $this->lng->txt('crs_objective_result_summary_qualifying'),
999 $qual_res . '%',
1000 (int) $qual_lim . '%'
1001 )
1002 );
1003 $tpl->parseCurrentBlock();
1004 }
1005
1006 //$this->logger->dump($a_lo_result);
1007
1008 $summary = self::getObjectiveResultSummary(
1009 $this->loc_settings->worksWithInitialTest(),
1010 $a_objective->getObjectiveId(),
1011 $a_lo_result ?? []
1012 );
1013 if (strlen($summary)) {
1014 $tpl->setCurrentBlock('objective_summary');
1015 $tpl->setVariable('SUMMARY_TXT', $summary);
1016 $tpl->parseCurrentBlock();
1017 }
1018
1019 // #15510
1020 $tpl->setVariable("ANCHOR_ID", "objtv_acc_" . $a_objective->getObjectiveId());
1021
1022 return $tpl->get();
1023 }
1024
1025 protected function buildAccordionContent(array $a_items): string
1026 {
1027 $tpl = new \ilTemplate("tpl.objective_accordion_content.html", true, true, "components/ILIAS/Container");
1028 foreach ($a_items as $item) {
1029 $tpl->setCurrentBlock("items_bl");
1030 $tpl->setVariable("ITEM", $item);
1031 $tpl->parseCurrentBlock();
1032 }
1033 return $tpl->get();
1034 }
1035
1036 protected function showButton(
1037 string $a_cmd,
1038 string $a_text,
1039 string $a_target = '',
1040 string $a_id = ""
1041 ): void {
1042 $ilToolbar = $this->gui->toolbar();
1043 $ilCtrl = $this->gui->ctrl();
1044
1045 // #11842
1046 $ilToolbar->addButton(
1047 $a_text,
1048 $ilCtrl->getLinkTarget($this->container_gui, $a_cmd),
1049 $a_target,
1050 null,
1051 '',
1052 $a_id
1053 );
1054 }
1055}
renderer()
$renderer
buildAccordionTitle(\ilCourseObjective $a_objective, ?array $a_lo_result=null)
renderTest(int $a_test_ref_id, ?int $a_objective_id, bool $a_is_initial=false)
ILIAS Container StandardGUIRequest $request
ILIAS Style Content Object ObjectFacade $content_style_domain
showButton(string $a_cmd, string $a_text, string $a_target='', string $a_id="")
static renderProgressMeter(?int $a_perc_result=null, ?int $a_perc_limit=null, ?int $a_compare_value=null, ?string $a_caption=null, ?string $a_url=null, ?string $a_tt_id=null, ?string $a_tt_txt=null, ?string $a_next_step=null, bool $a_sub=false, int $a_sub_style=30, string $a_main_text='', string $a_required_text='')
Render progress meter.
static getObjectiveResultSummary(bool $a_has_initial_test, int $a_objective_id, array $a_lo_result)
Get objective result summary.
renderObjective(int $a_objective_id, bool &$a_has_lo_page, ?\ilAccordionGUI $a_accordion=null, ?array $a_lo_result=null)
static buildObjectiveProgressBar(bool $a_has_initial_test, int $a_objective_id, array $a_lo_result, bool $a_list_mode=false, bool $a_sub=false, ?string $a_tt_suffix=null)
Render progressbar(s) for given objective and result data.
__construct()
Constructor setup ILIAS global object @access public.
Definition: class.ilias.php:76
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilContainerGUI This is a base GUI class for all container objects in ILIAS: root folder,...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
class ilcourseobjective
static lookupObjectiveTitle(int $a_objective_id, bool $a_add_description=false)
static _getObjectiveIds(int $course_id, bool $a_activated_only=false)
static _lookupTitle(int $a_obj_id)
static getInstanceByObjId(int $a_obj_id)
static getInstance(int $a_container_id)
static hasResults(int $a_container_id, int $a_user_id)
static hasActiveRun(int $a_container_id, int $a_test_ref_id, int $a_objective_id)
static getTestResultLinkForUser(int $a_test_ref_id, int $a_user_id)
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static getItemsByObjective(int $objective_id)
Get objective items.
static _lookupObjId(int $ref_id)
static _lookupTitle(int $obj_id)
static _existsAndNotEmpty(string $a_parent_type, int $a_id, string $a_lang="-")
checks whether page exists and is not empty (may return true on some empty pages)
static checkCondition(int $a_trigger_obj_id, string $a_operator, string $a_value, int $a_usr_id)
check condition for a specific user and object
$res
Definition: ltiservices.php:69
global $lng
Definition: privfeed.php:31
global $ilSetting
Definition: privfeed.php:31
global $DIC
Definition: shib_login.php:26