ILIAS  trunk Revision v11.0_alpha-1866-gfa368f7776e
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
ilChangeEvent Class Reference

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

+ Collaboration diagram for ilChangeEvent:

Static Public Member Functions

static _recordWriteEvent (int $obj_id, int $usr_id, string $action, ?int $parent_obj_id=null)
 Records a write event. More...
 
static _recordReadEvent (string $a_type, int $a_ref_id, int $obj_id, int $usr_id, bool $isCatchupWriteEvents=true, $a_ext_rc=null, $a_ext_time=null)
 
static _recordObjStats (int $a_obj_id, ?int $a_spent_seconds, ?int $a_read_count, ?int $a_childs_spent_seconds=null, ?int $a_child_read_count=null)
 
static _syncObjectStats (?int $a_now=null, int $a_minimum=20000)
 
static _catchupWriteEvents (int $obj_id, int $usr_id, ?string $timestamp=null)
 Catches up with all write events which occured before the specified timestamp. More...
 
static _lookupUncaughtWriteEvents (int $obj_id, int $usr_id)
 Reads all write events which occured on the object which happened after the last time the user caught up with them. More...
 
static _lookupChangeState (int $obj_id, int $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. More...
 
static lookupUsersInProgress (int $a_obj_id)
 
static hasAccessed (int $a_obj_id, int $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 (int $a_obj_id)
 Delete object entries. More...
 
static _deleteReadEvents (int $a_obj_id)
 
static _deleteReadEventsForUsers (int $a_obj_id, array $a_user_ids)
 
static _getAllUserIds (int $a_obj_id)
 
static _updateAccessForScormOfflinePlayer (int $obj_id, int $usr_id, int $i_last_access, string $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 array $has_accessed = []
 

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

Member Function Documentation

◆ _activate()

static ilChangeEvent::_activate ( )
static

Activates change event tracking.

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

References $DIC, $ilDB, $ilSetting, $res, _isActive(), and null.

Referenced by ilObjRepositorySettingsGUI\saveSettings().

675  : bool
676  {
677  if (ilChangeEvent::_isActive()) {
678  return false;
679  } else {
680  global $DIC;
681 
682  $ilDB = $DIC['ilDB'];
683 
684  // Insert initial data into table write_event
685  // We need to do this here, because we need
686  // to catch up write events that occured while the change event tracking was
687  // deactivated.
688 
689  // IGNORE isn't supported in oracle
690  $set = $ilDB->query(
691  sprintf(
692  'SELECT r1.obj_id,r2.obj_id p,d.owner,%s,d.create_date ' .
693  'FROM object_data d ' .
694  'LEFT JOIN write_event w ON d.obj_id = w.obj_id ' .
695  'JOIN object_reference r1 ON d.obj_id=r1.obj_id ' .
696  'JOIN tree t ON t.child=r1.ref_id ' .
697  'JOIN object_reference r2 on r2.ref_id=t.parent ' .
698  'WHERE w.obj_id IS NULL',
699  $ilDB->quote('create', 'text')
700  )
701  );
702  $res = null;
703  while ($rec = $ilDB->fetchAssoc($set)) {
704  $nid = $ilDB->nextId("write_event");
705  $query = 'INSERT INTO write_event ' .
706  '(write_id, obj_id,parent_obj_id,usr_id,action,ts) VALUES (' .
707  $ilDB->quote($nid, "integer") . "," .
708  $ilDB->quote($rec["obj_id"], "integer") . "," .
709  $ilDB->quote($rec["p"], "integer") . "," .
710  $ilDB->quote($rec["owner"], "integer") . "," .
711  $ilDB->quote("create", "text") . "," .
712  $ilDB->quote($rec["create_date"], "timestamp") .
713  ')';
714  $res = $ilDB->query($query);
715  }
716 
717  global $DIC;
718 
719  $ilSetting = $DIC['ilSetting'];
720  $ilSetting->set('enable_change_event_tracking', '1');
721 
722  return $res !== null;
723  }
724  }
$res
Definition: ltiservices.php:66
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
global $DIC
Definition: shib_login.php:22
global $ilSetting
Definition: privfeed.php:31
static _isActive()
Returns true, if change event tracking is active.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _catchupWriteEvents()

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

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

Parameters
$obj_idint The object.
$usr_idint The user.
$timestampstring|null timestamp.
Returns
void

This method was only used to write to catch_write_events, but the methods reading out that table are not used anywhere.

Deprecated:
, will be removed with ILIAS 11

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

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

544  : void {
545  }
+ Here is the caller graph for this function:

◆ _deactivate()

static ilChangeEvent::_deactivate ( )
static

Deactivates change event tracking.

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

References $DIC, and $ilSetting.

Referenced by ilObjRepositorySettingsGUI\saveSettings().

729  : bool
730  {
731  global $DIC;
732 
733  $ilSetting = $DIC['ilSetting'];
734  $ilSetting->set('enable_change_event_tracking', '0');
735  return true;
736  }
global $DIC
Definition: shib_login.php:22
global $ilSetting
Definition: privfeed.php:31
+ Here is the caller graph for this function:

◆ _delete()

static ilChangeEvent::_delete ( int  $a_obj_id)
static

Delete object entries.

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

References $DIC, and $ilDB.

Referenced by ilObjectLP\handleDelete().

752  : bool
753  {
754  global $DIC;
755 
756  $ilDB = $DIC['ilDB'];
757  $query = sprintf(
758  'DELETE FROM write_event WHERE obj_id = %s ',
759  $ilDB->quote($a_obj_id, 'integer')
760  );
761  $aff = $ilDB->manipulate($query);
762 
763  $query = sprintf(
764  'DELETE FROM read_event WHERE obj_id = %s ',
765  $ilDB->quote($a_obj_id, 'integer')
766  );
767  $aff = $ilDB->manipulate($query);
768  return true;
769  }
global $DIC
Definition: shib_login.php:22
+ Here is the caller graph for this function:

◆ _deleteReadEvents()

static ilChangeEvent::_deleteReadEvents ( int  $a_obj_id)
static

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

References $DIC, and $ilDB.

771  : void
772  {
773  global $DIC;
774 
775  $ilDB = $DIC['ilDB'];
776 
777  $ilDB->manipulate(
778  "DELETE FROM read_event" .
779  " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer")
780  );
781  }
global $DIC
Definition: shib_login.php:22

◆ _deleteReadEventsForUsers()

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

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

References $DIC, and $ilDB.

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

786  : void {
787  global $DIC;
788 
789  $ilDB = $DIC['ilDB'];
790 
791  $ilDB->manipulate(
792  "DELETE FROM read_event" .
793  " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") .
794  " AND " . $ilDB->in("usr_id", $a_user_ids, "", "integer")
795  );
796  }
global $DIC
Definition: shib_login.php:22
+ Here is the caller graph for this function:

◆ _getAllUserIds()

static ilChangeEvent::_getAllUserIds ( int  $a_obj_id)
static

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

References $DIC, $ilDB, $res, and ILIAS\Repository\int().

Referenced by ilObjectLP\gatherLPUsers().

798  : array
799  {
800  global $DIC;
801 
802  $ilDB = $DIC['ilDB'];
803  $res = array();
804  $set = $ilDB->query(
805  "SELECT usr_id FROM read_event" .
806  " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer")
807  );
808  while ($row = $ilDB->fetchAssoc($set)) {
809  $res[] = (int) $row["usr_id"];
810  }
811  return $res;
812  }
$res
Definition: ltiservices.php:66
global $DIC
Definition: shib_login.php:22
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _isActive()

static ilChangeEvent::_isActive ( )
static

Returns true, if change event tracking is active.

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

References $DIC, and $ilSetting.

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

741  : bool
742  {
743  global $DIC;
744 
745  $ilSetting = $DIC['ilSetting'];
746  return $ilSetting->get('enable_change_event_tracking', '0') == '1';
747  }
global $DIC
Definition: shib_login.php:22
global $ilSetting
Definition: privfeed.php:31
+ Here is the caller graph for this function:

◆ _lookupChangeState()

static ilChangeEvent::_lookupChangeState ( int  $obj_id,
int  $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
int 0 = object is unchanged, 1 = object is new, 2 = object has changed

This method is unused, so the table it read from was removed for performance reasons.

Deprecated:
, will be removed with ILIAS 11

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

578  : int
579  {
580  return 0;
581  }

◆ _lookupReadEvents()

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

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

References $DIC, $ilDB, $res, and null.

Referenced by ilLPStatusContentVisited\_getCompleted(), ilLPStatusVisits\_getCompleted(), ilLPStatusTypicalLearningTime\_getCompleted(), ilLPStatusVisits\_getInProgress(), ilLPStatusTypicalLearningTime\_getInProgress(), ilLearningProgress\_getProgress(), ilLearningProgress\_lookupProgressByObjId(), ilInfoScreenGUI\buildPublicAccessExportButton(), ilLPStatusVisits\determinePercentage(), ilLPStatusTypicalLearningTime\determinePercentage(), ilLPStatusVisits\determineStatus(), ilLPStatusTypicalLearningTime\determineStatus(), ilObjSCORMLearningModule\importSuccessForSahsUser(), and ILIAS\MetaData\Vocabularies\Dispatch\Presentation\Presentation\VideoViewGUI\renderSideColumn().

589  {
590  global $DIC;
591 
592  $ilDB = $DIC['ilDB'];
593 
594  if ($usr_id == null) {
595  $query = sprintf(
596  'SELECT * FROM read_event ' .
597  'WHERE obj_id = %s ' .
598  'ORDER BY last_access DESC',
599  $ilDB->quote($obj_id, 'integer')
600  );
601  $res = $ilDB->query($query);
602  } else {
603  $query = sprintf(
604  'SELECT * FROM read_event ' .
605  'WHERE obj_id = %s ' .
606  'AND usr_id = %s ' .
607  'ORDER BY last_access DESC',
608  $ilDB->quote($obj_id, 'integer'),
609  $ilDB->quote($usr_id, 'integer')
610  );
611  $res = $ilDB->query($query);
612  }
613 
614  $counter = 0;
615  $events = [];
616  while ($row = $ilDB->fetchAssoc($res)) {
617  $events[$counter]['obj_id'] = $row['obj_id'];
618  $events[$counter]['usr_id'] = $row['usr_id'];
619  $events[$counter]['last_access'] = $row['last_access'];
620  $events[$counter]['read_count'] = $row['read_count'];
621  $events[$counter]['spent_seconds'] = $row['spent_seconds'];
622  $events[$counter]['first_access'] = $row['first_access'];
623 
624  $counter++;
625  }
626  return $events;
627  }
$res
Definition: ltiservices.php:66
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
global $DIC
Definition: shib_login.php:22
+ Here is the caller graph for this function:

◆ _lookupUncaughtWriteEvents()

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

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

This method is unused, so the table it read from was removed for performance reasons.

Deprecated:
, will be removed with ILIAS 11

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

561  : array {
562  return [];
563  }

◆ _recordObjStats()

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

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

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

328  : void {
329  global $DIC;
330 
331  $ilDB = $DIC['ilDB'];
332 
334  $a_obj_id <= 0) { // #12706
335  return;
336  }
337 
338  $now = time();
339 
340  $fields = array();
341  $fields['log_id'] = array("integer", $ilDB->nextId('obj_stat_log'));
342  $fields["obj_id"] = array("integer", $a_obj_id);
343  $fields["obj_type"] = array("text", ilObject::_lookupType($a_obj_id));
344  $fields["tstamp"] = array("timestamp", $now);
345  $fields["yyyy"] = array("integer", date("Y"));
346  $fields["mm"] = array("integer", date("m"));
347  $fields["dd"] = array("integer", date("d"));
348  $fields["hh"] = array("integer", date("H"));
349  if ($a_spent_seconds > 0) {
350  $fields["spent_seconds"] = array("integer", $a_spent_seconds);
351  }
352  if ($a_read_count > 0) {
353  $fields["read_count"] = array("integer", $a_read_count);
354  }
355  if ($a_childs_spent_seconds > 0) {
356  $fields["childs_spent_seconds"] = array("integer",
357  $a_childs_spent_seconds
358  );
359  }
360  if ($a_child_read_count > 0) {
361  $fields["childs_read_count"] = array("integer",
362  $a_child_read_count
363  );
364  }
365  $ilDB->insert("obj_stat_log", $fields);
366 
367  // 0.01% probability
368  if (mt_rand(1, 100) == 1) {
369  self::_syncObjectStats($now);
370  }
371  }
global $DIC
Definition: shib_login.php:22
static _lookupType(int $id, bool $reference=false)
+ Here is the call graph for this function:

◆ _recordReadEvent()

static ilChangeEvent::_recordReadEvent ( string  $a_type,
int  $a_ref_id,
int  $obj_id,
int  $usr_id,
bool  $isCatchupWriteEvents = true,
  $a_ext_rc = null,
  $a_ext_time = null 
)
static

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

References $DIC, $ilDB, $path, $res, _catchupWriteEvents(), ilObjUserTracking\_getValidTimeSpan(), ilObject\_lookupObjId(), ilObject\_lookupType(), ILIAS\Repository\int(), and null.

Referenced by ilSCORM2004Tracking\_syncReadEvent(), ilObjSCORMTracking\_syncReadEvent(), ilLearningProgress\_tracProgress(), ilRemoteObjectBaseGUI\callObject(), ilSurveyExecutionGUI\executeCommand(), ilObjForumGUI\getContent(), ilObjSCORMLearningModule\importSuccessForSahsUser(), ilWikiPageGUI\increaseViewCount(), ilContainerGUI\performPasteIntoMultipleObjectsObject(), ilObjIndividualAssessmentGUI\recordIndividualAssessmentRead(), ilObjLearningSequenceGUI\recordLearningSequenceRead(), ilObjLinkResourceGUI\redirectToLink(), ilObjPortfolioBaseGUI\renderFullscreenHeader(), ilObjBlogGUI\renderFullscreenHeader(), ilObjCategoryGUI\renderObject(), ILIAS\MediaObjects\Tracking\TrackingManager\saveCompletion(), ilObjFileGUI\sendFile(), ilContainerContentGUI\setOutput(), ilObjMediaCastGUI\showContentObject(), ilObjSessionGUI\showJoinRequestButton(), ilObjSCORMTracking\syncGlobalStatus(), ilLMTracker\trackAccess(), ilObjCmiXapiGUI\trackObjectReadEvent(), ilObjLTIConsumerGUI\trackObjectReadEvent(), ilObjTestGUI\trackTestObjectReadEvent(), ilObjectGUI\viewObject(), and ilObjForumGUI\viewThreadObject().

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

◆ _recordWriteEvent()

static ilChangeEvent::_recordWriteEvent ( int  $obj_id,
int  $usr_id,
string  $action,
?int  $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
int$obj_idThe object which was written to.
int$usr_idThe user who performed a write action.
string$actionThe name of the write action. 'create', 'update', 'delete', 'add', 'remove', 'undelete'.
int | null$parent_obj_idThe 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.
Returns
void

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

References $DIC, $ilDB, and null.

Referenced by ilObjCourseGUI\afterSave(), ILIAS\Repository\Deletion\EventStandardAdapter\beforeSubtreeRemoval(), ilContainerGUI\pasteObject(), ilContainerGUI\performPasteIntoMultipleObjectsObject(), ilObjFileGUI\putObjectInTree(), ilObject2GUI\putObjectInTree(), ilObjectGUI\putObjectInTree(), ilRepUtil\removeObjectsFromSystem(), ilRepUtil\restoreObjects(), ilObjRootFolderGUI\updateObject(), ilObjGroupGUI\updateObject(), ilObjCourseGUI\updateObject(), and ilObjCategoryGUI\updateObject().

66  : void {
67  global $DIC;
68 
69  $ilDB = $DIC['ilDB'];
70 
71  /* see _recordReadEvent
72  if (!ilChangeEvent::_isActive())
73  {
74  return;
75  }
76  */
77 
78  if ($parent_obj_id == null) {
79  $pset = $ilDB->query(
80  'SELECT r2.obj_id par_obj_id FROM object_reference r1 ' .
81  'JOIN tree t ON t.child = r1.ref_id ' .
82  'JOIN object_reference r2 ON r2.ref_id = t.parent ' .
83  'WHERE r1.obj_id = ' . $ilDB->quote($obj_id, 'integer')
84  );
85 
86  while ($prec = $ilDB->fetchAssoc($pset)) {
87  $nid = $ilDB->nextId("write_event");
88  $query = sprintf(
89  'INSERT INTO write_event ' .
90  '(write_id, obj_id, parent_obj_id, usr_id, action, ts) VALUES ' .
91  '(%s, %s, %s, %s, %s, ' . $ilDB->now() . ')',
92  $ilDB->quote($nid, 'integer'),
93  $ilDB->quote($obj_id, 'integer'),
94  $ilDB->quote($prec["par_obj_id"], 'integer'),
95  $ilDB->quote($usr_id, 'integer'),
96  $ilDB->quote($action, 'text')
97  );
98 
99  $aff = $ilDB->manipulate($query);
100  }
101  } else {
102  $nid = $ilDB->nextId("write_event");
103  $query = sprintf(
104  'INSERT INTO write_event ' .
105  '(write_id, obj_id, parent_obj_id, usr_id, action, ts) ' .
106  'VALUES (%s,%s,%s,%s,%s,' . $ilDB->now() . ')',
107  $ilDB->quote($nid, 'integer'),
108  $ilDB->quote($obj_id, 'integer'),
109  $ilDB->quote($parent_obj_id, 'integer'),
110  $ilDB->quote($usr_id, 'integer'),
111  $ilDB->quote($action, 'text')
112  );
113  $aff = $ilDB->manipulate($query);
114  }
115  }
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
global $DIC
Definition: shib_login.php:22
+ Here is the caller graph for this function:

◆ _syncObjectStats()

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

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

References $check, $DIC, $ilDB, ilDBInterface\buildAtomQuery(), ilDBInterface\fetchAssoc(), ilDBInterface\insert(), ilDBInterface\numRows(), ilDBInterface\query(), ilDBInterface\quote(), and ilDBInterface\update().

Referenced by ilLPObjectStatisticsGUI\adminSync().

376  {
377  global $DIC;
378 
379  $ilDB = $DIC['ilDB'];
380 
381  if (!$a_now) {
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  $ilAtomQuery = $ilDB->buildAtomQuery();
392  $ilAtomQuery->addTableLock('obj_stat_log');
393  $ilAtomQuery->addTableLock('obj_stat_tmp');
394 
395  $ilAtomQuery->addQueryCallable(
396  function (ilDBInterface $ilDB) use ($a_now, $a_minimum, &$ret) {
397  // if other process was transferring, we had to wait for the lock and
398  // the source table should now have less than minimum/needed entries
399  $set = $ilDB->query(
400  "SELECT COUNT(*) AS counter FROM obj_stat_log"
401  );
402  $row = $ilDB->fetchAssoc($set);
403  if ($row["counter"] >= $a_minimum) {
404  // use only "full" seconds to have a clear cut
405  $ilDB->query(
406  "INSERT INTO obj_stat_tmp" .
407  " SELECT * FROM obj_stat_log" .
408  " WHERE tstamp < " . $ilDB->quote(
409  $a_now,
410  "timestamp"
411  )
412  );
413 
414  // remove transferred entries from source table
415  $ilDB->query(
416  "DELETE FROM obj_stat_log" .
417  " WHERE tstamp < " . $ilDB->quote(
418  $a_now,
419  "timestamp"
420  )
421  );
422 
423  $ret = true;
424  } else {
425  $ret = false;
426  }
427  }
428  );
429 
430  $ilAtomQuery->run();
431 
432  //continue only if obj_stat_log counter >= $a_minimum
433  if ($ret) {
434  $ilAtomQuery = $ilDB->buildAtomQuery();
435  $ilAtomQuery->addTableLock('obj_stat_tmp');
436  $ilAtomQuery->addTableLock('obj_stat');
437 
438  $ilAtomQuery->addQueryCallable(
439  function (ilDBInterface $ilDB) use ($a_now, $a_minimum) {
440  // process log data (timestamp is not needed anymore)
441  $sql = "SELECT obj_id, obj_type, yyyy, mm, dd, hh, SUM(read_count) AS read_count," .
442  " SUM(childs_read_count) AS childs_read_count, SUM(spent_seconds) AS spent_seconds," .
443  " SUM(childs_spent_seconds) AS childs_spent_seconds" .
444  " FROM obj_stat_tmp" .
445  " GROUP BY obj_id, obj_type, yyyy, mm, dd, hh";
446  $set = $ilDB->query($sql);
447  while ($row = $ilDB->fetchAssoc($set)) {
448  // "primary key"
449  $where = array("obj_id" => array("integer",
450  $row["obj_id"]
451  ),
452  "obj_type" => array("text",
453  $row["obj_type"]
454  ),
455  "yyyy" => array("integer",
456  $row["yyyy"]
457  ),
458  "mm" => array("integer", $row["mm"]),
459  "dd" => array("integer", $row["dd"]),
460  "hh" => array("integer", $row["hh"])
461  );
462 
463  $where_sql = array();
464  foreach ($where as $field => $def) {
465  $where_sql[] = $field . " = " . $ilDB->quote(
466  $def[1],
467  $def[0]
468  );
469  }
470  $where_sql = implode(" AND ", $where_sql);
471 
472  // existing entry?
473  $check = $ilDB->query(
474  "SELECT read_count, childs_read_count, spent_seconds," .
475  "childs_spent_seconds" .
476  " FROM obj_stat" .
477  " WHERE " . $where_sql
478  );
479  if ($ilDB->numRows($check)) {
480  $old = $ilDB->fetchAssoc($check);
481 
482  // add existing values
483  $fields = array("read_count" => array("integer",
484  $old["read_count"] + $row["read_count"]
485  ),
486  "childs_read_count" => array("integer",
487  $old["childs_read_count"] + $row["childs_read_count"]
488  ),
489  "spent_seconds" => array("integer",
490  $old["spent_seconds"] + $row["spent_seconds"]
491  ),
492  "childs_spent_seconds" => array("integer",
493  $old["childs_spent_seconds"] + $row["childs_spent_seconds"]
494  )
495  );
496 
497  $ilDB->update("obj_stat", $fields, $where);
498  } else {
499  // new entry
500  $fields = $where;
501  $fields["read_count"] = array("integer",
502  $row["read_count"]
503  );
504  $fields["childs_read_count"] = array("integer",
505  $row["childs_read_count"]
506  );
507  $fields["spent_seconds"] = array("integer",
508  $row["spent_seconds"]
509  );
510  $fields["childs_spent_seconds"] = array("integer",
511  $row["childs_spent_seconds"]
512  );
513 
514  $ilDB->insert("obj_stat", $fields);
515  }
516  }
517 
518  // clean up transfer table
519  $ilDB->query("DELETE FROM obj_stat_tmp");
520  }
521  );
522 
523  $ilAtomQuery->run();
524  }
525  }
526  }
numRows(ilDBStatement $statement)
insert(string $table_name, array $values)
fetchAssoc(ilDBStatement $statement)
update(string $table_name, array $values, array $where)
$where MUST contain existing columns only.
quote($value, string $type)
global $DIC
Definition: shib_login.php:22
query(string $query)
Run a (read-only) Query on the database.
$check
Definition: buildRTE.php:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _updateAccessForScormOfflinePlayer()

static ilChangeEvent::_updateAccessForScormOfflinePlayer ( int  $obj_id,
int  $usr_id,
int  $i_last_access,
string  $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

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

References $DIC, $ilDB, and $res.

824  : bool {
825  global $DIC;
826 
827  $ilDB = $DIC->database();
828  $res = $ilDB->queryF(
829  'UPDATE read_event SET first_access=%s, last_access = %s WHERE obj_id=%s AND usr_id=%s',
830  array('timestamp', 'integer', 'integer', 'integer'),
831  array($t_first_access, $i_last_access, $obj_id, $usr_id)
832  );
833  return true;
834  }
$res
Definition: ltiservices.php:66
global $DIC
Definition: shib_login.php:22

◆ hasAccessed()

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

Has accessed.

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

References $DIC, and $ilDB.

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

651  : bool
652  {
653  global $DIC;
654 
655  $ilDB = $DIC['ilDB'];
656 
657  if (isset(self::$has_accessed[$a_obj_id][$a_usr_id])) {
658  return self::$has_accessed[$a_obj_id][$a_usr_id];
659  }
660 
661  $set = $ilDB->query(
662  "SELECT usr_id FROM read_event WHERE " .
663  "obj_id = " . $ilDB->quote($a_obj_id, "integer") . " AND " .
664  "usr_id = " . $ilDB->quote($a_usr_id, "integer")
665  );
666  if ($rec = $ilDB->fetchAssoc($set)) {
667  return self::$has_accessed[$a_obj_id][$a_usr_id] = true;
668  }
669  return self::$has_accessed[$a_obj_id][$a_usr_id] = false;
670  }
global $DIC
Definition: shib_login.php:22
+ Here is the caller graph for this function:

◆ lookupUsersInProgress()

static ilChangeEvent::lookupUsersInProgress ( int  $a_obj_id)
static

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

References $DIC, $ilDB, $res, and ILIAS\Repository\int().

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

629  : array
630  {
631  global $DIC;
632 
633  $ilDB = $DIC['ilDB'];
634 
635  $query = sprintf(
636  'SELECT DISTINCT(usr_id) usr FROM read_event ' .
637  'WHERE obj_id = %s ',
638  $ilDB->quote($a_obj_id, 'integer')
639  );
640  $res = $ilDB->query($query);
641  $users = [];
642  while ($row = $ilDB->fetchObject($res)) {
643  $users[] = (int) $row->usr;
644  }
645  return $users;
646  }
$res
Definition: ltiservices.php:66
global $DIC
Definition: shib_login.php:22
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $has_accessed

array ilChangeEvent::$has_accessed = []
staticprivate

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


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