ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
ilChangeEvent Class Reference

Class ilChangeEvent tracks change events on repository objects. More...

+ Collaboration diagram for ilChangeEvent:

Static Public Member Functions

static _recordWriteEvent ($obj_id, $usr_id, $action, $parent_obj_id=null)
 Records a write event. More...
 
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. More...
 
static _recordObjStats ($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds=null, $a_child_read_count=null)
 
static _syncObjectStats ($a_now=null, $a_minimum=20000)
 Process object statistics log data. More...
 
static _catchupWriteEvents ($obj_id, $usr_id, $timestamp=null)
 Catches up with all write events which occured before the specified timestamp. More...
 
static _lookupUncaughtWriteEvents ($obj_id, $usr_id)
 Catches up with all write events which occured before the specified timestamp. More...
 
static _lookupChangeState ($obj_id, $usr_id)
 Returns the change state of the object for the specified user. More...
 
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 up with them. More...
 
static lookupUsersInProgress ($a_obj_id)
 Lookup users in progress. More...
 
static hasAccessed ($a_obj_id, $a_usr_id)
 Has accessed. More...
 
static _activate ()
 Activates change event tracking. More...
 
static _deactivate ()
 Deactivates change event tracking. More...
 
static _isActive ()
 Returns true, if change event tracking is active. More...
 
static _delete ($a_obj_id)
 Delete object entries. More...
 
static _deleteReadEvents ($a_obj_id)
 
static _deleteReadEventsForUsers ($a_obj_id, array $a_user_ids)
 
static _getAllUserIds ($a_obj_id)
 
static _updateAccessForScormOfflinePlayer ($obj_id, $usr_id, $i_last_access, $t_first_access)
 _updateAccessForScormOfflinePlayer needed to synchronize last_access and first_access when learning modul is used offline called in . More...
 

Static Private Attributes

static $has_accessed = array()
 

Detailed Description

Class ilChangeEvent tracks change events on repository objects.

The following events are considered to be a 'write event':

  • The creation of a new repository object
  • A change of the data or meta-data of an object
  • A move, link, copy, deletion or undeletion of the object UI objects, which cause a 'write event', must call _recordWriteEvent(...) In most cases, UI objects let the user catch up with write events on the object, when doing this call.

The following events are considered to be a 'read event':

  • Opening a container object in the browser*
  • Opening / downloading / reading an object UI objects, which cause a 'read event', must call _recordReadEvent(...). In most cases, UI objects let the user catch up with write events on the object, when doing this call.

*reading the content of a container using WebDAV is not counted, because WebDAV clients can't see all objects in a container.

A user can catch up with write events, by calling __catchupWriteEvents(...).

A user can query, if an object has changed, since the last time he has caught up with write events, by calling _lookupUncaughtWriteEvents(...).

Author
Werner Randelshofer werne.nosp@m.r.ra.nosp@m.ndels.nosp@m.hofe.nosp@m.r@hsl.nosp@m.u.ch
Version
Id
class.ilChangeEvent.php,v 1.02 2007/05/07 19:25:34 wrandels Exp

Definition at line 36 of file class.ilChangeEvent.php.

Member Function Documentation

◆ _activate()

static ilChangeEvent::_activate ( )
static

Activates change event tracking.

Returns
mixed true on success, a string with an error message on failure.

Definition at line 829 of file class.ilChangeEvent.php.

829 {
831 {
832 return 'change event tracking is already active';
833 }
834 else
835 {
836 global $ilDB;
837
838 // Insert initial data into table write_event
839 // We need to do this here, because we need
840 // to catch up write events that occured while the change event tracking was
841 // deactivated.
842
843 // IGNORE isn't supported in oracle
844 $set = $ilDB->query(sprintf('SELECT r1.obj_id,r2.obj_id p,d.owner,%s,d.create_date '.
845 'FROM object_data d '.
846 'LEFT JOIN write_event w ON d.obj_id = w.obj_id '.
847 'JOIN object_reference r1 ON d.obj_id=r1.obj_id '.
848 'JOIN tree t ON t.child=r1.ref_id '.
849 'JOIN object_reference r2 on r2.ref_id=t.parent '.
850 'WHERE w.obj_id IS NULL',
851 $ilDB->quote('create','text')));
852 while ($rec = $ilDB->fetchAssoc($set))
853 {
854 $nid = $ilDB->nextId("write_event");
855 $query = 'INSERT INTO write_event '.
856 '(write_id, obj_id,parent_obj_id,usr_id,action,ts) VALUES ('.
857 $ilDB->quote($nid, "integer").",".
858 $ilDB->quote($rec["obj_id"], "integer").",".
859 $ilDB->quote($rec["p"], "integer").",".
860 $ilDB->quote($rec["owner"], "integer").",".
861 $ilDB->quote("create", "text").",".
862 $ilDB->quote($rec["create_date"], "timestamp").
863 ')';
864 $res = $ilDB->query($query);
865 }
866
867 global $ilSetting;
868 $ilSetting->set('enable_change_event_tracking', '1');
869
870 return $res;
871 }
872 }
sprintf('%.4f', $callTime)
static _isActive()
Returns true, if change event tracking is active.
global $ilSetting
Definition: privfeed.php:17
global $ilDB

