ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 799 of file class.ilChangeEvent.php.

800 {
802 return 'change event tracking is already active';
803 } else {
804 global $ilDB;
805
806 // Insert initial data into table write_event
807 // We need to do this here, because we need
808 // to catch up write events that occured while the change event tracking was
809 // deactivated.
810
811 // IGNORE isn't supported in oracle
812 $set = $ilDB->query(sprintf(
813 'SELECT r1.obj_id,r2.obj_id p,d.owner,%s,d.create_date ' .
814 'FROM object_data d ' .
815 'LEFT JOIN write_event w ON d.obj_id = w.obj_id ' .
816 'JOIN object_reference r1 ON d.obj_id=r1.obj_id ' .
817 'JOIN tree t ON t.child=r1.ref_id ' .
818 'JOIN object_reference r2 on r2.ref_id=t.parent ' .
819 'WHERE w.obj_id IS NULL',
820 $ilDB->quote('create', 'text')
821 ));
822 while ($rec = $ilDB->fetchAssoc($set)) {
823 $nid = $ilDB->nextId("write_event");
824 $query = 'INSERT INTO write_event ' .
825 '(write_id, obj_id,parent_obj_id,usr_id,action,ts) VALUES (' .
826 $ilDB->quote($nid, "integer") . "," .
827 $ilDB->quote($rec["obj_id"], "integer") . "," .
828 $ilDB->quote($rec["p"], "integer") . "," .
829 $ilDB->quote($rec["owner"], "integer") . "," .
830 $ilDB->quote("create", "text") . "," .
831 $ilDB->quote($rec["create_date"], "timestamp") .
832 ')';
833 $res = $ilDB->query($query);
834 }
835
836 global $ilSetting;
837 $ilSetting->set('enable_change_event_tracking', '1');
838
839 return $res;
840 }
841 }
sprintf('%.4f', $callTime)
static _isActive()
Returns true, if change event tracking is active.
global $ilSetting
Definition: privfeed.php:17
$query
foreach($_POST as $key=> $value) $res
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 479 of file class.ilChangeEvent.php.

480 {
481 global $ilDB;
482
483 $query = "SELECT obj_id FROM catch_write_events " .
484 "WHERE obj_id = " . $ilDB->quote($obj_id, 'integer') . " " .
485 "AND usr_id = " . $ilDB->quote($usr_id, 'integer');
486 $res = $ilDB->query($query);
487 if ($res->numRows()) {
488 $ts = ($timestamp == null)
489 ? ilUtil::now()
490 : $timestamp;
491 /* $query = "UPDATE catch_write_events ".
492 "SET ts = ".($timestamp == null ? $ilDB->now() : $ilDB->quote($timestamp, 'timestamp'))." ".
493 "WHERE usr_id = ".$ilDB->quote($usr_id ,'integer')." ".
494 "AND obj_id = ".$ilDB->quote($obj_id ,'integer');
495 $res = $ilDB->manipulate($query);*/
496 } else {
497 $ts = ilUtil::now();
498 /* $query = "INSERT INTO catch_write_events (ts,obj_id,usr_id) ".
499 "VALUES( ".
500 $ilDB->now().", ".
501 $ilDB->quote($obj_id,'integer').", ".
502 $ilDB->quote($usr_id,'integer')." ".
503 ")";
504 $res = $ilDB->manipulate($query);*/
505 }
506
507 // alex, use replace due to bug #10406
508 $ilDB->replace(
509 "catch_write_events",
510 array(
511 "obj_id" => array("integer", $obj_id),
512 "usr_id" => array("integer", $usr_id)
513 ),
514 array(
515 "ts" => array("timestamp", $ts))
516 );
517 }
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 848 of file class.ilChangeEvent.php.

849 {
850 global $ilSetting;
851 $ilSetting->set('enable_change_event_tracking', '0');
852 }

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 871 of file class.ilChangeEvent.php.

872 {
873 global $ilDB;
874
875 $query = sprintf(
876 'DELETE FROM write_event WHERE obj_id = %s ',
877 $ilDB->quote($a_obj_id, 'integer')
878 );
879 $aff = $ilDB->manipulate($query);
880
881 $query = sprintf(
882 'DELETE FROM read_event WHERE obj_id = %s ',
883 $ilDB->quote($a_obj_id, 'integer')
884 );
885 $aff = $ilDB->manipulate($query);
886 return true;
887 }

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 889 of file class.ilChangeEvent.php.

