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'),
 
   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'),
 
  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')
 
  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
 
  158                             ? 
$row->spent_seconds + time() - 
$row->last_access
 
  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')
 
  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),
 
  217                    'spent_seconds' => array(
'integer', 
$time),
 
  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;
 
  228        if ($isCatchupWriteEvents) {
 
  233        if (!in_array(
$a_type, array(
"cat", 
"root", 
"crs"))) {
 
  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')
 
  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')
 
  289                                    'obj_id' => array(
'integer', $obj2_id),
 
  290                                    'usr_id' => array(
'integer', $usr_id)
 
  293                                    'read_count' => array(
'integer', 1),
 
  294                                    'spent_seconds' => array(
'integer', 
$time),
 
  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;
 
  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) {
 
  374        $set = 
$ilDB->query(
"SELECT COUNT(*) AS counter FROM obj_stat_log");
 
  376        if (
$row[
"counter"] >= $a_minimum) {
 
  377            $ilAtomQuery = 
$ilDB->buildAtomQuery();
 
  378            $ilAtomQuery->addTableLock(
'obj_stat_log');
 
  379            $ilAtomQuery->addTableLock(
'obj_stat_tmp');
 
  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"));
 
  407                $ilAtomQuery = 
$ilDB->buildAtomQuery();
 
  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);
 
  422                        $where = array(
"obj_id" => array(
"integer", $row[
"obj_id"]),
 
  423                            "obj_type" => array(
"text", $row[
"obj_type"]),
 
  424                            "yyyy" => array(
"integer", $row[
"yyyy"]),
 
  425                            "mm" => array(
"integer", $row[
"mm"]),
 
  426                            "dd" => array(
"integer", $row[
"dd"]),
 
  427                            "hh" => array(
"integer", $row[
"hh"]));
 
  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);
 
  440                        if (
$ilDB->numRows($check)) {
 
  441                            $old = $ilDB->fetchAssoc($check);
 
  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');
 
  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')
 
  624            "FROM catch_write_events " .
 
  625            "WHERE obj_id=" . 
$ilDB->quote($obj_id, 
'integer') . 
" " .
 
  626            "AND usr_id=" . 
$ilDB->quote($usr_id, 
'integer');
 
  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')
 
  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')
 
  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';
 
  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')
 
  882            'DELETE FROM read_event WHERE obj_id = %s ',
 
  883            $ilDB->quote($a_obj_id, 
'integer')
 
  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"));
 
  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)
 
sprintf('%.4f', $callTime)
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
foreach($mandatory_scripts as $file) $timestamp
An exception for terminatinating execution or to throw for unit testing.
Class ilChangeEvent tracks change events on repository objects.
static _recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds=null, $a_child_read_count=null)
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 _lookupChangeState($obj_id, $usr_id)
Returns the change state of the object for the specified user.
static _syncObjectStats($a_now=null, $a_minimum=20000)
Process object statistics log data.
static _catchupWriteEvents($obj_id, $usr_id, $timestamp=null)
Catches up with all write events which occured before the specified timestamp.
static _updateAccessForScormOfflinePlayer($obj_id, $usr_id, $i_last_access, $t_first_access)
_updateAccessForScormOfflinePlayer needed to synchronize last_access and first_access when learning m...
static _getAllUserIds($a_obj_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 lookupUsersInProgress($a_obj_id)
Lookup users in progress.
static _isActive()
Returns true, if change event tracking is active.
static _lookupUncaughtWriteEvents($obj_id, $usr_id)
Catches up with all write events which occured before the specified timestamp.
static _activate()
Activates change event tracking.
static _deactivate()
Deactivates change event tracking.
static hasAccessed($a_obj_id, $a_usr_id)
Has accessed.
static _deleteReadEventsForUsers($a_obj_id, array $a_user_ids)
static _recordWriteEvent($obj_id, $usr_id, $action, $parent_obj_id=null)
Records a write event.
static _delete($a_obj_id)
Delete object entries.
static _deleteReadEvents($a_obj_id)
static _enabledObjectStatistics()
check wether object statistics is enabled or not
static _getValidTimeSpan()
static _lookupObjId($a_id)
static _lookupType($a_id, $a_reference=false)
lookup object type
static now()
Return current timestamp in Y-m-d H:i:s format.
foreach($_POST as $key=> $value) $res