ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilChangeEvent.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 
37 {
38  private static $has_accessed = array();
39 
55  public static function _recordWriteEvent($obj_id, $usr_id, $action, $parent_obj_id = null)
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  }
104 
113  public static function _recordReadEvent(
114  $a_type,
115  $a_ref_id,
116  $obj_id,
117  $usr_id,
118  $isCatchupWriteEvents = true,
119  $a_ext_rc = false,
120  $a_ext_time = false
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  }
321 
322  public static function _recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds = null, $a_child_read_count = null)
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) {
360  self::_syncObjectStats($now);
361  }
362  }
363 
370  public static function _syncObjectStats($a_now = null, $a_minimum = 20000)
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  }
479 
488  public static function _catchupWriteEvents($obj_id, $usr_id, $timestamp = null)
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  }
529 
579  public static function _lookupUncaughtWriteEvents($obj_id, $usr_id)
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  }
634  public static function _lookupChangeState($obj_id, $usr_id)
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  }
684 
731  public static function _lookupReadEvents($obj_id, $usr_id = null)
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  }
770 
777  public static function lookupUsersInProgress($a_obj_id)
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  }
794 
798  public static function hasAccessed($a_obj_id, $a_usr_id)
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  }
818 
824  public static function _activate()
825  {
826  if (ilChangeEvent::_isActive()) {
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  }
871 
877  public static function _deactivate()
878  {
879  global $DIC;
880 
881  $ilSetting = $DIC['ilSetting'];
882  $ilSetting->set('enable_change_event_tracking', '0');
883  }
884 
890  public static function _isActive()
891  {
892  global $DIC;
893 
894  $ilSetting = $DIC['ilSetting'];
895  return $ilSetting->get('enable_change_event_tracking', '0') == '1';
896  }
897 
904  public static function _delete($a_obj_id)
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  }
923 
924  public static function _deleteReadEvents($a_obj_id)
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  }
933 
934  public static function _deleteReadEventsForUsers($a_obj_id, array $a_user_ids)
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  }
944 
945  public static function _getAllUserIds($a_obj_id)
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  }
961 
968  public static function _updateAccessForScormOfflinePlayer($obj_id, $usr_id, $i_last_access, $t_first_access)
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  }
980 }
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.
$path
Definition: aliased.php:25
static _activate()
Activates change event tracking.
static _enabledObjectStatistics()
check wether object statistics is enabled or not
$action
global $DIC
Definition: saml.php:7
static _recordWriteEvent($obj_id, $usr_id, $action, $parent_obj_id=null)
Records a write event.
if($argc< 2) $events
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.
numRows($query_result)
$time
Definition: cron.php:21
$a_type
Definition: workflow.php:92
$time_diff
Definition: langcheck.php:760
quote($value, $type)
static _delete($a_obj_id)
Delete object entries.
$r
Definition: example_031.php:79
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)
$query
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
$users
Definition: authpage.php:44
$row
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
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.
global $ilSetting
Definition: privfeed.php:17
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.
global $ilDB
$ret
Definition: parser.php:6
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)
$def
Definition: croninfo.php:21
static _syncObjectStats($a_now=null, $a_minimum=20000)
Process object statistics log data.
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.