890 {
891 global $ilDB;
892
893 $ilDB->manipulate("DELETE FROM read_event" .
894 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer"));
895 }

References $ilDB.

◆ _deleteReadEventsForUsers()

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

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

898 {
899 global $ilDB;
900
901 $ilDB->manipulate("DELETE FROM read_event" .
902 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") .
903 " AND " . $ilDB->in("usr_id", $a_user_ids, "", "integer"));
904 }

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 906 of file class.ilChangeEvent.php.

907 {
908 global $ilDB;
909
910 $res = array();
911
912 $set = $ilDB->query("SELECT usr_id FROM read_event" .
913 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer"));
914 while ($row = $ilDB->fetchAssoc($set)) {
915 $res[] = $row["usr_id"];
916 }
917
918 return $res;
919 }

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 859 of file class.ilChangeEvent.php.

860 {
861 global $ilSetting;
862 return $ilSetting->get('enable_change_event_tracking', '0') == '1';
863 }

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 619 of file class.ilChangeEvent.php.

620 {
621 global $ilDB;
622
623 $q = "SELECT ts " .
624 "FROM catch_write_events " .
625 "WHERE obj_id=" . $ilDB->quote($obj_id, 'integer') . " " .
626 "AND usr_id=" . $ilDB->quote($usr_id, 'integer');
627 $r = $ilDB->query($q);
628 $catchup = null;
629 while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
630 $catchup = $row['ts'];
631 }
632
633 if ($catchup == null) {
634 $ilDB->setLimit(1);
635 $query = sprintf(
636 'SELECT * FROM write_event ' .
637 'WHERE obj_id = %s ' .
638 'AND usr_id <> %s ',
639 $ilDB->quote($obj_id, 'integer'),
640 $ilDB->quote($usr_id, 'integer')
641 );
642 $res = $ilDB->query($query);
643 } else {
644 $ilDB->setLimit(1);
645 $query = sprintf(
646 'SELECT * FROM write_event ' .
647 'WHERE obj_id = %s ' .
648 'AND usr_id <> %s ' .
649 'AND ts > %s ',
650 $ilDB->quote($obj_id, 'integer'),
651 $ilDB->quote($usr_id, 'integer'),
652 $ilDB->quote($catchup, 'timestamp')
653 );
654 $res = $ilDB->query($query);
655 }
656
657 $numRows = $res->numRows();
658 if ($numRows > 0) {
659 $row = $ilDB->fetchAssoc($res);
660 // if we have write events, and user never catched one, report as new (1)
661 // if we have write events, and user catched an old write event, report as changed (2)
662 return ($catchup == null) ? 1 : 2;
663 } else {
664 return 0; // user catched all write events, report as unchanged (0)
665 }
666 }
$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 712 of file class.ilChangeEvent.php.

713 {
714 global $ilDB;
715
716 if ($usr_id == null) {
717 $query = sprintf(
718 'SELECT * FROM read_event ' .
719 'WHERE obj_id = %s ' .
720 'ORDER BY last_access DESC',
721 $ilDB->quote($obj_id, 'integer')
722 );
723 $res = $ilDB->query($query);
724 } else {
725 $query = sprintf(
726 'SELECT * FROM read_event ' .
727 'WHERE obj_id = %s ' .
728 'AND usr_id = %s ' .
729 'ORDER BY last_access DESC',
730 $ilDB->quote($obj_id, 'integer'),
731 $ilDB->quote($usr_id, 'integer')
732 );
733 $res = $ilDB->query($query);
734 }
735
736 $counter = 0;
737 while ($row = $ilDB->fetchAssoc($res)) {
738 $events[$counter]['obj_id'] = $row['obj_id'];
739 $events[$counter]['usr_id'] = $row['usr_id'];
740 $events[$counter]['last_access'] = $row['last_access'];
741 $events[$counter]['read_count'] = $row['read_count'];
742 $events[$counter]['spent_seconds'] = $row['spent_seconds'];
743 $events[$counter]['first_access'] = $row['first_access'];
744
745 $counter++;
746 }
747 return $events ? $events : array();
748 }
$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 566 of file class.ilChangeEvent.php.

567 {
568 global $ilDB;
569
570 $q = "SELECT ts " .
571 "FROM catch_write_events " .
572 "WHERE obj_id=" . $ilDB->quote($obj_id, 'integer') . " " .
573 "AND usr_id=" . $ilDB->quote($usr_id, 'integer');
574 $r = $ilDB->query($q);
575 $catchup = null;
576 while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
577 $catchup = $row['ts'];
578 }
579
580 if ($catchup == null) {
581 $query = sprintf(
582 'SELECT * FROM write_event ' .
583 'WHERE obj_id = %s ' .
584 'AND usr_id <> %s ' .
585 'ORDER BY ts DESC',
586 $ilDB->quote($obj_id, 'integer'),
587 $ilDB->quote($usr_id, 'integer')
588 );
589 $res = $ilDB->query($query);
590 } else {
591 $query = sprintf(
592 'SELECT * FROM write_event ' .
593 'WHERE obj_id = %s ' .
594 'AND usr_id <> %s ' .
595 'AND ts >= %s ' .
596 'ORDER BY ts DESC',
597 $ilDB->quote($obj_id, 'integer'),
598 $ilDB->quote($usr_id, 'integer'),
599 $ilDB->quote($catchup, 'timestamp')
600 );
601 $res = $ilDB->query($query);
602 }
603 $events = array();
604 while ($row = $ilDB->fetchAssoc($res)) {
605 $events[] = $row;
606 }
607 return $events;
608 }

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 317 of file class.ilChangeEvent.php.

