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'));
74 while ($prec =
$ilDB->fetchAssoc($pset)) {
75 $nid =
$ilDB->nextId(
"write_event");
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'),
90 $nid =
$ilDB->nextId(
"write_event");
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'),
118 $isCatchupWriteEvents =
true,
124 $ilDB = $DIC[
'ilDB'];
125 $tree = $DIC[
'tree'];
134 include_once(
'Services/Tracking/classes/class.ilObjUserTracking.php');
138 'SELECT * FROM read_event ' .
139 'WHERE obj_id = %s ' .
141 $ilDB->quote($obj_id,
'integer'),
142 $ilDB->quote($usr_id,
'integer')
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;
153 $read_count =
'read_count = read_count + 1, ';
154 $read_count_init = 1;
155 $read_count_diff = 1;
159 if ($a_ext_time !==
false) {
160 $time = (int) $a_ext_time;
162 $time =
$ilDB->quote((time() -
$row->last_access) <= $validTimeSpan
163 ?
$row->spent_seconds + time() -
$row->last_access
164 :
$row->spent_seconds,
'integer');
169 if ((time() -
$row->last_access) <= $validTimeSpan) {
171 $read_count_init = 1;
172 $read_count_diff = 0;
179 'UPDATE read_event SET ' .
181 'spent_seconds = %s, ' .
182 'last_access = %s ' .
183 'WHERE obj_id = %s ' .
186 $ilDB->quote(time(),
'integer'),
187 $ilDB->quote($obj_id,
'integer'),
188 $ilDB->quote($usr_id,
'integer')
192 self::_recordObjStats($obj_id,
$time_diff, $read_count_diff);
194 if ($a_ext_time !==
false) {
195 $time = (int) $a_ext_time;
217 'obj_id' => array(
'integer', $obj_id),
218 'usr_id' => array(
'integer', $usr_id)
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")),
224 'last_access' => array(
'integer', time())
228 self::$has_accessed[$obj_id][$usr_id] =
true;
230 self::_recordObjStats($obj_id,
$time_diff, $read_count_diff);
233 if ($isCatchupWriteEvents) {
238 if (!in_array(
$a_type, array(
"cat",
"root",
"crs"))) {
239 if (
$tree->isInTree($a_ref_id)) {
242 foreach (
$path as $p) {
246 if (($p != $a_ref_id) && (in_array($obj2_type, array(
"crs",
"fold",
"grp",
"lso")))) {
248 'SELECT * FROM read_event ' .
249 'WHERE obj_id = %s ' .
251 $ilDB->quote($obj2_id,
'integer'),
252 $ilDB->quote($usr_id,
'integer')
255 if ($row2 =
$ilDB->fetchAssoc($res2)) {
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 ' .
264 $ilDB->quote((
int) $read_count_diff,
'integer'),
266 $ilDB->quote($obj2_id,
'integer'),
267 $ilDB->quote($usr_id,
'integer')
271 self::_recordObjStats($obj2_id, null, null, (
int) $time_diff, (
int) $read_count_diff);
294 'obj_id' => array(
'integer', $obj2_id),
295 'usr_id' => array(
'integer', $usr_id)
298 'read_count' => array(
'integer', 1),
299 'spent_seconds' => array(
'integer',
$time),
300 'first_access' => array(
'timestamp', date(
"Y-m-d H:i:s")),
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)
307 self::$has_accessed[$obj2_id][$usr_id] =
true;
309 self::_recordObjStats($obj2_id,
$time, 1, (
int) $time_diff, (
int) $read_count_diff);
322 public static function _recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds = null, $a_child_read_count = null)
326 $ilDB = $DIC[
'ilDB'];
329 (
int) $a_obj_id <= 0) {
336 $fields[
'log_id'] = array(
"integer",
$ilDB->nextId(
'obj_stat_log'));
337 $fields[
"obj_id"] = array(
"integer", $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);
347 if ($a_read_count > 0) {
348 $fields[
"read_count"] = array(
"integer", $a_read_count);
350 if ($a_childs_spent_seconds > 0) {
351 $fields[
"childs_spent_seconds"] = array(
"integer", $a_childs_spent_seconds);
353 if ($a_child_read_count > 0) {
354 $fields[
"childs_read_count"] = array(
"integer", $a_child_read_count);
356 $ilDB->insert(
"obj_stat_log", $fields);
359 if (mt_rand(1, 100) == 1) {
360 self::_syncObjectStats($now);
374 $ilDB = $DIC[
'ilDB'];
383 $set =
$ilDB->query(
"SELECT COUNT(*) AS counter FROM obj_stat_log");
385 if (
$row[
"counter"] >= $a_minimum) {
386 $ilAtomQuery =
$ilDB->buildAtomQuery();
387 $ilAtomQuery->addTableLock(
'obj_stat_log');
388 $ilAtomQuery->addTableLock(
'obj_stat_tmp');
394 $set = $ilDB->
query(
"SELECT COUNT(*) AS counter FROM obj_stat_log");
396 if (
$row[
"counter"] >= $a_minimum) {
398 $ilDB->
query(
"INSERT INTO obj_stat_tmp" .
399 " SELECT * FROM obj_stat_log" .
400 " WHERE tstamp < " . $ilDB->
quote($a_now,
"timestamp"));
403 $ilDB->
query(
"DELETE FROM obj_stat_log" .
404 " WHERE tstamp < " . $ilDB->
quote($a_now,
"timestamp"));
417 $ilAtomQuery->addTableLock(
'obj_stat_tmp');
418 $ilAtomQuery->addTableLock(
'obj_stat');
420 $ilAtomQuery->addQueryCallable(
function (
ilDBInterface $ilDB) use ($a_now, $a_minimum) {
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);
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"]));
438 $where_sql = array();
439 foreach ($where as $field =>
$def) {
440 $where_sql[] = $field .
" = " . $ilDB->
quote(
$def[1],
$def[0]);
442 $where_sql = implode(
" AND ", $where_sql);
445 $check = $ilDB->
query(
"SELECT read_count, childs_read_count, spent_seconds," .
446 "childs_spent_seconds" .
448 " WHERE " . $where_sql);
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"]));
458 $ilDB->
update(
"obj_stat", $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"]);
467 $ilDB->
insert(
"obj_stat", $fields);
472 $ilDB->
query(
"DELETE FROM obj_stat_tmp");
492 $ilDB = $DIC[
'ilDB'];
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');
498 if (
$res->numRows()) {
520 "catch_write_events",
522 "obj_id" => array(
"integer", $obj_id),
523 "usr_id" => array(
"integer", $usr_id)
526 "ts" => array(
"timestamp", $ts))
583 $ilDB = $DIC[
'ilDB'];
586 "FROM catch_write_events " .
587 "WHERE obj_id=" .
$ilDB->quote($obj_id,
'integer') .
" " .
588 "AND usr_id=" .
$ilDB->quote($usr_id,
'integer');
592 $catchup =
$row[
'ts'];
595 if ($catchup == null) {
597 'SELECT * FROM write_event ' .
598 'WHERE obj_id = %s ' .
599 'AND usr_id <> %s ' .
601 $ilDB->quote($obj_id,
'integer'),
602 $ilDB->quote($usr_id,
'integer')
607 'SELECT * FROM write_event ' .
608 'WHERE obj_id = %s ' .
609 'AND usr_id <> %s ' .
612 $ilDB->quote($obj_id,
'integer'),
613 $ilDB->quote($usr_id,
'integer'),
614 $ilDB->quote($catchup,
'timestamp')
638 $ilDB = $DIC[
'ilDB'];
641 "FROM catch_write_events " .
642 "WHERE obj_id=" .
$ilDB->quote($obj_id,
'integer') .
" " .
643 "AND usr_id=" .
$ilDB->quote($usr_id,
'integer');
647 $catchup =
$row[
'ts'];
650 if ($catchup == null) {
653 'SELECT * FROM write_event ' .
654 'WHERE obj_id = %s ' .
656 $ilDB->quote($obj_id,
'integer'),
657 $ilDB->quote($usr_id,
'integer')
663 'SELECT * FROM write_event ' .
664 'WHERE obj_id = %s ' .
665 'AND usr_id <> %s ' .
667 $ilDB->quote($obj_id,
'integer'),
668 $ilDB->quote($usr_id,
'integer'),
669 $ilDB->quote($catchup,
'timestamp')
674 $numRows =
$res->numRows();
679 return ($catchup == null) ? 1 : 2;
735 $ilDB = $DIC[
'ilDB'];
737 if ($usr_id == null) {
739 'SELECT * FROM read_event ' .
740 'WHERE obj_id = %s ' .
741 'ORDER BY last_access DESC',
742 $ilDB->quote($obj_id,
'integer')
747 'SELECT * FROM read_event ' .
748 'WHERE obj_id = %s ' .
750 'ORDER BY last_access DESC',
751 $ilDB->quote($obj_id,
'integer'),
752 $ilDB->quote($usr_id,
'integer')
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'];
781 $ilDB = $DIC[
'ilDB'];
784 'SELECT DISTINCT(usr_id) usr FROM read_event ' .
785 'WHERE obj_id = %s ',
786 $ilDB->quote($a_obj_id,
'integer')
789 while (
$row =
$ilDB->fetchObject($res)) {
802 $ilDB = $DIC[
'ilDB'];
804 if (isset(self::$has_accessed[$a_obj_id][$a_usr_id])) {
805 return self::$has_accessed[$a_obj_id][$a_usr_id];
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")
813 if ($rec =
$ilDB->fetchAssoc($set)) {
814 return self::$has_accessed[$a_obj_id][$a_usr_id] =
true;
816 return self::$has_accessed[$a_obj_id][$a_usr_id] =
false;
827 return 'change event tracking is already active';
831 $ilDB = $DIC[
'ilDB'];
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')
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") .
866 $ilSetting->set(
'enable_change_event_tracking',
'1');
882 $ilSetting->set(
'enable_change_event_tracking',
'0');
895 return $ilSetting->get(
'enable_change_event_tracking',
'0') ==
'1';
908 $ilDB = $DIC[
'ilDB'];
911 'DELETE FROM write_event WHERE obj_id = %s ',
912 $ilDB->quote($a_obj_id,
'integer')
917 'DELETE FROM read_event WHERE obj_id = %s ',
918 $ilDB->quote($a_obj_id,
'integer')
928 $ilDB = $DIC[
'ilDB'];
930 $ilDB->manipulate(
"DELETE FROM read_event" .
931 " WHERE obj_id = " .
$ilDB->quote($a_obj_id,
"integer"));
938 $ilDB = $DIC[
'ilDB'];
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"));
949 $ilDB = $DIC[
'ilDB'];
953 $set =
$ilDB->query(
"SELECT usr_id FROM read_event" .
954 " WHERE obj_id = " .
$ilDB->quote($a_obj_id,
"integer"));
972 $ilDB = $DIC[
'ilDB'];
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)
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.
static hasAccessed($a_obj_id, $a_usr_id)
Has accessed.
static _activate()
Activates change event tracking.
static _enabledObjectStatistics()
check wether object statistics is enabled or not
static _recordWriteEvent($obj_id, $usr_id, $action, $parent_obj_id=null)
Records a write event.
static _deleteReadEvents($a_obj_id)
static _getAllUserIds($a_obj_id)
static now()
Return current timestamp in Y-m-d H:i:s format.
update($table_name, $values, $where)
static _catchupWriteEvents($obj_id, $usr_id, $timestamp=null)
Catches up with all write events which occured before the specified timestamp.
static _delete($a_obj_id)
Delete object entries.
static _updateAccessForScormOfflinePlayer($obj_id, $usr_id, $i_last_access, $t_first_access)
_updateAccessForScormOfflinePlayer needed to synchronize last_access and first_access when learning m...
foreach($_POST as $key=> $value) $res
static _lookupObjId($a_id)
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 ...
static _lookupType($a_id, $a_reference=false)
lookup object type
foreach($mandatory_scripts as $file) $timestamp
static _lookupUncaughtWriteEvents($obj_id, $usr_id)
Catches up with all write events which occured before the specified timestamp.
Class ilChangeEvent tracks change events on repository objects.
static _deleteReadEventsForUsers($a_obj_id, array $a_user_ids)
static _isActive()
Returns true, if change event tracking is active.
static _deactivate()
Deactivates change event tracking.
query($query)
Run a (read-only) Query on the database.
static _recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds=null, $a_child_read_count=null)
insert($table_name, $values)
fetchAssoc($query_result)
static _syncObjectStats($a_now=null, $a_minimum=20000)
Process object statistics log data.
static _getValidTimeSpan()
static _lookupChangeState($obj_id, $usr_id)
Returns the change state of the object for the specified user.
static lookupUsersInProgress($a_obj_id)
Lookup users in progress.