ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjStudyProgramme.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
24 {
25  public const CP_TYPE = 'cont';
26 
28 
32  protected $parent;
33 
37  protected ?array $children = null;
38 
42  protected ?array $lp_children = null;
43 
51 
52  // GLOBALS from ILIAS
53 
57  protected ?array $members_cache = null;
58 
62  protected ?array $reference_children = null;
63 
64  protected Filesystem $webdir;
65  protected ilObjUser $ilUser;
68  protected ilLogger $logger;
69 
74  public function __construct(int $id = 0, bool $call_by_reference = true)
75  {
77  $this->type = "prg";
78 
79  $this->type_repository = $dic['model.Type.ilStudyProgrammeTypeRepository'];
80  $this->auto_categories_repository = $dic['model.AutoCategories.ilStudyProgrammeAutoCategoriesRepository'];
81  $this->auto_memberships_repository = $dic['model.AutoMemberships.ilStudyProgrammeAutoMembershipsRepository'];
82  $this->membersourcereader_factory = $dic['model.AutoMemberships.ilStudyProgrammeMembershipSourceReaderFactory'];
83 
84  $this->settings_repository = $dic['model.Settings.ilStudyProgrammeSettingsRepository'];
85  $this->assignment_repository = $dic['repo.assignment'];
86  $this->events = $dic['ilStudyProgrammeEvents'];
87 
89 
90  $this->clearParentCache();
91  $this->clearChildrenCache();
92  $this->clearLPChildrenCache();
93 
94  global $DIC;
95  $tree = $DIC['tree'];
96  $ilUser = $DIC['ilUser'];
97  $this->webdir = $DIC->filesystem()->web();
98  $this->tree = $tree;
99  $this->ilUser = $ilUser;
100  $this->db = $DIC['ilDB'];
101  $this->lng = $DIC['lng'];
102  $this->logger = ilLoggerFactory::getLogger($this->type);
103 
104  $this->object_factory = ilObjectFactoryWrapper::singleton();
105 
106  $this->custom_icon_factory = $DIC['object.customicons.factory'];
107 
108  self::initStudyProgrammeCache();
109  }
110 
111  public static function initStudyProgrammeCache(): void
112  {
113  if (self::$study_programme_cache === null) {
114  self::$study_programme_cache = ilObjStudyProgrammeCache::singleton();
115  }
116  }
117 
121  protected function clearParentCache(): void
122  {
123  // This is not initialized, but we need null if there is no parent.
124  $this->parent = false;
125  }
126 
130  protected function clearChildrenCache(): void
131  {
132  $this->children = null;
133  }
134 
138  protected function clearLPChildrenCache(): void
139  {
140  $this->lp_children = null;
141  }
142 
143  public static function getRefIdFor(int $obj_id): int
144  {
145  $refs = ilObject::_getAllReferences($obj_id);
146  if (count($refs) < 1) {
147  throw new ilException("Could not find ref_id for programme with obj_id $obj_id");
148  }
149  return (int) array_shift($refs);
150  }
151 
152  protected function getPrgInstanceByObjId(int $obj_id): ilObjStudyProgramme
153  {
154  return self::getInstanceByRefId(self::getRefIdFor($obj_id));
155  }
156 
157  public static function getInstanceByObjId(int $obj_id): ilObjStudyProgramme
158  {
159  return self::getInstanceByRefId(self::getRefIdFor($obj_id));
160  }
161 
163  {
164  if (self::$study_programme_cache === null) {
165  self::initStudyProgrammeCache();
166  }
167  return self::$study_programme_cache->getInstanceByRefId((int) $ref_id);
168  }
169 
171  {
173  }
175  {
177  }
178  protected function getTree(): ilTree
179  {
180  return $this->tree;
181  }
182  protected function getLogger(): ilLogger
183  {
184  return $this->logger;
185  }
186 
192  public static function createInstance(): ilObjStudyProgramme
193  {
194  $obj = new ilObjStudyProgramme();
195  $obj->create();
196  $obj->createReference();
197  self::$study_programme_cache->addInstance($obj);
198  return $obj;
199  }
200 
202  // CRUD
204 
206  {
207  return $this->getSettingsRepository()->get($this->getId());
208  }
209 
211  {
212  if ($settings->getObjId() !== $this->getId()) {
213  throw new Exception("The given settings-object does not belong to this programme", 1);
214  }
215  $this->getSettingsRepository()->update($settings);
216 
217  return true;
218  }
219 
220  protected function deleteSettings(): void
221  {
222  $this->getSettingsRepository()->delete($this->getSettings());
223  }
224 
230  protected function deleteAssignmentsAndProgresses(): void
231  {
232  $this->assignment_repository->deleteAllAssignmentsForProgrammeId($this->getId());
233  }
234 
238  public function create(): int
239  {
240  $id = (int) parent::create();
241  $this->getSettingsRepository()->createFor($id);
242  return $id;
243  }
244 
248  public function update(): bool
249  {
250  parent::update();
251 
252  $type_settings = $this->getSettings()->getTypeSettings();
253  // Update selection for advanced metadata of the type
254  if ($type_settings->getTypeId()) {
256  $this->getId(),
257  'prg_type',
258  $this->type_repository->getAssignedAMDRecordIdsByType($type_settings->getTypeId())
259  );
260  } else {
261  // If no type is assigned, delete relations by passing an empty array
262  ilAdvancedMDRecord::saveObjRecSelection($this->getId(), 'prg_type', array());
263  }
264  return true;
265  }
266 
272  public function delete(): bool
273  {
274  // always call parent delete function first!!
275  if (!parent::delete()) {
276  return false;
277  }
278 
279  $this->deleteSettings();
281  try {
282  $this->auto_categories_repository->deleteFor($this->getId());
284  // This would be the case when SP is in trash (#17797)
285  }
286 
289 
290  $this->events->raise('delete', ['object' => $this, 'obj_id' => $this->getId()]);
291  return true;
292  }
293 
294  public function hasAdvancedMetadata(): bool
295  {
296  $sub_type_id = $this->getSettings()->getTypeSettings()->getTypeId();
297  $type = null;
298  if ($sub_type_id) {
299  $type = $this->type_repository->getType($sub_type_id);
300  }
301 
302  return !is_null($type) && count($this->type_repository->getAssignedAMDRecordIdsByType($type->getId(), true)) > 0;
303  }
304 
305  public function cloneObject(int $target_ref_id, int $copy_id = 0, bool $omit_tree = false): ?ilObject
306  {
307  $new_obj = parent::cloneObject($target_ref_id, $copy_id, $omit_tree);
308  $settings = $this->getSettings()->withObjId($new_obj->getId());
309  $settings = $settings->withAssessmentSettings(
310  $settings->getAssessmentSettings()->withStatus(ilStudyProgrammeSettings::STATUS_DRAFT)
311  );
312  $new_obj->updateSettings($settings);
313  return $new_obj;
314  }
315 
317  // GETTERS AND SETTERS
319 
323  public function getLastChange(): DateTime
324  {
325  return $this->getSettings()->getLastChange();
326  }
327 
331  public function getPoints(): int
332  {
333  return $this->getSettings()->getAssessmentSettings()->getPoints();
334  }
335 
341  public function setPoints(int $points): ilObjStudyProgramme
342  {
343  $settings = $this->getSettings();
344  $this->updateSettings(
345  $settings->withAssessmentSettings($settings->getAssessmentSettings()->withPoints($points))
346  );
347  $this->updateLastChange();
348  return $this;
349  }
350 
351  public function getLPMode(): int
352  {
353  return $this->getSettings()->getLPMode();
354  }
355 
364  public function adjustLPMode(): void
365  {
366  // Clear caches here, there have been some changes, because this method
367  // would not have been called otherwise, and the changer just does not
368  // know if we have filled the caches already...
369  $this->clearLPChildrenCache();
370  $this->clearChildrenCache();
371 
372  if ($this->tree->isInTree($this->getRefId())) {
373  if ($this->getAmountOfLPChildren() > 0) {
374  $this->settings_repository->update(
376  );
377  } elseif ($this->getAmountOfChildren(true) > 0) {
378  $this->settings_repository->update(
380  );
381  } else {
382  $this->settings_repository->update(
384  );
385  }
386  }
387  }
388 
389  public function getStatus(): int
390  {
391  return $this->getSettings()->getAssessmentSettings()->getStatus();
392  }
393 
399  public function setStatus(int $a_status): ilObjStudyProgramme
400  {
401  $settings = $this->getSettings();
402  $this->updateSettings(
403  $settings->withAssessmentSettings($settings->getAssessmentSettings()->withStatus($a_status))
404  );
405  $this->updateLastChange();
406  return $this;
407  }
408 
409  public function isActive(): bool
410  {
412  }
413 
417  public function getSubType(): ?ilStudyProgrammeType
418  {
419  $type_settings = $this->getSettings()->getTypeSettings();
420  if (!in_array($type_settings->getTypeId(), array("-", "0"))) {
421  $subtype_id = $type_settings->getTypeId();
422  return $this->type_repository->getType($subtype_id);
423  }
424 
425  return null;
426  }
427 
428  public function isCertificateActive(): bool
429  {
430  $global_settings = new ilSetting('certificate');
431  $global_active = (bool) $global_settings->get('active', '0');
432  if (!$global_active) {
433  return false;
434  }
436  $certificate_template = $certificate_template_repository->fetchCurrentlyUsedCertificate($this->getId());
437  return $certificate_template->isCurrentlyActive();
438  }
439 
440 
442  // TREE NAVIGATION
444 
453  public static function getAllChildren(int $a_ref_id, bool $include_references = false): array
454  {
455  $ret = array();
456  $root = self::getInstanceByRefId($a_ref_id);
457  $root_id = $root->getId();
458  $root->applyToSubTreeNodes(function (ilObjStudyProgramme $prg) use (&$ret, $root_id) {
459  // exclude root node of subtree.
460  if ($prg->getId() === $root_id) {
461  return;
462  }
463  $ret[] = $prg;
464  }, $include_references);
465  return $ret;
466  }
467 
468  public function getAllPrgChildren(): array
469  {
470  $ret = [];
471  $this->applyToSubTreeNodes(
472  function (ilObjStudyProgramme $prg) use (&$ret) {
473  if ($prg->getId() === $this->getId()) {
474  return;
475  }
476  $ret[] = $prg;
477  }
478  );
479  return $ret;
480  }
481 
489  public function getChildren(bool $include_references = false): array
490  {
491  $this->throwIfNotInTree();
492 
493  if ($this->children === null) {
494  $ref_ids = $this->tree->getChildsByType($this->getRefId(), "prg");
495 
496  // apply container sorting to tree
497  $sorting = ilContainerSorting::_getInstance($this->getId());
498  $ref_ids = $sorting->sortItems(array('prg' => $ref_ids));
499  $ref_ids = $ref_ids['prg'];
500 
501  $this->children = array_map(static function ($node_data) {
502  return ilObjStudyProgramme::getInstanceByRefId($node_data["child"]);
503  }, $ref_ids);
504  }
505 
506  if ($include_references && $this->reference_children === null) {
507  $this->reference_children = [];
508  $ref_child_ref_ids = $this->tree->getChildsByType($this->getRefId(), "prgr");
509  foreach ($this->children as $prg) {
510  $ref_child_ref_ids =
511  array_merge(
512  $this->tree->getChildsByType($prg->getRefId(), "prgr"),
513  $ref_child_ref_ids
514  );
515  }
516  foreach (
517  array_unique(
518  array_map(
519  static function ($data) {
520  return (int) $data['child'];
521  },
522  array_filter($ref_child_ref_ids, static function ($data) {
523  return $data["deleted"] === null;
524  })
525  )
526  ) as $prg_ref_id
527  ) {
528  $this->reference_children[] =
529  (new ilObjStudyProgrammeReference($prg_ref_id))->getReferencedObject();
530  }
531  }
532  return $include_references ?
533  array_merge($this->children, $this->reference_children) :
535  }
536 
543  public function getParent(): ?ilObjStudyProgramme
544  {
545  if ($this->parent === false) {
546  $this->throwIfNotInTree();
547  $parent_data = $this->tree->getParentNodeData($this->getRefId());
548  if ($parent_data["type"] !== "prg") {
549  $this->parent = null;
550  } else {
551  $this->parent = self::getInstanceByRefId($parent_data["ref_id"]);
552  }
553  }
554  return $this->parent;
555  }
556 
557  protected function getReferencesTo(ilObjStudyProgramme $prg): array
558  {
559  $tree = $this->tree;
560  return array_filter(
561  array_map(
562  static function ($id) {
563  $refs = ilObject::_getAllReferences((int) $id);
564  return new ilObjStudyProgrammeReference(
565  array_shift($refs)
566  );
567  },
569  ),
570  static function ($prg_ref) use ($tree) {
571  return !$tree->isDeleted($prg_ref->getRefId());
572  }
573  );
574  }
575 
576  public function getReferencesToSelf(): array
577  {
578  return $this->getReferencesTo($this);
579  }
580 
586  public function getParents(bool $include_references = false): array
587  {
588  $current = $this;
589  $parents = [];
590  $queque = [$current];
591  while ($element = array_shift($queque)) {
592  $parent = $element->getParent();
593  if ($parent === null || $include_references) {
594  foreach ($this->getReferencesTo($element) as $reference) {
595  if ($this->tree->isDeleted($reference->getRefId())) {
596  continue;
597  }
598  $r_parent = $reference->getParent();
599  if (is_null($r_parent)) {
600  continue;
601  }
602  $queque[] = $r_parent;
603  $parents[] = $r_parent;
604  }
605  continue;
606  }
607  $queque[] = $parent;
608  $parents[] = $parent;
609  }
610  return array_reverse($parents);
611  }
612 
618  public function hasChildren(bool $include_references = false): bool
619  {
620  return $this->getAmountOfChildren($include_references) > 0;
621  }
622 
629  public function getAmountOfChildren($include_references = false): int
630  {
631  return count($this->getChildren($include_references));
632  }
633 
640  public function getDepth(): int
641  {
642  $cur = $this;
643  $count = 0;
644  while ($cur = $cur->getParent()) {
645  $count++;
646  }
647  return $count;
648  }
649 
654  public function getRoot(): ilObjStudyProgramme
655  {
656  $parents = $this->getParents();
657  if (count($parents) < 1) {
658  return $this;
659  }
660  return $parents[0];
661  }
662 
669  public function getLPChildren(): array
670  {
671  $this->throwIfNotInTree();
672 
673  if ($this->lp_children === null) {
674  $this->lp_children = array();
675 
676  $ref_ids = $this->tree->getChildsByType($this->getRefId(), "crsr");
677 
678  // apply container sorting to tree
679  $sorting = ilContainerSorting::_getInstance($this->getId());
680  $ref_ids = $sorting->sortItems(array('crs_ref' => $ref_ids));
681  $ref_ids = $ref_ids['crs_ref'];
682 
683  $lp_children = array_map(function ($node_data) {
684  $lp_obj = $this->object_factory->getInstanceByRefId((int) $node_data["child"]);
685 
686  // filter out all StudyProgramme instances
687  return ($lp_obj instanceof $this) ? null : $lp_obj;
688  }, $ref_ids);
689 
690  $this->lp_children = array_filter($lp_children);
691  }
692  return $this->lp_children;
693  }
694 
701  public function getLPChildrenIds(): array
702  {
703  return array_map(static function ($child) {
704  return $child->getId();
705  }, $this->getLPChildren());
706  }
707 
712  public function getAmountOfLPChildren(): int
713  {
714  return count($this->getLPChildren());
715  }
716 
717  public function hasLPChildren(): bool
718  {
719  return ($this->getAmountOfLPChildren() > 0);
720  }
721 
725  protected function throwIfNotInTree(): void
726  {
727  if (!$this->tree->isInTree($this->getRefId())) {
728  throw new ilStudyProgrammeTreeException("This program is not in tree.");
729  }
730  }
731 
733  // QUERIES ON SUBTREE
735 
743  public function applyToSubTreeNodes(Closure $fun, bool $include_references = false): void
744  {
745  $this->throwIfNotInTree();
746 
747  if ($fun($this) !== false) {
748  foreach ($this->getChildren($include_references) as $child) {
749  $child->applyToSubTreeNodes($fun, $include_references);
750  }
751  }
752  }
753 
757  public function getCompletedCourses(int $usr_id): array
758  {
759  $node_data = $this->tree->getNodeData($this->getRefId());
760  $crsrs = $this->tree->getSubTree($node_data, true, ["crsr"]);
761 
762  $completed_crss = array();
763  foreach ($crsrs as $ref) {
764  $crs_id = (int) ilContainerReference::_lookupTargetId((int) $ref["obj_id"]);
765  $crs_ref_id = (int) ilContainerReference::_lookupTargetRefId((int) $ref["obj_id"]);
766 
767  if (ilObject::_exists((int) $ref['ref_id'], true) &&
768  is_null(ilObject::_lookupDeletedDate((int) $ref['ref_id'])) &&
769  ilObject::_exists($crs_id, false) &&
770  is_null(ilObject::_lookupDeletedDate($crs_ref_id)) &&
771  ilLPStatus::_hasUserCompleted($crs_id, $usr_id)
772  ) {
773  $containing_prg = self::getInstanceByRefId((int) $ref["parent"]);
774  if ($containing_prg->isActive()) {
775  $completed_crss[] = [
776  "crs_id" => $crs_id
777  , "prg_ref_id" => (int) $ref["parent"]
778  , "prg_obj_id" => $containing_prg->getId()
779  , "crsr_ref_id" => (int) $ref["child"]
780  , "crsr_id" => (int) $ref["obj_id"]
781  , "crs_ref_id" => (int) $crs_ref_id
782  , "crs_id" => (int) $crs_id
783 
784  , "title" => ilContainerReference::_lookupTitle((int) $ref["obj_id"])
785  ];
786  }
787  }
788  }
789  return $completed_crss;
790  }
791 
793  // TREE MANIPULATION
795 
807  {
808  $this->throwIfNotInTree();
809 
811  throw new ilStudyProgrammeTreeException("Program already contains leafs.");
812  }
813 
814  if ($this->tree->isInTree($a_prg->getRefId())) {
815  throw new ilStudyProgrammeTreeException("Other program already is in tree.");
816  }
817 
818  if ($a_prg->getRefId() === null) {
819  $a_prg->createReference();
820  }
821  $a_prg->putInTree($this->getRefId());
822  return $this;
823  }
824 
833  public function nodeInserted($prg): void
834  {
835  if (! $prg instanceof ilObjStudyProgrammeReference &&
836  ! $prg instanceof ilObjStudyProgramme
837  ) {
838  throw new ilStudyProgrammeTreeException("Wrong type of node: " . get_class($prg));
839  }
841  throw new ilStudyProgrammeTreeException("Program already contains leafs.");
842  }
843 
845  $this->settings_repository->update(
847  );
848  }
849 
850  $this->clearChildrenCache();
851  $this->addMissingProgresses();
852  }
853 
861  public function putInTree(int $parent_ref_id): void
862  {
863  parent::putInTree($parent_ref_id);
864 
865  if (ilObject::_lookupType($parent_ref_id, true) === "prg") {
866  $par = self::getInstanceByRefId($parent_ref_id);
867  $par->nodeInserted($this);
868  }
869  }
870 
881  {
882  if ($a_prg->getParent()->getId() !== $this->getId()) {
883  throw new ilStudyProgrammeTreeException("This is no parent of the given programm.");
884  }
885 
886  if (!$a_prg->canBeRemoved()) {
887  throw new ilStudyProgrammeTreeException("The node has relevant assignments.");
888  }
889 
890  // *sigh*...
891  $node_data = $this->tree->getNodeData($a_prg->getRefId());
892  $this->tree->deleteTree($node_data);
893  $a_prg->clearParentCache();
894  $this->clearChildrenCache();
895 
896  return $this;
897  }
898 
903  public function canBeRemoved(): bool
904  {
905  return ! $this->hasRelevantProgresses();
906  }
907 
917  public function moveTo(ilObjStudyProgramme $new_parent): ilObjStudyProgramme
918  {
919  global $DIC;
920  $rbacadmin = $DIC['rbacadmin'];
921 
922  if ($parent = $this->getParent()) {
923  // TODO: check if there some leafs in the new parent
924 
925  $this->tree->moveTree($this->getRefId(), $new_parent->getRefId());
926  // necessary to clean up permissions
927  $rbacadmin->adjustMovedObjectPermissions($this->getRefId(), $parent->getRefId());
928 
929  // TODO: lp-progress needs to be updated
930 
931  // clear caches on different nodes
932  $this->clearParentCache();
933 
934  $parent->clearChildrenCache();
935  $parent->clearLPChildrenCache();
936 
937  $new_parent->clearChildrenCache();
938  $new_parent->clearLPChildrenCache();
939  }
940 
941  return $this;
942  }
943 
945  // USER ASSIGNMENTS
947 
958  public function assignUser(int $usr_id, int $acting_usr_id = null, $raise_event = true): ilPRGAssignment
959  {
960  $this->members_cache = null;
961 
963  throw new ilException(
964  "ilObjStudyProgramme::assignUser: Can't assign user to program '"
965  . $this->getId() . "', since it's not in active status."
966  );
967  }
968 
969  if (is_null($acting_usr_id)) {
970  $acting_usr_id = $this->getLoggedInUserId();
971  }
972 
973  $ass = $this->assignment_repository->createFor($this->getId(), $usr_id, $acting_usr_id);
974  $ass = $ass
975  ->initAssignmentDates();
976 
977  $ass = $ass->resetProgresses(
978  $this->getSettingsRepository(),
979  $acting_usr_id
980  );
981 
982  $this->assignment_repository->store($ass);
983 
984  if ($raise_event) {
985  $this->events->userAssigned($ass);
986  }
987  return $ass;
988  }
989 
998  {
999  $this->members_cache = null;
1000  if ($assignment->getRootId() !== $this->getId()) {
1001  throw new ilException(
1002  "ilObjStudyProgramme::removeAssignment: Assignment '"
1003  . $assignment->getId() . "' does not belong to study "
1004  . "program '" . $this->getId() . "'."
1005  );
1006  }
1007 
1008  $this->assignment_repository->delete($assignment);
1009 
1010  $affected_node_ids = array_map(fn($pgs) => $pgs->getNodeId(), $assignment->getProgresses());
1011  foreach ($affected_node_ids as $node_obj_id) {
1012  $this->refreshLPStatus($assignment->getUserId(), $node_obj_id);
1013  }
1014 
1015  $this->events->userDeassigned($assignment);
1016  return $this;
1017  }
1018 
1019  public function getSpecificAssignment(int $assignment_id): ilPRGAssignment
1020  {
1021  return $this->assignment_repository->get($assignment_id);
1022  }
1023 
1024  public function storeExpiryInfoSentFor(ilPRGAssignment $ass): void
1025  {
1026  $this->assignment_repository->storeExpiryInfoSentFor($ass);
1027  }
1028 
1029  public function resetExpiryInfoSentFor(ilPRGAssignment $ass): void
1030  {
1031  $this->assignment_repository->resetExpiryInfoSentFor($ass);
1032  }
1033 
1034  public function storeRiskyToFailSentFor(ilPRGAssignment $ass): void
1035  {
1036  $this->assignment_repository->storeRiskyToFailSentFor($ass);
1037  }
1038 
1039  public function resetRiskyToFailSentFor(ilPRGAssignment $ass): void
1040  {
1041  $this->assignment_repository->resetRiskyToFailSentFor($ass);
1042  }
1043 
1047  public function hasAssignmentOf(int $user_id): bool
1048  {
1049  return $this->getAmountOfAssignmentsOf($user_id) > 0;
1050  }
1051 
1056  public function getAmountOfAssignmentsOf(int $user_id): int
1057  {
1058  return count($this->getAssignmentsOf($user_id));
1059  }
1060 
1068  public function getAssignmentsOf(int $user_id): array
1069  {
1070  $assignments = $this->assignment_repository->getAllForNodeIsContained(
1071  $this->getId(),
1072  [$user_id]
1073  );
1074 
1075  usort($assignments, function ($a_one, $a_other) {
1076  return strcmp(
1077  $a_one->getLastChange()->format('Y-m-d'),
1078  $a_other->getLastChange()->format('Y-m-d')
1079  );
1080  });
1081  return $assignments;
1082  }
1083 
1087  public function getAssignments(): array
1088  {
1089  return $this->assignment_repository->getAllForNodeIsContained($this->getId());
1090  }
1091 
1096  public function getMembers(): array
1097  {
1098  $usr_ids = [];
1099  foreach ($this->getAssignments() as $assignment) {
1100  $usr_ids[] = $assignment->getUserId();
1101  }
1102  return array_unique($usr_ids);
1103  }
1104 
1108  public function getLocalMembers(): array
1109  {
1110  if (!$this->members_cache) {
1111  $this->members_cache = array_map(
1112  static function ($assignment) {
1113  return $assignment->getUserId();
1114  },
1115  $this->assignment_repository->getByPrgId($this->getId())
1116  );
1117  }
1118  return $this->members_cache;
1119  }
1120 
1124  public function hasAssignments(): bool
1125  {
1126  $filter = new ilPRGAssignmentFilter($this->lng);
1127  $count = $this->assignment_repository->countAllForNodeIsContained(
1128  $this->getId(),
1129  null,
1130  $filter
1131  );
1132  return $count > 0;
1133 
1134  }
1135 
1141  public function getAssignmentsOfSingleProgramForUser(int $usr_id): array
1142  {
1143  return $this->assignment_repository->getAllForSpecificNode($this->getId(), [$usr_id]);
1144  }
1145 
1149  public function hasAssignmentsOfSingleProgramForUser(int $usr_id): bool
1150  {
1151  return count($this->getAssignmentsOfSingleProgramForUser($usr_id)) > 0;
1152  }
1153 
1154  public function getCertificateRelevantAssignmentIds(int ...$usr_ids): array
1155  {
1156  return $this->assignment_repository->getCertificateRelevantAssignmentIds(
1157  $this->getId(),
1158  ...$usr_ids
1159  );
1160  }
1161 
1162 
1164  // USER PROGRESS
1166 
1172  public function addMissingProgresses(): void
1173  {
1174  $assignments = $this->getAssignments();
1175  foreach ($assignments as $ass) {
1176  $this->assignment_repository->store($ass);
1177  }
1178  }
1179 
1183  public function hasRelevantProgresses(): bool
1184  {
1185  $filter = new ilPRGAssignmentFilter($this->lng);
1186  $filter = $filter->withValues([
1187  'prg_status_hide_irrelevant' => true
1188  ]);
1189  $count = $this->assignment_repository->countAllForNodeIsContained(
1190  $this->getId(),
1191  null,
1192  $filter
1193  );
1194  return $count > 0;
1195  }
1196 
1197  public function getIdsOfUsersWithRelevantProgress(): array
1198  {
1199  return array_map(
1200  fn($ass) => $ass->getUserId(),
1201  $this->getAssignments()
1202  );
1203  }
1204 
1205 
1207  // AUTOMATIC CONTENT CATEGORIES
1209 
1214  public function getAutomaticContentCategories(): array
1215  {
1216  return $this->auto_categories_repository->getFor($this->getId());
1217  }
1218 
1219  public function hasAutomaticContentCategories(): bool
1220  {
1221  return count($this->getAutomaticContentCategories()) > 0;
1222  }
1223 
1224 
1229  public function storeAutomaticContentCategory(int $category_ref_id): void
1230  {
1231  $ac = $this->auto_categories_repository->create(
1232  $this->getId(),
1233  $category_ref_id
1234  );
1235  $this->auto_categories_repository->update($ac);
1236  }
1237 
1242  public function deleteAutomaticContentCategories(array $category_ids = []): void
1243  {
1244  $this->auto_categories_repository->delete($this->getId(), $category_ids);
1245  }
1246 
1250  public function deleteAllAutomaticContentCategories(): void
1251  {
1252  $this->auto_categories_repository->deleteFor($this->getId());
1253  }
1254 
1258  public static function addCrsToProgrammes(int $crs_ref_id, int $cat_ref_id): void
1259  {
1260  foreach (self::getProgrammesMonitoringCategory($cat_ref_id) as $prg) {
1261  $course_ref = new ilObjCourseReference();
1262  $course_ref->setTitleType(ilContainerReference::TITLE_TYPE_REUSE);
1263  $course_ref->setTargetRefId($crs_ref_id);
1264  $course_ref->create();
1265  $course_ref->createReference();
1266  $course_ref->putInTree($prg->getRefId());
1267  $course_ref->setPermissions($crs_ref_id);
1268  $course_ref->setTargetId(ilObject::_lookupObjectId($crs_ref_id));
1269  $course_ref->update();
1270  $lp = new ilLPObjSettings($course_ref->getId());
1271  $lp->insert();
1272  $lp->setMode($lp::LP_MODE_COURSE_REFERENCE);
1273  $lp->update(false);
1274  }
1275  }
1276 
1282  public static function removeCrsFromProgrammes(int $crs_ref_id, int $cat_ref_id): void
1283  {
1284  foreach (self::getProgrammesMonitoringCategory($cat_ref_id) as $prg) {
1285  foreach ($prg->getLPChildren() as $child) {
1286  if ((int) $child->getTargetRefId() === $crs_ref_id) {
1287  $child->delete();
1288  }
1289  }
1290  }
1291  }
1292 
1297  protected static function getProgrammesMonitoringCategory(int $cat_ref_id): array
1298  {
1299  $db = ilStudyProgrammeDIC::dic()['model.AutoCategories.ilStudyProgrammeAutoCategoriesRepository'];
1300  $programmes =
1301  array_filter(
1302  array_map(
1303  static function (array $rec) {
1304  $values = array_values($rec);
1305  $prg_obj_id = (int) array_shift($values);
1306 
1307  $references = ilObject::_getAllReferences($prg_obj_id);
1308  $prg_ref_id = (int) array_shift($references);
1309 
1310  $prg = self::getInstanceByRefId($prg_ref_id);
1311  if ($prg->isAutoContentApplicable()) {
1312  return $prg;
1313  }
1314  },
1315  $db::getProgrammesFor($cat_ref_id)
1316  )
1317  );
1318  return $programmes;
1319  }
1320 
1327  public function isAutoContentApplicable(): bool
1328  {
1329  $valid_status = in_array(
1330  $this->getSettings()->getAssessmentSettings()->getStatus(),
1331  [
1334  ],
1335  true
1336  );
1337 
1338  $crslnk_allowed = (
1339  $this->hasLPChildren()
1340  || $this->getAmountOfChildren(true) === 0
1341  );
1342 
1343  return $valid_status && $crslnk_allowed;
1344  }
1345 
1346 
1348  // AUTOMATIC MEMBERSHIPS
1350 
1355  public function getAutomaticMembershipSources(): array
1356  {
1357  return $this->auto_memberships_repository->getFor($this->getId());
1358  }
1359 
1363  public function storeAutomaticMembershipSource(string $type, int $src_id): void
1364  {
1365  $ams = $this->auto_memberships_repository->create($this->getId(), $type, $src_id, false);
1366  $this->auto_memberships_repository->update($ams);
1367  }
1368 
1372  public function deleteAutomaticMembershipSource(string $type, int $src_id): void
1373  {
1374  $this->auto_memberships_repository->delete($this->getId(), $type, $src_id);
1375  }
1376 
1380  public function deleteAllAutomaticMembershipSources(): void
1381  {
1382  $this->auto_memberships_repository->deleteFor($this->getId());
1383  }
1384 
1388  public function disableAutomaticMembershipSource(string $type, int $src_id): void
1389  {
1390  $ams = $this->auto_memberships_repository->create($this->getId(), $type, $src_id, false);
1391  $this->auto_memberships_repository->update($ams);
1392  }
1393 
1398  public function enableAutomaticMembershipSource(string $type, int $src_id, bool $assign_now = false): void
1399  {
1400  if ($assign_now) {
1402  $member_ids = $this->getMembersOfMembershipSource($type, $src_id);
1403  foreach ($member_ids as $usr_id) {
1404  if (!$this->getAssignmentsOfSingleProgramForUser($usr_id)) {
1405  $this->assignUser($usr_id, $assigned_by);
1406  }
1407  }
1408  }
1409  $ams = $this->auto_memberships_repository->create($this->getId(), $type, $src_id, true);
1410  $this->auto_memberships_repository->update($ams);
1411  }
1412 
1418  protected function getMembersOfMembershipSource(string $src_type, int $src_id): array
1419  {
1420  $source_reader = $this->membersourcereader_factory->getReaderFor($src_type, $src_id);
1421  return $source_reader->getMemberIds();
1422  }
1423 
1424 
1429  protected static function getProgrammesMonitoringMemberSource(string $src_type, int $src_id): array
1430  {
1431  $db = ilStudyProgrammeDIC::dic()['model.AutoMemberships.ilStudyProgrammeAutoMembershipsRepository'];
1432  $programmes = array_map(
1433  static function ($rec) {
1434  $values = array_values($rec);
1435  $prg_obj_id = (int) array_shift($values);
1436 
1437  $references = ilObject::_getAllReferences($prg_obj_id);
1438  $prg_ref_id = (int) array_shift($references);
1439 
1440  $prg = self::getInstanceByRefId($prg_ref_id);
1441  return $prg;
1442  },
1443  $db::getProgrammesFor($src_type, $src_id)
1444  );
1445  return $programmes;
1446  }
1447 
1448  public static function addMemberToProgrammes(string $src_type, int $src_id, int $usr_id): void
1449  {
1450  foreach (self::getProgrammesMonitoringMemberSource($src_type, $src_id) as $prg) {
1451  if ($prg->isActive() &&
1452  !$prg->hasAssignmentsOfSingleProgramForUser($usr_id)) {
1453  $assigned_by = ilStudyProgrammeAutoMembershipSource::SOURCE_MAPPING[$src_type];
1454  $prg->assignUser($usr_id, $assigned_by);
1455  }
1456  }
1457  }
1458 
1459  public static function removeMemberFromProgrammes(string $src_type, int $src_id, int $usr_id): void
1460  {
1461  $now = new DateTimeImmutable();
1462  $assignment_repository = ilStudyProgrammeDIC::dic()['repo.assignment'];
1463  foreach (self::getProgrammesMonitoringMemberSource($src_type, $src_id) as $prg) {
1464  $assignments = $prg->getAssignmentsOfSingleProgramForUser($usr_id);
1465  $next_membership_source = $prg->getApplicableMembershipSourceForUser($usr_id, $src_id);
1466 
1467  foreach ($assignments as $assignment) {
1468  if (!$assignment->getProgressTree()->isInProgress()) {
1469  continue;
1470  }
1471 
1472  if (
1473  $next_membership_source !== null
1474  && $next_membership_source?->isEnabled()
1475  && $next_membership_source->getSourceId() !== $src_id
1476  ) {
1477  $new_src_type = $next_membership_source->getSourceType();
1478  $assigned_by = ilStudyProgrammeAutoMembershipSource::SOURCE_MAPPING[$new_src_type];
1479  $assignment = $assignment->withLastChange($assigned_by, $now);
1480  $assignment_repository->store($assignment);
1481  break;
1482  } else {
1483  $assignment_repository->delete($assignment);
1484  }
1485  }
1486  }
1487  }
1488 
1490  int $usr_id,
1491  ?int $exclude_id
1493  foreach ($this->getAutomaticMembershipSources() as $ams) {
1494  $src_id = $ams->getSourceId();
1495  if ($src_id !== $exclude_id
1496  && $ams->isEnabled()
1497  ) {
1498  $source_members = $this->getMembersOfMembershipSource($ams->getSourceType(), $src_id);
1499  if (in_array($usr_id, $source_members)) {
1500  return $ams;
1501  }
1502  }
1503  }
1504  return null;
1505  }
1506 
1508  // HELPERS
1510 
1514  protected function updateLastChange(): void
1515  {
1516  $this->getSettings()->updateLastChange();
1517  if ($parent = $this->getParent()) {
1518  $parent->updateLastChange();
1519  }
1520  $this->update();
1521  }
1522 
1535  int $ref_id,
1536  int $obj_id,
1537  int $user_id
1538  ): void {
1539  global $DIC; // TODO: replace this by a settable static for testing purpose?
1540  $tree = $DIC['tree'];
1541  $node_data = $tree->getParentNodeData($ref_id);
1542  if (count($node_data) === 0 || !array_key_exists('type', $node_data) || $node_data["type"] !== "prg") {
1543  return;
1544  }
1545  self::initStudyProgrammeCache();
1546  $prg = self::getInstanceByRefId($node_data["child"]);
1547  if ($prg->getLPMode() !== ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
1548  return;
1549  }
1550  $prg->succeed($user_id, $obj_id);
1551  }
1552 
1553  public function succeed(int $usr_id, int $triggering_obj_id, ilPRGAssignment $ass = null): void
1554  {
1555  $progress_node_id = $this->getId();
1556  if (is_null($ass)) {
1557  $user_assignments = $this->assignment_repository
1558  ->getAllForNodeIsContained($progress_node_id, [$usr_id]);
1559  } else {
1560  $user_assignments = [$ass];
1561  }
1562 
1563  foreach ($user_assignments as $ass) {
1564  $ass = $ass->succeed(
1565  $this->getSettingsRepository(),
1566  $progress_node_id,
1567  $triggering_obj_id
1568  );
1569  $this->assignment_repository->store($ass);
1570  }
1571  }
1572 
1573  public function updateCustomIcon(): void
1574  {
1575  $customIcon = $this->custom_icon_factory->getByObjId($this->getId(), $this->getType());
1576  $subtype = $this->getSubType();
1577 
1578  if ($subtype && $subtype->getIconIdentifier()
1579  && $src = $this->type_repository->getIconPathFS($subtype)
1580  ) {
1581  //This is a horrible hack to allow Flysystem/LocalFilesystem to read the file.
1582  $tmp = 'ico_' . $this->getId();
1583  copy($src, \ilFileUtils::getDataDir() . '/temp/' . $tmp);
1584 
1585  $customIcon->saveFromTempFileName($tmp);
1586  } else {
1587  $customIcon->remove();
1588  }
1589  }
1590 
1592  // HOOKS
1594 
1605  public static function getCreatableSubObjects(array $subobjects, $ref_id): array
1606  {
1607  if ($ref_id === null) {
1608  return $subobjects;
1609  }
1610 
1611  if (ilObject::_lookupType($ref_id, true) !== "prg") {
1612  throw new ilException("Ref-Id '$ref_id' does not belong to a study programme object.");
1613  }
1614 
1615  $parent = self::getInstanceByRefId($ref_id);
1616 
1617  $mode = $parent->getLPMode();
1618 
1619  switch ($mode) {
1621  $possible_subobjects = $subobjects;
1622  break;
1624  $possible_subobjects = [
1625  "prg" => $subobjects["prg"],
1626  "prgr" => $subobjects["prgr"]
1627  ];
1628  break;
1630  $possible_subobjects = ['crsr' => $subobjects['crsr']];
1631  break;
1632  default:
1633  throw new ilException("Undefined mode for study programme: '$mode'");
1634  }
1635 
1636  if ($parent->hasAutomaticContentCategories()) {
1637  $possible_subobjects = array_filter(
1638  $possible_subobjects,
1639  static function ($subtype) {
1640  return $subtype === 'crsr';
1641  },
1642  ARRAY_FILTER_USE_KEY
1643  );
1644  }
1645  return $possible_subobjects;
1646  }
1647 
1648 
1649  protected function getLoggedInUserId(): int
1650  {
1651  return $this->ilUser->getId();
1652  }
1653 
1654  protected function getNow(): DateTimeImmutable
1655  {
1656  return new DateTimeImmutable();
1657  }
1658 
1659  protected function refreshLPStatus(int $usr_id, int $node_obj_id = null): void
1660  {
1661  if (is_null($node_obj_id)) {
1662  $node_obj_id = $this->getId();
1663  }
1664  ilLPStatusWrapper::_updateStatus($node_obj_id, $usr_id);
1665  }
1666 
1667  public function markAccredited(
1668  int $assignment_id,
1669  int $acting_usr_id,
1670  ilPRGMessageCollection $err_collection
1671  ): void {
1672  $progress_node_id = $this->getId();
1673  $assignment = $this->assignment_repository->get($assignment_id)
1674  ->markAccredited(
1675  $this->getSettingsRepository(),
1676  $this->events,
1677  $progress_node_id,
1678  $acting_usr_id,
1679  $err_collection
1680  );
1681 
1682  $this->assignment_repository->store($assignment);
1683  }
1684 
1685  public function unmarkAccredited(
1686  int $assignment_id,
1687  int $acting_usr_id,
1688  ilPRGMessageCollection $err_collection
1689  ): void {
1690  $progress_node_id = $this->getId();
1691  $assignment = $this->assignment_repository->get($assignment_id)
1692  ->unmarkAccredited(
1693  $this->getSettingsRepository(),
1694  $progress_node_id,
1695  $acting_usr_id,
1696  $err_collection
1697  );
1698 
1699  $this->assignment_repository->store($assignment);
1700  $this->refreshLPStatus($assignment->getUserId());
1701  }
1702 
1703  public function markNotRelevant(
1704  int $assignment_id,
1705  int $acting_usr_id,
1706  ilPRGMessageCollection $err_collection
1707  ): void {
1708  $progress_node_id = $this->getId();
1709  $assignment = $this->assignment_repository->get($assignment_id)
1710  ->markNotRelevant(
1711  $this->getSettingsRepository(),
1712  $progress_node_id,
1713  $acting_usr_id,
1714  $err_collection
1715  );
1716 
1717  $this->assignment_repository->store($assignment);
1718  $this->refreshLPStatus($assignment->getUserId());
1719  }
1720 
1721  public function markRelevant(
1722  int $assignment_id,
1723  int $acting_usr_id,
1724  ilPRGMessageCollection $err_collection
1725  ): void {
1726  $progress_node_id = $this->getId();
1727  $assignment = $this->assignment_repository->get($assignment_id)
1728  ->markRelevant(
1729  $this->getSettingsRepository(),
1730  $progress_node_id,
1731  $acting_usr_id,
1732  $err_collection
1733  );
1734 
1735  $this->assignment_repository->store($assignment);
1736  $this->refreshLPStatus($assignment->getUserId());
1737  }
1738 
1739  public function changeProgressDeadline(
1740  int $assignment_id,
1741  int $acting_usr_id,
1742  ilPRGMessageCollection $err_collection,
1743  ?DateTimeImmutable $deadline
1744  ): void {
1745  $progress_node_id = $this->getId();
1746  $assignment = $this->assignment_repository->get($assignment_id)
1747  ->changeProgressDeadline(
1748  $this->getSettingsRepository(),
1749  $progress_node_id,
1750  $acting_usr_id,
1751  $err_collection,
1752  $deadline
1753  );
1754 
1755  $this->assignment_repository->store($assignment);
1756  $this->refreshLPStatus($assignment->getUserId());
1757  }
1758 
1760  int $assignment_id,
1761  int $acting_usr_id,
1762  ilPRGMessageCollection $err_collection,
1763  ?DateTimeImmutable $validity
1764  ): void {
1765  $progress_node_id = $this->getId();
1766  $assignment = $this->assignment_repository->get($assignment_id)
1767  ->changeProgressValidityDate(
1768  $this->getSettingsRepository(),
1769  $progress_node_id,
1770  $acting_usr_id,
1771  $err_collection,
1772  $validity
1773  );
1774 
1775  $this->assignment_repository->store($assignment);
1776  $this->refreshLPStatus($assignment->getUserId());
1777  }
1778 
1779  public function changeAmountOfPoints(
1780  int $assignment_id,
1781  int $acting_usr_id,
1782  ilPRGMessageCollection $err_collection,
1783  int $points
1784  ): void {
1785  $progress_node_id = $this->getId();
1786  $assignment = $this->assignment_repository->get($assignment_id)
1787  ->changeAmountOfPoints(
1788  $this->getSettingsRepository(),
1789  $progress_node_id,
1790  $acting_usr_id,
1791  $err_collection,
1792  $points
1793  );
1794 
1795  $this->assignment_repository->store($assignment);
1796  $this->refreshLPStatus($assignment->getUserId());
1797  }
1798 
1799  public function updatePlanFromRepository(
1800  int $assignment_id,
1801  int $acting_usr_id,
1802  ilPRGMessageCollection $err_collection = null
1803  ): void {
1804  $assignment = $this->assignment_repository->get($assignment_id)
1805  ->updatePlanFromRepository(
1806  $this->getSettingsRepository(),
1807  $acting_usr_id,
1808  $err_collection
1809  );
1810 
1811  $this->assignment_repository->store($assignment);
1812  $this->refreshLPStatus($assignment->getUserId());
1813  }
1814 
1815  public function acknowledgeCourses(
1816  int $assignment_id,
1817  array $nodes,
1818  ilPRGMessageCollection $err_collection = null
1819  ): void {
1820  $acting_usr_id = $this->getLoggedInUserId();
1821  $assignment = $this->assignment_repository->get($assignment_id);
1822  foreach ($nodes as $nodeinfo) {
1823  [$node_obj_id, $course_obj_id] = $nodeinfo;
1824 
1825  $assignment = $assignment->succeed(
1826  $this->settings_repository,
1827  $node_obj_id,
1828  $course_obj_id
1829  );
1830 
1831  $msg = sprintf(
1832  '%s, progress-id (%s/%s)',
1833  $assignment->getUserInformation()->getFullname(),
1834  $assignment->getId(),
1835  (string) $node_obj_id
1836  );
1837  $err_collection->add(true, 'acknowledged_course', $msg);
1838  }
1839  $this->assignment_repository->store($assignment);
1840  $this->refreshLPStatus($assignment->getUserId());
1841  }
1842 
1843  public function canBeCompleted(ilPRGProgress $progress): bool
1844  {
1846  return true;
1847  }
1848  $possible_points = $progress->getPossiblePointsOfRelevantChildren();
1849  return $possible_points >= $progress->getAmountOfPoints();
1850  }
1851 
1855  public function statusToRepr(int $status): string
1856  {
1857  $lng = $this->lng;
1858  $lng->loadLanguageModule("prg");
1859  if ($status === ilPRGProgress::STATUS_IN_PROGRESS) {
1860  return $lng->txt("prg_status_in_progress");
1861  }
1862  if ($status === ilPRGProgress::STATUS_COMPLETED) {
1863  return $lng->txt("prg_status_completed");
1864  }
1865  if ($status === ilPRGProgress::STATUS_ACCREDITED) {
1866  return $lng->txt("prg_status_accredited");
1867  }
1868  if ($status === ilPRGProgress::STATUS_NOT_RELEVANT) {
1869  return $lng->txt("prg_status_not_relevant");
1870  }
1871  if ($status === ilPRGProgress::STATUS_FAILED) {
1872  return $lng->txt("prg_status_failed");
1873  }
1874  throw new ilException("Unknown status: '$status'");
1875  }
1876 
1877  public function hasContentPage(): bool
1878  {
1879  return \ilContainerPage::_exists(self::CP_TYPE, $this->getId());
1880  }
1881  public function createContentPage(): void
1882  {
1883  if ($this->hasContentPage()) {
1884  throw new \LogicException('will not create content page - it already exists.');
1885  }
1886  $new_page_object = new \ilContainerPage();
1887  $new_page_object->setId($this->getId());
1888  $new_page_object->setParentId($this->getId());
1889  $new_page_object->createFromXML();
1890  }
1891 }
getCompletedCourses(int $usr_id)
Get courses in this program that the given user already completed.
setStatus(int $a_status)
Set the status of the node.
getCertificateRelevantAssignmentIds(int ... $usr_ids)
static _hasUserCompleted(int $a_obj_id, int $a_user_id)
Lookup user object completion.
adjustLPMode()
Adjust the lp mode to match current state of tree:
string $type
array $settings
Setting values (LTI parameters, custom parameters and local parameters).
Definition: System.php:200
addNode(ilObjStudyProgramme $a_prg)
Inserts another ilObjStudyProgramme in this object.
clearLPChildrenCache()
Clear the cached lp children.
static addCrsToProgrammes(int $crs_ref_id, int $cat_ref_id)
Check, if a category is under surveilllance and automatically add the course.
getSubType()
Gets the SubType Object.
static _lookupTitle(int $obj_id)
markRelevant(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection)
storeAutomaticContentCategory(int $category_ref_id)
Store a Category with auto-content for this StudyProgramme; a category can only be referenced once (p...
static getLogger(string $a_component_id)
Get component logger.
getParent()
Get the parent ilObjStudyProgramme of this object.
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
getApplicableMembershipSourceForUser(int $usr_id, ?int $exclude_id)
changeProgressValidityDate(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection, ?DateTimeImmutable $validity)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
isAutoContentApplicable()
AutoContent should only be available in active- or draft-mode, and only, if there is no sub-programme...
assignUser(int $usr_id, int $acting_usr_id=null, $raise_event=true)
Assign a user to this node at the study program.
getMembers()
get usr_ids with any progress on this node
unmarkAccredited(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection)
ilStudyProgrammeMembershipSourceReaderFactory $membersourcereader_factory
getRefIdFor(int $obj_id)
getChildren(bool $include_references=false)
Get all ilObjStudyProgrammes that are direct children of this object.
static getProgrammesMonitoringMemberSource(string $src_type, int $src_id)
Get all StudyProgrammes monitoring this membership-source.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getLPChildren()
Get the leafs the study programme contains.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getAllReferences(int $id)
get all reference ids for object ID
nodeInserted($prg)
Clears child cache and adds progress for new node.
ilTree $tree
isDeleted(int $a_node_id)
This is a wrapper for isSaved() with a more useful name.
__construct(int $id=0, bool $call_by_reference=true)
ATTENTION: After using the constructor the object won&#39;t be in the cache.
static saveObjRecSelection(int $a_obj_id, string $a_sub_type="", array $a_records=null, bool $a_delete_before=true)
Save repository object record selection.
disableAutomaticMembershipSource(string $type, int $src_id)
Disable a membership source.
applyToSubTreeNodes(Closure $fun, bool $include_references=false)
Apply the given Closure to every node in the subtree starting at this object.
static getCreatableSubObjects(array $subobjects, $ref_id)
Filter the list of possible subobjects for the objects that actually could be created on a concrete n...
loadLanguageModule(string $a_module)
Load language module.
deleteAssignmentsAndProgresses()
Delete all assignments from the DB.
markNotRelevant(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection)
storeAutomaticMembershipSource(string $type, int $src_id)
Store a source to be monitored for automatic memberships.
hasAssignmentOf(int $user_id)
Check whether user is assigned to this program or any node above.
storeRiskyToFailSentFor(ilPRGAssignment $ass)
storeExpiryInfoSentFor(ilPRGAssignment $ass)
getLocalMembers()
get usr_ids with assignment on this node
getAssignmentsOf(int $user_id)
Get the assignments of user at this program or any node above.
changeProgressDeadline(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection, ?DateTimeImmutable $deadline)
getAmountOfLPChildren()
Get the amount of leafs the study programme contains.
enableAutomaticMembershipSource(string $type, int $src_id, bool $assign_now=false)
Enable a membership source.
getRoot()
Get the ilObjStudyProgramme that is the root node of the tree this programme is in.
static getProgrammesMonitoringCategory(int $cat_ref_id)
Get all (not OUTDATED) StudyProgrammes monitoring this category.
static removeCrsFromProgrammes(int $crs_ref_id, int $cat_ref_id)
Check, if a category is under surveillance and automatically remove the deleted course.
global $DIC
Definition: feed.php:28
resetRiskyToFailSentFor(ilPRGAssignment $ass)
createReference()
creates reference for object
removeNode(ilObjStudyProgramme $a_prg)
Remove a node from this object.
hasAssignments()
Are there any assignments on this node or any node above?
A Progress is the status of a user on a single node of an assignment; it is unique by assignment_id:u...
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
__construct(VocabulariesInterface $vocabularies)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
clearChildrenCache()
Clear the cached children.
getAutomaticContentCategories()
Get configuration of categories with auto-content for this StudyProgramme;.
getParentNodeData(int $a_node_id)
get data of parent node from tree and object_data
resetExpiryInfoSentFor(ilPRGAssignment $ass)
deleteAllAutomaticContentCategories()
Delete all configuration of categories with auto-content for this StudyProgramme;.
ilStudyProgrammeAutoMembershipsDBRepository $auto_memberships_repository
hasRelevantProgresses()
Are there any users that have a relevant progress on this programme?
removeAssignment(ilPRGAssignment $assignment)
Remove an assignment from this program.
ilLanguage $lng
static addMemberToProgrammes(string $src_type, int $src_id, int $usr_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
bool $call_by_reference
getParents(bool $include_references=false)
Get all parents of the node, where the root of the program comes first.
ilDBInterface $db
cloneObject(int $target_ref_id, int $copy_id=0, bool $omit_tree=false)
getAssignmentsOfSingleProgramForUser(int $usr_id)
Get assignments of user to this program-node only.
static ilObjStudyProgrammeCache $study_programme_cache
getSpecificAssignment(int $assignment_id)
acknowledgeCourses(int $assignment_id, array $nodes, ilPRGMessageCollection $err_collection=null)
getProgresses(array &$ret=[], ilPRGProgress $pgs=null)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupObjectId(int $ref_id)
statusToRepr(int $status)
Get a user readable representation of a status.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
hasAssignmentsOfSingleProgramForUser(int $usr_id)
Get assignments of user to this program-node only.
markAccredited(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection)
changeAmountOfPoints(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection, int $points)
static getDataDir()
get data directory (outside webspace)
moveTo(ilObjStudyProgramme $new_parent)
Move this tree node to a new parent.
succeed(int $usr_id, int $triggering_obj_id, ilPRGAssignment $ass=null)
static removeMemberFromProgrammes(string $src_type, int $src_id, int $usr_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupSourceIds(int $a_target_id)
Get ids of all container references that target the object with the given id.
getMembersOfMembershipSource(string $src_type, int $src_id)
Get member-ids of a certain source.
canBeCompleted(ilPRGProgress $progress)
setPoints(int $points)
Set the amount of points.
updatePlanFromRepository(int $assignment_id, int $acting_usr_id, ilPRGMessageCollection $err_collection=null)
static getInstanceByObjId(int $obj_id)
getLastChange()
Get the timestamp of the last change on this program or sub program.
ilStudyProgrammeEvents $events
getObjId()
Get the id of the study program.
fetchCurrentlyUsedCertificate(int $objId)
static setProgressesCompletedIfParentIsProgrammeInLPCompletedMode(int $ref_id, int $obj_id, int $user_id)
Succeed all StudyProgramme(Nodes) where the object with the given id (a CRSR) is in a Programme with ...
ilPRGAssignmentDBRepository $assignment_repository
addMissingProgresses()
Add missing progress records for all assignments of this programm.
getReferencesTo(ilObjStudyProgramme $prg)
Class ilStudyProgrammeType.
static getAllChildren(int $a_ref_id, bool $include_references=false)
Get a list of all ilObjStudyProgrammes in the subtree starting at $a_ref_id.
canBeRemoved()
Check weather a node can be removed.
Assignments are relations of users to a PRG; They hold progress-information for (sub-)nodes of the PR...
getAutomaticMembershipSources()
Get sources for auto-memberships.
getDepth()
Get the depth of this StudyProgramme in the tree starting at the topmost StudyProgramme (not root nod...
hasChildren(bool $include_references=false)
Does this StudyProgramme have other ilObjStudyProgrammes as children?
ilStudyProgrammeAutoCategoryDBRepository $auto_categories_repository
putInTree(int $parent_ref_id)
Overwritten from ilObject.
ilObjectFactoryWrapper $object_factory
static _getInstance(int $a_obj_id)
static _lookupTargetRefId(int $a_obj_id)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
getLPChildrenIds()
Get the obj-ids of the leafs the program contains.
static _lookupTargetId(int $a_obj_id)
$dic
Definition: result.php:32
static createInstance()
Create an instance of ilObjStudyProgramme, put in cache.
static getRefIdFor(int $obj_id)
deleteAutomaticContentCategories(array $category_ids=[])
Delete configuration of categories with auto-content for this StudyProgramme;.
getPoints()
Get the amount of points.
ilStudyProgrammeSettingsDBRepository $settings_repository
Assignments are relations of users to a PRG; They hold progress-information for (sub-)nodes of the PR...
static _lookupType(int $id, bool $reference=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getAmountOfChildren($include_references=false)
Get the amount of other StudyProgrammes this StudyProgramme has as children.
refreshLPStatus(int $usr_id, int $node_obj_id=null)
getAmountOfAssignmentsOf(int $user_id)
Get the amount of assignments a user has on this program node or any node above.
ilObjectCustomIconFactory $custom_icon_factory
static _lookupDeletedDate(int $ref_id)
deleteAllAutomaticMembershipSources()
Delete all membership sources of this StudyProgramme;.
updateLastChange()
Update last change timestamp on this node and its parents.
ilCertificateTemplateRepository $certificate_template_repository
clearParentCache()
Clear the cached parent to query it again at the tree.
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
deleteAutomaticMembershipSource(string $type, int $src_id)
Delete a membership source.
Holds information about multi-actions, mainly in context of member-assignemnts and status changes...
ilStudyProgrammeTypeDBRepository $type_repository
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
updateSettings(ilStudyProgrammeSettings $settings)