ILIAS  release_7 Revision v7.30-3-g800a261c036
ilChangeEvent Class Reference

Class ilChangeEvent tracks change events on repository objects. More...

+ Collaboration diagram for ilChangeEvent:

Static Public Member Functions

static _recordWriteEvent ($obj_id, $usr_id, $action, $parent_obj_id=null)
 Records a write event. More...
 
static _recordReadEvent ( $a_type, $a_ref_id, $obj_id, $usr_id, $isCatchupWriteEvents=true, $a_ext_rc=false, $a_ext_time=false)
 Records a read event and catches up with write events. More...
 
static _recordObjStats ($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds=null, $a_child_read_count=null)
 
static _syncObjectStats ($a_now=null, $a_minimum=20000)
 Process object statistics log data. More...
 
static _catchupWriteEvents ($obj_id, $usr_id, $timestamp=null)
 Catches up with all write events which occured before the specified timestamp. More...
 
static _lookupUncaughtWriteEvents ($obj_id, $usr_id)
 Catches up with all write events which occured before the specified timestamp. More...
 
static _lookupChangeState ($obj_id, $usr_id)
 Returns the change state of the object for the specified user. More...
 
static _lookupReadEvents ($obj_id, $usr_id=null)
 Reads all read events which occured on the object which happened after the last time the user caught up with them. More...
 
static lookupUsersInProgress ($a_obj_id)
 Lookup users in progress. More...
 
static hasAccessed ($a_obj_id, $a_usr_id)
 Has accessed. More...
 
static _activate ()
 Activates change event tracking. More...
 
static _deactivate ()
 Deactivates change event tracking. More...
 
static _isActive ()
 Returns true, if change event tracking is active. More...
 
static _delete ($a_obj_id)
 Delete object entries. More...
 
static _deleteReadEvents ($a_obj_id)
 
static _deleteReadEventsForUsers ($a_obj_id, array $a_user_ids)
 
static _getAllUserIds ($a_obj_id)
 
static _updateAccessForScormOfflinePlayer ($obj_id, $usr_id, $i_last_access, $t_first_access)
 _updateAccessForScormOfflinePlayer needed to synchronize last_access and first_access when learning modul is used offline called in . More...
 

Static Private Attributes

static $has_accessed = array()
 

Detailed Description

Class ilChangeEvent tracks change events on repository objects.

The following events are considered to be a 'write event':

  • The creation of a new repository object
  • A change of the data or meta-data of an object
  • A move, link, copy, deletion or undeletion of the object UI objects, which cause a 'write event', must call _recordWriteEvent(...) In most cases, UI objects let the user catch up with write events on the object, when doing this call.

The following events are considered to be a 'read event':

  • Opening a container object in the browser*
  • Opening / downloading / reading an object UI objects, which cause a 'read event', must call _recordReadEvent(...). In most cases, UI objects let the user catch up with write events on the object, when doing this call.

*reading the content of a container using WebDAV is not counted, because WebDAV clients can't see all objects in a container.

A user can catch up with write events, by calling __catchupWriteEvents(...).

A user can query, if an object has changed, since the last time he has caught up with write events, by calling _lookupUncaughtWriteEvents(...).

Author
Werner Randelshofer werne.nosp@m.r.ra.nosp@m.ndels.nosp@m.hofe.nosp@m.r@hsl.nosp@m.u.ch
Version
Id
class.ilChangeEvent.php,v 1.02 2007/05/07 19:25:34 wrandels Exp

Definition at line 36 of file class.ilChangeEvent.php.

Member Function Documentation

◆ _activate()

static ilChangeEvent::_activate ( )
static

Activates change event tracking.

Returns
mixed true on success, a string with an error message on failure.

Definition at line 824 of file class.ilChangeEvent.php.

825 {
827 return 'change event tracking is already active';
828 } else {
829 global $DIC;
830
831 $ilDB = $DIC['ilDB'];
832
833 // Insert initial data into table write_event
834 // We need to do this here, because we need
835 // to catch up write events that occured while the change event tracking was
836 // deactivated.
837
838 // IGNORE isn't supported in oracle
839 $set = $ilDB->query(sprintf(
840 'SELECT r1.obj_id,r2.obj_id p,d.owner,%s,d.create_date ' .
841 'FROM object_data d ' .
842 'LEFT JOIN write_event w ON d.obj_id = w.obj_id ' .
843 'JOIN object_reference r1 ON d.obj_id=r1.obj_id ' .
844 'JOIN tree t ON t.child=r1.ref_id ' .
845 'JOIN object_reference r2 on r2.ref_id=t.parent ' .
846 'WHERE w.obj_id IS NULL',
847 $ilDB->quote('create', 'text')
848 ));
849 while ($rec = $ilDB->fetchAssoc($set)) {
850 $nid = $ilDB->nextId("write_event");
851 $query = 'INSERT INTO write_event ' .
852 '(write_id, obj_id,parent_obj_id,usr_id,action,ts) VALUES (' .
853 $ilDB->quote($nid, "integer") . "," .
854 $ilDB->quote($rec["obj_id"], "integer") . "," .
855 $ilDB->quote($rec["p"], "integer") . "," .
856 $ilDB->quote($rec["owner"], "integer") . "," .
857 $ilDB->quote("create", "text") . "," .
858 $ilDB->quote($rec["create_date"], "timestamp") .
859 ')';
860 $res = $ilDB->query($query);
861 }
862
863 global $DIC;
864
865 $ilSetting = $DIC['ilSetting'];
866 $ilSetting->set('enable_change_event_tracking', '1');
867
868 return $res;
869 }
870 }
static _isActive()
Returns true, if change event tracking is active.
global $DIC
Definition: goto.php:24
global $ilSetting
Definition: privfeed.php:17
$query
foreach($_POST as $key=> $value) $res
global $ilDB