318 {
319 global $ilDB;
320
322 (int) $a_obj_id <= 0) { // #12706
323 return;
324 }
325
326 $now = time();
327
328 $fields = array();
329 $fields['log_id'] = array("integer", $ilDB->nextId('obj_stat_log'));
330 $fields["obj_id"] = array("integer", $a_obj_id);
331 $fields["obj_type"] = array("text", ilObject::_lookupType($a_obj_id));
332 $fields["tstamp"] = array("timestamp", $now);
333 $fields["yyyy"] = array("integer", date("Y"));
334 $fields["mm"] = array("integer", date("m"));
335 $fields["dd"] = array("integer", date("d"));
336 $fields["hh"] = array("integer", date("H"));
337 if ($a_spent_seconds > 0) {
338 $fields["spent_seconds"] = array("integer", $a_spent_seconds);
339 }
340 if ($a_read_count > 0) {
341 $fields["read_count"] = array("integer", $a_read_count);
342 }
343 if ($a_childs_spent_seconds > 0) {
344 $fields["childs_spent_seconds"] = array("integer", $a_childs_spent_seconds);
345 }
346 if ($a_child_read_count > 0) {
347 $fields["childs_read_count"] = array("integer", $a_child_read_count);
348 }
349 $ilDB->insert("obj_stat_log", $fields);
350
351 // 0.01% probability
352 if (mt_rand(1, 100) == 1) {
354 }
355 }
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 111 of file class.ilChangeEvent.php.

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

References $a_type, $ilDB, $path, $query, $res, $row, $time, _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(), ilSurveyExecutionGUI\executeCommand(), 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 $pset = $ilDB->query('SELECT r2.obj_id par_obj_id FROM object_reference r1 ' .
68 'JOIN tree t ON t.child = r1.ref_id ' .
69 'JOIN object_reference r2 ON r2.ref_id = t.parent ' .
70 'WHERE r1.obj_id = ' . $ilDB->quote($obj_id, 'integer'));
71
72 while ($prec = $ilDB->fetchAssoc($pset)) {
73 $nid = $ilDB->nextId("write_event");
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");
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 }
$action

References $action, $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 363 of file class.ilChangeEvent.php.

