1<?php 2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetNonAvailablePool.php'; 5/** 6 * @author Björn Heyser <bheyser@databay.de> 7 * @version $Id$ 8 * 9 * @package Modules/Test 10 */ 11class ilTestRandomQuestionSetSourcePoolDefinitionList implements Iterator 12{ 13 /** 14 * global $ilDB object instance 15 * 16 * @var ilDBInterface 17 */ 18 protected $db = null; 19 20 /** 21 * object instance of current test 22 * 23 * @var ilObjTest 24 */ 25 protected $testOBJ = null; 26 27 /** 28 * @var ilTestRandomQuestionSetSourcePoolDefinition[] 29 */ 30 private $sourcePoolDefinitions = array(); 31 32 /** 33 * @var ilTestRandomQuestionSetSourcePoolDefinitionFactory 34 */ 35 private $sourcePoolDefinitionFactory = null; 36 37 /** 38 * @var array 39 */ 40 protected $lostPools = array(); 41 42 /** 43 * @var array 44 */ 45 protected $trashedPools = array(); 46 47 /** 48 * Constructor 49 * 50 * @param ilDBInterface $db 51 * @param ilObjTest $testOBJ 52 */ 53 public function __construct(ilDBInterface $db, ilObjTest $testOBJ, ilTestRandomQuestionSetSourcePoolDefinitionFactory $sourcePoolDefinitionFactory) 54 { 55 $this->db = $db; 56 $this->testOBJ = $testOBJ; 57 $this->sourcePoolDefinitionFactory = $sourcePoolDefinitionFactory; 58 } 59 60 public function addDefinition(ilTestRandomQuestionSetSourcePoolDefinition $sourcePoolDefinition) 61 { 62 $this->sourcePoolDefinitions[ $sourcePoolDefinition->getId() ] = $sourcePoolDefinition; 63 } 64 65 protected function addLostPool(ilTestRandomQuestionSetNonAvailablePool $lostPool) 66 { 67 $this->lostPools[$lostPool->getId()] = $lostPool; 68 } 69 70 public function isLostPool($poolId) 71 { 72 return isset($this->lostPools[$poolId]); 73 } 74 75 public function hasLostPool() 76 { 77 return (bool) count($this->lostPools); 78 } 79 80 public function getLostPools() 81 { 82 return $this->lostPools; 83 } 84 85 public function getLostPool($poolId) 86 { 87 if ($this->isLostPool($poolId)) { 88 return $this->lostPools[$poolId]; 89 } 90 91 return null; 92 } 93 94 public function isTrashedPool($poolId) 95 { 96 return isset($this->trashedPools[$poolId]); 97 } 98 99 public function hasTrashedPool() 100 { 101 return (bool) count($this->trashedPools); 102 } 103 104 /** 105 * @return array 106 */ 107 public function getTrashedPools() 108 { 109 return $this->trashedPools; 110 } 111 112 /** 113 * @param array $trashedPools 114 */ 115 public function setTrashedPools($trashedPools) 116 { 117 $this->trashedPools = $trashedPools; 118 } 119 120 // hey: fixRandomTestBuildable - provide single definitions, quantities distribution likes to deal with objects 121 122 public function hasDefinition($sourcePoolDefinitionId) 123 { 124 return $this->getDefinition($sourcePoolDefinitionId) !== null; 125 } 126 127 public function getDefinition($sourcePoolDefinitionId) 128 { 129 if (isset($this->sourcePoolDefinitions[$sourcePoolDefinitionId])) { 130 return $this->sourcePoolDefinitions[$sourcePoolDefinitionId]; 131 } 132 133 return null; 134 } 135 136 public function getDefinitionBySourcePoolId($sourcePoolId) 137 { 138 foreach ($this as $definition) { 139 if ($definition->getPoolId() != $sourcePoolId) { 140 continue; 141 } 142 143 return $definition; 144 } 145 146 throw new InvalidArgumentException('invalid source pool id given'); 147 } 148 149 public function getDefinitionIds() 150 { 151 return array_keys($this->sourcePoolDefinitions); 152 } 153 154 public function getDefinitionCount() 155 { 156 return count($this->sourcePoolDefinitions); 157 } 158 // hey. 159 160 public function loadDefinitions() 161 { 162 $query = " 163 SELECT tst_rnd_quest_set_qpls.*, odat.obj_id pool_id, tree.child 164 FROM tst_rnd_quest_set_qpls 165 LEFT JOIN object_data odat 166 ON odat.obj_id = pool_fi 167 LEFT JOIN object_reference oref 168 ON oref.obj_id = pool_fi 169 LEFT JOIN tree 170 ON tree = %s 171 AND child = oref.ref_id 172 WHERE test_fi = %s 173 ORDER BY sequence_pos ASC 174 "; 175 176 $res = $this->db->queryF($query, array('integer', 'integer'), array(1, $this->testOBJ->getTestId())); 177 178 $handledDefinitions = array(); 179 $trashedPools = array(); 180 181 while ($row = $this->db->fetchAssoc($res)) { 182 $sourcePoolDefinition = $this->sourcePoolDefinitionFactory->getEmptySourcePoolDefinition(); 183 $sourcePoolDefinition->initFromArray($row); 184 185 if (!isset($handledDefinitions[$sourcePoolDefinition->getId()])) { 186 $this->addDefinition($sourcePoolDefinition); 187 $handledDefinitions[$sourcePoolDefinition->getId()] = $sourcePoolDefinition->getId(); 188 189 $trashedPool = new ilTestRandomQuestionSetNonAvailablePool(); 190 $trashedPool->assignDbRow($row); 191 192 $trashedPool->setUnavailabilityStatus( 193 ilTestRandomQuestionSetNonAvailablePool::UNAVAILABILITY_STATUS_TRASHED 194 ); 195 196 $trashedPools[$trashedPool->getId()] = $trashedPool; 197 } 198 199 if (!$this->isLostPool($row['pool_id'])) { 200 if (!$row['pool_id']) { 201 $lostPool = new ilTestRandomQuestionSetNonAvailablePool(); 202 $lostPool->assignDbRow($row); 203 204 $lostPool->setUnavailabilityStatus( 205 ilTestRandomQuestionSetNonAvailablePool::UNAVAILABILITY_STATUS_LOST 206 ); 207 208 $this->addLostPool($lostPool); 209 210 if (isset($trashedPools[$lostPool->getId()])) { 211 unset($trashedPools[$lostPool->getId()]); 212 } 213 } 214 } 215 216 if ($row['child']) { 217 unset($trashedPools[$row['pool_id']]); 218 } 219 } 220 221 $this->setTrashedPools($trashedPools); 222 } 223 224 public function saveDefinitions() 225 { 226 foreach ($this as $sourcePoolDefinition) { 227 /** @var ilTestRandomQuestionSetSourcePoolDefinition $definition */ 228 $sourcePoolDefinition->saveToDb(); 229 } 230 } 231 232 public function cloneDefinitionsForTestId($testId) 233 { 234 $definitionIdMap = array(); 235 236 foreach ($this as $definition) { 237 /** @var ilTestRandomQuestionSetSourcePoolDefinition $definition */ 238 239 $originalId = $definition->getId(); 240 $definition->cloneToDbForTestId($testId); 241 $cloneId = $definition->getId(); 242 243 $definitionIdMap[$originalId] = $cloneId; 244 } 245 246 return $definitionIdMap; 247 } 248 249 public function deleteDefinitions() 250 { 251 $query = "DELETE FROM tst_rnd_quest_set_qpls WHERE test_fi = %s"; 252 $this->db->manipulateF($query, array('integer'), array($this->testOBJ->getTestId())); 253 } 254 255 public function reindexPositions() 256 { 257 $positionIndex = array(); 258 259 foreach ($this as $definition) { 260 /** @var ilTestRandomQuestionSetSourcePoolDefinition $definition */ 261 $positionIndex[ $definition->getId() ] = $definition->getSequencePosition(); 262 } 263 264 asort($positionIndex); 265 266 $i = 1; 267 268 foreach ($positionIndex as $definitionId => $definitionPosition) { 269 $positionIndex[$definitionId] = $i++; 270 } 271 272 foreach ($this as $definition) { 273 $definition->setSequencePosition($positionIndex[$definition->getId()]); 274 } 275 } 276 277 public function getNextPosition() 278 { 279 return (count($this->sourcePoolDefinitions) + 1); 280 } 281 282 public function getInvolvedSourcePoolIds() 283 { 284 $involvedSourcePoolIds = array(); 285 286 foreach ($this as $definition) { 287 /** @var ilTestRandomQuestionSetSourcePoolDefinition $definition */ 288 $involvedSourcePoolIds[ $definition->getPoolId() ] = $definition->getPoolId(); 289 } 290 291 return array_values($involvedSourcePoolIds); 292 } 293 294 public function getQuestionAmount() 295 { 296 $questionAmount = 0; 297 298 foreach ($this as $definition) { 299 /** @var ilTestRandomQuestionSetSourcePoolDefinition $definition */ 300 $questionAmount += $definition->getQuestionAmount(); 301 } 302 303 return $questionAmount; 304 } 305 306 /** 307 * @return bool 308 */ 309 public function savedDefinitionsExist() 310 { 311 $query = "SELECT COUNT(*) cnt FROM tst_rnd_quest_set_qpls WHERE test_fi = %s"; 312 $res = $this->db->queryF($query, array('integer'), array($this->testOBJ->getTestId())); 313 314 $row = $this->db->fetchAssoc($res); 315 316 return $row['cnt'] > 0; 317 } 318 319 public function hasTaxonomyFilters() 320 { 321 foreach ($this as $definition) { 322 /** @var ilTestRandomQuestionSetSourcePoolDefinition $definition */ 323 // fau: taxFilter/typeFilter - new check for existing taxonomy filter 324 if (count($definition->getMappedTaxonomyFilter())) { 325 return true; 326 } 327 #if( $definition->getMappedFilterTaxId() && $definition->getMappedFilterTaxNodeId() ) 328 #{ 329 # return true; 330 #} 331 // fau. 332 } 333 334 return false; 335 } 336 337 // fau: taxFilter/typeFilter - check for existing type filters 338 public function hasTypeFilters() 339 { 340 foreach ($this as $definition) { 341 if (count($definition->getTypeFilter())) { 342 return true; 343 } 344 } 345 return false; 346 } 347 // fau. 348 349 public function areAllUsedPoolsAvailable() 350 { 351 if ($this->hasLostPool()) { 352 return false; 353 } 354 355 if ($this->hasTrashedPool()) { 356 return false; 357 } 358 359 return true; 360 } 361 362 /** 363 * @return ilTestRandomQuestionSetSourcePoolDefinition 364 */ 365 public function rewind() 366 { 367 return reset($this->sourcePoolDefinitions); 368 } 369 370 /** 371 * @return ilTestRandomQuestionSetSourcePoolDefinition 372 */ 373 public function current() 374 { 375 return current($this->sourcePoolDefinitions); 376 } 377 378 /** 379 * @return integer 380 */ 381 public function key() 382 { 383 return key($this->sourcePoolDefinitions); 384 } 385 386 /** 387 * @return ilTestRandomQuestionSetSourcePoolDefinition 388 */ 389 public function next() 390 { 391 return next($this->sourcePoolDefinitions); 392 } 393 394 /** 395 * @return boolean 396 */ 397 public function valid() 398 { 399 return key($this->sourcePoolDefinitions) !== null; 400 } 401 402 public function getNonAvailablePools() 403 { 404 //echo get_class($this->getTrashedPools()[0]); 405 return array_merge($this->getTrashedPools(), $this->getLostPools()); 406 } 407} 408