References $ilDB, $ilSetting, $query, $res, _isActive(), and sprintf.

Referenced by ilObjRepositorySettingsGUI\saveSettings(), and ilTrackingTest\testChangeEvent().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _catchupWriteEvents()

static ilChangeEvent::_catchupWriteEvents (   $obj_id,
  $usr_id,
  $timestamp = null 
)
static

Catches up with all write events which occured before the specified timestamp.

Parameters
$obj_idint The object.
$usr_idint The user.
$timestampSQL timestamp.

Definition at line 504 of file class.ilChangeEvent.php.

505 {
506 global $ilDB;
507
508 $query = "SELECT obj_id FROM catch_write_events ".
509 "WHERE obj_id = ".$ilDB->quote($obj_id ,'integer')." ".
510 "AND usr_id = ".$ilDB->quote($usr_id ,'integer');
511 $res = $ilDB->query($query);
512 if($res->numRows())
513 {
514 $ts = ($timestamp == null)
515 ? ilUtil::now()
516 : $timestamp;
517/* $query = "UPDATE catch_write_events ".
518 "SET ts = ".($timestamp == null ? $ilDB->now() : $ilDB->quote($timestamp, 'timestamp'))." ".
519 "WHERE usr_id = ".$ilDB->quote($usr_id ,'integer')." ".
520 "AND obj_id = ".$ilDB->quote($obj_id ,'integer');
521 $res = $ilDB->manipulate($query);*/
522 }
523 else
524 {
525 $ts = ilUtil::now();
526/* $query = "INSERT INTO catch_write_events (ts,obj_id,usr_id) ".
527 "VALUES( ".
528 $ilDB->now().", ".
529 $ilDB->quote($obj_id,'integer').", ".
530 $ilDB->quote($usr_id,'integer')." ".
531 ")";
532 $res = $ilDB->manipulate($query);*/
533 }
534
535 // alex, use replace due to bug #10406
536 $ilDB->replace("catch_write_events",
537 array(
538 "obj_id" => array("integer", $obj_id),
539 "usr_id" => array("integer", $usr_id)
540 ),
541 array(
542 "ts" => array("timestamp", $ts))
543 );
544 }
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
static now()
Return current timestamp in Y-m-d H:i:s format.

References $ilDB, $query, $res, $timestamp, and ilUtil\now().

Referenced by _recordReadEvent(), ilContainerGUI\pasteObject(), ilContainerGUI\performPasteIntoMultipleObjectsObject(), ilDAVServer\PUT(), ilRepUtil\restoreObjects(), ilObjFileGUI\update(), ilObjCategoryGUI\updateObject(), ilObjCourseGUI\updateObject(), ilObjGroupGUI\updateObject(), and ilObjRootFolderGUI\updateObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _deactivate()

static ilChangeEvent::_deactivate ( )
static

Deactivates change event tracking.

Returns
mixed true on success, a string with an error message on failure.

Definition at line 879 of file class.ilChangeEvent.php.

879 {
880 global $ilSetting;
881 $ilSetting->set('enable_change_event_tracking', '0');
882 }

References $ilSetting.

Referenced by ilObjRepositorySettingsGUI\saveSettings(), and ilTrackingTest\testChangeEvent().

+ Here is the caller graph for this function:

◆ _delete()

static ilChangeEvent::_delete (   $a_obj_id)
static

Delete object entries.

Returns

Definition at line 900 of file class.ilChangeEvent.php.

901 {
902 global $ilDB;
903
904 $query = sprintf('DELETE FROM write_event WHERE obj_id = %s ',
905 $ilDB->quote($a_obj_id,'integer'));
906 $aff = $ilDB->manipulate($query);
907
908 $query = sprintf('DELETE FROM read_event WHERE obj_id = %s ',
909 $ilDB->quote($a_obj_id,'integer'));
910 $aff = $ilDB->manipulate($query);
911 return true;
912 }

References $ilDB, $query, and sprintf.

Referenced by ilObjectLP\handleDelete().

+ Here is the caller graph for this function:

◆ _deleteReadEvents()

static ilChangeEvent::_deleteReadEvents (   $a_obj_id)
static

Definition at line 914 of file class.ilChangeEvent.php.

915 {
916 global $ilDB;
917
918 $ilDB->manipulate("DELETE FROM read_event".
919 " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer"));
920 }

References $ilDB.

◆ _deleteReadEventsForUsers()

static ilChangeEvent::_deleteReadEventsForUsers (   $a_obj_id,
array  $a_user_ids 
)
static

Definition at line 922 of file class.ilChangeEvent.php.

923 {
924 global $ilDB;
925
926 $ilDB->manipulate("DELETE FROM read_event".
927 " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer").
928 " AND ".$ilDB->in("usr_id", $a_user_ids, "", "integer"));
929 }

References $ilDB.

Referenced by ilObjSCORM2004LearningModule\deleteTrackingDataOfUsers(), ilObjSCORMLearningModule\deleteTrackingDataOfUsers(), and ilObjectLP\resetLPDataForUserIds().

