19 declare(strict_types=1);
48 private readonly
Factory $factory,
55 $storage_array = $interaction->
toStorage();
57 $this->db->insert(self::TEST_ADMINISTRATION_LOG_TABLE, $storage_array);
62 $storage_array = $interaction->
toStorage();
64 $this->db->insert(self::QUESTION_ADMINISTRATION_LOG_TABLE, $storage_array);
69 $storage_array = $interaction->
toStorage();
71 $this->db->insert(self::PARTICIPANT_LOG_TABLE, $storage_array);
76 $storage_array = $interaction->
toStorage();
78 $this->db->insert(self::SCORING_LOG_TABLE, $storage_array);
83 $storage_array = $interaction->
toStorage();
85 $this->db->insert(self::ERROR_LOG_TABLE, $storage_array);
93 ?
int $from_filter =
null,
94 ?
int $to_filter =
null,
95 ?array $admin_filter =
null,
96 ?array $pax_filter =
null,
97 ?array $question_filter =
null,
98 ?
string $ip_filter =
null,
99 ?array $log_entry_type_filter =
null,
100 ?array $interaction_type_filter =
null 104 $log_entry_type_filter,
105 $interaction_type_filter
119 $log_entry_type_filter,
120 $interaction_type_filter
127 ?array $test_filter =
null,
128 ?
int $from_filter =
null,
129 ?
int $to_filter =
null,
130 ?array $admin_filter =
null,
131 ?array $pax_filter =
null,
132 ?array $question_filter =
null,
133 ?
string $ip_filter =
null,
134 ?array $log_entry_type_filter =
null,
135 ?array $interaction_type_filter =
null 146 $log_entry_type_filter,
147 $interaction_type_filter
152 $result = $this->db->query(
155 return $this->db->fetchObject($result)->cnt;
162 $query =
"SELECT *, '{$type}' AS type FROM {$this->getTableNameForTypeIdentifier($type)} WHERE " 164 $result = $this->db->query($query);
181 $this->db->manipulate(
188 $query = $this->db->queryF(
189 'SELECT COUNT(id) AS cnt FROM ' . self::PARTICIPANT_LOG_TABLE .
' WHERE ref_id=%s',
193 return $this->db->fetchObject($query)->cnt > 0;
198 $this->db->manipulateF(
199 'DELETE FROM ' . self::PARTICIPANT_LOG_TABLE .
' WHERE ref_id=%s',
210 if ($obj_id !==
null) {
211 $where =
' WHERE obj_fi = ' . $obj_id;
214 $result = $this->db->query(
215 'SELECT * FROM ' . self::LEGACY_LOG_TABLE . $where .
' ORDER BY tstamp' 218 while ($row = $this->db->fetchAssoc($result)) {
219 if (!array_key_exists($row[
'tstamp'],
$log)) {
220 $log[$row[
'tstamp']] = [];
222 $log[$row[
'tstamp']][] = $row;
227 foreach (
$log as $value) {
228 foreach ($value as $row) {
237 $unique_id_array = explode(
'_', $unique_id);
238 if (count($unique_id_array) !== 2
239 || !is_numeric($unique_id_array[1])) {
243 switch ($unique_id_array[0]) {
266 if ($this->db->numRows($query) === 0) {
270 return $this->
factory->buildTestAdministrationInteractionFromDBValues($this->db->fetchObject($query));
276 if ($this->db->numRows($query) === 0) {
280 return $this->
factory->buildQuestionAdministrationInteractionFromDBValues($this->db->fetchObject($query));
286 if ($this->db->numRows($query) === 0) {
290 return $this->
factory->buildParticipantInteractionFromDBValues($this->db->fetchObject($query));
296 if ($this->db->numRows($query) === 0) {
300 return $this->
factory->buildScoringInteractionFromDBValues($this->db->fetchObject($query));
306 if ($this->db->numRows($query) === 0) {
310 return $this->
factory->buildErrorFromDBValues($this->db->fetchObject($query));
320 ?array $admin_filter,
322 ?array $question_filter,
324 ?array $log_entry_type_filter,
325 ?array $interaction_type_filter
338 $log_entry_type_filter,
339 $interaction_type_filter
346 while ($interaction = $this->db->fetchObject($result)) {
347 switch ($interaction->type) {
349 yield $this->
factory->buildTestAdministrationInteractionFromDBValues($interaction);
352 yield $this->
factory->buildQuestionAdministrationInteractionFromDBValues($interaction);
355 yield $this->
factory->buildParticipantInteractionFromDBValues($interaction);
358 yield $this->
factory->buildScoringInteractionFromDBValues($interaction);
361 yield $this->
factory->buildErrorFromDBValues($interaction);
369 return $this->db->queryF(
370 "SELECT * FROM {$table_name} WHERE id=%s",
378 if ($unique_ids[0] ===
'ALL_OBJECTS') {
379 return 'TUNCATE TABLE ' . self::TEST_ADMINISTRATION_LOG_TABLE .
';' 380 .
'TUNCATE TABLE ' . self::QUESTION_ADMINISTRATION_LOG_TABLE .
';' 381 .
'TUNCATE TABLE ' . self::PARTICIPANT_LOG_TABLE .
';' 382 .
'TUNCATE TABLE ' . self::SCORING_LOG_TABLE .
';' 383 .
'TUNCATE TABLE ' . self::ERROR_LOG_TABLE .
';';
387 $query .=
"DELETE FROM {$this->getTableNameForTypeIdentifier($type)} WHERE " 400 ?array $admin_filter,
402 ?array $question_filter,
404 ?array $log_entry_type_filter,
405 ?array $interaction_type_filter
416 $log_entry_type_filter,
417 $interaction_type_filter
420 $init = PHP_EOL .
'ORDER BY ';
421 $order_by_string = $order?->
join(
423 static fn(
string $ret,
string $key,
string $value):
string =>
"{$ret} " 424 . self::VIEW_TABLE_TO_DB_TABLES[$key] .
" {$value}, ",
426 if ($order_by_string !==
null 427 && $order_by_string !== $init) {
428 $query .= mb_substr($order_by_string, 0, -2);
431 if ($range !==
null) {
435 return $this->db->query($query);
443 ?array $admin_filter,
445 ?array $question_filter,
447 ?array $log_entry_type_filter,
448 ?array $interaction_type_filter
459 $log_entry_type_filter,
460 $interaction_type_filter
462 if ($tables_query ===
'') {
465 return 'SELECT COUNT(*) AS cnt FROM (' . PHP_EOL . $tables_query . PHP_EOL .
') x';
473 ?array $admin_filter,
475 ?array $question_filter,
477 ?array $log_entry_type_filter,
478 ?array $interaction_type_filter
480 $log_entry_types_to_fetch = array_keys($valid_types);
483 foreach ($log_entry_types_to_fetch as $type) {
484 if ($log_entry_type_filter !==
null 485 && !in_array($type, $log_entry_type_filter)
486 || $interaction_type_filter !==
null 489 $interaction_type_filter
503 $interaction_type_filter
508 PHP_EOL .
'UNION' . PHP_EOL,
511 static fn(?
string $select):
bool => $select !==
null 521 ?array $admin_filter,
523 ?array $question_filter,
525 ?array $interaction_type_filter
528 if ($pax_filter !==
null 529 && ($table_name === self::TEST_ADMINISTRATION_LOG_TABLE
530 || $table_name === self::QUESTION_ADMINISTRATION_LOG_TABLE)
531 || $admin_filter !==
null 532 && $table_name === self::PARTICIPANT_LOG_TABLE
533 || $ip_filter !==
null 534 && $table_name !== self::PARTICIPANT_LOG_TABLE
535 || $question_filter !==
null 536 && $table_name === self::TEST_ADMINISTRATION_LOG_TABLE
551 $interaction_type_filter
554 return $query . $where;
559 switch ($table_name) {
560 case self::TEST_ADMINISTRATION_LOG_TABLE:
561 return "SELECT '{$type}' AS type, id, ref_id, NULL AS qst_id, admin_id, " 562 .
'NULL AS pax_id, NULL AS source_ip, interaction_type, modification_ts, ' 563 .
"additional_data FROM {$table_name}";
564 case self::QUESTION_ADMINISTRATION_LOG_TABLE:
565 return "SELECT '{$type}' AS type, id, ref_id, qst_id, admin_id, " 566 .
'NULL AS pax_id, NULL AS source_ip, interaction_type, modification_ts, ' 567 .
"additional_data FROM {$table_name}";
568 case self::PARTICIPANT_LOG_TABLE:
569 return "SELECT '{$type}' AS type, id, ref_id, qst_id, NULL AS admin_id, " 570 .
'pax_id, source_ip, interaction_type, modification_ts, ' 571 .
"additional_data FROM {$table_name}";
572 case self::SCORING_LOG_TABLE:
573 return "SELECT '{$type}' AS type, id, ref_id, qst_id, admin_id, " 574 .
'pax_id, NULL AS source_ip, interaction_type, modification_ts, ' 575 .
"additional_data FROM {$table_name}";
576 case self::ERROR_LOG_TABLE:
577 return "SELECT '{$type}' AS type, id, ref_id, qst_id, admin_id, " 578 .
'pax_id, NULL AS source_ip, interaction_type, modification_ts, ' 579 .
"error_message AS additional_data FROM {$table_name}";
581 throw new \ErrorException(
'Unknown Database Table');
589 ?array $admin_filter,
591 ?array $question_filter,
593 ?array $interaction_type_filter
596 if ($from_filter !==
null) {
597 $where[] =
'modification_ts > ' . $from_filter;
599 if ($to_filter !==
null) {
600 $where[] =
'modification_ts < ' . $to_filter;
602 if ($test_filter !==
null) {
605 if ($admin_filter !==
null) {
608 if ($pax_filter !==
null) {
611 if ($question_filter !==
null) {
614 if ($ip_filter !==
null) {
617 if ($interaction_type_filter !==
null) {
618 $where[] = $this->db->in(
'interaction_type', $interaction_type_filter,
false, \
ilDBConstants::T_TEXT);
625 return ' WHERE ' . implode(
' AND ', $where);
630 ?array $log_entry_types,
631 ?array $interaction_types
633 if ($log_entry_types !==
null 638 || $interaction_types !==
null 652 array $filter_log_types
654 return array_intersect(
656 array_keys($valid_types)
657 ) === $filter_log_types;
662 ?array $filter_log_types,
663 array $filter_interaction_types
665 if ($filter_log_types !==
null 666 && $filter_log_types !== []) {
667 $valid_types = array_filter(
669 fn(
string $key):
bool => in_array($key, $filter_log_types),
673 $valid_interaction_types = array_reduce(
675 fn(array $et, array $it): array => [...$et, ...$it],
680 array_intersect($filter_interaction_types, $valid_interaction_types)
681 === $filter_interaction_types
697 function (array $type_array,
string $unique_id): array {
698 $unique_id_array = explode(
'_', $unique_id);
699 if (count($unique_id_array) !== 2
700 || !is_numeric($unique_id_array[1])) {
704 if (!array_key_exists($unique_id_array[0], $type_array)) {
705 $type_array[$unique_id_array[0]] = [];
708 $type_array[$unique_id_array[0]][] = $unique_id_array[1];
717 switch ($identifier) {
719 return self::TEST_ADMINISTRATION_LOG_TABLE;
722 return self::QUESTION_ADMINISTRATION_LOG_TABLE;
725 return self::PARTICIPANT_LOG_TABLE;
728 return self::SCORING_LOG_TABLE;
731 return self::ERROR_LOG_TABLE;
733 throw new \ErrorException(
'Unknown Identifier Type');
areInteractionTypesValid(array $valid_types, ?array $filter_log_types, array $filter_interaction_types)
join($init, callable $fn)
const COLUMN_INTERACTION_TYPE
buildCountQuery(array $valid_types, ?int $from_filter, ?int $to_filter, ?array $test_filter, ?array $admin_filter, ?array $pax_filter, ?array $question_filter, ?string $ip_filter, ?array $log_entry_type_filter, ?array $interaction_type_filter)
buildInteractionsQuery(array $valid_types, ?int $from_filter, ?int $to_filter, ?array $test_filter, ?array $admin_filter, ?array $pax_filter, ?array $question_filter, ?string $ip_filter, ?array $log_entry_type_filter, ?array $interaction_type_filter)
deleteParticipantInteractionsForTest(int $ref_id)
Interface Observer Contains several chained tasks and infos about them.
storeError(TestError $interaction)
const QUESTION_ADMINISTRATION_LOG_TABLE
getLogs(array $valid_types, ?array $test_filter, ?\ILIAS\Data\Range $range=null, ?\ILIAS\Data\Order $order=null, ?int $from_filter=null, ?int $to_filter=null, ?array $admin_filter=null, ?array $pax_filter=null, ?array $question_filter=null, ?string $ip_filter=null, ?array $log_entry_type_filter=null, ?array $interaction_type_filter=null)
buildParticipantInteractionFromId(int $id)
areLogEntryTypesValid(array $valid_types, array $filter_log_types)
retrieveInteractions(array $valid_types, ?Range $range, ?Order $order, ?int $from_filter, ?int $to_filter, ?array $test_filter, ?array $admin_filter, ?array $pax_filter, ?array $question_filter, ?string $ip_filter, ?array $log_entry_type_filter, ?array $interaction_type_filter)
buildSelectForTable(string $table_name, string $type)
getLogsByUniqueIdentifiers(array $unique_ids)
buildDeleteQueryForUniqueIds(array $unique_ids)
fetchInteractionForResult(\ilDBStatement $result)
const VIEW_TABLE_TO_DB_TABLES
buildUserInteractionForUniqueIdentifier(string $unique_id)
const COLUMN_LOG_ENTRY_TYPE
getLegacyLogsForObjId(?int $obj_id)
deleteLogs(array $unique_ids)
buildSelectStatementForId(int $id, string $table_name)
__construct(private readonly Factory $factory, private readonly \ilDBInterface $db)
Both the subject and the direction need to be specified when expressing an order. ...
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
storeQuestionAdministrationInteraction(TestQuestionAdministrationInteraction $interaction)
getLog(string $unique_id)
buildScoringInteractionFromId(int $id)
isFilterValid(array $valid_types, ?array $log_entry_types, ?array $interaction_types)
const COLUMN_CORRESPONDING_TEST
buildErrorFromId(int $id)
buildWhereFromFilterValues(?int $from_filter, ?int $to_filter, ?array $test_filter, ?array $admin_filter, ?array $pax_filter, ?array $question_filter, ?string $ip_filter, ?array $interaction_type_filter)
storeTestAdministrationInteraction(TestAdministrationInteraction $interaction)
buildTestAdministrationInteractionFromId(int $id)
buildTableQueryFromFilterValues(string $type, ?int $from_filter, ?int $to_filter, ?array $test_filter, ?array $admin_filter, ?array $pax_filter, ?array $question_filter, ?string $ip_filter, ?array $interaction_type_filter)
getTableNameForTypeIdentifier(string $identifier)
getLogsCount(array $valid_types, ?array $test_filter=null, ?int $from_filter=null, ?int $to_filter=null, ?array $admin_filter=null, ?array $pax_filter=null, ?array $question_filter=null, ?string $ip_filter=null, ?array $log_entry_type_filter=null, ?array $interaction_type_filter=null)
buildInteractionsStatementWithLimitAndOrder(array $valid_types, ?Range $range, ?Order $order, ?int $from_filter, ?int $to_filter, ?array $test_filter, ?array $admin_filter, ?array $pax_filter, ?array $question_filter, ?string $ip_filter, ?array $log_entry_type_filter, ?array $interaction_type_filter)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const TEST_ADMINISTRATION_LOG_TABLE
storeScoringInteraction(TestScoringInteraction $interaction)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
storeParticipantInteraction(TestParticipantInteraction $interaction)
testHasParticipantInteractions(int $ref_id)
parseUniqueIdsToTypeArray(array $unique_ids)
const PARTICIPANT_LOG_TABLE
A simple class to express a naive range of whole positive numbers.
buildQuestionAdministrationInteractionFromId(int $id)