| Total Complexity | 157 | 
| Total Lines | 718 | 
| Duplicated Lines | 0 % | 
| Changes | 1 | ||
| Bugs | 0 | Features | 0 | 
Complex classes like Cc13Quiz often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Cc13Quiz, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 4 | class Cc13Quiz extends Cc13Entities  | 
            ||
| 5 | { | 
            ||
| 6 | public function generateData()  | 
            ||
| 7 |     { | 
            ||
| 8 | $data = [];  | 
            ||
| 9 | $instances = $this->generateInstances();  | 
            ||
| 10 |         if (!empty($instances)) { | 
            ||
| 11 |             foreach ($instances as $instance) { | 
            ||
| 12 |                 if ($instance['is_question_bank'] == 0) { | 
            ||
| 13 | $data[] = $this->getQuizData($instance);  | 
            ||
| 14 | }  | 
            ||
| 15 | }  | 
            ||
| 16 | }  | 
            ||
| 17 | |||
| 18 | return $data;  | 
            ||
| 19 | }  | 
            ||
| 20 | |||
| 21 | public function storeQuiz($quiz)  | 
            ||
| 22 |     { | 
            ||
| 23 | $courseInfo = api_get_course_info();  | 
            ||
| 24 | $exercise = new Exercise($courseInfo['real_id']);  | 
            ||
| 25 | $title = Exercise::format_title_variable($quiz['title']);  | 
            ||
| 26 | $exercise->updateTitle($title);  | 
            ||
| 27 |         $exercise->updateDescription(''); | 
            ||
| 28 | $exercise->updateAttempts($quiz['max_attempts']);  | 
            ||
| 29 | $exercise->updateFeedbackType(0);  | 
            ||
| 30 | |||
| 31 | $exercise->setRandom(0);  | 
            ||
| 32 | $exercise->updateRandomAnswers(!empty($moduleValues['shuffleanswers']));  | 
            ||
| 
                                                                                                    
                        
                         | 
                |||
| 33 | $exercise->updateExpiredTime((int) $quiz['timelimit']);  | 
            ||
| 34 | $exercise->updateType(1);  | 
            ||
| 35 | |||
| 36 | // Create the new Quiz  | 
            ||
| 37 | $exercise->save();  | 
            ||
| 38 | |||
| 39 |         if (!empty($quiz['questions'])) { | 
            ||
| 40 |             foreach ($quiz['questions'] as $question) { | 
            ||
| 41 | $qtype = $question['type'];  | 
            ||
| 42 | |||
| 43 | $types = ['unique_answer' => 1, 'multiple_answer' => 2];  | 
            ||
| 44 | $questionType = $types[$qtype];  | 
            ||
| 45 | |||
| 46 | $questionInstance = Question::getInstance($questionType);  | 
            ||
| 47 |                 if (empty($questionInstance)) { | 
            ||
| 48 | continue;  | 
            ||
| 49 | }  | 
            ||
| 50 | |||
| 51 | $questionInstance->updateTitle($question['title']);  | 
            ||
| 52 | $questionText = '';  | 
            ||
| 53 | |||
| 54 | // Replace the path from @@PLUGINFILE@@ to a correct chamilo path  | 
            ||
| 55 | $questionText = str_replace(  | 
            ||
| 56 | '@@PLUGINFILE@@',  | 
            ||
| 57 | '/courses/'.$courseInfo['path'].'/document/moodle',  | 
            ||
| 58 | $questionText  | 
            ||
| 59 | );  | 
            ||
| 60 | |||
| 61 | $questionInstance->updateDescription($questionText);  | 
            ||
| 62 | $questionInstance->updateLevel(1);  | 
            ||
| 63 | $questionInstance->updateCategory(0);  | 
            ||
| 64 | |||
| 65 | //Save normal question if NOT media  | 
            ||
| 66 |                 if ($questionInstance->type != MEDIA_QUESTION) { | 
            ||
| 67 | $questionInstance->save($exercise);  | 
            ||
| 68 | // modify the exercise  | 
            ||
| 69 | $exercise->addToList($questionInstance->iid);  | 
            ||
| 70 | $exercise->update_question_positions();  | 
            ||
| 71 | }  | 
            ||
| 72 | |||
| 73 |                 if ($qtype == 'unique_answer') { | 
            ||
| 74 | $objAnswer = new Answer($questionInstance->iid);  | 
            ||
| 75 | $questionWeighting = 0;  | 
            ||
| 76 |                     foreach ($question['answers'] as $slot => $answerValues) { | 
            ||
| 77 | $correct = $answerValues['score'] ? (int) $answerValues['score'] : 0;  | 
            ||
| 78 | $answer = $answerValues['title'];  | 
            ||
| 79 | $comment = $answerValues['feedback'];  | 
            ||
| 80 | $weighting = $answerValues['score'];  | 
            ||
| 81 | $weighting = abs($weighting);  | 
            ||
| 82 |                         if ($weighting > 0) { | 
            ||
| 83 | $questionWeighting += $weighting;  | 
            ||
| 84 | }  | 
            ||
| 85 | $goodAnswer = $correct ? true : false;  | 
            ||
| 86 | |||
| 87 | $objAnswer->createAnswer(  | 
            ||
| 88 | $answer,  | 
            ||
| 89 | $goodAnswer,  | 
            ||
| 90 | $comment,  | 
            ||
| 91 | $weighting,  | 
            ||
| 92 | $slot + 1,  | 
            ||
| 93 | null,  | 
            ||
| 94 | null,  | 
            ||
| 95 | ''  | 
            ||
| 96 | );  | 
            ||
| 97 | }  | 
            ||
| 98 | // saves the answers into the data base  | 
            ||
| 99 | $objAnswer->save();  | 
            ||
| 100 | // sets the total weighting of the question  | 
            ||
| 101 | $questionInstance->updateWeighting($questionWeighting);  | 
            ||
| 102 | $questionInstance->save($exercise);  | 
            ||
| 103 |                 } else { | 
            ||
| 104 | $objAnswer = new Answer($questionInstance->iid);  | 
            ||
| 105 | $questionWeighting = 0;  | 
            ||
| 106 |                     foreach ($question['answers'] as $slot => $answerValues) { | 
            ||
| 107 | $answer = $answerValues['title'];  | 
            ||
| 108 | $comment = $answerValues['feedback'];  | 
            ||
| 109 | $weighting = $answerValues['score'];  | 
            ||
| 110 |                         if ($weighting > 0) { | 
            ||
| 111 | $questionWeighting += $weighting;  | 
            ||
| 112 | }  | 
            ||
| 113 | $goodAnswer = $weighting > 0;  | 
            ||
| 114 | |||
| 115 | $objAnswer->createAnswer(  | 
            ||
| 116 | $answer,  | 
            ||
| 117 | $goodAnswer,  | 
            ||
| 118 | $comment,  | 
            ||
| 119 | $weighting,  | 
            ||
| 120 | $slot + 1,  | 
            ||
| 121 | null,  | 
            ||
| 122 | null,  | 
            ||
| 123 | ''  | 
            ||
| 124 | );  | 
            ||
| 125 | }  | 
            ||
| 126 | |||
| 127 | // saves the answers into the data base  | 
            ||
| 128 | $objAnswer->save();  | 
            ||
| 129 | // sets the total weighting of the question  | 
            ||
| 130 | $questionInstance->updateWeighting($questionWeighting);  | 
            ||
| 131 | $questionInstance->save($exercise);  | 
            ||
| 132 | }  | 
            ||
| 133 | }  | 
            ||
| 134 | }  | 
            ||
| 135 | }  | 
            ||
| 136 | |||
| 137 | public function storeQuizzes($quizzes)  | 
            ||
| 138 |     { | 
            ||
| 139 |         if (!empty($quizzes)) { | 
            ||
| 140 |             foreach ($quizzes as $quiz) { | 
            ||
| 141 | $this->storeQuiz($quiz);  | 
            ||
| 142 | }  | 
            ||
| 143 | }  | 
            ||
| 144 | }  | 
            ||
| 145 | |||
| 146 | public function getQuizData($instance)  | 
            ||
| 147 |     { | 
            ||
| 148 | $values = [];  | 
            ||
| 149 |         if (!empty($instance)) { | 
            ||
| 150 | $questions = [];  | 
            ||
| 151 |             if (!empty($instance['questions'])) { | 
            ||
| 152 |                 foreach ($instance['questions'] as $question) { | 
            ||
| 153 | $questions[$question['id']] = [  | 
            ||
| 154 | 'title' => $question['title'],  | 
            ||
| 155 | 'type' => $question['qtype'],  | 
            ||
| 156 | 'ponderation' => $question['defaultgrade'],  | 
            ||
| 157 | 'answers' => $question['answers'],  | 
            ||
| 158 | ];  | 
            ||
| 159 | }  | 
            ||
| 160 | }  | 
            ||
| 161 | $values = [  | 
            ||
| 162 | 'id' => $instance['id'],  | 
            ||
| 163 | 'title' => $instance['title'],  | 
            ||
| 164 | 'timelimit' => $instance['options']['timelimit'],  | 
            ||
| 165 | 'max_attempts' => $instance['options']['max_attempts'],  | 
            ||
| 166 | 'questions' => $questions,  | 
            ||
| 167 | ];  | 
            ||
| 168 | }  | 
            ||
| 169 | |||
| 170 | return $values;  | 
            ||
| 171 | }  | 
            ||
| 172 | |||
| 173 | private function generateInstances()  | 
            ||
| 174 |     { | 
            ||
| 175 | $lastInstanceId = 0;  | 
            ||
| 176 | $lastQuestionId = 0;  | 
            ||
| 177 | $lastAnswerId = 0;  | 
            ||
| 178 | |||
| 179 | $instances = [];  | 
            ||
| 180 | |||
| 181 | $types = [TOOL_TYPE_QUIZ];  | 
            ||
| 182 | |||
| 183 |         foreach ($types as $type) { | 
            ||
| 184 |             if (!empty(Cc1p3Convert::$instances['instances'][$type])) { | 
            ||
| 185 |                 foreach (Cc1p3Convert::$instances['instances'][$type] as $instance) { | 
            ||
| 186 |                     if ($type == TOOL_TYPE_QUIZ) { | 
            ||
| 187 | $is_question_bank = 0;  | 
            ||
| 188 |                     } else { | 
            ||
| 189 | $is_question_bank = 1;  | 
            ||
| 190 | }  | 
            ||
| 191 | |||
| 192 | $assessmentFile = $this->getExternalXml($instance['resource_indentifier']);  | 
            ||
| 193 | |||
| 194 |                     if (!empty($assessmentFile)) { | 
            ||
| 195 | $assessment = $this->loadXmlResource(Cc1p3Convert::$pathToManifestFolder.DIRECTORY_SEPARATOR.$assessmentFile);  | 
            ||
| 196 | |||
| 197 |                         if (!empty($assessment)) { | 
            ||
| 198 | $replaceValues = ['unlimited' => 0];  | 
            ||
| 199 | |||
| 200 | $questions = $this->getQuestions($assessment, $lastQuestionId, $lastAnswerId, dirname($assessmentFile), $is_question_bank);  | 
            ||
| 201 | $questionCount = count($questions);  | 
            ||
| 202 | |||
| 203 |                             if (!empty($questionCount)) { | 
            ||
| 204 | $lastInstanceId++;  | 
            ||
| 205 | |||
| 206 | $instances[$instance['resource_indentifier']]['questions'] = $questions;  | 
            ||
| 207 | $instances[$instance['resource_indentifier']]['id'] = $lastInstanceId;  | 
            ||
| 208 | $instances[$instance['resource_indentifier']]['title'] = $instance['title'];  | 
            ||
| 209 | $instances[$instance['resource_indentifier']]['is_question_bank'] = $is_question_bank;  | 
            ||
| 210 | $instances[$instance['resource_indentifier']]['options']['timelimit'] = $this->getGlobalConfig($assessment, 'qmd_timelimit', 0);  | 
            ||
| 211 | $instances[$instance['resource_indentifier']]['options']['max_attempts'] = $this->getGlobalConfig($assessment, 'cc_maxattempts', 0, $replaceValues);  | 
            ||
| 212 | }  | 
            ||
| 213 | }  | 
            ||
| 214 | }  | 
            ||
| 215 | }  | 
            ||
| 216 | }  | 
            ||
| 217 | }  | 
            ||
| 218 | |||
| 219 | return $instances;  | 
            ||
| 220 | }  | 
            ||
| 221 | |||
| 222 | private function getGlobalConfig($assessment, $option, $defaultValue, $replaceValues = '')  | 
            ||
| 223 |     { | 
            ||
| 224 | $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());  | 
            ||
| 225 |         $metadata = $xpath->query('/xmlns:questestinterop/xmlns:assessment/xmlns:qtimetadata/xmlns:qtimetadatafield'); | 
            ||
| 226 | |||
| 227 |         foreach ($metadata as $field) { | 
            ||
| 228 |             $fieldLabel = $xpath->query('xmlns:fieldlabel', $field); | 
            ||
| 229 | $fieldLabel = !empty($fieldLabel->item(0)->nodeValue) ? $fieldLabel->item(0)->nodeValue : '';  | 
            ||
| 230 | |||
| 231 |             if (strtolower($fieldLabel) == strtolower($option)) { | 
            ||
| 232 |                 $fieldEntry = $xpath->query('xmlns:fieldentry', $field); | 
            ||
| 233 | $response = !empty($fieldEntry->item(0)->nodeValue) ? $fieldEntry->item(0)->nodeValue : '';  | 
            ||
| 234 | }  | 
            ||
| 235 | }  | 
            ||
| 236 | |||
| 237 | $response = !empty($response) ? trim($response) : '';  | 
            ||
| 238 | |||
| 239 |         if (!empty($replaceValues)) { | 
            ||
| 240 |             foreach ($replaceValues as $key => $value) { | 
            ||
| 241 | $response = ($key == $response) ? $value : $response;  | 
            ||
| 242 | }  | 
            ||
| 243 | }  | 
            ||
| 244 | |||
| 245 | $response = empty($response) ? $defaultValue : $response;  | 
            ||
| 246 | |||
| 247 | return $response;  | 
            ||
| 248 | }  | 
            ||
