1<?php 2 3/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */ 4 5require_once 'Modules/Test/classes/class.ilTestParticipant.php'; 6 7/** 8 * Class ilTestParticipantList 9 * 10 * @author Björn Heyser <info@bjoernheyser.de> 11 * @version $Id$ 12 * 13 * @package Modules/Test 14 */ 15class ilTestParticipantList implements Iterator 16{ 17 /** 18 * @var ilTestParticipant[] 19 */ 20 protected $participants = array(); 21 22 /** 23 * @var ilObjTest 24 */ 25 protected $testObj; 26 27 /** 28 * @param ilObjTest $testObj 29 */ 30 public function __construct(ilObjTest $testObj) 31 { 32 $this->testObj = $testObj; 33 } 34 35 /** 36 * @return ilObjTest 37 */ 38 public function getTestObj() 39 { 40 return $this->testObj; 41 } 42 43 /** 44 * @param ilObjTest $testObj 45 */ 46 public function setTestObj($testObj) 47 { 48 $this->testObj = $testObj; 49 } 50 51 /** 52 * @param ilTestParticipant $participant 53 */ 54 public function addParticipant(ilTestParticipant $participant) 55 { 56 $this->participants[] = $participant; 57 } 58 59 public function getParticipantByUsrId($usrId) 60 { 61 foreach ($this as $participant) { 62 if ($participant->getUsrId() != $usrId) { 63 continue; 64 } 65 66 return $participant; 67 } 68 } 69 70 /** 71 * @param $activeId 72 * @return ilTestParticipant 73 */ 74 public function getParticipantByActiveId($activeId) 75 { 76 foreach ($this as $participant) { 77 if ($participant->getActiveId() != $activeId) { 78 continue; 79 } 80 81 return $participant; 82 } 83 } 84 85 /** 86 * @return bool 87 */ 88 public function hasUnfinishedPasses() 89 { 90 foreach ($this as $participant) { 91 if ($participant->hasUnfinishedPasses()) { 92 return true; 93 } 94 } 95 96 return false; 97 } 98 99 /** 100 * @return bool 101 */ 102 public function hasScorings() 103 { 104 foreach ($this as $participant) { 105 if ($participant->getScoring() instanceof ilTestParticipantScoring) { 106 return true; 107 } 108 } 109 110 return false; 111 } 112 113 public function getAllUserIds() 114 { 115 $usrIds = array(); 116 117 foreach ($this as $participant) { 118 $usrIds[] = $participant->getUsrId(); 119 } 120 121 return $usrIds; 122 } 123 124 public function getAllActiveIds() 125 { 126 $activeIds = array(); 127 128 foreach ($this as $participant) { 129 $activeIds[] = $participant->getActiveId(); 130 } 131 132 return $activeIds; 133 } 134 135 public function isActiveIdInList($activeId) 136 { 137 foreach ($this as $participant) { 138 if ($participant->getActiveId() == $activeId) { 139 return true; 140 } 141 } 142 143 return false; 144 } 145 146 public function getAccessFilteredList(callable $userAccessFilter) 147 { 148 $usrIds = call_user_func_array($userAccessFilter, [$this->getAllUserIds()]); 149 150 $accessFilteredList = new self($this->getTestObj()); 151 152 foreach ($this as $participant) { 153 if (in_array($participant->getUsrId(), $usrIds)) { 154 $participant = clone $participant; 155 $accessFilteredList->addParticipant($participant); 156 } 157 } 158 159 return $accessFilteredList; 160 } 161 162 public function current() 163 { 164 return current($this->participants); 165 } 166 public function next() 167 { 168 return next($this->participants); 169 } 170 public function key() 171 { 172 return key($this->participants); 173 } 174 public function valid() 175 { 176 return key($this->participants) !== null; 177 } 178 public function rewind() 179 { 180 return reset($this->participants); 181 } 182 183 /** 184 * @param array[] $dbRows 185 */ 186 public function initializeFromDbRows($dbRows) 187 { 188 foreach ($dbRows as $rowKey => $rowData) { 189 $participant = new ilTestParticipant(); 190 191 if ((int) $rowData['active_id']) { 192 $participant->setActiveId((int) $rowData['active_id']); 193 } 194 195 $participant->setUsrId((int) $rowData['usr_id']); 196 197 $participant->setLogin($rowData['login']); 198 $participant->setLastname($rowData['lastname']); 199 $participant->setFirstname($rowData['firstname']); 200 $participant->setMatriculation($rowData['matriculation']); 201 202 $participant->setActiveStatus((bool) $rowData['active']); 203 204 if (isset($rowData['clientip'])) { 205 $participant->setClientIp($rowData['clientip']); 206 } 207 208 $participant->setFinishedTries((int) $rowData['tries']); 209 $participant->setTestFinished((bool) $rowData['test_finished']); 210 $participant->setUnfinishedPasses((bool) $rowData['unfinished_passes']); 211 212 $this->addParticipant($participant); 213 } 214 } 215 216 /** 217 * @return ilTestParticipantList 218 */ 219 public function getScoredParticipantList() 220 { 221 require_once 'Modules/Test/classes/class.ilTestParticipantScoring.php'; 222 223 $scoredParticipantList = new self($this->getTestObj()); 224 225 global $DIC; /* @var ILIAS\DI\Container $DIC */ 226 227 $res = $DIC->database()->query($this->buildScoringsQuery()); 228 229 while ($row = $DIC->database()->fetchAssoc($res)) { 230 $scoring = new ilTestParticipantScoring(); 231 232 $scoring->setActiveId((int) $row['active_fi']); 233 $scoring->setScoredPass((int) $row['pass']); 234 235 $scoring->setAnsweredQuestions((int) $row['answeredquestions']); 236 $scoring->setTotalQuestions((int) $row['questioncount']); 237 238 $scoring->setReachedPoints((float) $row['reached_points']); 239 $scoring->setMaxPoints((float) $row['max_points']); 240 241 $scoring->setPassed((bool) $row['passed']); 242 $scoring->setFinalMark((string) $row['mark_official']); 243 244 $this->getParticipantByActiveId($row['active_fi'])->setScoring($scoring); 245 246 $scoredParticipantList->addParticipant( 247 $this->getParticipantByActiveId($row['active_fi']) 248 ); 249 } 250 251 return $scoredParticipantList; 252 } 253 254 public function buildScoringsQuery() 255 { 256 global $DIC; /* @var ILIAS\DI\Container $DIC */ 257 258 $IN_activeIds = $DIC->database()->in( 259 'tres.active_fi', 260 $this->getAllActiveIds(), 261 false, 262 'integer' 263 ); 264 265 if (false && !$this->getTestObj()->isDynamicTest()) { // BH: keep for the moment 266 $closedScoringsOnly = " 267 INNER JOIN tst_active tact 268 ON tact.active_id = tres.active_fi 269 AND tact.last_finished_pass = tact.last_started_pass 270 "; 271 } else { 272 $closedScoringsOnly = ''; 273 } 274 275 $query = " 276 SELECT * FROM tst_result_cache tres 277 278 INNER JOIN tst_pass_result pres 279 ON pres.active_fi = tres.active_fi 280 AND pres.pass = tres.pass 281 282 $closedScoringsOnly 283 284 WHERE $IN_activeIds 285 "; 286 287 return $query; 288 } 289 290 public function getParticipantsTableRows() 291 { 292 $rows = array(); 293 294 foreach ($this as $participant) { 295 $row = array( 296 'usr_id' => $participant->getUsrId(), 297 'active_id' => $participant->getActiveId(), 298 'login' => $participant->getLogin(), 299 'clientip' => $participant->getClientIp(), 300 'firstname' => $participant->getFirstname(), 301 'lastname' => $participant->getLastname(), 302 'name' => $this->buildFullname($participant), 303 'started' => ($participant->getActiveId() > 0) ? 1 : 0, 304 'unfinished' => $participant->hasUnfinishedPasses() ? 1 : 0, 305 'finished' => $participant->isTestFinished() ? 1 : 0, 306 'access' => $this->lookupLastAccess($participant->getActiveId()), 307 'tries' => $this->lookupNrOfTries($participant->getActiveId()) 308 ); 309 310 $rows[] = $row; 311 } 312 313 return $rows; 314 } 315 316 public function getScoringsTableRows() 317 { 318 $rows = array(); 319 320 foreach ($this as $participant) { 321 if (!$participant->hasScoring()) { 322 continue; 323 } 324 325 $row = array( 326 'usr_id' => $participant->getUsrId(), 327 'active_id' => $participant->getActiveId(), 328 'login' => $participant->getLogin(), 329 'firstname' => $participant->getFirstname(), 330 'lastname' => $participant->getLastname(), 331 'name' => $this->buildFullname($participant) 332 ); 333 334 if ($participant->getScoring()) { 335 $row['scored_pass'] = $participant->getScoring()->getScoredPass(); 336 $row['answered_questions'] = $participant->getScoring()->getAnsweredQuestions(); 337 $row['total_questions'] = $participant->getScoring()->getTotalQuestions(); 338 $row['reached_points'] = $participant->getScoring()->getReachedPoints(); 339 $row['max_points'] = $participant->getScoring()->getMaxPoints(); 340 $row['percent_result'] = $participant->getScoring()->getPercentResult(); 341 $row['passed_status'] = $participant->getScoring()->isPassed(); 342 $row['final_mark'] = $participant->getScoring()->getFinalMark(); 343 344 $row['pass_finished'] = ilObjTest::lookupLastTestPassAccess( 345 $participant->getActiveId(), 346 $participant->getScoring()->getScoredPass() 347 ); 348 } 349 350 $rows[] = $row; 351 } 352 353 return $rows; 354 } 355 356 /** 357 * @param integer $activeId 358 * @return int|null 359 */ 360 public function lookupNrOfTries($activeId) 361 { 362 $maxPassIndex = ilObjTest::_getMaxPass($activeId); 363 364 if ($maxPassIndex !== null) { 365 $nrOfTries = $maxPassIndex + 1; 366 return $nrOfTries; 367 } 368 369 return null; 370 } 371 372 /** 373 * @param integer $activeId 374 * @return string 375 */ 376 protected function lookupLastAccess($activeId) 377 { 378 if (!$activeId) { 379 return ''; 380 } 381 382 return $this->getTestObj()->_getLastAccess($activeId); 383 } 384 385 /** 386 * @param ilTestParticipant $participant 387 * @return string 388 */ 389 protected function buildFullname(ilTestParticipant $participant) 390 { 391 if ($this->getTestObj()->getFixedParticipants() && !$participant->getActiveId()) { 392 return $this->buildInviteeFullname($participant); 393 } 394 395 return $this->buildParticipantsFullname($participant); 396 } 397 398 /** 399 * @param ilTestParticipant $participant 400 * @return string 401 */ 402 protected function buildInviteeFullname(ilTestParticipant $participant) 403 { 404 global $DIC; /* @var ILIAS\DI\Container $DIC */ 405 406 if (strlen($participant->getFirstname() . $participant->getLastname()) == 0) { 407 return $DIC->language()->txt("deleted_user"); 408 } 409 410 if ($this->getTestObj()->getAnonymity()) { 411 return $DIC->language()->txt('anonymous'); 412 } 413 414 return trim($participant->getLastname() . ", " . $participant->getFirstname()); 415 } 416 417 /** 418 * @param ilTestParticipant $participant 419 * @return string 420 */ 421 protected function buildParticipantsFullname(ilTestParticipant $participant) 422 { 423 require_once 'Modules/Test/classes/class.ilObjTestAccess.php'; 424 return ilObjTestAccess::_getParticipantData($participant->getActiveId()); 425 } 426} 427