ILIAS  release_8 Revision v8.24
class.ilChangeEvent.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=0);
4/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
5
30{
31 private static array $has_accessed = [];
32
47 public static function _recordWriteEvent(
48 int $obj_id,
49 int $usr_id,
50 string $action,
51 ?int $parent_obj_id = null
52 ): void {
53 global $DIC;
54
55 $ilDB = $DIC['ilDB'];
56
57 /* see _recordReadEvent
58 if (!ilChangeEvent::_isActive())
59 {
60 return;
61 }
62 */
63
64 if ($parent_obj_id == null) {
65 $pset = $ilDB->query(
66 'SELECT r2.obj_id par_obj_id FROM object_reference r1 ' .
67 'JOIN tree t ON t.child = r1.ref_id ' .
68 'JOIN object_reference r2 ON r2.ref_id = t.parent ' .
69 'WHERE r1.obj_id = ' . $ilDB->quote($obj_id, 'integer')
70 );
71
72 while ($prec = $ilDB->fetchAssoc($pset)) {
73 $nid = $ilDB->nextId("write_event");
74 $query = sprintf(
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'),
82 $ilDB->quote($action, 'text')
83 );
84
85 $aff = $ilDB->manipulate($query);
86 }
87 } else {
88 $nid = $ilDB->nextId("write_event");
89 $query = sprintf(
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'),
97 $ilDB->quote($action, 'text')
98 );
99 $aff = $ilDB->manipulate($query);
100 }
101 }
102
103 public static function _recordReadEvent(
104 string $a_type,
105 int $a_ref_id,
106 int $obj_id,
107 int $usr_id,
108 bool $isCatchupWriteEvents = true,
109 $a_ext_rc = null,
110 $a_ext_time = null
111 ): void {
112 global $DIC;
113
114 $ilDB = $DIC['ilDB'];
115 $tree = $DIC['tree'];
116
117 $validTimeSpan = ilObjUserTracking::_getValidTimeSpan();
118
119 $query = sprintf(
120 'SELECT * FROM read_event ' .
121 'WHERE obj_id = %s ' .
122 'AND usr_id = %s ',
123 $ilDB->quote($obj_id, 'integer'),
124 $ilDB->quote($usr_id, 'integer')
125 );
126 $res = $ilDB->query($query);
127 $row = $ilDB->fetchObject($res);
128
129 // read counter
130 if ($a_ext_rc !== null) {
131 $read_count = 'read_count = ' . $ilDB->quote(
132 $a_ext_rc,
133 "integer"
134 ) . ", ";
135 $read_count_init = max(1, (int) $a_ext_rc);
136 $read_count_diff = max(1, (int) $a_ext_rc) - $row->read_count;
137 } else {
138 $read_count = 'read_count = read_count + 1, ';
139 $read_count_init = 1;
140 $read_count_diff = 1;
141 }
142
143 if ($row) {
144 if ($a_ext_time !== null) {
145 $time = (int) $a_ext_time;
146 } else {
147 $time = $ilDB->quote(
148 (time() - $row->last_access) <= $validTimeSpan
149 ? $row->spent_seconds + time() - $row->last_access
150 : $row->spent_seconds,
151 'integer'
152 );
153
154 // if we are in the valid interval, we do not
155 // add anything to the read_count, since this is the
156 // same access for us
157 if ((time() - $row->last_access) <= $validTimeSpan) {
158 $read_count = '';
159 $read_count_init = 1;
160 $read_count_diff = 0;
161 }
162 }
163 $time_diff = $time - (int) ($row->spent_seconds ?? 0);
164
165 // Update
166 $query = sprintf(
167 'UPDATE read_event SET ' .
168 $read_count .
169 'spent_seconds = %s, ' .
170 'last_access = %s ' .
171 'WHERE obj_id = %s ' .
172 'AND usr_id = %s ',
173 $time,
174 $ilDB->quote(time(), 'integer'),
175 $ilDB->quote($obj_id, 'integer'),
176 $ilDB->quote($usr_id, 'integer')
177 );
178 $aff = $ilDB->manipulate($query);
179
180 self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
181 } else {
182 if ($a_ext_time !== false) {
183 $time = (int) $a_ext_time;
184 } else {
185 $time = 0;
186 }
187
188 $time_diff = $time - (int) ($row->spent_seconds ?? 0);
189
190 // #10407
191 $ilDB->replace(
192 'read_event',
193 array(
194 'obj_id' => array('integer', $obj_id),
195 'usr_id' => array('integer', $usr_id)
196 ),
197 array(
198 'read_count' => array('integer', $read_count_init),
199 'spent_seconds' => array('integer', $time),
200 'first_access' => array('timestamp', date("Y-m-d H:i:s")),
201 // was $ilDB->now()
202 'last_access' => array('integer', time())
203 )
204 );
205
206 self::$has_accessed[$obj_id][$usr_id] = true;
207
208 self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
209 }
210
211 if ($isCatchupWriteEvents) {
212 ilChangeEvent::_catchupWriteEvents($obj_id, $usr_id);
213 }
214
215 // update parents (no categories or root)
216 if (!in_array($a_type, array("cat", "root", "crs"))) {
217 if ($tree->isInTree($a_ref_id)) {
218 $path = $tree->getPathId($a_ref_id);
219
220 foreach ($path as $p) {
221 $obj2_id = ilObject::_lookupObjId($p);
222 $obj2_type = ilObject::_lookupType($obj2_id);
223 //echo "<br>1-$obj2_type-$p-$obj2_id-";
224 if (($p != $a_ref_id) && (in_array(
225 $obj2_type,
226 array("crs",
227 "fold",
228 "grp",
229 "lso"
230 )
231 ))) {
232 $query = sprintf(
233 'SELECT * FROM read_event ' .
234 'WHERE obj_id = %s ' .
235 'AND usr_id = %s ',
236 $ilDB->quote($obj2_id, 'integer'),
237 $ilDB->quote($usr_id, 'integer')
238 );
239 $res2 = $ilDB->query($query);
240 if ($row2 = $ilDB->fetchAssoc($res2)) {
241 //echo "<br>2";
242 // update read count and spent seconds
243 $query = sprintf(
244 'UPDATE read_event SET ' .
245 'childs_read_count = childs_read_count + %s ,' .
246 'childs_spent_seconds = childs_spent_seconds + %s ' .
247 'WHERE obj_id = %s ' .
248 'AND usr_id = %s ',
249 $ilDB->quote((int) $read_count_diff, 'integer'),
250 $ilDB->quote((int) $time_diff, 'integer'),
251 $ilDB->quote($obj2_id, 'integer'),
252 $ilDB->quote($usr_id, 'integer')
253 );
254 $aff = $ilDB->manipulate($query);
255
256 self::_recordObjStats(
257 $obj2_id,
258 null,
259 null,
260 (int) $time_diff,
261 (int) $read_count_diff
262 );
263 } else {
264
265 // #10407
266 $ilDB->replace(
267 'read_event',
268 array(
269 'obj_id' => array('integer', $obj2_id),
270 'usr_id' => array('integer', $usr_id)
271 ),
272 array(
273 'read_count' => array('integer', 1),
274 'spent_seconds' => array('integer', $time),
275 'first_access' => array('timestamp',
276 date("Y-m-d H:i:s")
277 ), // was $ilDB->now()
278 'last_access' => array('integer', time()),
279 'childs_read_count' => array('integer',
280 (int) $read_count_diff
281 ),
282 'childs_spent_seconds' => array('integer',
283 (int) $time_diff
284 )
285 )
286 );
287
288 self::$has_accessed[$obj2_id][$usr_id] = true;
289
290 self::_recordObjStats(
291 $obj2_id,
292 $time,
293 1,
294 (int) $time_diff,
295 (int) $read_count_diff
296 );
297 }
298 }
299 }
300 }
301 }
302
303 // @todo:
304 // - calculate diff of spent_seconds and read_count
305 // - use ref id to get parents of types grp, crs, fold
306 // - add diffs to childs_spent_seconds and childs_read_count
307 }
308
309 public static function _recordObjStats(
310 int $a_obj_id,
311 ?int $a_spent_seconds,
312 ?int $a_read_count,
313 ?int $a_childs_spent_seconds = null,
314 ?int $a_child_read_count = null
315 ): void {
316 global $DIC;
317
318 $ilDB = $DIC['ilDB'];
319
321 $a_obj_id <= 0) { // #12706
322 return;
323 }
324
325 $now = time();
326
327 $fields = array();
328 $fields['log_id'] = array("integer", $ilDB->nextId('obj_stat_log'));
329 $fields["obj_id"] = array("integer", $a_obj_id);
330 $fields["obj_type"] = array("text", ilObject::_lookupType($a_obj_id));
331 $fields["tstamp"] = array("timestamp", $now);
332 $fields["yyyy"] = array("integer", date("Y"));
333 $fields["mm"] = array("integer", date("m"));
334 $fields["dd"] = array("integer", date("d"));
335 $fields["hh"] = array("integer", date("H"));
336 if ($a_spent_seconds > 0) {
337 $fields["spent_seconds"] = array("integer", $a_spent_seconds);
338 }
339 if ($a_read_count > 0) {
340 $fields["read_count"] = array("integer", $a_read_count);
341 }
342 if ($a_childs_spent_seconds > 0) {
343 $fields["childs_spent_seconds"] = array("integer",
344 $a_childs_spent_seconds
345 );
346 }
347 if ($a_child_read_count > 0) {
348 $fields["childs_read_count"] = array("integer",
349 $a_child_read_count
350 );
351 }
352 $ilDB->insert("obj_stat_log", $fields);
353
354 // 0.01% probability
355 if (mt_rand(1, 100) == 1) {
356 self::_syncObjectStats($now);
357 }
358 }
359
360 public static function _syncObjectStats(
361 ?int $a_now = null,
362 int $a_minimum = 20000
363 ) {
364 global $DIC;
365
366 $ilDB = $DIC['ilDB'];
367
368 if (!$a_now) {
369 $a_now = time();
370 }
371
372 set_time_limit(0);
373
374 // has source table enough entries?
375 $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
376 $row = $ilDB->fetchAssoc($set);
377 if ($row["counter"] >= $a_minimum) {
378 $ilAtomQuery = $ilDB->buildAtomQuery();
379 $ilAtomQuery->addTableLock('obj_stat_log');
380 $ilAtomQuery->addTableLock('obj_stat_tmp');
381
382 $ilAtomQuery->addQueryCallable(
383 function (ilDBInterface $ilDB) use ($a_now, $a_minimum, &$ret) {
384
385 // if other process was transferring, we had to wait for the lock and
386 // the source table should now have less than minimum/needed entries
387 $set = $ilDB->query(
388 "SELECT COUNT(*) AS counter FROM obj_stat_log"
389 );
390 $row = $ilDB->fetchAssoc($set);
391 if ($row["counter"] >= $a_minimum) {
392 // use only "full" seconds to have a clear cut
393 $ilDB->query(
394 "INSERT INTO obj_stat_tmp" .
395 " SELECT * FROM obj_stat_log" .
396 " WHERE tstamp < " . $ilDB->quote(
397 $a_now,
398 "timestamp"
399 )
400 );
401
402 // remove transferred entries from source table
403 $ilDB->query(
404 "DELETE FROM obj_stat_log" .
405 " WHERE tstamp < " . $ilDB->quote(
406 $a_now,
407 "timestamp"
408 )
409 );
410
411 $ret = true;
412 } else {
413 $ret = false;
414 }
415 }
416 );
417
418 $ilAtomQuery->run();
419
420 //continue only if obj_stat_log counter >= $a_minimum
421 if ($ret) {
422 $ilAtomQuery = $ilDB->buildAtomQuery();
423 $ilAtomQuery->addTableLock('obj_stat_tmp');
424 $ilAtomQuery->addTableLock('obj_stat');
425
426 $ilAtomQuery->addQueryCallable(
427 function (ilDBInterface $ilDB) use ($a_now, $a_minimum) {
428
429 // process log data (timestamp is not needed anymore)
430 $sql = "SELECT obj_id, obj_type, yyyy, mm, dd, hh, SUM(read_count) AS read_count," .
431 " SUM(childs_read_count) AS childs_read_count, SUM(spent_seconds) AS spent_seconds," .
432 " SUM(childs_spent_seconds) AS childs_spent_seconds" .
433 " FROM obj_stat_tmp" .
434 " GROUP BY obj_id, obj_type, yyyy, mm, dd, hh";
435 $set = $ilDB->query($sql);
436 while ($row = $ilDB->fetchAssoc($set)) {
437 // "primary key"
438 $where = array("obj_id" => array("integer",
439 $row["obj_id"]
440 ),
441 "obj_type" => array("text",
442 $row["obj_type"]
443 ),
444 "yyyy" => array("integer",
445 $row["yyyy"]
446 ),
447 "mm" => array("integer", $row["mm"]),
448 "dd" => array("integer", $row["dd"]),
449 "hh" => array("integer", $row["hh"])
450 );
451
452 $where_sql = array();
453 foreach ($where as $field => $def) {
454 $where_sql[] = $field . " = " . $ilDB->quote(
455 $def[1],
456 $def[0]
457 );
458 }
459 $where_sql = implode(" AND ", $where_sql);
460
461 // existing entry?
462 $check = $ilDB->query(
463 "SELECT read_count, childs_read_count, spent_seconds," .
464 "childs_spent_seconds" .
465 " FROM obj_stat" .
466 " WHERE " . $where_sql
467 );
468 if ($ilDB->numRows($check)) {
469 $old = $ilDB->fetchAssoc($check);
470
471 // add existing values
472 $fields = array("read_count" => array("integer",
473 $old["read_count"] + $row["read_count"]
474 ),
475 "childs_read_count" => array("integer",
476 $old["childs_read_count"] + $row["childs_read_count"]
477 ),
478 "spent_seconds" => array("integer",
479 $old["spent_seconds"] + $row["spent_seconds"]
480 ),
481 "childs_spent_seconds" => array("integer",
482 $old["childs_spent_seconds"] + $row["childs_spent_seconds"]
483 )
484 );
485
486 $ilDB->update("obj_stat", $fields, $where);
487 } else {
488 // new entry
489 $fields = $where;
490 $fields["read_count"] = array("integer",
491 $row["read_count"]
492 );
493 $fields["childs_read_count"] = array("integer",
494 $row["childs_read_count"]
495 );
496 $fields["spent_seconds"] = array("integer",
497 $row["spent_seconds"]
498 );
499 $fields["childs_spent_seconds"] = array("integer",
500 $row["childs_spent_seconds"]
501 );
502
503 $ilDB->insert("obj_stat", $fields);
504 }
505 }
506
507 // clean up transfer table
508 $ilDB->query("DELETE FROM obj_stat_tmp");
509 }
510 );
511
512 $ilAtomQuery->run();
513 }
514 }
515 }
516
525 public static function _catchupWriteEvents(
526 int $obj_id,
527 int $usr_id,
528 ?string $timestamp = null
529 ): void {
530 global $DIC;
531
532 $ilDB = $DIC['ilDB'];
533
534 $query = "SELECT obj_id FROM catch_write_events " .
535 "WHERE obj_id = " . $ilDB->quote($obj_id, 'integer') . " " .
536 "AND usr_id = " . $ilDB->quote($usr_id, 'integer');
537 $res = $ilDB->query($query);
538 if ($res->numRows()) {
539 $ts = ($timestamp == null)
540 ? ilUtil::now()
541 : $timestamp;
542 } else {
543 $ts = ilUtil::now();
544 }
545
546 // alex, use replace due to bug #10406
547 $ilDB->replace(
548 "catch_write_events",
549 array(
550 "obj_id" => array("integer", $obj_id),
551 "usr_id" => array("integer", $usr_id)
552 ),
553 array(
554 "ts" => array("timestamp", $ts)
555 )
556 );
557 }
558
566 public static function _lookupUncaughtWriteEvents(
567 int $obj_id,
568 int $usr_id
569 ): array {
570 global $DIC;
571
572 $ilDB = $DIC['ilDB'];
573 $q = "SELECT ts " .
574 "FROM catch_write_events " .
575 "WHERE obj_id=" . $ilDB->quote($obj_id, 'integer') . " " .
576 "AND usr_id=" . $ilDB->quote($usr_id, 'integer');
577 $r = $ilDB->query($q);
578 $catchup = null;
579 while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
580 $catchup = $row['ts'];
581 }
582
583 if ($catchup == null) {
584 $query = sprintf(
585 'SELECT * FROM write_event ' .
586 'WHERE obj_id = %s ' .
587 'AND usr_id <> %s ' .
588 'ORDER BY ts DESC',
589 $ilDB->quote($obj_id, 'integer'),
590 $ilDB->quote($usr_id, 'integer')
591 );
592 $res = $ilDB->query($query);
593 } else {
594 $query = sprintf(
595 'SELECT * FROM write_event ' .
596 'WHERE obj_id = %s ' .
597 'AND usr_id <> %s ' .
598 'AND ts >= %s ' .
599 'ORDER BY ts DESC',
600 $ilDB->quote($obj_id, 'integer'),
601 $ilDB->quote($usr_id, 'integer'),
602 $ilDB->quote($catchup, 'timestamp')
603 );
604 $res = $ilDB->query($query);
605 }
606 $events = array();
607 while ($row = $ilDB->fetchAssoc($res)) {
608 $events[] = $row;
609 }
610 return $events;
611 }
612
622 public static function _lookupChangeState(int $obj_id, int $usr_id): int
623 {
624 global $DIC;
625
626 $ilDB = $DIC['ilDB'];
627
628 $q = "SELECT ts " .
629 "FROM catch_write_events " .
630 "WHERE obj_id=" . $ilDB->quote($obj_id, 'integer') . " " .
631 "AND usr_id=" . $ilDB->quote($usr_id, 'integer');
632 $r = $ilDB->query($q);
633 $catchup = null;
634 while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
635 $catchup = $row['ts'];
636 }
637
638 if ($catchup == null) {
639 $ilDB->setLimit(1);
640 $query = sprintf(
641 'SELECT * FROM write_event ' .
642 'WHERE obj_id = %s ' .
643 'AND usr_id <> %s ',
644 $ilDB->quote($obj_id, 'integer'),
645 $ilDB->quote($usr_id, 'integer')
646 );
647 $res = $ilDB->query($query);
648 } else {
649 $ilDB->setLimit(1);
650 $query = sprintf(
651 'SELECT * FROM write_event ' .
652 'WHERE obj_id = %s ' .
653 'AND usr_id <> %s ' .
654 'AND ts > %s ',
655 $ilDB->quote($obj_id, 'integer'),
656 $ilDB->quote($usr_id, 'integer'),
657 $ilDB->quote($catchup, 'timestamp')
658 );
659 $res = $ilDB->query($query);
660 }
661
662 $numRows = $res->numRows();
663 if ($numRows > 0) {
664 $row = $ilDB->fetchAssoc($res);
665 // if we have write events, and user never catched one, report as new (1)
666 // if we have write events, and user catched an old write event, report as changed (2)
667 return ($catchup == null) ? 1 : 2;
668 } else {
669 return 0; // user catched all write events, report as unchanged (0)
670 }
671 }
672
678 public static function _lookupReadEvents($obj_id, $usr_id = null)
679 {
680 global $DIC;
681
682 $ilDB = $DIC['ilDB'];
683
684 if ($usr_id == null) {
685 $query = sprintf(
686 'SELECT * FROM read_event ' .
687 'WHERE obj_id = %s ' .
688 'ORDER BY last_access DESC',
689 $ilDB->quote($obj_id, 'integer')
690 );
691 $res = $ilDB->query($query);
692 } else {
693 $query = sprintf(
694 'SELECT * FROM read_event ' .
695 'WHERE obj_id = %s ' .
696 'AND usr_id = %s ' .
697 'ORDER BY last_access DESC',
698 $ilDB->quote($obj_id, 'integer'),
699 $ilDB->quote($usr_id, 'integer')
700 );
701 $res = $ilDB->query($query);
702 }
703
704 $counter = 0;
705 $events = [];
706 while ($row = $ilDB->fetchAssoc($res)) {
707 $events[$counter]['obj_id'] = $row['obj_id'];
708 $events[$counter]['usr_id'] = $row['usr_id'];
709 $events[$counter]['last_access'] = $row['last_access'];
710 $events[$counter]['read_count'] = $row['read_count'];
711 $events[$counter]['spent_seconds'] = $row['spent_seconds'];
712 $events[$counter]['first_access'] = $row['first_access'];
713
714 $counter++;
715 }
716 return $events;
717 }
718
719 public static function lookupUsersInProgress(int $a_obj_id): array
720 {
721 global $DIC;
722
723 $ilDB = $DIC['ilDB'];
724
725 $query = sprintf(
726 'SELECT DISTINCT(usr_id) usr FROM read_event ' .
727 'WHERE obj_id = %s ',
728 $ilDB->quote($a_obj_id, 'integer')
729 );
730 $res = $ilDB->query($query);
731 $users = [];
732 while ($row = $ilDB->fetchObject($res)) {
733 $users[] = (int) $row->usr;
734 }
735 return $users;
736 }
737
741 public static function hasAccessed(int $a_obj_id, int $a_usr_id): bool
742 {
743 global $DIC;
744
745 $ilDB = $DIC['ilDB'];
746
747 if (isset(self::$has_accessed[$a_obj_id][$a_usr_id])) {
748 return self::$has_accessed[$a_obj_id][$a_usr_id];
749 }
750
751 $set = $ilDB->query(
752 "SELECT usr_id FROM read_event WHERE " .
753 "obj_id = " . $ilDB->quote($a_obj_id, "integer") . " AND " .
754 "usr_id = " . $ilDB->quote($a_usr_id, "integer")
755 );
756 if ($rec = $ilDB->fetchAssoc($set)) {
757 return self::$has_accessed[$a_obj_id][$a_usr_id] = true;
758 }
759 return self::$has_accessed[$a_obj_id][$a_usr_id] = false;
760 }
761
765 public static function _activate(): bool
766 {
768 return false;
769 } else {
770 global $DIC;
771
772 $ilDB = $DIC['ilDB'];
773
774 // Insert initial data into table write_event
775 // We need to do this here, because we need
776 // to catch up write events that occured while the change event tracking was
777 // deactivated.
778
779 // IGNORE isn't supported in oracle
780 $set = $ilDB->query(
781 sprintf(
782 'SELECT r1.obj_id,r2.obj_id p,d.owner,%s,d.create_date ' .
783 'FROM object_data d ' .
784 'LEFT JOIN write_event w ON d.obj_id = w.obj_id ' .
785 'JOIN object_reference r1 ON d.obj_id=r1.obj_id ' .
786 'JOIN tree t ON t.child=r1.ref_id ' .
787 'JOIN object_reference r2 on r2.ref_id=t.parent ' .
788 'WHERE w.obj_id IS NULL',
789 $ilDB->quote('create', 'text')
790 )
791 );
792 $res = null;
793 while ($rec = $ilDB->fetchAssoc($set)) {
794 $nid = $ilDB->nextId("write_event");
795 $query = 'INSERT INTO write_event ' .
796 '(write_id, obj_id,parent_obj_id,usr_id,action,ts) VALUES (' .
797 $ilDB->quote($nid, "integer") . "," .
798 $ilDB->quote($rec["obj_id"], "integer") . "," .
799 $ilDB->quote($rec["p"], "integer") . "," .
800 $ilDB->quote($rec["owner"], "integer") . "," .
801 $ilDB->quote("create", "text") . "," .
802 $ilDB->quote($rec["create_date"], "timestamp") .
803 ')';
804 $res = $ilDB->query($query);
805 }
806
807 global $DIC;
808
809 $ilSetting = $DIC['ilSetting'];
810 $ilSetting->set('enable_change_event_tracking', '1');
811
812 return $res !== null;
813 }
814 }
815
819 public static function _deactivate(): bool
820 {
821 global $DIC;
822
823 $ilSetting = $DIC['ilSetting'];
824 $ilSetting->set('enable_change_event_tracking', '0');
825 return true;
826 }
827
831 public static function _isActive(): bool
832 {
833 global $DIC;
834
835 $ilSetting = $DIC['ilSetting'];
836 return $ilSetting->get('enable_change_event_tracking', '0') == '1';
837 }
838
842 public static function _delete(int $a_obj_id): bool
843 {
844 global $DIC;
845
846 $ilDB = $DIC['ilDB'];
847 $query = sprintf(
848 'DELETE FROM write_event WHERE obj_id = %s ',
849 $ilDB->quote($a_obj_id, 'integer')
850 );
851 $aff = $ilDB->manipulate($query);
852
853 $query = sprintf(
854 'DELETE FROM read_event WHERE obj_id = %s ',
855 $ilDB->quote($a_obj_id, 'integer')
856 );
857 $aff = $ilDB->manipulate($query);
858 return true;
859 }
860
861 public static function _deleteReadEvents(int $a_obj_id): void
862 {
863 global $DIC;
864
865 $ilDB = $DIC['ilDB'];
866
867 $ilDB->manipulate(
868 "DELETE FROM read_event" .
869 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer")
870 );
871 }
872
873 public static function _deleteReadEventsForUsers(
874 int $a_obj_id,
875 array $a_user_ids
876 ): void {
877 global $DIC;
878
879 $ilDB = $DIC['ilDB'];
880
881 $ilDB->manipulate(
882 "DELETE FROM read_event" .
883 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") .
884 " AND " . $ilDB->in("usr_id", $a_user_ids, "", "integer")
885 );
886 }
887
888 public static function _getAllUserIds(int $a_obj_id): array
889 {
890 global $DIC;
891
892 $ilDB = $DIC['ilDB'];
893 $res = array();
894 $set = $ilDB->query(
895 "SELECT usr_id FROM read_event" .
896 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer")
897 );
898 while ($row = $ilDB->fetchAssoc($set)) {
899 $res[] = (int) $row["usr_id"];
900 }
901 return $res;
902 }
903}
$check
Definition: buildRTE.php:81
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
Class ilChangeEvent tracks change events on repository objects.
static _deleteReadEvents(int $a_obj_id)
static _syncObjectStats(?int $a_now=null, int $a_minimum=20000)
static _recordReadEvent(string $a_type, int $a_ref_id, int $obj_id, int $usr_id, bool $isCatchupWriteEvents=true, $a_ext_rc=null, $a_ext_time=null)
static _lookupReadEvents($obj_id, $usr_id=null)
Reads all read events which occured on the object.
static _isActive()
Returns true, if change event tracking is active.
static hasAccessed(int $a_obj_id, int $a_usr_id)
Has accessed.
static _deleteReadEventsForUsers(int $a_obj_id, array $a_user_ids)
static array $has_accessed
static _lookupUncaughtWriteEvents(int $obj_id, int $usr_id)
Reads all write events which occured on the object which happened after the last time the user caught...
static _activate()
Activates change event tracking.
static _lookupChangeState(int $obj_id, int $usr_id)
Returns the change state of the object for the specified user.
static _deactivate()
Deactivates change event tracking.
static lookupUsersInProgress(int $a_obj_id)
static _recordObjStats(int $a_obj_id, ?int $a_spent_seconds, ?int $a_read_count, ?int $a_childs_spent_seconds=null, ?int $a_child_read_count=null)
static _catchupWriteEvents(int $obj_id, int $usr_id, ?string $timestamp=null)
Catches up with all write events which occured before the specified timestamp.
static _delete(int $a_obj_id)
Delete object entries.
static _getAllUserIds(int $a_obj_id)
static _recordWriteEvent(int $obj_id, int $usr_id, string $action, ?int $parent_obj_id=null)
Records a write event.
static _lookupType(int $id, bool $reference=false)
static _lookupObjId(int $ref_id)
static now()
Return current timestamp in Y-m-d H:i:s format.
global $DIC
Definition: feed.php:28
Interface ilDBInterface.
$path
Definition: ltiservices.php:32
$res
Definition: ltiservices.php:69
global $ilSetting
Definition: privfeed.php:17
$query