| 249 | |||
| 250 | private function getQuestions($assessment, &$lastQuestionId, &$last_answer_id, $rootPath, $is_question_bank)  | 
            ||
| 251 |     { | 
            ||
| 252 | $questions = [];  | 
            ||
| 253 | |||
| 254 | $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());  | 
            ||
| 255 | |||
| 256 |         if (!$is_question_bank) { | 
            ||
| 257 |             $questionsItems = $xpath->query('/xmlns:questestinterop/xmlns:assessment/xmlns:section/xmlns:item'); | 
            ||
| 258 |         } else { | 
            ||
| 259 |             $questionsItems = $xpath->query('/xmlns:questestinterop/xmlns:objectbank/xmlns:item'); | 
            ||
| 260 | }  | 
            ||
| 261 | |||
| 262 |         foreach ($questionsItems as $question_item) { | 
            ||
| 263 |             $countQuestions = $xpath->evaluate('count(xmlns:presentation/xmlns:flow/xmlns:material/xmlns:mattext)', $question_item); | 
            ||
| 264 | |||
| 265 |             if ($countQuestions == 0) { | 
            ||
| 266 |                 $questionTitle = $xpath->query('xmlns:presentation/xmlns:material/xmlns:mattext', $question_item); | 
            ||
| 267 |             } else { | 
            ||
| 268 |                 $questionTitle = $xpath->query('xmlns:presentation/xmlns:flow/xmlns:material/xmlns:mattext', $question_item); | 
            ||
| 269 | }  | 
            ||
| 270 | |||
| 271 | $questionTitle = !empty($questionTitle->item(0)->nodeValue) ? $questionTitle->item(0)->nodeValue : '';  | 
            ||
| 272 | |||
| 273 |             $questionIdentifier = $xpath->query('@ident', $question_item); | 
            ||
| 274 | $questionIdentifier = !empty($questionIdentifier->item(0)->nodeValue) ? $questionIdentifier->item(0)->nodeValue : '';  | 
            ||
| 275 | |||
| 276 |             if (!empty($questionIdentifier)) { | 
            ||
| 277 | $questionType = $this->getQuestionType($questionIdentifier, $assessment);  | 
            ||
| 278 | |||
| 279 |                 if (!empty($questionType['qtype'])) { | 
            ||
| 280 | $lastQuestionId++;  | 
            ||
| 281 | |||
| 282 | $questions[$questionIdentifier]['id'] = $lastQuestionId;  | 
            ||
| 283 | |||
| 284 | $questionTitle = $this->updateSources($questionTitle, $rootPath);  | 
            ||
| 285 |                     $questionTitle = !empty($questionTitle) ? str_replace("%24", "\$", $this->includeTitles($questionTitle)) : ''; | 
            ||
| 286 | |||
| 287 |                     $questionname = $xpath->query('@title', $question_item); | 
            ||
| 288 | $questionname = !empty($questionname->item(0)->nodeValue) ? $questionname->item(0)->nodeValue : '';  | 
            ||
| 289 | |||
| 290 | $questions[$questionIdentifier]['title'] = $questionTitle;  | 
            ||
| 291 | $questions[$questionIdentifier]['name'] = $questionname;  | 
            ||
| 292 | $questions[$questionIdentifier]['identifier'] = $questionIdentifier;  | 
            ||
| 293 | $questions[$questionIdentifier]['qtype'] = $questionType['qtype'];  | 
            ||
| 294 | $questions[$questionIdentifier]['cc_type'] = $questionType['cc'];  | 
            ||
| 295 | $questions[$questionIdentifier]['feedback'] = $this->getGeneralFeedback($assessment, $questionIdentifier);  | 
            ||
| 296 | $questions[$questionIdentifier]['defaultgrade'] = $this->getDefaultgrade($assessment, $questionIdentifier);  | 
            ||
| 297 | $questions[$questionIdentifier]['answers'] = $this->getAnswers($questionIdentifier, $assessment, $lastAnswerId);  | 
            ||
| 298 | }  | 
            ||
| 299 | }  | 
            ||
| 300 | }  | 
            ||
