ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilStudyProgrammeUserProgress.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 2015 Richard Klees <richard.klees@concepts-and-training.de> Extended GPL, see docs/LICENSE */
4 /* Copyright (c) 2019 Stefan Hecken <stefan.hecken@concepts-and-training.de> Extended GPL, see docs/LICENSE */
5 
6 declare(strict_types=1);
7 
15 {
16  const ACTION_MARK_ACCREDITED = "mark_accredited";
17  const ACTION_UNMARK_ACCREDITED = "unmark_accredited";
18  const ACTION_SHOW_INDIVIDUAL_PLAN = "show_individual_plan";
19  const ACTION_REMOVE_USER = "remove_user";
20  const ACTION_CHANGE_EXPIRE_DATE = "change_expire_date";
21  const ACTION_CHANGE_DEADLINE = "change_deadline";
22 
26  protected $progress;
27 
32 
37 
41  protected $events;
42 
43  public function __construct(
48  ) {
49  $this->progress = $progress;
50  $this->progress_repository = $progress_repository;
51  $this->assignment_repository = $assignment_repository;
52  $this->events = $events;
53  }
54 
65  {
66  $refs = ilObject::_getAllReferences($this->progress->getNodeId());
67  if (!count($refs)) {
68  throw new ilException(
69  "ilStudyProgrammeUserAssignment::getStudyProgramme: "
70  . "could not find ref_id for program '"
71  . $this->progress->getNodeId() . "'."
72  )
73  ;
74  }
75  return ilObjStudyProgramme::getInstanceByRefId(array_shift($refs));
76  }
77 
81  public function getAssignmentId() : int
82  {
83  return $this->progress->getAssignmentId();
84  }
85 
89  public function getId() : int
90  {
91  return $this->progress->getId();
92  }
93 
97  public function getNodeId() : int
98  {
99  return $this->progress->getNodeId();
100  }
101 
105  public function getUserId() : int
106  {
107  return $this->progress->getUserId();
108  }
109 
113  public function getStatus() : int
114  {
115  return $this->progress->getStatus();
116  }
117 
122  public function getAmountOfPoints() : int
123  {
124  return $this->progress->getAmountOfPoints();
125  }
126 
130  public function getCurrentAmountOfPoints() : int
131  {
132  if (
133  $this->isAccredited() ||
134  ($this->isSuccessful() && $this->getStudyProgramme()->hasLPChildren())
135  ) {
136  return $this->getAmountOfPoints();
137  }
138 
139  return $this->progress->getCurrentAmountOfPoints();
140  }
141 
145  public function getLastChange() : DateTime
146  {
147  return $this->progress->getLastChange();
148  }
149 
153  public function getLastChangeBy() : ?int
154  {
155  return $this->progress->getLastChangeBy();
156  }
157 
161  public function getCompletionBy()
162  {
163  return $this->progress->getCompletionBy();
164  }
165 
169  public function getAssignmentDate() : DateTime
170  {
171  return $this->progress->getAssignmentDate();
172  }
173 
177  public function getCompletionDate() : ?DateTime
178  {
179  return $this->progress->getCompletionDate();
180  }
181 
185  public function getDeadline()
186  {
187  return $this->progress->getDeadline();
188  }
189 
193  public function setDeadline(DateTime $deadline = null) : ilStudyProgrammeProgress
194  {
195  return $this->progress->setDeadline($deadline);
196  }
197 
204  {
205  return $this->progress->getValidityOfQualification();
206  }
207 
211  public function setValidityOfQualification(DateTime $date = null) : void
212  {
213  $this->progress->setValidityOfQualification($date);
214  }
215 
216  public function storeProgress() : void
217  {
218  $this->progress_repository->update($this->progress);
219  }
220 
224  public function delete() : void
225  {
226  $this->progress_repository->delete($this->progress);
227  }
228 
229 
238  public function markAccredited(int $user_id) : ilStudyProgrammeUserProgress
239  {
240  $prg = $this->getStudyProgramme();
242  if ($prg->getStatus() == ilStudyProgrammeSettings::STATUS_OUTDATED) {
243  throw new ilException(
244  "ilStudyProgrammeUserProgress::markAccredited: "
245  . "Can't mark as accredited since program is outdated."
246  );
247  }
248  }
249  $progress = $this->progress
251  ->setCompletionBy($user_id)
252  ->setLastChangeBy($user_id)
253  ->setLastChange(new DateTime())
254  ->setCompletionDate(new DateTime())
255  ;
256 
257  $this->progress_repository->update($progress);
258 
259  $assignment = $this->assignment_repository->read($this->getAssignmentId());
260  if ((int) $prg->getId() === $assignment->getRootId()) {
261  $this->maybeLimitProgressValidity($prg, $assignment);
262  }
263 
264  $this->events->userSuccessful($this);
265  $this->updateParentStatus();
266 
267  return $this;
268  }
269 
278  {
279  if ($this->progress->getStatus() != ilStudyProgrammeProgress::STATUS_ACCREDITED) {
280  throw new ilException("Expected status ACCREDITED.");
281  }
282 
283  $this->progress_repository->update(
284  $this->progress
286  ->setCompletionBy(null)
287  ->setCompletionDate(null)
288  );
289 
290  $this->refreshLPStatus();
291  $this->updateParentStatus();
292 
293  return $this;
294  }
295 
303  public function markFailed(int $a_user_id) : ilStudyProgrammeUserProgress
304  {
305  $status = array(
309  );
310 
311  if (in_array($this->getStatus(), $status)) {
312  throw new ilException("Can't mark as failed since program is passed.");
313  }
314 
315  $this->progress
317  ->setLastChangeBy($a_user_id)
318  ->setCompletionDate(null);
319 
320  $this->progress_repository->update($this->progress);
321  $this->refreshLPStatus();
322 
323  return $this;
324  }
325 
334  {
335  $status = array(
339  );
340 
341  if (in_array($this->getStatus(), $status) && !$this->isSuccessfulExpired()) {
342  throw new ilException("Can't mark as failed since program is passed.");
343  }
344 
345  $this->progress_repository->update(
346  $this->progress->invalidate()
347  );
348 
349  $this->refreshLPStatus();
350 
351  return $this;
352  }
353 
354  public function isInvalidated() : bool
355  {
356  return $this->progress->isInvalidated();
357  }
358 
362  public function isSuccessfulExpired() : bool
363  {
364  if ($this->getValidityOfQualification() === null) {
365  return false;
366  }
367 
368  if (!$this->isSuccessful()) {
369  return false;
370  }
371 
372  if (
373  $this->getValidityOfQualification()->format('Y-m-d') < (new DateTime())->format('Y-m-d')
374  ) {
375  return true;
376  }
377 
378  return false;
379  }
380 
388  public function markNotFailed(int $user_id) : ilStudyProgrammeUserProgress
389  {
390  if ($this->progress->getStatus() != ilStudyProgrammeProgress::STATUS_FAILED) {
391  throw new ilException("Expected status FAILED.");
392  }
393 
394  $this->progress_repository->update(
395  $this->progress
397  ->setCompletionBy(null)
398  ->setLastChangeBy($user_id)
399  );
400 
401  $this->refreshLPStatus();
402 
403  return $this;
404  }
405 
415  public function markNotRelevant(int $user_id) : ilStudyProgrammeUserProgress
416  {
417  $this->progress_repository->update(
418  $this->progress
420  ->setCompletionBy($user_id)
421  ->setLastChangeBy($user_id)
422  );
423 
424  $this->updateStatus();
425 
426  return $this;
427  }
428 
436  public function markRelevant(int $user_id) : ilStudyProgrammeUserProgress
437  {
438  if ($this->progress->getStatus() != ilStudyProgrammeProgress::STATUS_NOT_RELEVANT) {
439  throw new ilException("Expected status IN_PROGRESS.");
440  }
441 
442  $this->progress_repository->update(
443  $this->progress
445  ->setCompletionBy($user_id)
446  ->setLastChangeBy($user_id)
447  );
448 
449  $this->updateStatus();
450 
451  return $this;
452  }
453 
461  public function setRequiredAmountOfPoints(
462  int $a_points,
463  int $user_id
465  $this->progress_repository->update(
466  $this->progress
467  ->setAmountOfPoints($a_points)
468  ->setLastChangeBy($user_id)
469  );
470 
471  $this->updateStatus();
472 
473  return $this;
474  }
475 
486  public function getMaximumPossibleAmountOfPoints(bool $only_relevant = false) : int
487  {
488  $prg = $this->getStudyProgramme();
489  if ($prg->getLPMode() == ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
490  return $this->getAmountOfPoints();
491  }
492 
493  $children = $prg->getChildren();
494  $ass = $this->progress->getAssignmentId();
495  $points = array_map(function ($child) use ($ass, $only_relevant) {
496  $relevant = $child->getProgressForAssignment($ass)->isRelevant();
497  if ($only_relevant) {
498  if ($relevant) {
499  return $child->getProgressForAssignment($ass)->getAmountOfPoints();
500  } else {
501  return 0;
502  }
503  } else {
504  return $child->getProgressForAssignment($ass)->getAmountOfPoints();
505  }
506  }, $children);
507 
508  return array_reduce($points, function ($a, $b) {
509  return $a + $b;
510  }, 0);
511  }
512 
519  public function canBeCompleted() : bool
520  {
521  $prg = $this->getStudyProgramme();
522 
523  if ($prg->getLPMode() == ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
524  return true;
525  }
526 
527  if ($this->getMaximumPossibleAmountOfPoints(true) < $this->getAmountOfPoints()) {
528  // Fast track
529  return false;
530  }
531 
532  $children_progress = $this->getChildrenProgress();
533  foreach ($children_progress as $progress) {
534  if ($progress->isRelevant() && !$progress->canBeCompleted()) {
535  return false;
536  }
537  }
538 
539  return true;
540  }
541 
545  public function hasIndividualModifications() : bool
546  {
547  return $this->getLastChangeBy() !== null;
548  }
549 
554  public function isSuccessful() : bool
555  {
556  $status = $this->getStatus();
557 
558  return
561  ;
562  }
563 
567  public function isFailed() : bool
568  {
569  $status = $this->getStatus();
570 
571  return $status == ilStudyProgrammeProgress::STATUS_FAILED;
572  }
573 
579  public function recalculateFailedToDeadline() : void
580  {
581  $deadline = $this->getDeadline();
583 
584  if ($deadline
585  && $deadline->format(ilStudyProgrammeProgress::DATE_FORMAT) < $today
586  && $this->progress->getStatus() === ilStudyProgrammeProgress::STATUS_IN_PROGRESS
587  ) {
588  $this->progress_repository->update(
589  $this->progress
591  );
592  }
593  }
594 
598  public function isAccredited() : bool
599  {
601  }
602 
606  public function isRelevant() : bool
607  {
609  }
610 
619  public function updateFromProgramNode()
620  {
621  if ($this->hasIndividualModifications()) {
622  return false;
623  }
624 
626  return false;
627  }
628 
629  $prg = $this->getStudyProgramme();
630 
632  if ($prg->getStatus() == ilStudyProgrammeSettings::STATUS_ACTIVE) {
634  }
635 
636  $this->progress_repository->update(
637  $this->progress
638  ->setAmountOfPoints($prg->getPoints())
639  ->setStatus($status)
640  );
641 
642  $this->updateStatus();
643  }
644 
652  protected function updateStatus()
653  {
654  $prg = $this->getStudyProgramme();
655  if (
656  ($prg->getLPMode() == ilStudyProgrammeSettings::MODE_LP_COMPLETED &&
659  ) {
660  // Nothing to do here, as the status will be set by LP.
661  // OR current status is NOT RELEVANT
662  return;
663  }
664 
665  $add = function ($a, $b) {
666  return $a + $b;
667  };
668  $get_points = function ($child) {
669  if (!$child->isSuccessful()) {
670  return 0;
671  }
672  return $child->getAmountOfPoints();
673  };
674 
675  $achieved_points = array_reduce(array_map($get_points, $this->getChildrenProgress()), $add);
676  if (!$achieved_points) {
677  $achieved_points = 0;
678  }
679 
680  $successful = $achieved_points >= $this->getAmountOfPoints() && $this->hasSuccessfullChildren();
681  $this->progress->setCurrentAmountOfPoints($achieved_points);
682 
683  if ($successful) {
684  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_COMPLETED);
685  if (!$this->progress->getCompletionDate()) {
686  $this->progress->setCompletionDate(new DateTime());
687  }
688 
689  $assignment = $this->assignment_repository->read($this->getAssignmentId());
690  if ((int) $prg->getId() === $assignment->getRootId()) {
691  $this->maybeLimitProgressValidity($prg, $assignment);
692  }
693  $this->events->userSuccessful($this);
694  } else {
695  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_IN_PROGRESS);
696  $this->progress->setCompletionDate(null);
697  }
698 
699  $this->progress_repository->update(
700  $this->progress
701  );
702 
703  $this->refreshLPStatus();
704  $this->updateParentStatus();
705  }
706 
710  protected function hasSuccessfullChildren() : bool
711  {
712  foreach ($this->getChildrenProgress() as $child) {
713  if ($child->isSuccessful()) {
714  return true;
715  }
716  }
717 
718  return false;
719  }
720 
724  protected function updateParentStatus() : void
725  {
726  foreach ($this->getParentProgresses() as $parent) {
727  $parent->updateStatus();
728  }
729  }
730 
742  public function setLPCompleted(int $obj_id, int $usr_id)
743  {
744  if ($this->isSuccessful() || !$this->isRelevant()) {
745  return true;
746  }
747 
748  $prg = $this->getStudyProgramme();
749  if ($prg->getLPMode() != ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
750  throw new ilException(
751  "ilStudyProgrammeUserProgress::setLPCompleted: "
752  . "The node '" . $prg->getId() . "' is not in LP_COMPLETED mode."
753  );
754  }
755 
756  if ($this->getUserId() != $usr_id) {
757  throw new ilException(
758  "ilStudyProgrammeUserProgress::setLPCompleted: "
759  . "This progress does belong to user '" . $this->getUserId()
760  . "' and not to user '$usr_id'"
761  );
762  }
763 
764  if (!in_array($obj_id, $prg->getLPChildrenIds())) {
765  throw new ilException(
766  "ilStudyProgrammeUserProgress::setLPCompleted: "
767  . "Object '$obj_id' is no child of node '" . $prg->getId() . "'."
768  );
769  }
770 
771  $this->progress_repository->update(
772  $this->progress
774  ->setCompletionBy($obj_id)
775  ->setCompletionDate(new DateTime())
776  );
777 
778  $this->refreshLPStatus();
779 
780  $assignment = $this->assignment_repository->read($this->getAssignmentId());
781  if ((int) $prg->getId() === $assignment->getRootId()) {
782  $this->maybeLimitProgressValidity($prg, $assignment);
783  }
784 
785  $this->events->userSuccessful($this);
786  $this->updateParentStatus();
787  }
788 
792  protected function maybeLimitProgressValidity(
793  ilObjStudyProgramme $prg,
794  ilStudyProgrammeAssignment $assignment
795  ) : void {
796  $qualification_date = $prg->getValidityOfQualificationSettings()->getQualificationDate();
797  $qualification_period = $prg->getValidityOfQualificationSettings()->getQualificationPeriod();
798  if (!is_null($qualification_date)) {
799  $date = $qualification_date;
800  } elseif (
802  ) {
803  $date = new DateTime();
804  $date->add(new DateInterval('P' . $qualification_period . 'D'));
805  } else {
806  // nothing to do
807  return;
808  }
809 
810  $this->progress_repository->update($this->progress->setValidityOfQualification($date));
811 
812  $restart_period = $prg->getValidityOfQualificationSettings()->getRestartPeriod();
813  if (ilStudyProgrammeSettings::NO_RESTART !== $restart_period) {
814  $date->sub(new DateInterval('P' . $restart_period . 'D'));
815  $this->assignment_repository->update($assignment->setRestartDate($date));
816  }
817  }
818 
826  protected function getParentProgresses() : array
827  {
828  if ($this->getStudyProgramme()->getId() == $this->assignment_repository->read($this->getAssignmentId())->getRootId()) {
829  return [];
830  }
831 
832  $overall_parents = [];
833  $prg = $this->getStudyProgramme();
834  $parent = $prg->getParent();
835 
836  if ($parent) {
837  $overall_parents[] = $parent;
838  }
839 
840  foreach ($prg->getReferencesToSelf() as $ref) {
841  $overall_parents[] = $ref->getParent();
842  }
843 
844  return array_map(
845  function ($parent) {
846  return $parent->getProgressForAssignment($this->progress->getAssignmentId());
847  },
848  $overall_parents
849  );
850  }
851 
859  public function getChildrenProgress() : array
860  {
861  $prg = $this->getStudyProgramme();
862  if ($prg->getLPMode() == ilStudyProgrammeSettings::MODE_LP_COMPLETED) {
863  throw new ilException(
864  "ilStudyProgrammeUserProgress::getChildrenProgress: "
865  . "There is some problem in the implementation. This "
866  . "method should only be callled for nodes in points "
867  . "mode."
868  );
869  }
870 
871  $ass_id = $this->progress->getAssignmentId();
872 
873  return array_map(function ($child) use ($ass_id) {
874  return $child->getProgressForAssignment($ass_id);
875  }, $prg->getChildren(true));
876  }
877 
885  public function getNamesOfCompletedOrAccreditedChildren() : array
886  {
887  $prg = $this->getStudyProgramme();
888  $children = $prg->getChildren(true);
889  $ass_id = $this->progress->getAssignmentId();
890  $names = array();
891 
892  foreach ($children as $child) {
893  $prgrs = $child->getProgressForAssignment($ass_id);
894  if (!$prgrs->isSuccessful()) {
895  continue;
896  }
897  $names[] = $child->getTitle();
898  }
899 
900  return $names;
901  }
902 
908  public static function getPossibleActions(
909  int $node_id,
910  int $root_prg_id,
911  int $status
912  ) : array {
913  $actions = array();
914 
915  if ($node_id == $root_prg_id) {
916  $actions[] = self::ACTION_SHOW_INDIVIDUAL_PLAN;
917  $actions[] = self::ACTION_REMOVE_USER;
918  }
919 
921  $actions[] = self::ACTION_UNMARK_ACCREDITED;
922  } elseif ($status == ilStudyProgrammeProgress::STATUS_IN_PROGRESS) {
923  $actions[] = self::ACTION_MARK_ACCREDITED;
924  }
925 
926  return $actions;
927  }
928 
929  protected function refreshLPStatus() : void
930  {
931  // thanks to some caching within ilLPStatusWrapper
932  // the status may not be read properly otherwise ...
933  ilLPStatusWrapper::_resetInfoCaches($this->progress->getNodeId());
935  $this->getStudyProgramme()->getId(),
936  array($this->getUserId())
937  );
938  }
939 
945  public function updateProgress(int $user_id) : void
946  {
947  $this->progress_repository->update(
948  $this->progress->setLastChangeBy($user_id)
949  );
950  }
951 
952  public function informUserForRiskToFail() : void
953  {
954  $this->events->userRiskyToFail($this);
955  }
956 
960  public static function sendRiskyToFailMail(int $progress_id, int $usr_id) : void
961  {
962  global $DIC;
963  $lng = $DIC['lng'];
964  $log = $DIC['ilLog'];
965  $lng->loadLanguageModule("prg");
966  $lng->loadLanguageModule("mail");
967 
969  $usr_progress_db = ilStudyProgrammeDIC::dic()['ilStudyProgrammeUserProgressDB'];
971  $usr_progress = $usr_progress_db->getInstanceById($progress_id);
973  $prg = $usr_progress->getStudyProgramme();
974 
975  if (!$prg->shouldSendRiskyToFailMail()) {
976  $log->write("Send risky to fail mail is deactivated in study programme settings");
977  return;
978  }
979 
980  $subject = $lng->txt("risky_to_fail_mail_subject");
981  $gender = ilObjUser::_lookupGender($usr_id);
983  $body = sprintf(
984  $lng->txt("risky_to_fail_mail_body"),
985  $lng->txt("mail_salutation_" . $gender),
986  $name,
987  $prg->getTitle()
988  );
989 
990  $send = true;
991  $mail = new ilMail(ANONYMOUS_USER_ID);
992  try {
993  $mail->enqueue(
994  ilObjUser::_lookupLogin($usr_id),
995  '',
996  '',
997  $subject,
998  $body,
999  null
1000  );
1001  } catch (Exception $e) {
1002  $send = false;
1003  }
1004 
1005  if ($send) {
1006  $usr_progress_db->reminderSendFor($usr_progress->getId());
1007  }
1008  }
1009 
1010  public function hasSuccessStatus() : bool
1011  {
1012  return in_array(
1013  $this->getStatus(),
1014  [
1017  ]
1018  );
1019  }
1020 }
setDeadline(DateTime $deadline=null)
Set the deadline of this node.
isSuccessfulExpired()
Check, whether a the course is passed and expired due to limited validity.
static _lookupLogin($a_user_id)
lookup login
getChildrenProgress()
Get the progresses on the child nodes of this node for the same assignment this progress belongs to...
getCurrentAmountOfPoints()
Get the amount of points the user currently achieved.
isRelevant()
Check whether this node is relevant for the user.
markNotRelevant(int $user_id)
Set the node to be not relevant for the user.
setValidityOfQualification(DateTime $date=null)
Set validity of qualification.
static _lookupFullname($a_user_id)
Lookup Full Name.
updateProgress(int $user_id)
Updates current progress.
updateParentStatus()
Update the status of the parent of this node.
markNotFailed(int $user_id)
Set the node to in progress.
getStudyProgramme()
Get the program node this progress belongs to.
getAssignmentId()
Get the assignment this progress belongs to.
unmarkAccredited()
Set the node to in progress.
markRelevant(int $user_id)
Set the node to be relevant for the user.
invalidate()
Mark this progress as failed.
isSuccessful()
Check whether the user was successful on this node.
getStatus()
Get the status of the progress.
static _refreshStatus($a_obj_id, $a_users=null)
Set dirty.
getNodeId()
Get the id of the program node the progress belongs to.
isAccredited()
Check whether the user was accredited on this node.
static _lookupGender($a_user_id)
Lookup gender.
recalculateFailedToDeadline()
Recalculates the status according to deadline.
getAssignmentDate()
Get the assignment date of this node.
static _resetInfoCaches($a_obj_id)
static _getAllReferences($a_id)
get all reference ids of object
setLPCompleted(int $obj_id, int $usr_id)
Set this node to be completed due to a completed learning progress.
static getInstanceByRefId($a_ref_id)
canBeCompleted()
Check whether the user can achieve enough points on the subnodes to be able to complete this node...
if($format !==null) $name
Definition: metadata.php:230
getMaximumPossibleAmountOfPoints(bool $only_relevant=false)
Get the maximum possible amount of points a user can achieve for the completion of this node...
setDeadline(DateTime $deadline=null)
Set the deadline of this progress.
$lng
$log
Definition: result.php:15
getParentProgresses()
Get the progress on the parent node for the same assignment this progress belongs to...
getValidityOfQualification()
Get validity of qualification.
getNamesOfCompletedOrAccreditedChildren()
Get a list with the names of the children of this node that a were completed or accredited for the gi...
getLastChange()
Get the timestamp when the last change was made on this progress.
Class ilStudyProgrammeAssignment.
getUserId()
Get the id of the user who is assigned.
isFailed()
Check whether user as failed on this node.
getAmountOfPoints()
Get the amount of points needed to complete the node.
hasIndividualModifications()
Check whether there are individual modifications for the user on this program.
markAccredited(int $user_id)
Mark this progress as accredited.
Class ilStudyProgrammeProgress.
getLastChangeBy()
Get the id of the user who did the last change on this progress.
setRequiredAmountOfPoints(int $a_points, int $user_id)
Set the amount of points the user is required to have to complete this node.
static getPossibleActions(int $node_id, int $root_prg_id, int $status)
Get a list with possible actions on a progress record.
updateStatus()
Updates the status of this progress based on the status of the progress on the sub nodes...
Covers the persistence of settings belonging to a study programme (SP).
$DIC
Definition: xapitoken.php:46
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
getCompletionDate()
Get the completion date of this node.
maybeLimitProgressValidity(ilObjStudyProgramme $prg, ilStudyProgrammeAssignment $assignment)
updateFromProgramNode()
Update the progress from its program node.
getDeadline()
Get the deadline of this node.
markFailed(int $a_user_id)
Mark this progress as failed.
getCompletionBy()
Get the id of the user or course that lead to completion of this node.
__construct(ilStudyProgrammeProgress $progress, ilStudyProgrammeProgressRepository $progress_repository, ilStudyProgrammeAssignmentRepository $assignment_repository, ilStudyProgrammeEvents $events)
setRestartDate(DateTime $date=null)
Set the date, at which the user is to be reassigned to the programme.
Represents the progress of a user at one node of a study programme.