ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
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  static private $has_accessed = array();
39 
55  function _recordWriteEvent($obj_id, $usr_id, $action, $parent_obj_id = null)
56  {
57  global $ilDB;
58 
59  /* see _recordReadEvent
60  if (!ilChangeEvent::_isActive())
61  {
62  return;
63  }
64  */
65 
66  if ($parent_obj_id == null)
67  {
68  $pset = $ilDB->query('SELECT r2.obj_id par_obj_id FROM object_reference r1 '.
69  'JOIN tree t ON t.child = r1.ref_id '.
70  'JOIN object_reference r2 ON r2.ref_id = t.parent '.
71  'WHERE r1.obj_id = '.$ilDB->quote($obj_id,'integer'));
72 
73  while ($prec = $ilDB->fetchAssoc($pset))
74  {
75  $nid = $ilDB->nextId("write_event");
76  $query = sprintf('INSERT INTO write_event '.
77  '(write_id, obj_id, parent_obj_id, usr_id, action, ts) VALUES '.
78  '(%s, %s, %s, %s, %s, '.$ilDB->now().')',
79  $ilDB->quote($nid,'integer'),
80  $ilDB->quote($obj_id,'integer'),
81  $ilDB->quote($prec["par_obj_id"],'integer'),
82  $ilDB->quote($usr_id,'integer'),
83  $ilDB->quote($action,'text'));
84 
85  $aff = $ilDB->manipulate($query);
86  }
87  }
88  else
89  {
90  $nid = $ilDB->nextId("write_event");
91  $query = sprintf('INSERT INTO write_event '.
92  '(write_id, obj_id, parent_obj_id, usr_id, action, ts) '.
93  'VALUES (%s,%s,%s,%s,%s,'.$ilDB->now().')',
94  $ilDB->quote($nid,'integer'),
95  $ilDB->quote($obj_id,'integer'),
96  $ilDB->quote($parent_obj_id,'integer'),
97  $ilDB->quote($usr_id,'integer'),
98  $ilDB->quote($action,'text'));
99  $aff = $ilDB->manipulate($query);
100 
101  }
102  //error_log ('ilChangeEvent::_recordWriteEvent '.$q);
103  }
104 
113  function _recordReadEvent($a_type, $a_ref_id, $obj_id, $usr_id,
114  $isCatchupWriteEvents = true, $a_ext_rc = false, $a_ext_time = false)
115  {
116  global $ilDB, $tree;
117 
118  /* read_event data is now used for several features, so we are always keeping track
119  if (!ilChangeEvent::_isActive())
120  {
121  return;
122  }
123  */
124 
125  include_once('Services/Tracking/classes/class.ilObjUserTracking.php');
126  $validTimeSpan = ilObjUserTracking::_getValidTimeSpan();
127 
128  $query = sprintf('SELECT * FROM read_event '.
129  'WHERE obj_id = %s '.
130  'AND usr_id = %s ',
131  $ilDB->quote($obj_id,'integer'),
132  $ilDB->quote($usr_id,'integer'));
133  $res = $ilDB->query($query);
134  $row = $ilDB->fetchObject($res);
135 
136  // read counter
137  if ($a_ext_rc !== false)
138  {
139  $read_count = 'read_count = '.$ilDB->quote($a_ext_rc, "integer").", ";
140  $read_count_init = max(1, (int) $a_ext_rc);
141  $read_count_diff = max(1, (int) $a_ext_rc) - $row->read_count;
142  }
143  else
144  {
145  $read_count = 'read_count = read_count + 1, ';
146  $read_count_init = 1;
147  $read_count_diff = 1;
148  }
149 
150  if ($row)
151  {
152 
153  if ($a_ext_time !== false)
154  {
155  $time = (int) $a_ext_time;
156  }
157  else
158  {
159  $time = $ilDB->quote((time() - $row->last_access) <= $validTimeSpan
160  ? $row->spent_seconds + time() - $row->last_access
161  : $row->spent_seconds,'integer');
162 
163  // if we are in the valid interval, we do not
164  // add anything to the read_count, since this is the
165  // same access for us
166  if ((time() - $row->last_access) <= $validTimeSpan)
167  {
168  $read_count = '';
169  $read_count_init = 1;
170  $read_count_diff = 0;
171  }
172  }
173  $time_diff = $time - (int) $row->spent_seconds;
174 
175  // Update
176  $query = sprintf('UPDATE read_event SET '.
177  $read_count.
178  'spent_seconds = %s, '.
179  'last_access = %s '.
180  'WHERE obj_id = %s '.
181  'AND usr_id = %s ',
182  $time,
183  $ilDB->quote(time(),'integer'),
184  $ilDB->quote($obj_id,'integer'),
185  $ilDB->quote($usr_id,'integer'));
186  $aff = $ilDB->manipulate($query);
187 
188  self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
189  }
190  else
191  {
192  if ($a_ext_time !== false)
193  {
194  $time = (int) $a_ext_time;
195  }
196  else
197  {
198  $time = 0;
199  }
200 
201  $time_diff = $time - (int) $row->spent_seconds;
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 
211  $aff = $ilDB->manipulate($query);
212 
213  self::$has_accessed[$obj_id][$usr_id] = true;
214 
215  self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
216  }
217 
218  if ($isCatchupWriteEvents)
219  {
221  }
222 
223  // update parents (no categories or root)
224  if (!in_array($a_type, array("cat", "root", "crs")))
225  {
226  if ($tree->isInTree($a_ref_id))
227  {
228  $path = $tree->getPathId($a_ref_id);
229 
230  foreach ($path as $p)
231  {
232  $obj2_id = ilObject::_lookupObjId($p);
233  $obj2_type = ilObject::_lookupType($obj2_id);
234 //echo "<br>1-$obj2_type-$p-$obj2_id-";
235  if (($p != $a_ref_id) && (in_array($obj2_type, array("crs", "fold", "grp"))))
236  {
237  $query = sprintf('SELECT * FROM read_event '.
238  'WHERE obj_id = %s '.
239  'AND usr_id = %s ',
240  $ilDB->quote($obj2_id, 'integer'),
241  $ilDB->quote($usr_id, 'integer'));
242  $res2 = $ilDB->query($query);
243  if ($row2 = $ilDB->fetchAssoc($res2))
244  {
245 //echo "<br>2";
246  // update read count and spent seconds
247  $query = sprintf('UPDATE read_event SET '.
248  'childs_read_count = childs_read_count + %s ,'.
249  'childs_spent_seconds = childs_spent_seconds + %s '.
250  'WHERE obj_id = %s '.
251  'AND usr_id = %s ',
252  $ilDB->quote((int) $read_count_diff,'integer'),
253  $ilDB->quote((int) $time_diff,'integer'),
254  $ilDB->quote($obj2_id,'integer'),
255  $ilDB->quote($usr_id,'integer'));
256  $aff = $ilDB->manipulate($query);
257 
258  self::_recordObjStats($obj2_id, null, null, (int)$time_diff, (int)$read_count_diff);
259  }
260  else
261  {
262 //echo "<br>3";
263 //$ilLog->write("insert read event for obj_id -".$obj2_id."-".$usr_id."-");
264  $query = sprintf('INSERT INTO read_event (obj_id,usr_id,last_access,read_count,spent_seconds,first_access,'.
265  'childs_read_count, childs_spent_seconds) '.
266  'VALUES (%s,%s,%s,%s,%s,'.$ilDB->now().', %s, %s) ',
267  $ilDB->quote($obj2_id,'integer'),
268  $ilDB->quote($usr_id,'integer'),
269  $ilDB->quote(time(),'integer'),
270  $ilDB->quote(1,'integer'),
271  $ilDB->quote($time,'integer'),
272  $ilDB->quote((int) $read_count_diff,'integer'),
273  $ilDB->quote((int) $time_diff,'integer')
274  );
275  $aff = $ilDB->manipulate($query);
276 
277  self::$has_accessed[$obj2_id][$usr_id] = true;
278 
279  self::_recordObjStats($obj2_id, $time, 1, (int)$time_diff, (int)$read_count_diff);
280  }
281  }
282  }
283  }
284  }
285 
286  // @todo:
287  // - calculate diff of spent_seconds and read_count
288  // - use ref id to get parents of types grp, crs, fold
289  // - add diffs to childs_spent_seconds and childs_read_count
290  }
291 
292  function _recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds = null, $a_child_read_count = null)
293  {
294  global $ilDB;
295 
297  (int)$a_obj_id <= 0) // #12706
298  {
299  return;
300  }
301 
302  $now = time();
303 
304  $fields = array();
305  $fields["obj_id"] = array("integer", $a_obj_id);
306  $fields["obj_type"] = array("text", ilObject::_lookupType($a_obj_id));
307  $fields["tstamp"] = array("timestamp", $now);
308  $fields["yyyy"] = array("integer", date("Y"));
309  $fields["mm"] = array("integer", date("m"));
310  $fields["dd"] = array("integer", date("d"));
311  $fields["hh"] = array("integer", date("H"));
312  if($a_spent_seconds > 0)
313  {
314  $fields["spent_seconds"] = array("integer", $a_spent_seconds);
315  }
316  if($a_read_count > 0)
317  {
318  $fields["read_count"] = array("integer", $a_read_count);
319  }
320  if($a_childs_spent_seconds > 0)
321  {
322  $fields["childs_spent_seconds"] = array("integer", $a_childs_spent_seconds);
323  }
324  if($a_child_read_count > 0)
325  {
326  $fields["childs_read_count"] = array("integer", $a_child_read_count);
327  }
328  $ilDB->insert("obj_stat_log", $fields);
329 
330  // 0.01% probability
331  if(mt_rand(1, 100) == 1)
332  {
334  }
335  }
336 
343  function _syncObjectStats($a_now = null, $a_minimum = 20000)
344  {
345  global $ilDB;
346 
347  if(!$a_now)
348  {
349  $a_now = time();
350  }
351 
352  set_time_limit(0);
353 
354  // has source table enough entries?
355  $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
356  $row = $ilDB->fetchAssoc($set);
357  if($row["counter"] >= $a_minimum)
358  {
359  // lock source and transfer table
360  $ilDB->lockTables(array(array("name"=>"obj_stat_log", "type"=>ilDB::LOCK_WRITE),
361  array("name"=>"obj_stat_tmp", "type"=>ilDB::LOCK_WRITE)));
362 
363  // if other process was transferring, we had to wait for the lock and
364  // the source table should now have less than minimum/needed entries
365  $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
366  $row = $ilDB->fetchAssoc($set);
367  if($row["counter"] >= $a_minimum)
368  {
369  // use only "full" seconds to have a clear cut
370  $ilDB->query("INSERT INTO obj_stat_tmp".
371  " SELECT * FROM obj_stat_log".
372  " WHERE tstamp < ".$ilDB->quote($a_now, "timestamp"));
373 
374  // remove transferred entries from source table
375  $ilDB->query("DELETE FROM obj_stat_log".
376  " WHERE tstamp < ".$ilDB->quote($a_now, "timestamp"));
377 
378  // remove lock from source table
379  $ilDB->unlockTables();
380 
381  // lock transfer and target table (is this needed?)
382  $ilDB->lockTables(array(array("name"=>"obj_stat_tmp", "type"=>ilDB::LOCK_WRITE),
383  array("name"=>"obj_stat", "type"=>ilDB::LOCK_WRITE)));
384 
385  // process log data (timestamp is not needed anymore)
386  $sql = "SELECT obj_id, obj_type, yyyy, mm, dd, hh, SUM(read_count) AS read_count,".
387  " SUM(childs_read_count) AS childs_read_count, SUM(spent_seconds) AS spent_seconds,".
388  " SUM(childs_spent_seconds) AS childs_spent_seconds".
389  " FROM obj_stat_tmp".
390  " GROUP BY obj_id, obj_type, yyyy, mm, dd, hh";
391  $set = $ilDB->query($sql);
392  while($row = $ilDB->fetchAssoc($set))
393  {
394  // "primary key"
395  $where = array("obj_id" => array("integer", $row["obj_id"]),
396  "obj_type" => array("text", $row["obj_type"]),
397  "yyyy" => array("integer", $row["yyyy"]),
398  "mm" => array("integer", $row["mm"]),
399  "dd" => array("integer", $row["dd"]),
400  "hh" => array("integer", $row["hh"]));
401 
402  $where_sql = array();
403  foreach($where as $field => $def)
404  {
405  $where_sql[] = $field." = ".$ilDB->quote($def[1], $def[0]);
406  }
407  $where_sql = implode(" AND ", $where_sql);
408 
409  // existing entry?
410  $check = $ilDB->query("SELECT read_count, childs_read_count, spent_seconds,".
411  "childs_spent_seconds".
412  " FROM obj_stat".
413  " WHERE ".$where_sql);
414  if($ilDB->numRows($check))
415  {
416  $old = $ilDB->fetchAssoc($check);
417 
418  // add existing values
419  $fields = array("read_count" => array("integer", $old["read_count"]+$row["read_count"]),
420  "childs_read_count" => array("integer", $old["childs_read_count"]+$row["childs_read_count"]),
421  "spent_seconds" => array("integer", $old["spent_seconds"]+$row["spent_seconds"]),
422  "childs_spent_seconds" => array("integer", $old["childs_spent_seconds"]+$row["childs_spent_seconds"]));
423 
424  $ilDB->update("obj_stat", $fields, $where);
425  }
426  else
427  {
428  // new entry
429  $fields = $where;
430  $fields["read_count"] = array("integer", $row["read_count"]);
431  $fields["childs_read_count"] = array("integer", $row["childs_read_count"]);
432  $fields["spent_seconds"] = array("integer", $row["spent_seconds"]);
433  $fields["childs_spent_seconds"] = array("integer", $row["childs_spent_seconds"]);
434 
435  $ilDB->insert("obj_stat", $fields);
436  }
437  }
438 
439  // clean up transfer table
440  $ilDB->query("DELETE FROM obj_stat_tmp");
441  }
442 
443  // remove all locks (does not matter if transfer was actually performed)
444  $ilDB->unlockTables();
445  }
446  }
447 
456  function _catchupWriteEvents($obj_id, $usr_id, $timestamp = null)
457  {
458  global $ilDB;
459 
460  $query = "SELECT obj_id FROM catch_write_events ".
461  "WHERE obj_id = ".$ilDB->quote($obj_id ,'integer')." ".
462  "AND usr_id = ".$ilDB->quote($usr_id ,'integer');
463  $res = $ilDB->query($query);
464  if($res->numRows())
465  {
466  $query = "UPDATE catch_write_events ".
467  "SET ts = ".($timestamp == null ? $ilDB->now() : $ilDB->quote($timestamp, 'timestamp'))." ".
468  "WHERE usr_id = ".$ilDB->quote($usr_id ,'integer')." ".
469  "AND obj_id = ".$ilDB->quote($obj_id ,'integer');
470  $res = $ilDB->manipulate($query);
471  }
472  else
473  {
474  $query = "INSERT INTO catch_write_events (ts,obj_id,usr_id) ".
475  "VALUES( ".
476  $ilDB->now().", ".
477  $ilDB->quote($obj_id,'integer').", ".
478  $ilDB->quote($usr_id,'integer')." ".
479  ")";
480  $res = $ilDB->manipulate($query);
481 
482  }
483 
484  /*
485  $q = "INSERT INTO catch_write_events ".
486  "(obj_id, usr_id, ts) ".
487  "VALUES (".
488  $ilDB->quote($obj_id,'integer').",".
489  $ilDB->quote($usr_id,'integer').",";
490  if ($timestamp == null)
491  {
492  $q .= "NOW()".
493  ") ON DUPLICATE KEY UPDATE ts=NOW()";
494  }
495  else {
496  $q .= $ilDB->quote($timestamp).
497  ") ON DUPLICATE KEY UPDATE ts=".$ilDB->quote($timestamp);
498  }
499  //error_log ('ilChangeEvent::_catchupWriteEvents '.$q);
500  $r = $ilDB->query($q);
501  */
502  }
550  public static function _lookupUncaughtWriteEvents($obj_id, $usr_id)
551  {
552  global $ilDB;
553 
554  $q = "SELECT ts ".
555  "FROM catch_write_events ".
556  "WHERE obj_id=".$ilDB->quote($obj_id ,'integer')." ".
557  "AND usr_id=".$ilDB->quote($usr_id ,'integer');
558  $r = $ilDB->query($q);
559  $catchup = null;
560  while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC)) {
561  $catchup = $row['ts'];
562  }
563 
564  if($catchup == null)
565  {
566  $query = sprintf('SELECT * FROM write_event '.
567  'WHERE obj_id = %s '.
568  'AND usr_id <> %s '.
569  'ORDER BY ts DESC',
570  $ilDB->quote($obj_id,'integer'),
571  $ilDB->quote($usr_id,'integer'));
572  $res = $ilDB->query($query);
573  }
574  else
575  {
576  $query = sprintf('SELECT * FROM write_event '.
577  'WHERE obj_id = %s '.
578  'AND usr_id <> %s '.
579  'AND ts >= %s '.
580  'ORDER BY ts DESC',
581  $ilDB->quote($obj_id,'integer'),
582  $ilDB->quote($usr_id,'integer'),
583  $ilDB->quote($catchup,'timestamp'));
584  $res = $ilDB->query($query);
585  }
586  $events = array();
587  while($row = $ilDB->fetchAssoc($res))
588  {
589  $events[] = $row;
590  }
591  return $events;
592  }
603  public static function _lookupChangeState($obj_id, $usr_id)
604  {
605  global $ilDB;
606 
607  $q = "SELECT ts ".
608  "FROM catch_write_events ".
609  "WHERE obj_id=".$ilDB->quote($obj_id ,'integer')." ".
610  "AND usr_id=".$ilDB->quote($usr_id ,'integer');
611  $r = $ilDB->query($q);
612  $catchup = null;
613  while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC)) {
614  $catchup = $row['ts'];
615  }
616 
617  if($catchup == null)
618  {
619  $ilDB->setLimit(1);
620  $query = sprintf('SELECT * FROM write_event '.
621  'WHERE obj_id = %s '.
622  'AND usr_id <> %s ',
623  $ilDB->quote($obj_id,'integer'),
624  $ilDB->quote($usr_id,'integer'));
625  $res = $ilDB->query($query);
626  }
627  else
628  {
629  $ilDB->setLimit(1);
630  $query = sprintf('SELECT * FROM write_event '.
631  'WHERE obj_id = %s '.
632  'AND usr_id <> %s '.
633  'AND ts > %s ',
634  $ilDB->quote($obj_id,'integer'),
635  $ilDB->quote($usr_id,'integer'),
636  $ilDB->quote($catchup,'timestamp'));
637  $res = $ilDB->query($query);
638  }
639 
640  $numRows = $res->numRows();
641  if ($numRows > 0)
642  {
643  $row = $ilDB->fetchAssoc($res);
644  // if we have write events, and user never catched one, report as new (1)
645  // if we have write events, and user catched an old write event, report as changed (2)
646  return ($catchup == null) ? 1 : 2;
647  }
648  else
649  {
650  return 0; // user catched all write events, report as unchanged (0)
651  }
652  }
668  public static function _lookupInsideChangeState($parent_obj_id, $usr_id)
669  {
670  global $ilDB;
671 
672  $q = "SELECT ts ".
673  "FROM catch_write_events ".
674  "WHERE obj_id=".$ilDB->quote($parent_obj_id)." ".
675  "AND usr_id=".$ilDB->quote($usr_id);
676  $r = $ilDB->query($q);
677  $catchup = null;
678  while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC)) {
679  $catchup = $row['ts'];
680  }
681 
682  if($catchup == null)
683  {
684  $ilDB->setLimit(1);
685  $query = sprintf('SELECT * FROM write_event '.
686  'WHERE parent_obj_id = %s '.
687  'AND usr_id <> %s ',
688  $ilDB->quote($parent_obj_id,'integer'),
689  $ilDB->quote($usr_id,'integer'));
690  $res = $ilDB->query($query);
691  }
692  else
693  {
694  $ilDB->setLimit(1);
695  $query = sprintf('SELECT * FROM write_event '.
696  'WHERE parent_obj_id = %s '.
697  'AND usr_id <> %s '.
698  'AND ts > %s ',
699  $ilDB->quote($parent_obj_id,'integer'),
700  $ilDB->quote($usr_id,'integer'),
701  $ilDB->quote($catchup,'timestamp'));
702  $res = $ilDB->query($query);
703  }
704  $numRows = $res->numRows();
705  if ($numRows > 0)
706  {
707  $row = $ilDB->fetchAssoc($res);
708  // if we have write events, and user never catched one, report as new (1)
709  // if we have write events, and user catched an old write event, report as changed (2)
710  return ($catchup == null) ? 1 : 2;
711  }
712  else
713  {
714  return 0; // user catched all write events, report as unchanged (0)
715  }
716  }
761  public static function _lookupReadEvents($obj_id, $usr_id = null)
762  {
763  global $ilDB;
764 
765  if ($usr_id == null)
766  {
767  $query = sprintf('SELECT * FROM read_event '.
768  'WHERE obj_id = %s '.
769  'ORDER BY last_access DESC',
770  $ilDB->quote($obj_id,'integer'));
771  $res = $ilDB->query($query);
772  }
773  else
774  {
775  $query = sprintf('SELECT * FROM read_event '.
776  'WHERE obj_id = %s '.
777  'AND usr_id = %s '.
778  'ORDER BY last_access DESC',
779  $ilDB->quote($obj_id,'integer'),
780  $ilDB->quote($usr_id,'integer'));
781  $res = $ilDB->query($query);
782  }
783 
784  $counter = 0;
785  while ($row = $ilDB->fetchAssoc($res))
786  {
787  $events[$counter]['obj_id'] = $row['obj_id'];
788  $events[$counter]['usr_id'] = $row['usr_id'];
789  $events[$counter]['last_access'] = $row['last_access'];
790  $events[$counter]['read_count'] = $row['read_count'];
791  $events[$counter]['spent_seconds'] = $row['spent_seconds'];
792  $events[$counter]['first_access'] = $row['first_access'];
793 
794  $counter++;
795 
796  }
797  return $events ? $events : array();
798  }
799 
806  public static function lookupUsersInProgress($a_obj_id)
807  {
808  global $ilDB;
809 
810  $query = sprintf('SELECT DISTINCT(usr_id) usr FROM read_event '.
811  'WHERE obj_id = %s ',
812  $ilDB->quote($a_obj_id,'integer'));
813  $res = $ilDB->query($query);
814  while($row = $ilDB->fetchObject($res))
815  {
816  $users[] = $row->usr;
817  }
818  return $users ? $users : array();
819  }
820 
824  static function hasAccessed($a_obj_id, $a_usr_id)
825  {
826  global $ilDB;
827 
828  if (isset(self::$has_accessed[$a_obj_id][$a_usr_id]))
829  {
830  return self::$has_accessed[$a_obj_id][$a_usr_id];
831  }
832 
833  $set = $ilDB->query("SELECT usr_id FROM read_event WHERE ".
834  "obj_id = ".$ilDB->quote($a_obj_id, "integer")." AND ".
835  "usr_id = ".$ilDB->quote($a_usr_id, "integer")
836  );
837  if ($rec = $ilDB->fetchAssoc($set))
838  {
839  return self::$has_accessed[$a_obj_id][$a_usr_id] = true;
840  }
841  return self::$has_accessed[$a_obj_id][$a_usr_id] = false;
842  }
843 
849  public static function _activate() {
851  {
852  return 'change event tracking is already active';
853  }
854  else
855  {
856  global $ilDB;
857 
858  // Insert initial data into table write_event
859  // We need to do this here, because we need
860  // to catch up write events that occured while the change event tracking was
861  // deactivated.
862 
863  // IGNORE isn't supported in oracle
864  $set = $ilDB->query(sprintf('SELECT r1.obj_id,r2.obj_id p,d.owner,%s,d.create_date '.
865  'FROM object_data d '.
866  'LEFT JOIN write_event w ON d.obj_id = w.obj_id '.
867  'JOIN object_reference r1 ON d.obj_id=r1.obj_id '.
868  'JOIN tree t ON t.child=r1.ref_id '.
869  'JOIN object_reference r2 on r2.ref_id=t.parent '.
870  'WHERE w.obj_id IS NULL',
871  $ilDB->quote('create','text')));
872  while ($rec = $ilDB->fetchAssoc($set))
873  {
874  $nid = $ilDB->nextId("write_event");
875  $query = 'INSERT INTO write_event '.
876  '(write_id, obj_id,parent_obj_id,usr_id,action,ts) VALUES ('.
877  $ilDB->quote($nid, "integer").",".
878  $ilDB->quote($rec["obj_id"], "integer").",".
879  $ilDB->quote($rec["p"], "integer").",".
880  $ilDB->quote($rec["owner"], "integer").",".
881  $ilDB->quote("create", "text").",".
882  $ilDB->quote($rec["create_date"], "timestamp").
883  ')';
884  $res = $ilDB->query($query);
885  }
886 
887  if ($ilDB->isError($res) || $ilDB->isError($res->result))
888  {
889  return 'couldn\'t insert initial data into table "write_event": '.
890  (($ilDB->isError($r->result)) ? $r->result->getMessage() : $r->getMessage());
891  }
892 
893 
894  global $ilias;
895  $ilias->setSetting('enable_change_event_tracking', '1');
896 
897  return $res;
898  }
899  }
900 
906  public static function _deactivate() {
907  global $ilias;
908  $ilias->setSetting('enable_change_event_tracking', '0');
909 
910  }
911 
917  public static function _isActive() {
918  global $ilias;
919  return $ilias->getSetting('enable_change_event_tracking', '0') == '1';
920 
921  }
922 
929  public static function _delete($a_obj_id)
930  {
931  global $ilDB;
932 
933  $query = sprintf('DELETE FROM write_event WHERE obj_id = %s ',
934  $ilDB->quote($a_obj_id,'integer'));
935  $aff = $ilDB->manipulate($query);
936 
937  $query = sprintf('DELETE FROM read_event WHERE obj_id = %s ',
938  $ilDB->quote($a_obj_id,'integer'));
939  $aff = $ilDB->manipulate($query);
940  return true;
941  }
942 
943  public static function _deleteReadEvents($a_obj_id)
944  {
945  global $ilDB;
946 
947  $ilDB->manipulate("DELETE FROM read_event".
948  " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer"));
949  }
950 
951  public static function _deleteReadEventsForUsers($a_obj_id, array $a_user_ids)
952  {
953  global $ilDB;
954 
955  $ilDB->manipulate("DELETE FROM read_event".
956  " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer").
957  " AND ".$ilDB->in("usr_id", $a_user_ids, "", "integer"));
958  }
959 
960  public static function _getAllUserIds($a_obj_id)
961  {
962  global $ilDB;
963 
964  $res = array();
965 
966  $set = $ilDB->query("SELECT usr_id FROM read_event".
967  " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer"));
968  while($row = $ilDB->fetchAssoc($set))
969  {
970  $res[] = $row["usr_id"];
971  }
972 
973  return $res;
974  }
975 
982  function _updateAccessForScormOfflinePlayer($obj_id, $usr_id, $i_last_access, $t_first_access) {
983  global $ilDB;
984  $res = $ilDB->queryF('UPDATE read_event SET first_access=%s, last_access = %s WHERE obj_id=%s AND usr_id=%s',
985  array('timestamp','integer','integer','integer'),
986  array($t_first_access,$i_last_access,$obj_id,$usr_id)
987  );
988  return $res;
989  }
990 }
991 
992 ?>