+ Here is the caller graph for this function:

◆ _getAllUserIds()

static ilChangeEvent::_getAllUserIds (   $a_obj_id)
static

Definition at line 931 of file class.ilChangeEvent.php.

932 {
933 global $ilDB;
934
935 $res = array();
936
937 $set = $ilDB->query("SELECT usr_id FROM read_event".
938 " WHERE obj_id = ".$ilDB->quote($a_obj_id, "integer"));
939 while($row = $ilDB->fetchAssoc($set))
940 {
941 $res[] = $row["usr_id"];
942 }
943
944 return $res;
945 }

References $ilDB, $res, and $row.

Referenced by ilObjectLP\gatherLPUsers().

+ Here is the caller graph for this function:

◆ _isActive()

static ilChangeEvent::_isActive ( )
static

Returns true, if change event tracking is active.

Returns
mixed true on success, a string with an error message on failure.

Definition at line 889 of file class.ilChangeEvent.php.

889 {
890 global $ilSetting;
891 return $ilSetting->get('enable_change_event_tracking', '0') == '1';
892 }

References $ilSetting.

Referenced by ilObjUserTracking\__readSettings(), _activate(), ilInfoScreenGUI\addObjectSections(), ilObjRepositorySettingsGUI\addToExternalSettingsForm(), and ilObjRepositorySettingsGUI\initSettingsForm().

+ Here is the caller graph for this function:

◆ _lookupChangeState()

static ilChangeEvent::_lookupChangeState (   $obj_id,
  $usr_id 
)
static

Returns the change state of the object for the specified user.

which happened after the last time the user caught up with them.

Parameters
$obj_idint The object
$usr_idint The user who is interested into these events.
Returns
0 = object is unchanged, 1 = object is new, 2 = object has changed

Definition at line 646 of file class.ilChangeEvent.php.

647 {
648 global $ilDB;
649
650 $q = "SELECT ts ".
651 "FROM catch_write_events ".
652 "WHERE obj_id=".$ilDB->quote($obj_id ,'integer')." ".
653 "AND usr_id=".$ilDB->quote($usr_id ,'integer');
654 $r = $ilDB->query($q);
655 $catchup = null;
656 while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
657 $catchup = $row['ts'];
658 }
659
660 if($catchup == null)
661 {
662 $ilDB->setLimit(1);
663 $query = sprintf('SELECT * FROM write_event '.
664 'WHERE obj_id = %s '.
665 'AND usr_id <> %s ',
666 $ilDB->quote($obj_id,'integer'),
667 $ilDB->quote($usr_id,'integer'));
668 $res = $ilDB->query($query);
669 }
670 else
671 {
672 $ilDB->setLimit(1);
673 $query = sprintf('SELECT * FROM write_event '.
674 'WHERE obj_id = %s '.
675 'AND usr_id <> %s '.
676 'AND ts > %s ',
677 $ilDB->quote($obj_id,'integer'),
678 $ilDB->quote($usr_id,'integer'),
679 $ilDB->quote($catchup,'timestamp'));
680 $res = $ilDB->query($query);
681 }
682
683 $numRows = $res->numRows();
684 if ($numRows > 0)
685 {
686 $row = $ilDB->fetchAssoc($res);
687 // if we have write events, and user never catched one, report as new (1)
688 // if we have write events, and user catched an old write event, report as changed (2)
689 return ($catchup == null) ? 1 : 2;
690 }
691 else
692 {
693 return 0; // user catched all write events, report as unchanged (0)
694 }
695 }
$r
Definition: example_031.php:79

References $ilDB, $query, $r, $res, $row, ilDBConstants\FETCHMODE_ASSOC, and sprintf.

Referenced by ilTrackingTest\testChangeEvent().

+ Here is the caller graph for this function:

◆ _lookupReadEvents()

static ilChangeEvent::_lookupReadEvents (   $obj_id,
  $usr_id = null 
)
static

Reads all read events which occured on the object which happened after the last time the user caught up with them.

NOTE: THIS FUNCTION NEEDS TO BE REWRITTEN. READ EVENTS ARE OF INTEREST AT REF_ID's OF OBJECTS.

Parameters
$obj_idint The object
$usr_idint The user who is interested into these events. / public static function _lookupUncaughtReadEvents($obj_id, $usr_id) { global $ilDB;

$q = "SELECT ts ". "FROM catch_read_events ". "WHERE obj_id=".$ilDB->quote($obj_id)." ". "AND usr_id=".$ilDB->quote($usr_id); $r = $ilDB->query($q); $catchup = null; while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) { $catchup = $row['ts']; }

$q = "SELECT * ". "FROM read_event ". "WHERE obj_id=".$ilDB->quote($obj_id)." ". ($catchup == null ? "" : "AND last_access > ".$ilDB->quote($catchup))." ". ($catchup == null ? "" : "AND last_access > ".$ilDB->quote($catchup))." ". "ORDER BY last_access DESC"; $r = $ilDB->query($q); $events = array(); while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) { $events[] = $row; } return $events; } Reads all read events which occured on the object.

Parameters
$obj_idint The object
$usr_idint Optional, the user who performed these events.

Definition at line 741 of file class.ilChangeEvent.php.

742 {
743 global $ilDB;
744
745 if ($usr_id == null)
746 {
747 $query = sprintf('SELECT * FROM read_event '.
748 'WHERE obj_id = %s '.
749 'ORDER BY last_access DESC',
750 $ilDB->quote($obj_id,'integer'));
751 $res = $ilDB->query($query);
752 }
753 else
754 {
755 $query = sprintf('SELECT * FROM read_event '.
756 'WHERE obj_id = %s '.
757 'AND usr_id = %s '.
758 'ORDER BY last_access DESC',
759 $ilDB->quote($obj_id,'integer'),
760 $ilDB->quote($usr_id,'integer'));
761 $res = $ilDB->query($query);
762 }
763
764 $counter = 0;
765 while ($row = $ilDB->fetchAssoc($res))
766 {
767 $events[$counter]['obj_id'] = $row['obj_id'];
768 $events[$counter]['usr_id'] = $row['usr_id'];
769 $events[$counter]['last_access'] = $row['last_access'];
770 $events[$counter]['read_count'] = $row['read_count'];
771 $events[$counter]['spent_seconds'] = $row['spent_seconds'];
772 $events[$counter]['first_access'] = $row['first_access'];
773
774 $counter++;
775
776 }
777 return $events ? $events : array();
778 }
$counter

References $counter, $ilDB, $query, $res, $row, and sprintf.

Referenced by ilLPStatusDownloaded\_getCompleted(), ilLPStatusTypicalLearningTime\_getCompleted(), ilLPStatusVisits\_getCompleted(), ilLPStatusTypicalLearningTime\_getInProgress(), ilLPStatusVisits\_getInProgress(), ilLearningProgress\_getProgress(), ilLearningProgress\_lookupProgressByObjId(), ilInfoScreenGUI\addObjectSections(), ilLPStatusTypicalLearningTime\determinePercentage(), ilLPStatusVisits\determinePercentage(), ilLPStatusTypicalLearningTime\determineStatus(), ilLPStatusVisits\determineStatus(), and ilSCORMOfflineMode\il2sopSahsUser().

+ Here is the caller graph for this function:

◆ _lookupUncaughtWriteEvents()

static ilChangeEvent::_lookupUncaughtWriteEvents (   $obj_id,
  $usr_id 
)
static

Catches up with all write events which occured before the specified timestamp.

THIS FUNCTION IS CURRENTLY NOT IN USE. BEFORE IT CAN BE USED, THE TABLE catch_read_events MUST BE CREATED.

Parameters
$obj_idint The object.
$usr_idint The user.
$timestampSQL timestamp. / function _catchupReadEvents($obj_id, $usr_id, $timestamp = null) { global $ilDB;

$q = "INSERT INTO catch_read_events ". "(obj_id, usr_id, action, ts) ". "VALUES (". $ilDB->quote($obj_id).",". $ilDB->quote($usr_id).",". $ilDB->quote('read').","; if ($timestamp == null) { $q .= "NOW()". ") ON DUPLICATE KEY UPDATE ts=NOW()"; } else { $q .= $ilDB->quote($timestamp). ") ON DUPLICATE KEY UPDATE ts=".$ilDB->quote($timestamp); }

$r = $ilDB->query($q); } Reads all write events which occured on the object which happened after the last time the user caught up with them.

Parameters
$obj_idint The object
$usr_idint The user who is interested into these events.
Returns
array with rows from table write_event

Definition at line 593 of file class.ilChangeEvent.php.

594 {
595 global $ilDB;
596
597 $q = "SELECT ts ".
598 "FROM catch_write_events ".
599 "WHERE obj_id=".$ilDB->quote($obj_id ,'integer')." ".
600 "AND usr_id=".$ilDB->quote($usr_id ,'integer');
601 $r = $ilDB->query($q);
602 $catchup = null;
603 while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
604 $catchup = $row['ts'];
605 }
606
607 if($catchup == null)
608 {
609 $query = sprintf('SELECT * FROM write_event '.
610 'WHERE obj_id = %s '.
611 'AND usr_id <> %s '.
612 'ORDER BY ts DESC',
613 $ilDB->quote($obj_id,'integer'),
614 $ilDB->quote($usr_id,'integer'));
615 $res = $ilDB->query($query);
616 }
617 else
618 {
619 $query = sprintf('SELECT * FROM write_event '.
620 'WHERE obj_id = %s '.
621 'AND usr_id <> %s '.
622 'AND ts >= %s '.
623 'ORDER BY ts DESC',
624 $ilDB->quote($obj_id,'integer'),
625 $ilDB->quote($usr_id,'integer'),
626 $ilDB->quote($catchup,'timestamp'));
627 $res = $ilDB->query($query);
628 }
629 $events = array();
630 while($row = $ilDB->fetchAssoc($res))
631 {
632 $events[] = $row;
633 }
634 return $events;
635 }

References $ilDB, $query, $r, $res, $row, ilDBConstants\FETCHMODE_ASSOC, and sprintf.

Referenced by ilTrackingTest\testChangeEvent().

+ Here is the caller graph for this function:

◆ _recordObjStats()

static ilChangeEvent::_recordObjStats (   $a_obj_id,
  $a_spent_seconds,
  $a_read_count,
  $a_childs_spent_seconds = null,
  $a_child_read_count = null 
)
static

Definition at line 324 of file class.ilChangeEvent.php.

325 {
326 global $ilDB;
327
329 (int)$a_obj_id <= 0) // #12706
330 {
331 return;
332 }
333
334 $now = time();
335
336 $fields = array();
337 $fields['log_id'] = array("integer", $ilDB->nextId('obj_stat_log'));
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 }
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
static _syncObjectStats($a_now=null, $a_minimum=20000)
Process object statistics log data.
static _enabledObjectStatistics()
check wether object statistics is enabled or not
static _lookupType($a_id, $a_reference=false)
lookup object type

References $ilDB, ilObjUserTracking\_enabledObjectStatistics(), ilObject\_lookupType(), _syncObjectStats(), and date.

Referenced by _recordReadEvent().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _recordReadEvent()

static ilChangeEvent::_recordReadEvent (   $a_type,
  $a_ref_id,
  $obj_id,
  $usr_id,
  $isCatchupWriteEvents = true,
  $a_ext_rc = false,
  $a_ext_time = false 
)
static

Records a read event and catches up with write events.

Parameters
$obj_idint The object which was read.
$usr_idint The user who performed a read action.
$catchupWriteEventsboolean If true, this function catches up with write events.

Definition at line 112 of file class.ilChangeEvent.php.

