ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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 /*
204 $query = sprintf('INSERT INTO read_event (obj_id,usr_id,last_access,read_count,spent_seconds,first_access) '.
205 'VALUES (%s,%s,%s,%s,%s,'.$ilDB->now().') ',
206 $ilDB->quote($obj_id,'integer'),
207 $ilDB->quote($usr_id,'integer'),
208 $ilDB->quote(time(),'integer'),
209 $ilDB->quote($read_count_init,'integer'),
210 $ilDB->quote($time,'integer'));
211 $ilDB->manipulate($query);
212 */
213
214 // #10407
215 $ilDB->replace('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 {
235 ilChangeEvent::_catchupWriteEvents($obj_id, $usr_id);
236 }
237
238 // update parents (no categories or root)
239 if (!in_array($a_type, array("cat", "root", "crs")))
240 {
241 if ($tree->isInTree($a_ref_id))
242 {
243 $path = $tree->getPathId($a_ref_id);
244
245 foreach ($path as $p)
246 {
247 $obj2_id = ilObject::_lookupObjId($p);
248 $obj2_type = ilObject::_lookupType($obj2_id);
249//echo "<br>1-$obj2_type-$p-$obj2_id-";
250 if (($p != $a_ref_id) && (in_array($obj2_type, array("crs", "fold", "grp"))))
251 {
252 $query = sprintf('SELECT * FROM read_event '.
253 'WHERE obj_id = %s '.
254 'AND usr_id = %s ',
255 $ilDB->quote($obj2_id, 'integer'),
256 $ilDB->quote($usr_id, 'integer'));
257 $res2 = $ilDB->query($query);
258 if ($row2 = $ilDB->fetchAssoc($res2))
259 {
260//echo "<br>2";
261 // update read count and spent seconds
262 $query = sprintf('UPDATE read_event SET '.
263 'childs_read_count = childs_read_count + %s ,'.
264 'childs_spent_seconds = childs_spent_seconds + %s '.
265 'WHERE obj_id = %s '.
266 'AND usr_id = %s ',
267 $ilDB->quote((int) $read_count_diff,'integer'),
268 $ilDB->quote((int) $time_diff,'integer'),
269 $ilDB->quote($obj2_id,'integer'),
270 $ilDB->quote($usr_id,'integer'));
271 $aff = $ilDB->manipulate($query);
272
273 self::_recordObjStats($obj2_id, null, null, (int)$time_diff, (int)$read_count_diff);
274 }
275 else
276 {
277//echo "<br>3";
278//$ilLog->write("insert read event for obj_id -".$obj2_id."-".$usr_id."-");
279 /*
280 $query = sprintf('INSERT INTO read_event (obj_id,usr_id,last_access,read_count,spent_seconds,first_access,'.
281 'childs_read_count, childs_spent_seconds) '.
282 'VALUES (%s,%s,%s,%s,%s,'.$ilDB->now().', %s, %s) ',
283 $ilDB->quote($obj2_id,'integer'),
284 $ilDB->quote($usr_id,'integer'),
285 $ilDB->quote(time(),'integer'),
286 $ilDB->quote(1,'integer'),
287 $ilDB->quote($time,'integer'),
288 $ilDB->quote((int) $read_count_diff,'integer'),
289 $ilDB->quote((int) $time_diff,'integer')
290 );
291 $aff = $ilDB->manipulate($query);
292 */
293
294 // #10407
295 $ilDB->replace('read_event',
296 array(
297 'obj_id' => array('integer', $obj2_id),
298 'usr_id' => array('integer', $usr_id)
299 ),
300 array(
301 'read_count' => array('integer', 1),
302 'spent_seconds' => array('integer', $time),
303 'first_access' => array('timestamp', date("Y-m-d H:i:s")), // was $ilDB->now()
304 'last_access' => array('integer', time()),
305 'childs_read_count' => array('integer', (int)$read_count_diff),
306 'childs_spent_seconds' => array('integer', (int)$time_diff)
307 )
308 );
309
310 self::$has_accessed[$obj2_id][$usr_id] = true;
311
312 self::_recordObjStats($obj2_id, $time, 1, (int)$time_diff, (int)$read_count_diff);
313 }
314 }
315 }
316 }
317 }
318
319 // @todo:
320 // - calculate diff of spent_seconds and read_count
321 // - use ref id to get parents of types grp, crs, fold
322 // - add diffs to childs_spent_seconds and childs_read_count
323 }
324
325 function _recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds = null, $a_child_read_count = null)
326 {
327 global $ilDB;
328
330 (int)$a_obj_id <= 0) // #12706
331 {
332 return;
333 }
334
335 $now = time();
336
337 $fields = array();
338 $fields["obj_id"] = array("integer", $a_obj_id);
339 $fields["obj_type"] = array("text", ilObject::_lookupType($a_obj_id));
340 $fields["tstamp"] = array("timestamp", $now);
341 $fields["yyyy"] = array("integer", date("Y"));
342 $fields["mm"] = array("integer", date("m"));
343 $fields["dd"] = array("integer", date("d"));
344 $fields["hh"] = array("integer", date("H"));
345 if($a_spent_seconds > 0)
346 {
347 $fields["spent_seconds"] = array("integer", $a_spent_seconds);
348 }
349 if($a_read_count > 0)
350 {
351 $fields["read_count"] = array("integer", $a_read_count);
352 }
353 if($a_childs_spent_seconds > 0)
354 {
355 $fields["childs_spent_seconds"] = array("integer", $a_childs_spent_seconds);
356 }
357 if($a_child_read_count > 0)
358 {
359 $fields["childs_read_count"] = array("integer", $a_child_read_count);
360 }
361 $ilDB->insert("obj_stat_log", $fields);
362
363 // 0.01% probability
364 if(mt_rand(1, 100) == 1)
365 {
367 }
368 }
369
376 function _syncObjectStats($a_now = null, $a_minimum = 20000)
377 {
378 global $ilDB;
379
380 if(!$a_now)
381 {
382 $a_now = time();
383 }
384
385 set_time_limit(0);
386
387 // has source table enough entries?
388 $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
389 $row = $ilDB->fetchAssoc($set);
390 if($row["counter"] >= $a_minimum)
391 {
392 // lock source and transfer table
393 $ilDB->lockTables(array(array("name"=>"obj_stat_log", "type"=>ilDB::LOCK_WRITE),
394 array("name"=>"obj_stat_tmp", "type"=>ilDB::LOCK_WRITE)));
395
396 // if other process was transferring, we had to wait for the lock and
397 // the source table should now have less than minimum/needed entries
398 $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
399 $row = $ilDB->fetchAssoc($set);
400 if($row["counter"] >= $a_minimum)
401 {
402 // use only "full" seconds to have a clear cut
403 $ilDB->query("INSERT INTO obj_stat_tmp".
404 " SELECT * FROM obj_stat_log".
405 " WHERE tstamp < ".$ilDB->quote($a_now, "timestamp"));
406
407 // remove transferred entries from source table
408 $ilDB->query("DELETE FROM obj_stat_log".
409 " WHERE tstamp < ".$ilDB->quote($a_now, "timestamp"));
410
411 // remove lock from source table
412 $ilDB->unlockTables();
413
414 // lock transfer and target table (is this needed?)
415 $ilDB->lockTables(array(array("name"=>"obj_stat_tmp", "type"=>ilDB::LOCK_WRITE),
416 array("name"=>"obj_stat", "type"=>ilDB::LOCK_WRITE)));
417
418 // process log data (timestamp is not needed anymore)
419 $sql = "SELECT obj_id, obj_type, yyyy, mm, dd, hh, SUM(read_count) AS read_count,".
420 " SUM(childs_read_count) AS childs_read_count, SUM(spent_seconds) AS spent_seconds,".
421 " SUM(childs_spent_seconds) AS childs_spent_seconds".
422 " FROM obj_stat_tmp".
423 " GROUP BY obj_id, obj_type, yyyy, mm, dd, hh";
424 $set = $ilDB->query($sql);
425 while($row = $ilDB->fetchAssoc($set))
426 {
427 // "primary key"
428 $where = array("obj_id" => array("integer", $row["obj_id"]),
429 "obj_type" => array("text", $row["obj_type"]),
430 "yyyy" => array("integer", $row["yyyy"]),
431 "mm" => array("integer", $row["mm"]),
432 "dd" => array("integer", $row["dd"]),
433 "hh" => array("integer", $row["hh"]));
434
435 $where_sql = array();
436 foreach($where as $field => $def)
437 {
438 $where_sql[] = $field." = ".$ilDB->quote($def[1], $def[0]);
439 }
440 $where_sql = implode(" AND ", $where_sql);
441
442 // existing entry?
443 $check = $ilDB->query("SELECT read_count, childs_read_count, spent_seconds,".
444 "childs_spent_seconds".
445 " FROM obj_stat".
446 " WHERE ".$where_sql);
447 if($ilDB->numRows($check))
448 {
449 $old = $ilDB->fetchAssoc($check);
450
451 // add existing values
452 $fields = array("read_count" => array("integer", $old["read_count"]+$row["read_count"]),
453 "childs_read_count" => array("integer", $old["childs_read_count"]+$row["childs_read_count"]),
454 "spent_seconds" => array("integer", $old["spent_seconds"]+$row["spent_seconds"]),
455 "childs_spent_seconds" => array("integer", $old["childs_spent_seconds"]+$row["childs_spent_seconds"]));
456
457 $ilDB->update("obj_stat", $fields, $where);
458 }
459 else
460 {
461 // new entry
462 $fields = $where;
463 $fields["read_count"] = array("integer", $row["read_count"]);
464 $fields["childs_read_count"] = array("integer", $row["childs_read_count"]);
465 $fields["spent_seconds"] = array("integer", $row["spent_seconds"]);
466 $fields["childs_spent_seconds"] = array("integer", $row["childs_spent_seconds"]);
467
468 $ilDB->insert("obj_stat", $fields);
469 }
470 }
471
472 // clean up transfer table
473 $ilDB->query("DELETE FROM obj_stat_tmp");
474 }
475
476 // remove all locks (does not matter if transfer was actually performed)
477 $ilDB->unlockTables();
478 }
479 }
480
489 function _catchupWriteEvents($obj_id, $usr_id, $timestamp = null)
490 {
491 global $ilDB;
492
493 $query = "SELECT obj_id FROM catch_write_events ".
494 "WHERE obj_id = ".$ilDB->quote($obj_id ,'integer')." ".
495 "AND usr_id = ".$ilDB->quote($usr_id ,'integer');
496 $res = $ilDB->query($query);
497 if($res->numRows())
498 {
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 }
508 else
509 {
510 $ts = ilUtil::now();
511/* $query = "INSERT INTO catch_write_events (ts,obj_id,usr_id) ".
512 "VALUES( ".
513 $ilDB->now().", ".
514 $ilDB->quote($obj_id,'integer').", ".
515 $ilDB->quote($usr_id,'integer')." ".
516 ")";
517 $res = $ilDB->manipulate($query);*/
518 }
519
520 // alex, use replace due to bug #10406
521 $ilDB->replace("catch_write_events",
522 array(
523 "obj_id" => array("integer", $obj_id),
524 "usr_id" => array("integer", $usr_id)
525 ),
526 array(
527 "ts" => array("timestamp", $ts))
528 );
529 }
530
578 public static function _lookupUncaughtWriteEvents($obj_id, $usr_id)
579 {
580 global $ilDB;
581
582 $q = "SELECT ts ".
583 "FROM catch_write_events ".
584 "WHERE obj_id=".$ilDB->quote($obj_id ,'integer')." ".
585 "AND usr_id=".$ilDB->quote($usr_id ,'integer');
586 $r = $ilDB->query($q);
587 $catchup = null;
588 while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC)) {
589 $catchup = $row['ts'];
590 }
591
592 if($catchup == null)
593 {
594 $query = sprintf('SELECT * FROM write_event '.
595 'WHERE obj_id = %s '.
596 'AND usr_id <> %s '.
597 'ORDER BY ts DESC',
598 $ilDB->quote($obj_id,'integer'),
599 $ilDB->quote($usr_id,'integer'));
600 $res = $ilDB->query($query);
601 }
602 else
603 {
604 $query = sprintf('SELECT * FROM write_event '.
605 'WHERE obj_id = %s '.
606 'AND usr_id <> %s '.
607 'AND ts >= %s '.
608 'ORDER BY ts DESC',
609 $ilDB->quote($obj_id,'integer'),
610 $ilDB->quote($usr_id,'integer'),
611 $ilDB->quote($catchup,'timestamp'));
612 $res = $ilDB->query($query);
613 }
614 $events = array();
615 while($row = $ilDB->fetchAssoc($res))
616 {
617 $events[] = $row;
618 }
619 return $events;
620 }
631 public static function _lookupChangeState($obj_id, $usr_id)
632 {
633 global $ilDB;
634
635 $q = "SELECT ts ".
636 "FROM catch_write_events ".
637 "WHERE obj_id=".$ilDB->quote($obj_id ,'integer')." ".
638 "AND usr_id=".$ilDB->quote($usr_id ,'integer');
639 $r = $ilDB->query($q);
640 $catchup = null;
641 while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC)) {
642 $catchup = $row['ts'];
643 }
644
645 if($catchup == null)
646 {
647 $ilDB->setLimit(1);
648 $query = sprintf('SELECT * FROM write_event '.
649 'WHERE obj_id = %s '.
650 'AND usr_id <> %s ',
651 $ilDB->quote($obj_id,'integer'),
652 $ilDB->quote($usr_id,'integer'));
653 $res = $ilDB->query($query);
654 }
655 else
656 {
657 $ilDB->setLimit(1);
658 $query = sprintf('SELECT * FROM write_event '.
659 'WHERE obj_id = %s '.
660 'AND usr_id <> %s '.
661 'AND ts > %s ',
662 $ilDB->quote($obj_id,'integer'),
663 $ilDB->quote($usr_id,'integer'),
664 $ilDB->quote($catchup,'timestamp'));
665 $res = $ilDB->query($query);
666 }
667
668 $numRows = $res->numRows();
669 if ($numRows > 0)
670 {
671 $row = $ilDB->fetchAssoc($res);
672 // if we have write events, and user never catched one, report as new (1)
673 // if we have write events, and user catched an old write event, report as changed (2)
674 return ($catchup == null) ? 1 : 2;
675 }
676 else
677 {
678 return 0; // user catched all write events, report as unchanged (0)
679 }
680 }
696 public static function _lookupInsideChangeState($parent_obj_id, $usr_id)
697 {
698 global $ilDB;
699
700 $q = "SELECT ts ".
701 "FROM catch_write_events ".
702 "WHERE obj_id=".$ilDB->quote($parent_obj_id)." ".
703 "AND usr_id=".$ilDB->quote($usr_id);
704 $r = $ilDB->query($q);
705 $catchup = null;
706 while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC)) {
707 $catchup = $row['ts'];
708 }
709
710 if($catchup == null)
711 {
712 $ilDB->setLimit(1);
713 $query = sprintf('SELECT * FROM write_event '.
714 'WHERE parent_obj_id = %s '.
715 'AND usr_id <> %s ',
716 $ilDB->quote($parent_obj_id,'integer'),
717 $ilDB->quote($usr_id,'integer'));
718 $res = $ilDB->query($query);
719 }
720 else
721 {
722 $ilDB->setLimit(1);
723 $query = sprintf('SELECT * FROM write_event '.
724 'WHERE parent_obj_id = %s '.
725 'AND usr_id <> %s '.
726 'AND ts > %s ',
727 $ilDB->quote($parent_obj_id,'integer'),
728 $ilDB->quote($usr_id,'integer'),
729 $ilDB->quote($catchup,'timestamp'));
730 $res = $ilDB->query($query);
731 }
732 $numRows = $res->numRows();
733 if ($numRows > 0)
734 {
735 $row = $ilDB->fetchAssoc($res);
736 // if we have write events, and user never catched one, report as new (1)
737 // if we have write events, and user catched an old write event, report as changed (2)
738 return ($catchup == null) ? 1 : 2;
739 }
740 else
741 {
742 return 0; // user catched all write events, report as unchanged (0)
743 }
744 }
789 public static function _lookupReadEvents($obj_id, $usr_id = null)
790 {
791 global $ilDB;
792
793 if ($usr_id == null)
794 {
795 $query = sprintf('SELECT * FROM read_event '.
796 'WHERE obj_id = %s '.
797 'ORDER BY last_access DESC',
798 $ilDB->quote($obj_id,'integer'));
799 $res = $ilDB->query($query);
800 }
801 else
802 {
803 $query = sprintf('SELECT * FROM read_event '.
804 'WHERE obj_id = %s '.
805 'AND usr_id = %s '.
806 'ORDER BY last_access DESC',
807 $ilDB->quote($obj_id,'integer'),
808 $ilDB->quote($usr_id,'integer'));
809 $res = $ilDB->query($query);
810 }
811
812 $counter = 0;
813 while ($row = $ilDB->fetchAssoc($res))
814 {
815 $events[$counter]['obj_id'] = $row['obj_id'];
816 $events[$counter]['usr_id'] = $row['usr_id'];
817 $events[$counter]['last_access'] = $row['last_access'];
818 $events[$counter]['read_count'] = $row['read_count'];
819 $events[$counter]['spent_seconds'] = $row['spent_seconds'];
820 $events[$counter]['first_access'] = $row['first_access'];
821
822 $counter++;
823
824 }
825 return $events ? $events : array();
826 }
827
834 public static function lookupUsersInProgress($a_obj_id)
835 {
836 global $ilDB;
837
838 $query = sprintf('SELECT DISTINCT(usr_id) usr FROM read_event '.
839 'WHERE obj_id = %s ',
840 $ilDB->quote($a_obj_id,'integer'));
841 $res = $ilDB->query($query);
842 while($row = $ilDB->fetchObject($res))
843 {
844 $users[] = $row->usr;
845 }
846 return $users ? $users : array();
847 }
848
852 static function hasAccessed($a_obj_id, $a_usr_id)
853 {
854 global $ilDB;
855
856 if (isset(self::$has_accessed[$a_obj_id][$a_usr_id]))
857 {
858 return self::$has_accessed[$a_obj_id][$a_usr_id];
859 }
860
861 $set = $ilDB->query("SELECT usr_id FROM read_event WHERE ".
862 "obj_id = ".$ilDB->quote($a_obj_id, "integer")." AND ".
863 "usr_id = ".$ilDB->quote($a_usr_id, "integer")
864 );
865 if ($rec = $ilDB->fetchAssoc($set))
866 {
867 return self::$has_accessed[$a_obj_id][$a_usr_id] = true;
868 }
869 return self::$has_accessed[$a_obj_id][$a_usr_id] = false;
870 }
871
877 public static function _activate() {
879 {
880 return 'change event tracking is already active';
881 }
882 else
883 {
884 global $ilDB;
885
886 // Insert initial data into table write_event
887 // We need to do this here, because we need
888 // to catch up write events that occured while the change event tracking was
889 // deactivated.
890
891 // IGNORE isn't supported in oracle
892 $set = $ilDB->query(sprintf('SELECT r1.obj_id,r2.obj_id p,d.owner,%s,d.create_date '.
893 'FROM object_data d '.
894 'LEFT JOIN write_event w ON d.obj_id = w.obj_id '.
895 'JOIN object_reference r1 ON d.obj_id=r1.obj_id '.
896 'JOIN tree t ON t.child=r1.ref_id '.
897 'JOIN object_reference r2 on r2.ref_id=t.parent '.
898 'WHERE w.obj_id IS NULL',
899 $ilDB->quote('create','text')));
900 while ($rec = $ilDB->fetchAssoc($set))
901 {
902 $nid = $ilDB->nextId("write_event");
903 $query = 'INSERT INTO write_event '.
904 '(write_id, obj_id,parent_obj_id,usr_id,action,ts) VALUES ('.
905 $ilDB->quote($nid, "integer").",".
906 $ilDB->quote($rec["obj_id"], "integer").",".
907 $ilDB->quote($rec["p"], "integer").",".
908 $ilDB->quote($rec["owner"], "integer").",".
909 $ilDB->quote("create", "text").",".
910 $ilDB->quote($rec["create_date"], "timestamp").
911 ')';
912 $res = $ilDB->query($query);
913 }
914
915 if ($ilDB->isError($res) || $ilDB->isError($res->result))
916 {
917 return 'couldn\'t insert initial data into table "write_event": '.
918 (($ilDB->isError($r->result)) ? $r->result->getMessage() : $r->getMessage());
919 }
920
921
922 global $ilias;
923 $ilias->setSetting('enable_change_event_tracking', '1');
924
925 return $res;
926 }
927 }
928
934 public static function _deactivate() {
935 global $ilias;
936 $ilias->setSetting('enable_change_event_tracking', '0');
937
938 }
939
945 public static function _isActive() {
946 global $ilias;
947 return $ilias->getSetting('enable_change_event_tracking', '0') == '1';
948
949 }
950
957 public static function _delete($a_obj_id)
958 {
959 global $ilDB;
960
961 $query = sprintf('DELETE FROM write_event WHERE obj_id = %s ',
962 $ilDB->quote($a_obj_id,'integer'));
963 $aff = $ilDB->manipulate($query);
964
965 $query = sprintf('DELETE FROM read_event WHERE obj_id = %s ',
966 $ilDB->quote($a_obj_id,'integer'));
967 $aff = $ilDB->manipulate($query);
968 return true;
969 }
970
971 public static function _deleteReadEvents($a_obj_id)
972 {
973 global $ilDB;
974
975 $ilDB->manipulate("DELETE FROM read_event".
976 " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer"));
977 }
978
979 public static function _deleteReadEventsForUsers($a_obj_id, array $a_user_ids)
980 {
981 global $ilDB;
982
983 $ilDB->manipulate("DELETE FROM read_event".
984 " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer").
985 " AND ".$ilDB->in("usr_id", $a_user_ids, "", "integer"));
986 }
987
988 public static function _getAllUserIds($a_obj_id)
989 {
990 global $ilDB;
991
992 $res = array();
993
994 $set = $ilDB->query("SELECT usr_id FROM read_event".
995 " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer"));
996 while($row = $ilDB->fetchAssoc($set))
997 {
998 $res[] = $row["usr_id"];
999 }
1000
1001 return $res;
1002 }
1003
1010 function _updateAccessForScormOfflinePlayer($obj_id, $usr_id, $i_last_access, $t_first_access) {
1011 global $ilDB;
1012 $res = $ilDB->queryF('UPDATE read_event SET first_access=%s, last_access = %s WHERE obj_id=%s AND usr_id=%s',
1013 array('timestamp','integer','integer','integer'),
1014 array($t_first_access,$i_last_access,$obj_id,$usr_id)
1015 );
1016 return $res;
1017 }
1018}
1019
1020?>
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
const DB_FETCHMODE_ASSOC
Definition: class.ilDB.php:10
Class ilChangeEvent tracks change events on repository objects.
_updateAccessForScormOfflinePlayer($obj_id, $usr_id, $i_last_access, $t_first_access)
_updateAccessForScormOfflinePlayer needed to synchronize last_access and first_access when learning m...
static _lookupChangeState($obj_id, $usr_id)
Returns the change state of the object for the specified user.
_recordWriteEvent($obj_id, $usr_id, $action, $parent_obj_id=null)
Records a write event.
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.
_catchupWriteEvents($obj_id, $usr_id, $timestamp=null)
Catches up with all write events which occured before the specified timestamp.
static _lookupInsideChangeState($parent_obj_id, $usr_id)
Returns the changed state of objects which are children of the specified parent object.
_syncObjectStats($a_now=null, $a_minimum=20000)
Process object statistics log data.
static _lookupUncaughtWriteEvents($obj_id, $usr_id)
Catches up with all write events which occured before the specified timestamp.
_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 _activate()
Activates change event tracking.
_recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds=null, $a_child_read_count=null)
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 _delete($a_obj_id)
Delete object entries.
static _deleteReadEvents($a_obj_id)
const LOCK_WRITE
Definition: class.ilDB.php:30
static _enabledObjectStatistics()
check wether object statistics is enabled or not
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.
$r
Definition: example_031.php:79
$path
Definition: index.php:22
global $ilDB