References $DIC, $ilDB, $ilSetting, $query, $res, and _isActive().

Referenced by ilObjRepositorySettingsGUI\saveSettings(), and ilTrackingTest\testChangeEvent().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _catchupWriteEvents()

static ilChangeEvent::_catchupWriteEvents (   $obj_id,
  $usr_id,
  $timestamp = null 
)
static

Catches up with all write events which occured before the specified timestamp.

Parameters
$obj_idint The object.
$usr_idint The user.
$timestampSQL timestamp.

Definition at line 488 of file class.ilChangeEvent.php.

489 {
490 global $DIC;
491
492 $ilDB = $DIC['ilDB'];
493
494 $query = "SELECT obj_id FROM catch_write_events " .
495 "WHERE obj_id = " . $ilDB->quote($obj_id, 'integer') . " " .
496 "AND usr_id = " . $ilDB->quote($usr_id, 'integer');
497 $res = $ilDB->query($query);
498 if ($res->numRows()) {
499 $ts = ($timestamp == null)
500 ? ilUtil::now()
501 : $timestamp;
502 /* $query = "UPDATE catch_write_events ".
503 "SET ts = ".($timestamp == null ? $ilDB->now() : $ilDB->quote($timestamp, 'timestamp'))." ".
504 "WHERE usr_id = ".$ilDB->quote($usr_id ,'integer')." ".
505 "AND obj_id = ".$ilDB->quote($obj_id ,'integer');
506 $res = $ilDB->manipulate($query);*/
507 } else {
508 $ts = ilUtil::now();
509 /* $query = "INSERT INTO catch_write_events (ts,obj_id,usr_id) ".
510 "VALUES( ".
511 $ilDB->now().", ".
512 $ilDB->quote($obj_id,'integer').", ".
513 $ilDB->quote($usr_id,'integer')." ".
514 ")";
515 $res = $ilDB->manipulate($query);*/
516 }
517
518 // alex, use replace due to bug #10406
519 $ilDB->replace(
520 "catch_write_events",
521 array(
522 "obj_id" => array("integer", $obj_id),
523 "usr_id" => array("integer", $usr_id)
524 ),
525 array(
526 "ts" => array("timestamp", $ts))
527 );
528 }
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
static now()
Return current timestamp in Y-m-d H:i:s format.

References $DIC, $ilDB, $query, $res, $timestamp, and ilUtil\now().

Referenced by _recordReadEvent(), ilContainerGUI\pasteObject(), ilContainerGUI\performPasteIntoMultipleObjectsObject(), ilRepUtil\restoreObjects(), ilObjFileGUI\update(), ilObjCategoryGUI\updateObject(), ilObjCourseGUI\updateObject(), and ilObjGroupGUI\updateObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _deactivate()

static ilChangeEvent::_deactivate ( )
static

Deactivates change event tracking.

Returns
mixed true on success, a string with an error message on failure.

Definition at line 877 of file class.ilChangeEvent.php.

878 {
879 global $DIC;
880
881 $ilSetting = $DIC['ilSetting'];
882 $ilSetting->set('enable_change_event_tracking', '0');
883 }

References $DIC, and $ilSetting.

Referenced by ilObjRepositorySettingsGUI\saveSettings(), and ilTrackingTest\testChangeEvent().

+ Here is the caller graph for this function:

◆ _delete()

static ilChangeEvent::_delete (   $a_obj_id)
static

Delete object entries.

Returns

Definition at line 904 of file class.ilChangeEvent.php.

905 {
906 global $DIC;
907
908 $ilDB = $DIC['ilDB'];
909
910 $query = sprintf(
911 'DELETE FROM write_event WHERE obj_id = %s ',
912 $ilDB->quote($a_obj_id, 'integer')
913 );
914 $aff = $ilDB->manipulate($query);
915
916 $query = sprintf(
917 'DELETE FROM read_event WHERE obj_id = %s ',
918 $ilDB->quote($a_obj_id, 'integer')
919 );
920 $aff = $ilDB->manipulate($query);
921 return true;
922 }

References $DIC, $ilDB, and $query.

Referenced by ilObjectLP\handleDelete().

+ Here is the caller graph for this function:

◆ _deleteReadEvents()

static ilChangeEvent::_deleteReadEvents (   $a_obj_id)
static

Definition at line 924 of file class.ilChangeEvent.php.

925 {
926 global $DIC;
927
928 $ilDB = $DIC['ilDB'];
929
930 $ilDB->manipulate("DELETE FROM read_event" .
931 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer"));
932 }

References $DIC, and $ilDB.

◆ _deleteReadEventsForUsers()

static ilChangeEvent::_deleteReadEventsForUsers (   $a_obj_id,
array  $a_user_ids 
)
static

Definition at line 934 of file class.ilChangeEvent.php.

935 {
936 global $DIC;
937
938 $ilDB = $DIC['ilDB'];
939
940 $ilDB->manipulate("DELETE FROM read_event" .
941 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") .
942 " AND " . $ilDB->in("usr_id", $a_user_ids, "", "integer"));
943 }

References $DIC, and $ilDB.

Referenced by ilObjSCORM2004LearningModule\deleteTrackingDataOfUsers(), ilObjSCORMLearningModule\deleteTrackingDataOfUsers(), and ilObjectLP\resetLPDataForUserIds().

+ Here is the caller graph for this function:

◆ _getAllUserIds()

static ilChangeEvent::_getAllUserIds (   $a_obj_id)
static

Definition at line 945 of file class.ilChangeEvent.php.

946 {
947 global $DIC;
948
949 $ilDB = $DIC['ilDB'];
950
951 $res = array();
952
953 $set = $ilDB->query("SELECT usr_id FROM read_event" .
954 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer"));
955 while ($row = $ilDB->fetchAssoc($set)) {
956 $res[] = $row["usr_id"];
957 }
958
959 return $res;
960 }

References $DIC, $ilDB, and $res.

Referenced by ilObjectLP\gatherLPUsers().

+ Here is the caller graph for this function:

◆ _isActive()

static ilChangeEvent::_isActive ( )
static

Returns true, if change event tracking is active.

Returns
mixed true on success, a string with an error message on failure.

Definition at line 890 of file class.ilChangeEvent.php.

891 {
892 global $DIC;
893
894 $ilSetting = $DIC['ilSetting'];
895 return $ilSetting->get('enable_change_event_tracking', '0') == '1';
896 }

References $DIC, and $ilSetting.

Referenced by ilObjUserTracking\__readSettings(), _activate(), ilInfoScreenGUI\addObjectSections(), ilObjRepositorySettingsGUI\addToExternalSettingsForm(), and ilObjRepositorySettingsGUI\initSettingsForm().

+ Here is the caller graph for this function:

◆ _lookupChangeState()

static ilChangeEvent::_lookupChangeState (   $obj_id,
  $usr_id 
)
static

Returns the change state of the object for the specified user.

which happened after the last time the user caught up with them.

Parameters
$obj_idint The object
$usr_idint The user who is interested into these events.
Returns
0 = object is unchanged, 1 = object is new, 2 = object has changed

Definition at line 634 of file class.ilChangeEvent.php.

635 {
636 global $DIC;
637
638 $ilDB = $DIC['ilDB'];
639
640 $q = "SELECT ts " .
641 "FROM catch_write_events " .
642 "WHERE obj_id=" . $ilDB->quote($obj_id, 'integer') . " " .
643 "AND usr_id=" . $ilDB->quote($usr_id, 'integer');
644 $r = $ilDB->query($q);
645 $catchup = null;
646 while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
647 $catchup = $row['ts'];
648 }
649
650 if ($catchup == null) {
651 $ilDB->setLimit(1);
652 $query = sprintf(
653 'SELECT * FROM write_event ' .
654 'WHERE obj_id = %s ' .
655 'AND usr_id <> %s ',
656 $ilDB->quote($obj_id, 'integer'),
657 $ilDB->quote($usr_id, 'integer')
658 );
659 $res = $ilDB->query($query);
660 } else {
661 $ilDB->setLimit(1);
662 $query = sprintf(
663 'SELECT * FROM write_event ' .
664 'WHERE obj_id = %s ' .
665 'AND usr_id <> %s ' .
666 'AND ts > %s ',
667 $ilDB->quote($obj_id, 'integer'),
668 $ilDB->quote($usr_id, 'integer'),
669 $ilDB->quote($catchup, 'timestamp')
670 );
671 $res = $ilDB->query($query);
672 }
673
674 $numRows = $res->numRows();
675 if ($numRows > 0) {
676 $row = $ilDB->fetchAssoc($res);
677 // if we have write events, and user never catched one, report as new (1)
678 // if we have write events, and user catched an old write event, report as changed (2)
679 return ($catchup == null) ? 1 : 2;
680 } else {
681 return 0; // user catched all write events, report as unchanged (0)
682 }
683 }

References $DIC, $ilDB, $query, $res, and ilDBConstants\FETCHMODE_ASSOC.

Referenced by ilTrackingTest\testChangeEvent().

+ Here is the caller graph for this function:

◆ _lookupReadEvents()

static ilChangeEvent::_lookupReadEvents (   $obj_id,
  $usr_id = null 
)
static

Reads all read events which occured on the object which happened after the last time the user caught up with them.

NOTE: THIS FUNCTION NEEDS TO BE REWRITTEN. READ EVENTS ARE OF INTEREST AT REF_ID's OF OBJECTS.

Parameters
$obj_idint The object
$usr_idint The user who is interested into these events. / public static function _lookupUncaughtReadEvents($obj_id, $usr_id) { global $DIC;

$ilDB = $DIC['ilDB'];

$q = "SELECT ts ". "FROM catch_read_events ". "WHERE obj_id=".$ilDB->quote($obj_id)." ". "AND usr_id=".$ilDB->quote($usr_id); $r = $ilDB->query($q); $catchup = null; while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) { $catchup = $row['ts']; }

$q = "SELECT * ". "FROM read_event ". "WHERE obj_id=".$ilDB->quote($obj_id)." ". ($catchup == null ? "" : "AND last_access > ".$ilDB->quote($catchup))." ". ($catchup == null ? "" : "AND last_access > ".$ilDB->quote($catchup))." ". "ORDER BY last_access DESC"; $r = $ilDB->query($q); $events = array(); while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) { $events[] = $row; } return $events; } Reads all read events which occured on the object.

Parameters
$obj_idint The object
$usr_idint Optional, the user who performed these events.

Definition at line 731 of file class.ilChangeEvent.php.

732 {
733 global $DIC;
734
735 $ilDB = $DIC['ilDB'];
736
737 if ($usr_id == null) {
738 $query = sprintf(
739 'SELECT * FROM read_event ' .
740 'WHERE obj_id = %s ' .
741 'ORDER BY last_access DESC',
742 $ilDB->quote($obj_id, 'integer')
743 );
744 $res = $ilDB->query($query);
745 } else {
746 $query = sprintf(
747 'SELECT * FROM read_event ' .
748 'WHERE obj_id = %s ' .
749 'AND usr_id = %s ' .
750 'ORDER BY last_access DESC',
751 $ilDB->quote($obj_id, 'integer'),
752 $ilDB->quote($usr_id, 'integer')
753 );
754 $res = $ilDB->query($query);
755 }
756
757 $counter = 0;
758 while ($row = $ilDB->fetchAssoc($res)) {
759 $events[$counter]['obj_id'] = $row['obj_id'];
760 $events[$counter]['usr_id'] = $row['usr_id'];
761 $events[$counter]['last_access'] = $row['last_access'];
762 $events[$counter]['read_count'] = $row['read_count'];
763 $events[$counter]['spent_seconds'] = $row['spent_seconds'];
764 $events[$counter]['first_access'] = $row['first_access'];
765
766 $counter++;
767 }
768 return $events ? $events : array();
769 }

References $DIC, $ilDB, $query, and $res.

Referenced by ilLPStatusContentVisited\_getCompleted(), ilLPStatusTypicalLearningTime\_getCompleted(), ilLPStatusVisits\_getCompleted(), ilLPStatusTypicalLearningTime\_getInProgress(), ilLPStatusVisits\_getInProgress(), ilLearningProgress\_getProgress(), ilLearningProgress\_lookupProgressByObjId(), ilInfoScreenGUI\addObjectSections(), ilLPStatusTypicalLearningTime\determinePercentage(), ilLPStatusVisits\determinePercentage(), ilLPStatusTypicalLearningTime\determineStatus(), ilLPStatusVisits\determineStatus(), and ilSCORMOfflineMode\il2sopSahsUser().

+ Here is the caller graph for this function:

◆ _lookupUncaughtWriteEvents()

static ilChangeEvent::_lookupUncaughtWriteEvents (   $obj_id,
  $usr_id 
)
static

Catches up with all write events which occured before the specified timestamp.

THIS FUNCTION IS CURRENTLY NOT IN USE. BEFORE IT CAN BE USED, THE TABLE catch_read_events MUST BE CREATED.

Parameters
$obj_idint The object.
$usr_idint The user.
$timestampSQL timestamp. / function _catchupReadEvents($obj_id, $usr_id, $timestamp = null) { global $DIC;

$ilDB = $DIC['ilDB'];

$q = "INSERT INTO catch_read_events ".
    "(obj_id, usr_id, action, ts) ".
    "VALUES (".
    $ilDB->quote($obj_id).",".
    $ilDB->quote($usr_id).",".
    $ilDB->quote('read').",";
if ($timestamp == null)
{
    $q .= "NOW()".
    ") ON DUPLICATE KEY UPDATE ts=NOW()";
}
else {
    $q .= $ilDB->quote($timestamp).
    ") ON DUPLICATE KEY UPDATE ts=".$ilDB->quote($timestamp);
}

$r = $ilDB->query($q);

} Reads all write events which occured on the object which happened after the last time the user caught up with them.

Parameters
$obj_idint The object
$usr_idint The user who is interested into these events.
Returns
array with rows from table write_event

Definition at line 579 of file class.ilChangeEvent.php.

580 {
581 global $DIC;
582
583 $ilDB = $DIC['ilDB'];
584
585 $q = "SELECT ts " .
586 "FROM catch_write_events " .
587 "WHERE obj_id=" . $ilDB->quote($obj_id, 'integer') . " " .
588 "AND usr_id=" . $ilDB->quote($usr_id, 'integer');
589 $r = $ilDB->query($q);
590 $catchup = null;
591 while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
592 $catchup = $row['ts'];
593 }
594
595 if ($catchup == null) {
596 $query = sprintf(
597 'SELECT * FROM write_event ' .
598 'WHERE obj_id = %s ' .
599 'AND usr_id <> %s ' .
600 'ORDER BY ts DESC',
601 $ilDB->quote($obj_id, 'integer'),
602 $ilDB->quote($usr_id, 'integer')
603 );
604 $res = $ilDB->query($query);
605 } else {
606 $query = sprintf(
607 'SELECT * FROM write_event ' .
608 'WHERE obj_id = %s ' .
609 'AND usr_id <> %s ' .
610 'AND ts >= %s ' .
611 'ORDER BY ts DESC',
612 $ilDB->quote($obj_id, 'integer'),
613 $ilDB->quote($usr_id, 'integer'),
614 $ilDB->quote($catchup, 'timestamp')
615 );
616 $res = $ilDB->query($query);
617 }
618 $events = array();
619 while ($row = $ilDB->fetchAssoc($res)) {
620 $events[] = $row;
621 }
622 return $events;
623 }

References $DIC, $ilDB, $query, $res, and ilDBConstants\FETCHMODE_ASSOC.

Referenced by ilTrackingTest\testChangeEvent().

+ Here is the caller graph for this function:

◆ _recordObjStats()

static ilChangeEvent::_recordObjStats (   $a_obj_id,
  $a_spent_seconds,
  $a_read_count,
  $a_childs_spent_seconds = null,
  $a_child_read_count = null 
)
static

Definition at line 322 of file class.ilChangeEvent.php.

323 {
324 global $DIC;
325
326 $ilDB = $DIC['ilDB'];
327
329 (int) $a_obj_id <= 0) { // #12706
330 return;
331 }
332
333 $now = time();
334
335 $fields = array();
336 $fields['log_id'] = array("integer", $ilDB->nextId('obj_stat_log'));
337 $fields["obj_id"] = array("integer", $a_obj_id);
338 $fields["obj_type"] = array("text", ilObject::_lookupType($a_obj_id));
339 $fields["tstamp"] = array("timestamp", $now);
340 $fields["yyyy"] = array("integer", date("Y"));
341 $fields["mm"] = array("integer", date("m"));
342 $fields["dd"] = array("integer", date("d"));
343 $fields["hh"] = array("integer", date("H"));
344 if ($a_spent_seconds > 0) {
345 $fields["spent_seconds"] = array("integer", $a_spent_seconds);
346 }
347 if ($a_read_count > 0) {
348 $fields["read_count"] = array("integer", $a_read_count);
349 }
350 if ($a_childs_spent_seconds > 0) {
351 $fields["childs_spent_seconds"] = array("integer", $a_childs_spent_seconds);
352 }
353 if ($a_child_read_count > 0) {
354 $fields["childs_read_count"] = array("integer", $a_child_read_count);
355 }
356 $ilDB->insert("obj_stat_log", $fields);
357
358 // 0.01% probability
359 if (mt_rand(1, 100) == 1) {
361 }
362 }
static _syncObjectStats($a_now=null, $a_minimum=20000)
Process object statistics log data.
static _enabledObjectStatistics()
check wether object statistics is enabled or not
static _lookupType($a_id, $a_reference=false)
lookup object type

References $DIC, $ilDB, ilObjUserTracking\_enabledObjectStatistics(), ilObject\_lookupType(), and _syncObjectStats().

Referenced by _recordReadEvent().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _recordReadEvent()

static ilChangeEvent::_recordReadEvent (   $a_type,
  $a_ref_id,
  $obj_id,
  $usr_id,
  $isCatchupWriteEvents = true,
  $a_ext_rc = false,
  $a_ext_time = false 
)
static

Records a read event and catches up with write events.

Parameters
$obj_idint The object which was read.
$usr_idint The user who performed a read action.
$catchupWriteEventsboolean If true, this function catches up with write events.

Definition at line 113 of file class.ilChangeEvent.php.

121 {
122 global $DIC;
123
124 $ilDB = $DIC['ilDB'];
125 $tree = $DIC['tree'];
126
127 /* read_event data is now used for several features, so we are always keeping track
128 if (!ilChangeEvent::_isActive())
129 {
130 return;
131 }
132 */
133
134 include_once('Services/Tracking/classes/class.ilObjUserTracking.php');
135 $validTimeSpan = ilObjUserTracking::_getValidTimeSpan();
136
137 $query = sprintf(
138 'SELECT * FROM read_event ' .
139 'WHERE obj_id = %s ' .
140 'AND usr_id = %s ',
141 $ilDB->quote($obj_id, 'integer'),
142 $ilDB->quote($usr_id, 'integer')
143 );
144 $res = $ilDB->query($query);
145 $row = $ilDB->fetchObject($res);
146
147 // read counter
148 if ($a_ext_rc !== false) {
149 $read_count = 'read_count = ' . $ilDB->quote($a_ext_rc, "integer") . ", ";
150 $read_count_init = max(1, (int) $a_ext_rc);
151 $read_count_diff = max(1, (int) $a_ext_rc) - $row->read_count;
152 } else {
153 $read_count = 'read_count = read_count + 1, ';
154 $read_count_init = 1;
155 $read_count_diff = 1;
156 }
157
158 if ($row) {
159 if ($a_ext_time !== false) {
160 $time = (int) $a_ext_time;
161 } else {
162 $time = $ilDB->quote((time() - $row->last_access) <= $validTimeSpan
163 ? $row->spent_seconds + time() - $row->last_access
164 : $row->spent_seconds, 'integer');
165
166 // if we are in the valid interval, we do not
167 // add anything to the read_count, since this is the
168 // same access for us
169 if ((time() - $row->last_access) <= $validTimeSpan) {
170 $read_count = '';
171 $read_count_init = 1;
172 $read_count_diff = 0;
173 }
174 }
175 $time_diff = $time - (int) $row->spent_seconds;
176
177 // Update
178 $query = sprintf(
179 'UPDATE read_event SET ' .
180 $read_count .
181 'spent_seconds = %s, ' .
182 'last_access = %s ' .
183 'WHERE obj_id = %s ' .
184 'AND usr_id = %s ',
185 $time,
186 $ilDB->quote(time(), 'integer'),
187 $ilDB->quote($obj_id, 'integer'),
188 $ilDB->quote($usr_id, 'integer')
189 );
190 $aff = $ilDB->manipulate($query);
191
192 self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
193 } else {
194 if ($a_ext_time !== false) {
195 $time = (int) $a_ext_time;
196 } else {
197 $time = 0;
198 }
199
200 $time_diff = $time - (int) $row->spent_seconds;
201
202 /*
203 $query = sprintf('INSERT INTO read_event (obj_id,usr_id,last_access,read_count,spent_seconds,first_access) '.
204 'VALUES (%s,%s,%s,%s,%s,'.$ilDB->now().') ',
205 $ilDB->quote($obj_id,'integer'),
206 $ilDB->quote($usr_id,'integer'),
207 $ilDB->quote(time(),'integer'),
208 $ilDB->quote($read_count_init,'integer'),
209 $ilDB->quote($time,'integer'));
210 $ilDB->manipulate($query);
211 */
212
213 // #10407
214 $ilDB->replace(
215 'read_event',
216 array(
217 'obj_id' => array('integer', $obj_id),
218 'usr_id' => array('integer', $usr_id)
219 ),
220 array(
221 'read_count' => array('integer', $read_count_init),
222 'spent_seconds' => array('integer', $time),
223 'first_access' => array('timestamp', date("Y-m-d H:i:s")), // was $ilDB->now()
224 'last_access' => array('integer', time())
225 )
226 );
227
228 self::$has_accessed[$obj_id][$usr_id] = true;
229
230 self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
231 }
232
233 if ($isCatchupWriteEvents) {
234 ilChangeEvent::_catchupWriteEvents($obj_id, $usr_id);
235 }
236
237 // update parents (no categories or root)
238 if (!in_array($a_type, array("cat", "root", "crs"))) {
239 if ($tree->isInTree($a_ref_id)) {
240 $path = $tree->getPathId($a_ref_id);
241
242 foreach ($path as $p) {
243 $obj2_id = ilObject::_lookupObjId($p);
244 $obj2_type = ilObject::_lookupType($obj2_id);
245 //echo "<br>1-$obj2_type-$p-$obj2_id-";
246 if (($p != $a_ref_id) && (in_array($obj2_type, array("crs", "fold", "grp", "lso")))) {
247 $query = sprintf(
248 'SELECT * FROM read_event ' .
249 'WHERE obj_id = %s ' .
250 'AND usr_id = %s ',
251 $ilDB->quote($obj2_id, 'integer'),
252 $ilDB->quote($usr_id, 'integer')
253 );
254 $res2 = $ilDB->query($query);
255 if ($row2 = $ilDB->fetchAssoc($res2)) {
256 //echo "<br>2";
257 // update read count and spent seconds
258 $query = sprintf(
259 'UPDATE read_event SET ' .
260 'childs_read_count = childs_read_count + %s ,' .
261 'childs_spent_seconds = childs_spent_seconds + %s ' .
262 'WHERE obj_id = %s ' .
263 'AND usr_id = %s ',
264 $ilDB->quote((int) $read_count_diff, 'integer'),
265 $ilDB->quote((int) $time_diff, 'integer'),
266 $ilDB->quote($obj2_id, 'integer'),
267 $ilDB->quote($usr_id, 'integer')
268 );
269 $aff = $ilDB->manipulate($query);
270
271 self::_recordObjStats($obj2_id, null, null, (int) $time_diff, (int) $read_count_diff);
272 } else {
273 //echo "<br>3";
274 //$ilLog->write("insert read event for obj_id -".$obj2_id."-".$usr_id."-");
275 /*
276 $query = sprintf('INSERT INTO read_event (obj_id,usr_id,last_access,read_count,spent_seconds,first_access,'.
277 'childs_read_count, childs_spent_seconds) '.
278 'VALUES (%s,%s,%s,%s,%s,'.$ilDB->now().', %s, %s) ',
279 $ilDB->quote($obj2_id,'integer'),
280 $ilDB->quote($usr_id,'integer'),
281 $ilDB->quote(time(),'integer'),
282 $ilDB->quote(1,'integer'),
283 $ilDB->quote($time,'integer'),
284 $ilDB->quote((int) $read_count_diff,'integer'),
285 $ilDB->quote((int) $time_diff,'integer')
286 );
287 $aff = $ilDB->manipulate($query);
288 */
289
290 // #10407
291 $ilDB->replace(
292 'read_event',
293 array(
294 'obj_id' => array('integer', $obj2_id),
295 'usr_id' => array('integer', $usr_id)
296 ),
297 array(
298 'read_count' => array('integer', 1),
299 'spent_seconds' => array('integer', $time),
300 'first_access' => array('timestamp', date("Y-m-d H:i:s")), // was $ilDB->now()
301 'last_access' => array('integer', time()),
302 'childs_read_count' => array('integer', (int) $read_count_diff),
303 'childs_spent_seconds' => array('integer', (int) $time_diff)
304 )
305 );
306
307 self::$has_accessed[$obj2_id][$usr_id] = true;
308
309 self::_recordObjStats($obj2_id, $time, 1, (int) $time_diff, (int) $read_count_diff);
310 }
311 }
312 }
313 }
314 }
315
316 // @todo:
317 // - calculate diff of spent_seconds and read_count
318 // - use ref id to get parents of types grp, crs, fold
319 // - add diffs to childs_spent_seconds and childs_read_count
320 }
static _recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds=null, $a_child_read_count=null)
static _catchupWriteEvents($obj_id, $usr_id, $timestamp=null)
Catches up with all write events which occured before the specified timestamp.
static _lookupObjId($a_id)

References $DIC, $ilDB, $query, $res, _catchupWriteEvents(), ilObjUserTracking\_getValidTimeSpan(), ilObject\_lookupObjId(), ilObject\_lookupType(), and _recordObjStats().

Referenced by ilObjSCORMTracking\_syncReadEvent(), ilSCORM2004Tracking\_syncReadEvent(), ilLearningProgress\_tracProgress(), ilRemoteObjectBaseGUI\callObject(), ilSurveyExecutionGUI\executeCommand(), ilObjMediaCast\handleLPUpdate(), ilObjSCORMLearningModule\importSuccessForSahsUser(), ilWikiPageGUI\increaseViewCount(), ilObjSessionGUI\infoScreen(), ilContainerGUI\performPasteIntoMultipleObjectsObject(), ilObjIndividualAssessmentGUI\recordIndividualAssessmentRead(), ilObjLearningSequenceGUI\recordLearningSequenceRead(), ilObjLinkResourceGUI\redirectToLink(), ilObjPortfolioBaseGUI\renderFullscreenHeader(), ilObjBlogGUI\renderFullscreenHeader(), ilObjCategoryGUI\renderObject(), ilObjFileGUI\sendFile(), ilContainerContentGUI\setOutput(), ilObjMediaCastGUI\showContentObject(), ilObjSCORMTracking\syncGlobalStatus(), ilLMTracker\trackAccess(), ilLTIConsumerLPStatus\trackAccess(), ilObjCmiXapiGUI\trackObjectReadEvent(), ilObjLTIConsumerGUI\trackObjectReadEvent(), ilObjContentPage\trackProgress(), ilObjTestGUI\trackTestObjectReadEvent(), ilCourseContentGUI\view(), and ilObjectGUI\viewObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _recordWriteEvent()

static ilChangeEvent::_recordWriteEvent (   $obj_id,
  $usr_id,
  $action,
  $parent_obj_id = null 
)
static

Records a write event.

The parent object should be specified for the 'delete', 'undelete' and 'add' and 'remove' events.

Parameters
$obj_idint The object which was written to.
$usr_idint The user who performed a write action.
$actionstring The name of the write action. 'create', 'update', 'delete', 'add', 'remove', 'undelete'.
$parent_obj_idint The object id of the parent object. If this is null, then the event is recorded for all parents of the object. If this is not null, then the event is only recorded for the specified parent.

Definition at line 55 of file class.ilChangeEvent.php.

