ILIAS  trunk Revision v11.0_alpha-1723-g8e69f309bab
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
DatabaseRepository.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
25 
27 {
28  private const SEQUENCE_TABLE_TEST_FIXED = 'tst_sequence';
29  private const SEQUENCE_TABLE_TEST_RANDOM = 'tst_test_rnd_qst';
30  private const LINKING_TABLE_TEST_FIXED = 'tst_test_question';
31  private const LINKING_TABLE_TEST_RANDOM = 'tst_rnd_cpy';
32  private const RESULTS_TABLE = 'tst_test_result';
33  private const ATTEMPTS_TABLE = 'tst_active';
34 
35  public function __construct(
36  private readonly \ilDBInterface $db,
37  private readonly GeneralQuestionPropertiesRepository $question_properties_repo
38  ) {
39  }
40 
41  public function getQuestionPropertiesForQuestionId(int $question_id): ?Properties
42  {
43  return $this->getQuestionPropertiesForQuestionIds([$question_id])[$question_id] ?? null;
44  }
45 
46  public function getQuestionPropertiesForQuestionIds(array $question_ids): array
47  {
49  $this->question_properties_repo->getForQuestionIds($question_ids),
50  $this->getSequencePropertiesForQuestionIds($question_ids)
51  );
52  }
53 
54  public function getQuestionPropertiesForTest(\ilObjTest $test): array
55  {
56  if ($test->isFixedTest()) {
57  return $this->buildQuestionPropertiesForFixedTest($test);
58  }
59 
60  if ($test->isRandomTest()) {
61  return $this->buildQuestionPropertiesForRandomTest($test);
62  }
63 
64  return [];
65  }
66 
68  {
69  $general_question_properties = $this->getQuestionPropertiesForTest($test);
70  $query = $this->db->query(
71  'SELECT question_fi, COUNT(*) as nr_of_answers, SUM(points) as achieved_points'
72  . ' FROM ' . self::RESULTS_TABLE
73  . ' INNER JOIN ' . self::ATTEMPTS_TABLE . ' ON active_fi = active_id'
74  . ' WHERE answered = 1 AND ' . $this->db->in(
75  'question_fi',
76  array_keys($general_question_properties),
77  false,
79  ) . ' GROUP BY question_fi'
80  );
81 
82  return array_reduce(
83  $this->db->fetchAll($query, \ilDBConstants::FETCHMODE_OBJECT),
84  static function (array $c, \stdClass $v): array {
85  if ($c[$v->question_fi] === null) {
86  return $c;
87  }
88 
89  $c[$v->question_fi] = $c[$v->question_fi]->withAggregatedResults(
91  $v->question_fi,
92  $v->nr_of_answers,
93  $c[$v->question_fi]->getGeneralQuestionProperties()->getAvailablePoints(),
94  $v->achieved_points
95  )
96  );
97  return $c;
98  },
99  $general_question_properties
100  );
101  }
102 
103  public function questionHasAnswers(int $question_id): bool
104  {
105  $query = $this->db->query(
106  'SELECT COUNT(*) as nr_of_answers'
107  . ' FROM ' . self::RESULTS_TABLE
108  . ' INNER JOIN ' . self::ATTEMPTS_TABLE . ' ON active_fi = active_id'
109  . ' WHERE answered = 1 AND question_fi=' . $question_id
110  );
111 
112  return $this->db->fetchObject($query)->nr_of_answers > 0;
113  }
114 
115  public function originalQuestionExists(int $question_id): bool
116  {
117  return $this->question_properties_repo->originalQuestionExists($question_id);
118  }
119 
124  private function getSequencePropertiesForQuestionIds(array $question_ids): array
125  {
126  $query = $this->db->query(
127  'SELECT test_fi, question_fi, sequence FROM ' . self::LINKING_TABLE_TEST_FIXED
128  . ' WHERE ' . $this->db->in('question_fi', $question_ids, false, \ilDBConstants::T_INTEGER)
129  );
130 
131  return array_reduce(
132  $this->db->fetchAll($query, \ilDBConstants::FETCHMODE_OBJECT),
133  static function (array $c, \stdClass $v): array {
134  $c[$v->question_fi] = new PropertySequence(
135  $v->question_fi,
136  $v->test_fi,
137  $v->sequence
138  );
139  return $c;
140  },
141  array_fill_keys($question_ids, null)
142  );
143  }
144 
148  private function getQuestionIdsForRandomTest(int $test_id): array
149  {
150  $query = $this->db->query(
151  'SELECT qst_fi FROM ' . self::LINKING_TABLE_TEST_RANDOM
152  . ' WHERE tst_fi=' . $test_id
153  );
154 
155  return array_map(
156  fn(\stdClass $v): int => $v->qst_fi,
157  $this->db->fetchAll($query, \ilDBConstants::FETCHMODE_OBJECT)
158  );
159  }
160 
164  private function buildQuestionPropertiesForFixedTest(\ilObjTest $test): array
165  {
166  $general_question_properties = $this->question_properties_repo->getForParentObjectId($test->getId());
168  $general_question_properties,
169  $this->getSequencePropertiesForQuestionIds(array_keys($general_question_properties)),
170  true
171  );
172  }
173 
177  private function buildQuestionPropertiesForRandomTest(\ilObjTest $test): array
178  {
179  if ($test->getQuestionSetConfig()->getLastQuestionSyncTimestamp() === 0) {
180  return [];
181  }
182  $question_ids = $this->getQuestionIdsForRandomTest($test->getTestId());
183  return array_reduce(
184  $this->question_properties_repo->getForQuestionIds($question_ids),
185  static function (array $c, GeneralQuestionProperties $v): array {
186  if ($v === null) {
187  return $c;
188  }
189  $c[$v->getQuestionId()] = new Properties(
190  $v->getQuestionId(),
191  $v
192  );
193  return $c;
194  },
195  []
196  );
197  }
198 
209  array $general_question_properties,
210  array $sequence_properties,
211  bool $delete_on_missing_sequence = false
212  ): array {
213  return array_reduce(
214  $general_question_properties,
215  static function (array $c, GeneralQuestionProperties $v) use (
216  $sequence_properties,
217  $delete_on_missing_sequence
218  ): array {
219  if ($v === null
220  || $delete_on_missing_sequence
221  && $sequence_properties[$v->getQuestionId()] === null) {
222  return $c;
223  }
224 
225  $question_properties = new Properties(
226  $v->getQuestionId(),
227  $v
228  );
229  if ($sequence_properties[$v->getQuestionId()] !== null) {
230  $question_properties = $question_properties
231  ->withSequenceInformation($sequence_properties[$v->getQuestionId()]);
232  }
233 
234  $c[$v->getQuestionId()] = $question_properties;
235  return $c;
236  },
237  []
238  );
239  }
240 }
originalQuestionExists(int $question_id)
This is an adaptor to query the question pool if a question exists for the original_id of a given que...
__construct(private readonly \ilDBInterface $db, private readonly GeneralQuestionPropertiesRepository $question_properties_repo)
getTestId()
Gets the database id of the additional test data.
$c
Definition: deliver.php:25
isRandomTest()
Returns the fact wether this test is a random questions test or not.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
isFixedTest()
Returns the fact wether this test is a fixed question set test or not.
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
getQuestionPropertiesWithAggregatedResultsForTest(\ilObjTest $test)
Returns an array of Properties-objects with AggregatedResultsProperties if available.
buildQuestionPropertiesFromGeneralQuestionPropertiesAndSquenceProperties(array $general_question_properties, array $sequence_properties, bool $delete_on_missing_sequence=false)
getQuestionPropertiesForQuestionIds(array $question_ids)
Returns an array of Properties-objects if available.
withSequenceInformation(PropertySequence $sequence)
Definition: Properties.php:68
getQuestionPropertiesForQuestionId(int $question_id)
Returns a Properties-objects if available.