1<?php 2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4require_once 'Services/Xml/classes/class.ilSaxParser.php'; 5 6/** 7 * @author Björn Heyser <bheyser@databay.de> 8 * @version $Id$ 9 * 10 * @package Modules/Test 11 */ 12class ilObjTestXMLParser extends ilSaxParser 13{ 14 /** 15 * @var ilObjTest 16 */ 17 protected $testOBJ; 18 19 /** 20 * @var ilImportMapping 21 */ 22 protected $importMapping; 23 24 /** 25 * @return ilObjTest 26 */ 27 public function getTestOBJ() 28 { 29 return $this->testOBJ; 30 } 31 32 /** 33 * @param ilObjTest $testOBJ 34 */ 35 public function setTestOBJ($testOBJ) 36 { 37 $this->testOBJ = $testOBJ; 38 } 39 40 /** 41 * @return ilImportMapping 42 */ 43 public function getImportMapping() 44 { 45 return $this->importMapping; 46 } 47 48 /** 49 * @param ilImportMapping $importMapping 50 */ 51 public function setImportMapping($importMapping) 52 { 53 $this->importMapping = $importMapping; 54 } 55 56 public function setHandlers($xmlParser) 57 { 58 xml_set_object($xmlParser, $this); 59 xml_set_element_handler($xmlParser, 'handlerBeginTag', 'handlerEndTag'); 60 xml_set_character_data_handler($xmlParser, 'handlerCharacterData'); 61 } 62 63 public function handlerBeginTag($xmlParser, $tagName, $tagAttributes) 64 { 65 switch ($tagName) { 66 case 'RandomQuestionSetConfig': 67 $this->inRandomQuestionSetConfig = true; 68 break; 69 70 case 'RandomQuestionSetSettings': 71 if ($this->inRandomQuestionSetConfig) { 72 $this->inRandomQuestionSetSettings = true; 73 $this->cdata = ''; 74 $this->attr = $tagAttributes; 75 } 76 break; 77 78 case 'RandomQuestionStage': 79 if ($this->inRandomQuestionSetConfig) { 80 $this->inRandomQuestionStage = true; 81 } 82 break; 83 84 case 'RandomQuestionStagingPool': 85 if ($this->inRandomQuestionStage) { 86 $this->cdata = ''; 87 $this->attr = $tagAttributes; 88 } 89 break; 90 91 case 'RandomQuestionSelectionDefinitions': 92 if ($this->inRandomQuestionSetConfig) { 93 $this->inRandomQuestionSelectionDefinitions = true; 94 } 95 break; 96 97 case 'RandomQuestionSelectionDefinition': 98 if ($this->inRandomQuestionSelectionDefinitions) { 99 $this->sourcePoolDefinition = $this->getRandomQuestionSourcePoolDefinitionInstance(); 100 $this->attr = $tagAttributes; 101 } 102 break; 103 104 case 'RandomQuestionSourcePoolTitle': 105 case 'RandomQuestionSourcePoolPath': 106 if ($this->sourcePoolDefinition instanceof ilTestRandomQuestionSetSourcePoolDefinition) { 107 $this->cdata = ''; 108 } 109 break; 110 } 111 } 112 113 public function handlerEndTag($xmlParser, $tagName) 114 { 115 switch ($tagName) { 116 case 'RandomQuestionSetConfig': 117 $this->inRandomQuestionSetConfig = false; 118 break; 119 120 case 'RandomQuestionSetSettings': 121 if ($this->inRandomQuestionSetConfig) { 122 $this->importRandomQuestionSetSettings($this->attr); 123 $this->attr = null; 124 } 125 break; 126 127 case 'RandomQuestionStage': 128 if ($this->inRandomQuestionSetConfig) { 129 $this->inRandomQuestionStage = false; 130 } 131 break; 132 133 case 'RandomQuestionStagingPool': 134 if ($this->inRandomQuestionSetConfig && $this->inRandomQuestionStage) { 135 $this->importRandomQuestionStagingPool($this->attr, $this->cdata); 136 $this->attr = null; 137 $this->cdata = ''; 138 } 139 break; 140 141 case 'RandomQuestionSelectionDefinitions': 142 if ($this->inRandomQuestionSetConfig) { 143 $this->inRandomQuestionSelectionDefinitions = false; 144 } 145 break; 146 147 case 'RandomQuestionSelectionDefinition': 148 if ($this->inRandomQuestionSetConfig && $this->inRandomQuestionSelectionDefinitions) { 149 $this->importRandomQuestionSourcePoolDefinition($this->sourcePoolDefinition, $this->attr); 150 $this->sourcePoolDefinition->saveToDb(); 151 152 $this->getImportMapping()->addMapping( 153 'Modules/Test', 154 'rnd_src_pool_def', 155 $this->attr['id'], 156 $this->sourcePoolDefinition->getId() 157 ); 158 159 $this->sourcePoolDefinition = null; 160 $this->attr = null; 161 } 162 break; 163 164 case 'RandomQuestionSourcePoolTitle': 165 if ($this->sourcePoolDefinition instanceof ilTestRandomQuestionSetSourcePoolDefinition) { 166 $this->sourcePoolDefinition->setPoolTitle($this->cdata); 167 $this->cdata = ''; 168 } 169 break; 170 171 case 'RandomQuestionSourcePoolPath': 172 if ($this->sourcePoolDefinition instanceof ilTestRandomQuestionSetSourcePoolDefinition) { 173 $this->sourcePoolDefinition->setPoolPath($this->cdata); 174 $this->cdata = ''; 175 } 176 break; 177 } 178 } 179 180 public function handlerCharacterData($xmlParser, $charData) 181 { 182 if ($charData != "\n") { 183 // Replace multiple tabs with one space 184 $charData = preg_replace("/\t+/", " ", $charData); 185 186 $this->cdata .= $charData; 187 } 188 } 189 190 protected function importRandomQuestionSetSettings($attr) 191 { 192 global $DIC; 193 $tree = $DIC['tree']; 194 $ilDB = $DIC['ilDB']; 195 $ilPluginAdmin = $DIC['ilPluginAdmin']; 196 197 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetConfig.php'; 198 $questionSetConfig = new ilTestRandomQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this->testOBJ); 199 200 if (!$questionSetConfig->isValidQuestionAmountConfigurationMode($attr['amountMode'])) { 201 require_once 'Modules/Test/exceptions/class.ilTestException.php'; 202 throw new ilTestException( 203 'invalid random test question set config amount mode given: "' . $attr['amountMode'] . '"' 204 ); 205 } 206 207 $questionSetConfig->setQuestionAmountConfigurationMode($attr['amountMode']); 208 $questionSetConfig->setQuestionAmountPerTest((int) $attr['questAmount']); 209 $questionSetConfig->setPoolsWithHomogeneousScoredQuestionsRequired((bool) $attr['homogeneous']); 210 $questionSetConfig->setLastQuestionSyncTimestamp((int) $attr['synctimestamp']); 211 212 $questionSetConfig->saveToDb(); 213 } 214 215 protected function importRandomQuestionStagingPool($attr, $cdata) 216 { 217 global $DIC; 218 $ilDB = $DIC['ilDB']; 219 220 $oldPoolId = $attr['poolId']; 221 $newPoolId = $ilDB->nextId('object_data'); // yes !! 222 223 $this->getImportMapping()->addMapping( 224 'Modules/Test', 225 'pool', 226 $oldPoolId, 227 $newPoolId 228 ); 229 230 $oldQuestionIds = explode(',', $cdata); 231 232 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetStagingPoolQuestion.php'; 233 234 foreach ($oldQuestionIds as $oldQuestionId) { 235 $newQuestionId = $this->getImportMapping()->getMapping( 236 'Modules/Test', 237 'quest', 238 $oldQuestionId 239 ); 240 241 $stagingQuestion = new ilTestRandomQuestionSetStagingPoolQuestion($ilDB); 242 $stagingQuestion->setTestId($this->testOBJ->getTestId()); 243 $stagingQuestion->setPoolId($newPoolId); 244 $stagingQuestion->setQuestionId($newQuestionId); 245 246 $stagingQuestion->saveQuestionStaging(); 247 } 248 } 249 250 protected function getRandomQuestionSourcePoolDefinitionInstance() 251 { 252 global $DIC; 253 $ilDB = $DIC['ilDB']; 254 255 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinition.php'; 256 257 return new ilTestRandomQuestionSetSourcePoolDefinition($ilDB, $this->testOBJ); 258 } 259 260 protected function importRandomQuestionSourcePoolDefinition(ilTestRandomQuestionSetSourcePoolDefinition $sourcePoolDefinition, $attr) 261 { 262 $source_pool_id = (int) $attr['poolId']; 263 $effective_pool_id = (int) $this->getImportMapping()->getMapping( 264 'Modules/Test', 265 'pool', 266 $source_pool_id 267 ); 268 $sourcePoolDefinition->setPoolId($effective_pool_id); 269 270 $derive_from_obj_id = true; 271 // The ref_id might not be given in old export files, so we have to check for existence 272 if (isset($attr['ref_id']) && is_numeric($attr['ref_id'])) { 273 if ($source_pool_id === $effective_pool_id) { 274 $derive_from_obj_id = false; 275 $sourcePoolDefinition->setPoolRefId((int) $attr['ref_id']); 276 } 277 } 278 279 if ($derive_from_obj_id) { 280 $ref_ids = ilObject::_getAllReferences($effective_pool_id); 281 $ref_id = current($ref_ids); 282 $sourcePoolDefinition->setPoolRefId($ref_id ? (int) $ref_id : null); 283 } 284 285 $sourcePoolDefinition->setPoolQuestionCount((int) $attr['poolQuestCount']); 286 $sourcePoolDefinition->setQuestionAmount((int) $attr['questAmount']); 287 $sourcePoolDefinition->setSequencePosition((int) $attr['position']); 288 289 // #21330 290 if (isset($attr['tax']) && isset($attr['taxNode'])) { 291 $mappedTaxFilter = array( 292 (int) $attr['tax'] => array( 293 (int) $attr['taxNode'] 294 ) 295 ); 296 $sourcePoolDefinition->setMappedTaxonomyFilter($mappedTaxFilter); 297 } elseif (isset($attr['taxFilter']) && strlen($attr['taxFilter']) > 0) { 298 $mappedTaxFilter = unserialize($attr['taxFilter']); 299 $sourcePoolDefinition->setMappedTaxonomyFilter($mappedTaxFilter); 300 } 301 } 302} 303