56 {
57 global $DIC;
58
59 $ilDB = $DIC['ilDB'];
60
61 /* see _recordReadEvent
62 if (!ilChangeEvent::_isActive())
63 {
64 return;
65 }
66 */
67
68 if ($parent_obj_id == null) {
69 $pset = $ilDB->query('SELECT r2.obj_id par_obj_id FROM object_reference r1 ' .
70 'JOIN tree t ON t.child = r1.ref_id ' .
71 'JOIN object_reference r2 ON r2.ref_id = t.parent ' .
72 'WHERE r1.obj_id = ' . $ilDB->quote($obj_id, 'integer'));
73
74 while ($prec = $ilDB->fetchAssoc($pset)) {
75 $nid = $ilDB->nextId("write_event");
76 $query = sprintf(
77 'INSERT INTO write_event ' .
78 '(write_id, obj_id, parent_obj_id, usr_id, action, ts) VALUES ' .
79 '(%s, %s, %s, %s, %s, ' . $ilDB->now() . ')',
80 $ilDB->quote($nid, 'integer'),
81 $ilDB->quote($obj_id, 'integer'),
82 $ilDB->quote($prec["par_obj_id"], 'integer'),
83 $ilDB->quote($usr_id, 'integer'),
84 $ilDB->quote($action, 'text')
85 );
86
87 $aff = $ilDB->manipulate($query);
88 }
89 } else {
90 $nid = $ilDB->nextId("write_event");
91 $query = sprintf(
92 'INSERT INTO write_event ' .
93 '(write_id, obj_id, parent_obj_id, usr_id, action, ts) ' .
94 'VALUES (%s,%s,%s,%s,%s,' . $ilDB->now() . ')',
95 $ilDB->quote($nid, 'integer'),
96 $ilDB->quote($obj_id, 'integer'),
97 $ilDB->quote($parent_obj_id, 'integer'),
98 $ilDB->quote($usr_id, 'integer'),
99 $ilDB->quote($action, 'text')
100 );
101 $aff = $ilDB->manipulate($query);
102 }
103 }

References $DIC, $ilDB, and $query.

Referenced by ilObjCourseGUI\afterSave(), ilContainerGUI\pasteObject(), ilContainerGUI\performPasteIntoMultipleObjectsObject(), ilObject2GUI\putObjectInTree(), ilObjectGUI\putObjectInTree(), ilRepUtil\removeObjectsFromSystem(), ilRepUtil\restoreObjects(), ilObjFileGUI\update(), ilObjCategoryGUI\updateObject(), ilObjCourseGUI\updateObject(), and ilObjGroupGUI\updateObject().

+ Here is the caller graph for this function:

◆ _syncObjectStats()

static ilChangeEvent::_syncObjectStats (   $a_now = null,
  $a_minimum = 20000 
)
static

Process object statistics log data.

Parameters
integer$a_now
integer$a_minimum

Definition at line 370 of file class.ilChangeEvent.php.

371 {
372 global $DIC;
373
374 $ilDB = $DIC['ilDB'];
375
376 if (!$a_now) {
377 $a_now = time();
378 }
379
380 set_time_limit(0);
381
382 // has source table enough entries?
383 $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
384 $row = $ilDB->fetchAssoc($set);
385 if ($row["counter"] >= $a_minimum) {
386 $ilAtomQuery = $ilDB->buildAtomQuery();
387 $ilAtomQuery->addTableLock('obj_stat_log');
388 $ilAtomQuery->addTableLock('obj_stat_tmp');
389
390 $ilAtomQuery->addQueryCallable(function (ilDBInterface $ilDB) use ($a_now, $a_minimum, &$ret) {
391
392 // if other process was transferring, we had to wait for the lock and
393 // the source table should now have less than minimum/needed entries
394 $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
395 $row = $ilDB->fetchAssoc($set);
396 if ($row["counter"] >= $a_minimum) {
397 // use only "full" seconds to have a clear cut
398 $ilDB->query("INSERT INTO obj_stat_tmp" .
399 " SELECT * FROM obj_stat_log" .
400 " WHERE tstamp < " . $ilDB->quote($a_now, "timestamp"));
401
402 // remove transferred entries from source table
403 $ilDB->query("DELETE FROM obj_stat_log" .
404 " WHERE tstamp < " . $ilDB->quote($a_now, "timestamp"));
405
406 $ret = true;
407 } else {
408 $ret = false;
409 }
410 });
411
412 $ilAtomQuery->run();
413
414 //continue only if obj_stat_log counter >= $a_minimum
415 if ($ret) {
416 $ilAtomQuery = $ilDB->buildAtomQuery();
417 $ilAtomQuery->addTableLock('obj_stat_tmp');
418 $ilAtomQuery->addTableLock('obj_stat');
419
420 $ilAtomQuery->addQueryCallable(function (ilDBInterface $ilDB) use ($a_now, $a_minimum) {
421
422 // process log data (timestamp is not needed anymore)
423 $sql = "SELECT obj_id, obj_type, yyyy, mm, dd, hh, SUM(read_count) AS read_count," .
424 " SUM(childs_read_count) AS childs_read_count, SUM(spent_seconds) AS spent_seconds," .
425 " SUM(childs_spent_seconds) AS childs_spent_seconds" .
426 " FROM obj_stat_tmp" .
427 " GROUP BY obj_id, obj_type, yyyy, mm, dd, hh";
428 $set = $ilDB->query($sql);
429 while ($row = $ilDB->fetchAssoc($set)) {
430 // "primary key"
431 $where = array("obj_id" => array("integer", $row["obj_id"]),
432 "obj_type" => array("text", $row["obj_type"]),
433 "yyyy" => array("integer", $row["yyyy"]),
434 "mm" => array("integer", $row["mm"]),
435 "dd" => array("integer", $row["dd"]),
436 "hh" => array("integer", $row["hh"]));
437
438 $where_sql = array();
439 foreach ($where as $field => $def) {
440 $where_sql[] = $field . " = " . $ilDB->quote($def[1], $def[0]);
441 }
442 $where_sql = implode(" AND ", $where_sql);
443
444 // existing entry?
445 $check = $ilDB->query("SELECT read_count, childs_read_count, spent_seconds," .
446 "childs_spent_seconds" .
447 " FROM obj_stat" .
448 " WHERE " . $where_sql);
449 if ($ilDB->numRows($check)) {
450 $old = $ilDB->fetchAssoc($check);
451
452 // add existing values
453 $fields = array("read_count" => array("integer", $old["read_count"] + $row["read_count"]),
454 "childs_read_count" => array("integer", $old["childs_read_count"] + $row["childs_read_count"]),
455 "spent_seconds" => array("integer", $old["spent_seconds"] + $row["spent_seconds"]),
456 "childs_spent_seconds" => array("integer", $old["childs_spent_seconds"] + $row["childs_spent_seconds"]));
457
458 $ilDB->update("obj_stat", $fields, $where);
459 } else {
460 // new entry
461 $fields = $where;
462 $fields["read_count"] = array("integer", $row["read_count"]);
463 $fields["childs_read_count"] = array("integer", $row["childs_read_count"]);
464 $fields["spent_seconds"] = array("integer", $row["spent_seconds"]);
465 $fields["childs_spent_seconds"] = array("integer", $row["childs_spent_seconds"]);
466
467 $ilDB->insert("obj_stat", $fields);
468 }
469 }
470
471 // clean up transfer table
472 $ilDB->query("DELETE FROM obj_stat_tmp");
473 });
474
475 $ilAtomQuery->run();
476 }
477 }
478 }
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$ret
Definition: parser.php:6

