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
5require_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
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
482 }
483
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
558 && $this->getStatus() != ilStudyProgrammeProgress::STATUS_ACCREDITED)
559 || $this->getStatus() == ilStudyProgrammeProgress::STATUS_NOT_RELEVANT) {
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) {
739 $actions[] = self::ACTION_REMOVE_USER;
740 }
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}
static where($where, $operator=null)
An exception for terminatinating execution or to throw for unit testing.
const IL_CAL_DATE
Base class for ILIAS Exception handling.
static _refreshStatus($a_obj_id, $a_users=null)
Set dirty.
static getInstanceByRefId($a_ref_id)
Get an instance of ilObjStudyProgramme, use cache.
static _getAllReferences($a_id)
get all reference ids of object
static userSuccessful(ilStudyProgrammeUserProgress $a_progress)
Class ilStudyProgrammeProgress.
Represents the progress of a user at one node of a study programme.
markNotRelevant($a_user_id)
Set the node to be not relevant for the user.
getDeadline()
Get the deadline of this node.
getCompletionBy()
Get the id of the user or course that lead to completion of this node.
getChildrenProgress()
Get the progresses on the child nodes of this node for the same assignment this progress belongs to.
markRelevant($a_user_id)
Set the node to be relevant for the user.
isFailed()
Check wether user as failed on this node.
recalculateFailedToDeadline()
Recalculates the status according to deadline.
getMaximumPossibleAmountOfPoints($only_relevant=false)
Get the maximum possible amount of points a user can achieve for the completion of this node.
getStatus()
Get the status of the progress.
updateStatus()
Updates the status of this progress based on the status of the progress on the sub nodes.
getNamesOfCompletedOrAccreditedChildren()
Get a list with the names of the children of this node that a were completed or accredited for the gi...
__construct($a_ids_or_model)
Throws when id does not refer to a study programme progress.
canBeCompleted()
Check whether the user can achieve enough points on the subnodes to be able to complete this node.
getNodeId()
Get the id of the program node the progress belongs to.
isAccredited()
Check whether the user was accredited on this node.
unmarkAccredited()
Set the node to in progress.
isSuccessful()
Check whether the user was successful on this node.
setLPCompleted($a_obj_id, $a_usr_id)
Set this node to be completed due to a completed learning progress.
getCurrentAmountOfPoints()
Get the amount of points the user currently achieved.
static getPossibleActions($a_node_id, $a_root_prg_id, $a_status)
Get a list with possible actions on a progress record.
setRequiredAmountOfPoints($a_points, $a_user_id)
Set the amount of points the user is required to have to complete this node.
getAssignment()
Get the assignment this progress belongs to.
markFailed($a_user_id)
Mark this progress as failed.
updateParentStatus()
Update the status of the parent of this node.
getUserId()
Get the id of the user who is assigned.
getAmountOfPoints()
Get the amount of points needed to complete the node.
hasIndividualModifications()
Check whether there are individual modifications for the user on this program.
getStudyProgramme()
Get the program node where this progress belongs to was made.
getParentProgress()
Get the progress on the parent node for the same assignment this progress belongs to.
markAccredited($a_user_id)
Mark this progress as accredited.
updateFromProgramNode()
Update the progress from its program node.
updateProgress($user_id)
Updates current progress.
isRelevant()
Check whether this node is relevant for the user.
getLastChange()
Get the timestamp when the last change was made on this progress.
setDeadline($deadline)
Set the deadline of this node.
getLastChangeBy()
Get the id of the user who did the last change on this progress.