ILIAS  release_8 Revision v8.24
class.ilTestSession.php
Go to the documentation of this file.
1<?php
2
29{
30 public const ACCESS_CODE_SESSION_INDEX = "tst_access_code";
31 public const ACCESS_CODE_CHAR_DOMAIN = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
32 public const ACCESS_CODE_LENGTH = 5;
33
34 private int $ref_id;
35 private int $pass;
36 public int $active_id;
37 public int $user_id;
39 public $anonymous_id = null;
40 public int $test_id;
41 public int $lastsequence;
42 protected ?string $lastPresentationMode;
43 public bool $submitted;
44 public int $tstamp;
45 public ?string $submittedTimestamp;
47
50
51
60 public function __construct()
61 {
62 $this->active_id = 0;
63 $this->user_id = 0;
64 $this->anonymous_id = 0;
65 $this->test_id = 0;
66 $this->lastsequence = 0;
67 $this->lastPresentationMode = null;
68 $this->submitted = false;
69 $this->submittedTimestamp = "";
70 $this->pass = 0;
71 $this->ref_id = 0;
72 $this->tstamp = 0;
73
74 $this->lastStartedPass = null;
75 $this->lastFinishedPass = null;
76 $this->objectiveOrientedContainerId = 0;
77 }
78
79 public function setRefId(int $a_val): void
80 {
81 $this->ref_id = $a_val;
82 }
83
84 public function getRefId(): int
85 {
86 return $this->ref_id;
87 }
88
89 protected function activeIDExists($user_id, $test_id): bool
90 {
91 global $DIC;
92 $ilDB = $DIC['ilDB'];
93
94 if ($GLOBALS['DIC']['ilUser']->getId() != ANONYMOUS_USER_ID) {
95 $result = $ilDB->queryF(
96 "SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
97 array('integer','integer'),
98 array($user_id, $test_id)
99 );
100 if ($result->numRows()) {
101 $row = $ilDB->fetchAssoc($result);
102 $this->active_id = (int) $row["active_id"];
103 $this->user_id = (int) $row["user_fi"];
104 $this->anonymous_id = $row["anonymous_id"];
105 $this->test_id = (int) $row["test_fi"];
106 $this->lastsequence = (int) $row["lastindex"];
107 $this->pass = (int) $row["tries"];
108 $this->submitted = ($row["submitted"]) ? true : false;
109 $this->submittedTimestamp = (string) $row["submittimestamp"];
110 $this->tstamp = (int) $row["tstamp"];
111
112 $this->setLastStartedPass($row['last_started_pass']);
113 $this->setLastFinishedPass($row['last_finished_pass']);
114 $this->setObjectiveOrientedContainerId((int) $row['objective_container']);
115
116 return true;
117 }
118 }
119 return false;
120 }
121
122 public function increaseTestPass(): void
123 {
124 global $DIC;
125 $ilDB = $DIC['ilDB'];
126 $ilLog = $DIC['ilLog'];
127
128 if (!$this->active_id) {
129 require_once 'Modules/Test/exceptions/class.ilTestException.php';
130 throw new ilTestException('missing active id on test pass increase!');
131 }
132
133 $this->increasePass();
134 $this->setLastSequence(0);
135 $submitted = ($this->isSubmitted()) ? 1 : 0;
136 $active = ilSession::get($this->active_id);
137 if (!isset($active['tst_last_increase_pass']) || $active['tst_last_increase_pass'] !== null) {
138 $active['tst_last_increase_pass'] = 0;
139 //ilSession::set($this->active_id, $active);
140 //$_SESSION[$this->active_id]['tst_last_increase_pass'] = 0;
141 }
142
143 // there has to be at least 10 seconds between new test passes (to ensure that noone double clicks the finish button and increases the test pass by more than 1)
144 if (time() - $active['tst_last_increase_pass'] > 10) {
145 $active['tst_last_increase_pass'] = time();
146 //ilSession::set($this->active_id, $active);
147 $this->tstamp = time();
148 $ilDB->update(
149 'tst_active',
150 array(
151 'lastindex' => array('integer', $this->getLastSequence()),
152 'tries' => array('integer', $this->getPass()),
153 'submitted' => array('integer', $submitted),
154 'submittimestamp' => array('timestamp', strlen($this->getSubmittedTimestamp()) ? $this->getSubmittedTimestamp() : null),
155 'tstamp' => array('integer', time()),
156 'last_finished_pass' => array('integer', $this->getLastFinishedPass()),
157 'last_started_pass' => array('integer', $this->getLastStartedPass()),
158 'objective_container' => array('integer', $this->getObjectiveOrientedContainerId())
159 ),
160 array(
161 'active_id' => array('integer', $this->getActiveId())
162 )
163 );
164 }
165 }
166
167 public function saveToDb(): void
168 {
169 global $DIC;
170 $ilDB = $DIC['ilDB'];
171 $ilLog = $DIC['ilLog'];
172
173 $submitted = ($this->isSubmitted()) ? 1 : 0;
174 if ($this->active_id > 0) {
175 $ilDB->update(
176 'tst_active',
177 array(
178 'lastindex' => array('integer', $this->getLastSequence()),
179 'tries' => array('integer', $this->getPass()),
180 'submitted' => array('integer', $submitted),
181 'submittimestamp' => array('timestamp', (strlen($this->getSubmittedTimestamp())) ? $this->getSubmittedTimestamp() : null),
182 'tstamp' => array('integer', time() - 10),
183 'last_finished_pass' => array('integer', $this->getLastFinishedPass()),
184 'last_started_pass' => array('integer', $this->getPass()),
185 'objective_container' => array('integer', $this->getObjectiveOrientedContainerId())
186 ),
187 array(
188 'active_id' => array('integer', $this->getActiveId())
189 )
190 );
191 } else {
192 if (!$this->activeIDExists($this->getUserId(), $this->getTestId())) {
193 $anonymous_id = $this->getAnonymousId() ?: null;
194
195 $next_id = $ilDB->nextId('tst_active');
196 $ilDB->insert(
197 'tst_active',
198 array(
199 'active_id' => array('integer', $next_id),
200 'user_fi' => array('integer', $this->getUserId()),
201 'anonymous_id' => array('text', $anonymous_id),
202 'test_fi' => array('integer', $this->getTestId()),
203 'lastindex' => array('integer', $this->getLastSequence()),
204 'tries' => array('integer', $this->getPass()),
205 'submitted' => array('integer', $submitted),
206 'submittimestamp' => array('timestamp', (strlen($this->getSubmittedTimestamp())) ? $this->getSubmittedTimestamp() : null),
207 'tstamp' => array('integer', time() - 10),
208 'last_finished_pass' => array('integer', $this->getLastFinishedPass()),
209 'last_started_pass' => array('integer', $this->getPass()),
210 'objective_container' => array('integer', $this->getObjectiveOrientedContainerId())
211 )
212 );
213 $this->active_id = $next_id;
214 }
215 }
216 }
217
218 public function loadTestSession($test_id, $user_id = "", $anonymous_id = ""): void
219 {
220 global $DIC;
221 $ilDB = $DIC['ilDB'];
222 $ilUser = $DIC['ilUser'];
223
224 if (!$user_id) {
225 $user_id = $ilUser->getId();
226 }
227 if (($GLOBALS['DIC']['ilUser']->getId() == ANONYMOUS_USER_ID) && $this->doesAccessCodeInSessionExists()) {
228 $result = $ilDB->queryF(
229 "SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
230 array('integer','integer','text'),
232 );
233 } elseif (strlen($anonymous_id)) {
234 $result = $ilDB->queryF(
235 "SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
236 array('integer','integer','text'),
238 );
239 } else {
240 if ($GLOBALS['DIC']['ilUser']->getId() == ANONYMOUS_USER_ID) {
241 return;
242 }
243 $result = $ilDB->queryF(
244 "SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
245 array('integer','integer'),
246 array($user_id, $test_id)
247 );
248 }
249
250 // TODO bheyser: Refactor
251 $this->user_id = $user_id;
252
253 if ($result->numRows()) {
254 $row = $ilDB->fetchAssoc($result);
255 $this->active_id = $row["active_id"];
256 $this->user_id = $row["user_fi"];
257 $this->anonymous_id = $row["anonymous_id"];
258 $this->test_id = $row["test_fi"];
259 $this->lastsequence = $row["lastindex"];
260 $this->pass = $row["tries"];
261 $this->submitted = ($row["submitted"]) ? true : false;
262 $this->submittedTimestamp = $row["submittimestamp"];
263 $this->tstamp = $row["tstamp"];
264
265 $this->setLastStartedPass($row['last_started_pass']);
266 $this->setLastFinishedPass($row['last_finished_pass']);
267 $this->setObjectiveOrientedContainerId((int) $row['objective_container']);
268 } elseif ($this->doesAccessCodeInSessionExists()) {
270 }
271 }
272
278 public function loadFromDb($active_id)
279 {
280 global $DIC;
281 $ilDB = $DIC['ilDB'];
282 $result = $ilDB->queryF(
283 "SELECT * FROM tst_active WHERE active_id = %s",
284 array('integer'),
285 array($active_id)
286 );
287 if ($result->numRows()) {
288 $row = $ilDB->fetchAssoc($result);
289 $this->active_id = $row["active_id"];
290 $this->user_id = $row["user_fi"];
291 $this->anonymous_id = $row["anonymous_id"];
292 $this->test_id = $row["test_fi"];
293 $this->lastsequence = $row["lastindex"];
294 $this->pass = $row["tries"];
295 $this->submitted = ($row["submitted"]) ? true : false;
296 $this->submittedTimestamp = $row["submittimestamp"];
297 $this->tstamp = $row["tstamp"];
298
299 $this->setLastStartedPass($row['last_started_pass']);
300 $this->setLastFinishedPass($row['last_finished_pass']);
301 $this->setObjectiveOrientedContainerId((int) $row['objective_container']);
302 }
303 }
304
305 public function getActiveId(): int
306 {
307 return $this->active_id;
308 }
309
310 public function setUserId($user_id): void
311 {
312 $this->user_id = $user_id;
313 }
314
315 public function getUserId(): int
316 {
317 return $this->user_id;
318 }
319
320 public function setTestId($test_id): void
321 {
322 $this->test_id = $test_id;
323 }
324
325 public function getTestId(): int
326 {
327 return $this->test_id;
328 }
329
334 public function setAnonymousId($anonymous_id): void
335 {
336 $this->anonymous_id = $anonymous_id;
337 }
338
342 public function getAnonymousId()
343 {
344 return $this->anonymous_id;
345 }
346
348 {
349 $this->lastsequence = $lastsequence;
350 }
351
352 public function getLastSequence(): int
353 {
354 return $this->lastsequence;
355 }
356
357 public function setPass($pass)
358 {
359 $this->pass = $pass;
360 }
361
362 public function getPass(): int
363 {
364 return $this->pass;
365 }
366
367 public function increasePass()
368 {
369 $this->pass += 1;
370 }
371
372 public function isSubmitted(): bool
373 {
374 return $this->submitted;
375 }
376
377 public function setSubmitted()
378 {
379 $this->submitted = true;
380 }
381
382 public function getSubmittedTimestamp(): ?string
383 {
385 }
386
387 public function setSubmittedTimestamp()
388 {
389 $this->submittedTimestamp = date('Y-m-d H:i:s');
390 }
391
393 {
394 $this->lastFinishedPass = $lastFinishedPass;
395 }
396
397 public function getLastFinishedPass()
398 {
400 }
401
402 public function setObjectiveOrientedContainerId($objectiveOriented)
403 {
404 $this->objectiveOrientedContainerId = $objectiveOriented;
405 }
406
408 {
410 }
411
415 public function getLastStartedPass(): ?int
416 {
418 }
419
424 {
425 $this->lastStartedPass = $lastStartedPass;
426 }
427
428 public function isObjectiveOriented(): bool
429 {
430 return (bool) $this->getObjectiveOrientedContainerId();
431 }
432
433 public function persistTestStartLock($testStartLock)
434 {
435 global $DIC;
436 $ilDB = $DIC['ilDB'];
437
438 $ilDB->update(
439 'tst_active',
440 array('start_lock' => array('text', $testStartLock)),
441 array('active_id' => array('integer', $this->getActiveId()))
442 );
443 }
444
445 public function lookupTestStartLock()
446 {
447 global $DIC;
448 $ilDB = $DIC['ilDB'];
449
450 $res = $ilDB->queryF(
451 "SELECT start_lock FROM tst_active WHERE active_id = %s",
452 array('integer'),
453 array($this->getActiveId())
454 );
455
456 while ($row = $ilDB->fetchAssoc($res)) {
457 return $row['start_lock'];
458 }
459
460 return null;
461 }
462
463 public function setAccessCodeToSession($access_code)
464 {
465 if (!is_array(ilSession::get(self::ACCESS_CODE_SESSION_INDEX))) {
466 ilSession::set(self::ACCESS_CODE_SESSION_INDEX, array());
467 }
468 $session_code = ilSession::get(self::ACCESS_CODE_SESSION_INDEX);
469 $session_code[$this->getTestId()] = $access_code;
470 ilSession::set(self::ACCESS_CODE_SESSION_INDEX, $session_code);
471 //$_SESSION[self::ACCESS_CODE_SESSION_INDEX][$this->getTestId()] = $access_code;
472 }
473
474 public function unsetAccessCodeInSession()
475 {
476 $session_code = ilSession::get(self::ACCESS_CODE_SESSION_INDEX);
477 unset($session_code[$this->getTestId()]);
478 ilSession::set(self::ACCESS_CODE_SESSION_INDEX, $session_code);
479 //unset($_SESSION[self::ACCESS_CODE_SESSION_INDEX][$this->getTestId()]);
480 }
481
482 public function getAccessCodeFromSession()
483 {
484 if (!is_array(ilSession::get(self::ACCESS_CODE_SESSION_INDEX))) {
485 return null;
486 }
487 $session_code = ilSession::get(self::ACCESS_CODE_SESSION_INDEX);
488 if (!isset($session_code[$this->getTestId()])) {
489 return null;
490 }
491
492 return $session_code[$this->getTestId()];
493 }
494
495 public function doesAccessCodeInSessionExists(): bool
496 {
497 if (!is_array(ilSession::get(self::ACCESS_CODE_SESSION_INDEX))) {
498 return false;
499 }
500 $session_code = ilSession::get(self::ACCESS_CODE_SESSION_INDEX);
501 if (!isset($session_code[$this->getTestId()])) {
502 return false;
503 }
504
505 return isset($session_code[$this->getTestId()]);
506 }
507
508 public function createNewAccessCode(): string
509 {
510 do {
511 $code = $this->buildAccessCode();
512 } while ($this->isAccessCodeUsed($code));
513
514 return $code;
515 }
516
517 public function isAccessCodeUsed($code): bool
518 {
519 global $DIC;
520 $ilDB = $DIC['ilDB'];
521
522 $query = "SELECT anonymous_id FROM tst_active WHERE test_fi = %s AND anonymous_id = %s";
523
524 $result = $ilDB->queryF(
525 $query,
526 array('integer', 'text'),
527 array($this->getTestId(), $code)
528 );
529
530 return ($result->numRows() > 0);
531 }
532
533 private function buildAccessCode(): string
534 {
535 // create a 5 character code
536 $codestring = self::ACCESS_CODE_CHAR_DOMAIN;
537
538 mt_srand();
539
540 $code = "";
541
542 for ($i = 1; $i <= self::ACCESS_CODE_LENGTH; $i++) {
543 $index = mt_rand(0, strlen($codestring) - 1);
544 $code .= substr($codestring, $index, 1);
545 }
546
547 return $code;
548 }
549
550 public function isAnonymousUser(): bool
551 {
552 return $this->getUserId() == ANONYMOUS_USER_ID;
553 }
554
555 public function isPasswordChecked(): bool
556 {
557 if (ilSession::get('pw_checked_' . $this->active_id) === null) {
558 return false;
559 }
560 return ilSession::get('pw_checked_' . $this->active_id);
561 }
562
563 public function setPasswordChecked(bool $value): void
564 {
565 ilSession::set('pw_checked_' . $this->active_id, $value);
566 }
567
572
577 public function reportableResultsAvailable(ilObjTest $testOBJ): ?bool
578 {
579 if ($this->reportableResultsAvailable === null) {
580 $this->reportableResultsAvailable = true;
581
582 if (!$this->getActiveId()) {
583 $this->reportableResultsAvailable = false;
584 }
585
586 if (!$testOBJ->canShowTestResults($this)) {
587 $this->reportableResultsAvailable = false;
588 }
589 }
590
592 }
593
597 public function hasSinglePassReportable(ilObjTest $testObj): bool
598 {
599 global $DIC; /* @var ILIAS\DI\Container $DIC */
600
601 require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
602 $testPassesSelector = new ilTestPassesSelector($DIC->database(), $testObj);
603 $testPassesSelector->setActiveId($this->getActiveId());
604 $testPassesSelector->setLastFinishedPass($this->getLastFinishedPass());
605
606 if (count($testPassesSelector->getReportablePasses()) == 1) {
607 return true;
608 }
609
610 return false;
611 }
612}
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
canShowTestResults(ilTestSession $testSession)
static get(string $a_var)
static set(string $a_var, $a_val)
Set a value.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
activeIDExists($user_id, $test_id)
setAccessCodeToSession($access_code)
persistTestStartLock($testStartLock)
setPasswordChecked(bool $value)
__construct()
ilTestSession constructor
setAnonymousId($anonymous_id)
setObjectiveOrientedContainerId($objectiveOriented)
loadTestSession($test_id, $user_id="", $anonymous_id="")
loadFromDb($active_id)
Loads the session data for a given active id.
setLastSequence($lastsequence)
setLastFinishedPass($lastFinishedPass)
setRefId(int $a_val)
reportableResultsAvailable(ilObjTest $testOBJ)
setLastStartedPass($lastStartedPass)
hasSinglePassReportable(ilObjTest $testObj)
const ANONYMOUS_USER_ID
Definition: constants.php:27
global $DIC
Definition: feed.php:28
$ilUser
Definition: imgupload.php:34
$res
Definition: ltiservices.php:69
$index
Definition: metadata.php:145
$i
Definition: metadata.php:41
$query