| 301 | |||
| 302 | $questions = !empty($questions) ? $questions : '';  | 
            ||
| 303 | |||
| 304 | return $questions;  | 
            ||
| 305 | }  | 
            ||
| 306 | |||
| 307 | private function getDefaultgrade($assessment, $questionIdentifier)  | 
            ||
| 308 |     { | 
            ||
| 309 | $result = 1;  | 
            ||
| 310 | $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());  | 
            ||
| 311 | $query = '//xmlns:item[@ident="'.$questionIdentifier.'"]';  | 
            ||
| 312 | $query .= '//xmlns:qtimetadatafield[xmlns:fieldlabel="cc_weighting"]/xmlns:fieldentry';  | 
            ||
| 313 | $defgrade = $xpath->query($query);  | 
            ||
| 314 |         if (!empty($defgrade) && ($defgrade->length > 0)) { | 
            ||
| 315 | $resp = (int) $defgrade->item(0)->nodeValue;  | 
            ||
| 316 |             if ($resp >= 0 && $resp <= 99) { | 
            ||
| 317 | $result = $resp;  | 
            ||
| 318 | }  | 
            ||
| 319 | }  | 
            ||
| 320 | |||
| 321 | return $result;  | 
            ||
| 322 | }  | 
            ||
| 323 | |||
| 324 | private function getGeneralFeedback($assessment, $questionIdentifier)  | 
            ||
