ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilCronFinishUnfinishedTestPasses.php
Go to the documentation of this file.
1 <?php
2 require_once 'Services/Cron/classes/class.ilCronJob.php';
3 require_once 'Services/Cron/classes/class.ilCronJobResult.php';
4 require_once 'Modules/Test/classes/class.ilObjTest.php';
5 require_once 'Modules/Test/classes/class.ilTestPassFinishTasks.php';
6 require_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 
42  protected $unfinished_passes;
43 
44  protected $test_ids;
45 
46  protected $test_ending_times;
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  {
110  return self::SCHEDULE_TYPE_DAILY;
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 
155  protected function gatherUsersWithUnfinishedPasses()
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 
181  protected function getTestsFinishAndProcessingTime()
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 }
Class ilTestPassFinishTasks.
$data
Definition: storeScorm.php:23
$result
static _exists($a_id, $a_reference=false, $a_type=null)
checks if an object exists in object_data
Cron job application base class.
global $DIC
Definition: goto.php:24
Class ilCronFinishUnfinishedTestPasses.
$query
__construct(Container $dic, ilPlugin $plugin)
global $ilDB
static getLogger($a_component_id)
Get component logger.
Cron job result data container.
$test
Definition: Utf8Test.php:84