ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilLPStatusCollection.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=0);
4 /*
5  +-----------------------------------------------------------------------------+
6  | ILIAS open source |
7  +-----------------------------------------------------------------------------+
8  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
9  | |
10  | This program is free software; you can redistribute it and/or |
11  | modify it under the terms of the GNU General Public License |
12  | as published by the Free Software Foundation; either version 2 |
13  | of the License, or (at your option) any later version. |
14  | |
15  | This program is distributed in the hope that it will be useful, |
16  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18  | GNU General Public License for more details. |
19  | |
20  | You should have received a copy of the GNU General Public License |
21  | along with this program; if not, write to the Free Software |
22  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
23  +-----------------------------------------------------------------------------+
24 */
25 
31 {
32  private ilTree $tree;
33 
34  public function __construct(int $a_obj_id)
35  {
36  global $DIC;
37 
38  parent::__construct($a_obj_id);
39  $this->tree = $DIC->repositoryTree();
40  }
41 
42  public static function _getNotAttempted(int $a_obj_id): array
43  {
44  $users = array();
45 
46  $members = self::getMembers($a_obj_id);
47  if ($members) {
48  // diff in progress and completed (use stored result in LPStatusWrapper)
49  $users = array_diff(
50  (array) $members,
52  );
53  $users = array_diff(
54  $users,
56  );
57  $users = array_diff(
58  $users,
60  );
61  }
62 
63  return $users;
64  }
65 
66  public static function _getInProgress(int $a_obj_id): array
67  {
68  $users = ilChangeEvent::lookupUsersInProgress($a_obj_id);
69 
70  $olp = ilObjectLP::getInstance($a_obj_id);
71  $collection = $olp->getCollectionInstance();
72  if ($collection) {
73  foreach ($collection->getItems() as $item_id) {
74  $item_id = ilObject::_lookupObjId($item_id);
75 
76  // merge arrays of users with status 'in progress'
77  $users = array_unique(
78  array_merge(
79  $users,
81  )
82  );
83  $users = array_unique(
84  array_merge(
85  $users,
87  )
88  );
89  }
90  }
91 
92  // Exclude all users with status completed.
93  $users = array_diff(
94  $users,
96  );
97  // Exclude all users with status failed.
98  $users = array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id));
99 
100  if ($users) {
101  // Exclude all non members
102  $users = array_intersect(self::getMembers($a_obj_id), $users);
103  }
104 
105  return $users;
106  }
107 
112  public static function _getCompleted(int $a_obj_id): array
113  {
114  global $DIC;
115 
116  $ilObjDataCache = $DIC['ilObjDataCache'];
117 
118  $olp = ilObjectLP::getInstance($a_obj_id);
119  $collection = $olp->getCollectionInstance();
120  $grouped_items = [];
121  if ($collection) {
122  $grouped_items = $collection->getGroupedItemsForLPStatus();
123  }
124  if (!count($grouped_items)) {
125  // #11513 - empty collections cannot be completed
126  return array();
127  } else {
128  // New handling for optional assignments
129  $counter = 0;
130  $users = array();
131  foreach ($grouped_items as $grouping_id => $grouping) {
132  $isGrouping = $grouping_id ? true : false;
133  $grouping_completed = array();
134  $grouping_completed_users_num = array();
135  foreach ((array) $grouping['items'] as $item) {
136  $item_id = $ilObjDataCache->lookupObjId((int) $item);
137  $tmp_users = ilLPStatusWrapper::_getCompleted($item_id);
138  if ($isGrouping) {
139  // Iterated through all grouped items and count the number of fullfiled items
140  foreach ($tmp_users as $tmp_user_id) {
141  $grouping_completed_users_num[$tmp_user_id] =
142  ($grouping_completed_users_num[$tmp_user_id] ?? 0) + 1;
143  }
144  } elseif (!$counter++) {
145  $users = $tmp_users;
146  } else {
147  $users = array_intersect($users, $tmp_users);
148  }
149  }
150  if ($isGrouping) {
151  // Iterate through all "grouping_completed_users_num"
152  // All users with completed items greater equal than "num_obligatory" are completed
153  foreach ($grouping_completed_users_num as $tmp_user_id => $grouping_num_completed) {
154  if ($grouping_num_completed >= $grouping['num_obligatory']) {
155  $grouping_completed[] = $tmp_user_id;
156  }
157  }
158 
159  // build intersection of users
160  if (!$counter++) {
161  $users = $grouping_completed;
162  } else {
163  $users = array_intersect($users, $grouping_completed);
164  }
165  }
166  }
167  }
168 
169  $users = array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id));
170 
171  if ($users) {
172  // Exclude all non members
173  $users = array_intersect(self::getMembers($a_obj_id), $users);
174  }
175 
176  return (array) $users;
177  }
178 
179  public static function _getFailed(int $a_obj_id): array
180  {
181  global $DIC;
182 
183  $ilObjDataCache = $DIC['ilObjDataCache'];
184 
185  $users = array();
186 
187  $olp = ilObjectLP::getInstance($a_obj_id);
188  $collection = $olp->getCollectionInstance();
189  if ($collection) {
190  foreach ($collection->getGroupedItemsForLPStatus(
191  ) as $grouping_id => $grouping) {
192  $isGrouping = $grouping_id ? true : false;
193 
194  $gr_failed = array();
195  $gr_failed_users_num = array();
196  $counter = 0;
197  foreach ((array) $grouping['items'] as $item) {
198  $item_id = $ilObjDataCache->lookupObjId((int) $item);
199  $tmp_users = ilLPStatusWrapper::_getFailed($item_id);
200 
201  if ($isGrouping) {
202  foreach ($tmp_users as $tmp_user_id) {
203  $gr_failed_users_num[$tmp_user_id] =
204  ($gr_failed_users_num[$tmp_user_id] ?? 0) + 1;
205  }
206  } else {
207  // One item failed is sufficient for status failed.
208  $gr_failed = array_merge($gr_failed, $tmp_users);
209  }
210  $counter++;
211  }
212  if ($isGrouping) {
213  $allowed_failed = count(
214  $grouping['items']
215  ) - $grouping['num_obligatory'];
216  // Itereate over all failed users and check whether the allowd_failed value exceeded
217  foreach ($gr_failed_users_num as $tmp_user_id => $num_failed) {
218  if ($num_failed > $allowed_failed) {
219  $gr_failed[] = $tmp_user_id;
220  }
221  }
222  }
223  $users = array_unique(array_merge($users, $gr_failed));
224  }
225  }
226 
227  if ($users) {
228  // Exclude all non members
229  $users = array_intersect(self::getMembers($a_obj_id), $users);
230  }
231 
232  return array_unique($users);
233  }
234 
235  public static function _getStatusInfo(int $a_obj_id): array
236  {
237  $status_info = array();
238 
239  $olp = ilObjectLP::getInstance($a_obj_id);
240  $collection = $olp->getCollectionInstance();
241  if ($collection) {
242  $status_info['collections'] = $collection->getItems();
243  $status_info['num_collections'] = count(
244  $status_info['collections']
245  );
246  }
247 
248  return $status_info;
249  }
250 
251  public static function _getTypicalLearningTime(int $a_obj_id): int
252  {
253  global $DIC;
254 
255  $ilObjDataCache = $DIC['ilObjDataCache'];
256 
257  if ($ilObjDataCache->lookupType($a_obj_id) == 'sahs') {
258  return parent::_getTypicalLearningTime($a_obj_id);
259  }
260 
261  $tlt = 0;
262  $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id);
263  foreach ($status_info['collections'] as $item) {
265  $ilObjDataCache->lookupObjId((int) $item)
266  );
267  }
268  return $tlt;
269  }
270 
271  public function determineStatus(
272  int $a_obj_id,
273  int $a_usr_id,
274  object $a_obj = null
275  ): int {
276  global $DIC;
277 
278  $ilObjDataCache = $DIC['ilObjDataCache'];
279 
280  $status['completed'] = true;
281  $status['failed'] = false;
282  $status['in_progress'] = false;
283 
284  switch ($this->ilObjDataCache->lookupType($a_obj_id)) {
285  case "crs":
286  case "fold":
287  case "grp":
288  case "lso":
289  if (ilChangeEvent::hasAccessed($a_obj_id, $a_usr_id)) {
290  $status['in_progress'] = true;
291  }
292 
293  $olp = ilObjectLP::getInstance($a_obj_id);
294  $collection = $olp->getCollectionInstance();
295  $grouped_items = [];
296  if ($collection) {
297  $grouped_items = $collection->getGroupedItemsForLPStatus();
298  }
299  if (!count($grouped_items)) {
300  // #11513 - empty collections cannot be completed
301  $status['completed'] = false;
302  } else {
303  foreach ($grouped_items as $grouping_id => $grouping) {
304  $isGrouping = $grouping_id ? true : false;
305  $status = self::determineGroupingStatus(
306  $status,
307  $grouping,
308  $a_usr_id,
309  $isGrouping
310  );
311  }
312  }
313 
314  if ($status['completed']) {
315  if (!$this->isMember((int) $a_obj_id, (int) $a_usr_id)) {
316  return self::LP_STATUS_IN_PROGRESS_NUM;
317  }
318 
319  return self::LP_STATUS_COMPLETED_NUM;
320  }
321 
322  if ($status['failed']) {
323  return self::LP_STATUS_FAILED_NUM;
324  }
325 
326  if ($status['in_progress']) {
327  return self::LP_STATUS_IN_PROGRESS_NUM;
328  }
329  break;
330  }
331  return self::LP_STATUS_NOT_ATTEMPTED_NUM;
332  }
333 
337  public static function determineGroupingStatus(
338  array $status,
339  array $gr_info,
340  int $user_id,
341  bool $is_grouping
342  ): array {
343  global $DIC;
344 
345  $ilObjDataCache = $DIC['ilObjDataCache'];
346 
347  $items = $gr_info['items'];
348  if ($is_grouping) {
349  $max_allowed_failed = count($items) - $gr_info['num_obligatory'];
350  $required_completed = $gr_info['num_obligatory'];
351  } else {
352  $max_allowed_failed = 0;
353  $required_completed = count($items);
354  }
355 
356  // Required for grouping with a number of obligatory items
357  $num_failed = 0;
358  $num_completed = 0;
359 
360  foreach ($items as $item_id) {
361  $item_id = $ilObjDataCache->lookupObjId((int) $item_id);
363  $item_id,
364  $user_id
365  );
366 
367  if ($gr_status == self::LP_STATUS_FAILED_NUM) {
368  if (++$num_failed > $max_allowed_failed) {
369  $status['failed'] = true;
370  $status['completed'] = false;
371  return $status;
372  }
373  }
374  if ($gr_status == self::LP_STATUS_COMPLETED_NUM) {
375  if (++$num_completed >= $required_completed) {
376  return $status;
377  }
378  }
379  }
380  // Not completed since returned above
381  $status['completed'] = false;
382  return $status;
383  }
384 
390  protected function isMember(int $objId, int $usrId): bool
391  {
392  switch ($this->ilObjDataCache->lookupType($objId)) {
393  case 'crs':
394  $participants = ilCourseParticipant::_getInstanceByObjId($objId, $usrId);
395  return $participants->isMember();
396 
397  case 'grp':
398  $participants = ilGroupParticipants::_getInstanceByObjId($objId);
399  return $participants->isMember($usrId);
400 
401  case 'fold':
402  $folderRefIds = ilObject::_getAllReferences($objId);
403  $folderRefId = current($folderRefIds);
404  if ($crsRefId = $this->tree->checkForParentType($folderRefId, 'crs')) {
405  $participants = ilCourseParticipant::_getInstanceByObjId(ilObject::_lookupObjId($crsRefId), $usrId);
406  return $participants->isMember();
407  }
408 
409  if ($grpRefId = $this->tree->checkForParentType($folderRefId, 'grp')) {
411  return $participants->isMember($usrId);
412  }
413  break;
414 
415  case 'lso':
417  return $participants->isMember($usrId);
418  }
419 
420  return true;
421  }
422 
428  protected static function getMembers(int $a_obj_id): array
429  {
430  global $DIC;
431 
432  $ilObjDataCache = $DIC['ilObjDataCache'];
433  $tree = $DIC['tree'];
434 
435  switch ($ilObjDataCache->lookupType($a_obj_id)) {
436  case 'crs':
438  $a_obj_id
439  );
440  return $member_obj->getMembers();
441 
442  case 'grp':
444  $a_obj_id
445  );
446  return $member_obj->getMembers();
447 
448  case 'fold':
449  $folder_ref_ids = ilObject::_getAllReferences($a_obj_id);
450  $folder_ref_id = current($folder_ref_ids);
451  if ($crs_id = $tree->checkForParentType(
452  $folder_ref_id,
453  'crs'
454  )) {
456  ilObject::_lookupObjId($crs_id)
457  );
458  return $member_obj->getMembers();
459  }
460  break;
461 
462  case 'lso':
464  $a_obj_id
465  );
466  return $member_obj->getMembers();
467  break;
468  }
469 
470  return array();
471  }
472 
476  public static function _lookupCompletedForObject(
477  int $a_obj_id,
478  ?array $a_user_ids = null
479  ): array {
480  if (!$a_user_ids) {
481  $a_user_ids = self::getMembers($a_obj_id);
482  if (!$a_user_ids) {
483  return array();
484  }
485  }
486  return self::_lookupStatusForObject(
487  $a_obj_id,
488  self::LP_STATUS_COMPLETED_NUM,
489  $a_user_ids
490  );
491  }
492 
496  public static function _lookupFailedForObject(
497  int $a_obj_id,
498  ?array $a_user_ids = null
499  ): array {
500  if (!$a_user_ids) {
501  $a_user_ids = self::getMembers($a_obj_id);
502  if (!$a_user_ids) {
503  return array();
504  }
505  }
506  return self::_lookupStatusForObject(
507  $a_obj_id,
508  self::LP_STATUS_FAILED_NUM,
509  $a_user_ids
510  );
511  }
512 
516  public static function _lookupInProgressForObject(
517  int $a_obj_id,
518  ?array $a_user_ids = null
519  ): array {
520  if (!$a_user_ids) {
521  $a_user_ids = self::getMembers($a_obj_id);
522  if (!$a_user_ids) {
523  return array();
524  }
525  }
526  return self::_lookupStatusForObject(
527  $a_obj_id,
528  self::LP_STATUS_IN_PROGRESS_NUM,
529  $a_user_ids
530  );
531  }
532 }
static _getFailed(int $a_obj_id)
static _getCompleted(int $a_obj_id)
Static function to read the users who have the status &#39;completed&#39;.
determineStatus(int $a_obj_id, int $a_usr_id, object $a_obj=null)
static _getStatusInfo(int $a_obj_id)
Reads informations about the object e.g test results, tlt, number of visits.
static _getInstanceByObjId(int $a_obj_id, int $a_usr_id)
static _getAllReferences(int $id)
get all reference ids for object ID
static _getCompleted(int $a_obj_id)
Get completed users New handling for optional grouped assignments.
static hasAccessed(int $a_obj_id, int $a_usr_id)
Has accessed.
static _getTypicalLearningTime(int $a_obj_id)
$objId
Definition: xapitoken.php:57
isMember(int $objId, int $usrId)
static _getInProgress(int $a_obj_id)
Static function to read users who have the status &#39;in_progress&#39;.
static _getStatusInfo(int $a_obj_id)
static _lookupObjId(int $ref_id)
global $DIC
Definition: feed.php:28
static lookupUsersInProgress(int $a_obj_id)
static determineGroupingStatus(array $status, array $gr_info, int $user_id, bool $is_grouping)
Determine grouping status.
checkForParentType(int $a_ref_id, string $a_type, bool $a_exclude_source_check=false)
Check for parent type e.g check if a folder (ref_id 3) is in a parent course obj => checkForParentTyp...
static _getInstanceByObjId(int $a_obj_id)
static _getFailed(int $a_obj_id)
Static function to read the users who have the status &#39;completed&#39;.
static getMembers(int $a_obj_id)
Get members for object.
static _getTypicalLearningTime(int $a_obj_id)
Reads Typical learning time.
ilObjectDataCache $ilObjDataCache
static _lookupCompletedForObject(int $a_obj_id, ?array $a_user_ids=null)
Get completed users for object.
static _getInProgress(int $a_obj_id)
static _lookupInProgressForObject(int $a_obj_id, ?array $a_user_ids=null)
Get in progress users for object.
static _getInstanceByObjId(int $a_obj_id)
Get singleton instance.
__construct(Container $dic, ilPlugin $plugin)
static _determineStatus(int $a_obj_id, int $a_usr_id)
static _lookupFailedForObject(int $a_obj_id, ?array $a_user_ids=null)
Get failed users for object.
static getInstance(int $obj_id)
static _getNotAttempted(int $a_obj_id)