References $DIC, $ilDB, and $ret.

Referenced by _recordObjStats(), and ilLPObjectStatisticsGUI\adminSync().

+ Here is the caller graph for this function:

◆ _updateAccessForScormOfflinePlayer()

static ilChangeEvent::_updateAccessForScormOfflinePlayer (   $obj_id,
  $usr_id,
  $i_last_access,
  $t_first_access 
)
static

_updateAccessForScormOfflinePlayer needed to synchronize last_access and first_access when learning modul is used offline called in .

/Modules/ScormAicc/classes/class.ilSCORMOfflineMode.php

Returns
true

Definition at line 968 of file class.ilChangeEvent.php.

969 {
970 global $DIC;
971
972 $ilDB = $DIC['ilDB'];
973 $res = $ilDB->queryF(
974 'UPDATE read_event SET first_access=%s, last_access = %s WHERE obj_id=%s AND usr_id=%s',
975 array('timestamp','integer','integer','integer'),
976 array($t_first_access,$i_last_access,$obj_id,$usr_id)
977 );
978 return $res;
979 }

References $DIC, $ilDB, and $res.

Referenced by ilSCORMOfflineMode\scormPlayerUnloadForSop2il().

+ Here is the caller graph for this function:

◆ hasAccessed()

static ilChangeEvent::hasAccessed (   $a_obj_id,
  $a_usr_id 
)
static

Has accessed.

Definition at line 798 of file class.ilChangeEvent.php.

799 {
800 global $DIC;
801
802 $ilDB = $DIC['ilDB'];
803
804 if (isset(self::$has_accessed[$a_obj_id][$a_usr_id])) {
805 return self::$has_accessed[$a_obj_id][$a_usr_id];
806 }
807
808 $set = $ilDB->query(
809 "SELECT usr_id FROM read_event WHERE " .
810 "obj_id = " . $ilDB->quote($a_obj_id, "integer") . " AND " .
811 "usr_id = " . $ilDB->quote($a_usr_id, "integer")
812 );
813 if ($rec = $ilDB->fetchAssoc($set)) {
814 return self::$has_accessed[$a_obj_id][$a_usr_id] = true;
815 }
816 return self::$has_accessed[$a_obj_id][$a_usr_id] = false;
817 }

References $DIC, and $ilDB.

Referenced by ilLPStatusCollection\determineStatus(), ilLPStatusCollectionMobs\determineStatus(), ilLPStatusExerciseReturned\determineStatus(), ilLPStatusManual\determineStatus(), ilLPStatusManualByTutor\determineStatus(), ilLPStatusObjectives\determineStatus(), ilLPStatusQuestions\determineStatus(), ilLPStatusSCORM\determineStatus(), ilLPStatusTypicalLearningTime\determineStatus(), ilLPStatusVisitedPages\determineStatus(), and ilLPStatusVisits\determineStatus().

+ Here is the caller graph for this function:

◆ lookupUsersInProgress()

static ilChangeEvent::lookupUsersInProgress (   $a_obj_id)
static

Lookup users in progress.

Returns

Definition at line 777 of file class.ilChangeEvent.php.

778 {
779 global $DIC;
780
781 $ilDB = $DIC['ilDB'];
782
783 $query = sprintf(
784 'SELECT DISTINCT(usr_id) usr FROM read_event ' .
785 'WHERE obj_id = %s ',
786 $ilDB->quote($a_obj_id, 'integer')
787 );
788 $res = $ilDB->query($query);
789 while ($row = $ilDB->fetchObject($res)) {
790 $users[] = $row->usr;
791 }
792 return $users ? $users : array();
793 }

References $DIC, $ilDB, $query, and $res.

Referenced by ilLPStatusQuestions\_getCompleted(), ilLPStatusCollection\_getInProgress(), ilLPStatusExerciseReturned\_getInProgress(), ilLPStatusManual\_getInProgress(), ilLPStatusManualByTutor\_getInProgress(), ilLPStatusQuestions\_getInProgress(), ilLPStatusVisitedPages\_getInProgress(), ilLPStatusObjectives\_getStatusInfo(), and ilLPStatusCollectionMobs\_getStatusInfo().

+ Here is the caller graph for this function:

Field Documentation

◆ $has_accessed

ilChangeEvent::$has_accessed = array()
staticprivate

Definition at line 38 of file class.ilChangeEvent.php.


The documentation for this class was generated from the following file: