66 if ($parent_obj_id == null) {
67 $pset = $ilDB->query(
'SELECT r2.obj_id par_obj_id FROM object_reference r1 ' .
68 'JOIN tree t ON t.child = r1.ref_id ' .
69 'JOIN object_reference r2 ON r2.ref_id = t.parent ' .
70 'WHERE r1.obj_id = ' . $ilDB->quote($obj_id,
'integer'));
72 while ($prec = $ilDB->fetchAssoc($pset)) {
73 $nid = $ilDB->nextId(
"write_event");
75 'INSERT INTO write_event ' .
76 '(write_id, obj_id, parent_obj_id, usr_id, action, ts) VALUES ' .
77 '(%s, %s, %s, %s, %s, ' . $ilDB->now() .
')',
78 $ilDB->quote($nid,
'integer'),
79 $ilDB->quote($obj_id,
'integer'),
80 $ilDB->quote($prec[
"par_obj_id"],
'integer'),
81 $ilDB->quote($usr_id,
'integer'),
85 $aff = $ilDB->manipulate(
$query);
88 $nid = $ilDB->nextId(
"write_event");
90 'INSERT INTO write_event ' .
91 '(write_id, obj_id, parent_obj_id, usr_id, action, ts) ' .
92 'VALUES (%s,%s,%s,%s,%s,' . $ilDB->now() .
')',
93 $ilDB->quote($nid,
'integer'),
94 $ilDB->quote($obj_id,
'integer'),
95 $ilDB->quote($parent_obj_id,
'integer'),
96 $ilDB->quote($usr_id,
'integer'),
99 $aff = $ilDB->manipulate(
$query);
116 $isCatchupWriteEvents =
true,
129 include_once(
'Services/Tracking/classes/class.ilObjUserTracking.php');
133 'SELECT * FROM read_event ' .
134 'WHERE obj_id = %s ' .
136 $ilDB->quote($obj_id,
'integer'),
137 $ilDB->quote($usr_id,
'integer')
140 $row = $ilDB->fetchObject($res);
143 if ($a_ext_rc !==
false) {
144 $read_count =
'read_count = ' . $ilDB->quote($a_ext_rc,
"integer") .
", ";
145 $read_count_init = max(1, (
int) $a_ext_rc);
146 $read_count_diff = max(1, (
int) $a_ext_rc) -
$row->read_count;
148 $read_count =
'read_count = read_count + 1, ';
149 $read_count_init = 1;
150 $read_count_diff = 1;
154 if ($a_ext_time !==
false) {
155 $time = (int) $a_ext_time;
157 $time = $ilDB->quote((
time() -
$row->last_access) <= $validTimeSpan
159 :
$row->spent_seconds,
'integer');
164 if ((
time() -
$row->last_access) <= $validTimeSpan) {
166 $read_count_init = 1;
167 $read_count_diff = 0;
170 $time_diff =
$time - (int)
$row->spent_seconds;
174 'UPDATE read_event SET ' .
176 'spent_seconds = %s, ' .
177 'last_access = %s ' .
178 'WHERE obj_id = %s ' .
181 $ilDB->quote(
time(),
'integer'),
182 $ilDB->quote($obj_id,
'integer'),
183 $ilDB->quote($usr_id,
'integer')
185 $aff = $ilDB->manipulate(
$query);
187 self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
189 if ($a_ext_time !==
false) {
190 $time = (int) $a_ext_time;
195 $time_diff =
$time - (int)
$row->spent_seconds;
212 'obj_id' =>
array(
'integer', $obj_id),
213 'usr_id' =>
array(
'integer', $usr_id)
216 'read_count' =>
array(
'integer', $read_count_init),
218 'first_access' =>
array(
'timestamp',
date(
"Y-m-d H:i:s")),
219 'last_access' =>
array(
'integer',
time())
223 self::$has_accessed[$obj_id][$usr_id] =
true;
225 self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
228 if ($isCatchupWriteEvents) {
234 if ($tree->isInTree($a_ref_id)) {
235 $path = $tree->getPathId($a_ref_id);
237 foreach (
$path as $p) {
241 if (($p != $a_ref_id) && (in_array($obj2_type,
array(
"crs",
"fold",
"grp")))) {
243 'SELECT * FROM read_event ' .
244 'WHERE obj_id = %s ' .
246 $ilDB->quote($obj2_id,
'integer'),
247 $ilDB->quote($usr_id,
'integer')
249 $res2 = $ilDB->query(
$query);
250 if ($row2 = $ilDB->fetchAssoc($res2)) {
254 'UPDATE read_event SET ' .
255 'childs_read_count = childs_read_count + %s ,' .
256 'childs_spent_seconds = childs_spent_seconds + %s ' .
257 'WHERE obj_id = %s ' .
259 $ilDB->quote((
int) $read_count_diff,
'integer'),
260 $ilDB->quote((
int) $time_diff,
'integer'),
261 $ilDB->quote($obj2_id,
'integer'),
262 $ilDB->quote($usr_id,
'integer')
264 $aff = $ilDB->manipulate(
$query);
266 self::_recordObjStats($obj2_id, null, null, (
int) $time_diff, (
int) $read_count_diff);
289 'obj_id' =>
array(
'integer', $obj2_id),
290 'usr_id' =>
array(
'integer', $usr_id)
293 'read_count' =>
array(
'integer', 1),
295 'first_access' =>
array(
'timestamp',
date(
"Y-m-d H:i:s")),
296 'last_access' =>
array(
'integer',
time()),
297 'childs_read_count' =>
array(
'integer', (
int) $read_count_diff),
298 'childs_spent_seconds' =>
array(
'integer', (
int) $time_diff)
302 self::$has_accessed[$obj2_id][$usr_id] =
true;
304 self::_recordObjStats($obj2_id,
$time, 1, (
int) $time_diff, (
int) $read_count_diff);
317 public static function _recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds = null, $a_child_read_count = null)
322 (
int) $a_obj_id <= 0) {
329 $fields[
'log_id'] =
array(
"integer", $ilDB->nextId(
'obj_stat_log'));
330 $fields[
"obj_id"] =
array(
"integer", $a_obj_id);
332 $fields[
"tstamp"] =
array(
"timestamp", $now);
333 $fields[
"yyyy"] =
array(
"integer",
date(
"Y"));
334 $fields[
"mm"] =
array(
"integer",
date(
"m"));
335 $fields[
"dd"] =
array(
"integer",
date(
"d"));
336 $fields[
"hh"] =
array(
"integer",
date(
"H"));
337 if ($a_spent_seconds > 0) {
338 $fields[
"spent_seconds"] =
array(
"integer", $a_spent_seconds);
340 if ($a_read_count > 0) {
341 $fields[
"read_count"] =
array(
"integer", $a_read_count);
343 if ($a_childs_spent_seconds > 0) {
344 $fields[
"childs_spent_seconds"] =
array(
"integer", $a_childs_spent_seconds);
346 if ($a_child_read_count > 0) {
347 $fields[
"childs_read_count"] =
array(
"integer", $a_child_read_count);
349 $ilDB->insert(
"obj_stat_log", $fields);
352 if (mt_rand(1, 100) == 1) {
353 self::_syncObjectStats($now);
374 $set = $ilDB->query(
"SELECT COUNT(*) AS counter FROM obj_stat_log");
375 $row = $ilDB->fetchAssoc($set);
376 if (
$row[
"counter"] >= $a_minimum) {
377 $ilAtomQuery = $ilDB->buildAtomQuery();
378 $ilAtomQuery->addTableLock(
'obj_stat_log');
379 $ilAtomQuery->addTableLock(
'obj_stat_tmp');
381 $ilAtomQuery->addQueryCallable(
function (
ilDBInterface $ilDB) use ($a_now, $a_minimum, &
$ret) {
385 $set = $ilDB->
query(
"SELECT COUNT(*) AS counter FROM obj_stat_log");
387 if (
$row[
"counter"] >= $a_minimum) {
389 $ilDB->
query(
"INSERT INTO obj_stat_tmp" .
390 " SELECT * FROM obj_stat_log" .
391 " WHERE tstamp < " . $ilDB->
quote($a_now,
"timestamp"));
394 $ilDB->
query(
"DELETE FROM obj_stat_log" .
395 " WHERE tstamp < " . $ilDB->
quote($a_now,
"timestamp"));
408 $ilAtomQuery->addTableLock(
'obj_stat_tmp');
409 $ilAtomQuery->addTableLock(
'obj_stat');
411 $ilAtomQuery->addQueryCallable(
function (
ilDBInterface $ilDB) use ($a_now, $a_minimum) {
414 $sql =
"SELECT obj_id, obj_type, yyyy, mm, dd, hh, SUM(read_count) AS read_count," .
415 " SUM(childs_read_count) AS childs_read_count, SUM(spent_seconds) AS spent_seconds," .
416 " SUM(childs_spent_seconds) AS childs_spent_seconds" .
417 " FROM obj_stat_tmp" .
418 " GROUP BY obj_id, obj_type, yyyy, mm, dd, hh";
419 $set = $ilDB->
query($sql);
423 "obj_type" =>
array(
"text",
$row[
"obj_type"]),
424 "yyyy" =>
array(
"integer",
$row[
"yyyy"]),
429 $where_sql =
array();
430 foreach ($where as $field =>
$def) {
431 $where_sql[] = $field .
" = " . $ilDB->
quote(
$def[1],
$def[0]);
433 $where_sql = implode(
" AND ", $where_sql);
436 $check = $ilDB->
query(
"SELECT read_count, childs_read_count, spent_seconds," .
437 "childs_spent_seconds" .
439 " WHERE " . $where_sql);
444 $fields =
array(
"read_count" =>
array(
"integer",
$old[
"read_count"]+
$row[
"read_count"]),
445 "childs_read_count" =>
array(
"integer",
$old[
"childs_read_count"]+
$row[
"childs_read_count"]),
446 "spent_seconds" =>
array(
"integer",
$old[
"spent_seconds"]+
$row[
"spent_seconds"]),
447 "childs_spent_seconds" =>
array(
"integer",
$old[
"childs_spent_seconds"]+
$row[
"childs_spent_seconds"]));
449 $ilDB->
update(
"obj_stat", $fields, $where);
453 $fields[
"read_count"] =
array(
"integer",
$row[
"read_count"]);
454 $fields[
"childs_read_count"] =
array(
"integer",
$row[
"childs_read_count"]);
455 $fields[
"spent_seconds"] =
array(
"integer",
$row[
"spent_seconds"]);
456 $fields[
"childs_spent_seconds"] =
array(
"integer",
$row[
"childs_spent_seconds"]);
458 $ilDB->
insert(
"obj_stat", $fields);
463 $ilDB->
query(
"DELETE FROM obj_stat_tmp");
483 $query =
"SELECT obj_id FROM catch_write_events " .
484 "WHERE obj_id = " . $ilDB->quote($obj_id,
'integer') .
" " .
485 "AND usr_id = " . $ilDB->quote($usr_id,
'integer');
487 if (
$res->numRows()) {
509 "catch_write_events",
511 "obj_id" =>
array(
"integer", $obj_id),
512 "usr_id" =>
array(
"integer", $usr_id)
515 "ts" =>
array(
"timestamp", $ts))
571 "FROM catch_write_events " .
572 "WHERE obj_id=" . $ilDB->quote($obj_id,
'integer') .
" " .
573 "AND usr_id=" . $ilDB->quote($usr_id,
'integer');
574 $r = $ilDB->query($q);
577 $catchup =
$row[
'ts'];
580 if ($catchup == null) {
582 'SELECT * FROM write_event ' .
583 'WHERE obj_id = %s ' .
584 'AND usr_id <> %s ' .
586 $ilDB->quote($obj_id,
'integer'),
587 $ilDB->quote($usr_id,
'integer')
592 'SELECT * FROM write_event ' .
593 'WHERE obj_id = %s ' .
594 'AND usr_id <> %s ' .
597 $ilDB->quote($obj_id,
'integer'),
598 $ilDB->quote($usr_id,
'integer'),
599 $ilDB->quote($catchup,
'timestamp')
604 while (
$row = $ilDB->fetchAssoc(
$res)) {
624 "FROM catch_write_events " .
625 "WHERE obj_id=" . $ilDB->quote($obj_id,
'integer') .
" " .
626 "AND usr_id=" . $ilDB->quote($usr_id,
'integer');
627 $r = $ilDB->query($q);
630 $catchup =
$row[
'ts'];
633 if ($catchup == null) {
636 'SELECT * FROM write_event ' .
637 'WHERE obj_id = %s ' .
639 $ilDB->quote($obj_id,
'integer'),
640 $ilDB->quote($usr_id,
'integer')
646 'SELECT * FROM write_event ' .
647 'WHERE obj_id = %s ' .
648 'AND usr_id <> %s ' .
650 $ilDB->quote($obj_id,
'integer'),
651 $ilDB->quote($usr_id,
'integer'),
652 $ilDB->quote($catchup,
'timestamp')
657 $numRows =
$res->numRows();
662 return ($catchup == null) ? 1 : 2;
716 if ($usr_id == null) {
718 'SELECT * FROM read_event ' .
719 'WHERE obj_id = %s ' .
720 'ORDER BY last_access DESC',
721 $ilDB->quote($obj_id,
'integer')
726 'SELECT * FROM read_event ' .
727 'WHERE obj_id = %s ' .
729 'ORDER BY last_access DESC',
730 $ilDB->quote($obj_id,
'integer'),
731 $ilDB->quote($usr_id,
'integer')
737 while (
$row = $ilDB->fetchAssoc(
$res)) {
742 $events[
$counter][
'spent_seconds'] =
$row[
'spent_seconds'];
743 $events[
$counter][
'first_access'] =
$row[
'first_access'];
747 return $events ? $events :
array();
761 'SELECT DISTINCT(usr_id) usr FROM read_event ' .
762 'WHERE obj_id = %s ',
763 $ilDB->quote($a_obj_id,
'integer')
766 while (
$row = $ilDB->fetchObject($res)) {
779 if (isset(self::$has_accessed[$a_obj_id][$a_usr_id])) {
780 return self::$has_accessed[$a_obj_id][$a_usr_id];
784 "SELECT usr_id FROM read_event WHERE " .
785 "obj_id = " . $ilDB->quote($a_obj_id,
"integer") .
" AND " .
786 "usr_id = " . $ilDB->quote($a_usr_id,
"integer")
788 if ($rec = $ilDB->fetchAssoc($set)) {
789 return self::$has_accessed[$a_obj_id][$a_usr_id] =
true;
791 return self::$has_accessed[$a_obj_id][$a_usr_id] =
false;
802 return 'change event tracking is already active';
812 $set = $ilDB->query(sprintf(
813 'SELECT r1.obj_id,r2.obj_id p,d.owner,%s,d.create_date ' .
814 'FROM object_data d ' .
815 'LEFT JOIN write_event w ON d.obj_id = w.obj_id ' .
816 'JOIN object_reference r1 ON d.obj_id=r1.obj_id ' .
817 'JOIN tree t ON t.child=r1.ref_id ' .
818 'JOIN object_reference r2 on r2.ref_id=t.parent ' .
819 'WHERE w.obj_id IS NULL',
820 $ilDB->quote(
'create',
'text')
822 while ($rec = $ilDB->fetchAssoc($set)) {
823 $nid = $ilDB->nextId(
"write_event");
824 $query =
'INSERT INTO write_event ' .
825 '(write_id, obj_id,parent_obj_id,usr_id,action,ts) VALUES (' .
826 $ilDB->quote($nid,
"integer") .
"," .
827 $ilDB->quote($rec[
"obj_id"],
"integer") .
"," .
828 $ilDB->quote($rec[
"p"],
"integer") .
"," .
829 $ilDB->quote($rec[
"owner"],
"integer") .
"," .
830 $ilDB->quote(
"create",
"text") .
"," .
831 $ilDB->quote($rec[
"create_date"],
"timestamp") .
837 $ilSetting->set(
'enable_change_event_tracking',
'1');
851 $ilSetting->set(
'enable_change_event_tracking',
'0');
862 return $ilSetting->get(
'enable_change_event_tracking',
'0') ==
'1';
876 'DELETE FROM write_event WHERE obj_id = %s ',
877 $ilDB->quote($a_obj_id,
'integer')
879 $aff = $ilDB->manipulate(
$query);
882 'DELETE FROM read_event WHERE obj_id = %s ',
883 $ilDB->quote($a_obj_id,
'integer')
885 $aff = $ilDB->manipulate(
$query);
893 $ilDB->manipulate(
"DELETE FROM read_event" .
894 " WHERE obj_id = " . $ilDB->quote($a_obj_id,
"integer"));
901 $ilDB->manipulate(
"DELETE FROM read_event" .
902 " WHERE obj_id = " . $ilDB->quote($a_obj_id,
"integer") .
903 " AND " . $ilDB->in(
"usr_id", $a_user_ids,
"",
"integer"));
912 $set = $ilDB->query(
"SELECT usr_id FROM read_event" .
913 " WHERE obj_id = " . $ilDB->quote($a_obj_id,
"integer"));
914 while (
$row = $ilDB->fetchAssoc($set)) {
930 $res = $ilDB->queryF(
931 'UPDATE read_event SET first_access=%s, last_access = %s WHERE obj_id=%s AND usr_id=%s',
932 array(
'timestamp',
'integer',
'integer',
'integer'),
933 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)
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
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 ...
Create styles array
The data for the language used.
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)
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
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.