ILIAS  release_8 Revision v8.24
class.ilCronFinishUnfinishedTestPasses.php
Go to the documentation of this file.
1<?php
2
24{
28 protected $log;
29
30 protected ilLanguage $lng;
31 protected ilDBInterface $db;
33 protected int $now;
34 protected array $unfinished_passes;
35 protected array $test_ids;
36 protected array $test_ending_times;
38
39 public function __construct()
40 {
41 global $DIC;
42
43 $this->log = ilLoggerFactory::getLogger('tst');
44 $this->lng = $DIC['lng'];
45 $this->lng->loadLanguageModule('assessment');
46 $this->db = $DIC->database();
47 $this->obj_data_cache = $DIC['ilObjDataCache'];
48 $this->now = time();
49 $this->unfinished_passes = array();
50 $this->test_ids = array();
51 $this->test_ending_times = array();
52
53 require_once 'Modules/Test/classes/class.ilTestProcessLockerFactory.php';
54 $this->processLockerFactory = new ilTestProcessLockerFactory(
55 new ilSetting('assessment'),
56 $this->db
57 );
58 }
59
60 public function getId(): string
61 {
62 return 'finish_unfinished_passes';
63 }
64
65 public function getTitle(): string
66 {
67 global $DIC;
68 $lng = $DIC['lng'];
69
70 return $lng->txt("finish_unfinished_passes");
71 }
72
73 public function getDescription(): string
74 {
75 global $DIC;
76 $lng = $DIC['lng'];
77
78 return $lng->txt("finish_unfinished_passes_desc");
79 }
80
81 public function getDefaultScheduleType(): int
82 {
84 }
85
86 public function getDefaultScheduleValue(): int
87 {
88 return 1;
89 }
90
91 public function hasAutoActivation(): bool
92 {
93 return false;
94 }
95
96 public function hasFlexibleSchedule(): bool
97 {
98 return true;
99 }
100
101 public function hasCustomSettings(): bool
102 {
103 return true;
104 }
105
106 public function run(): ilCronJobResult
107 {
108 $this->log->info('start inf cronjob...');
109
110 $result = new ilCronJobResult();
111
113 if (count($this->unfinished_passes) > 0) {
114 $this->log->info('found ' . count($this->unfinished_passes) . ' unfinished passes starting analyses.');
116 $this->processPasses();
117 } else {
118 $this->log->info('No unfinished passes found.');
119 }
120
121 $result->setStatus(ilCronJobResult::STATUS_OK);
122
123 $this->log->info(' ...finishing cronjob.');
124
125 return $result;
126 }
127
128 protected function gatherUsersWithUnfinishedPasses(): void
129 {
130 $query = "SELECT tst_active.active_id,
131 tst_active.tries,
132 tst_active.user_fi usr_id,
133 tst_active.test_fi test_fi,
134 usr_data.login,
135 usr_data.lastname,
136 usr_data.firstname,
137 tst_active.submitted test_finished,
138 usr_data.matriculation,
139 usr_data.active,
140 tst_active.lastindex,
141 tst_active.last_started_pass last_started
142 FROM tst_active
143 LEFT JOIN usr_data
144 ON tst_active.user_fi = usr_data.usr_id
145 WHERE IFNULL(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass
146 ";
147 $result = $this->db->query($query);
148 while ($row = $this->db->fetchAssoc($result)) {
149 $this->unfinished_passes[] = $row;
150 $this->test_ids[] = $row['test_fi'];
151 }
152 }
153
154 protected function getTestsFinishAndProcessingTime(): void
155 {
156 $query = 'SELECT test_id, obj_fi, ending_time, ending_time_enabled, processing_time, enable_processing_time FROM tst_tests WHERE ' .
157 $this->db->in('test_id', $this->test_ids, false, 'integer');
158 $result = $this->db->query($query);
159 while ($row = $this->db->fetchAssoc($result)) {
160 $this->test_ending_times[$row['test_id']] = $row;
161 }
162 $this->log->info('Gathered data for ' . count($this->test_ids) . ' test id(s) => (' . implode(',', $this->test_ids) . ')');
163 }
164
165 protected function processPasses(): void
166 {
167 $now = time();
168 foreach ($this->unfinished_passes as $key => $data) {
169 $test_id = $data['test_fi'];
170 $can_not_be_finished = true;
171 if (array_key_exists($test_id, $this->test_ending_times)) {
172 if ($this->test_ending_times[$test_id]['ending_time_enabled'] == 1) {
173 $this->log->info('Test (' . $test_id . ') has ending time (' . $this->test_ending_times[$test_id]['ending_time'] . ')');
174 $ending_time = $this->test_ending_times[$test_id]['ending_time'];
175 if ($ending_time < $now) {
176 $this->finishPassForUser($data['active_id'], $this->test_ending_times[$test_id]['obj_fi']);
177 $can_not_be_finished = false;
178 } else {
179 $this->log->info('Test (' . $test_id . ') ending time (' . $this->test_ending_times[$test_id]['ending_time'] . ') > now (' . $now . ') is not reached.');
180 }
181 } else {
182 $this->log->info('Test (' . $test_id . ') has no ending time.');
183 }
184 if ($this->test_ending_times[$test_id]['enable_processing_time'] == 1) {
185 $this->log->info('Test (' . $test_id . ') has processing time (' . $this->test_ending_times[$test_id]['processing_time'] . ')');
186 $obj_id = $this->test_ending_times[$test_id]['obj_fi'];
187 if(ilObject::_exists($obj_id)) {
188 $test_obj = new ilObjTest($obj_id, false);
189 $startingTime = $test_obj->getStartingTimeOfUser($data['active_id']);
190 $max_processing_time = $test_obj->isMaxProcessingTimeReached($startingTime, $data['active_id']);
191 if ($max_processing_time) {
192 $this->log->info('Max Processing time reached for user id (' . $data['usr_id'] . ') so test with active id (' . $data['active_id'] . ') will be finished.');
193 $this->finishPassForUser($data['active_id'], $this->test_ending_times[$test_id]['obj_fi']);
194 $can_not_be_finished = false;
195 } else {
196 $this->log->info('Max Processing time not reached for user id (' . $data['usr_id'] . ') in test with active id (' . $data['active_id'] . '). Starting time: ' . $startingTime . ' Processing time: ' . $test_obj->getProcessingTime() . ' / ' . $test_obj->getProcessingTimeInSeconds() . 's');
197 }
198 } else {
199 $this->log->info('Test object with id (' . $obj_id . ') does not exist.');
200 }
201 } else {
202 $this->log->info('Test (' . $test_id . ') has no processing time.');
203 }
204
205 if ($can_not_be_finished) {
206 $this->log->info('Test session with active id (' . $data['active_id'] . ') can not be finished by this cron job.');
207 }
208 }
209 }
210 }
211
212 protected function finishPassForUser($active_id, $obj_id): void
213 {
214 $processLocker = $this->processLockerFactory->withContextId((int) $active_id)->getLocker();
215
216 $testSession = new ilTestSession();
217 $testSession->loadFromDb($active_id);
218
219 if(ilObject::_exists($obj_id)) {
220 $test = new ilObjTest($obj_id, false);
221
222 assQuestion::_updateTestPassResults(
223 $active_id,
224 $testSession->getPass(),
225 $test->areObligationsEnabled(),
226 null,
227 $obj_id
228 );
229
230 $pass_finisher = new ilTestPassFinishTasks($active_id, $obj_id);
231 $pass_finisher->performFinishTasks($processLocker);
232
233 $this->log->info('Test session with active id (' . $active_id . ') and obj_id (' . $obj_id . ') is now finished.');
234 } else {
235 $this->log->info('Test object with id (' . $obj_id . ') does not exist.');
236 }
237 }
238}
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
hasAutoActivation()
Is to be activated on "installation", does only work for ILIAS core cron jobs.
const SCHEDULE_TYPE_DAILY
@depracated This will be replaced with an ENUM in ILIAS 9
language handling
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static getLogger(string $a_component_id)
Get component logger.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
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...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $DIC
Definition: feed.php:28
Interface ilDBInterface.
string $key
Consumer key/client ID value.
Definition: System.php:193
$query