364 {
365 global $ilDB;
366
367 if (!$a_now) {
368 $a_now = time();
369 }
370
371 set_time_limit(0);
372
373 // has source table enough entries?
374 $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
375 $row = $ilDB->fetchAssoc($set);
376 if ($row["counter"] >= $a_minimum) {
377 $ilAtomQuery = $ilDB->buildAtomQuery();
378 $ilAtomQuery->addTableLock('obj_stat_log');
379 $ilAtomQuery->addTableLock('obj_stat_tmp');
380
381 $ilAtomQuery->addQueryCallable(function (ilDBInterface $ilDB) use ($a_now, $a_minimum, &$ret) {
382
383 // if other process was transferring, we had to wait for the lock and
384 // the source table should now have less than minimum/needed entries
385 $set = $ilDB->query("SELECT COUNT(*) AS counter FROM obj_stat_log");
386 $row = $ilDB->fetchAssoc($set);
387 if ($row["counter"] >= $a_minimum) {
388 // use only "full" seconds to have a clear cut
389 $ilDB->query("INSERT INTO obj_stat_tmp" .
390 " SELECT * FROM obj_stat_log" .
391 " WHERE tstamp < " . $ilDB->quote($a_now, "timestamp"));
392
393 // remove transferred entries from source table
394 $ilDB->query("DELETE FROM obj_stat_log" .
395 " WHERE tstamp < " . $ilDB->quote($a_now, "timestamp"));
396
397 $ret = true;
398 } else {
399 $ret = false;
400 }
401 });
402
403 $ilAtomQuery->run();
404
405 //continue only if obj_stat_log counter >= $a_minimum
406 if ($ret) {
407 $ilAtomQuery = $ilDB->buildAtomQuery();
408 $ilAtomQuery->addTableLock('obj_stat_tmp');
409 $ilAtomQuery->addTableLock('obj_stat');
410
411 $ilAtomQuery->addQueryCallable(function (ilDBInterface $ilDB) use ($a_now, $a_minimum) {
412
413 // process log data (timestamp is not needed anymore)
414 $sql = "SELECT obj_id, obj_type, yyyy, mm, dd, hh, SUM(read_count) AS read_count," .
415 " SUM(childs_read_count) AS childs_read_count, SUM(spent_seconds) AS spent_seconds," .
416 " SUM(childs_spent_seconds) AS childs_spent_seconds" .
417 " FROM obj_stat_tmp" .
418 " GROUP BY obj_id, obj_type, yyyy, mm, dd, hh";
419 $set = $ilDB->query($sql);
420 while ($row = $ilDB->fetchAssoc($set)) {
421 // "primary key"
422 $where = array("obj_id" => array("integer", $row["obj_id"]),
423 "obj_type" => array("text", $row["obj_type"]),
424 "yyyy" => array("integer", $row["yyyy"]),
425 "mm" => array("integer", $row["mm"]),
426 "dd" => array("integer", $row["dd"]),
427 "hh" => array("integer", $row["hh"]));
428
429 $where_sql = array();
430 foreach ($where as $field => $def) {
431 $where_sql[] = $field . " = " . $ilDB->quote($def[1], $def[0]);
432 }
433 $where_sql = implode(" AND ", $where_sql);
434
435 // existing entry?
436 $check = $ilDB->query("SELECT read_count, childs_read_count, spent_seconds," .
437 "childs_spent_seconds" .
438 " FROM obj_stat" .
439 " WHERE " . $where_sql);
440 if ($ilDB->numRows($check)) {
441 $old = $ilDB->fetchAssoc($check);
442
443 // add existing values
444 $fields = array("read_count" => array("integer", $old["read_count"]+$row["read_count"]),
445 "childs_read_count" => array("integer", $old["childs_read_count"]+$row["childs_read_count"]),
446 "spent_seconds" => array("integer", $old["spent_seconds"]+$row["spent_seconds"]),
447 "childs_spent_seconds" => array("integer", $old["childs_spent_seconds"]+$row["childs_spent_seconds"]));
448
449 $ilDB->update("obj_stat", $fields, $where);
450 } else {
451 // new entry
452 $fields = $where;
453 $fields["read_count"] = array("integer", $row["read_count"]);
454 $fields["childs_read_count"] = array("integer", $row["childs_read_count"]);
455 $fields["spent_seconds"] = array("integer", $row["spent_seconds"]);
456 $fields["childs_spent_seconds"] = array("integer", $row["childs_spent_seconds"]);
457
458 $ilDB->insert("obj_stat", $fields);
459 }
460 }
461
462 // clean up transfer table
463 $ilDB->query("DELETE FROM obj_stat_tmp");
464 });
465
466 $ilAtomQuery->run();
467 }
468 }
469 }
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 927 of file class.ilChangeEvent.php.

928 {
929 global $ilDB;
930 $res = $ilDB->queryF(
931 'UPDATE read_event SET first_access=%s, last_access = %s WHERE obj_id=%s AND usr_id=%s',
932 array('timestamp','integer','integer','integer'),
933 array($t_first_access,$i_last_access,$obj_id,$usr_id)
934 );
935 return $res;
936 }

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 775 of file class.ilChangeEvent.php.

776 {
777 global $ilDB;
778
779 if (isset(self::$has_accessed[$a_obj_id][$a_usr_id])) {
780 return self::$has_accessed[$a_obj_id][$a_usr_id];
781 }
782
783 $set = $ilDB->query(
784 "SELECT usr_id FROM read_event WHERE " .
785 "obj_id = " . $ilDB->quote($a_obj_id, "integer") . " AND " .
786 "usr_id = " . $ilDB->quote($a_usr_id, "integer")
787 );
788 if ($rec = $ilDB->fetchAssoc($set)) {
789 return self::$has_accessed[$a_obj_id][$a_usr_id] = true;
790 }
791 return self::$has_accessed[$a_obj_id][$a_usr_id] = false;
792 }

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 756 of file class.ilChangeEvent.php.

757 {
758 global $ilDB;
759
760 $query = sprintf(
761 'SELECT DISTINCT(usr_id) usr FROM read_event ' .
762 'WHERE obj_id = %s ',
763 $ilDB->quote($a_obj_id, 'integer')
764 );
765 $res = $ilDB->query($query);
766 while ($row = $ilDB->fetchObject($res)) {
767 $users[] = $row->usr;
768 }
769 return $users ? $users : array();
770 }
$users
Definition: authpage.php:44

References $ilDB, $query, $res, $row, $users, 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: