ILIAS  trunk Revision v12.0_alpha-1540-g00f839d5fa1
class.ilObjStudyProgramme.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
23
25{
26 public const CP_TYPE = 'cont';
27
29
33 protected $parent;
34
38 protected ?array $children = null;
39
43 protected ?array $lp_children = null;
44
52
53 // GLOBALS from ILIAS
54
58 protected ?array $members_cache = null;
59
63 protected ?array $reference_children = null;
64
66 protected ilObjUser $ilUser;
68 protected CustomIconFactory $custom_icon_factory;
69 protected ilLogger $logger;
70
75 public function __construct(int $id = 0, bool $call_by_reference = true)
76 {
78 $this->type = "prg";
79
80 $this->type_repository = $dic['model.Type.ilStudyProgrammeTypeRepository'];
81 $this->auto_categories_repository = $dic['model.AutoCategories.ilStudyProgrammeAutoCategoriesRepository'];
82 $this->auto_memberships_repository = $dic['model.AutoMemberships.ilStudyProgrammeAutoMembershipsRepository'];
83 $this->membersourcereader_factory = $dic['model.AutoMemberships.ilStudyProgrammeMembershipSourceReaderFactory'];
84
85 $this->settings_repository = $dic['model.Settings.ilStudyProgrammeSettingsRepository'];
86 $this->assignment_repository = $dic['repo.assignment'];
87 $this->events = $dic['ilStudyProgrammeEvents'];
88
90
91 $this->clearParentCache();
92 $this->clearChildrenCache();
93 $this->clearLPChildrenCache();
94
95 global $DIC;
96 $tree = $DIC['tree'];
97 $ilUser = $DIC['ilUser'];
98 $this->webdir = $DIC->filesystem()->web();
99 $this->tree = $tree;
100 $this->ilUser = $ilUser;
101 $this->db = $DIC['ilDB'];
102 $this->lng = $DIC['lng'];
103 $this->logger = ilLoggerFactory::getLogger($this->type);
104
105 $this->object_factory = ilObjectFactoryWrapper::singleton();
106
107 $this->custom_icon_factory = $DIC['object.customicons.factory'];
108
110 }
111
112 public static function initStudyProgrammeCache(): void
113 {
114 if (self::$study_programme_cache === null) {
115 self::$study_programme_cache = ilObjStudyProgrammeCache::singleton();
116 }
117 }
118
122 protected function clearParentCache(): void
123 {
124 // This is not initialized, but we need null if there is no parent.
125 $this->parent = false;
126 }
127
131 protected function clearChildrenCache(): void
132 {
133 $this->children = null;
134 }
135
139 protected function clearLPChildrenCache(): void
140 {
141 $this->lp_children = null;
142 }
143
144 public static function getRefIdFor(int $obj_id): int
145 {
146 $refs = ilObject::_getAllReferences($obj_id);
147 if (count($refs) < 1) {
148 throw new ilException("Could not find ref_id for programme with obj_id $obj_id");
149 }
150 return (int) array_shift($refs);
151 }
152
153 protected function getPrgInstanceByObjId(int $obj_id): ilObjStudyProgramme
154 {
156 }
157
158 public static function getInstanceByObjId(int $obj_id): ilObjStudyProgramme
159 {
161 }
162
164 {
165 if (self::$study_programme_cache === null) {
167 }
168 return self::$study_programme_cache->getInstanceByRefId((int) $ref_id);
169 }
170
172 {
174 }
176 {
178 }
179 protected function getTree(): ilTree
180 {
181 return $this->tree;
182 }
183 protected function getLogger(): ilLogger
184 {
185 return $this->logger;
186 }
187
193 public static function createInstance(): ilObjStudyProgramme
194 {
195 $obj = new ilObjStudyProgramme();
196 $obj->create();
197 $obj->createReference();
198 self::$study_programme_cache->addInstance($obj);
199 return $obj;
200 }
201
203 // CRUD
205
207 {
208 return $this->getSettingsRepository()->get($this->getId());
209 }
210
211 public function updateSettings(ilStudyProgrammeSettings $settings): bool
212 {
213 if ($settings->getObjId() !== $this->getId()) {
214 throw new Exception("The given settings-object does not belong to this programme", 1);
215 }
216 $this->getSettingsRepository()->update($settings);
217
218 return true;
219 }
220
221 protected function deleteSettings(): void
222 {
223 $this->getSettingsRepository()->delete($this->getSettings());
224 }
225
231 protected function deleteAssignmentsAndProgresses(): void
232 {
233 $this->assignment_repository->deleteAllAssignmentsForProgrammeId($this->getId());
234 }
235
239 public function create(): int
240 {
241 $id = (int) parent::create();
242 $this->getSettingsRepository()->createFor($id);
243 return $id;
244 }
245
249 public function update(): bool
250 {
251 parent::update();
252
253 $type_settings = $this->getSettings()->getTypeSettings();
254 // Update selection for advanced metadata of the type
255 if ($type_settings->getTypeId()) {
257 $this->getId(),
258 'prg_type',
259 $this->type_repository->getAssignedAMDRecordIdsByType($type_settings->getTypeId())
260 );
261 } else {
262 // If no type is assigned, delete relations by passing an empty array
263 ilAdvancedMDRecord::saveObjRecSelection($this->getId(), 'prg_type', array());
264 }
265 return true;
266 }
267
273 public function delete(): bool
274 {
275 // always call parent delete function first!!
276 if (!parent::delete()) {
277 return false;
278 }
279
280 $this->deleteSettings();
282 try {
283 $this->auto_categories_repository->deleteFor($this->getId());
285 // This would be the case when SP is in trash (#17797)
286 }
287
290
291 $this->events->raise('delete', ['object' => $this, 'obj_id' => $this->getId()]);
292 return true;
293 }
294
295 public function hasAdvancedMetadata(): bool
296 {
297 $sub_type_id = $this->getSettings()->getTypeSettings()->getTypeId();
298 $type = null;
299 if ($sub_type_id) {
300 $type = $this->type_repository->getType($sub_type_id);
301 }
302
303 return !is_null($type) && count($this->type_repository->getAssignedAMDRecordIdsByType($type->getId(), true)) > 0;
304 }
305
306 public function cloneObject(int $target_ref_id, int $copy_id = 0, bool $omit_tree = false): ?ilObject
307 {
308 $new_obj = parent::cloneObject($target_ref_id, $copy_id, $omit_tree);
309 $settings = $this->getSettings()->withObjId($new_obj->getId());
310 $settings = $settings->withAssessmentSettings(
311 $settings->getAssessmentSettings()->withStatus(ilStudyProgrammeSettings::STATUS_DRAFT)
312 );
313 $new_obj->updateSettings($settings);
314 return $new_obj;
315 }
316
318 // GETTERS AND SETTERS
320
324 public function getLastChange(): DateTime
325 {
326 return $this->getSettings()->getLastChange();
327 }
328
332 public function getPoints(): int
333 {
334 return $this->getSettings()->getAssessmentSettings()->getPoints();
335 }
336
342 public function setPoints(int $points): ilObjStudyProgramme
343 {
344 $settings = $this->getSettings();
345 $this->updateSettings(
346 $settings->withAssessmentSettings($settings->getAssessmentSettings()->withPoints($points))
347 );
348 $this->updateLastChange();
349 return $this;
350 }
351
352 public function getLPMode(): int
353 {
354 return $this->getSettings()->getLPMode();
355 }
356
365 public function adjustLPMode(): void
366 {
367 // Clear caches here, there have been some changes, because this method
368 // would not have been called otherwise, and the changer just does not
369 // know if we have filled the caches already...
370 $this->clearLPChildrenCache();
371 $this->clearChildrenCache();
372
373 if ($this->tree->isInTree($this->getRefId())) {
374 if ($this->getAmountOfLPChildren() > 0) {
375 $this->settings_repository->update(
377 );
378 } elseif ($this->getAmountOfChildren(true) > 0) {
379 $this->settings_repository->update(
381 );
382 } else {
383 $this->settings_repository->update(
385 );
386 }
387 }
388 }
389
390 public function getStatus(): int
391 {
392 return $this->getSettings()->getAssessmentSettings()->getStatus();
393 }
394
400 public function setStatus(int $a_status): ilObjStudyProgramme
401 {
402 $settings = $this->getSettings();
403 $this->updateSettings(
404 $settings->withAssessmentSettings($settings->getAssessmentSettings()->withStatus($a_status))
405 );
406 $this->updateLastChange();
407 return $this;
408 }
409
410 public function isActive(): bool
411 {
413 }
414
419 {
420 $type_settings = $this->getSettings()->getTypeSettings();
421 if (!in_array($type_settings->getTypeId(), array("-", "0"))) {
422 $subtype_id = $type_settings->getTypeId();
423 return $this->type_repository->getType($subtype_id);
424 }
425
426 return null;
427 }
428
429 public function isCertificateActive(): bool
430 {
431 $global_settings = new ilSetting('certificate');
432 $global_active = (bool) $global_settings->get('active', '0');
433 if (!$global_active) {
434 return false;
435 }
438 return $certificate_template->isCurrentlyActive();
439 }
440
441
443 // TREE NAVIGATION
445
454 public static function getAllChildren(int $a_ref_id, bool $include_references = false): array
455 {
456 $ret = array();
457 $root = self::getInstanceByRefId($a_ref_id);
458 $root_id = $root->getId();
459 $root->applyToSubTreeNodes(function (ilObjStudyProgramme $prg) use (&$ret, $root_id) {
460 // exclude root node of subtree.
461 if ($prg->getId() === $root_id) {
462 return;
463 }
464 $ret[] = $prg;
465 }, $include_references);
466 return $ret;
467 }
468
469 public function getAllPrgChildren(): array
470 {
471 $ret = [];
472 $this->applyToSubTreeNodes(
473 function (ilObjStudyProgramme $prg) use (&$ret) {
474 if ($prg->getId() === $this->getId()) {
475 return;
476 }
477 $ret[] = $prg;
478 }
479 );
480 return $ret;
481 }
482
490 public function getChildren(bool $include_references = false): array
491 {
492 $this->throwIfNotInTree();
493
494 if ($this->children === null) {
495 $ref_ids = $this->tree->getChildsByType($this->getRefId(), "prg");
496
497 // apply container sorting to tree
498 $sorting = ilContainerSorting::_getInstance($this->getId());
499 $ref_ids = $sorting->sortItems(array('prg' => $ref_ids));
500 $ref_ids = $ref_ids['prg'];
501
502 $this->children = array_map(static function ($node_data) {
503 return ilObjStudyProgramme::getInstanceByRefId($node_data["child"]);
504 }, $ref_ids);
505 }
506
507 if ($include_references && $this->reference_children === null) {
508 $this->reference_children = [];
509 $ref_child_ref_ids = $this->tree->getChildsByType($this->getRefId(), "prgr");
510 foreach (
511 array_unique(
512 array_map(
513 static function ($data) {
514 return (int) $data['child'];
515 },
516 array_filter($ref_child_ref_ids, static function ($data) {
517 return $data["deleted"] === null;
518 })
519 )
520 ) as $prg_ref_id
521 ) {
522 $this->reference_children[] =
523 (new ilObjStudyProgrammeReference($prg_ref_id))->getReferencedObject();
524 }
525 }
526 return $include_references ?
527 array_merge($this->children, $this->reference_children) :
529 }
530
537 public function getParent(): ?ilObjStudyProgramme
538 {
539 if ($this->parent === false) {
540 $this->throwIfNotInTree();
541 $parent_data = $this->tree->getParentNodeData($this->getRefId());
542 if ($parent_data["type"] !== "prg") {
543 $this->parent = null;
544 } else {
545 $this->parent = self::getInstanceByRefId($parent_data["ref_id"]);
546 }
547 }
548 return $this->parent;
549 }
550
551 protected function getReferencesTo(ilObjStudyProgramme $prg): array
552 {
554 return array_filter(
555 array_map(
556 static function ($id) {
557 $refs = ilObject::_getAllReferences((int) $id);
559 array_shift($refs)
560 );
561 },
563 ),
564 static function ($prg_ref) use ($tree) {
565 return !$tree->isDeleted($prg_ref->getRefId());
566 }
567 );
568 }
569
570 public function getReferencesToSelf(): array
571 {
572 return $this->getReferencesTo($this);
573 }
574
580 public function getParents(bool $include_references = false): array
581 {
582 $current = $this;
583 $parents = [];
584 $queque = [$current];
585 while ($element = array_shift($queque)) {
586 $parent = $element->getParent();
587 if ($parent === null || $include_references) {
588 foreach ($this->getReferencesTo($element) as $reference) {
589 if ($this->tree->isDeleted($reference->getRefId())) {
590 continue;
591 }
592 $r_parent = $reference->getParent();
593 if (is_null($r_parent)) {
594 continue;
595 }
596 $queque[] = $r_parent;
597 $parents[] = $r_parent;
598 }
599 continue;
600 }
601 $queque[] = $parent;
602 $parents[] = $parent;
603 }
604 return array_reverse($parents);
605 }
606
612 public function hasChildren(bool $include_references = false): bool
613 {
614 return $this->getAmountOfChildren($include_references) > 0;
615 }
616
623 public function getAmountOfChildren($include_references = false): int
624 {
625 return count($this->getChildren($include_references));
626 }
627
634 public function getDepth(): int
635 {
636 $cur = $this;
637 $count = 0;
638 while ($cur = $cur->getParent()) {
639 $count++;
640 }
641 return $count;
642 }
643
648 public function getRoot(): ilObjStudyProgramme
649 {
650 $parents = $this->getParents();
651 if (count($parents) < 1) {
652 return $this;
653 }
654 return $parents[0];
655 }
656
663 public function getLPChildren(): array
664 {
665 $this->throwIfNotInTree();
666
667 if ($this->lp_children === null) {
668 $this->lp_children = array();
669
670 $ref_ids = $this->tree->getChildsByType($this->getRefId(), "crsr");
671
672 // apply container sorting to tree
673 $sorting = ilContainerSorting::_getInstance($this->getId());
674 $ref_ids = $sorting->sortItems(array('crs_ref' => $ref_ids));
675 $ref_ids = $ref_ids['crs_ref'];
676
677 $lp_children = array_map(function ($node_data) {
678 $lp_obj = $this->object_factory->getInstanceByRefId((int) $node_data["child"]);
679
680 // filter out all StudyProgramme instances
681 return ($lp_obj instanceof $this) ? null : $lp_obj;
682 }, $ref_ids);
683
684 $this->lp_children = array_filter($lp_children);
685 }
686 return $this->lp_children;
687 }
688
695 public function getLPChildrenIds(): array
696 {
697 return array_map(static function ($child) {
698 return $child->getId();
699 }, $this->getLPChildren());
700 }
701
706 public function getAmountOfLPChildren(): int
707 {
708 return count($this->getLPChildren());
709 }
710
711 public function hasLPChildren(): bool
712 {
713 return ($this->getAmountOfLPChildren() > 0);
714 }
715
719 protected function throwIfNotInTree(): void
720 {
721 if (!$this->tree->isInTree($this->getRefId())) {
722 throw new ilStudyProgrammeTreeException("This program is not in tree.");
723 }
724 }
725
727 // QUERIES ON SUBTREE
729
737 public function applyToSubTreeNodes(Closure $fun, bool $include_references = false): void
738 {
739 $this->throwIfNotInTree();
740
741 if ($fun($this) !== false) {
742 foreach ($this->getChildren($include_references) as $child) {
743 $child->applyToSubTreeNodes($fun, $include_references);
744 }
745 }
746 }
747
751 public function getCompletedCourses(ilPRGAssignment $assignment): array
752 {
753 $completed_crss = [];
754 $f = function ($prg) use (&$completed_crss, $assignment) {
755 if ($prg->isActive() &&
756 $assignment->getProgressForNode($prg->getId())->isRelevant()
757 ) {
758 foreach ($prg->getLPChildren() as $child) {
759 $crs_id = (int) ilContainerReference::_lookupTargetId((int) $child->getId());
760 $crs_ref_id = (int) ilContainerReference::_lookupTargetRefId((int) $child->getId());
761 $crsr_ref_id = (int) $child->getRefId();
762
763 if (ilObject::_exists($crsr_ref_id, true) &&
764 is_null(ilObject::_lookupDeletedDate($crsr_ref_id)) &&
765 ilObject::_exists($crs_id, false) &&
766 is_null(ilObject::_lookupDeletedDate($crs_ref_id)) &&
767 ilLPStatus::_hasUserCompleted($crs_id, $assignment->getUserId())
768 ) {
769 $completed_crss[] = [
770 'crs_id' => $crs_id,
771 'prg_ref_id' => $prg->getRefId(),
772 'prg_obj_id' => $prg->getId(),
773 'crsr_ref_id' => $crsr_ref_id,
774 'crsr_id' => $child->getId(),
775 'crs_ref_id' => $crs_ref_id,
776 'title' => ilContainerReference::_lookupTitle((int) $child->getId()),
777 ];
778 }
779 }
780 return true;
781 }
782 return false;
783 };
784 $this->applyToSubTreeNodes($f, true);
785 return $completed_crss;
786 }
787
789 // TREE MANIPULATION
791
803 {
804 $this->throwIfNotInTree();
805
807 throw new ilStudyProgrammeTreeException("Program already contains leafs.");
808 }
809
810 if ($this->tree->isInTree($a_prg->getRefId())) {
811 throw new ilStudyProgrammeTreeException("Other program already is in tree.");
812 }
813
814 if ($a_prg->getRefId() === null) {
815 $a_prg->createReference();
816 }
817 $a_prg->putInTree($this->getRefId());
818 return $this;
819 }
820
829 public function nodeInserted($prg): void
830 {
831 if (! $prg instanceof ilObjStudyProgrammeReference &&
832 ! $prg instanceof ilObjStudyProgramme
833 ) {
834 throw new ilStudyProgrammeTreeException("Wrong type of node: " . get_class($prg));
835 }
837 throw new ilStudyProgrammeTreeException("Program already contains leafs.");
838 }
839
841 $this->settings_repository->update(
843 );
844 }
845
846 $this->clearChildrenCache();
847 $this->addMissingProgresses();
848 }
849
857 public function putInTree(int $parent_ref_id): void
858 {
859 parent::putInTree($parent_ref_id);
860
861 if (ilObject::_lookupType($parent_ref_id, true) === "prg") {
862 $par = self::getInstanceByRefId($parent_ref_id);
863 $par->nodeInserted($this);
864 }
865 }
866
877 {
878 if ($a_prg->getParent()->getId() !== $this->getId()) {
879 throw new ilStudyProgrammeTreeException("This is no parent of the given programm.");
880 }
881
882 if (!$a_prg->canBeRemoved()) {
883 throw new ilStudyProgrammeTreeException("The node has relevant assignments.");
884 }
885
886 // *sigh*...
887 $node_data = $this->tree->getNodeData($a_prg->getRefId());
888 $this->tree->deleteTree($node_data);
889 $a_prg->clearParentCache();
890 $this->clearChildrenCache();
891
892 return $this;
893 }
894
899 public function canBeRemoved(): bool
900 {
901 return ! $this->hasRelevantProgresses();
902 }
903
913 public function moveTo(ilObjStudyProgramme $new_parent): ilObjStudyProgramme
914 {
915 global $DIC;
916 $rbacadmin = $DIC['rbacadmin'];
917
918 if ($parent = $this->getParent()) {
919 // TODO: check if there some leafs in the new parent
920
921 $this->tree->moveTree($this->getRefId(), $new_parent->getRefId());
922 // necessary to clean up permissions
923 $rbacadmin->adjustMovedObjectPermissions($this->getRefId(), $parent->getRefId());
924
925 // TODO: lp-progress needs to be updated
926
927 // clear caches on different nodes
928 $this->clearParentCache();
929
930 $parent->clearChildrenCache();
931 $parent->clearLPChildrenCache();
932
933 $new_parent->clearChildrenCache();
934 $new_parent->clearLPChildrenCache();
935 }
936
937 return $this;
938 }
939
941 // USER ASSIGNMENTS
943
954 public function assignUser(int $usr_id, ?int $acting_usr_id = null, $raise_event = true): ilPRGAssignment
955 {
956 $this->members_cache = null;
957
959 throw new ilException(
960 "ilObjStudyProgramme::assignUser: Can't assign user to program '"
961 . $this->getId() . "', since it's not in active status."
962 );
963 }
964
965 if (is_null($acting_usr_id)) {
966 $acting_usr_id = $this->getLoggedInUserId();
967 }
968
969 $ass = $this->assignment_repository->createFor($this->getId(), $usr_id, $acting_usr_id);
970 $ass = $ass
971 ->initAssignmentDates();
972
973 $ass = $ass->resetProgresses(
974 $this->getSettingsRepository(),
975 $acting_usr_id
976 );
977
978 $this->assignment_repository->store($ass);
979
980 if ($raise_event) {
981 $this->events->userAssigned($ass);
982 }
983 return $ass;
984 }
985
994 {
995 $this->members_cache = null;
996 if ($assignment->getRootId() !== $this->getId()) {
997 throw new ilException(
998 "ilObjStudyProgramme::removeAssignment: Assignment '"
999 . $assignment->getId() . "' does not belong to study "
1000 . "program '" . $this->getId() . "'."
1001 );
1002 }
1003
1004 $this->assignment_repository->delete($assignment);
1005
1006 $affected_node_ids = array_map(fn($pgs) => $pgs->getNodeId(), $assignment->getProgresses());
1007 foreach ($affected_node_ids as $node_obj_id) {
1008 $this->refreshLPStatus($assignment->getUserId(), $node_obj_id);
1009 }
1010
1011 $this->events->userDeassigned($assignment);
1012 return $this;
1013 }
1014
1015 public function getSpecificAssignment(int $assignment_id): ilPRGAssignment
1016 {
1017 return $this->assignment_repository->get($assignment_id);
1018 }
1019
1020 public function storeExpiryInfoSentFor(ilPRGAssignment $ass): void
1021 {
1022 $this->assignment_repository->storeExpiryInfoSentFor($ass);
1023 }
1024
1025 public function resetExpiryInfoSentFor(ilPRGAssignment $ass): void
1026 {
1027 $this->assignment_repository->resetExpiryInfoSentFor($ass);
1028 }
1029
1030 public function storeRiskyToFailSentFor(ilPRGAssignment $ass): void
1031 {
1032 $this->assignment_repository->storeRiskyToFailSentFor($ass);
1033 }
1034
1035 public function resetRiskyToFailSentFor(ilPRGAssignment $ass): void
1036 {
1037 $this->assignment_repository->resetRiskyToFailSentFor($ass);
1038 }
1039
1043 public function hasAssignmentOf(int $user_id): bool
1044 {
1045 return $this->getAmountOfAssignmentsOf($user_id) > 0;
1046 }
1047
1053 {
1054 return count($this->getAssignmentsOf($user_id));
1055 }
1056
1064 public function getAssignmentsOf(int $user_id): array
1065 {
1066 $assignments = $this->assignment_repository->getAllForNodeIsContained(
1067 $this->getId(),
1068 [$user_id]
1069 );
1070
1071 usort($assignments, static function (ilPRGAssignment $a_one, ilPRGAssignment $a_other): int {
1072 $left = $a_one->getLastChange();
1073 $right = $a_other->getLastChange();
1074 if ($left === null || $right === null) {
1075 return (int) ($left !== null) <=> (int) ($right !== null);
1076 }
1077
1078 return $left->getTimestamp() <=> $right->getTimestamp();
1079 });
1080 return $assignments;
1081 }
1082
1086 public function getAssignments(): array
1087 {
1088 return $this->assignment_repository->getAllForNodeIsContained($this->getId());
1089 }
1090
1095 public function getMembers(): array
1096 {
1097 $usr_ids = [];
1098 foreach ($this->getAssignments() as $assignment) {
1099 $usr_ids[] = $assignment->getUserId();
1100 }
1101 return array_unique($usr_ids);
1102 }
1103
1107 public function getLocalMembers(): array
1108 {
1109 if (!$this->members_cache) {
1110 $this->members_cache = array_map(
1111 static function ($assignment) {
1112 return $assignment->getUserId();
1113 },
1114 $this->assignment_repository->getByPrgId($this->getId())
1115 );
1116 }
1117 return $this->members_cache;
1118 }
1119
1123 public function hasAssignments(): bool
1124 {
1125 $filter = new ilPRGAssignmentFilter($this->lng);
1126 $count = $this->assignment_repository->countAllForNodeIsContained(
1127 $this->getId(),
1128 null,
1129 $filter
1130 );
1131 return $count > 0;
1132
1133 }
1134
1140 public function getAssignmentsOfSingleProgramForUser(int $usr_id): array
1141 {
1142 return $this->assignment_repository->getAllForSpecificNode($this->getId(), [$usr_id]);
1143 }
1144
1148 public function hasAssignmentsOfSingleProgramForUser(int $usr_id): bool
1149 {
1150 return count($this->getAssignmentsOfSingleProgramForUser($usr_id)) > 0;
1151 }
1152
1153 public function getCertificateRelevantAssignmentIds(int ...$usr_ids): array
1154 {
1155 return $this->assignment_repository->getCertificateRelevantAssignmentIds(
1156 $this->getId(),
1157 ...$usr_ids
1158 );
1159 }
1160
1161
1163 // USER PROGRESS
1165
1171 public function addMissingProgresses(): void
1172 {
1173 $assignments = $this->getAssignments();
1174 foreach ($assignments as $ass) {
1175 $this->assignment_repository->store($ass);
1176 }
1177 }
1178
1182 public function hasRelevantProgresses(): bool
1183 {
1184 $filter = new ilPRGAssignmentFilter($this->lng);
1185 $filter = $filter->withValues([
1186 'prg_status_hide_irrelevant' => true
1187 ]);
1188 $count = $this->assignment_repository->countAllForNodeIsContained(
1189 $this->getId(),
1190 null,
1191 $filter
1192 );
1193 return $count > 0;
1194 }
1195
1196 public function getIdsOfUsersWithRelevantProgress(): array
1197 {
1198 return array_map(
1199 fn($ass) => $ass->getUserId(),
1200 $this->getAssignments()
1201 );
1202 }
1203
1204
1206 // AUTOMATIC CONTENT CATEGORIES
1208
1213 public function getAutomaticContentCategories(): array
1214 {
1215 return $this->auto_categories_repository->getFor($this->getId());
1216 }
1217
1218 public function hasAutomaticContentCategories(): bool
1219 {
1220 return count($this->getAutomaticContentCategories()) > 0;
1221 }
1222
1223
1228 public function storeAutomaticContentCategory(int $category_ref_id): void
1229 {
1230 $ac = $this->auto_categories_repository->create(
1231 $this->getId(),
1232 $category_ref_id
1233 );
1234 $this->auto_categories_repository->update($ac);
1235 }
1236
1241 public function deleteAutomaticContentCategories(array $category_ids = []): void
1242 {
1243 $this->auto_categories_repository->delete($this->getId(), $category_ids);
1244 }
1245
1250 {
1251 $this->auto_categories_repository->deleteFor($this->getId());
1252 }
1253
1257 public static function addCrsToProgrammes(int $crs_ref_id, int $cat_ref_id): void
1258 {
1259 foreach (self::getProgrammesMonitoringCategory($cat_ref_id) as $prg) {
1260 $course_ref = new ilObjCourseReference();
1261 $course_ref->setTitleType(ilContainerReference::TITLE_TYPE_REUSE);
1262 $course_ref->setTargetRefId($crs_ref_id);
1263 $course_ref->create();
1264 $course_ref->createReference();
1265 $course_ref->putInTree($prg->getRefId());
1266 $course_ref->setPermissions($crs_ref_id);
1267 $course_ref->setTargetId(ilObject::_lookupObjectId($crs_ref_id));
1268 $course_ref->update();
1269 $lp = new ilLPObjSettings($course_ref->getId());
1270 $lp->insert();
1271 $lp->setMode($lp::LP_MODE_COURSE_REFERENCE);
1272 $lp->update(false);
1273 }
1274 }
1275
1281 public static function removeCrsFromProgrammes(int $crs_ref_id, int $cat_ref_id): void
1282 {
1283 foreach (self::getProgrammesMonitoringCategory($cat_ref_id) as $prg) {
1284 foreach ($prg->getLPChildren() as $child) {
1285 if ((int) $child->getTargetRefId() === $crs_ref_id) {
1286 $child->delete();
1287 }
1288 }
1289 }
1290 }
1291
1296 protected static function getProgrammesMonitoringCategory(int $cat_ref_id): array
1297 {
1298 $db = ilStudyProgrammeDIC::dic()['model.AutoCategories.ilStudyProgrammeAutoCategoriesRepository'];
1299 $programmes =
1300 array_filter(
1301 array_map(
1302 static function (array $rec) {
1303 $values = array_values($rec);
1304 $prg_obj_id = (int) array_shift($values);
1305
1306 $references = ilObject::_getAllReferences($prg_obj_id);
1307 $prg_ref_id = (int) array_shift($references);
1308
1309 $prg = self::getInstanceByRefId($prg_ref_id);
1310 if ($prg->isAutoContentApplicable()) {
1311 return $prg;
1312 }
1313 },
1314 $db::getProgrammesFor($cat_ref_id)
1315 )
1316 );
1317 return $programmes;
1318 }
1319
1326 public function isAutoContentApplicable(): bool
1327 {
1328 $valid_status = in_array(
1329 $this->getSettings()->getAssessmentSettings()->getStatus(),
1330 [
1333 ],
1334 true
1335 );
1336
1337 $crslnk_allowed = (
1338 $this->hasLPChildren()
1339 || $this->getAmountOfChildren(true) === 0
1340 );
1341
1342 return $valid_status && $crslnk_allowed;
1343 }
1344
1345
1347 // AUTOMATIC MEMBERSHIPS
1349
1354 public function getAutomaticMembershipSources(): array
1355 {
1356 return $this->auto_memberships_repository->getFor($this->getId());
1357 }
1358
1362 public function storeAutomaticMembershipSource(string $type, int $src_id, bool $search_recursive): void
1363 {
1364 $ams = $this->auto_memberships_repository->create(
1365 $this->getId(),
1366 $type,
1367 $src_id,
1368 false,
1369 null,
1370 null,
1371 $search_recursive
1372 );
1373 $this->auto_memberships_repository->update($ams);
1374 }
1375
1379 public function deleteAutomaticMembershipSource(string $type, int $src_id): void
1380 {
1381 $this->auto_memberships_repository->delete($this->getId(), $type, $src_id);
1382 }
1383
1388 {
1389 $this->auto_memberships_repository->deleteFor($this->getId());
1390 }
1391
1395 public function disableAutomaticMembershipSource(string $type, int $src_id, bool $search_recursive): void
1396 {
1397 $ams = $this->auto_memberships_repository->create(
1398 $this->getId(),
1399 $type,
1400 $src_id,
1401 false,
1402 null,
1403 null,
1404 $search_recursive
1405 );
1406 $this->auto_memberships_repository->update($ams);
1407 }
1408
1413 public function enableAutomaticMembershipSource(string $type, int $src_id, bool $search_recursive, $assign_now = false): void
1414 {
1415 if ($assign_now) {
1417 $member_ids = $this->getMembersOfMembershipSource($type, $src_id);
1418 foreach ($member_ids as $usr_id) {
1419 if (!$this->getAssignmentsOfSingleProgramForUser($usr_id)) {
1420 $this->assignUser($usr_id, $assigned_by);
1421 }
1422 }
1423 }
1424 $ams = $this->auto_memberships_repository->create(
1425 $this->getId(),
1426 $type,
1427 $src_id,
1428 true,
1429 null,
1430 null,
1431 $search_recursive
1432 );
1433 $this->auto_memberships_repository->update($ams);
1434 }
1435
1441 protected function getMembersOfMembershipSource(ilStudyProgrammeAutoMembershipSource $ams, ?int $exclude_id): array
1442 {
1443 $source_reader = $this->membersourcereader_factory->getReaderFor($ams, $exclude_id);
1444 return $source_reader->getMemberIds();
1445 }
1446
1451 protected static function getProgrammesMonitoringMemberSource(string $src_type, int $src_id): array
1452 {
1453 $db = ilStudyProgrammeDIC::dic()['model.AutoMemberships.ilStudyProgrammeAutoMembershipsRepository'];
1454 $programmes = array_map(
1455 static function ($rec) {
1456 $values = array_values($rec);
1457 $prg_obj_id = (int) array_shift($values);
1458
1459 $references = ilObject::_getAllReferences($prg_obj_id);
1460 $prg_ref_id = (int) array_shift($references);
1461
1462 $prg = self::getInstanceByRefId($prg_ref_id);
1463 return $prg;
1464 },
1465 $db::getProgrammesFor($src_type, $src_id)
1466 );
1467 return $programmes;
1468 }
1469
1470 public static function addMemberToProgrammes(string $src_type, int $src_id, int $usr_id): void
1471 {
1472 foreach (self::getProgrammesMonitoringMemberSource($src_type, $src_id) as $prg) {
1473 if ($prg->isActive() &&
1474 !$prg->hasAssignmentsOfSingleProgramForUser($usr_id)) {
1476 $prg->assignUser($usr_id, $assigned_by);
1477 }
1478 }
1479 }
1480
1481 public static function removeMemberFromProgrammes(string $src_type, int $src_id, int $usr_id): void
1482 {
1483 $now = new DateTimeImmutable();
1484 $assignment_repository = ilStudyProgrammeDIC::dic()['repo.assignment'];
1485 foreach (self::getProgrammesMonitoringMemberSource($src_type, $src_id) as $prg) {
1486 $assignments = $prg->getAssignmentsOfSingleProgramForUser($usr_id);
1487 $next_membership_source = $prg->getApplicableMembershipSourceForUser($usr_id, $src_id);
1488
1489 foreach ($assignments as $assignment) {
1490 if (!$assignment->getProgressTree()->isInProgress()) {
1491 continue;
1492 }
1493
1494 if (
1495 $next_membership_source !== null
1496 && $next_membership_source?->isEnabled()
1497 && $next_membership_source->getSourceId() !== $src_id
1498 ) {
1499 $new_src_type = $next_membership_source->getSourceType();
1500 $assigned_by = ilStudyProgrammeAutoMembershipSource::SOURCE_MAPPING[$new_src_type];
1501 $assignment = $assignment->withLastChange($assigned_by, $now);
1502 $assignment_repository->store($assignment);
1503 break;
1504 } else {
1505 $assignment_repository->delete($assignment);
1506 }
1507 }
1508 }
1509 }
1510
1512 int $usr_id,
1513 ?int $exclude_id
1515 foreach ($this->getAutomaticMembershipSources() as $ams) {
1516 if ($ams->isEnabled()) {
1517 $source_members = $this->getMembersOfMembershipSource($ams, $exclude_id);
1518 if (in_array($usr_id, $source_members)) {
1519 return $ams;
1520 }
1521 }
1522 }
1523 return null;
1524 }
1525
1527 // HELPERS
1529
1533 protected function updateLastChange(): void
1534 {
1535 $this->getSettings()->updateLastChange();
1536 if ($parent = $this->getParent()) {
1537 $parent->updateLastChange();
1538 }
1539 $this->update();
1540 }
1541
1553 public static function setProgressesCompletedFor(int $obj_id, int $user_id): void
1554 {
1555 // We only use courses via crs_refs
1556 $type = ilObject::_lookupType($obj_id);
1557 if ($type === "crsr") {
1558 foreach (ilObject::_getAllReferences($obj_id) as $ref_id) {
1559 self::setProgressesCompletedIfParentIsProgrammeInLPCompletedMode($ref_id, $obj_id, $user_id);
1560 }
1561 }
1562 }
1563
1568 int $ref_id,
1569 int $obj_id,
1570 int $user_id
1571 ): void {
1572 global $DIC; // TODO: replace this by a settable static for testing purpose?
1573 $tree = $DIC['tree'];
1574 $node_data = $tree->getParentNodeData($ref_id);
1575 if (count($node_data) === 0 || !array_key_exists('type', $node_data) || $node_data["type"] !== "prg") {
1576 return;
1577 }
1578 self::initStudyProgrammeCache();
1579 $prg = self::getInstanceByRefId($node_data["child"]);
1580 if ($prg->getLPMode() !== ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
1581 return;
1582 }
1583 $prg->succeed($user_id, $obj_id);
1584 }
1585
1586 public function succeed(int $usr_id, int $triggering_obj_id, ?ilPRGAssignment $ass = null): void
1587 {
1588 $progress_node_id = $this->getId();
1589 if (is_null($ass)) {
1590 $user_assignments = $this->assignment_repository
1591 ->getAllForNodeIsContained($progress_node_id, [$usr_id]);
1592 } else {
1593 $user_assignments = [$ass];
1594 }
1595
1596 foreach ($user_assignments as $ass) {
1597 $ass = $ass->succeed(
1598 $this->getSettingsRepository(),
1599 $progress_node_id,
1600 $triggering_obj_id
1601 );
1602 $this->assignment_repository->store($ass);
1603 }
1604 }
1605
1606 public function updateCustomIcon(): void
1607 {
1608 $customIcon = $this->custom_icon_factory->getByObjId($this->getId(), $this->getType());
1609 $subtype = $this->getSubType();
1610
1611 if ($subtype && $subtype->getIconIdentifier()) {
1612 $src = $this->type_repository->getIconPathFS($subtype);
1613
1614 //This is a horrible hack to allow Flysystem/LocalFilesystem to read the file.
1615 $tmp = 'ico_' . $this->getId();
1616 copy($src, \ilFileUtils::getDataDir() . '/temp/' . $tmp);
1617
1618 $customIcon->saveFromTempFileName($tmp);
1619 } else {
1620 $customIcon->remove();
1621 }
1622 }
1623
1625 // HOOKS
1627
1638 public static function getCreatableSubObjects(array $subobjects, $ref_id): array
1639 {
1640 if ($ref_id === null) {
1641 return $subobjects;
1642 }
1643
1644 if (ilObject::_lookupType($ref_id, true) !== "prg") {
1645 throw new ilException("Ref-Id '$ref_id' does not belong to a study programme object.");
1646 }
1647
1648 $parent = self::getInstanceByRefId($ref_id);
1649
1650 $mode = $parent->getLPMode();
1651
1652 switch ($mode) {
1654 $possible_subobjects = $subobjects;
1655 break;
1657 $possible_subobjects = [
1658 "prg" => $subobjects["prg"],
1659 "prgr" => $subobjects["prgr"]
1660 ];
1661 break;
1663 $possible_subobjects = ['crsr' => $subobjects['crsr']];
1664 break;
1665 default:
1666 throw new ilException("Undefined mode for study programme: '$mode'");
1667 }
1668
1669 if ($parent->hasAutomaticContentCategories()) {
1670 $possible_subobjects = array_filter(
1671 $possible_subobjects,
1672 static function ($subtype) {
1673 return $subtype === 'crsr';
1674 },
1675 ARRAY_FILTER_USE_KEY
1676 );
1677 }
1678 return $possible_subobjects;
1679 }
1680
1681
1682 protected function getLoggedInUserId(): int
1683 {
1684 return $this->ilUser->getId();
1685 }
1686
1687 protected function getNow(): DateTimeImmutable
1688 {
1689 return new DateTimeImmutable();
1690 }
1691
1692 protected function refreshLPStatus(int $usr_id, ?int $node_obj_id = null): void
1693 {
1694 if (is_null($node_obj_id)) {
1695 $node_obj_id = $this->getId();
1696 }
1697 ilLPStatusWrapper::_updateStatus($node_obj_id, $usr_id);
1698 }
1699
1700 public function markAccredited(
1701 int $assignment_id,
1702 int $acting_usr_id,
1703 ilPRGMessageCollection $err_collection
1704 ): void {
1705 $progress_node_id = $this->getId();
1706 $assignment = $this->assignment_repository->get($assignment_id)
1707 ->markAccredited(
1708 $this->getSettingsRepository(),
1709 $this->events,
1710 $progress_node_id,
1711 $acting_usr_id,
1712 $err_collection
1713 );
1714
1715 $this->assignment_repository->store($assignment);
1716 }
1717
1718 public function unmarkAccredited(
1719 int $assignment_id,
1720 int $acting_usr_id,
1721 ilPRGMessageCollection $err_collection
1722 ): void {
1723 $progress_node_id = $this->getId();
1724 $assignment = $this->assignment_repository->get($assignment_id)
1725 ->unmarkAccredited(
1726 $this->getSettingsRepository(),
1727 $progress_node_id,
1728 $acting_usr_id,
1729 $err_collection
1730 );
1731
1732 $this->assignment_repository->store($assignment);
1733 $this->refreshLPStatus($assignment->getUserId());
1734 }
1735
1736 public function markNotRelevant(
1737 int $assignment_id,
1738 int $acting_usr_id,
1739 ilPRGMessageCollection $err_collection
1740 ): void {
1741 $progress_node_id = $this->getId();
1742 $assignment = $this->assignment_repository->get($assignment_id)
1743 ->markNotRelevant(
1744 $this->getSettingsRepository(),
1745 $progress_node_id,
1746 $acting_usr_id,
1747 $err_collection
1748 );
1749
1750 $this->assignment_repository->store($assignment);
1751 $this->refreshLPStatus($assignment->getUserId());
1752 }
1753
1754 public function markRelevant(
1755 int $assignment_id,
1756 int $acting_usr_id,
1757 ilPRGMessageCollection $err_collection
1758 ): void {
1759 $progress_node_id = $this->getId();
1760 $assignment = $this->assignment_repository->get($assignment_id)
1761 ->markRelevant(
1762 $this->getSettingsRepository(),
1763 $progress_node_id,
1764 $acting_usr_id,
1765 $err_collection
1766 );
1767
1768 $this->assignment_repository->store($assignment);
1769 $this->refreshLPStatus($assignment->getUserId());
1770 }
1771
1772 public function changeProgressDeadline(
1773 int $assignment_id,
1774 int $acting_usr_id,
1775 ilPRGMessageCollection $err_collection,
1776 ?DateTimeImmutable $deadline
1777 ): void {
1778 $progress_node_id = $this->getId();
1779 $assignment = $this->assignment_repository->get($assignment_id)
1780 ->changeProgressDeadline(
1781 $this->getSettingsRepository(),
1782 $progress_node_id,
1783 $acting_usr_id,
1784 $err_collection,
1785 $deadline
1786 );
1787
1788 $this->assignment_repository->store($assignment);
1789 $this->refreshLPStatus($assignment->getUserId());
1790 }
1791
1793 int $assignment_id,
1794 int $acting_usr_id,
1795 ilPRGMessageCollection $err_collection,
1796 ?DateTimeImmutable $validity
1797 ): void {
1798 $progress_node_id = $this->getId();
1799 $assignment = $this->assignment_repository->get($assignment_id)
1800 ->changeProgressValidityDate(
1801 $this->getSettingsRepository(),
1802 $progress_node_id,
1803 $acting_usr_id,
1804 $err_collection,
1805 $validity
1806 );
1807
1808 $this->assignment_repository->store($assignment);
1809 $this->refreshLPStatus($assignment->getUserId());
1810 }
1811
1812 public function changeAmountOfPoints(
1813 int $assignment_id,
1814 int $acting_usr_id,
1815 ilPRGMessageCollection $err_collection,
1816 int $points
1817 ): void {
1818 $progress_node_id = $this->getId();
1819 $assignment = $this->assignment_repository->get($assignment_id)
1820 ->changeAmountOfPoints(
1821 $this->getSettingsRepository(),
1822 $progress_node_id,
1823 $acting_usr_id,
1824 $err_collection,
1825 $points
1826 );
1827
1828 $this->assignment_repository->store($assignment);
1829 $this->refreshLPStatus($assignment->getUserId());
1830 }
1831
1833 int $assignment_id,
1834 int $acting_usr_id,
1835 ?ilPRGMessageCollection $err_collection = null
1836 ): void {
1837 $assignment = $this->assignment_repository->get($assignment_id)
1839 $this->getSettingsRepository(),
1840 $acting_usr_id,
1841 $err_collection
1842 );
1843
1844 $this->assignment_repository->store($assignment);
1845 $this->refreshLPStatus($assignment->getUserId());
1846 }
1847
1848 public function acknowledgeCourses(
1849 int $assignment_id,
1850 array $nodes,
1851 ?ilPRGMessageCollection $err_collection = null
1852 ): void {
1853 $acting_usr_id = $this->getLoggedInUserId();
1854 $assignment = $this->assignment_repository->get($assignment_id);
1855 foreach ($nodes as $nodeinfo) {
1856 [$node_obj_id, $course_obj_id] = $nodeinfo;
1857
1858 $assignment = $assignment->succeed(
1859 $this->settings_repository,
1860 $node_obj_id,
1861 $course_obj_id
1862 );
1863
1864 $msg = sprintf(
1865 '%s, progress-id (%s/%s)',
1866 $assignment->getUserInformation()->getFullname(),
1867 $assignment->getId(),
1868 (string) $node_obj_id
1869 );
1870 $err_collection->add(true, 'acknowledged_course', $msg);
1871 }
1872 $this->assignment_repository->store($assignment);
1873 $this->refreshLPStatus($assignment->getUserId());
1874 }
1875
1876 public function canBeCompleted(ilPRGProgress $progress): bool
1877 {
1878 if ($this->getStatus() === ilStudyProgrammeSettings::STATUS_DRAFT) {
1879 return false;
1880 }
1881 if ($this->getLPMode() == ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
1882 return true;
1883 }
1884 $possible_points = $progress->getPossiblePointsOfRelevantChildren();
1885 return $possible_points >= $progress->getAmountOfPoints();
1886 }
1887
1891 public function statusToRepr(int $status): string
1892 {
1893 $lng = $this->lng;
1894 $lng->loadLanguageModule("prg");
1895 if ($status === ilPRGProgress::STATUS_IN_PROGRESS) {
1896 return $lng->txt("prg_status_in_progress");
1897 }
1898 if ($status === ilPRGProgress::STATUS_COMPLETED) {
1899 return $lng->txt("prg_status_completed");
1900 }
1901 if ($status === ilPRGProgress::STATUS_ACCREDITED) {
1902 return $lng->txt("prg_status_accredited");
1903 }
1904 if ($status === ilPRGProgress::STATUS_NOT_RELEVANT) {
1905 return $lng->txt("prg_status_not_relevant");
1906 }
1907 if ($status === ilPRGProgress::STATUS_FAILED) {
1908 return $lng->txt("prg_status_failed");
1909 }
1910 throw new ilException("Unknown status: '$status'");
1911 }
1912
1913 public function hasContentPage(): bool
1914 {
1915 return \ilContainerPage::_exists(self::CP_TYPE, $this->getId());
1916 }
1917 public function createContentPage(): void
1918 {
1919 if ($this->hasContentPage()) {
1920 throw new \LogicException('will not create content page - it already exists.');
1921 }
1922 $new_page_object = new \ilContainerPage();
1923 $new_page_object->setId($this->getId());
1924 $new_page_object->setParentId($this->getId());
1925 $new_page_object->createFromXML();
1926 }
1927}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
static saveObjRecSelection(int $a_obj_id, string $a_sub_type="", ?array $a_records=null, bool $a_delete_before=true)
Save repository object record selection.
static _lookupTitle(int $obj_id)
static _lookupSourceIds(int $a_target_id)
Get ids of all container references that target the object with the given id.
static _lookupTargetId(int $a_obj_id)
static _lookupTargetRefId(int $a_obj_id)
static _getInstance(int $a_obj_id)
Class ilContainer.
Base class for ILIAS Exception handling.
static getDataDir()
get data directory (outside webspace)
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
static _hasUserCompleted(int $a_obj_id, int $a_user_id)
Lookup user object completion.
static getLogger(string $a_component_id)
Get component logger.
Component logger with individual log levels by component id.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Cache for ilObjStudyProgrammes.
enableAutomaticMembershipSource(string $type, int $src_id, bool $search_recursive, $assign_now=false)
Enable a membership source.
getLPChildren()
Get the leafs the study programme contains.
getCertificateRelevantAssignmentIds(int ... $usr_ids)
hasAssignmentOf(int $user_id)
Check whether user is assigned to this program or any node above.
getAssignmentsOf(int $user_id)
Get the assignments of user at this program or any node above.
getRoot()
Get the ilObjStudyProgramme that is the root node of the tree this programme is in.
static setProgressesCompletedIfParentIsProgrammeInLPCompletedMode(int $ref_id, int $obj_id, int $user_id)
getAmountOfChildren($include_references=false)
Get the amount of other StudyProgrammes this StudyProgramme has as children.
getMembers()
get usr_ids with any progress on this node
canBeCompleted(ilPRGProgress $progress)
__construct(int $id=0, bool $call_by_reference=true)
ATTENTION: After using the constructor the object won't be in the cache.
static removeCrsFromProgrammes(int $crs_ref_id, int $cat_ref_id)
Check, if a category is under surveillance and automatically remove the deleted course.
hasAssignmentsOfSingleProgramForUser(int $usr_id)
Get assignments of user to this program-node only.
deleteAutomaticContentCategories(array $category_ids=[])
Delete configuration of categories with auto-content for this StudyProgramme;.
ilStudyProgrammeSettingsDBRepository $settings_repository
getSpecificAssignment(int $assignment_id)
static getCreatableSubObjects(array $subobjects, $ref_id)
Filter the list of possible subobjects for the objects that actually could be created on a concrete n...
getMembersOfMembershipSource(ilStudyProgrammeAutoMembershipSource $ams, ?int $exclude_id)
Get member-ids of a certain source.
updateSettings(ilStudyProgrammeSettings $settings)
changeProgressDeadline(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection, ?DateTimeImmutable $deadline)
refreshLPStatus(int $usr_id, ?int $node_obj_id=null)
applyToSubTreeNodes(Closure $fun, bool $include_references=false)
Apply the given Closure to every node in the subtree starting at this object.
canBeRemoved()
Check weather a node can be removed.
changeAmountOfPoints(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection, int $points)
changeProgressValidityDate(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection, ?DateTimeImmutable $validity)
isAutoContentApplicable()
AutoContent should only be available in active- or draft-mode, and only, if there is no sub-programme...
resetRiskyToFailSentFor(ilPRGAssignment $ass)
static getProgrammesMonitoringMemberSource(string $src_type, int $src_id)
Get all StudyProgrammes monitoring this membership-source.
acknowledgeCourses(int $assignment_id, array $nodes, ?ilPRGMessageCollection $err_collection=null)
setPoints(int $points)
Set the amount of points.
resetExpiryInfoSentFor(ilPRGAssignment $ass)
deleteAllAutomaticContentCategories()
Delete all configuration of categories with auto-content for this StudyProgramme;.
static getInstanceByObjId(int $obj_id)
ilPRGAssignmentDBRepository $assignment_repository
getReferencesTo(ilObjStudyProgramme $prg)
static setProgressesCompletedFor(int $obj_id, int $user_id)
Succeed all StudyProgramme(Nodes) where the object with the given id (a CRSR) is in a Programme with ...
statusToRepr(int $status)
Get a user readable representation of a status.
markRelevant(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection)
nodeInserted($prg)
Clears child cache and adds progress for new node.
static getProgrammesMonitoringCategory(int $cat_ref_id)
Get all (not OUTDATED) StudyProgrammes monitoring this category.
cloneObject(int $target_ref_id, int $copy_id=0, bool $omit_tree=false)
deleteAllAutomaticMembershipSources()
Delete all membership sources of this StudyProgramme;.
getPoints()
Get the amount of points.
assignUser(int $usr_id, ?int $acting_usr_id=null, $raise_event=true)
Assign a user to this node at the study program.
removeAssignment(ilPRGAssignment $assignment)
Remove an assignment from this program.
storeAutomaticContentCategory(int $category_ref_id)
Store a Category with auto-content for this StudyProgramme; a category can only be referenced once (p...
ilStudyProgrammeEvents $events
clearLPChildrenCache()
Clear the cached lp children.
moveTo(ilObjStudyProgramme $new_parent)
Move this tree node to a new parent.
getLocalMembers()
get usr_ids with assignment on this node
getCompletedCourses(ilPRGAssignment $assignment)
Get courses in this program that the given user already completed.
disableAutomaticMembershipSource(string $type, int $src_id, bool $search_recursive)
Disable a membership source.
clearParentCache()
Clear the cached parent to query it again at the tree.
addMissingProgresses()
Add missing progress records for all assignments of this programm.
storeRiskyToFailSentFor(ilPRGAssignment $ass)
getChildren(bool $include_references=false)
Get all ilObjStudyProgrammes that are direct children of this object.
updatePlanFromRepository(int $assignment_id, int $acting_usr_id, ?ilPRGMessageCollection $err_collection=null)
static addMemberToProgrammes(string $src_type, int $src_id, int $usr_id)
ilStudyProgrammeTypeDBRepository $type_repository
CustomIconFactory $custom_icon_factory
ilObjectFactoryWrapper $object_factory
getAutomaticContentCategories()
Get configuration of categories with auto-content for this StudyProgramme;.
static addCrsToProgrammes(int $crs_ref_id, int $cat_ref_id)
Check, if a category is under surveilllance and automatically add the course.
getLastChange()
Get the timestamp of the last change on this program or sub program.
getApplicableMembershipSourceForUser(int $usr_id, ?int $exclude_id)
clearChildrenCache()
Clear the cached children.
storeExpiryInfoSentFor(ilPRGAssignment $ass)
putInTree(int $parent_ref_id)
Overwritten from ilObject.
hasChildren(bool $include_references=false)
Does this StudyProgramme have other ilObjStudyProgrammes as children?
ilStudyProgrammeAutoMembershipsDBRepository $auto_memberships_repository
deleteAssignmentsAndProgresses()
Delete all assignments from the DB.
setStatus(int $a_status)
Set the status of the node.
getAssignmentsOfSingleProgramForUser(int $usr_id)
Get assignments of user to this program-node only.
succeed(int $usr_id, int $triggering_obj_id, ?ilPRGAssignment $ass=null)
getAutomaticMembershipSources()
Get sources for auto-memberships.
unmarkAccredited(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection)
getDepth()
Get the depth of this StudyProgramme in the tree starting at the topmost StudyProgramme (not root nod...
static getAllChildren(int $a_ref_id, bool $include_references=false)
Get a list of all ilObjStudyProgrammes in the subtree starting at $a_ref_id.
static createInstance()
Create an instance of ilObjStudyProgramme, put in cache.
static ilObjStudyProgrammeCache $study_programme_cache
getSubType()
Gets the SubType Object.
getAmountOfAssignmentsOf(int $user_id)
Get the amount of assignments a user has on this program node or any node above.
ilStudyProgrammeAutoCategoryDBRepository $auto_categories_repository
removeNode(ilObjStudyProgramme $a_prg)
Remove a node from this object.
static getRefIdFor(int $obj_id)
markAccredited(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection)
deleteAutomaticMembershipSource(string $type, int $src_id)
Delete a membership source.
hasAssignments()
Are there any assignments on this node or any node above?
getParent()
Get the parent ilObjStudyProgramme of this object.
hasRelevantProgresses()
Are there any users that have a relevant progress on this programme?
getLPChildrenIds()
Get the obj-ids of the leafs the program contains.
updateLastChange()
Update last change timestamp on this node and its parents.
getAmountOfLPChildren()
Get the amount of leafs the study programme contains.
static removeMemberFromProgrammes(string $src_type, int $src_id, int $usr_id)
adjustLPMode()
Adjust the lp mode to match current state of tree:
storeAutomaticMembershipSource(string $type, int $src_id, bool $search_recursive)
Store a source to be monitored for automatic memberships.
addNode(ilObjStudyProgramme $a_prg)
Inserts another ilObjStudyProgramme in this object.
ilStudyProgrammeMembershipSourceReaderFactory $membersourcereader_factory
getParents(bool $include_references=false)
Get all parents of the node, where the root of the program comes first.
markNotRelevant(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection)
User class.
Class ilObjectFactoryWrapper.
Class ilObject Basic functions for all objects.
static _lookupObjectId(int $ref_id)
static _lookupType(int $id, bool $reference=false)
createReference()
creates reference for object
static _getAllReferences(int $id)
get all reference ids for object ID
static _lookupDeletedDate(int $ref_id)
ilTree $tree
bool $call_by_reference
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
string $type
ilDBInterface $db
Assignments are relations of users to a PRG; They hold progress-information for (sub-)nodes of the PR...
Assignments are relations of users to a PRG; They hold progress-information for (sub-)nodes of the PR...
getProgresses(array &$ret=[], ?ilPRGProgress $pgs=null)
getProgressForNode(int $node_id)
Holds information about multi-actions, mainly in context of member-assignemnts and status changes.
add(bool $success, string $message, string $record_identitifer)
A Progress is the status of a user on a single node of an assignment; it is unique by assignment_id:u...
ILIAS Setting Class.
Provides adapters to read member-ids from a specific source.
getObjId()
Get the id of the study program.
Exception is thrown when invariants on the program tree would be violated by manipulation of tree.
Class ilStudyProgrammeType.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
isDeleted(int $a_node_id)
This is a wrapper for isSaved() with a more useful name.
getRefIdFor(int $obj_id)
updatePlanFromRepository(ilStudyProgrammeSettingsRepository $settings_repo, int $acting_usr_id, ilPRGMessageCollection $err_collection)
ilCertificateTemplateRepository $certificate_template_repository
The filesystem interface provides the public interface for the Filesystem service API consumer.
Definition: Filesystem.php:37
fetchCurrentlyUsedCertificate(int $objId)
Covers the persistence of settings belonging to a study programme (SP).
$ref_id
Definition: ltiauth.php:66
$dic
Definition: ltiresult.php:33
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
get(string $class_name)
global $lng
Definition: privfeed.php:26
global $DIC
Definition: shib_login.php:26