ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilCronFinishUnfinishedTestPasses.php
Go to the documentation of this file.
1<?php
2require_once 'Services/Cron/classes/class.ilCronJob.php';
3require_once 'Services/Cron/classes/class.ilCronJobResult.php';
4require_once 'Modules/Test/classes/class.ilObjTest.php';
5require_once 'Modules/Test/classes/class.ilTestPassFinishTasks.php';
6require_once 'Services/Logging/classes/public/class.ilLoggerFactory.php';
7
8/* Copyright (c) 1998-2016 ILIAS open source, Extended GPL, see docs/LICENSE */
9
15{
16
20 protected $log;
21
25 protected $lng;
26
30 protected $db;
31
35 protected $obj_data_cache;
36
40 protected $now;
41
43
44 protected $test_ids;
45
47
52
56 public function __construct()
57 {
63 global $DIC;
64 $ilObjDataCache = $DIC['ilObjDataCache'];
65 $lng = $DIC['lng'];
66 $ilDB = $DIC['ilDB'];
67
68 global $DIC; /* @var ILIAS\DI\Container $DIC */
69
70 $this->log = ilLoggerFactory::getLogger('tst');
71 $this->lng = $lng;
72 $this->lng->loadLanguageModule('assessment');
73 $this->db = $ilDB;
74 $this->obj_data_cache = $ilObjDataCache;
75 $this->now = time();
76 $this->unfinished_passes = array();
77 $this->test_ids = array();
78 $this->test_ending_times = array();
79
80 require_once 'Modules/Test/classes/class.ilTestProcessLockerFactory.php';
81 $this->processLockerFactory = new ilTestProcessLockerFactory(
82 new ilSetting('assessment'),
83 $DIC->database()
84 );
85 }
86
87 public function getId()
88 {
89 return 'finish_unfinished_passes';
90 }
91
92 public function getTitle()
93 {
94 global $DIC;
95 $lng = $DIC['lng'];
96
97 return $lng->txt("finish_unfinished_passes");
98 }
99
100 public function getDescription()
101 {
102 global $DIC;
103 $lng = $DIC['lng'];
104
105 return $lng->txt("finish_unfinished_passes_desc");
106 }
107
108 public function getDefaultScheduleType()
109 {
111 }
112
113 public function getDefaultScheduleValue()
114 {
115 return;
116 }
117
118 public function hasAutoActivation()
119 {
120 return false;
121 }
122
123 public function hasFlexibleSchedule()
124 {
125 return true;
126 }
127
128 public function hasCustomSettings()
129 {
130 return true;
131 }
132
133 public function run()
134 {
135 $this->log->info('start inf cronjob...');
136
137 $result = new ilCronJobResult();
138
140 if (count($this->unfinished_passes) > 0) {
141 $this->log->info('found ' . count($this->unfinished_passes) . ' unfinished passes starting analyses.');
143 $this->processPasses();
144 } else {
145 $this->log->info('No unfinished passes found.');
146 }
147
149
150 $this->log->info(' ...finishing cronjob.');
151
152 return $result;
153 }
154
156 {
157 $query = "SELECT tst_active.active_id,
158 tst_active.tries,
159 tst_active.user_fi usr_id,
160 tst_active.test_fi test_fi,
161 usr_data.login,
162 usr_data.lastname,
163 usr_data.firstname,
164 tst_active.submitted test_finished,
165 usr_data.matriculation,
166 usr_data.active,
167 tst_active.lastindex,
168 tst_active.last_started_pass last_started
169 FROM tst_active
170 LEFT JOIN usr_data
171 ON tst_active.user_fi = usr_data.usr_id
172 WHERE IFNULL(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass
173 ";
174 $result = $this->db->query($query);
175 while ($row = $this->db->fetchAssoc($result)) {
176 $this->unfinished_passes[] = $row;
177 $this->test_ids[] = $row['test_fi'];
178 }
179 }
180
182 {
183 $query = 'SELECT test_id, obj_fi, ending_time, ending_time_enabled, processing_time, enable_processing_time FROM tst_tests WHERE ' .
184 $this->db->in('test_id', $this->test_ids, false, 'integer');
185 $result = $this->db->query($query);
186 while ($row = $this->db->fetchAssoc($result)) {
187 $this->test_ending_times[$row['test_id']] = $row;
188 }
189 $this->log->info('Gathered data for ' . count($this->test_ids) . ' test id(s) => (' . implode(',', $this->test_ids) . ')');
190 }
191
192 protected function processPasses()
193 {
194 $now = time();
195 foreach ($this->unfinished_passes as $key => $data) {
196 $test_id = $data['test_fi'];
197 $can_not_be_finished = true;
198 if (array_key_exists($test_id, $this->test_ending_times)) {
199 if ($this->test_ending_times[$test_id]['ending_time_enabled'] == 1) {
200 $this->log->info('Test (' . $test_id . ') has ending time (' . $this->test_ending_times[$test_id]['ending_time'] . ')');
201 $ending_time = $this->test_ending_times[$test_id]['ending_time'];
202 if ($ending_time < $now) {
203 $this->finishPassForUser($data['active_id'], $this->test_ending_times[$test_id]['obj_fi']);
204 $can_not_be_finished = false;
205 } else {
206 $this->log->info('Test (' . $test_id . ') ending time (' . $this->test_ending_times[$test_id]['ending_time'] . ') > now (' . $now . ') is not reached.');
207 }
208 } else {
209 $this->log->info('Test (' . $test_id . ') has no ending time.');
210 }
211 if ($this->test_ending_times[$test_id]['enable_processing_time'] == 1) {
212 $this->log->info('Test (' . $test_id . ') has processing time (' . $this->test_ending_times[$test_id]['processing_time'] . ')');
213 $obj_id = $this->test_ending_times[$test_id]['obj_fi'];
214 if(ilObject::_exists($obj_id)) {
215 $test_obj = new ilObjTest($obj_id, false);
216 $startingTime = $test_obj->getStartingTimeOfUser($data['active_id']);
217 $max_processing_time = $test_obj->isMaxProcessingTimeReached($startingTime, $data['active_id']);
218 if ($max_processing_time) {
219 $this->log->info('Max Processing time reached for user id (' . $data['usr_id'] . ') so test with active id (' . $data['active_id'] . ') will be finished.');
220 $this->finishPassForUser($data['active_id'], $this->test_ending_times[$test_id]['obj_fi']);
221 $can_not_be_finished = false;
222 } else {
223 $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');
224 }
225 } else {
226 $this->log->info('Test object with id (' . $obj_id . ') does not exist.');
227 }
228 } else {
229 $this->log->info('Test (' . $test_id . ') has no processing time.');
230 }
231
232 if ($can_not_be_finished) {
233 $this->log->info('Test session with active id (' . $data['active_id'] . ') can not be finished by this cron job.');
234 }
235 }
236 }
237 }
238
239 protected function finishPassForUser($active_id, $obj_id)
240 {
241 $processLocker = $this->processLockerFactory->withContextId((int) $active_id)->getLocker();
242
243 $testSession = new ilTestSession();
244 $testSession->loadFromDb($active_id);
245
246 if(ilObject::_exists($obj_id)) {
247 $test = new ilObjTest($obj_id, false);
248
249 assQuestion::_updateTestPassResults(
250 $active_id,
251 $testSession->getPass(),
252 $test->areObligationsEnabled(),
253 null,
254 $obj_id
255 );
256
257 $pass_finisher = new ilTestPassFinishTasks($active_id, $obj_id);
258 $pass_finisher->performFinishTasks($processLocker);
259
260 $this->log->info('Test session with active id (' . $active_id . ') and obj_id (' . $obj_id . ') is now finished.');
261 } else {
262 $this->log->info('Test object with id (' . $obj_id . ') does not exist.');
263 }
264 }
265}
$result
$test
Definition: Utf8Test.php:84
An exception for terminatinating execution or to throw for unit testing.
hasCustomSettings()
Has cron job any custom setting which can be edited?
hasAutoActivation()
Is to be activated on "installation".
Cron job result data container.
Cron job application base class.
const SCHEDULE_TYPE_DAILY
static getLogger($a_component_id)
Get component logger.
static _exists($a_id, $a_reference=false, $a_type=null)
checks if an object exists in object_data@access public
ILIAS Setting Class.
Class ilTestPassFinishTasks.
Test session handler.
global $DIC
Definition: goto.php:24
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
$query
global $ilDB
$data
Definition: storeScorm.php:23