ILIAS  release_8 Revision v8.24
class.ilPersonalSkillsGUI.php
Go to the documentation of this file.
1<?php
2
25use ILIAS\ResourceStorage\Services as ResourceStorage;
26use ILIAS\Data\Factory as DataFactory;
31
39{
40 public const LIST_SELECTED = "selected";
41 public const LIST_PROFILES = "";
42
43 protected string $offline_mode = "";
44
48 protected array $actual_levels = [];
49
53 protected array $next_level_fuls = [];
54
58 protected array $gap_self_eval_levels = [];
59 protected bool $history_view = false;
60
64 protected array $trigger_objects_filter = [];
65 protected string $intro_text = "";
66
70 protected array $hidden_skills = [];
71 protected string $mode = "";
72 protected string $gap_mode = "";
73 protected int $gap_mode_obj_id = 0;
74 protected string $gap_mode_type = "";
75 protected string $gap_cat_title = "";
76
77 protected UIServices $ui;
78 protected ilCtrl $ctrl;
79 protected ilLanguage $lng;
80 protected ilHelpGUI $help;
82 protected ilObjUser $user;
84 protected ilTabsGUI $tabs;
87 protected Factory $ui_fac;
88 protected Renderer $ui_ren;
89 protected ResourceStorage $storage;
90 protected DataFactory $data_fac;
91 protected ilTree $tree;
93
94 protected int $obj_id = 0;
95
99 protected array $obj_skills = [];
100 protected int $profile_id = 0;
101
105 protected array $profile_levels = [];
106
110 protected array $user_profiles = [];
111
115 protected array $cont_profiles = [];
116 protected bool $use_materials = false;
125 protected int $requested_node_id = 0;
126 protected int $requested_profile_id = 0;
127 protected int $requested_skill_id = 0;
128
132 protected array $requested_skill_ids = [];
133 protected int $requested_basic_skill_id = 0;
134 protected int $requested_tref_id = 0;
135 protected int $requested_level_id = 0;
137 protected int $requested_wsp_id = 0;
138
142 protected array $requested_wsp_ids = [];
143
147 protected array $trigger_user_filter = [];
148
149 public function __construct()
150 {
151 global $DIC;
152
153 $this->ctrl = $DIC->ctrl();
154 $this->lng = $DIC->language();
155 $this->help = $DIC["ilHelp"];
156 $this->setting = $DIC["ilSetting"];
157 $this->user = $DIC->user();
158 $this->tpl = $DIC["tpl"];
159 $this->tabs = $DIC->tabs();
160 $this->toolbar = $DIC->toolbar();
161 $this->access = $DIC->access();
162 $this->ui_fac = $DIC->ui()->factory();
163 $this->ui_ren = $DIC->ui()->renderer();
164 $this->ui = $DIC->ui();
165 $this->storage = $DIC->resourceStorage();
166 $this->data_fac = new \ILIAS\Data\Factory();
167 $this->tree = $DIC->repositoryTree();
168 $this->obj_definition = $DIC["objDefinition"];
169 $this->personal_gui_request = $DIC->skills()->internal()->gui()->personal_request();
170 $this->tree_repo = $DIC->skills()->internal()->repo()->getTreeRepo();
171 $this->tree_service = $DIC->skills()->tree();
172 $this->profile_manager = $DIC->skills()->internal()->manager()->getProfileManager();
173 $this->profile_completion_manager = $DIC->skills()->internal()->manager()->getProfileCompletionManager();
174
175 $ilCtrl = $this->ctrl;
176 $ilHelp = $this->help;
179
180
181 $lng->loadLanguageModule('skmg');
182 $ilHelp->setScreenIdComponent("skill");
183
184 $ilCtrl->saveParameter($this, "skill_id");
185 $ilCtrl->saveParameter($this, "tref_id");
186 $ilCtrl->saveParameter($this, "profile_id");
187 $ilCtrl->saveParameter($this, "list_mode");
188
189 $this->requested_list_mode = $this->personal_gui_request->getListMode();
190 $this->requested_node_id = $this->personal_gui_request->getNodeId();
191 $this->requested_profile_id = $this->personal_gui_request->getProfileId();
192 $this->requested_skill_id = $this->personal_gui_request->getSkillId();
193 $this->requested_skill_ids = $this->personal_gui_request->getSkillIds();
194 $this->requested_basic_skill_id = $this->personal_gui_request->getBasicSkillId();
195 $this->requested_tref_id = $this->personal_gui_request->getTrefId();
196 $this->requested_level_id = $this->personal_gui_request->getLevelId();
197 $this->requested_self_eval_level_id = $this->personal_gui_request->getSelfEvaluationLevelId();
198 $this->requested_wsp_id = $this->personal_gui_request->getWorkspaceId();
199 $this->requested_wsp_ids = $this->personal_gui_request->getWorkspaceIds();
200
201 $this->user_profiles = $this->profile_manager->getProfilesOfUser($this->user->getId());
202 $this->cont_profiles = [];
203
204 $this->use_materials = !$ilSetting->get("disable_personal_workspace");
205
206 $this->skmg_settings = new ilSkillManagementSettings();
207
208 $this->filter = new ilPersonalSkillsFilterGUI();
209 }
210
212 {
213 return $this->filter;
214 }
215
216 public function setProfileId(int $a_val): void
217 {
218 $this->profile_id = $a_val;
219 }
220
221 public function getProfileId(): int
222 {
223 return $this->profile_id;
224 }
225
229 public function setGapAnalysisSelfEvalLevels(array $a_val): void
230 {
231 $this->gap_self_eval_levels = $a_val;
232 }
233
237 public function getGapAnalysisSelfEvalLevels(): array
238 {
240 }
241
242 public function setHistoryView(bool $a_val): void
243 {
244 $this->history_view = $a_val;
245 }
246
247 public function getHistoryView(): bool
248 {
249 return $this->history_view;
250 }
251
252 public function getNonHistoricGapModeView(): bool
253 {
254 return ($this->mode == "gap" && !$this->history_view);
255 }
256
257 public function getTriggerObjectsFilter(): array
258 {
260 }
261
263 {
264 $this->trigger_objects_filter = $trigger_objects_filter;
265 }
266
267 public function setIntroText(string $a_val): void
268 {
269 $this->intro_text = $a_val;
270 }
271
272 public function getIntroText(): string
273 {
274 return $this->intro_text;
275 }
276
280 public function getTriggerUserFilter(): array
281 {
283 }
284
288 public function setTriggerUserFilter(array $trigger_user_filter): void
289 {
290 $this->trigger_user_filter = $trigger_user_filter;
291 }
292
293 public function hideSkill(int $a_skill_id, int $a_tref_id = 0): void
294 {
295 $this->hidden_skills[] = $a_skill_id . ":" . $a_tref_id;
296 }
297
298 public function determineCurrentProfile(): void
299 {
300 $ilCtrl = $this->ctrl;
301
302 if (count($this->cont_profiles) == 0) {
303 return;
304 }
305 $current_prof_id = 0;
306 if ($this->requested_profile_id > 0) {
307 foreach ($this->cont_profiles as $p) {
308 if ($p["profile_id"] == $this->requested_profile_id) {
309 $current_prof_id = $this->requested_profile_id;
310 }
311 }
312 }
313
314 if ($current_prof_id == 0 && !(is_array($this->obj_skills) && $this->obj_id > 0)) {
315 $current_prof_id = $this->cont_profiles[0]["profile_id"];
316 }
317 $ilCtrl->setParameter($this, "profile_id", $current_prof_id);
318 $this->setProfileId($current_prof_id);
319 }
320
321 public function getObjectId(): int
322 {
323 return $this->obj_id;
324 }
325
329 public function getObjectSkills(): array
330 {
331 return $this->obj_skills;
332 }
333
337 public function setObjectSkills(int $a_obj_id, array $a_skills): void
338 {
339 $this->obj_id = $a_obj_id;
340 $this->obj_skills = $a_skills;
341 }
342
343 public function setObjectSkillProfiles(
344 ilContainerGlobalProfiles $a_g_profiles,
345 ilContainerLocalProfiles $a_l_profils
346 ): void {
347 $this->cont_profiles = array_merge($a_g_profiles->getProfiles(), $a_l_profils->getProfiles());
348 }
349
350 public function executeCommand(): void
351 {
352 $ilCtrl = $this->ctrl;
353 $ilUser = $this->user;
356
357 $next_class = $ilCtrl->getNextClass($this);
358
359
360 $cmd = $ilCtrl->getCmd("render");
361
362 //$tpl->setTitle($lng->txt("skills"));
363 //$tpl->setTitleIcon(ilUtil::getImagePath("icon_skmg.svg"));
364
365 switch ($next_class) {
366 default:
367 $this->$cmd();
368 break;
369 }
370 }
371
372 public function setTabs(string $a_activate): void
373 {
374 $ilCtrl = $this->ctrl;
376 $ilTabs = $this->tabs;
377
378 if (count($this->user_profiles) > 0) {
379 $ilCtrl->setParameter($this, "list_mode", self::LIST_PROFILES);
380 $ilTabs->addTab(
381 "profile",
382 $lng->txt("skmg_assigned_profiles"),
383 $ilCtrl->getLinkTarget($this, "render")
384 );
385 }
386
387 // list skills
388 $ilCtrl->setParameter($this, "list_mode", self::LIST_SELECTED);
389 $ilTabs->addTab(
390 "list_skills",
391 $lng->txt("skmg_selected_skills"),
392 $ilCtrl->getLinkTarget($this, "render")
393 );
394
395 $ilCtrl->clearParameterByClass(get_class($this), "list_mode");
396
397 // assign materials
398
399 $ilTabs->activateTab($a_activate);
400 }
401
402 public function setOfflineMode(string $a_file_path): void
403 {
404 $this->offline_mode = $a_file_path;
405 }
406
407 protected function render(): void
408 {
409 if ($this->requested_list_mode == self::LIST_SELECTED || !count($this->user_profiles) > 0) {
410 $this->listSkills();
411 } else {
412 $this->listAllAssignedProfiles();
413 }
414 }
415
416 public function listSkills(): void
417 {
418 $ilCtrl = $this->ctrl;
419 $ilUser = $this->user;
421 $main_tpl = $this->tpl;
422 $ilToolbar = $this->toolbar;
423
424 $tpl = new ilTemplate("tpl.skill_filter.html", true, true, "Services/Skill");
425
426 $this->setTabs("list_skills");
427
428 // skill selection / add new personal skill
429 $ilToolbar->addFormButton(
430 $lng->txt("skmg_add_skill"),
431 "listSkillsForAdd"
432 );
433 $ilToolbar->setFormAction($ilCtrl->getFormAction($this));
434
435 $filter_toolbar = new ilToolbarGUI();
436 $filter_toolbar->setFormAction($ilCtrl->getFormAction($this));
437 $this->getFilter()->addToToolbar($filter_toolbar, false);
438
440 $html = "";
441 foreach ($skills as $s) {
442 $path = $this->tree_service->getSkillTreePath($s["skill_node_id"]);
443
444 // check draft
445 foreach ($path as $p) {
446 if ($p["status"] == ilSkillTreeNode::STATUS_DRAFT) {
447 continue(2);
448 }
449 }
450 $html .= $this->getSkillHTML($s["skill_node_id"], 0, true);
451 }
452
453 // list skills
454
455 if ($html != "") {
456 $filter_toolbar->addFormButton($this->lng->txt("skmg_refresh_view"), "applyFilter");
457 $tpl->setVariable("FILTER", $filter_toolbar->getHTML());
458 $html = $tpl->get() . $html;
459 } else {
460 $box = $this->ui_fac->messageBox()->info($lng->txt("skmg_no_skills_selected_info"));
461 $html = $this->ui_ren->render($box);
462 }
463
464 $main_tpl->setContent($html);
465 }
466
467 protected function applyFilter(): void
468 {
469 $this->getFilter()->save();
470 $this->ctrl->setParameter($this, "list_mode", self::LIST_SELECTED);
471 $this->ctrl->redirect($this, "listSkills");
472 }
473
477 protected function applyFilterAssignedProfiles(): void
478 {
479 $this->getFilter()->save();
480 $this->ctrl->redirect($this, "listAssignedProfile");
481 }
482
483
492 public function getSkillHTML(
493 int $a_top_skill_id,
494 int $a_user_id = 0,
495 bool $a_edit = false,
496 int $a_tref_id = 0
497 ): string {
498 $main_tpl = $this->tpl;
499
500 // user interface plugin slot + default rendering
501 $uip = new ilUIHookProcessor(
502 "Services/Skill",
503 "personal_skill_html",
504 array("personal_skills_gui" => $this, "top_skill_id" => $a_top_skill_id, "user_id" => $a_user_id,
505 "edit" => $a_edit, "tref_id" => $a_tref_id)
506 );
507 $skill_html = "";
508 if (!$uip->replaced()) {
509 $skill_html = $this->renderSkillHTML($a_top_skill_id, $a_user_id, $a_edit, $a_tref_id);
510 }
511 $skill_html = $uip->getHTML($skill_html);
512 $main_tpl->addJavaScript("./Services/Skill/js/SkillEntries.js");
513
514 return $skill_html;
515 }
516
517 public function renderSkillHTML(
518 int $a_top_skill_id,
519 int $a_user_id = 0,
520 bool $a_edit = false,
521 int $a_tref_id = 0
522 ): string {
523 $ilCtrl = $this->ctrl;
524 $ilUser = $this->user;
526
527 $sub_panels = [];
528
529 if ($a_user_id == 0) {
530 $user = $ilUser;
531 } else {
532 $user = new ilObjUser($a_user_id);
533 }
534
535 $tpl = new ilTemplate("tpl.skill_pres.html", true, true, "Services/Skill");
536
537 $vtree = $this->tree_repo->getVirtualTreeForNodeId($a_top_skill_id);
538 $tref_id = $a_tref_id;
539 $skill_id = $a_top_skill_id;
540 if (ilSkillTreeNode::_lookupType($a_top_skill_id) == "sktr") {
541 $tref_id = $a_top_skill_id;
542 $skill_id = ilSkillTemplateReference::_lookupTemplateId($a_top_skill_id);
543 }
544 $b_skills = $vtree->getSubTreeForCSkillId($skill_id . ":" . $tref_id, true);
545
546 foreach ($b_skills as $bs) {
547 $bs["id"] = $bs["skill_id"];
548 $bs["tref"] = $bs["tref_id"];
549
550 $path = $this->tree_service->getSkillTreePath($bs["id"], $bs["tref"]);
551
552 $panel_comps = [];
553
554
555 // check draft
556 foreach ($path as $p) {
557 if ($p["status"] == ilSkillTreeNode::STATUS_DRAFT) {
558 continue(2);
559 }
560 }
561 reset($path);
562
563 $skill = ilSkillTreeNodeFactory::getInstance($bs["id"]);
564 $level_data = $skill->getLevelData();
565
566
567 $title = $sep = "";
568 $description = "";
569 $found = false;
570 foreach ($path as $p) {
571 if ($found) {
572 $title .= $sep . $p["title"];
573 $sep = " > ";
574 $description = $p["description"];
575 }
576 if ($a_top_skill_id == $p["child"]) {
577 $found = true;
578 }
579 }
580 if (empty($title)) {
581 $title = $lng->txt("skmg_skill_overview");
582 }
583
584 // skill description
585 $panel_comps[] = $this->ui_fac->legacy($this->getBasicSkillDescription((string) $description));
586
587
588 // skill level description
589 $skl_lvl_desc = $this->getSkillLevelDescription($skill);
590 if (!empty($skl_lvl_desc)) {
591 $acc = new ilAccordionGUI();
592 $acc->setBehaviour(ilAccordionGUI::ALL_CLOSED);
593 $acc->addItem($lng->txt('skmg_skill_levels'), $skl_lvl_desc);
594 $panel_comps[] = $this->ui_fac->legacy($acc->getHTML());
595 }
596
597 $prof_comp_head_rendered = false;
598 $has_at_least_one_entry = false;
599 if ($this->getProfileId() > 0) {
600 if ($this->getNonHistoricGapModeView()) {
601 if (!empty($self_eval_gap_item_prof = $this->getSelfEvalGapItem($level_data, $bs["tref"]))) {
602 $panel_comps[] = $this->ui_fac->legacy($this->getSkillEntriesHeader(ilBasicSkill::EVAL_BY_SELF));
603 $has_at_least_one_entry = true;
604 }
605 $panel_comps[] = $this->ui_fac->legacy($self_eval_gap_item_prof);
606 } else {
607 // get all self eval entries and render them
608 $self_eval_entries_latest = $this->getLatestEntriesForSkillHTML(
609 $a_top_skill_id,
610 $bs,
611 $skill,
612 $user,
614 $level_data
615 );
616 $self_eval_entries_non_latest = $this->getNonLatestEntriesForSkillHTML(
617 $a_top_skill_id,
618 $bs,
619 $skill,
620 $user,
622 $level_data
623 );
624
625 if (!empty($self_eval_entries_latest)) {
626 $panel_comps[] = $this->ui_fac->legacy($this->getSkillEntriesHeader(ilBasicSkill::EVAL_BY_SELF));
627 $has_at_least_one_entry = true;
628 }
629 $panel_comps[] = $this->ui_fac->legacy($self_eval_entries_latest);
630 $panel_comps[] = $this->ui_fac->legacy($self_eval_entries_non_latest);
631 }
632
633 if (!$this->skmg_settings->getHideProfileBeforeSelfEval() ||
634 ilBasicSkill::hasSelfEvaluated($user->getId(), $bs["id"], $bs["tref"])) {
635 if ($this->getFilter()->showTargetLevel()) {
636 $panel_comps[] = $this->ui_fac->legacy($this->getSkillEntriesHeader(ilBasicSkill::EVAL_BY_OTHERS));
637 $prof_comp_head_rendered = true;
638 $panel_comps[] = $this->ui_fac->legacy($this->getProfileTargetItem($this->getProfileId(), $level_data, $bs["tref"]));
639 }
640 }
641 }
642
643 if ($this->getNonHistoricGapModeView()) {
644 if (!empty($actual_gap_item = $this->getActualGapItem($level_data, $bs["tref"]))) {
645 $panel_comps[] = $this->ui_fac->legacy($actual_gap_item);
646 $has_at_least_one_entry = true;
647 }
648 if ($this->getProfileId() == 0) {
649 if (!empty($self_eval_gap_item_non_prof = $this->getSelfEvalGapItem($level_data, $bs["tref"]))) {
650 $panel_comps[] = $this->ui_fac->legacy($self_eval_gap_item_non_prof);
651 $has_at_least_one_entry = true;
652 }
653 }
654 } else {
655 if ($this->getProfileId() > 0) {
656 // get all non-self eval entries and render them
657 $object_entries_latest = $this->getLatestEntriesForSkillHTML(
658 $a_top_skill_id,
659 $bs,
660 $skill,
661 $user,
663 $level_data
664 );
665 $object_entries_non_latest = $this->getNonLatestEntriesForSkillHTML(
666 $a_top_skill_id,
667 $bs,
668 $skill,
669 $user,
671 $level_data
672 );
673
674 if (!empty($object_entries_latest) && !$prof_comp_head_rendered) {
675 $panel_comps[] = $this->ui_fac->legacy($this->getSkillEntriesHeader(ilBasicSkill::EVAL_BY_OTHERS));
676 }
677 if (!empty($object_entries_latest)) {
678 $has_at_least_one_entry = true;
679 }
680 $panel_comps[] = $this->ui_fac->legacy($object_entries_latest);
681 $panel_comps[] = $this->ui_fac->legacy($object_entries_non_latest);
682 } else {
683 // get all skill entries and render them
684 $all_entries_latest = $this->getLatestEntriesForSkillHTML(
685 $a_top_skill_id,
686 $bs,
687 $skill,
688 $user,
690 $level_data
691 );
692 $all_entries_non_latest = $this->getNonLatestEntriesForSkillHTML(
693 $a_top_skill_id,
694 $bs,
695 $skill,
696 $user,
698 $level_data
699 );
700
701 if (!empty($all_entries_latest) && !$prof_comp_head_rendered) {
702 $panel_comps[] = $this->ui_fac->legacy($this->getSkillEntriesHeader(ilBasicSkill::EVAL_BY_OTHERS));
703 }
704 if (!empty($all_entries_latest)) {
705 $has_at_least_one_entry = true;
706 }
707 $panel_comps[] = $this->ui_fac->legacy($all_entries_latest);
708 $panel_comps[] = $this->ui_fac->legacy($all_entries_non_latest);
709 }
710 }
711
712 if (!$has_at_least_one_entry) {
713 $panel_comps[] = $this->ui_fac->legacy("<br/>" . $lng->txt("skmg_no_skill_entries"));
714 }
715
716 // materials (new)
717 if ($this->mode != "gap") {
718 $mat = "";
719 if ($this->getFilter()->showMaterialsRessources() && $this->use_materials) {
720 $mat = $this->getMaterials($level_data, $bs["tref"], $user->getId());
721 }
722 if ($mat != "") {
723 $panel_comps[] = $this->ui_fac->legacy($mat);
724 }
725 }
726
727 // suggested resources
728 $sugg = "";
729 if ($this->getFilter()->showMaterialsRessources() && $this->getProfileId() == 0 && !$this->gap_mode_obj_id) {
730 // no profile, just list all resources and only in global view
731 $sugg = $this->getAllSuggestedResources($bs["id"], $bs["tref"]);
732 }
733 if ($sugg != "") {
734 $panel_comps[] = $this->ui_fac->legacy($sugg);
735 }
736
737 $sub = $this->ui_fac->panel()->sub($title, $panel_comps);
738 if ($this->getFilter()->showMaterialsRessources() && $this->getProfileId() > 0
739 && $res = $this->getSuggestedResourcesForProfile($level_data, $bs["id"], $bs["tref"], $this->gap_mode_obj_id)) {
740 $sub = $sub->withFurtherInformation($res);
741 }
742 if ($a_edit) {
743 $actions = [];
744 $ilCtrl->setParameterByClass("ilpersonalskillsgui", "skill_id", $a_top_skill_id);
745 $ilCtrl->setParameterByClass("ilpersonalskillsgui", "tref_id", $bs["tref"]);
746 $ilCtrl->setParameterByClass("ilpersonalskillsgui", "basic_skill_id", $bs["id"]);
747 $ilCtrl->setParameterByClass("ilpersonalskillsgui", "list_mode", $this->requested_list_mode);
748 if ($this->use_materials) {
749 $actions[] = $this->ui_fac->button()->shy(
750 $lng->txt('skmg_assign_materials'),
751 $ilCtrl->getLinkTargetByClass("ilpersonalskillsgui", "assignMaterials")
752 );
753 }
754 $actions[] = $this->ui_fac->button()->shy(
755 $lng->txt('skmg_self_evaluation'),
756 $ilCtrl->getLinkTargetByClass("ilpersonalskillsgui", "selfEvaluation")
757 );
758 $sub = $sub->withActions($this->ui_fac->dropdown()->standard($actions)->withLabel($lng->txt("actions")));
759 }
760
761 $sub_panels[] = $sub;
762
763 $tpl->parseCurrentBlock();
764 }
765
766 $des = $this->getSkillCategoryDescription($skill_id, $tref_id);
767
768 //put the description of the skill category to the very top of the sub panels
769 $sub_panels = $this->ui_fac->legacy($des . $this->ui_ren->render($sub_panels));
770
771 $panel = $this->ui_fac->panel()->standard(
772 ilSkillTreeNode::_lookupTitle($skill_id, $tref_id),
773 $sub_panels
774 );
775
776 if ($a_edit && $this->getProfileId() == 0) {
777 $actions = [];
778
779 $ilCtrl->setParameterByClass("ilpersonalskillsgui", "skill_id", $a_top_skill_id);
780 $actions[] = $this->ui_fac->button()->shy(
781 $lng->txt('skmg_remove_skill'),
782 $ilCtrl->getLinkTargetByClass("ilpersonalskillsgui", "confirmSkillRemove")
783 );
784
785 $panel = $panel->withActions($this->ui_fac->dropdown()->standard($actions)->withLabel($lng->txt("actions")));
786 }
787
788 return $this->ui_ren->render($panel);
789 }
790
791
795 public function getMaterialInfo(int $a_wsp_id, int $a_user_id): array
796 {
797 $ws_tree = new ilWorkspaceTree($a_user_id);
798 $ws_access = new ilWorkspaceAccessHandler();
799
800 $obj_id = $ws_tree->lookupObjectId($a_wsp_id);
801 $caption = ilObject::_lookupTitle($obj_id);
802
803 if (!$this->offline_mode) {
804 $url = $ws_access->getGotoLink($a_wsp_id, $obj_id);
805 } else {
806 $url = $this->offline_mode . "file_" . $obj_id . "/";
807
808 // all possible material types for now
809 switch (ilObject::_lookupType($obj_id)) {
810 case "tstv":
811 $obj = new ilObjTestVerification($obj_id, false);
812 $url .= $obj->getOfflineFilename();
813 break;
814
815 case "excv":
816 $obj = new ilObjExerciseVerification($obj_id, false);
817 $url .= $obj->getOfflineFilename();
818 break;
819
820 case "crsv":
821 $obj = new ilObjCourseVerification($obj_id, false);
822 $url .= $obj->getOfflineFilename();
823 break;
824
825 case "cmxv":
826 $obj = new ilObjCmiXapiVerification($obj_id, false);
827 $url .= $obj->getOfflineFilename();
828 break;
829
830 case "ltiv":
831 $obj = new ilObjLTIConsumerVerification($obj_id, false);
832 $url .= $obj->getOfflineFilename();
833 break;
834
835 case "scov":
836 $obj = new ilObjSCORMVerification($obj_id, false);
837 $url .= $obj->getOfflineFilename();
838 break;
839
840 case "file":
841 $file = new ilObjFile($obj_id, false);
842 $url .= $file->getFileName();
843 break;
844 }
845 }
846
847 return array($caption, $url);
848 }
849
850 public function addSkill(): void
851 {
852 $ilCtrl = $this->ctrl;
853 $ilUser = $this->user;
855
856 ilPersonalSkill::addPersonalSkill($ilUser->getId(), $this->requested_node_id);
857
858 $this->tpl->setOnScreenMessage('success', $lng->txt("msg_object_modified"));
859 $ilCtrl->setParameter($this, "list_mode", self::LIST_SELECTED);
860 $ilCtrl->redirect($this, "listSkills");
861 }
862
863 public function confirmSkillRemove(): void
864 {
867 $ilCtrl = $this->ctrl;
868
869 if ($this->requested_skill_id > 0) {
870 $this->requested_skill_ids[] = $this->requested_skill_id;
871 }
872 if (empty($this->requested_skill_ids)) {
873 $this->tpl->setOnScreenMessage('info', $lng->txt("no_checkbox"), true);
874 $ilCtrl->setParameter($this, "list_mode", self::LIST_SELECTED);
875 $ilCtrl->redirect($this, "listSkills");
876 } else {
877 $cgui = new ilConfirmationGUI();
878 $cgui->setFormAction($ilCtrl->getFormAction($this));
879 $cgui->setHeaderText($lng->txt("skmg_really_remove_skills"));
880 $cgui->setCancel($lng->txt("cancel"), "listSkills");
881 $cgui->setConfirm($lng->txt("remove"), "removeSkills");
882
883 foreach ($this->requested_skill_ids as $i) {
884 $cgui->addItem("id[]", $i, ilSkillTreeNode::_lookupTitle($i));
885 }
886
887 $tpl->setContent($cgui->getHTML());
888 }
889 }
890
891 public function removeSkills(): void
892 {
893 $ilCtrl = $this->ctrl;
894 $ilUser = $this->user;
896
897 if (!empty($this->requested_skill_ids)) {
898 foreach ($this->requested_skill_ids as $n_id) {
899 ilPersonalSkill::removeSkill($ilUser->getId(), $n_id);
900 }
901 }
902
903 $this->tpl->setOnScreenMessage('success', $lng->txt("msg_object_modified"));
904 $ilCtrl->setParameter($this, "list_mode", self::LIST_SELECTED);
905 $ilCtrl->redirect($this, "listSkills");
906 }
907
908
909 //
910 // Materials assignments
911 //
912
916 public function assignMaterials(): void
917 {
918 $ilCtrl = $this->ctrl;
921 $ilToolbar = $this->toolbar;
922 $ilTabs = $this->tabs;
923
924 $cmd = ($this->requested_list_mode == self::LIST_SELECTED || !count($this->user_profiles) > 0)
925 ? "render"
926 : "listAssignedProfile";
927 $ilTabs->setBackTarget(
928 $lng->txt("back"),
929 $ilCtrl->getLinkTarget($this, $cmd)
930 );
931
932 $ilCtrl->saveParameter($this, "skill_id");
933 $ilCtrl->saveParameter($this, "basic_skill_id");
934 $ilCtrl->saveParameter($this, "tref_id");
935
936 $tpl->setTitle(ilSkillTreeNode::_lookupTitle($this->requested_skill_id));
937 $tpl->setTitleIcon(ilUtil::getImagePath("icon_" .
938 ilSkillTreeNode::_lookupType($this->requested_skill_id) .
939 ".svg"));
940
941 // basic skill selection
942 $vtree = $this->tree_repo->getVirtualTreeForNodeId($this->requested_skill_id);
943 $tref_id = 0;
944 $skill_id = $this->requested_skill_id;
945 if (ilSkillTreeNode::_lookupType($this->requested_skill_id) == "sktr") {
946 $tref_id = $this->requested_skill_id;
947 $skill_id = ilSkillTemplateReference::_lookupTemplateId($this->requested_skill_id);
948 }
949 $bs = $vtree->getSubTreeForCSkillId($skill_id . ":" . $tref_id, true);
950
951 $options = [];
952 foreach ($bs as $b) {
953 //$options[$b["id"]] = ilSkillTreeNode::_lookupTitle($b["id"]);
954 $options[$b["skill_id"]] = ilSkillTreeNode::_lookupTitle($b["skill_id"]);
955 }
956
957 $cur_basic_skill_id = ($this->requested_basic_skill_id > 0)
958 ? $this->requested_basic_skill_id
959 : key($options);
960
961 $ilCtrl->setParameter($this, "basic_skill_id", $cur_basic_skill_id);
962
963 if (count($options) > 1) {
964 $si = new ilSelectInputGUI($lng->txt("skmg_skill"), "basic_skill_id");
965 $si->setOptions($options);
966 $si->setValue($cur_basic_skill_id);
967 $ilToolbar->addInputItem($si, true);
968 $ilToolbar->addFormButton(
969 $lng->txt("select"),
970 "assignMaterials"
971 );
972
973 $ilToolbar->setFormAction($ilCtrl->getFormAction($this));
974 }
975
976 // table
978 $this,
979 "assignMaterials",
980 $this->requested_skill_id,
981 $this->requested_tref_id,
982 $cur_basic_skill_id
983 );
984
985 $tpl->setContent($tab->getHTML());
986 }
987
988
992 public function assignMaterial(): void
993 {
994 $ilCtrl = $this->ctrl;
995 $ilUser = $this->user;
998 $ilTabs = $this->tabs;
999 $ilSetting = $this->setting;
1000 $ui = $this->ui;
1001
1002 $message = "";
1003 if (!$ilSetting->get("disable_personal_workspace")) {
1004 $url = 'ilias.php?baseClass=ilDashboardGUI&amp;cmd=jumpToWorkspace';
1005 $mbox = $ui->factory()->messageBox()->info($lng->txt("skmg_ass_materials_from_workspace"))
1006 ->withLinks([$ui->factory()->link()->standard(
1007 $lng->txt("personal_resources"),
1008 $url
1009 )]);
1010 $message = $ui->renderer()->render($mbox);
1011 }
1012
1013 $ilCtrl->saveParameter($this, "skill_id");
1014 $ilCtrl->saveParameter($this, "level_id");
1015 $ilCtrl->saveParameter($this, "tref_id");
1016 $ilCtrl->saveParameter($this, "basic_skill_id");
1017
1018 $ilTabs->setBackTarget(
1019 $lng->txt("back"),
1020 $ilCtrl->getLinkTarget($this, "assignMaterials")
1021 );
1022
1023
1024 $exp = new ilWorkspaceExplorerGUI($ilUser->getId(), $this, "assignMaterial", $this, "");
1025 $exp->setTypeWhiteList(array("blog", "wsrt", "wfld", "file", "tstv", "excv"));
1026 $exp->setSelectableTypes(array("file", "tstv", "excv"));
1027 $exp->setSelectMode("wsp_ids", true);
1028 if ($exp->handleCommand()) {
1029 return;
1030 }
1031
1032 // fill template
1033 $mtpl = new ilTemplate("tpl.materials_selection.html", true, true, "Services/Skill");
1034 $mtpl->setVariable("EXP", $exp->getHTML());
1035
1036 // toolbars
1037 $tb = new ilToolbarGUI();
1038 $tb->addFormButton(
1039 $lng->txt("select"),
1040 "selectMaterial"
1041 );
1042 $tb->setFormAction($ilCtrl->getFormAction($this));
1043 $tb->setOpenFormTag(true);
1044 $tb->setCloseFormTag(false);
1045 $mtpl->setVariable("TOOLBAR1", $tb->getHTML());
1046 $tb->setOpenFormTag(false);
1047 $tb->setCloseFormTag(true);
1048 $mtpl->setVariable("TOOLBAR2", $tb->getHTML());
1049
1050 $tpl->setContent($message . $mtpl->get());
1051 }
1052
1053 public function selectMaterial(): void
1054 {
1055 $ilCtrl = $this->ctrl;
1056 $ilUser = $this->user;
1057 $lng = $this->lng;
1058
1059
1060 if (!empty($this->requested_wsp_ids)) {
1061 foreach ($this->requested_wsp_ids as $w) {
1063 $ilUser->getId(),
1064 $this->requested_skill_id,
1065 $this->requested_tref_id,
1066 $this->requested_basic_skill_id,
1067 $this->requested_level_id,
1068 $w
1069 );
1070 }
1071 $this->tpl->setOnScreenMessage('success', $lng->txt("msg_obj_modified"), true);
1072 }
1073
1074 $ilCtrl->saveParameter($this, "skill_id");
1075 $ilCtrl->saveParameter($this, "level_id");
1076 $ilCtrl->saveParameter($this, "tref_id");
1077 $ilCtrl->saveParameter($this, "basic_skill_id");
1078
1079 $ilCtrl->redirect($this, "assignMaterials");
1080 }
1081
1082 public function removeMaterial(): void
1083 {
1084 $ilCtrl = $this->ctrl;
1085 $ilUser = $this->user;
1086 $lng = $this->lng;
1087
1088
1090 $ilUser->getId(),
1091 $this->requested_tref_id,
1092 $this->requested_level_id,
1093 $this->requested_wsp_id
1094 );
1095 $this->tpl->setOnScreenMessage('success', $lng->txt("msg_obj_modified"), true);
1096 $ilCtrl->redirect($this, "assignMaterials");
1097 }
1098
1099
1100 //
1101 // Self evaluation
1102 //
1103
1104 public function selfEvaluation(): void
1105 {
1106 $ilCtrl = $this->ctrl;
1107 $lng = $this->lng;
1108 $tpl = $this->tpl;
1109 $ilToolbar = $this->toolbar;
1110 $ilTabs = $this->tabs;
1111
1112 $cmd = ($this->requested_list_mode == self::LIST_SELECTED || !count($this->user_profiles) > 0)
1113 ? "render"
1114 : "listAssignedProfile";
1115 $ilTabs->setBackTarget(
1116 $lng->txt("back"),
1117 $ilCtrl->getLinkTarget($this, $cmd)
1118 );
1119
1120 $ilCtrl->saveParameter($this, "skill_id");
1121 $ilCtrl->saveParameter($this, "basic_skill_id");
1122 $ilCtrl->saveParameter($this, "tref_id");
1123
1124 $tpl->setTitle(ilSkillTreeNode::_lookupTitle($this->requested_skill_id));
1125 $tpl->setTitleIcon(ilUtil::getImagePath("icon_" .
1126 ilSkillTreeNode::_lookupType($this->requested_skill_id) .
1127 ".svg"));
1128
1129 // basic skill selection
1130 $vtree = $this->tree_repo->getVirtualTreeForNodeId($this->requested_skill_id);
1131 $tref_id = 0;
1132 $skill_id = $this->requested_skill_id;
1133 if (ilSkillTreeNode::_lookupType($this->requested_skill_id) == "sktr") {
1134 $tref_id = $this->requested_skill_id;
1135 $skill_id = ilSkillTemplateReference::_lookupTemplateId($this->requested_skill_id);
1136 }
1137 $bs = $vtree->getSubTreeForCSkillId($skill_id . ":" . $tref_id, true);
1138
1139
1140 $options = [];
1141 foreach ($bs as $b) {
1142 $options[$b["skill_id"]] = ilSkillTreeNode::_lookupTitle($b["skill_id"]);
1143 }
1144
1145 $cur_basic_skill_id = ($this->requested_basic_skill_id > 0)
1146 ? $this->requested_basic_skill_id
1147 : key($options);
1148
1149 $ilCtrl->setParameter($this, "basic_skill_id", $cur_basic_skill_id);
1150
1151 if (count($options) > 1) {
1152 $si = new ilSelectInputGUI($lng->txt("skmg_skill"), "basic_skill_id");
1153 $si->setOptions($options);
1154 $si->setValue($cur_basic_skill_id);
1155 $ilToolbar->addInputItem($si, true);
1156 $ilToolbar->addFormButton(
1157 $lng->txt("select"),
1158 "selfEvaluation"
1159 );
1160
1161 $ilToolbar->setFormAction($ilCtrl->getFormAction($this));
1162 }
1163
1164 // table
1166 $this,
1167 "selfEvaluation",
1168 $this->requested_skill_id,
1169 $this->requested_tref_id,
1170 $cur_basic_skill_id
1171 );
1172
1173 $tpl->setContent($tab->getHTML());
1174 }
1175
1176 public function saveSelfEvaluation(): void
1177 {
1178 $ilCtrl = $this->ctrl;
1179 $ilUser = $this->user;
1180 $lng = $this->lng;
1181
1183 $ilUser->getId(),
1184 $this->requested_skill_id,
1185 $this->requested_tref_id,
1186 $this->requested_basic_skill_id,
1187 $this->requested_self_eval_level_id
1188 );
1189 $this->tpl->setOnScreenMessage('success', $lng->txt("msg_obj_modified"), true);
1190
1191 /* $ilCtrl->saveParameter($this, "skill_id");
1192 $ilCtrl->saveParameter($this, "level_id");
1193 $ilCtrl->saveParameter($this, "tref_id");
1194 $ilCtrl->saveParameter($this, "basic_skill_id");*/
1195
1196 $cmd = ($this->requested_list_mode == self::LIST_SELECTED || !count($this->user_profiles) > 0)
1197 ? "render" : "listAssignedProfile";
1198 $ilCtrl->redirect($this, $cmd);
1199 }
1200
1201 public function listSkillsForAdd(): void
1202 {
1203 $ilCtrl = $this->ctrl;
1204 $lng = $this->lng;
1205 $tpl = $this->tpl;
1206 $ilTabs = $this->tabs;
1207
1208
1209 $ilCtrl->setParameter($this, "list_mode", self::LIST_SELECTED);
1210 $ilTabs->setBackTarget(
1211 $lng->txt("back"),
1212 $ilCtrl->getLinkTarget($this, "render")
1213 );
1214 $ilCtrl->clearParameterByClass(get_class($this), "list_mode");
1215
1216 $exp = new ilPersonalSkillExplorerGUI($this, "listSkillsForAdd", $this, "addSkill");
1217 if ($exp->getHasSelectableNodes()) {
1218 if (!$exp->handleCommand()) {
1219 $tpl->setContent($exp->getHTML());
1220 }
1221 $this->tpl->setOnScreenMessage('info', $lng->txt("skmg_select_skill"));
1222 } else {
1223 $this->tpl->setOnScreenMessage('info', $lng->txt("skmg_no_nodes_selectable"));
1224 }
1225 }
1226
1227 public function listProfilesForGap(): void
1228 {
1229 $tpl = $this->tpl;
1230
1231 //$a_user_id = $ilUser->getId();
1232
1233 //$profiles = ilSkillProfile::getProfilesOfUser($a_user_id);
1234
1235 if (count($this->cont_profiles) == 0 && $this->obj_skills == null) {
1236 return;
1237 }
1238
1239 $this->determineCurrentProfile();
1240 $this->showProfileSelectorToolbar();
1241
1242 $html = $this->showInfoBox() . $this->getGapAnalysisHTML();
1243 $tpl->setContent($html);
1244 }
1245
1246 public function showInfoBox(): string
1247 {
1248 $link = $this->ui_fac->link()->standard(
1249 $this->lng->txt("skmg_open_all_assigned_profiles"),
1250 $this->ctrl->getLinkTargetByClass(["ilDashboardGUI", "ilAchievementsGUI", "ilPersonalSkillsGUI"])
1251 );
1252 $box = $this->ui_fac->messageBox()->info($this->lng->txt("skmg_cont_profiles_info"))->withLinks([$link]);
1253
1254 return $this->ui_ren->render($box);
1255 }
1256
1257 public function showProfileSelectorToolbar(): void
1258 {
1259 $ilToolbar = $this->toolbar;
1260 $lng = $this->lng;
1261 $ilCtrl = $this->ctrl;
1262
1263 $options = [];
1264 $cont_options = [];
1265 if (is_array($this->obj_skills) && $this->obj_id > 0) {
1266 $options[0] = $lng->txt("obj_" . ilObject::_lookupType($this->obj_id)) . ": " . ilObject::_lookupTitle($this->obj_id);
1267 }
1268
1269 foreach ($this->cont_profiles as $p) {
1270 $cont_options[$p["profile_id"]] = $p["title"];
1271 }
1272
1273 asort($cont_options);
1274 $options = $options + $cont_options;
1275
1276 $si = new ilSelectInputGUI($lng->txt("skmg_profile"), "profile_id");
1277 $si->setOptions($options);
1278 $si->setValue($this->getProfileId());
1279 $ilToolbar->addInputItem($si, true);
1280 $ilToolbar->addFormButton(
1281 $lng->txt("select"),
1282 "selectProfile"
1283 );
1284 $ilToolbar->setFormAction($ilCtrl->getFormAction($this));
1285 }
1286
1287 public function setGapAnalysisActualStatusModePerType(string $a_type, string $a_cat_title = ""): void
1288 {
1289 $this->gap_mode = "max_per_type";
1290 $this->gap_mode_type = $a_type;
1291 $this->gap_cat_title = $a_cat_title;
1292 $this->mode = "gap";
1293 }
1294
1295 public function setGapAnalysisActualStatusModePerObject(int $a_obj_id, string $a_cat_title = ""): void
1296 {
1297 $this->gap_mode = "max_per_object";
1298 $this->gap_mode_obj_id = $a_obj_id;
1299 $this->gap_cat_title = $a_cat_title;
1300 $this->mode = "gap";
1301 }
1302
1303 public function getGapAnalysisHTML(int $a_user_id = 0, array $a_skills = null): string
1304 {
1305 $ilUser = $this->user;
1306 $lng = $this->lng;
1307
1308 // needed fix for profiles in gap view, because there is no filter shown (yet)
1309 $this->getFilter()->clear();
1310
1311 if ($a_skills == null) {
1312 $a_skills = $this->obj_skills;
1313 }
1314
1315 $intro_html = "";
1316 if ($this->getIntroText() != "") {
1317 $pan = ilPanelGUI::getInstance();
1318 $pan->setPanelStyle(ilPanelGUI::PANEL_STYLE_PRIMARY);
1319 $pan->setBody($this->getIntroText());
1320 $intro_html = $pan->getHTML();
1321 }
1322
1323 // $this->setTabs("list_skills");
1324
1325 if ($a_user_id == 0) {
1326 $user_id = $ilUser->getId();
1327 } else {
1328 $user_id = $a_user_id;
1329 }
1330
1331 $skills = [];
1332 if ($this->getProfileId() > 0) {
1333 $profile = $this->profile_manager->getById($this->getProfileId());
1334 $this->profile_levels = $profile->getSkillLevels();
1335
1336 foreach ($this->profile_levels as $l) {
1337 $skills[] = array(
1338 "base_skill_id" => $l["base_skill_id"],
1339 "tref_id" => $l["tref_id"],
1340 "level_id" => $l["level_id"]
1341 );
1342 }
1343 } else {
1344 $skills = $a_skills;
1345 }
1346
1347 // get actual levels for gap analysis
1348 $this->actual_levels = $this->profile_completion_manager->getActualMaxLevels(
1349 $user_id,
1350 $skills,
1351 $this->gap_mode,
1352 $this->gap_mode_type,
1353 $this->gap_mode_obj_id
1354 );
1355 $this->next_level_fuls = $this->profile_completion_manager->getActualNextLevelFulfilments(
1356 $user_id,
1357 $skills,
1358 $this->gap_mode,
1359 $this->gap_mode_type,
1360 $this->gap_mode_obj_id
1361 );
1362
1363 if (!$this->getProfileId() > 0) {
1364 // order skills per virtual skill tree
1365 $vtree = $this->tree_service->getGlobalVirtualSkillTree();
1366 $skills = $vtree->getOrderedNodeset($skills, "base_skill_id", "tref_id");
1367 }
1368
1369 $bc_skills = [];
1370 $html = "";
1371
1372 foreach ($skills as $s) {
1373 $path = $this->tree_service->getSkillTreePath($s["base_skill_id"]);
1374
1375 // check draft
1376 foreach ($path as $p) {
1377 if ($p["status"] == ilSkillTreeNode::STATUS_DRAFT) {
1378 continue(2);
1379 }
1380 }
1381 $bc_skills[] = $s;
1382 $html .= $this->getSkillHTML($s["base_skill_id"], $user_id, false, $s["tref_id"]);
1383 }
1384
1385
1386 // output bar charts
1387 $all_chart_html = $this->getBarChartHTML($bc_skills);
1388
1389 if (!empty($all_chart_html)) {
1390 $pan = ilPanelGUI::getInstance();
1391 $pan->setPanelStyle(ilPanelGUI::PANEL_STYLE_PRIMARY);
1392 $pan->setBody($all_chart_html);
1393 $all_chart_html = $pan->getHTML();
1394 }
1395
1396 // list skills
1397
1398 return $intro_html . $all_chart_html . $html;
1399 }
1400
1404 protected function getBarChartHTML(array $skills): string
1405 {
1406 $lng = $this->lng;
1407
1408 // dimension names
1409 $target_dim = $lng->txt("skmg_target_level");
1410 $eval_dim = $lng->txt("skmg_eval_type_1");
1411 if ($this->gap_cat_title != "") {
1412 $eval_dim = $this->gap_cat_title;
1413 } elseif ($this->gap_mode == "max_per_type") {
1414 $eval_dim = $lng->txt("objs_" . $this->gap_mode_type);
1415 } elseif ($this->gap_mode == "max_per_object") {
1416 $eval_dim = ilObject::_lookupTitle($this->gap_mode_obj_id);
1417 }
1418 $self_eval_dim = $lng->txt("skmg_self_evaluation");
1419
1420 $incl_self_eval = false;
1421 $self_vals = [];
1422 if (count($this->getGapAnalysisSelfEvalLevels()) > 0) {
1423 $incl_self_eval = true;
1424 $self_vals = $this->getGapAnalysisSelfEvalLevels();
1425 }
1426
1427 $chart_counter = 0;
1428 $bar_counter = 0;
1429 $tmp_labels = [];
1430 $all_chart_data = [];
1431 $render_eval_dim = false;
1432 foreach ($skills as $l) {
1433 $bs = new ilBasicSkill($l["base_skill_id"]);
1434 $levels = $bs->getLevelData();
1435 // filter out skills with no levels from chart
1436 if (empty($levels)) {
1437 continue;
1438 }
1439
1440 $cnt = 0;
1441 $points = [];
1442 $tooltips = [];
1443 $labels = [0 => ""];
1444 foreach ($levels as $lv) {
1445 // points and tooltips
1446 $cnt++;
1447 $labels[] = $lv["title"];
1448 if ($this->getProfileId() > 0) {
1449 if ($l["level_id"] == $lv["id"]) {
1450 $points[$target_dim] = [$cnt - 0.01, $cnt];
1451 $tooltips[$target_dim] = $lv["title"];
1452 } else {
1453 $points[$target_dim] = $points[$target_dim] ?? null;
1454 $tooltips[$target_dim] = $tooltips[$target_dim] ?? null;
1455 }
1456 }
1457 if ($this->actual_levels[$l["base_skill_id"]][$l["tref_id"]] == $lv["id"]) {
1458 $perc = $this->next_level_fuls[$l["base_skill_id"]][$l["tref_id"]];
1459 $points[$eval_dim] = $cnt + $perc;
1460 $tooltips[$eval_dim] = null;
1461 if ($perc > 0) {
1462 $tooltips[$eval_dim] = $lv["title"] . " + " . $perc * 100 . "%";
1463 }
1464 $render_eval_dim = true;
1465 } else {
1466 $points[$eval_dim] = $points[$eval_dim] ?? null;
1467 $tooltips[$eval_dim] = $tooltips[$eval_dim] ?? null;
1468 if (!is_null($points[$eval_dim])) {
1469 $render_eval_dim = true;
1470 }
1471 }
1472 if ($incl_self_eval) {
1473 if (($self_vals[$l["base_skill_id"]][$l["tref_id"]] ?? 0) == $lv["id"]) {
1474 $points[$self_eval_dim] = $cnt;
1475 $tooltips[$self_eval_dim] = null;
1476 } else {
1477 $points[$self_eval_dim] = $points[$self_eval_dim] ?? null;
1478 $tooltips[$self_eval_dim] = $tooltips[$self_eval_dim] ?? null;
1479 }
1480 }
1481 }
1482
1483 // do not show eval dimension if there is no data for it
1484 if (!$render_eval_dim) {
1485 unset($points[$eval_dim]);
1486 unset($tooltips[$eval_dim]);
1487 }
1488
1489 /*
1490 * create new chart when number and title of the levels of the current skill are not identical with
1491 * the previous skill
1492 */
1493 if (!empty($tmp_labels) && $tmp_labels !== $labels) {
1494 $chart_counter++;
1495 $bar_counter = 0;
1496 }
1497 $tmp_labels = $labels;
1498
1499 $all_chart_data[$chart_counter][$bar_counter]["item_title"] = ilBasicSkill::_lookupTitle(
1500 $l["base_skill_id"],
1501 $l["tref_id"]
1502 );
1503 $all_chart_data[$chart_counter][$bar_counter]["levels"] = $labels;
1504 $all_chart_data[$chart_counter][$bar_counter]["points"] = $points;
1505 $all_chart_data[$chart_counter][$bar_counter]["tooltips"] = $tooltips;
1506
1507 $bar_counter++;
1508 }
1509
1510 $all_chart_html = "";
1511 foreach ($all_chart_data as $chart_data) {
1512 $c_dimension = $this->data_fac->dimension()->cardinal($chart_data[0]["levels"]);
1513 $r_dimension = $this->data_fac->dimension()->range($c_dimension);
1514
1515 // dimensions and bar configs
1516 $ds = [];
1517 $bars = [];
1518
1519 if ($this->getProfileId() > 0) {
1520 $target_bar = new BarConfig();
1521 $target_bar = $target_bar->withRelativeWidth(1.1);
1522 $target_bar = $target_bar->withColor($this->data_fac->color("#333333"));
1523 $ds[$target_dim] = $r_dimension;
1524 $bars[$target_dim] = $target_bar;
1525 }
1526
1527 if ($render_eval_dim) {
1528 $eval_bar = new BarConfig();
1529 $eval_bar = $eval_bar->withRelativeWidth(0.5);
1530 $eval_bar = $eval_bar->withColor($this->data_fac->color("#307C88"));
1531 if (ilObject::_lookupType($this->gap_mode_obj_id) == "tst") {
1532 $eval_bar = $eval_bar->withColor($this->data_fac->color("#d38000"));
1533 }
1534 $ds[$eval_dim] = $c_dimension;
1535 $bars[$eval_dim] = $eval_bar;
1536 }
1537
1538 if ($incl_self_eval) {
1539 $self_eval_bar = new BarConfig();
1540 $self_eval_bar = $self_eval_bar->withRelativeWidth(0.5);
1541 $self_eval_bar = $self_eval_bar->withColor($this->data_fac->color("#557b2e"));
1542 $ds[$self_eval_dim] = $c_dimension;
1543 $bars[$self_eval_dim] = $self_eval_bar;
1544 }
1545
1546 $dataset = $this->data_fac->dataset($ds);
1547
1548 $render_chart = false;
1549 foreach ($chart_data as $a) {
1550 if ($render_eval_dim && !isset($a["points"][$eval_dim])) {
1551 $a["points"][$eval_dim] = null;
1552 $a["tooltips"][$eval_dim] = null;
1553 }
1554 $dataset = $dataset->withPoint($a["item_title"], $a["points"]);
1555 $dataset = $dataset->withAlternativeInformation($a["item_title"], $a["tooltips"]);
1556 foreach ($a["points"] as $dim => $p) {
1557 // render chart only if there are bars
1558 if (!is_null($p) && $dim != $target_dim) {
1559 $render_chart = true;
1560 }
1561 }
1562 }
1563
1564 if ($render_chart) {
1565 $bar_chart = $this->ui_fac->chart()->bar()->horizontal(
1566 "",
1567 $dataset,
1568 $bars
1569 );
1570
1571 $x_axis = new XAxis();
1572 $x_axis = $x_axis->withMaxValue(count($chart_data[0]["levels"]) - 1);
1574 $bar_chart = $bar_chart->withCustomXAxis($x_axis);
1575 $bar_chart = $bar_chart->withTitleVisible(false);
1576
1577 $all_chart_html .= $this->ui_ren->render($bar_chart);
1578 }
1579 }
1580
1581 return $all_chart_html;
1582 }
1583
1584 public function selectProfile(): void
1585 {
1586 $ilCtrl = $this->ctrl;
1587
1588 $ilCtrl->setParameter($this, "profile_id", $this->requested_profile_id);
1589 if ($this->mode == "gap") {
1590 $ilCtrl->redirect($this, "listProfilesForGap");
1591 } else {
1592 $ilCtrl->redirect($this, "listAssignedProfile");
1593 }
1594 }
1595
1596 public function getMaterials(array $a_levels, int $a_tref_id = 0, int $a_user_id = 0): string
1597 {
1598 $ilUser = $this->user;
1599 $lng = $this->lng;
1600
1601 if ($a_user_id == 0) {
1602 $a_user_id = $ilUser->getId();
1603 }
1604
1605 // only render, if materials given
1606 $got_mat = false;
1607 foreach ($a_levels as $v) {
1609 $a_user_id,
1610 $a_tref_id,
1611 $v["id"]
1612 );
1613 if ($mat_cnt > 0) {
1614 $got_mat = true;
1615 }
1616 }
1617 if (!$got_mat) {
1618 return "";
1619 }
1620
1621 $tpl = new ilTemplate("tpl.skill_materials.html", true, true, "Services/Skill");
1622 foreach ($a_levels as $k => $v) {
1623 $got_mat = false;
1625 $a_user_id,
1626 $a_tref_id,
1627 $v["id"]
1628 ) as $item) {
1629 $tpl->setCurrentBlock("material");
1630 $mat_data = $this->getMaterialInfo($item["wsp_id"], $a_user_id);
1631 $tpl->setVariable("HREF_LINK", $mat_data[1]);
1632 $tpl->setVariable("TXT_LINK", $mat_data[0]);
1633 $tpl->parseCurrentBlock();
1634 $got_mat = true;
1635 }
1636 if ($got_mat) {
1637 $tpl->setCurrentBlock("level");
1638 $tpl->setVariable("LEVEL_VAL", $v["title"]);
1639 $tpl->parseCurrentBlock();
1640 }
1641 }
1642 $tpl->setVariable("TXT_MATERIAL", $lng->txt("skmg_materials"));
1643
1644 return $tpl->get();
1645 }
1646
1647 public function getProfileTargetItem(int $a_profile_id, array $a_levels, int $a_tref_id = 0): string
1648 {
1649 $lng = $this->lng;
1650
1651 $profile = $this->profile_manager->getById($a_profile_id);
1652 $profile_levels = $profile->getSkillLevels();
1653
1654 $a_activated_levels = [];
1655
1656 foreach ($a_levels as $k => $v) {
1657 foreach ($profile_levels as $pl) {
1658 if ($pl["level_id"] == $v["id"] &&
1659 $pl["base_skill_id"] == $v["skill_id"] &&
1660 $a_tref_id == $pl["tref_id"]) {
1661 $a_activated_levels[] = $pl["level_id"];
1662 }
1663 }
1664 }
1665
1666 $tpl = new ilTemplate("tpl.skill_eval_item.html", true, true, "Services/Skill");
1667 $tpl->setVariable("SCALE_BAR", $this->getScaleBar($a_levels, $a_activated_levels));
1668
1669 $tpl->setVariable("TYPE", $lng->txt("skmg_target_level"));
1670 $tpl->setVariable("TITLE", "");
1671
1672 return $tpl->get();
1673 }
1674
1675 public function getActualGapItem(array $a_levels, int $a_tref_id = 0): string
1676 {
1677 $lng = $this->lng;
1678
1679 $a_activated_levels = [];
1680 foreach ($a_levels as $k => $v) {
1681 if ($this->actual_levels[$v["skill_id"]][$a_tref_id] == $v["id"]) {
1682 $a_activated_levels[] = $v["id"];
1683 }
1684 }
1685
1686 if (empty($a_activated_levels)) {
1687 return "";
1688 }
1689
1690 $title = "";
1691 if ($this->gap_cat_title != "") {
1692 $title = $this->gap_cat_title;
1693 } elseif ($this->gap_mode == "max_per_type") {
1694 $title = $lng->txt("objs_" . $this->gap_mode_type);
1695 } elseif ($this->gap_mode == "max_per_object") {
1696 $title = ilObject::_lookupTitle($this->gap_mode_obj_id);
1697 }
1698
1699 $tpl = new ilTemplate("tpl.skill_eval_item.html", true, true, "Services/Skill");
1700 $tpl->setVariable("SCALE_BAR", $this->getScaleBar($a_levels, $a_activated_levels));
1701
1702 $type = 1;
1703 $tpl->setVariable("TYPE", $lng->txt("skmg_eval_type_latest_" . $type));
1704 if ($type > 0) {
1705 $tpl->touchBlock("st" . $type);
1706 $tpl->touchBlock("stb" . $type);
1707 }
1708
1709 if ($title != $lng->txt("skmg_eval_type_" . $type)) {
1710 $tpl->setVariable("TITLE", $title);
1711 }
1712
1713 return $tpl->get();
1714 }
1715
1716 public function getSelfEvalGapItem(array $a_levels, int $a_tref_id = 0): string
1717 {
1718 $lng = $this->lng;
1719
1720 $self_vals = $this->getGapAnalysisSelfEvalLevels();
1721 if (empty($self_vals)) {
1722 return "";
1723 }
1724
1725 $a_activated_levels = [];
1726 foreach ($a_levels as $k => $v) {
1727 if (isset($self_vals[$v["skill_id"]][$a_tref_id]) &&
1728 $self_vals[$v["skill_id"]][$a_tref_id] == $v["id"]) {
1729 $a_activated_levels[] = $v["id"];
1730 }
1731 }
1732
1733 if (empty($a_activated_levels)) {
1734 return "";
1735 }
1736
1737 $tpl = new ilTemplate("tpl.skill_eval_item.html", true, true, "Services/Skill");
1738 $tpl->setVariable("SCALE_BAR", $this->getScaleBar($a_levels, $a_activated_levels));
1739
1740 $type = 3;
1741 $tpl->setVariable("TYPE", $lng->txt("skmg_eval_type_latest_" . $type));
1742 if ($type > 0) {
1743 $tpl->touchBlock("st" . $type);
1744 $tpl->touchBlock("stb" . $type);
1745 }
1746
1747 return $tpl->get();
1748 }
1749
1755 public function getScaleBar(array $a_levels, $a_activated_levels): string
1756 {
1757 $vals = [];
1758
1759 if (!is_array($a_activated_levels)) {
1760 $a_activated_levels = array($a_activated_levels);
1761 }
1762
1763 foreach ($a_levels as $level) {
1764 $vals[$level["title"]] = (in_array($level["id"], $a_activated_levels));
1765 }
1766 $scale_bar = $this->ui_fac->chart()->scaleBar($vals);
1767
1768 return $this->ui_ren->render($scale_bar);
1769 }
1770
1771 public function getEvalItem(array $a_levels, array $a_level_entry, bool $is_latest = false): string
1772 {
1773 $lng = $this->lng;
1774 $ilAccess = $this->access;
1775
1776 $tpl = new ilTemplate("tpl.skill_eval_item.html", true, true, "Services/Skill");
1777 $tpl->setVariable("SCALE_BAR", $this->getScaleBar($a_levels, $a_level_entry["level_id"]));
1778
1780
1781 if ($a_level_entry["self_eval"] == 1) {
1783 }
1784
1785 if ($a_level_entry["trigger_obj_type"] == "tst") {
1787 }
1788
1790 $title = "";
1791 if ($a_level_entry["trigger_obj_id"] > 0) {
1792 if (ilObject::_exists($a_level_entry["trigger_ref_id"], true)) {
1793 $title = ilObject::_lookupTitle($a_level_entry["trigger_obj_id"]);
1794 } elseif (!empty($del_data = ilObjectDataDeletionLog::get($a_level_entry["trigger_obj_id"]))) {
1795 $title = $del_data["title"];
1796 } else {
1797 $title = ($a_level_entry["trigger_title"]) ?? "";
1798 }
1799 }
1800
1801 if ($a_level_entry["trigger_ref_id"] > 0
1802 && $ilAccess->checkAccess("read", "", $a_level_entry["trigger_ref_id"])) {
1803 $title = "<a href='" . ilLink::_getLink($a_level_entry["trigger_ref_id"]) . "'>" . $title . "</a>";
1804 }
1805
1806 if ($is_latest) {
1807 $tpl->setVariable("TYPE", $lng->txt("skmg_eval_type_latest_" . $type));
1808 } else {
1809 $tpl->setVariable("TYPE", $lng->txt("skmg_eval_type_" . $type));
1810 }
1811 if ($type > 0) {
1812 $tpl->touchBlock("st" . $type);
1813 $tpl->touchBlock("stb" . $type);
1814 }
1815 $tpl->setVariable("TITLE", $title);
1816 $tpl->setVariable(
1817 "DATE",
1818 ilDatePresentation::formatDate(new ilDate($a_level_entry["status_date"], IL_CAL_DATETIME))
1819 );
1820
1822
1823 return $tpl->get();
1824 }
1825
1827 int $top_skill_id,
1828 array $bs,
1829 ilSkillTreeNode $skill,
1830 ilObjUser $user,
1831 int $eval_type,
1832 array $level_data
1833 ): string {
1834 $lng = $this->lng;
1835
1836 $tpl = new ilTemplate("tpl.skill_entries_latest.html", true, true, "Services/Skill");
1837
1838 $user_entries = $skill->getAllHistoricLevelEntriesOfUser($bs["tref"], $user->getId(), $eval_type);
1839 $user_entries_filtered = $this->getFilteredEntriesForSkill(
1840 $user_entries,
1841 $top_skill_id,
1842 $bs,
1843 $user
1844 );
1845 if ($eval_type == ilBasicSkill::EVAL_BY_SELF) {
1846 $latest_entries = $this->getSelfEvalEntriesLatestOnly($user_entries_filtered);
1847 } else {
1848 $latest_entries = $this->getAllEntriesLatestOnly($user_entries_filtered);
1849 }
1850
1851 $latest_entries_html = "";
1852 foreach ($latest_entries as $entry) {
1853 $latest_entries_html .= $this->ui_ren->render(
1854 $this->ui_fac->legacy($this->getEvalItem($level_data, $entry, true))
1855 );
1856 }
1857
1858 if (!empty($latest_entries_html)) {
1859 $tpl->setVariable("SKILL_ENTRIES", $latest_entries_html);
1860
1861 if (count($user_entries_filtered) != count($latest_entries)) {
1862 $tpl->setCurrentBlock("all_entries_button");
1863 $show_all_button = $this->ui_fac->button()->standard($lng->txt("skmg_show_all"), "#")
1864 ->withOnLoadCode(function ($id) {
1865 return "$('#$id').on('click', function() {SkillEntries.showNonLatest($id); return false;})";
1866 });
1867 $tpl->setVariable("BUTTON", $this->ui_ren->render($show_all_button));
1868 $tpl->parseCurrentBlock();
1869 }
1870
1871 return $tpl->get();
1872 }
1873
1874 return "";
1875 }
1876
1878 int $top_skill_id,
1879 array $bs,
1880 ilSkillTreeNode $skill,
1881 ilObjUser $user,
1882 int $eval_type,
1883 array $level_data
1884 ): string {
1885 $lng = $this->lng;
1886
1887 $tpl = new ilTemplate("tpl.skill_entries_non_latest.html", true, true, "Services/Skill");
1888
1889 $user_entries = $skill->getAllHistoricLevelEntriesOfUser($bs["tref"], $user->getId(), $eval_type);
1890 $user_entries_filtered = $this->getFilteredEntriesForSkill(
1891 $user_entries,
1892 $top_skill_id,
1893 $bs,
1894 $user
1895 );
1896 if ($eval_type == ilBasicSkill::EVAL_BY_SELF) {
1897 $non_latest_entries = $this->getSelfEvalEntriesWithoutLatest($user_entries_filtered);
1898 } else {
1899 $non_latest_entries = $this->getAllEntriesWithoutLatest($user_entries_filtered);
1900 }
1901
1902 $non_latest_entries_filtered_html = "";
1903 foreach ($non_latest_entries as $entry) {
1904 $non_latest_entries_filtered_html .= $this->ui_ren->render(
1905 $this->ui_fac->legacy($this->getEvalItem($level_data, $entry, false))
1906 );
1907 }
1908
1909 if (!empty($non_latest_entries_filtered_html)) {
1910 $tpl->setVariable("SKILL_ENTRIES", $non_latest_entries_filtered_html);
1911
1912 $show_latest_button = $this->ui_fac->button()->standard($lng->txt("skmg_show_latest_entries"), "#")
1913 ->withOnLoadCode(function ($id) {
1914 return "$('#$id').on('click', function() {SkillEntries.hideNonLatest($id); return false;})";
1915 });
1916 $tpl->setVariable("BUTTON", $this->ui_ren->render($show_latest_button));
1917
1918 return $tpl->get();
1919 }
1920
1921 return "";
1922 }
1923
1924 protected function getFilteredEntriesForSkill(
1925 array $entries,
1926 int $top_skill_id,
1927 array $bs,
1928 ilObjUser $user
1929 ): array {
1930 // get date of self evaluation
1931 $se_date = ilPersonalSkill::getSelfEvaluationDate($user->getId(), $top_skill_id, $bs["tref"], $bs["id"]);
1932 $se_rendered = $se_date == "";
1933
1934 $filtered_entries = [];
1935 foreach ($entries as $level_entry) {
1936 if (count($this->getTriggerObjectsFilter()) && !in_array($level_entry['trigger_obj_id'], $this->getTriggerObjectsFilter())) {
1937 continue;
1938 }
1939 if (count($this->getTriggerUserFilter()) && !in_array($level_entry['trigger_user_id'], $this->getTriggerUserFilter())) {
1940 continue;
1941 }
1942
1943 // render the self evaluation at the correct position within the list of object triggered entries
1944 if ($se_date > $level_entry["status_date"] && !$se_rendered) {
1945 $se_rendered = true;
1946 }
1947 if ($this->getFilter()->isInRange($level_entry)) {
1948 $filtered_entries[] = $level_entry;
1949 }
1950 }
1951
1952 return $filtered_entries;
1953 }
1954
1955 protected function getSelfEvalEntriesLatestOnly(array $entries): array
1956 {
1957 if (!empty($entries)) {
1958 $last_entry[] = $entries[0];
1959 return $last_entry;
1960 }
1961
1962 return [];
1963 }
1964
1965 protected function getSelfEvalEntriesWithoutLatest(array $entries): array
1966 {
1967 if (count($entries) > 1) {
1968 array_shift($entries);
1969 return $entries;
1970 }
1971
1972 return [];
1973 }
1974
1975 protected function getAllEntriesLatestOnly(array $entries): array
1976 {
1977 $first_self_added = false;
1978 $first_measurement_added = false;
1979 $first_appraisal_added = false;
1980 $latest_entries = [];
1981 foreach ($entries as $entry) {
1982 if (!$first_self_added && $entry["self_eval"] == 1) {
1983 $latest_entries[] = $entry;
1984 $first_self_added = true;
1985 continue;
1986 }
1987 if (!$first_measurement_added && $entry["trigger_obj_type"] == "tst") {
1988 $latest_entries[] = $entry;
1989 $first_measurement_added = true;
1990 continue;
1991 }
1992 if (!$first_appraisal_added && $entry["self_eval"] != 1 && $entry["trigger_obj_type"] != "tst") {
1993 $latest_entries[] = $entry;
1994 $first_appraisal_added = true;
1995 }
1996 }
1997
1998 return $latest_entries;
1999 }
2000
2001 protected function getAllEntriesWithoutLatest(array $entries): array
2002 {
2003 $first_self_filtered = false;
2004 $first_measurement_filtered = false;
2005 $first_appraisal_filtered = false;
2006 $non_latest_entries = [];
2007 foreach ($entries as $entry) {
2008 if (!$first_self_filtered && $entry["self_eval"] == 1) {
2009 $first_self_filtered = true;
2010 continue;
2011 }
2012 if (!$first_measurement_filtered && $entry["trigger_obj_type"] == "tst") {
2013 $first_measurement_filtered = true;
2014 continue;
2015 }
2016 if (!$first_appraisal_filtered && $entry["self_eval"] != 1 && $entry["trigger_obj_type"] != "tst") {
2017 $first_appraisal_filtered = true;
2018 continue;
2019 }
2020 $non_latest_entries[] = $entry;
2021 }
2022
2023 return $non_latest_entries;
2024 }
2025
2026 protected function getSkillEntriesHeader(int $eval_type): string
2027 {
2028 $tpl = new ilTemplate("tpl.skill_entries_header.html", true, true, "Services/Skill");
2029
2030 if ($eval_type == ilBasicSkill::EVAL_BY_SELF) {
2031 $tpl->setVariable("HEADING", $this->lng->txt("skmg_self_evaluation"));
2032 $tpl->setCurrentBlock("header_byline");
2033 $tpl->setVariable("BYLINE", $this->lng->txt("skmg_self_evaluation_byline"));
2034 $tpl->parseCurrentBlock();
2035 } else {
2036 if ($this->getProfileId() > 0) {
2037 $tpl->setVariable("HEADING", $this->lng->txt("skmg_skill_profile_records"));
2038 }
2039 }
2040
2041 return $tpl->get();
2042 }
2043
2044 protected function getSkillCategoryDescription(int $skill_id, int $tref_id): string
2045 {
2046 $tpl = new ilTemplate("tpl.skill_description_category.html", true, true, "Services/Skill");
2047
2048 //if (ilSkillTreeNode::_lookupType($skill_id) == "scat") {
2049 $des = ilSkillTreeNode::_lookupDescription($skill_id);
2050 if (!empty($des)) {
2051 $tpl->setCurrentBlock("description_category");
2052 $tpl->setVariable("DESCRIPTION_CATEGORY", $des);
2053 $tpl->parseCurrentBlock();
2054 }
2055 //}
2056
2057 return $tpl->get();
2058 }
2059
2060 protected function getBasicSkillDescription(string $description): string
2061 {
2062 $tpl = new ilTemplate("tpl.skill_description_basic.html", true, true, "Services/Skill");
2063
2064 if (!empty($description)) {
2065 $tpl->setCurrentBlock("description_basic");
2066 $tpl->setVariable("DESCRIPTION_BASIC", $description);
2067 $tpl->parseCurrentBlock();
2068 }
2069
2070 return $tpl->get();
2071 }
2072
2073 public function getSkillLevelDescription(ilSkillTreeNode $skill): string
2074 {
2075 $level_data = $skill->getLevelData();
2076 $tpl = new ilTemplate("tpl.skill_desc.html", true, true, "Services/Skill");
2077
2078 $desc_exists = false;
2079 foreach ($level_data as $l) {
2080 if ($l["description"] != "") {
2081 $desc_exists = true;
2082 }
2083 }
2084 reset($level_data);
2085 if ($desc_exists) {
2086 foreach ($level_data as $l) {
2087 $tpl->setCurrentBlock("level");
2088 $tpl->setVariable("LEVEL_VAL", $l["title"]);
2089 $tpl->setVariable("LEVEL_DESC", nl2br($l["description"]));
2090 $tpl->parseCurrentBlock();
2091 }
2092 }
2093
2094 return $tpl->get();
2095 }
2096
2098 array $a_levels,
2099 int $a_base_skill,
2100 int $a_tref_id,
2101 int $gap_mode_obj_id = 0
2102 ): ?\ILIAS\UI\Component\Panel\Secondary\Secondary {
2103 $lng = $this->lng;
2104
2105 $res_manager = new ilSkillResourcesManager($a_base_skill, $a_tref_id);
2106
2107 $gap_mode_obj_type = ilObject::_lookupType($gap_mode_obj_id);
2108 if ($gap_mode_obj_id > 0 && !$this->obj_definition->isContainer($gap_mode_obj_type)) {
2109 return null;
2110 }
2111
2112 // note for self-evaluation
2113 if ($this->skmg_settings->getHideProfileBeforeSelfEval() &&
2114 !ilBasicSkill::hasSelfEvaluated($this->user->getId(), $a_base_skill, $a_tref_id)) {
2115 $sec_panel_content = $this->ui_fac->legacy($lng->txt("skmg_skill_needs_self_eval"));
2116 $sec_panel = $this->ui_fac->panel()->secondary()->legacy("", $sec_panel_content);
2117 return $sec_panel;
2118 }
2119
2120 // suggested resources
2121 if ($res_manager->isLevelTooLow($a_levels, $this->profile_levels, $this->actual_levels)) {
2122 $imp_resources = $res_manager->getSuggestedResources();
2123 $info[] = $this->ui_fac->item()->standard($lng->txt("skmg_recommended_learning_material_info"));
2124 $info_group = $this->ui_fac->item()->group("", $info);
2125 $items = [];
2126
2127 $sub_objects = [];
2128 $is_container = false;
2129 if ($gap_mode_obj_id > 0 && $this->obj_definition->isContainer($gap_mode_obj_type)) {
2130 $is_container = true;
2131 $sub_objects = $this->tree->getSubTree(
2132 $this->tree->getNodeData((int) current(\ilObject::_getAllReferences($gap_mode_obj_id))),
2133 false
2134 );
2135 }
2136
2137 foreach ($imp_resources as $r) {
2138 $ref_id = $r["rep_ref_id"];
2139 // in containers: filter resources only by objects in sub tree
2140 if ($is_container && !in_array($ref_id, $sub_objects)) {
2141 continue;
2142 }
2144 $title = ilObject::_lookupTitle($obj_id);
2145 $icon = $this->ui_fac->symbol()->icon()->standard(
2146 ilObject::_lookupType($obj_id),
2147 $lng->txt("icon") . " " . $lng->txt(ilObject::_lookupType($obj_id))
2148 );
2149 $link = $this->ui_fac->link()->standard($title, ilLink::_getLink($ref_id));
2150
2151 $items[] = $this->ui_fac->item()->standard($link)->withLeadIcon($icon);
2152 }
2153 if (count($items) > 0) {
2154 switch ($gap_mode_obj_type) {
2155 case "crs":
2156 $sec_panel_title = $lng->txt("skmg_recommended_learning_material_crs");
2157 break;
2158 case "grp":
2159 $sec_panel_title = $lng->txt("skmg_recommended_learning_material_grp");
2160 break;
2161 default:
2162 $sec_panel_title = $lng->txt("skmg_recommended_learning_material_global");
2163 }
2164
2165 $item_group = $this->ui_fac->item()->group("", $items);
2166 $sec_panel = $this->ui_fac->panel()->secondary()->listing(
2167 $sec_panel_title,
2168 [$info_group, $item_group]
2169 );
2170 } else {
2171 $sec_panel_content = $this->ui_fac->legacy($lng->txt("skmg_skill_needs_impr_no_res"));
2172 $sec_panel = $this->ui_fac->panel()->secondary()->legacy("", $sec_panel_content);
2173 }
2174 } else {
2175 $sec_panel_content = $this->ui_fac->legacy($lng->txt("skmg_skill_no_needs_impr_info"));
2176 $sec_panel = $this->ui_fac->panel()->secondary()->legacy($lng->txt("skmg_skill_no_needs_impr"), $sec_panel_content);
2177 }
2178
2179 return $sec_panel;
2180 }
2181
2182 public function getAllSuggestedResources(int $a_base_skill, int $a_tref_id): string
2183 {
2184 $lng = $this->lng;
2185
2186 $tpl = new ilTemplate("tpl.suggested_resources.html", true, true, "Services/Skill");
2187
2188 $skill_res = new ilSkillResources($a_base_skill, $a_tref_id);
2189 $res = $skill_res->getResources();
2190 // add $r["level_id"] info
2191 $any = false;
2192 foreach ($res as $level) {
2193 $available = false;
2194 $cl = 0;
2195 foreach ($level as $r) {
2196 if ($r["imparting"]) {
2197 $ref_id = $r["rep_ref_id"];
2199 $title = ilObject::_lookupTitle($obj_id);
2200 $tpl->setCurrentBlock("resource_item");
2201 $tpl->setVariable("TXT_RES", $title);
2202 $tpl->setVariable("HREF_RES", ilLink::_getLink($ref_id));
2203 $tpl->parseCurrentBlock();
2204 $available = true;
2205 $any = true;
2206 $cl = $r["level_id"];
2207 }
2208 }
2209 if ($available) {
2210 $tpl->setCurrentBlock("resources_list_level");
2211 $tpl->setVariable("TXT_LEVEL", $lng->txt("skmg_level"));
2212 $tpl->setVariable("LEVEL_NAME", ilBasicSkill::lookupLevelTitle($cl));
2213 $tpl->parseCurrentBlock();
2214 $tpl->touchBlock("resources_list");
2215 }
2216 }
2217 if ($any) {
2218 $tpl->setVariable("SUGGESTED_MAT_MESS", $lng->txt("skmg_suggested_resources"));
2219 return $tpl->get();
2220 }
2221
2222 return "";
2223 }
2224
2225 public function listAllAssignedProfiles(): void
2226 {
2227 if (empty($this->user_profiles)) {
2228 $this->ctrl->redirect($this, "listSkills");
2229 }
2230
2231 $this->setTabs("profile");
2232
2233 $prof_items = [];
2234
2235 foreach ($this->user_profiles as $p) {
2236 $image_id = $p["image_id"];
2237 if ($image_id) {
2238 $identification = $this->storage->manage()->find($image_id);
2239 $src = $this->storage->consume()->src($identification);
2240 $image = $this->ui_fac->image()->responsive($src->getSrc(), $this->lng->txt("skmg_custom_image_alt"));
2241 } else {
2242 $image = $this->ui_fac->image()->responsive(
2243 "./templates/default/images/logo/ilias_logo_72x72.png",
2244 "ILIAS"
2245 );
2246 }
2247
2248 $this->ctrl->setParameter($this, "profile_id", $p["id"]);
2249 $link = $this->ui_fac->link()->standard(
2250 $p["title"],
2251 $this->ctrl->getLinkTarget($this, "listassignedprofile")
2252 );
2253 $this->ctrl->setParameter($this, "profile_id", "");
2254
2255 $chart_value = $this->profile_completion_manager->getProfileProgress($this->user->getId(), $p["id"]);
2256 $prof_item = $this->ui_fac->item()->standard($link)
2257 ->withDescription($p["description"])
2258 ->withLeadImage($image)
2259 ->withProgress($this->ui_fac->chart()->progressMeter()->standard(100, $chart_value));
2260
2261 $prof_items[] = $prof_item;
2262 }
2263
2264 $prof_list = $this->ui_fac->panel()->listing()->standard("", array(
2265 $this->ui_fac->item()->group("", $prof_items)
2266 ));
2267
2268 $this->tpl->setContent($this->ui_ren->render($prof_list));
2269 }
2270
2271 public function listAssignedProfile(): void
2272 {
2273 $ilCtrl = $this->ctrl;
2274 $lng = $this->lng;
2275
2276 $main_tpl = $this->tpl;
2277
2278 $tpl = new ilTemplate("tpl.skill_filter.html", true, true, "Services/Skill");
2279
2280 $this->tabs->clearTargets();
2281 $this->tabs->setBackTarget(
2282 $this->lng->txt("back"),
2283 $ilCtrl->getLinkTarget($this, "listallassignedprofiles")
2284 );
2285 $this->setProfileId($this->requested_profile_id);
2286
2287 $main_tpl->setTitle($this->profile_manager->lookupTitle($this->getProfileId()));
2288
2289 $filter_toolbar = new ilToolbarGUI();
2290 $filter_toolbar->setFormAction($ilCtrl->getFormAction($this));
2291 $this->getFilter()->addToToolbar($filter_toolbar, true);
2292
2293 $skills = [];
2294 if ($this->getProfileId() > 0) {
2295 $profile = $this->profile_manager->getById($this->getProfileId());
2296 $this->profile_levels = $profile->getSkillLevels();
2297
2298 foreach ($this->profile_levels as $l) {
2299 $skills[] = array(
2300 "base_skill_id" => $l["base_skill_id"],
2301 "tref_id" => $l["tref_id"],
2302 "level_id" => $l["level_id"]
2303 );
2304 }
2305 }
2306
2307 $this->actual_levels = $this->profile_completion_manager->getActualMaxLevels(
2308 $this->user->getId(),
2309 $skills,
2310 $this->gap_mode,
2311 $this->gap_mode_type,
2312 $this->gap_mode_obj_id
2313 );
2314
2315 // render
2316 $html = "";
2317 $not_all_self_evaluated = false;
2318 foreach ($skills as $s) {
2319 if ($this->skmg_settings->getHideProfileBeforeSelfEval() &&
2320 !ilBasicSkill::hasSelfEvaluated($this->user->getId(), $s["base_skill_id"], $s["tref_id"])) {
2321 $not_all_self_evaluated = true;
2322 }
2323
2324 // todo draft check
2325 $html .= $this->getSkillHTML($s["base_skill_id"], 0, true, $s["tref_id"]);
2326 }
2327
2328 if ($html != "") {
2329 $filter_toolbar->addFormButton($this->lng->txt("skmg_refresh_view"), "applyFilterAssignedProfiles");
2330
2331 $tpl->setVariable("FILTER", $filter_toolbar->getHTML());
2332
2333 $html = $tpl->get() . $html;
2334 }
2335
2336 if ($not_all_self_evaluated) {
2337 $box = $this->ui_fac->messageBox()->info($lng->txt("skmg_skill_needs_self_eval_box"));
2338 $html = $this->ui_ren->render($box) . $html;
2339 }
2340
2341 $main_tpl->setContent($html);
2342 }
2343}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Provides fluid interface to RBAC services.
Definition: UIServices.php:24
renderer()
Get a renderer for UI components.
Definition: UIServices.php:43
factory()
Get the factory that crafts UI components.
Definition: UIServices.php:35
Builds data types.
Definition: Factory.php:21
Request wrapper for personal skills guis.
const IL_CAL_DATETIME
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 lookupLevelTitle(int $a_id)
static hasSelfEvaluated(int $a_user_id, int $a_skill_id, int $a_tref_id)
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...
Class ilCtrl provides processing control methods.
static setUseRelativeDates(bool $a_status)
set use relative dates
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false)
Class for single dates.
Help GUI class.
language handling
loadLanguageModule(string $a_module)
Load language module.
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...
Class ilObjFile.
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...
User class.
parses the objects.xml it handles the xml-description of all ilias objects
static _lookupType(int $id, bool $reference=false)
static _getAllReferences(int $id)
get all reference ids for object ID
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static _lookupObjId(int $ref_id)
static _lookupTitle(int $obj_id)
static getInstance()
const PANEL_STYLE_PRIMARY
Explorer for selecting a personal skill.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static addPersonalSkill(int $a_user_id, int $a_skill_node_id)
static removeMaterial(int $a_user_id, int $a_tref_id, int $a_level_id, int $a_wsp_id)
static getSelectedUserSkills(int $a_user_id)
static removeSkill(int $a_user_id, int $a_skill_node_id)
static assignMaterial(int $a_user_id, int $a_top_skill, int $a_tref_id, int $a_basic_skill, int $a_level, int $a_wsp_id)
Assign material to skill level.
static countAssignedMaterial(int $a_user_id, int $a_tref_id, int $a_level)
Count assigned material (for a skill level and user)
static getAssignedMaterial(int $a_user_id, int $a_tref_id, int $a_level)
Get assigned material (for a skill level and user)
static saveSelfEvaluation(int $a_user_id, int $a_top_skill, int $a_tref_id, int $a_basic_skill, int $a_level)
Personal skills GUI class.
SkillProfileCompletionManager $profile_completion_manager
hideSkill(int $a_skill_id, int $a_tref_id=0)
assignMaterials()
Assign materials to skill levels.
getScaleBar(array $a_levels, $a_activated_levels)
getLatestEntriesForSkillHTML(int $top_skill_id, array $bs, ilSkillTreeNode $skill, ilObjUser $user, int $eval_type, array $level_data)
setGapAnalysisActualStatusModePerObject(int $a_obj_id, string $a_cat_title="")
setTriggerUserFilter(array $trigger_user_filter)
ilSkillManagementSettings $skmg_settings
getBasicSkillDescription(string $description)
setGapAnalysisActualStatusModePerType(string $a_type, string $a_cat_title="")
SkillPersonalGUIRequest $personal_gui_request
getFilteredEntriesForSkill(array $entries, int $top_skill_id, array $bs, ilObjUser $user)
getSelfEvalGapItem(array $a_levels, int $a_tref_id=0)
getNonLatestEntriesForSkillHTML(int $top_skill_id, array $bs, ilSkillTreeNode $skill, ilObjUser $user, int $eval_type, array $level_data)
getSkillCategoryDescription(int $skill_id, int $tref_id)
ilSkillTreeRepository $tree_repo
getProfileTargetItem(int $a_profile_id, array $a_levels, int $a_tref_id=0)
getSelfEvalEntriesLatestOnly(array $entries)
getMaterialInfo(int $a_wsp_id, int $a_user_id)
Get material file name and goto url.
setTriggerObjectsFilter(array $trigger_objects_filter)
applyFilterAssignedProfiles()
Apply filter for profiles view.
getAllSuggestedResources(int $a_base_skill, int $a_tref_id)
assignMaterial()
Assign materials to skill level.
ilObjectDefinition $obj_definition
SkillProfileManager $profile_manager
setGapAnalysisSelfEvalLevels(array $a_val)
setOfflineMode(string $a_file_path)
getSkillHTML(int $a_top_skill_id, int $a_user_id=0, bool $a_edit=false, int $a_tref_id=0)
Get skill presentation HTML.
getGapAnalysisHTML(int $a_user_id=0, array $a_skills=null)
getMaterials(array $a_levels, int $a_tref_id=0, int $a_user_id=0)
ilPersonalSkillsFilterGUI $filter
setObjectSkills(int $a_obj_id, array $a_skills)
ilGlobalTemplateInterface $tpl
getSkillLevelDescription(ilSkillTreeNode $skill)
setObjectSkillProfiles(ilContainerGlobalProfiles $a_g_profiles, ilContainerLocalProfiles $a_l_profils)
renderSkillHTML(int $a_top_skill_id, int $a_user_id=0, bool $a_edit=false, int $a_tref_id=0)
getEvalItem(array $a_levels, array $a_level_entry, bool $is_latest=false)
getAllEntriesWithoutLatest(array $entries)
getSelfEvalEntriesWithoutLatest(array $entries)
getSuggestedResourcesForProfile(array $a_levels, int $a_base_skill, int $a_tref_id, int $gap_mode_obj_id=0)
getActualGapItem(array $a_levels, int $a_tref_id=0)
This class represents a selection list property in a property form.
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...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupDescription(int $a_obj_id)
static _lookupTitle(int $a_obj_id, int $a_tref_id=0)
static _lookupType(int $a_obj_id)
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...
static getImagePath(string $img, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Explorer for selecting a personal workspace item.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $DIC
Definition: feed.php:28
if(isset($_FILES['img_file']) &&is_array($_FILES['img_file'])) $panel
Definition: imgupload.php:198
$ilUser
Definition: imgupload.php:34
This is how the factory for UI elements looks.
Definition: Factory.php:38
An entity that renders components to a string output.
Definition: Renderer.php:31
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...
setCurrentBlock(string $part=self::DEFAULT_BLOCK)
Sets the template to the given block.
parseCurrentBlock(string $block_name=self::DEFAULT_BLOCK)
Parses the given block.
setVariable(string $variable, $value='')
Sets the given variable to the given value.
get(string $part=self::DEFAULT_BLOCK)
Renders the given block and returns the html string.
Interface ilSkillTreeRepository.
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
$ref_id
Definition: ltiauth.php:67
$path
Definition: ltiservices.php:32
$res
Definition: ltiservices.php:69
$i
Definition: metadata.php:41
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ChatMainBarProvider \MainMenu\Provider.
Class Factory.
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
global $ilSetting
Definition: privfeed.php:17
$type
$url
$lng
$message
Definition: xapiexit.php:32