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.

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

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

800  {
801  if (ilChangeEvent::_isActive()) {
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  }
foreach($_POST as $key=> $value) $res
$query
global $ilSetting
Definition: privfeed.php:17
static _isActive()
Returns true, if change event tracking is active.
global $ilDB
+ 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.

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

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

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  }
static now()
Return current timestamp in Y-m-d H:i:s format.
foreach($_POST as $key=> $value) $res
$query
Create styles array
The data for the language used.
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
global $ilDB
+ 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.

References $ilSetting.

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

849  {
850  global $ilSetting;
851  $ilSetting->set('enable_change_event_tracking', '0');
852  }
global $ilSetting
Definition: privfeed.php:17
+ 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.

References $ilDB, and $query.

Referenced by ilObjectLP\handleDelete().

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  }
$query
global $ilDB
+ 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.

References $ilDB.

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

◆ _deleteReadEventsForUsers()

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

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

References $ilDB.

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

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  }
global $ilDB
+ 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.

References $ilDB, $res, $row, and array.

Referenced by ilObjectLP\gatherLPUsers().

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  }
foreach($_POST as $key=> $value) $res
Create styles array
The data for the language used.
global $ilDB
+ 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.

References $ilSetting.

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

860  {
861  global $ilSetting;
862  return $ilSetting->get('enable_change_event_tracking', '0') == '1';
863  }
global $ilSetting
Definition: privfeed.php:17
+ 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.

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

Referenced by ilTrackingTest\testChangeEvent().

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
foreach($_POST as $key=> $value) $res
$query
global $ilDB
+ 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.

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

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

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
foreach($_POST as $key=> $value) $res
$query
Create styles array
The data for the language used.
global $ilDB
+ 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.

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

Referenced by ilTrackingTest\testChangeEvent().

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  }
$r
Definition: example_031.php:79
foreach($_POST as $key=> $value) $res
$query
Create styles array
The data for the language used.
global $ilDB
+ 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.

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

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) {
353  self::_syncObjectStats($now);
354  }
355  }
static _enabledObjectStatistics()
check wether object statistics is enabled or not
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
Create styles array
The data for the language used.
static _lookupType($a_id, $a_reference=false)
lookup object type
global $ilDB
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
+ Here is the call 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.

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

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().

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 _catchupWriteEvents($obj_id, $usr_id, $timestamp=null)
Catches up with all write events which occured before the specified timestamp.
$time
Definition: cron.php:21
$a_type
Definition: workflow.php:92
foreach($_POST as $key=> $value) $res
static _lookupObjId($a_id)
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
$query
Create styles array
The data for the language used.
static _lookupType($a_id, $a_reference=false)
lookup object type
global $ilDB
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
+ 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.

References $action, $ilDB, and $query.

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(), ilObjRootFolderGUI\updateObject(), ilObjGroupGUI\updateObject(), ilObjCourseGUI\updateObject(), and ilObjCategoryGUI\updateObject().

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");
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  }
$action
$query
global $ilDB
+ 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.

References $def, $ilDB, $old, $ret, $row, array, ilDBInterface\buildAtomQuery(), ilDBInterface\fetchAssoc(), ilDBInterface\insert(), ilDBInterface\numRows(), ilDBInterface\query(), ilDBInterface\quote(), time, and ilDBInterface\update().

Referenced by ilLPObjectStatisticsGUI\adminSync().

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  }
update($table_name, $values, $where)
numRows($query_result)
Interface ilDBInterface.
quote($value, $type)
$old
Create styles array
The data for the language used.
global $ilDB
$ret
Definition: parser.php:6
query($query)
Run a (read-only) Query on the database.
insert($table_name, $values)
fetchAssoc($query_result)
$def
Definition: croninfo.php:21
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
+ Here is the call graph for this function:
+ 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.

References $ilDB, $res, and array.

Referenced by ilSCORMOfflineMode\scormPlayerUnloadForSop2il().

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  }
foreach($_POST as $key=> $value) $res
Create styles array
The data for the language used.
global $ilDB
+ 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.

References $ilDB.

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

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  }
global $ilDB
+ 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.

References $ilDB, $query, $res, $row, $users, and array.

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

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  }
foreach($_POST as $key=> $value) $res
$query
Create styles array
The data for the language used.
$users
Definition: authpage.php:44
global $ilDB
+ 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: