ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilLPStatus.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 define('LP_STATUS_NOT_ATTEMPTED','trac_no_attempted');
5 define('LP_STATUS_IN_PROGRESS','trac_in_progress');
6 define('LP_STATUS_COMPLETED','trac_completed');
7 define('LP_STATUS_FAILED','trac_failed');
8 
9 define('LP_STATUS_NOT_ATTEMPTED_NUM', 0);
10 define('LP_STATUS_IN_PROGRESS_NUM', 1);
11 define('LP_STATUS_COMPLETED_NUM', 2);
12 define('LP_STATUS_FAILED_NUM', 3);
13 
14 // Stati for events
15 define('LP_STATUS_REGISTERED','trac_registered');
16 define('LP_STATUS_NOT_REGISTERED','trac_not_registered');
17 define('LP_STATUS_PARTICIPATED','trac_participated');
18 define('LP_STATUS_NOT_PARTICIPATED','trac_not_participated');
19 
32 {
33  var $obj_id = null;
34 
35  var $db = null;
36 
37  function ilLPStatus($a_obj_id)
38  {
39  global $ilDB;
40 
41  $this->obj_id = $a_obj_id;
42  $this->db =& $ilDB;
43  }
44 
45  function _getCountNotAttempted($a_obj_id)
46  {
47  return 0;
48  }
49 
50  function _getNotAttempted($a_obj_id)
51  {
52  return array();
53  }
54 
55  function _getCountInProgress($a_obj_id)
56  {
57  return 0;
58  }
59  function _getInProgress($a_obj_id)
60  {
61  return array();
62  }
63 
64  function _getCountCompleted($a_obj_id)
65  {
66  return 0;
67  }
68  function _getCompleted($a_obj_id)
69  {
70  return array();
71  }
72  function _getFailed($a_obj_id)
73  {
74  return array();
75  }
76  function _getCountFailed()
77  {
78  return 0;
79  }
80  function _getStatusInfo($a_obj_id)
81  {
82  return array();
83  }
84  function _getTypicalLearningTime($a_obj_id)
85  {
86  include_once 'Services/MetaData/classes/class.ilMDEducational.php';
88  }
89 
90 
195  function _updateStatus($a_obj_id, $a_usr_id, $a_obj = null, $a_percentage = false, $a_no_raise = false)
196  {
197 //global $ilLog;
198 //$ilLog->write("ilLPStatus-_updateStatus-");
199 
200  $status = $this->determineStatus($a_obj_id, $a_usr_id, $a_obj);
201  $percentage = $this->determinePercentage($a_obj_id, $a_usr_id, $a_obj);
202  $changed = ilLPStatus::writeStatus($a_obj_id, $a_usr_id, $status, $percentage);
203 
204  if(!$a_no_raise && $changed)
205  {
206  self::raiseEvent($a_obj_id, $a_usr_id, $status, $percentage);
207  }
208  }
209 
216  function determinePercentage($a_obj_id, $a_usr_id, $a_obj = null)
217  {
218  return false;
219  }
220 
227  function determineStatus($a_obj_id, $a_usr_id, $a_obj = null)
228  {
229  return false;
230  }
231 
232 
240  static function checkStatusForObject($a_obj_id, $a_users = false)
241  {
242  global $ilDB;
243 
244 //@todo: there maybe the need to add extra handling for sessions here, since the
245 // "in progress" status is time dependent here. On the other hand, if they registered
246 // to the session, they already accessed the course and should have a "in progress"
247 // anyway. But the status on the session itself may not be correct.
248 
249  $sql = "SELECT usr_id FROM ut_lp_marks WHERE ".
250  " obj_id = ".$ilDB->quote($a_obj_id, "integer")." AND ".
251  " status_dirty = ".$ilDB->quote(1, "integer");
252  if(is_array($a_users) && count($a_users) > 0)
253  {
254  $sql .= " AND ".$ilDB->in("usr_id", $a_users, false, "integer");
255  }
256  $set = $ilDB->query($sql);
257  $dirty = false;
258  if ($rec = $ilDB->fetchAssoc($set))
259  {
260  $dirty = true;
261  }
262 
263  // check if any records are missing
264  $missing = false;
265  if (!$dirty && is_array($a_users) && count($a_users) > 0)
266  {
267  $set = $ilDB->query("SELECT count(usr_id) cnt FROM ut_lp_marks WHERE ".
268  " obj_id = ".$ilDB->quote($a_obj_id, "integer")." AND ".
269  $ilDB->in("usr_id", $a_users, false, "integer"));
270  $r = $ilDB->fetchAssoc($set);
271  if ($r["cnt"] < count($a_users))
272  {
273  $missing = true;
274  }
275  }
276 
277  // refresh status, if records are dirty or missing
278  if ($dirty || $missing)
279  {
280  require_once "Services/Tracking/classes/class.ilLPStatusFactory.php"; // #13330
281  $class = ilLPStatusFactory::_getClassById($a_obj_id);
282  $trac_obj = new $class($a_obj_id);
283  $trac_obj->refreshStatus($a_obj_id, $a_users);
284  }
285  }
286 
287  protected function raiseEvent($a_obj_id, $a_usr_id, $a_status, $a_percentage)
288  {
289  global $ilAppEventHandler;
290 
291  $ilAppEventHandler->raise("Services/Tracking", "updateStatus", array(
292  "obj_id" => $a_obj_id,
293  "usr_id" => $a_usr_id,
294  "status" => $a_status,
295  "percentage" => $a_percentage
296  ));
297  }
298 
305  function refreshStatus($a_obj_id, $a_users = null)
306  {
307  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
308  $not_attempted = ilLPStatusWrapper::_getNotAttempted($a_obj_id);
309  foreach ($not_attempted as $user_id)
310  {
311  $percentage = $this->determinePercentage($a_obj_id, $user_id);
312  if(ilLPStatus::writeStatus($a_obj_id, $user_id, LP_STATUS_NOT_ATTEMPTED_NUM, $percentage, true))
313  {
314  self::raiseEvent($a_obj_id, $user_id, LP_STATUS_NOT_ATTEMPTED_NUM, $percentage);
315  }
316  }
317  $in_progress = ilLPStatusWrapper::_getInProgress($a_obj_id);
318  foreach ($in_progress as $user_id)
319  {
320  $percentage = $this->determinePercentage($a_obj_id, $user_id);
321  if(ilLPStatus::writeStatus($a_obj_id, $user_id, LP_STATUS_IN_PROGRESS_NUM, $percentage, true))
322  {
323  self::raiseEvent($a_obj_id, $user_id, LP_STATUS_IN_PROGRESS_NUM, $percentage);
324  }
325  }
326  $completed = ilLPStatusWrapper::_getCompleted($a_obj_id);
327  foreach ($completed as $user_id)
328  {
329  $percentage = $this->determinePercentage($a_obj_id, $user_id);
330  if(ilLPStatus::writeStatus($a_obj_id, $user_id, LP_STATUS_COMPLETED_NUM, $percentage, true))
331  {
332  self::raiseEvent($a_obj_id, $user_id, LP_STATUS_COMPLETED_NUM, $percentage);
333  }
334  }
336  foreach ($failed as $user_id)
337  {
338  $percentage = $this->determinePercentage($a_obj_id, $user_id);
339  if(ilLPStatus::writeStatus($a_obj_id, $user_id, LP_STATUS_FAILED_NUM, $percentage, true))
340  {
341  self::raiseEvent($a_obj_id, $user_id, LP_STATUS_FAILED_NUM, $percentage);
342  }
343  }
344  if($a_users)
345  {
346  $missing_users = array_diff($a_users, $not_attempted+$in_progress+$completed+$failed);
347  if($missing_users)
348  {
349  foreach ($missing_users as $user_id)
350  {
351  ilLPStatusWrapper::_updateStatus($a_obj_id, $user_id);
352  }
353  }
354  }
355  }
356 
363  static function writeStatus($a_obj_id, $a_user_id, $a_status, $a_percentage = false, $a_force_per = false)
364  {
365  global $ilDB;
366 
367  $update_collections = false;
368 
369  // get status in DB
370  $set = $ilDB->query("SELECT usr_id,status,status_dirty FROM ut_lp_marks WHERE ".
371  " obj_id = ".$ilDB->quote($a_obj_id, "integer")." AND ".
372  " usr_id = ".$ilDB->quote($a_user_id, "integer")
373  );
374  $rec = $ilDB->fetchAssoc($set);
375 
376  // update
377  if ($rec)
378  {
379  // status has changed: update
380  if ($rec["status"] != $a_status)
381  {
382  $ret = $ilDB->manipulate("UPDATE ut_lp_marks SET ".
383  " status = ".$ilDB->quote($a_status, "integer").",".
384  " status_changed = ".$ilDB->now().",".
385  " status_dirty = ".$ilDB->quote(0, "integer").
386  " WHERE usr_id = ".$ilDB->quote($a_user_id, "integer").
387  " AND obj_id = ".$ilDB->quote($a_obj_id, "integer")
388  );
389  if ($ret != 0)
390  {
391  $update_collections = true;
392  }
393  }
394  // status has not changed: reset dirty flag
395  else if ($rec["status_dirty"])
396  {
397  $ilDB->manipulate("UPDATE ut_lp_marks SET ".
398  " status_dirty = ".$ilDB->quote(0, "integer").
399  " WHERE usr_id = ".$ilDB->quote($a_user_id, "integer").
400  " AND obj_id = ".$ilDB->quote($a_obj_id, "integer")
401  );
402  }
403  }
404  // insert
405  else
406  {
407  $ilDB->manipulate("INSERT INTO ut_lp_marks ".
408  "(status, status_changed, usr_id, obj_id, status_dirty) VALUES (".
409  $ilDB->quote($a_status, "integer").",".
410  $ilDB->now().",".
411  $ilDB->quote($a_user_id, "integer").",".
412  $ilDB->quote($a_obj_id, "integer").",".
413  $ilDB->quote(0, "integer").
414  ")");
415  $update_collections = true;
416  }
417 
418  // update percentage
419  if ($a_percentage !== false || $a_force_per)
420  {
421  $a_percentage = max(0, (int) $a_percentage);
422  $a_percentage = min(100, $a_percentage);
423  $ret = $ilDB->manipulate("UPDATE ut_lp_marks SET ".
424  " percentage = ".$ilDB->quote($a_percentage, "integer").
425  " WHERE usr_id = ".$ilDB->quote($a_user_id, "integer").
426  " AND obj_id = ".$ilDB->quote($a_obj_id, "integer")
427  );
428  }
429 
430  // update collections
431  if ($update_collections)
432  {
433  // a change occured - remove existing cache entry
434  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
435  ilLPStatusWrapper::_removeStatusCache($a_obj_id, $a_user_id);
436 
437  $set = $ilDB->query("SELECT ut_lp_collections.obj_id obj_id FROM ".
438  "object_reference JOIN ut_lp_collections ON ".
439  "(object_reference.obj_id = ".$ilDB->quote($a_obj_id, "integer").
440  " AND object_reference.ref_id = ut_lp_collections.item_id)");
441  while ($rec = $ilDB->fetchAssoc($set))
442  {
443  if (in_array(ilObject::_lookupType($rec["obj_id"]), array("crs", "grp", "fold")))
444  {
445  // just to make sure - remove existing cache entry
446  ilLPStatusWrapper::_removeStatusCache($rec["obj_id"], $a_user_id);
447 
448  ilLPStatusWrapper::_updateStatus($rec["obj_id"], $a_user_id);
449  }
450  }
451  }
452 
453  return $update_collections;
454  }
455 
461  static function setInProgressIfNotAttempted($a_obj_id, $a_user_id)
462  {
463  global $ilDB;
464 
465  $set = $ilDB->query("SELECT usr_id FROM ut_lp_marks WHERE ".
466  " obj_id = ".$ilDB->quote($a_obj_id, "integer")." AND ".
467  " usr_id = ".$ilDB->quote($a_user_id, "integer")
468  );
469 
470  $update_collections = false;
471  if ($rec = $ilDB->fetchAssoc($set))
472  {
473  $ret = $ilDB->manipulate("UPDATE ut_lp_marks SET ".
474  " status = ".$ilDB->quote(LP_STATUS_IN_PROGRESS_NUM, "integer").",".
475  " status_changed = ".$ilDB->now().",".
476  " status_dirty = ".$ilDB->quote(0, "integer").
477  " WHERE usr_id = ".$ilDB->quote($a_user_id, "integer").
478  " AND obj_id = ".$ilDB->quote($a_obj_id, "integer").
479  " AND status = ".$ilDB->quote(LP_STATUS_NOT_ATTEMPTED_NUM, "integer")
480  );
481  if ($ret != 0)
482  {
483  $update_collections = true;
484  }
485  }
486  else
487  {
488  $ilDB->manipulate("INSERT INTO ut_lp_marks ".
489  "(status, status_changed, usr_id, obj_id, status_dirty) VALUES (".
490  $ilDB->quote(LP_STATUS_IN_PROGRESS_NUM, "integer").",".
491  $ilDB->now().",".
492  $ilDB->quote($a_user_id, "integer").",".
493  $ilDB->quote($a_obj_id, "integer").",".
494  $ilDB->quote(0, "integer").
495  ")");
496  $update_collections = true;
497  }
498 
499  // update collections
500  if ($update_collections)
501  {
502  $set = $ilDB->query("SELECT ut_lp_collections.obj_id obj_id FROM ".
503  "object_reference JOIN ut_lp_collections ON ".
504  "(object_reference.obj_id = ".$ilDB->quote($a_obj_id, "integer").
505  " AND object_reference.ref_id = ut_lp_collections.item_id)");
506  while ($rec = $ilDB->fetchAssoc($set))
507  {
508  if (in_array(ilObject::_lookupType($rec["obj_id"]), array("crs", "grp", "fold")))
509  {
510  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
511  ilLPStatusWrapper::_updateStatus($rec["obj_id"], $a_user_id);
512  }
513  }
514  }
515  }
516 
523  static function setAllDirty()
524  {
525  global $ilDB;
526 
527  $ilDB->manipulate("UPDATE ut_lp_marks SET ".
528  " status_dirty = ".$ilDB->quote(1, "integer")
529  );
530 
531  }
532 
539  static function setDirty($a_obj_id)
540  {
541  global $ilDB;
542 
543  $ilDB->manipulate("UPDATE ut_lp_marks SET ".
544  " status_dirty = ".$ilDB->quote(1, "integer").
545  " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer")
546  );
547  }
548 
555  function _lookupStatus($a_obj_id, $a_user_id)
556  {
557  global $ilDB;
558 
559  $set = $ilDB->query("SELECT status FROM ut_lp_marks WHERE ".
560  " status_dirty = ".$ilDB->quote(0, "integer").
561  " AND usr_id = ".$ilDB->quote($a_user_id, "integer").
562  " AND obj_id = ".$ilDB->quote($a_obj_id, "integer")
563  );
564  if ($rec = $ilDB->fetchAssoc($set))
565  {
566  return $rec["status"];
567  }
568  else
569  {
570  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
571  ilLPStatusWrapper::_updateStatus($a_obj_id, $a_user_id);
572  $set = $ilDB->query("SELECT status FROM ut_lp_marks WHERE ".
573  " status_dirty = ".$ilDB->quote(0, "integer").
574  " AND usr_id = ".$ilDB->quote($a_user_id, "integer").
575  " AND obj_id = ".$ilDB->quote($a_obj_id, "integer")
576  );
577  if ($rec = $ilDB->fetchAssoc($set))
578  {
579  return $rec["status"];
580  }
581  }
582  }
583 
590  function _lookupStatusChanged($a_obj_id, $a_user_id)
591  {
592  global $ilDB;
593 
594  $set = $ilDB->query("SELECT status_changed FROM ut_lp_marks WHERE ".
595  " status_dirty = ".$ilDB->quote(0, "integer").
596  " AND usr_id = ".$ilDB->quote($a_user_id, "integer").
597  " AND obj_id = ".$ilDB->quote($a_obj_id, "integer")
598  );
599  if ($rec = $ilDB->fetchAssoc($set))
600  {
601  return $rec["status_changed"];
602  }
603  else
604  {
605  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
606  ilLPStatusWrapper::_updateStatus($a_obj_id, $a_user_id);
607  $set = $ilDB->query("SELECT status_changed FROM ut_lp_marks WHERE ".
608  " status_dirty = ".$ilDB->quote(0, "integer").
609  " AND usr_id = ".$ilDB->quote($a_user_id, "integer").
610  " AND obj_id = ".$ilDB->quote($a_obj_id, "integer")
611  );
612  if ($rec = $ilDB->fetchAssoc($set))
613  {
614  return $rec["status_changed"];
615  }
616  }
617  }
618 
627  protected static function _lookupStatusForObject($a_obj_id, $a_status, $a_user_ids = null)
628  {
629  global $ilDB;
630 
631  $sql = "SELECT usr_id, status, status_dirty FROM ut_lp_marks".
632  " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer").
633  " AND status = ".$ilDB->quote($a_status, "integer");
634  if($a_user_ids)
635  {
636  $sql .= " AND ".$ilDB->in("usr_id", $a_user_ids, "", "integer");
637  }
638 
639  $set = $ilDB->query($sql);
640  $res = array();
641  while($rec = $ilDB->fetchAssoc($set))
642  {
643  if($res["status_dirty"])
644  {
645  // update status and check again
646  if(self::_lookupStatus($a_obj_id, $rec["usr_id"]) != $a_status)
647  {
648  continue;
649  }
650  }
651  $res[] = $rec["usr_id"];
652  }
653 
654  return $res;
655  }
656 
664  public static function _lookupCompletedForObject($a_obj_id, $a_user_ids = null)
665  {
666  return self::_lookupStatusForObject($a_obj_id, LP_STATUS_COMPLETED_NUM, $a_user_ids);
667  }
668 
676  public static function _lookupFailedForObject($a_obj_id, $a_user_ids = null)
677  {
678  return self::_lookupStatusForObject($a_obj_id, LP_STATUS_FAILED_NUM, $a_user_ids);
679  }
680 
688  public static function _lookupInProgressForObject($a_obj_id, $a_user_ids = null)
689  {
690  return self::_lookupStatusForObject($a_obj_id, LP_STATUS_IN_PROGRESS_NUM, $a_user_ids);
691  }
692 }
693 ?>