114 {
115 global $ilDB, $tree;
116
117 /* read_event data is now used for several features, so we are always keeping track
118 if (!ilChangeEvent::_isActive())
119 {
120 return;
121 }
122 */
123
124 include_once('Services/Tracking/classes/class.ilObjUserTracking.php');
125 $validTimeSpan = ilObjUserTracking::_getValidTimeSpan();
126
127 $query = sprintf('SELECT * FROM read_event '.
128 'WHERE obj_id = %s '.
129 'AND usr_id = %s ',
130 $ilDB->quote($obj_id,'integer'),
131 $ilDB->quote($usr_id,'integer'));
132 $res = $ilDB->query($query);
133 $row = $ilDB->fetchObject($res);
134
135 // read counter
136 if ($a_ext_rc !== false)
137 {
138 $read_count = 'read_count = '.$ilDB->quote($a_ext_rc, "integer").", ";
139 $read_count_init = max(1, (int) $a_ext_rc);
140 $read_count_diff = max(1, (int) $a_ext_rc) - $row->read_count;
141 }
142 else
143 {
144 $read_count = 'read_count = read_count + 1, ';
145 $read_count_init = 1;
146 $read_count_diff = 1;
147 }
148
149 if ($row)
150 {
151
152 if ($a_ext_time !== false)
153 {
154 $time = (int) $a_ext_time;
155 }
156 else
157 {
158 $time = $ilDB->quote((time() - $row->last_access) <= $validTimeSpan
159 ? $row->spent_seconds + time() - $row->last_access
160 : $row->spent_seconds,'integer');
161
162 // if we are in the valid interval, we do not
163 // add anything to the read_count, since this is the
164 // same access for us
165 if ((time() - $row->last_access) <= $validTimeSpan)
166 {
167 $read_count = '';
168 $read_count_init = 1;
169 $read_count_diff = 0;
170 }
171 }
172 $time_diff = $time - (int) $row->spent_seconds;
173
174 // Update
175 $query = sprintf('UPDATE read_event SET '.
176 $read_count.
177 'spent_seconds = %s, '.
178 'last_access = %s '.
179 'WHERE obj_id = %s '.
180 'AND usr_id = %s ',
181 $time,
182 $ilDB->quote(time(),'integer'),
183 $ilDB->quote($obj_id,'integer'),
184 $ilDB->quote($usr_id,'integer'));
185 $aff = $ilDB->manipulate($query);
186
187 self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
188 }
189 else
190 {
191 if ($a_ext_time !== false)
192 {
193 $time = (int) $a_ext_time;
194 }
195 else
196 {
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('read_event',
215 array(
216 'obj_id' => array('integer', $obj_id),
217 'usr_id' => array('integer', $usr_id)
218 ),
219 array(
220 'read_count' => array('integer', $read_count_init),
221 'spent_seconds' => array('integer', $time),
222 'first_access' => array('timestamp', date("Y-m-d H:i:s")), // was $ilDB->now()
223 'last_access' => array('integer', time())
224 )
225 );
226
227 self::$has_accessed[$obj_id][$usr_id] = true;
228
229 self::_recordObjStats($obj_id, $time_diff, $read_count_diff);
230 }
231
232 if ($isCatchupWriteEvents)
233 {
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 {
240 if ($tree->isInTree($a_ref_id))
241 {
242 $path = $tree->getPathId($a_ref_id);
243
244 foreach ($path as $p)
245 {
246 $obj2_id = ilObject::_lookupObjId($p);
247 $obj2_type = ilObject::_lookupType($obj2_id);
248//echo "<br>1-$obj2_type-$p-$obj2_id-";
249 if (($p != $a_ref_id) && (in_array($obj2_type, array("crs", "fold", "grp"))))
250 {
251 $query = sprintf('SELECT * FROM read_event '.
252 'WHERE obj_id = %s '.
253 'AND usr_id = %s ',
254 $ilDB->quote($obj2_id, 'integer'),
255 $ilDB->quote($usr_id, 'integer'));
256 $res2 = $ilDB->query($query);
257 if ($row2 = $ilDB->fetchAssoc($res2))
258 {
259//echo "<br>2";
260 // update read count and spent seconds
261 $query = sprintf('UPDATE read_event SET '.
262 'childs_read_count = childs_read_count + %s ,'.
263 'childs_spent_seconds = childs_spent_seconds + %s '.
264 'WHERE obj_id = %s '.
265 'AND usr_id = %s ',
266 $ilDB->quote((int) $read_count_diff,'integer'),
267 $ilDB->quote((int) $time_diff,'integer'),
268 $ilDB->quote($obj2_id,'integer'),
269 $ilDB->quote($usr_id,'integer'));
270 $aff = $ilDB->manipulate($query);
271
272 self::_recordObjStats($obj2_id, null, null, (int)$time_diff, (int)$read_count_diff);
273 }
274 else
275 {
276//echo "<br>3";
277//$ilLog->write("insert read event for obj_id -".$obj2_id."-".$usr_id."-");
278 /*
279 $query = sprintf('INSERT INTO read_event (obj_id,usr_id,last_access,read_count,spent_seconds,first_access,'.
280 'childs_read_count, childs_spent_seconds) '.
281 'VALUES (%s,%s,%s,%s,%s,'.$ilDB->now().', %s, %s) ',
282 $ilDB->quote($obj2_id,'integer'),
283 $ilDB->quote($usr_id,'integer'),
284 $ilDB->quote(time(),'integer'),
285 $ilDB->quote(1,'integer'),
286 $ilDB->quote($time,'integer'),
287 $ilDB->quote((int) $read_count_diff,'integer'),
288 $ilDB->quote((int) $time_diff,'integer')
289 );
290 $aff = $ilDB->manipulate($query);
291 */
292
293 // #10407
294 $ilDB->replace('read_event',
295 array(
296 'obj_id' => array('integer', $obj2_id),
297 'usr_id' => array('integer', $usr_id)
298 ),
299 array(
300 'read_count' => array('integer', 1),
301 'spent_seconds' => array('integer', $time),
302 'first_access' => array('timestamp', date("Y-m-d H:i:s")), // was $ilDB->now()
303 'last_access' => array('integer', time()),
304 'childs_read_count' => array('integer', (int)$read_count_diff),
305 'childs_spent_seconds' => array('integer', (int)$time_diff)
306 )
307 );
308
309 self::$has_accessed[$obj2_id][$usr_id] = true;
310
311 self::_recordObjStats($obj2_id, $time, 1, (int)$time_diff, (int)$read_count_diff);
312 }
313 }
314 }
315 }
316 }
317
318 // @todo:
319 // - calculate diff of spent_seconds and read_count
320 // - use ref id to get parents of types grp, crs, fold
321 // - add diffs to childs_spent_seconds and childs_read_count
322 }
$path
Definition: aliased.php:25
static _recordObjStats($a_obj_id, $a_spent_seconds, $a_read_count, $a_childs_spent_seconds=null, $a_child_read_count=null)
static _catchupWriteEvents($obj_id, $usr_id, $timestamp=null)
Catches up with all write events which occured before the specified timestamp.
static _lookupObjId($a_id)
$time_diff
Definition: langcheck.php:760
$a_type
Definition: workflow.php:93

References $a_type, $ilDB, $path, $query, $res, $row, $time_diff, _catchupWriteEvents(), ilObjUserTracking\_getValidTimeSpan(), ilObject\_lookupObjId(), ilObject\_lookupType(), _recordObjStats(), date, and sprintf.

Referenced by ilLicense\_noteAccess(), ilObjSCORMTracking\_syncReadEvent(), ilSCORM2004Tracking\_syncReadEvent(), ilLearningProgress\_tracProgress(), ilRemoteObjectBaseGUI\callObject(), ilDAVServer\COPY(), ilDAVServer\GET(), ilObjMediaCast\handleLPUpdate(), ilObjSCORMLearningModule\importSuccessForSahsUser(), ilWikiPageGUI\increaseViewCount(), ilObjSessionGUI\infoScreen(), ilContainerGUI\performPasteIntoMultipleObjectsObject(), ilDAVServer\PROPFIND(), ilObjLinkResourceGUI\redirectToLink(), ilObjPortfolioBaseGUI\renderFullscreenHeader(), ilObjBlogGUI\renderFullscreenHeader(), ilObjFileGUI\sendFile(), ilContainerContentGUI\setOutput(), ilObjMediaCastGUI\showContentObject(), ilObjSCORMTracking\syncGlobalStatus(), ilObjTestGUI\trackTestObjectReadEvent(), ilCourseContentGUI\view(), and ilObjectGUI\viewObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _recordWriteEvent()

static ilChangeEvent::_recordWriteEvent (   $obj_id,
  $usr_id,
  $action,
  $parent_obj_id = null 
)
static

Records a write event.

The parent object should be specified for the 'delete', 'undelete' and 'add' and 'remove' events.

Parameters
$obj_idint The object which was written to.
$usr_idint The user who performed a write action.
$actionstring The name of the write action. 'create', 'update', 'delete', 'add', 'remove', 'undelete'.
$parent_obj_idint The object id of the parent object. If this is null, then the event is recorded for all parents of the object. If this is not null, then the event is only recorded for the specified parent.

Definition at line 55 of file class.ilChangeEvent.php.

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 }

References $ilDB, $query, and sprintf.

Referenced by ilObjCourseGUI\afterSave(), ilDAVServer\COPY(), ilDAVServer\DELETE(), ilObjFileGUI\handleFileUpload(), ilDAVServer\MKCOL(), ilDAVServer\MOVE(), ilContainerGUI\pasteObject(), ilContainerGUI\performPasteIntoMultipleObjectsObject(), ilDAVServer\PUT(), ilObject2GUI\putObjectInTree(), ilObjectGUI\putObjectInTree(), ilRepUtil\removeObjectsFromSystem(), ilRepUtil\restoreObjects(), ilObjFileGUI\save(), ilObjFileGUI\update(), ilObjCategoryGUI\updateObject(), ilObjCourseGUI\updateObject(), ilObjGroupGUI\updateObject(), and ilObjRootFolderGUI\updateObject().

+ Here is the caller graph for this function:

◆ _syncObjectStats()

static ilChangeEvent::_syncObjectStats (   $a_now = null,
  $a_minimum = 20000 
)
static

Process object statistics log data.

Parameters
integer$a_now
integer$a_minimum

Definition at line 376 of file class.ilChangeEvent.php.

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 $ilAtomQuery = $ilDB->buildAtomQuery();
393 $ilAtomQuery->addTableLock('obj_stat_log');
394 $ilAtomQuery->addTableLock('obj_stat_tmp');
395
396 $ilAtomQuery->addQueryCallable(function(ilDBInterface $ilDB) use($a_now, $a_minimum, &$ret){
397
398 // if other process was transferring, we had to wait for the lock and
399 // the source table should now have less than minimum/needed entries
400 $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
401 $row = $ilDB->fetchAssoc($set);
402 if($row["counter"] >= $a_minimum)
403 {
404 // use only "full" seconds to have a clear cut
405 $ilDB->query("INSERT INTO obj_stat_tmp".
406 " SELECT * FROM obj_stat_log".
407 " WHERE tstamp < ".$ilDB->quote($a_now, "timestamp"));
408
409 // remove transferred entries from source table
410 $ilDB->query("DELETE FROM obj_stat_log".
411 " WHERE tstamp < ".$ilDB->quote($a_now, "timestamp"));
412
413 $ret = true;
414 }
415 else
416 {
417 $ret = false;
418 }
419 });
420
421 $ilAtomQuery->run();
422
423 //continue only if obj_stat_log counter >= $a_minimum
424 if($ret)
425 {
426 $ilAtomQuery = $ilDB->buildAtomQuery();
427 $ilAtomQuery->addTableLock('obj_stat_tmp');
428 $ilAtomQuery->addTableLock('obj_stat');
429
430 $ilAtomQuery->addQueryCallable(function(ilDBInterface $ilDB) use($a_now, $a_minimum){
431
432 // process log data (timestamp is not needed anymore)
433 $sql = "SELECT obj_id, obj_type, yyyy, mm, dd, hh, SUM(read_count) AS read_count,".
434 " SUM(childs_read_count) AS childs_read_count, SUM(spent_seconds) AS spent_seconds,".
435 " SUM(childs_spent_seconds) AS childs_spent_seconds".
436 " FROM obj_stat_tmp".
437 " GROUP BY obj_id, obj_type, yyyy, mm, dd, hh";
438 $set = $ilDB->query($sql);
439 while($row = $ilDB->fetchAssoc($set))
440 {
441 // "primary key"
442 $where = array("obj_id" => array("integer", $row["obj_id"]),
443 "obj_type" => array("text", $row["obj_type"]),
444 "yyyy" => array("integer", $row["yyyy"]),
445 "mm" => array("integer", $row["mm"]),
446 "dd" => array("integer", $row["dd"]),
447 "hh" => array("integer", $row["hh"]));
448
449 $where_sql = array();
450 foreach($where as $field => $def)
451 {
452 $where_sql[] = $field." = ".$ilDB->quote($def[1], $def[0]);
453 }
454 $where_sql = implode(" AND ", $where_sql);
455
456 // existing entry?
457 $check = $ilDB->query("SELECT read_count, childs_read_count, spent_seconds,".
458 "childs_spent_seconds".
459 " FROM obj_stat".
460 " WHERE ".$where_sql);
461 if($ilDB->numRows($check))
462 {
463 $old = $ilDB->fetchAssoc($check);
464
465 // add existing values
466 $fields = array("read_count" => array("integer", $old["read_count"]+$row["read_count"]),
467 "childs_read_count" => array("integer", $old["childs_read_count"]+$row["childs_read_count"]),
468 "spent_seconds" => array("integer", $old["spent_seconds"]+$row["spent_seconds"]),
469 "childs_spent_seconds" => array("integer", $old["childs_spent_seconds"]+$row["childs_spent_seconds"]));
470
471 $ilDB->update("obj_stat", $fields, $where);
472 }
473 else
474 {
475 // new entry
476 $fields = $where;
477 $fields["read_count"] = array("integer", $row["read_count"]);
478 $fields["childs_read_count"] = array("integer", $row["childs_read_count"]);
479 $fields["spent_seconds"] = array("integer", $row["spent_seconds"]);
480 $fields["childs_spent_seconds"] = array("integer", $row["childs_spent_seconds"]);
481
482 $ilDB->insert("obj_stat", $fields);
483 }
484 }
485
486 // clean up transfer table
487 $ilDB->query("DELETE FROM obj_stat_tmp");
488
489 });
490
491 $ilAtomQuery->run();
492 }
493 }
494 }
Interface ilDBInterface.
$ret
Definition: parser.php:6

