ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilObjStudyProgramme.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 2015-2019 Richard Klees <richard.klees@concepts-and-training.de>, Stefan Hecken <stefan.hecken@concepts-and-training.de> Extended GPL, see docs/LICENSE */
4
5declare(strict_types=1);
6
8{
12 protected $settings;
13
17 protected $parent;
18
22 protected $children;
23
27 protected $lp_children;
28
33
38
43
48
53
58
62 protected $progress_db;
63
67 protected $assignment_db;
68
72 protected $events;
73
74 // GLOBALS from ILIAS
75
79 public $webdir;
80
84 public $tree;
85
89 public $ilUser;
90
94 protected $db;
95
99 protected $plugin_admin;
100
105
111
115 protected $ps;
116
120 protected $reference_children = [];
121
125 public static $study_programme_cache = null;
126
130 protected $members_cache;
131
136 public function __construct($a_id = 0, bool $a_call_by_reference = true)
137 {
138 $this->type = "prg";
139 $this->settings = null;
140 $this->settings_repository =
141 ilStudyProgrammeDIC::dic()['model.Settings.ilStudyProgrammeSettingsRepository'];
142 $this->type_repository =
143 ilStudyProgrammeDIC::dic()['model.Type.ilStudyProgrammeTypeRepository'];
144 $this->assignment_repository =
145 ilStudyProgrammeDIC::dic()['model.Assignment.ilStudyProgrammeAssignmentRepository'];
146 $this->progress_repository =
147 ilStudyProgrammeDIC::dic()['model.Progress.ilStudyProgrammeProgressRepository'];
148 $this->auto_categories_repository =
149 ilStudyProgrammeDIC::dic()['model.AutoCategories.ilStudyProgrammeAutoCategoriesRepository'];
150 $this->auto_memberships_repository =
151 ilStudyProgrammeDIC::dic()['model.AutoMemberships.ilStudyProgrammeAutoMembershipsRepository'];
152 $this->membersourcereader_factory =
153 ilStudyProgrammeDIC::dic()['model.AutoMemberships.ilStudyProgrammeMembershipSourceReaderFactory'];
154
155 $this->progress_db = ilStudyProgrammeDIC::dic()['ilStudyProgrammeUserProgressDB'];
156 $this->assignment_db = ilStudyProgrammeDIC::dic()['ilStudyProgrammeUserAssignmentDB'];
157 $this->events = ilStudyProgrammeDIC::dic()['ilStudyProgrammeEvents'];
158
159 parent::__construct($a_id, $a_call_by_reference);
160
161 $this->clearParentCache();
162 $this->clearChildrenCache();
163 $this->clearLPChildrenCache();
164
165 global $DIC;
166 $tree = $DIC['tree'];
167 $ilUser = $DIC['ilUser'];
168 $this->webdir = $DIC->filesystem()->web();
169 $this->tree = $tree;
170 $this->ilUser = $ilUser;
171 $this->db = $DIC['ilDB'];
172 $this->plugin_admin = $DIC['ilPluginAdmin'];
173 $this->lng = $DIC['lng'];
174
175 $this->object_factory = ilObjectFactoryWrapper::singleton();
176 $this->ps = ilStudyProgrammeDIC::dic()['ilOrgUnitObjectTypePositionSetting'];
177
179 }
180
181 public static function initStudyProgrammeCache() : void
182 {
183 if (self::$study_programme_cache === null) {
184 self::$study_programme_cache = ilObjStudyProgrammeCache::singleton();
185 }
186 }
187
191 protected function clearParentCache() : void
192 {
193 // This is not initialized, but we need null if there is no parent.
194 $this->parent = false;
195 }
196
200 protected function clearChildrenCache() : void
201 {
202 $this->children = null;
203 }
204
208 protected function clearLPChildrenCache() : void
209 {
210 $this->lp_children = null;
211 }
212
213 public static function getInstanceByRefId($a_ref_id) : ilObjStudyProgramme
214 {
215 if (self::$study_programme_cache === null) {
217 }
218 return self::$study_programme_cache->getInstanceByRefId($a_ref_id);
219 }
220
226 public static function createInstance() : ilObjStudyProgramme
227 {
228 $obj = new ilObjStudyProgramme();
229 $obj->create();
230 $obj->createReference();
231 self::$study_programme_cache->addInstance($obj);
232 return $obj;
233 }
234
236 // CRUD
238
246 protected function readSettings() : void
247 {
248 if ($this->settings !== null) {
249 throw new ilException("ilObjStudyProgramme::loadSettings: already loaded.");
250 }
251 $id = $this->getId();
252 if (!$id) {
253 throw new ilException("ilObjStudyProgramme::loadSettings: no id.");
254 }
255 $this->settings = $this->settings_repository->read($this->getId());
256 }
257
265 protected function createSettings() : void
266 {
267 if ($this->settings !== null) {
268 throw new ilException("ilObjStudyProgramme::createSettings: already loaded.");
269 }
270
271 $id = $this->getId();
272 if (!$id) {
273 throw new ilException("ilObjStudyProgramme::loadSettings: no id.");
274 }
275 $this->settings = $this->settings_repository->createFor($this->getId());
276 }
277
284 protected function updateSettings() : void
285 {
286 if ($this->settings === null) {
287 throw new ilException("ilObjStudyProgramme::updateSettings: no settings loaded.");
288 }
289 $this->settings_repository->update($this->settings);
290 }
291
298 protected function deleteSettings() : void
299 {
300 if ($this->settings === null) {
301 throw new ilException("ilObjStudyProgramme::deleteSettings: no settings loaded.");
302 }
303 $this->settings_repository->delete($this->settings);
304 }
305
311 protected function deleteAssignments() : void
312 {
313 foreach ($this->getAssignments() as $ass) {
314 $ass->delete();
315 }
316 }
317
321 public function read() : void
322 {
323 parent::read();
324 $this->readSettings();
325 }
326
330 public function create() : int
331 {
332 $id = parent::create();
333 $this->createSettings();
334
335 return (int) $id;
336 }
337
341 public function update() : void
342 {
343 parent::update();
344
345 // Update selection for advanced meta data of the type
346 if ($this->getTypeSettings()->getTypeId()) {
348 $this->getId(),
349 'prg_type',
350 $this->type_repository->readAssignedAMDRecordIdsByType($this->getTypeSettings()->getTypeId())
351 );
352 } else {
353 // If no type is assigned, delete relations by passing an empty array
354 ilAdvancedMDRecord::saveObjRecSelection($this->getId(), 'prg_type', array());
355 }
356 $this->updateSettings();
357 }
358
364 public function delete() : bool
365 {
366 // always call parent delete function first!!
367 if (!parent::delete()) {
368 return false;
369 }
370
371 $this->deleteSettings();
372 try {
373 $this->deleteAssignments();
374 $this->auto_categories_repository->deleteFor((int) $this->getId());
376 // This would be the case when SP is in trash (#17797)
377 }
378
381
382 $this->events->raise('delete', ['object' => $this, 'obj_id' => $this->getId()]);
383 return true;
384 }
385
387 // GETTERS AND SETTERS
389
393 public function getLastChange() : DateTime
394 {
395 return $this->settings->getLastChange();
396 }
397
401 public function getPoints() : int
402 {
403 return $this->settings->getAssessmentSettings()->getPoints();
404 }
405
411 public function setPoints(int $a_points) : ilObjStudyProgramme
412 {
414 $settings = $settings->withPoints($a_points);
416 $this->updateLastChange();
417 return $this;
418 }
419
420 public function getLPMode() : int
421 {
422 return $this->settings->getLPMode();
423 }
424
433 public function adjustLPMode() : void
434 {
435 if ($this->getAmountOfLPChildren() > 0) {
436 $this->settings_repository->update(
438 );
439 } else {
440 if ($this->getAmountOfChildren(true) > 0) {
441 $this->settings_repository->update(
443 );
444 } else {
445 $this->settings_repository->update(
447 );
448 }
449 }
450 }
451
452 public function getStatus() : int
453 {
454 return $this->getAssessmentSettings()->getStatus();
455 }
456
462 public function setStatus(int $a_status) : ilObjStudyProgramme
463 {
464 $settings = $this->getAssessmentSettings()->withStatus($a_status);
466 $this->updateLastChange();
467 return $this;
468 }
469
470 public function isActive() : bool
471 {
473 }
474
480 public function getSubType()
481 {
482 if (!in_array($this->getTypeSettings()->getTypeId(), array("-", "0"))) {
483 $subtype_id = $this->getTypeSettings()->getTypeId();
484 return $this->type_repository->readType($subtype_id);
485 }
486
487 return null;
488 }
489
491 {
492 return $this->settings->getTypeSettings();
493 }
494
495 public function setTypeSettings(\ilStudyProgrammeTypeSettings $type_settings) : void
496 {
497 $this->settings = $this->settings->withTypeSettings($type_settings);
498 }
499
501 {
502 return $this->settings->getAssessmentSettings();
503 }
504
505 public function setAssessmentSettings(
506 \ilStudyProgrammeAssessmentSettings $assessment_settings
507 ) : void {
508 $this->settings = $this->settings->withAssessmentSettings($assessment_settings);
509 }
510
512 {
513 return $this->settings->getDeadlineSettings();
514 }
515
516 public function setDeadlineSettings(\ilStudyProgrammeDeadlineSettings $deadline_settings) : void
517 {
518 $this->settings = $this->settings->withDeadlineSettings($deadline_settings);
519 }
520
522 {
523 return $this->settings->getValidityOfQualificationSettings();
524 }
525
527 \ilStudyProgrammeValidityOfAchievedQualificationSettings $validity_of_qualification_settings
528 ) : void {
529 $this->settings = $this->settings->withValidityOfQualificationSettings(
530 $validity_of_qualification_settings
531 );
532 }
533
535 {
536 return
537 $this->getPositionSettingsIsActiveForPrg() &&
538 !$this->getPositionSettingsIsChangeableForPrg()
539 ;
540 }
541
542 public function getPositionSettingsIsActiveForPrg() : bool
543 {
544 return $this->ps->isActive();
545 }
546
548 {
549 return $this->ps->isChangeableForObject();
550 }
551
553 {
554 return $this->settings->getAutoMailSettings();
555 }
556
557 public function setAutoMailSettings(\ilStudyProgrammeAutoMailSettings $automail_settings) : void
558 {
559 $this->settings = $this->settings->withAutoMailSettings($automail_settings);
560 }
561
562 public function shouldSendReAssignedMail() : bool
563 {
564 return $this->getAutoMailSettings()->getSendReAssignedMail();
565 }
566
567 public function shouldSendInfoToReAssignMail() : bool
568 {
569 return $this->getAutoMailSettings()->getReminderNotRestartedByUserDays() > 0;
570 }
571
572 public function shouldSendRiskyToFailMail() : bool
573 {
574 return $this->getAutoMailSettings()->getProcessingEndsNotSuccessfulDays() > 0;
575 }
576
578 // TREE NAVIGATION
580
589 public static function getAllChildren(int $a_ref_id, bool $include_references = false)
590 {
591 $ret = array();
592 $root = self::getInstanceByRefId($a_ref_id);
593 $root_id = $root->getId();
594 $root->applyToSubTreeNodes(function (ilObjStudyProgramme $prg) use (&$ret, $root_id) {
595 // exclude root node of subtree.
596 if ($prg->getId() == $root_id) {
597 return;
598 }
599 $ret[] = $prg;
600 }, $include_references);
601 return $ret;
602 }
603
604 public function getAllPrgChildren() : array
605 {
606 $ret = [];
607 $this->applyToSubTreeNodes(
608 function (ilObjStudyProgramme $prg) use (&$ret) {
609 if ($prg->getId() == $this->getId()) {
610 return;
611 }
612 $ret[] = $prg;
613 },
614 false
615 );
616 return $ret;
617 }
618
626 public function getChildren(bool $include_references = false) : array
627 {
628 $this->throwIfNotInTree();
629
630 if ($this->children === null) {
631 $ref_ids = $this->tree->getChildsByType($this->getRefId(), "prg");
632
633 // apply container sorting to tree
634 $sorting = ilContainerSorting::_getInstance($this->getId());
635 $ref_ids = $sorting->sortItems(array('prg' => $ref_ids));
636 $ref_ids = $ref_ids['prg'];
637
638 $this->children = array_map(function ($node_data) {
639 return ilObjStudyProgramme::getInstanceByRefId($node_data["child"]);
640 }, $ref_ids);
641 }
642 if ($include_references && $this->reference_children === null) {
643 $this->reference_children = [];
644 $ref_child_ref_ids = $this->tree->getChildsByType($this->getRefId(), "prgr");
645 foreach ($this->children as $prg) {
646 $ref_child_ref_ids =
647 array_merge(
648 $this->tree->getChildsByType($prg->getRefId(), "prgr"),
649 $ref_child_ref_ids
650 );
651 }
652 foreach (
653 array_unique(
654 array_map(
655 function ($data) {
656 return $data['child'];
657 },
658 array_filter($ref_child_ref_ids, function ($data) {
659 return $data["deleted"] === null;
660 })
661 )
662 ) as $prg_ref_id
663 ) {
664 $this->reference_children[] =
665 (new ilObjStudyProgrammeReference($prg_ref_id))->getReferencedObject();
666 }
667 }
668 return $include_references ?
669 array_merge($this->children, $this->reference_children) :
670 $this->children;
671 }
672
680 public function getParent()
681 {
682 if ($this->parent === false) {
683 $this->throwIfNotInTree();
684 $parent_data = $this->tree->getParentNodeData($this->getRefId());
685 if ($parent_data["type"] != "prg") {
686 $this->parent = null;
687 } else {
688 $this->parent = ilObjStudyProgramme::getInstanceByRefId($parent_data["ref_id"]);
689 }
690 }
691 return $this->parent;
692 }
693
694 protected function getReferencesTo(ilObjStudyProgramme $prg) : array
695 {
696 $tree = $this->tree;
697 return array_filter(
698 array_map(
699 function ($id) {
701 array_shift(
703 )
704 );
705 },
707 ),
708 function ($prg_ref) use ($tree) {
709 return !$tree->isDeleted($prg_ref->getRefId());
710 }
711 );
712 }
713
714 public function getReferencesToSelf() : array
715 {
716 return $this->getReferencesTo($this);
717 }
718
724 public function getParents(bool $include_references = false)
725 {
726 $current = $this;
727 $parents = [];
728 $queque = [$current];
729 while ($element = array_shift($queque)) {
730 $parent = $element->getParent();
731 if ($parent === null || $include_references) {
732 foreach ($this->getReferencesTo($element) as $reference) {
733 if ($this->tree->isDeleted($reference->getRefId())) {
734 continue;
735 }
736 $r_parent = $reference->getParent();
737 if (is_null($r_parent)) {
738 continue;
739 }
740 array_push($queque, $r_parent);
741 $parents[] = $r_parent;
742 }
743 continue;
744 }
745 array_push($queque, $parent);
746 $parents[] = $parent;
747 }
748 return array_reverse($parents);
749 }
750
756 public function hasChildren(bool $include_references = false) : bool
757 {
758 return $this->getAmountOfChildren($include_references) > 0;
759 }
760
768 public function getAmountOfChildren($include_references = false)
769 {
770 return count($this->getChildren($include_references));
771 }
772
780 public function getDepth() : int
781 {
782 $cur = $this;
783 $count = 0;
784 while ($cur = $cur->getParent()) {
785 $count++;
786 }
787 return $count;
788 }
789
796 public function getRoot()
797 {
798 $parents = $this->getParents();
799 return $parents[0];
800 }
801
808 public function getLPChildren()
809 {
810 $this->throwIfNotInTree();
811
812 if ($this->lp_children === null) {
813 $this->lp_children = array();
814
815 // TODO: find a better way to get all elements except StudyProgramme-children
816 $ref_ids = $this->tree->getChildsByType($this->getRefId(), "crsr");
817
818 // apply container sorting to tree
819 $sorting = ilContainerSorting::_getInstance($this->getId());
820 $ref_ids = $sorting->sortItems(array('crs_ref' => $ref_ids));
821 $ref_ids = $ref_ids['crs_ref'];
822
823 $lp_children = array_map(function ($node_data) {
824 $lp_obj = $this->object_factory->getInstanceByRefId($node_data["child"]);
825
826 // filter out all StudyProgramme instances
827 return ($lp_obj instanceof $this) ? null : $lp_obj;
828 }, $ref_ids);
829
830 $this->lp_children = array_filter($lp_children);
831 }
832 return $this->lp_children;
833 }
834
841 public function getLPChildrenIds()
842 {
843 return array_map(function ($child) {
844 return $child->getId();
845 }, $this->getLPChildren());
846 }
847
853 public function getAmountOfLPChildren()
854 {
855 return count($this->getLPChildren());
856 }
857
865 public function hasLPChildren()
866 {
867 return ($this->getAmountOfLPChildren() > 0);
868 }
869
874 protected function throwIfNotInTree()
875 {
876 if (!$this->tree->isInTree($this->getRefId())) {
877 throw new ilStudyProgrammeTreeException("This program is not in tree.");
878 }
879 }
880
882 // QUERIES ON SUBTREE
884
892 public function applyToSubTreeNodes(Closure $fun, bool $include_references = false)
893 {
894 $this->throwIfNotInTree();
895
896 if ($fun($this) !== false) {
897 foreach ($this->getChildren($include_references) as $child) {
898 $child->applyToSubTreeNodes($fun, $include_references);
899 }
900 }
901 }
902
908 public function getCompletedCourses(int $a_user_id) : array
909 {
910 require_once("Services/ContainerReference/classes/class.ilContainerReference.php");
911 require_once("Services/Tracking/classes/class.ilLPStatus.php");
912
913 $node_data = $this->tree->getNodeData($this->getRefId());
914 $crsrs = $this->tree->getSubTree($node_data, true, "crsr");
915
916 $completed_crss = array();
917 foreach ($crsrs as $ref) {
918 $crs_id = ilContainerReference::_lookupTargetId($ref["obj_id"]);
919 if (ilLPStatus::_hasUserCompleted($crs_id, $a_user_id)) {
920 $completed_crss[] = array("crs_id" => $crs_id
921 , "prg_ref_id" => $ref["parent"]
922 , "crsr_ref_id" => $ref["child"]
923 , "crsr_id" => $ref["obj_id"]
924 , "title" => ilContainerReference::_lookupTargetTitle($ref["obj_id"])
925 );
926 }
927 }
928
929 return $completed_crss;
930 }
931
933 // TREE MANIPULATION
935
947 {
948 $this->throwIfNotInTree();
949
950 if ($this->getLPMode() == ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
951 throw new ilStudyProgrammeTreeException("Program already contains leafs.");
952 }
953
954 if ($this->tree->isInTree($a_prg->getRefId())) {
955 throw new ilStudyProgrammeTreeException("Other program already is in tree.");
956 }
957
958 if ($a_prg->getRefId() === null) {
959 $a_prg->createReference();
960 }
961 $a_prg->putInTree($this->getRefId());
962 return $this;
963 }
964
971 public function nodeInserted(ilObjStudyProgramme $a_prg)
972 {
973 if ($this->getLPMode() == ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
974 throw new ilStudyProgrammeTreeException("Program already contains leafs.");
975 }
976
977 if ($this->settings->getLPMode() !== ilStudyProgrammeSettings::MODE_POINTS) {
978 $this->settings_repository->update(
980 );
981 }
982
983 $this->clearChildrenCache();
984 $this->addMissingProgresses();
985 }
986
996 public function putInTree($a_parent_ref)
997 {
998 $res = parent::putInTree($a_parent_ref);
999
1000 if (ilObject::_lookupType($a_parent_ref, true) == "prg") {
1001 $par = ilObjStudyProgramme::getInstanceByRefId($a_parent_ref);
1002 $par->nodeInserted($this);
1003 }
1004
1005 return $res;
1006 }
1007
1018 {
1019 if ($a_prg->getParent()->getId() !== $this->getId()) {
1020 throw new ilStudyProgrammeTreeException("This is no parent of the given programm.");
1021 }
1022
1023 if (!$a_prg->canBeRemoved()) {
1024 throw new ilStudyProgrammeTreeException("The node has relevant assignments.");
1025 }
1026
1027 // *sigh*...
1028 $node_data = $this->tree->getNodeData($a_prg->getRefId());
1029 $this->tree->deleteTree($node_data);
1030 $a_prg->clearParentCache();
1031 $this->clearChildrenCache();
1032
1033 return $this;
1034 }
1035
1040 public function canBeRemoved() : bool
1041 {
1042 foreach ($this->getProgresses() as $progress) {
1043 if ($progress->getStatus() != ilStudyProgrammeProgress::STATUS_NOT_RELEVANT) {
1044 return false;
1045 }
1046 if ($progress->getLastChangeBy() !== null) {
1047 return false;
1048 }
1049 }
1050 return true;
1051 }
1052
1063 {
1064 $this->throwIfNotInTree();
1065
1066 if ($this->hasChildren()) {
1067 throw new ilStudyProgrammeTreeException("Program already contains other programm nodes.");
1068 }
1069
1070 if ($a_leaf->getRefId() === null) {
1071 $a_leaf->createReference();
1072 }
1073 $a_leaf->putInTree($this->getRefId());
1074 $this->clearLPChildrenCache();
1075 $this->settings_repository->update(
1077 );
1078
1079 return $this;
1080 }
1081
1092 {
1093 if (self::getParentId($a_leaf) !== $this->getId()) {
1094 throw new ilStudyProgrammeTreeException("This is no parent of the given leaf node.");
1095 }
1096
1097 $node_data = $this->tree->getNodeData($a_leaf->getRefId());
1098 $this->tree->deleteTree($node_data);
1099 $this->clearLPChildrenCache();
1100
1101 return $this;
1102 }
1103
1113 public function moveTo(ilObjStudyProgramme $a_new_parent) : ilObjStudyProgramme
1114 {
1115 global $DIC;
1116 $rbacadmin = $DIC['rbacadmin'];
1117
1118 if ($parent = $this->getParent()) {
1119
1120 // TODO: check if there some leafs in the new parent
1121
1122 $this->tree->moveTree($this->getRefId(), $a_new_parent->getRefId());
1123 // necessary to clean up permissions
1124 $rbacadmin->adjustMovedObjectPermissions($this->getRefId(), $parent->getRefId());
1125
1126 // TODO: lp-progress needs to be updated
1127
1128 // clear caches on different nodes
1129 $this->clearParentCache();
1130
1131 $parent->clearChildrenCache();
1132 $parent->clearLPChildrenCache();
1133
1134 $a_new_parent->clearChildrenCache();
1135 $a_new_parent->clearLPChildrenCache();
1136 }
1137
1138 return $this;
1139 }
1140
1142 // USER ASSIGNMENTS
1144
1155 public function assignUser(int $a_usr_id, int $a_assigning_usr_id = null) : ilStudyProgrammeUserAssignment
1156 {
1157 $this->members_cache = null;
1158 if ($this->settings === null) {
1159 throw new ilException(
1160 "ilObjStudyProgramme::assignUser: Program was not properly created.'"
1161 );
1162 }
1163
1164 if ($this->getStatus() != ilStudyProgrammeSettings::STATUS_ACTIVE) {
1165 throw new ilException(
1166 "ilObjStudyProgramme::assignUser: Can't assign user to program '"
1167 . $this->getId() . "', since it's not in active status."
1168 );
1169 }
1170
1171 if ($a_assigning_usr_id === null) {
1172 $a_assigning_usr_id = $this->ilUser->getId();
1173 }
1174 $ass_mod = $this->assignment_repository->createFor($this->settings->getObjId(), $a_usr_id, $a_assigning_usr_id);
1175 $ass = $this->assignment_db->getInstanceByModel($ass_mod);
1176 $this->applyToSubTreeNodes(
1177 function (ilObjStudyProgramme $node) use ($ass_mod, $a_assigning_usr_id) {
1178 $progress = $node->createProgressForAssignment($ass_mod);
1180 $this->progress_repository->update(
1181 $progress->setStatus(ilStudyProgrammeProgress::STATUS_NOT_RELEVANT)
1182 );
1183 } else {
1184 $deadline_date = null;
1185 if ($deadline_date = $node->getDeadlineSettings()->getDeadlineDate()) {
1186 $this->progress_repository->update(
1187 $progress->setDeadline($deadline_date)
1188 );
1189 }
1190 if ($deadline_period = $node->getDeadlineSettings()->getDeadlinePeriod()) {
1191 $deadline_date = new DateTime();
1192 $deadline_date->add(new DateInterval('P' . $deadline_period . 'D'));
1193 $this->progress_repository->update(
1194 $progress->setDeadline($deadline_date)
1195 );
1196 }
1197 if ($deadline_date) {
1198 $this->progress_db->getInstanceById($progress->getId())->recalculateFailedToDeadline();
1199 }
1200 }
1201 },
1202 true
1203 );
1204
1205 $this->events->userAssigned($ass);
1206
1207 return $ass;
1208 }
1209
1218 {
1219 $this->members_cache = null;
1220 if ($a_assignment->getStudyProgramme()->getId() != $this->getId()) {
1221 throw new ilException(
1222 "ilObjStudyProgramme::removeAssignment: Assignment '"
1223 . $a_assignment->getId() . "' does not belong to study "
1224 . "program '" . $this->getId() . "'."
1225 );
1226 }
1227
1228 $this->events->userDeassigned($a_assignment);
1229
1230 $a_assignment->delete();
1231
1232 return $this;
1233 }
1234
1238 public function hasAssignmentOf(int $a_user_id) : bool
1239 {
1240 return $this->getAmountOfAssignmentsOf($a_user_id) > 0;
1241 }
1242
1247 public function getAmountOfAssignmentsOf(int $a_user_id) : int
1248 {
1249 return count($this->getAssignmentsOf($a_user_id));
1250 }
1251
1259 public function getAssignmentsOf(int $a_user_id) : array
1260 {
1261 $prg_ids = $this->getIdsFromNodesOnPathFromRootToHere();
1262 $assignments = [];
1263 foreach ($prg_ids as $prg_id) {
1264 $assignments = array_merge(
1265 $assignments,
1266 $this->assignment_repository->readByUsrIdAndPrgId($a_user_id, $prg_id)
1267 );
1268 }
1269 usort($assignments, function ($a_one, $a_other) {
1270 return strcmp(
1271 $a_one->getLastChange()->format('Y-m-d'),
1272 $a_other->getLastChange()->format('Y-m-d')
1273 );
1274 });
1275 $assignment_db = $this->assignment_db;
1276 return array_map(function ($ass) use ($assignment_db) {
1277 return $assignment_db->getInstanceByModel($ass);
1278 }, array_values($assignments)); // use array values since we want keys 0...
1279 }
1280
1286 public function getAssignments() : array
1287 {
1288 $assignment_db = $this->assignment_db;
1289 return array_map(function ($ass) use ($assignment_db) {
1290 return $assignment_db->getInstanceByModel($ass);
1291 }, array_values($this->getAssignmentsRaw())); // use array values since we want keys 0...
1292 }
1293
1297 public function getMembers()
1298 {
1299 if (!$this->members_cache) {
1300 $this->members_cache = array_map(
1301 function ($assignment) {
1302 return $assignment->getUserId();
1303 },
1304 $this->assignment_repository->readByPrgId($this->getId())
1305 );
1306 }
1307 return $this->members_cache;
1308 }
1309
1313 public function hasAssignments() : bool
1314 {
1315 return count($this->getAssignments()) > 0;
1316 }
1317
1322 {
1323 $this->members_cache = null;
1324 $assignments = $this->assignment_db->getInstancesForProgram((int) $this->getId());
1325 foreach ($assignments as $ass) {
1326 $ass->updateFromProgram();
1327 }
1328 return $this;
1329 }
1330
1336 public function getAssignmentsOfSingleProgramForUser(int $usr_id) : array
1337 {
1338 return $this->assignment_repository->readByUsrIdAndPrgId($usr_id, $this->getId());
1339 }
1340
1344 public function hasAssignmentsOfSingleProgramForUser(int $usr_id) : bool
1345 {
1346 return count($this->getAssignmentsOfSingleProgramForUser($usr_id)) > 0;
1347 }
1348
1349
1351 // USER PROGRESS
1353
1358 {
1359 return $this->progress_repository->createFor($this->settings, $ass);
1360 }
1361
1368 public function getProgressesOf(int $a_user_id) : array
1369 {
1370 return $this->progress_db->getInstancesForUser($this->getId(), $a_user_id);
1371 }
1372
1382 public function getProgressForAssignment(int $a_assignment_id) : ilStudyProgrammeUserProgress
1383 {
1384 return $this->progress_db->getInstanceForAssignment($this->getId(), $a_assignment_id);
1385 }
1386
1392 public function addMissingProgresses() : void
1393 {
1394 $progress_repository = $this->progress_repository;
1395 $log = $this->getLog();
1396
1397 foreach ($this->getAssignments() as $ass) {
1398 $id = $ass->getId();
1399 $assignment = $ass->getSPAssignment();
1400
1401 $mapping = function (ilObjStudyProgramme $node) use ($id, $log, $progress_repository, $assignment) {
1402 try {
1403 $node->getProgressForAssignment($id);
1405 $log->debug("Adding progress for: " . $id . " " . $node->getId());
1406 $progress_repository->update(
1407 $progress_repository->createFor(
1408 $node->getRawSettings(),
1409 $assignment
1410 )->setStatus(
1412 )
1413 );
1414 }
1415 };
1416
1417 $this->applyToSubTreeNodes($mapping, true);
1418 }
1419 }
1420
1426 public function getProgresses() : array
1427 {
1428 return $this->progress_db->getInstancesForProgram($this->getId());
1429 }
1430
1434 public function hasProgresses() : bool
1435 {
1436 return count($this->getProgresses()) > 0;
1437 }
1438
1442 public function hasRelevantProgresses() : bool
1443 {
1444 foreach ($this->getProgresses() as $progress) {
1445 if ($progress->isRelevant()) {
1446 return true;
1447 }
1448 }
1449 return false;
1450 }
1451
1457 public function getIdsOfUsersWithRelevantProgress() : array
1458 {
1459 $returns = array();
1460 foreach ($this->getProgresses() as $progress) {
1461 if ($progress->isRelevant()) {
1462 $returns[] = $progress->getUserId();
1463 }
1464 }
1465 return array_unique($returns);
1466 }
1467
1473 public function getIdsOfUsersWithCompletedProgress() : array
1474 {
1475 $returns = array();
1476 foreach ($this->getProgresses() as $progress) {
1477 $progress->recalculateFailedToDeadline();
1478 if ($progress->isSuccessful() && !$progress->isSuccessfulExpired()) {
1479 $returns[] = $progress->getUserId();
1480 }
1481 }
1482 return array_unique($returns);
1483 }
1484
1490 public function getIdsOfUsersWithFailedProgress() : array
1491 {
1492 $returns = array();
1493 foreach ($this->getProgresses() as $progress) {
1494 $progress->recalculateFailedToDeadline();
1495 if ($progress->isFailed() || $progress->isSuccessfulExpired()) {
1496 $returns[] = $progress->getUserId();
1497 }
1498 }
1499 return array_unique(array_diff($returns, $this->getIdsOfUsersWithCompletedProgress()));
1500 }
1501
1502
1510 {
1511 $returns = array();
1512 foreach ($this->getProgresses() as $progress) {
1513 if ($progress->isRelevant() && !$progress->isSuccessful()) {
1514 $returns[] = $progress->getUserId();
1515 }
1516 }
1517 return array_unique($returns);
1518 }
1519
1520
1522 // AUTOMATIC CONTENT CATEGORIES
1524
1529 public function getAutomaticContentCategories() : array
1530 {
1531 return $this->auto_categories_repository->readFor($this->getId());
1532 }
1533
1534 public function hasAutomaticContentCategories() : bool
1535 {
1536 return count($this->getAutomaticContentCategories()) > 0;
1537 }
1538
1539
1544 public function storeAutomaticContentCategory(int $category_ref_id) : void
1545 {
1546 $ac = $this->auto_categories_repository->create(
1547 $this->getId(),
1548 $category_ref_id
1549 );
1550 $this->auto_categories_repository->update($ac);
1551 }
1552
1557 public function deleteAutomaticContentCategories(array $category_ids = []) : void
1558 {
1559 $this->auto_categories_repository->delete($this->getId(), $category_ids);
1560 }
1561
1566 {
1567 $this->auto_categories_repository->deleteFor($this->getId());
1568 }
1569
1573 public static function addCrsToProgrammes(int $crs_ref_id, int $cat_ref_id) : void
1574 {
1575 foreach (self::getProgrammesMonitoringCategory($cat_ref_id) as $prg) {
1576 $course_ref = new ilObjCourseReference();
1577 $course_ref->setTitleType(ilObjCourseReference::TITLE_TYPE_REUSE);
1578 $course_ref->setTargetRefId($crs_ref_id);
1579 $course_ref->create();
1580 $course_ref->createReference();
1581 $course_ref->putInTree($prg->getRefId());
1582 $course_ref->setPermissions($crs_ref_id);
1583 $course_ref->setTargetId(ilObject::_lookupObjectId($crs_ref_id));
1584 $course_ref->update();
1585 }
1586 }
1587
1593 public static function removeCrsFromProgrammes(int $crs_ref_id, int $cat_ref_id)
1594 {
1595 foreach (self::getProgrammesMonitoringCategory($cat_ref_id) as $prg) {
1596 foreach ($prg->getLPChildren() as $child) {
1597 if ((int) $child->getTargetRefId() === $crs_ref_id) {
1598 $child->delete();
1599 }
1600 }
1601 }
1602 }
1603
1608 protected static function getProgrammesMonitoringCategory(int $cat_ref_id) : array
1609 {
1610 $db = ilStudyProgrammeDIC::dic()['model.AutoCategories.ilStudyProgrammeAutoCategoriesRepository'];
1611 $programmes = array_map(
1612 function ($rec) {
1613 $prg_obj_id = (int) array_shift(array_values($rec));
1614 $prg_ref_id = (int) array_shift(ilObject::_getAllReferences($prg_obj_id));
1615 $prg = self::getInstanceByRefId($prg_ref_id);
1616 if ($prg->isAutoContentApplicable()) {
1617 return $prg;
1618 }
1619 },
1620 $db::getProgrammesFor($cat_ref_id)
1621 );
1622 return $programmes;
1623 }
1624
1631 public function isAutoContentApplicable() : bool
1632 {
1633 $valid_status = in_array(
1634 $this->settings->getAssessmentSettings()->getStatus(),
1635 [
1638 ]
1639 );
1640
1641 $crslnk_allowed = (
1642 $this->hasLPChildren()
1643 || $this->getAmountOfChildren(true) === 0
1644 );
1645
1646 return $valid_status && $crslnk_allowed;
1647 }
1648
1649
1651 // AUTOMATIC MEMBERSHIPS
1653
1658 public function getAutomaticMembershipSources() : array
1659 {
1660 return $this->auto_memberships_repository->readFor($this->getId());
1661 }
1662
1666 public function storeAutomaticMembershipSource(string $type, int $src_id) : void
1667 {
1668 $ams = $this->auto_memberships_repository->create($this->getId(), $type, $src_id, false);
1669 $this->auto_memberships_repository->update($ams);
1670 }
1671
1675 public function deleteAutomaticMembershipSource(string $type, int $src_id) : void
1676 {
1677 $this->auto_memberships_repository->delete($this->getId(), $type, $src_id);
1678 }
1679
1684 {
1685 $this->auto_memberships_repository->deleteFor($this->getId());
1686 }
1687
1691 public function disableAutomaticMembershipSource(string $type, int $src_id) : void
1692 {
1693 $ams = $this->auto_memberships_repository->create($this->getId(), $type, $src_id, false);
1694 $this->auto_memberships_repository->update($ams);
1695 }
1696
1701 public function enableAutomaticMembershipSource(string $type, int $src_id) : void
1702 {
1704 $member_ids = $this->getMembersOfMembershipSource($type, $src_id);
1705
1706 foreach ($member_ids as $usr_id) {
1707 if (!$this->getAssignmentsOfSingleProgramForUser($usr_id)) {
1708 $this->assignUser($usr_id, $assigned_by);
1709 }
1710 }
1711 $ams = $this->auto_memberships_repository->create($this->getId(), $type, $src_id, true);
1712 $this->auto_memberships_repository->update($ams);
1713 }
1714
1720 protected function getMembersOfMembershipSource(string $src_type, int $src_id) : array
1721 {
1722 $source_reader = $this->membersourcereader_factory->getReaderFor($src_type, $src_id);
1723 return $source_reader->getMemberIds();
1724 }
1725
1726
1731 protected static function getProgrammesMonitoringMemberSource(string $src_type, int $src_id) : array
1732 {
1733 $db = ilStudyProgrammeDIC::dic()['model.AutoMemberships.ilStudyProgrammeAutoMembershipsRepository'];
1734 $programmes = array_map(
1735 function ($rec) {
1736 $prg_obj_id = (int) array_shift(array_values($rec));
1737 $prg_ref_id = (int) array_shift(ilObject::_getAllReferences($prg_obj_id));
1738 $prg = self::getInstanceByRefId($prg_ref_id);
1739 return $prg;
1740 },
1741 $db::getProgrammesFor($src_type, $src_id)
1742 );
1743 return $programmes;
1744 }
1745
1746 public static function addMemberToProgrammes(string $src_type, int $src_id, int $usr_id) : void
1747 {
1748 foreach (self::getProgrammesMonitoringMemberSource($src_type, $src_id) as $prg) {
1749 if (!$prg->hasAssignmentsOfSingleProgramForUser($usr_id)) {
1751 $prg->assignUser($usr_id, $assigned_by);
1752 }
1753 }
1754 }
1755
1756 public static function removeMemberFromProgrammes(string $src_type, int $src_id, int $usr_id) : void
1757 {
1758 foreach (self::getProgrammesMonitoringMemberSource($src_type, $src_id) as $prg) {
1759 foreach ($prg->getProgressesOf($usr_id) as $progress) {
1760 if ($progress->getStatus() !== ilStudyProgrammeProgress::STATUS_IN_PROGRESS) {
1761 continue;
1762 }
1763 $assignments = $prg->getAssignmentsOfSingleProgramForUser($usr_id);
1764 $next_membership_source = $prg->getApplicableMembershipSourceForUser($usr_id, $src_type);
1765
1766 foreach ($assignments as $assignment) {
1767 if (!is_null($next_membership_source)) {
1768 $new_src_type = $next_membership_source->getSourceType();
1769 $assigned_by = ilStudyProgrammeAutoMembershipSource::SOURCE_MAPPING[$new_src_type];
1770 $assignment = $assignment->setLastChangeBy($assigned_by);
1771 $prg->assignment_repository->update($assignment);
1772 break;
1773 } else {
1774 $assignment_db = ilStudyProgrammeDIC::dic()['ilStudyProgrammeUserAssignmentDB'];
1775 $user_assignment = $assignment_db->getInstanceByModel($assignment);
1776 $prg->removeAssignment($user_assignment);
1777 }
1778 }
1779 }
1780 }
1781 }
1782
1786 public function getApplicableMembershipSourceForUser(int $usr_id, string $exclude_type)
1787 {
1788 foreach ($this->getAutomaticMembershipSources() as $ams) {
1789 $src_type = $ams->getSourceType();
1790 if ($src_type !== $exclude_type) {
1791 $source_members = $this->getMembersOfMembershipSource($src_type, $ams->getSourceId());
1792 if (in_array($usr_id, $source_members)) {
1793 return $ams;
1794 }
1795 }
1796 }
1797 return null;
1798 }
1799
1801 // HELPERS
1803
1807 protected function updateLastChange() : void
1808 {
1809 $this->settings->updateLastChange();
1810 if ($parent = $this->getParent()) {
1811 $parent->updateLastChange();
1812 }
1813 $this->update();
1814 }
1815
1822 protected function getIdsFromNodesOnPathFromRootToHere(bool $include_references = false) : array
1823 {
1824 $prg_ids = array_map(function ($par) {
1825 return $par->getId();
1826 }, $this->getParents($include_references));
1827 $prg_ids[] = $this->getId();
1828 return $prg_ids;
1829 }
1830
1836 protected function getAssignmentsRaw() : array
1837 {
1838 $assignments = [];
1839 foreach ($this->getIdsFromNodesOnPathFromRootToHere(true) as $prg_id) {
1840 $assignments = array_merge($this->assignment_repository->readByPrgId($prg_id), $assignments);
1841 }
1842 usort(
1843 $assignments,
1844 function (ilStudyProgrammeAssignment $a_one, ilStudyProgrammeAssignment $a_other) {
1845 return -strcmp(
1846 $a_one->getLastChange()->format('Y-m-d'),
1847 $a_other->getLastChange()->format('Y-m-d')
1848 );
1849 }
1850 );
1851 return $assignments;
1852 }
1853
1858 public static function setProgressesCompletedFor(int $a_obj_id, int $a_user_id) : void
1859 {
1860 // We only use courses via crs_refs
1861 $type = ilObject::_lookupType($a_obj_id);
1862 if ($type == "crs") {
1863 require_once("Services/ContainerReference/classes/class.ilContainerReference.php");
1864 $crs_reference_obj_ids = ilContainerReference::_lookupSourceIds($a_obj_id);
1865 foreach ($crs_reference_obj_ids as $obj_id) {
1866 foreach (ilObject::_getAllReferences($obj_id) as $ref_id) {
1867 self::setProgressesCompletedIfParentIsProgrammeInLPCompletedMode((int) $ref_id, (int) $obj_id, $a_user_id);
1868 }
1869 }
1870 } else {
1871 foreach (ilObject::_getAllReferences($a_obj_id) as $ref_id) {
1872 self::setProgressesCompletedIfParentIsProgrammeInLPCompletedMode((int) $ref_id, $a_obj_id, $a_user_id);
1873 }
1874 }
1875 }
1876
1881 int $a_ref_id,
1882 int $a_obj_id,
1883 int $a_user_id
1884 ) : void {
1885 global $DIC; // TODO: replace this by a settable static for testing purpose?
1886 $tree = $DIC['tree'];
1887 $node_data = $tree->getParentNodeData($a_ref_id);
1888 if ($node_data["type"] !== "prg") {
1889 return;
1890 }
1891 self::initStudyProgrammeCache();
1892 $prg = ilObjStudyProgramme::getInstanceByRefId($node_data["child"]);
1893 if ($prg->getLPMode() != ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
1894 return;
1895 }
1896 foreach ($prg->getProgressesOf($a_user_id) as $progress) {
1897 $progress->setLPCompleted($a_obj_id, $a_user_id);
1898 }
1899 }
1900
1907 protected static function getParentId(ilObject $a_object)
1908 {
1909 global $DIC;
1910 $tree = $DIC['tree'];
1911 if (!$tree->isInTree($a_object->getRefId())) {
1912 return null;
1913 }
1914
1915 $nd = $tree->getParentNodeData($a_object->getRefId());
1916 return $nd["obj_id"];
1917 }
1918
1926 public function getRawSettings()
1927 {
1928 return $this->settings;
1929 }
1930
1935 public function updateCustomIcon() : void
1936 {
1937 global $DIC;
1938
1940 $customIconFactory = $DIC['object.customicons.factory'];
1941 $customIcon = $customIconFactory->getByObjId($this->getId(), $this->getType());
1942
1943 $subtype = $this->getSubType();
1944
1945 if ($subtype) {
1946 if ($this->webdir->has($subtype->getIconPath(true))) {
1947 $icon = $subtype->getIconPath(true);
1948 $customIcon->saveFromSourceFile($icon);
1949 } else {
1950 $customIcon->remove();
1951 }
1952 } else {
1953 $customIcon->remove();
1954 }
1955 }
1956
1958 // HOOKS
1960
1971 public static function getCreatableSubObjects(array $a_subobjects, $a_ref_id) : array
1972 {
1973 if ($a_ref_id === null) {
1974 return $a_subobjects;
1975 }
1976
1977 if (ilObject::_lookupType($a_ref_id, true) != "prg") {
1978 throw new ilException("Ref-Id '$a_ref_id' does not belong to a study programme object.");
1979 }
1980
1981 $parent = ilObjStudyProgramme::getInstanceByRefId($a_ref_id);
1982
1983 $mode = $parent->getLPMode();
1984
1985 switch ($mode) {
1987 $possible_subobjects = $a_subobjects;
1988 break;
1990 $possible_subobjects = [
1991 "prg" => $a_subobjects["prg"],
1992 "prgr" => $a_subobjects["prgr"]
1993 ];
1994 break;
1996 $possible_subobjects = ['crsr' => $a_subobjects['crsr']];
1997 break;
1998 default:
1999 throw new ilException("Undefined mode for study programme: '$mode'");
2000 }
2001
2002 if ($parent->hasAutomaticContentCategories()) {
2003 $possible_subobjects = array_filter(
2004 $possible_subobjects,
2005 function ($subtype) {
2006 return $subtype === 'crsr';
2007 },
2008 ARRAY_FILTER_USE_KEY
2009
2010 );
2011 }
2012 return $possible_subobjects;
2013 }
2014
2015 public static function sendReAssignedMail(int $ref_id, int $usr_id) : bool
2016 {
2017 global $DIC;
2018 $lng = $DIC['lng'];
2019 $log = $DIC->logger()->root();
2020 $lng->loadLanguageModule("prg");
2021 $lng->loadLanguageModule("mail");
2022
2025
2026 if (!$prg->shouldSendReAssignedMail()) {
2027 $log->write("Send re assign mail is deactivated in study programme settings");
2028 return false;
2029 }
2030
2031 $subject = $lng->txt("re_assigned_mail_subject");
2032 $gender = ilObjUser::_lookupGender($usr_id);
2034 $body = sprintf(
2035 $lng->txt("re_assigned_mail_body"),
2036 $lng->txt("mail_salutation_" . $gender),
2037 $name,
2038 $prg->getTitle()
2039 );
2040
2041 $send = true;
2042 $mail = new ilMail(ANONYMOUS_USER_ID);
2043 try {
2044 $mail->enqueue(
2045 ilObjUser::_lookupLogin($usr_id),
2046 '',
2047 '',
2048 $subject,
2049 $body,
2050 null
2051 );
2052 } catch (Exception $e) {
2053 $send = false;
2054 }
2055
2056 return $send;
2057 }
2058
2059 public static function sendInvalidateMail(int $ref_id, int $usr_id) : bool
2060 {
2061 global $DIC;
2062 $lng = $DIC['lng'];
2063 $lng->loadLanguageModule("prg");
2064 $lng->loadLanguageModule("mail");
2065
2067
2068 $subject = $lng->txt("invalidate_mail_subject");
2069 $gender = ilObjUser::_lookupGender($usr_id);
2071 $body = sprintf(
2072 $lng->txt("invalidate_mail_body"),
2073 $lng->txt("mail_salutation_" . $gender),
2074 $name,
2075 $prg->getTitle()
2076 );
2077
2078 $send = true;
2079 $mail = new ilMail(ANONYMOUS_USER_ID);
2080 try {
2081 $mail->enqueue(
2082 ilObjUser::_lookupLogin($usr_id),
2083 '',
2084 '',
2085 $subject,
2086 $body,
2087 null
2088 );
2089 } catch (Exception $e) {
2090 $send = false;
2091 }
2092
2093 return $send;
2094 }
2095
2096
2097 protected function getLog()
2098 {
2099 return ilLoggerFactory::getLogger($this->type);
2100 }
2101}
An exception for terminatinating execution or to throw for unit testing.
static saveObjRecSelection($a_obj_id, $a_sub_type="", array $a_records=null, $a_delete_before=true)
Save repository object record selection.
static _lookupTargetId($a_obj_id)
lookup target id
static _lookupTargetTitle($a_obj_id)
Lookup target title.
static _lookupSourceIds($a_target_id)
Get ids of all container references that target the object with the given id.
static _getInstance($a_obj_id)
get instance by obj_id
Class ilContainer.
Base class for ILIAS Exception handling.
static _hasUserCompleted($a_obj_id, $a_user_id)
Lookup user object completion.
static getLogger($a_component_id)
Get component logger.
static setProgressesCompletedIfParentIsProgrammeInLPCompletedMode(int $a_ref_id, int $a_obj_id, int $a_user_id)
getLPChildren()
Get the leafs the study programme contains.
getAssignmentsOf(int $a_user_id)
Get the assignments of user at this program or any node above.
hasLPChildren()
Does this StudyProgramme has leafs?
getRoot()
Get the ilObjStudyProgramme that is the root node of the tree this programme is in.
addLeaf(ilStudyProgrammeLeaf $a_leaf)
Insert a leaf in this object.
getAmountOfAssignmentsOf(int $a_user_id)
Get the amount of assignments a user has on this program node or any node above.
getAssignmentsRaw()
Get model objects for the assignments on this programm.
setPoints(int $a_points)
Set the amount of points.
setValidityOfQualificationSettings(\ilStudyProgrammeValidityOfAchievedQualificationSettings $validity_of_qualification_settings)
getAmountOfChildren($include_references=false)
Get the amount of other StudyProgrammes this StudyProgramme has as children.
static sendInvalidateMail(int $ref_id, int $usr_id)
getApplicableMembershipSourceForUser(int $usr_id, string $exclude_type)
static removeCrsFromProgrammes(int $crs_ref_id, int $cat_ref_id)
Check, if a category is under surveilllance and automatically remove the deleted course.
removeLeaf(ilStudyProgrammeLeaf $a_leaf)
Remove a leaf from this object.
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;.
setAssessmentSettings(\ilStudyProgrammeAssessmentSettings $assessment_settings)
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.
enableAutomaticMembershipSource(string $type, int $src_id)
Enable a membership source.
getIdsOfUsersWithNotCompletedAndRelevantProgress()
Get the ids of all users that have not completed this programme but have a relevant progress on it.
isAutoContentApplicable()
AutoContent should only be available in active- or draft-mode, and only, if there is no sub-programme...
static getProgrammesMonitoringMemberSource(string $src_type, int $src_id)
Get all StudyProgrammes monitoring this membership-source.
storeAutomaticMembershipSource(string $type, int $src_id)
Store a source to be monitored for automatic memberships.
deleteAssignments()
Delete all assignments from the DB.
deleteAllAutomaticContentCategories()
Delete all configuration of categories with auto-content for this StudyProgramme;.
getReferencesTo(ilObjStudyProgramme $prg)
getCompletedCourses(int $a_user_id)
Get courses in this program that the given user already completed.
setAutoMailSettings(\ilStudyProgrammeAutoMailSettings $automail_settings)
readSettings()
Load Settings from DB.
createProgressForAssignment(ilStudyProgrammeAssignment $ass)
Create a progress on this programme for the given assignment.
static getProgrammesMonitoringCategory(int $cat_ref_id)
Get all StudyProgrammes monitoring this category.
static getInstanceByRefId($a_ref_id)
deleteAllAutomaticMembershipSources()
Delete all membership sources of this StudyProgramme;.
getIdsFromNodesOnPathFromRootToHere(bool $include_references=false)
Get the ids from the nodes in the path leading from the root node of this program to this node,...
getPoints()
Get the amount of points.
static getCreatableSubObjects(array $a_subobjects, $a_ref_id)
Filter the list of possible subobjects for the objects that actually could be created on a concrete n...
storeAutomaticContentCategory(int $category_ref_id)
Store a Category with auto-content for this StudyProgramme; a category can only be referenced once (p...
moveTo(ilObjStudyProgramme $a_new_parent)
Move this tree node to a new parent.
getProgressesOf(int $a_user_id)
Get the progresses the user has on this node.
getProgressForAssignment(int $a_assignment_id)
Get the progress for an assignment on this node.
createSettings()
Create new settings object.
getAssignments()
Get all assignments to this program or any node above.
clearLPChildrenCache()
Clear the cached lp children.
static getParentId(ilObject $a_object)
Get the obj id of the parent object for the given object.
setTypeSettings(\ilStudyProgrammeTypeSettings $type_settings)
getMembersOfMembershipSource(string $src_type, int $src_id)
Get member-ids of a certain source.
disableAutomaticMembershipSource(string $type, int $src_id)
Disable a membership source.
getRawSettings()
Get the underlying model of this program.
clearParentCache()
Clear the cached parent to query it again at the tree.
addMissingProgresses()
Add missing progress records for all assignments of this programm.
getChildren(bool $include_references=false)
Get all ilObjStudyProgrammes that are direct children of this object.
getProgresses()
Get all progresses on this node.
assignUser(int $a_usr_id, int $a_assigning_usr_id=null)
Assign a user to this node at the study program.
updateAllAssignments()
Update all assignments to this program node.
static addMemberToProgrammes(string $src_type, int $src_id, int $usr_id)
nodeInserted(ilObjStudyProgramme $a_prg)
Clears child chache and adds progress for new node.
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.
setDeadlineSettings(\ilStudyProgrammeDeadlineSettings $deadline_settings)
getLastChange()
Get the timestamp of the last change on this program or sub program.
throwIfNotInTree()
Helper function to check, weather object is in tree.
clearChildrenCache()
Clear the cached children.
__construct($a_id=0, bool $a_call_by_reference=true)
ATTENTION: After using the constructor the object won't be in the cache.
hasProgresses()
Are there any users that have a progress on this programme?
getIdsOfUsersWithRelevantProgress()
Get the ids of all users that have a relevant progress at this programme.
hasChildren(bool $include_references=false)
Does this StudyProgramme have other ilObjStudyProgrammes as children?
setStatus(int $a_status)
Set the status of the node.
getAssignmentsOfSingleProgramForUser(int $usr_id)
Get assignments of user to this program-node only.
getAutomaticMembershipSources()
Get sources for auto-memberships.
getIdsOfUsersWithFailedProgress()
Get the ids of all users that have failed this programme.
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.
getSubType()
Gets the SubType Object.
removeNode(ilObjStudyProgramme $a_prg)
Remove a node from this object.
hasAssignmentOf(int $a_user_id)
Check whether user is assigned to this program or any node above.
deleteAutomaticMembershipSource(string $type, int $src_id)
Delete a membership source.
removeAssignment(ilStudyProgrammeUserAssignment $a_assignment)
Remove an assignment from this program.
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 ids of the leafs the program contains.
deleteSettings()
Delete settings from DB.
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)
putInTree($a_parent_ref)
Overwritten from ilObject.
adjustLPMode()
Adjust the lp mode to match current state of tree:
static setProgressesCompletedFor(int $a_obj_id, int $a_user_id)
Set all progresses to completed where the object with given id is a leaf and that belong to the user.
addNode(ilObjStudyProgramme $a_prg)
Inserts another ilObjStudyProgramme in this object.
getIdsOfUsersWithCompletedProgress()
Get the ids of all users that have completed this programme.
updateSettings()
Update settings in DB.
getParents(bool $include_references=false)
Get all parents of the node, where the root of the program comes first.
static _lookupLogin($a_user_id)
lookup login
static _lookupGender($a_user_id)
Lookup gender.
static _lookupFullname($a_user_id)
Lookup Full Name.
Class ilObject Basic functions for all objects.
createReference()
creates reference for object
static _lookupObjectId($a_ref_id)
lookup object id
getRefId()
get reference id @access public
static _getAllReferences($a_id)
get all reference ids of object
getId()
get object id @access public
static _lookupType($a_id, $a_reference=false)
lookup object type
Class ilStudyProgrammeAssignment.
getLastChange()
Get the timestamp of the last change on this program or a sub program.
Exception is thrown when a progress for some programme node and assignment is missing.
Class ilStudyProgrammeProgress.
Exception is thrown when invariants on the program tree would be violated by manipulation of tree.
Represents one assignment of a user to a study programme.
getStudyProgramme()
Get the program node where this assignment was made.
delete()
Delete the assignment from database.
Represents the progress of a user at one node of a study programme.
if(!file_exists(getcwd() . '/ilias.ini.php'))
registration confirmation script for ilias
Definition: confirmReg.php:12
$nd
Definition: error.php:12
The interface a class has to fullfill if it should be used as leaf in a program.
getRefId()
Get the ILIAS reference id of the leaf.
putInTree($a_ref_id)
Put the leaf object in the repository tree under object identified by $a_ref_id.
createReference()
Create a reference id for this object.
if($format !==null) $name
Definition: metadata.php:230
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
$ret
Definition: parser.php:6
$type
$log
Definition: result.php:15
$lng
foreach($_POST as $key=> $value) $res
settings()
Definition: settings.php:2
$data
Definition: storeScorm.php:23
$DIC
Definition: xapitoken.php:46