ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 
5 require_once("./Modules/StudyProgramme/classes/model/class.ilStudyProgrammeProgress.php");
6 
16 {
17  protected $progress; // ilStudyProgrammeProgress
18 
28  public function __construct($a_ids_or_model)
29  {
30  if ($a_ids_or_model instanceof ilStudyProgrammeProgress) {
31  $this->progress = $a_ids_or_model;
32  } else {
33  if (count($a_ids_or_model) != 3) {
34  throw new ilException("ilStudyProgrammeUserProgress::__construct: "
35  . "expected array with 3 items.");
36  }
37 
38  // TODO: ActiveRecord won't be caching the model objects, since
39  // we are not using find. Maybe we should do this ourselves??
40  // Or should we instead cache in getInstance?
41  $this->progress = array_shift(
42  ilStudyProgrammeProgress::where(array( "assignment_id" => $a_ids_or_model[0]
43  , "prg_id" => $a_ids_or_model[1]
44  , "usr_id" => $a_ids_or_model[2]
45  ))->get()
46  );
47  }
48  if ($this->progress === null) {
49  throw new ilException("ilStudyProgrammeUserProgress::__construct: Could not find progress.");
50  }
51  }
52 
63  public function getStudyProgramme()
64  {
65  require_once("./Modules/StudyProgramme/classes/class.ilObjStudyProgramme.php");
66  $refs = ilObject::_getAllReferences($this->progress->getNodeId());
67  if (!count($refs)) {
68  throw new ilException("ilStudyProgrammeUserAssignment::getStudyProgramme: "
69  . "could not find ref_id for program '"
70  . $this->progress->getNodeId() . "'.");
71  }
72  return ilObjStudyProgramme::getInstanceByRefId(array_shift($refs));
73  }
74 
80  public function getAssignment()
81  {
82  require_once("Modules/StudyProgramme/classes/class.ilStudyProgrammeUserAssignment.php");
83  return ilStudyProgrammeUserAssignment::getInstance($this->progress->getAssignmentId());
84  }
85 
91  public function getId()
92  {
93  return $this->progress->getId();
94  }
95 
101  public function getNodeId()
102  {
103  return $this->progress->getNodeId();
104  }
105 
111  public function getUserId()
112  {
113  return $this->progress->getUserId();
114  }
115 
121  public function getStatus()
122  {
123  return $this->progress->getStatus();
124  }
125 
132  public function getAmountOfPoints()
133  {
134  return $this->progress->getAmountOfPoints();
135  }
136 
142  public function getCurrentAmountOfPoints()
143  {
144  if ($this->isAccredited()
145  || ($this->isSuccessful() && $this->getStudyProgramme()->hasLPChildren())) {
146  return $this->getAmountOfPoints();
147  }
148  return $this->progress->getCurrentAmountOfPoints();
149  }
150 
156  public function getLastChange()
157  {
158  return $this->progress->getLastChange();
159  }
160 
166  public function getLastChangeBy()
167  {
168  return $this->progress->getLastChangeBy();
169  }
170 
176  public function getCompletionBy()
177  {
178  return $this->progress->getCompletionBy();
179  }
180 
186  public function getDeadline()
187  {
188  return $this->progress->getDeadline();
189  }
190 
196  public function setDeadline($deadline)
197  {
198  return $this->progress->setDeadline($deadline);
199  }
200 
204  public function delete()
205  {
206  $this->progress->delete();
207  }
208 
209 
220  public function markAccredited($a_user_id)
221  {
223  $prg = $this->getStudyProgramme();
224  if ($prg->getStatus() == ilStudyProgramme::STATUS_OUTDATED) {
225  throw new ilException("ilStudyProgrammeUserProgress::markAccredited: "
226  . "Can't mark as accredited since program is outdated.");
227  }
228  }
229 
230  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_ACCREDITED)
231  ->setCompletionBy($a_user_id)
232  ->update();
233 
234  require_once("Modules/StudyProgramme/classes/class.ilStudyProgrammeEvents.php");
236 
237  $this->updateParentStatus();
238  return $this;
239  }
240 
249  public function unmarkAccredited()
250  {
251  if ($this->progress->getStatus() != ilStudyProgrammeProgress::STATUS_ACCREDITED) {
252  throw new ilException("Expected status ACCREDITED.");
253  }
254 
255  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_IN_PROGRESS)
256  ->setCompletionBy(null)
257  ->update();
258 
259  $this->refreshLPStatus();
260 
261  $this->updateParentStatus();
262  return $this;
263  }
264 
274  public function markFailed($a_user_id)
275  {
279  );
280 
281  if (in_array($this->getStatus(), $status)) {
282  throw new ilException("Can't mark as failed since program is passed.");
283  }
284 
285  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_FAILED)
286  ->setLastChangeBy($a_user_id)
287  ->update();
288 
289  $this->refreshLPStatus();
290 
291  return $this;
292  }
293 
302  public function markNotFailed()
303  {
304  if ($this->progress->getStatus() != ilStudyProgrammeProgress::STATUS_FAILED) {
305  throw new ilException("Expected status FAILED.");
306  }
307 
308  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_IN_PROGRESS)
309  ->setCompletionBy(null)
310  ->setLastChangeBy($a_user_id)
311  ->update();
312 
313  $this->refreshLPStatus();
314 
315  return $this;
316  }
317 
327  public function markNotRelevant($a_user_id)
328  {
329  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_NOT_RELEVANT)
330  ->setCompletionBy($a_user_id)
331  ->setLastChangeBy($a_user_id)
332  ->update();
333 
334  $this->updateStatus();
335  return $this;
336  }
337 
347  public function markRelevant($a_user_id)
348  {
349  if ($this->progress->getStatus() != ilStudyProgrammeProgress::STATUS_NOT_RELEVANT) {
350  throw new ilException("Expected status IN_PROGRESS.");
351  }
352 
353  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_IN_PROGRESS)
354  ->setCompletionBy($a_user_id)
355  ->setLastChangeBy($a_user_id)
356  ->update();
357 
358  $this->updateStatus();
359  return $this;
360  }
361 
372  public function setRequiredAmountOfPoints($a_points, $a_user_id)
373  {
374  $this->progress->setAmountOfPoints($a_points)
375  ->setLastChangeBy($a_user_id)
376  ->update();
377 
378  $this->updateStatus();
379  return $this;
380  }
381 
394  public function getMaximumPossibleAmountOfPoints($only_relevant = false)
395  {
396  $prg = $this->getStudyProgramme();
397  if ($prg->getLPMode() == ilStudyProgramme::MODE_LP_COMPLETED) {
398  return $this->getAmountOfPoints();
399  }
400  $children = $prg->getChildren();
401  $ass = $this->progress->getAssignmentId();
402  $points = array_map(function ($child) use ($ass, $only_relevant) {
403  $relevant = $child->getProgressForAssignment($ass)->isRelevant();
404  if ($only_relevant) {
405  if ($relevant) {
406  return $child->getProgressForAssignment($ass)->getAmountOfPoints();
407  } else {
408  return 0;
409  }
410  } else {
411  return $child->getProgressForAssignment($ass)->getAmountOfPoints();
412  }
413  }, $children);
414 
415  return array_reduce($points, function ($a, $b) {
416  return $a + $b;
417  }, 0);
418  }
419 
426  public function canBeCompleted()
427  {
428  $prg = $this->getStudyProgramme();
429 
430  if ($prg->getLPMode() == ilStudyProgramme::MODE_LP_COMPLETED) {
431  return true;
432  }
433 
434  if ($this->getMaximumPossibleAmountOfPoints(true) < $this->getAmountOfPoints()) {
435  // Fast track
436  return false;
437  }
438 
439  $children_progress = $this->getChildrenProgress();
440  foreach ($children_progress as $progress) {
441  if ($progress->isRelevant() && !$progress->canBeCompleted()) {
442  return false;
443  }
444  }
445  return true;
446  }
447 
453  public function hasIndividualModifications()
454  {
455  return $this->getLastChangeBy() !== null;
456  }
457 
464  public function isSuccessful()
465  {
466  $status = $this->getStatus();
467 
470  }
471 
477  public function isFailed()
478  {
479  $status = $this->getStatus();
480 
481  return $status == ilStudyProgrammeProgress::STATUS_FAILED;
482  }
483 
489  public function recalculateFailedToDeadline()
490  {
491  $deadline = $this->getDeadline();
492  $today = date("Y-m-d");
493 
494  if ($deadline && $deadline->get(IL_CAL_DATE) < $today) {
495  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_FAILED)
496  ->update();
497  }
498  }
499 
505  public function isAccredited()
506  {
507  $status = $this->getStatus();
508 
510  }
511 
517  public function isRelevant()
518  {
520  }
521 
529  public function updateFromProgramNode()
530  {
531  if ($this->hasIndividualModifications()) {
532  return false;
533  }
535  return false;
536  }
537 
538  $prg = $this->getStudyProgramme();
539  $this->progress->setAmountOfPoints($prg->getPoints())
540  ->setStatus(
541  $prg->getStatus() == ilStudyProgramme::STATUS_ACTIVE
544  )
545  ->update();
546 
547  $this->updateStatus();
548  }
549 
554  protected function updateStatus()
555  {
556  $prg = $this->getStudyProgramme();
557  if (($prg->getLPMode() == ilStudyProgramme::MODE_LP_COMPLETED
560  // Nothing to do here, as the status will be set by LP.
561  // OR current status is NOT RELEVANT
562  return;
563  }
564 
565  $add = function ($a, $b) {
566  return $a + $b;
567  };
568  $get_points = function ($child) {
569  if (!$child->isSuccessful()) {
570  return 0;
571  }
572  return $child->getAmountOfPoints();
573  };
574 
575  $achieved_points = array_reduce(array_map($get_points, $this->getChildrenProgress()), $add);
576  if (!$achieved_points) {
577  $achieved_points = 0;
578  }
579  $successful = $achieved_points >= $this->getAmountOfPoints() && $this->hasSuccessfullChildren();
580  $status = $this->getStatus();
581 
582  $this->progress->setCurrentAmountOfPoints($achieved_points);
583  if ($successful) {
584  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_COMPLETED);
585  require_once("Modules/StudyProgramme/classes/class.ilStudyProgrammeEvents.php");
587  } else {
588  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_IN_PROGRESS);
589  }
590 
591  $this->progress->update();
592  $this->refreshLPStatus();
593  $this->updateParentStatus();
594  }
595 
596  protected function hasSuccessfullChildren()
597  {
598  foreach ($this->getChildrenProgress() as $child) {
599  if ($child->isSuccessful()) {
600  return true;
601  }
602  }
603  return false;
604  }
605 
609  protected function updateParentStatus()
610  {
611  $parent = $this->getParentProgress();
612  if ($parent) {
613  $parent->updateStatus();
614  }
615  }
616 
627  public function setLPCompleted($a_obj_id, $a_usr_id)
628  {
629  if ($this->isSuccessful() || !$this->isRelevant()) {
630  return true;
631  }
632 
633  $prg = $this->getStudyProgramme();
634  if ($prg->getLPMode() != ilStudyProgramme::MODE_LP_COMPLETED) {
635  throw new ilException("ilStudyProgrammeUserProgress::setLPCompleted: "
636  . "The node '" . $prg->getId() . "' is not in LP_COMPLETED mode.");
637  }
638  if ($this->getUserId() != $a_usr_id) {
639  throw new ilException("ilStudyProgrammeUserProgress::setLPCompleted: "
640  . "This progress does belong to user '" . $this->getUserId()
641  . "' and not to user '$a_usr_id'");
642  }
643  if (!in_array($a_obj_id, $prg->getLPChildrenIds())) {
644  throw new ilException("ilStudyProgrammeUserProgress::setLPCompleted: "
645  . "Object '$a_obj_id' is no child of node '" . $prg->getId() . "'.");
646  }
647 
648  $this->progress->setStatus(ilStudyProgrammeProgress::STATUS_COMPLETED)
649  ->setCompletionBy($a_obj_id)
650  ->update();
651 
652  require_once("Modules/StudyProgramme/classes/class.ilStudyProgrammeEvents.php");
654 
655  $this->refreshLPStatus();
656  $this->updateParentStatus();
657  }
658 
663  protected function getParentProgress()
664  {
665  $prg = $this->getStudyProgramme();
666  $parent = $prg->getParent();
667  if (!$parent) {
668  return null;
669  }
670 
671  if ($this->getStudyProgramme()->getId() == $this->getAssignment()->getStudyProgramme()->getId()) {
672  return null;
673  }
674 
675  return $parent->getProgressForAssignment($this->progress->getAssignmentId());
676  }
677 
684  public function getChildrenProgress()
685  {
686  $prg = $this->getStudyProgramme();
687  if ($prg->getLPMode() == ilStudyProgramme::MODE_LP_COMPLETED) {
688  throw new ilException("ilStudyProgrammeUserProgress::getChildrenProgress: "
689  . "There is some problem in the implementation. This "
690  . "method should only be callled for nodes in points "
691  . "mode.");
692  }
693 
694  $ass_id = $this->progress->getAssignmentId();
695  return array_map(function ($child) use ($ass_id) {
696  return $child->getProgressForAssignment($ass_id);
697  }, $prg->getChildren());
698  }
699 
708  {
709  $prg = $this->getStudyProgramme();
710  $children = $prg->getChildren();
711  $ass_id = $this->progress->getAssignmentId();
712  $names = array();
713  foreach ($children as $child) {
714  $prgrs = $child->getProgressForAssignment($ass_id);
715  if (!$prgrs->isSuccessful()) {
716  continue;
717  }
718  $names[] = $child->getTitle();
719  }
720  return $names;
721  }
722 
723  const ACTION_MARK_ACCREDITED = "mark_accredited";
724  const ACTION_UNMARK_ACCREDITED = "unmark_accredited";
725  const ACTION_SHOW_INDIVIDUAL_PLAN = "show_individual_plan";
726  const ACTION_REMOVE_USER = "remove_user";
734  public static function getPossibleActions($a_node_id, $a_root_prg_id, $a_status)
735  {
736  $actions = array();
737  if ($a_node_id == $a_root_prg_id) {
738  $actions[] = self::ACTION_SHOW_INDIVIDUAL_PLAN;
739  $actions[] = self::ACTION_REMOVE_USER;
740  }
742  $actions[] = self::ACTION_UNMARK_ACCREDITED;
743  } elseif ($a_status == ilStudyProgrammeProgress::STATUS_IN_PROGRESS) {
744  $actions[] = self::ACTION_MARK_ACCREDITED;
745  }
746  return $actions;
747  }
748 
749  protected function refreshLPStatus()
750  {
751  require_once("Services/Tracking/classes/class.ilLPStatusWrapper.php");
753  }
754 
762  public function updateProgress($user_id)
763  {
764  $this->progress->setLastChangeBy($user_id)
765  ->update();
766  }
767 }
getChildrenProgress()
Get the progresses on the child nodes of this node for the same assignment this progress belongs to...
static userSuccessful(ilStudyProgrammeUserProgress $a_progress)
getCurrentAmountOfPoints()
Get the amount of points the user currently achieved.
isRelevant()
Check whether this node is relevant for the user.
updateParentStatus()
Update the status of the parent of this node.
setRequiredAmountOfPoints($a_points, $a_user_id)
Set the amount of points the user is required to have to complete this node.
getStudyProgramme()
Get the program node where this progress belongs to was made.
unmarkAccredited()
Set the node to in progress.
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.
recalculateFailedToDeadline()
Recalculates the status according to deadline.
static where($where, $operator=null)
getAssignment()
Get the assignment this progress belongs to.
getParentProgress()
Get the progress on the parent node for the same assignment this progress belongs to...
static _getAllReferences($a_id)
get all reference ids of object
static getInstanceByRefId($a_ref_id)
Get an instance of ilObjStudyProgramme, use cache.
canBeCompleted()
Check whether the user can achieve enough points on the subnodes to be able to complete this node...
markNotRelevant($a_user_id)
Set the node to be not relevant for the user.
markAccredited($a_user_id)
Mark this progress as accredited.
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.
static getPossibleActions($a_node_id, $a_root_prg_id, $a_status)
Get a list with possible actions on a progress record.
markNotFailed()
Set the node to in progress.
getUserId()
Get the id of the user who is assigned.
isFailed()
Check wether 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.
markFailed($a_user_id)
Mark this progress as failed.
Class ilStudyProgrammeProgress.
update($pash, $contents, Config $config)
getLastChangeBy()
Get the id of the user who did the last change on this progress.
const IL_CAL_DATE
setLPCompleted($a_obj_id, $a_usr_id)
Set this node to be completed due to a completed learning progress.
updateProgress($user_id)
Updates current progress.
updateStatus()
Updates the status of this progress based on the status of the progress on the sub nodes...
getMaximumPossibleAmountOfPoints($only_relevant=false)
Get the maximum possible amount of points a user can achieve for the completion of this node...
markRelevant($a_user_id)
Set the node to be relevant for the user.
updateFromProgramNode()
Update the progress from its program node.
getDeadline()
Get the deadline of this node.
getCompletionBy()
Get the id of the user or course that lead to completion of this node.
setDeadline($deadline)
Set the deadline of this node.
__construct($a_ids_or_model)
Throws when id does not refer to a study programme progress.
Represents the progress of a user at one node of a study programme.