| 325 |     { | 
            ||
| 326 | $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());  | 
            ||
| 327 | |||
| 328 |         $respconditions = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition'); | 
            ||
| 329 | |||
| 330 |         if (!empty($respconditions)) { | 
            ||
| 331 |             foreach ($respconditions as $respcondition) { | 
            ||
| 332 |                 $continue = $respcondition->getAttributeNode('continue'); | 
            ||
| 333 | $continue = !empty($continue->nodeValue) ? strtolower($continue->nodeValue) : '';  | 
            ||
| 334 | |||
| 335 |                 if ($continue == 'yes') { | 
            ||
| 336 |                     $displayFeedback = $xpath->query('xmlns:displayfeedback', $respcondition); | 
            ||
| 337 | |||
| 338 |                     if (!empty($displayFeedback)) { | 
            ||
| 339 |                         foreach ($displayFeedback as $feedback) { | 
            ||
| 340 |                             $feedbackIdentifier = $feedback->getAttributeNode('linkrefid'); | 
            ||
| 341 | $feedbackIdentifier = !empty($feedbackIdentifier->nodeValue) ? $feedbackIdentifier->nodeValue : '';  | 
            ||
| 342 | |||
| 343 |                             if (!empty($feedbackIdentifier)) { | 
            ||
| 344 | $feedbackIdentifiers[] = $feedbackIdentifier;  | 
            ||
| 345 | }  | 
            ||
| 346 | }  | 
            ||
| 347 | }  | 
            ||
| 348 | }  | 
            ||
| 349 | }  | 
            ||
| 350 | }  | 
            ||