References $ilDB, $ret, and $row.

Referenced by _recordObjStats(), and ilLPObjectStatisticsGUI\adminSync().

+ Here is the caller graph for this function:

◆ _updateAccessForScormOfflinePlayer()

static ilChangeEvent::_updateAccessForScormOfflinePlayer (   $obj_id,
  $usr_id,
  $i_last_access,
  $t_first_access 
)
static

_updateAccessForScormOfflinePlayer needed to synchronize last_access and first_access when learning modul is used offline called in .

/Modules/ScormAicc/classes/class.ilSCORMOfflineMode.php

Returns
true

Definition at line 953 of file class.ilChangeEvent.php.

953 {
954 global $ilDB;
955 $res = $ilDB->queryF('UPDATE read_event SET first_access=%s, last_access = %s WHERE obj_id=%s AND usr_id=%s',
956 array('timestamp','integer','integer','integer'),
957 array($t_first_access,$i_last_access,$obj_id,$usr_id)
958 );
959 return $res;
960 }

References $ilDB, and $res.

Referenced by ilSCORMOfflineMode\scormPlayerUnloadForSop2il().

+ Here is the caller graph for this function:

◆ hasAccessed()

static ilChangeEvent::hasAccessed (   $a_obj_id,
  $a_usr_id 
)
static