| 351 | |||
| 352 | $feedback = '';  | 
            ||
| 353 | $feedbackIdentifiers = empty($feedbackIdentifiers) ? '' : $feedbackIdentifiers;  | 
            ||
| 354 | |||
| 355 |         if (!empty($feedbackIdentifiers)) { | 
            ||
| 356 |             foreach ($feedbackIdentifiers as $feedbackIdentifier) { | 
            ||
| 357 |                 $feedbacks = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:itemfeedback[@ident="'.$feedbackIdentifier.'"]/xmlns:flow_mat/xmlns:material/xmlns:mattext'); | 
            ||
| 358 | $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue.' ' : '';  | 
            ||
| 359 | }  | 
            ||
| 360 | }  | 
            ||
| 361 | |||
| 362 | return $feedback;  | 
            ||
| 363 | }  | 
            ||
| 364 | |||
| 365 | private function getFeedback($assessment, $identifier, $itemIdentifier, $questionType)  | 
            ||
| 366 |     { | 
            ||
| 367 | $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());  | 
            ||
| 368 | |||
| 369 |         $resourceProcessing = $xpath->query('//xmlns:item[@ident="'.$itemIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition'); | 
            ||
| 370 | |||
| 371 |         if (!empty($resourceProcessing)) { | 
            ||
| 372 |             foreach ($resourceProcessing as $response) { | 
            ||
| 373 |                 $varequal = $xpath->query('xmlns:conditionvar/xmlns:varequal', $response); | 
            ||
| 374 | $varequal = !empty($varequal->item(0)->nodeValue) ? $varequal->item(0)->nodeValue : '';  | 
            ||
| 375 | |||
| 376 |                 if (strtolower($varequal) == strtolower($identifier) || ($questionType == CC_QUIZ_ESSAY)) { | 
            ||
| 377 |                     $displayFeedback = $xpath->query('xmlns:displayfeedback', $response); | 
            ||
| 378 | |||
| 379 |                     if (!empty($displayFeedback)) { | 
            ||
| 380 |                         foreach ($displayFeedback as $feedback) { | 
            ||
| 381 |                             $feedbackIdentifier = $feedback->getAttributeNode('linkrefid'); | 
            ||
| 382 | $feedbackIdentifier = !empty($feedbackIdentifier->nodeValue) ? $feedbackIdentifier->nodeValue : '';  | 
            ||
| 383 | |||
| 384 |                             if (!empty($feedbackIdentifier)) { | 
            ||
| 385 | $feedbackIdentifiers[] = $feedbackIdentifier;  | 
            ||
| 386 | }  | 
            ||
| 387 | }  | 
            ||
| 388 | }  | 
            ||
| 389 | }  | 
            ||
| 390 | }  | 
            ||
| 391 | }  | 
            ||
| 392 | |||
| 393 | $feedback = '';  | 
            ||
| 394 | $feedbackIdentifiers = empty($feedbackIdentifiers) ? '' : $feedbackIdentifiers;  | 
            ||
| 395 | |||
| 396 |         if (!empty($feedbackIdentifiers)) { | 
            ||
| 397 |             foreach ($feedbackIdentifiers as $feedbackIdentifier) { | 
            ||
| 398 |                 $feedbacks = $xpath->query('//xmlns:item[@ident="'.$itemIdentifier.'"]/xmlns:itemfeedback[@ident="'.$feedbackIdentifier.'"]/xmlns:flow_mat/xmlns:material/xmlns:mattext'); | 
            ||
| 399 | $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue.' ' : '';  | 
            ||
| 400 | }  | 
            ||
| 401 | }  | 
            ||
| 402 | |||
| 403 | return $feedback;  | 
            ||
| 404 | }  | 
            ||
| 405 | |||
| 406 | private function getAnswersFib($questionIdentifier, $identifier, $assessment, &$lastAnswerId)  | 
            ||
| 407 |     { | 
            ||
| 408 | $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());  | 
            ||
| 409 | |||
| 410 | $correctanswersfib = [];  | 
            ||
| 411 | $incorrectanswersfib = [];  | 
            ||
| 412 | |||
| 413 |         $responseItems = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition'); | 
            ||
| 414 | |||
| 415 |         $correctrespcond = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition/xmlns:setvar[text()="100"]/..'); | 
            ||
| 416 |         $correctanswers = $xpath->query('xmlns:conditionvar/xmlns:varequal', $correctrespcond->item(0)); | 
            ||
| 417 | |||
| 418 | // Correct answers.  | 
            ||
| 419 |         foreach ($correctanswers as $correctans) { | 
            ||
| 420 | $answertitle = !empty($correctans->nodeValue) ? $correctans->nodeValue : '';  | 
            ||
| 421 |             if (empty($answertitle)) { | 
            ||
| 422 | continue;  | 
            ||
| 423 | }  | 
            ||
| 424 | |||
| 425 | $lastAnswerId++;  | 
            ||
| 426 | |||
| 427 | $correctanswersfib[$answertitle] = [  | 
            ||
| 428 | 'id' => $lastAnswerId,  | 
            ||
| 429 | 'title' => $answertitle,  | 
            ||
| 430 | 'score' => 1,  | 
            ||
| 431 | 'feedback' => '',  | 
            ||
| 432 | 'case' => 0, ];  | 
            ||
| 433 | }  | 
            ||
| 434 | |||
| 435 | // Handle incorrect answers and feedback for all items.  | 
            ||
| 436 |         foreach ($responseItems as $response_item) { | 
            ||
| 437 |             $setvar = $xpath->query('xmlns:setvar', $response_item); | 
            ||
| 438 |             if (!empty($setvar->length) && $setvar->item(0)->nodeValue == '100') { | 
            ||
| 439 | // Skip the correct answer responsecondition.  | 
            ||
| 440 | continue;  | 
            ||
| 441 | }  | 
            ||
| 442 | |||
| 443 |             $varequal = $xpath->query('xmlns:conditionvar/xmlns:varequal', $response_item); | 
            ||
| 444 |             if (empty($varequal->length)) { | 
            ||
| 445 | // Skip respcondition elements that don't have varequal containing an answer  | 
            ||
| 446 | continue;  | 
            ||
| 447 | }  | 
            ||
| 448 | $answerTitle = !empty($varequal->item(0)->nodeValue) ? $varequal->item(0)->nodeValue : '';  | 
            ||
| 449 | |||
| 450 |             $displayFeedback = $xpath->query('xmlns:displayfeedback', $response_item); | 
            ||
| 451 | |||
| 452 | unset($feedbackIdentifiers);  | 
            ||
| 453 | |||
| 454 |             if (!empty($displayFeedback)) { | 
            ||
| 455 |                 foreach ($displayFeedback as $feedback) { | 
            ||
| 456 |                     $feedbackIdentifier = $feedback->getAttributeNode('linkrefid'); | 
            ||
| 457 | $feedbackIdentifier = !empty($feedbackIdentifier->nodeValue) ? $feedbackIdentifier->nodeValue : '';  | 
            ||
| 458 | |||
| 459 |                     if (!empty($feedbackIdentifier)) { | 
            ||
| 460 | $feedbackIdentifiers[] = $feedbackIdentifier;  | 
            ||
| 461 | }  | 
            ||
| 462 | }  | 
            ||
| 463 | }  | 
            ||
| 464 | |||
| 465 | $feedback = '';  | 
            ||
| 466 | $feedbackIdentifiers = empty($feedbackIdentifiers) ? '' : $feedbackIdentifiers;  | 
            ||
| 467 | |||
| 468 |             if (!empty($feedbackIdentifiers)) { | 
            ||
| 469 |                 foreach ($feedbackIdentifiers as $feedbackIdentifier) { | 
            ||
| 470 |                     $feedbacks = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:itemfeedback[@ident="'.$feedbackIdentifier.'"]/xmlns:flow_mat/xmlns:material/xmlns:mattext'); | 
            ||
| 471 | $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue.' ' : '';  | 
            ||
| 472 | }  | 
            ||
| 473 | }  | 
            ||
| 474 | |||
| 475 |             if (array_key_exists($answerTitle, $correctanswersfib)) { | 
            ||
| 476 | // Already a correct answer, just need the feedback for the correct answer.  | 
            ||
| 477 | $correctanswerfib[$answerTitle]['feedback'] = $feedback;  | 
            ||
| 478 |             } else { | 
            ||
| 479 | // Need to add an incorrect answer.  | 
            ||
| 480 | $lastAnswerId++;  | 
            ||
| 481 | $incorrectanswersfib[] = [  | 
            ||
| 482 | 'id' => $lastAnswerId,  | 
            ||
| 483 | 'title' => $answerTitle,  | 
            ||
| 484 | 'score' => 0,  | 
            ||
| 485 | 'feedback' => $feedback,  | 
            ||
| 486 | 'case' => 0, ];  | 
            ||
| 487 | }  | 
            ||
| 488 | }  | 
            ||
| 489 | |||
| 490 | $answersFib = array_merge($correctanswersfib, $incorrectanswersfib);  | 
            ||
| 491 | $answersFib = empty($answersFib) ? '' : $answersFib;  | 
            ||
| 492 | |||
| 493 | return $answersFib;  | 
            ||
| 494 | }  | 
            ||
| 495 | |||
| 496 | private function getAnswersPatternMatch($questionIdentifier, $identifier, $assessment, &$lastAnswerId)  | 
            ||
| 497 |     { | 
            ||
| 498 | $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());  | 
            ||
| 499 | |||
| 500 | $answersFib = [];  | 
            ||
| 501 | |||
| 502 |         $responseItems = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition'); | 
            ||
| 503 | |||
| 504 |         foreach ($responseItems as $response_item) { | 
            ||
| 505 |             $setvar = $xpath->query('xmlns:setvar', $response_item); | 
            ||
| 506 | $setvar = is_object($setvar->item(0)) ? $setvar->item(0)->nodeValue : '';  | 
            ||
| 507 | |||
| 508 |             if ($setvar != '') { | 
            ||
| 509 | $lastAnswerId++;  | 
            ||
| 510 | |||
| 511 |                 $answerTitle = $xpath->query('xmlns:conditionvar/xmlns:varequal[@respident="'.$identifier.'"]', $response_item); | 
            ||
| 512 | $answerTitle = !empty($answerTitle->item(0)->nodeValue) ? $answerTitle->item(0)->nodeValue : '';  | 
            ||
| 513 | |||
| 514 |                 if (empty($answerTitle)) { | 
            ||
| 515 |                     $answerTitle = $xpath->query('xmlns:conditionvar/xmlns:varsubstring[@respident="'.$identifier.'"]', $response_item); | 
            ||
| 516 | $answerTitle = !empty($answerTitle->item(0)->nodeValue) ? '*'.$answerTitle->item(0)->nodeValue.'*' : '';  | 
            ||
| 517 | }  | 
            ||
| 518 | |||
| 519 |                 if (empty($answerTitle)) { | 
            ||
| 520 | $answerTitle = '*';  | 
            ||
| 521 | }  | 
            ||
| 522 | |||
| 523 |                 $case = $xpath->query('xmlns:conditionvar/xmlns:varequal/@case', $response_item); | 
            ||
| 524 | $case = is_object($case->item(0)) ? $case->item(0)->nodeValue : 'no'  | 
            ||
| 525 | ;  | 
            ||
| 526 | $case = strtolower($case) == 'yes' ? 1 :  | 
            ||
| 527 | 0;  | 
            ||
| 528 | |||
| 529 |                 $displayFeedback = $xpath->query('xmlns:displayfeedback', $response_item); | 
            ||
| 530 | |||
| 531 | unset($feedbackIdentifiers);  | 
            ||
| 532 | |||
| 533 |                 if (!empty($displayFeedback)) { | 
            ||
| 534 |                     foreach ($displayFeedback as $feedback) { | 
            ||
| 535 |                         $feedbackIdentifier = $feedback->getAttributeNode('linkrefid'); | 
            ||
| 536 | $feedbackIdentifier = !empty($feedbackIdentifier->nodeValue) ? $feedbackIdentifier->nodeValue : '';  | 
            ||
| 537 | |||
| 538 |                         if (!empty($feedbackIdentifier)) { | 
            ||
| 539 | $feedbackIdentifiers[] = $feedbackIdentifier;  | 
            ||
| 540 | }  | 
            ||
| 541 | }  | 
            ||
| 542 | }  | 
            ||
| 543 | |||
| 544 | $feedback = '';  | 
            ||
| 545 | $feedbackIdentifiers = empty($feedbackIdentifiers) ? '' : $feedbackIdentifiers;  | 
            ||
| 546 | |||
| 547 |                 if (!empty($feedbackIdentifiers)) { | 
            ||
| 548 |                     foreach ($feedbackIdentifiers as $feedbackIdentifier) { | 
            ||
| 549 |                         $feedbacks = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:itemfeedback[@ident="'.$feedbackIdentifier.'"]/xmlns:flow_mat/xmlns:material/xmlns:mattext'); | 
            ||
| 550 | $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue.' ' : '';  | 
            ||
| 551 | }  | 
            ||
| 552 | }  | 
            ||
| 553 | |||
| 554 | $answersFib[] = ['id' => $lastAnswerId,  | 
            ||
| 555 | 'title' => $answerTitle,  | 
            ||
| 556 | 'score' => $setvar,  | 
            ||
| 557 | 'feedback' => $feedback,  | 
            ||
| 558 | 'case' => $case, ];  | 
            ||
| 559 | }  | 
            ||
| 560 | }  | 
            ||
| 561 | |||
| 562 | $answersFib = empty($answersFib) ? '' : $answersFib;  | 
            ||
| 563 | |||
| 564 | return $answersFib;  | 
            ||
| 565 | }  | 
            ||
| 566 | |||
| 567 | private function getAnswers($identifier, $assessment, &$lastAnswerId)  | 
            ||
| 665 | }  | 
            ||
| 666 | |||
| 667 | private function getScore($assessment, $identifier, $questionIdentifier)  | 
            ||
| 668 |     { | 
            ||
| 669 | $xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());  | 
            ||
| 670 | |||
| 671 |         $resourceProcessing = $xpath->query('//xmlns:item[@ident="'.$questionIdentifier.'"]/xmlns:resprocessing/xmlns:respcondition'); | 
            ||
| 672 | |||
| 673 |         if (!empty($resourceProcessing)) { | 
            ||
| 674 |             foreach ($resourceProcessing as $response) { | 
            ||
| 675 | $questionCcType = $this->getQuestionType($questionIdentifier, $assessment);  | 
            ||
| 676 | $questionCcType = $questionCcType['cc'];  | 
            ||
| 677 | |||
| 678 |                 $varequal = $xpath->query('xmlns:conditionvar/xmlns:varequal', $response); | 
            ||
| 679 | $varequal = !empty($varequal->item(0)->nodeValue) ? $varequal->item(0)->nodeValue : '';  | 
            ||
| 680 | |||
| 681 |                 if (strtolower($varequal) == strtolower($identifier)) { | 
            ||
| 682 |                     $score = $xpath->query('xmlns:setvar', $response); | 
            ||
| 683 | $score = !empty($score->item(0)->nodeValue) ? $score->item(0)->nodeValue : '';  | 
            ||
| 684 | }  | 
            ||
| 685 | }  | 
            ||
| 686 | }  | 
            ||
| 687 | |||
| 688 | $score = empty($score) ? "0.0000000" : '1.0000000';  | 
            ||
| 689 | |||
| 690 | return $score;  | 
            ||
| 691 | }  | 
            ||
| 692 | |||
| 693 | private function getQuestionType($identifier, $assessment)  | 
            ||
| 722 | }  | 
            ||
| 723 | }  | 
            ||
| 724 |