Has accessed.

Definition at line 804 of file class.ilChangeEvent.php.

805 {
806 global $ilDB;
807
808 if (isset(self::$has_accessed[$a_obj_id][$a_usr_id]))
809 {
810 return self::$has_accessed[$a_obj_id][$a_usr_id];
811 }
812
813 $set = $ilDB->query("SELECT usr_id FROM read_event WHERE ".
814 "obj_id = ".$ilDB->quote($a_obj_id, "integer")." AND ".
815 "usr_id = ".$ilDB->quote($a_usr_id, "integer")
816 );
817 if ($rec = $ilDB->fetchAssoc($set))
818 {
819 return self::$has_accessed[$a_obj_id][$a_usr_id] = true;
820 }
821 return self::$has_accessed[$a_obj_id][$a_usr_id] = false;
822 }

References $ilDB.

Referenced by ilLPStatusCollection\determineStatus(), ilLPStatusExerciseReturned\determineStatus(), ilLPStatusManual\determineStatus(), ilLPStatusManualByTutor\determineStatus(), ilLPStatusObjectives\determineStatus(), ilLPStatusQuestions\determineStatus(), ilLPStatusSCORM\determineStatus(), ilLPStatusTypicalLearningTime\determineStatus(), ilLPStatusVisitedPages\determineStatus(), and ilLPStatusVisits\determineStatus().

+ Here is the caller graph for this function:

◆ lookupUsersInProgress()

static ilChangeEvent::lookupUsersInProgress (   $a_obj_id)
static

Lookup users in progress.

Returns

Definition at line 786 of file class.ilChangeEvent.php.

787 {
788 global $ilDB;
789
790 $query = sprintf('SELECT DISTINCT(usr_id) usr FROM read_event '.
791 'WHERE obj_id = %s ',
792 $ilDB->quote($a_obj_id,'integer'));
793 $res = $ilDB->query($query);
794 while($row = $ilDB->fetchObject($res))
795 {
796 $users[] = $row->usr;
797 }
798 return $users ? $users : array();
799 }

References $ilDB, $query, $res, $row, and sprintf.

Referenced by ilLPStatusQuestions\_getCompleted(), ilLPStatusCollection\_getInProgress(), ilLPStatusExerciseReturned\_getInProgress(), ilLPStatusManual\_getInProgress(), ilLPStatusManualByTutor\_getInProgress(), ilLPStatusQuestions\_getInProgress(), ilLPStatusVisitedPages\_getInProgress(), and ilLPStatusObjectives\_getStatusInfo().

+ Here is the caller graph for this function:

Field Documentation

◆ $has_accessed

ilChangeEvent::$has_accessed = array()
staticprivate

Definition at line 38 of file class.ilChangeEvent.php.


The documentation for this class was generated from the following file: