1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 /** 17 * @package moodlecore 18 * @subpackage backup-imscc 19 * @copyright 2009 Mauro Rondinelli (mauro.rondinelli [AT] uvcms.com) 20 * @copyright 2011 Darko Miletic (dmiletic@moodlerooms.com) 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 */ 23 24 defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); 25 26 class cc_quiz extends entities { 27 28 public function generate_node_question_categories () { 29 30 $instances = $this->generate_instances(); 31 32 $node_course_question_categories = $this->create_node_course_question_categories($instances); 33 $node_course_question_categories = empty($node_course_question_categories) ? '' : $node_course_question_categories; 34 35 return $node_course_question_categories; 36 37 } 38 39 public function generate_node_course_modules_mod () { 40 41 cc2moodle::log_action('Creating Quiz mods'); 42 43 $node_course_modules_mod = ''; 44 $instances = $this->generate_instances(); 45 46 if (!empty($instances)) { 47 foreach ($instances as $instance) { 48 if ($instance['is_question_bank'] == 0) { 49 $node_course_modules_mod .= $this->create_node_course_modules_mod($instance); 50 } 51 } 52 } 53 54 return $node_course_modules_mod; 55 56 } 57 58 private function create_node_course_modules_mod_quiz_feedback () { 59 60 $sheet_question_mod_feedback = cc2moodle::loadsheet(SHEET_COURSE_SECTIONS_SECTION_MODS_MOD_QUIZ_FEEDBACK); 61 62 return $sheet_question_mod_feedback; 63 } 64 65 private function generate_instances () { 66 67 $last_instance_id = 0; 68 $last_question_id = 0; 69 $last_answer_id = 0; 70 71 $instances = array(); 72 73 $types = array(MOODLE_TYPE_QUIZ, MOODLE_TYPE_QUESTION_BANK); 74 75 foreach ($types as $type) { 76 77 if (!empty(cc2moodle::$instances['instances'][$type])) { 78 79 foreach (cc2moodle::$instances['instances'][$type] as $instance) { 80 81 if ($type == MOODLE_TYPE_QUIZ) { 82 $is_question_bank = 0; 83 } else { 84 $is_question_bank = 1; 85 } 86 87 $assessment_file = $this->get_external_xml($instance['resource_indentifier']); 88 89 if (!empty($assessment_file)) { 90 91 $assessment = $this->load_xml_resource( 92 cc2moodle::$path_to_manifest_folder . DIRECTORY_SEPARATOR . $assessment_file 93 ); 94 95 if (!empty($assessment)) { 96 97 $replace_values = array('unlimited' => 0); 98 99 $questions = $this->get_questions( 100 $assessment, $last_question_id, $last_answer_id, dirname($assessment_file), $is_question_bank 101 ); 102 $question_count = count($questions); 103 104 if (!empty($question_count)) { 105 106 $last_instance_id++; 107 108 $instances[$instance['resource_indentifier']]['questions'] = $questions; 109 $instances[$instance['resource_indentifier']]['id'] = $last_instance_id; 110 $instances[$instance['resource_indentifier']]['title'] = $instance['title']; 111 $instances[$instance['resource_indentifier']]['is_question_bank'] = $is_question_bank; 112 $instances[$instance['resource_indentifier']]['options']['timelimit'] = 113 $this->get_global_config($assessment, 'qmd_timelimit', 0); 114 $instances[$instance['resource_indentifier']]['options']['max_attempts'] = 115 $this->get_global_config($assessment, 'cc_maxattempts', 0, $replace_values); 116 } 117 } 118 } 119 } 120 } 121 } 122 123 return $instances; 124 } 125 126 127 private function create_node_course_modules_mod ($instance) { 128 129 $sheet_question_mod = cc2moodle::loadsheet(SHEET_COURSE_SECTIONS_SECTION_MODS_MOD_QUIZ); 130 131 $node_course_modules_quiz_question_instances = $this->create_node_course_modules_mod_quiz_question_instances($instance); 132 $node_course_modules_quiz_feedback = $this->create_node_course_modules_mod_quiz_feedback($instance); 133 134 $questions_strings = $this->get_questions_string($instance); 135 $quiz_stamp = 'localhost+' . time() . '+' . $this->generate_random_string(6); 136 137 $find_tags = array('[#mod_id#]', 138 '[#mod_name#]', 139 '[#mod_intro#]', 140 '[#mod_stamp#]', 141 '[#question_string#]', 142 '[#date_now#]', 143 '[#mod_max_attempts#]', 144 '[#mod_timelimit#]', 145 '[#node_question_instance#]', 146 '[#node_questions_feedback#]'); 147 148 $replace_values = array($instance['id'], 149 self::safexml($instance['title']), 150 self::safexml($instance['title']), 151 self::safexml($quiz_stamp), 152 self::safexml($questions_strings), 153 time(), 154 $instance['options']['max_attempts'], 155 $instance['options']['timelimit'], 156 $node_course_modules_quiz_question_instances, 157 $node_course_modules_quiz_feedback); // This one has tags. 158 159 $node_question_mod = str_replace($find_tags, $replace_values, $sheet_question_mod); 160 161 return $node_question_mod; 162 } 163 164 private function get_global_config ($assessment, $option, $default_value, $replace_values = '') { 165 166 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 167 $metadata = $xpath->query('/xmlns:questestinterop/xmlns:assessment/xmlns:qtimetadata/xmlns:qtimetadatafield'); 168 169 foreach ($metadata as $field) { 170 $field_label = $xpath->query('xmlns:fieldlabel', $field); 171 $field_label = !empty($field_label->item(0)->nodeValue) ? $field_label->item(0)->nodeValue : ''; 172 173 if (strtolower($field_label) == strtolower($option)) { 174 $field_entry = $xpath->query('xmlns:fieldentry', $field); 175 $response = !empty($field_entry->item(0)->nodeValue) ? $field_entry->item(0)->nodeValue : ''; 176 } 177 } 178 179 $response = !empty($response) ? trim($response) : ''; 180 181 if (!empty($replace_values)) { 182 foreach ($replace_values as $key => $value) { 183 $response = ($key == $response) ? $value : $response; 184 } 185 } 186 187 $response = empty($response) ? $default_value : $response; 188 189 return $response; 190 } 191 192 private function create_node_course_modules_mod_quiz_question_instances ($instance) { 193 194 $node_course_module_mod_quiz_questions_instances = ''; 195 $sheet_question_mod_instance = cc2moodle::loadsheet(SHEET_COURSE_SECTIONS_SECTION_MODS_MOD_QUIZ_QUESTION_INSTANCE); 196 197 $find_tags = array('[#question_id#]' , '[#instance_id#]'); 198 199 if (!empty($instance['questions'])) { 200 201 foreach ($instance['questions'] as $question) { 202 $replace_values = array($question['id'] , $question['id']); 203 $node_course_module_mod_quiz_questions_instances .= str_replace( 204 $find_tags, $replace_values, $sheet_question_mod_instance 205 ); 206 } 207 208 $node_course_module_mod_quiz_questions_instances = str_replace( 209 $find_tags, $replace_values, $node_course_module_mod_quiz_questions_instances 210 ); 211 } 212 213 return $node_course_module_mod_quiz_questions_instances; 214 } 215 216 private function get_questions_string ($instance) { 217 218 $questions_string = ''; 219 220 if (!empty($instance['questions'])) { 221 foreach ($instance['questions'] as $question) { 222 $questions_string .= $question['id'] . ','; 223 } 224 } 225 226 $questions_string = !empty($questions_string) ? substr($questions_string, 0, strlen($questions_string) - 1) : ''; 227 228 return $questions_string; 229 } 230 231 private function create_node_course_question_categories($instances) { 232 233 $sheet_question_categories = cc2moodle::loadsheet(SHEET_COURSE_QUESTION_CATEGORIES); 234 235 if (!empty($instances)) { 236 237 $node_course_question_categories_question_category = ''; 238 239 foreach ($instances as $instance) { 240 $node_course_question_categories_question_category .= 241 $this->create_node_course_question_categories_question_category($instance); 242 } 243 244 $find_tags = array('[#node_course_question_categories_question_category#]'); 245 $replace_values = array($node_course_question_categories_question_category); 246 247 $node_course_question_categories = str_replace($find_tags, $replace_values, $sheet_question_categories); 248 } 249 250 $node_course_question_categories = empty($node_course_question_categories) ? '' : $node_course_question_categories; 251 252 return $node_course_question_categories; 253 } 254 255 private function create_node_course_question_categories_question_category ($instance) { 256 257 $sheet_question_categories_quetion_category = cc2moodle::loadsheet(SHEET_COURSE_QUESTION_CATEGORIES_QUESTION_CATEGORY); 258 259 $find_tags = array('[#quiz_id#]', 260 '[#quiz_name#]', 261 '[#quiz_stamp#]', 262 '[#node_course_question_categories_question_category_questions#]'); 263 264 $node_course_question_categories_questions = 265 $this->create_node_course_question_categories_question_category_question($instance); 266 $node_course_question_categories_questions = 267 empty($node_course_question_categories_questions) ? '' : $node_course_question_categories_questions; 268 269 $quiz_stamp = 'localhost+' . time() . '+' . $this->generate_random_string(6); 270 271 $replace_values = array($instance['id'], 272 self::safexml($instance['title']), 273 $quiz_stamp, 274 $node_course_question_categories_questions); 275 276 $node_question_categories = str_replace($find_tags, $replace_values, $sheet_question_categories_quetion_category); 277 278 return $node_question_categories; 279 } 280 281 private function create_node_course_question_categories_question_category_question ($instance) { 282 283 global $USER; 284 285 $node_course_question_categories_question = ''; 286 287 $find_tags = array('[#question_id#]', 288 '[#question_title#]', 289 '[#question_text#]', 290 '[#question_type#]', 291 '[#question_general_feedback#]', 292 '[#question_defaultgrade#]', 293 '[#date_now#]', 294 '[#question_type_nodes#]', 295 '[#question_stamp#]', 296 '[#question_version#]', 297 '[#logged_user#]'); 298 299 $sheet_question_categories_question = cc2moodle::loadsheet(SHEET_COURSE_QUESTION_CATEGORIES_QUESTION_CATEGORY_QUESTION); 300 301 $questions = $instance['questions']; 302 303 if (!empty($questions)) { 304 305 foreach ($questions as $question) { 306 307 $quiz_stamp = 'localhost+' . time() . '+' . $this->generate_random_string(6); 308 $quiz_version = 'localhost+' . time() . '+' . $this->generate_random_string(6); 309 310 $question_moodle_type = $question['moodle_type']; 311 $question_cc_type = $question['cc_type']; 312 313 $question_type_node = ''; 314 315 $question_type_node = ($question_moodle_type == MOODLE_QUIZ_MULTIPLE_CHOICE) ? $this->create_node_course_question_categories_question_category_question_multiple_choice($question) : $question_type_node; 316 $question_type_node = ($question_moodle_type == MOODLE_QUIZ_TRUE_FALSE) ? $this->create_node_course_question_categories_question_category_question_true_false($question) : $question_type_node; 317 $question_type_node = ($question_moodle_type == MOODLE_QUIZ_ESSAY) ? $this->create_node_course_question_categories_question_category_question_eesay($question) : $question_type_node; 318 $question_type_node = ($question_moodle_type == MOODLE_QUIZ_SHORTANSWER) ? $this->create_node_course_question_categories_question_category_question_shortanswer($question) : $question_type_node; 319 320 $replace_values = array($question['id'], 321 self::safexml($this->truncate_text($question['title'], 255, true)), 322 self::safexml($question['title']), 323 $question_moodle_type, 324 self::safexml($question['feedback']), 325 $question['defaultgrade'], //default grade 326 time(), 327 $question_type_node, 328 $quiz_stamp, 329 $quiz_version, 330 $USER->id); 331 332 $node_course_question_categories_question .= str_replace($find_tags, $replace_values, $sheet_question_categories_question); 333 } 334 } 335 336 $node_course_question_categories_question = empty($node_course_question_categories_question) ? '' : $node_course_question_categories_question; 337 338 return $node_course_question_categories_question; 339 } 340 341 private function get_questions ($assessment, &$last_question_id, &$last_answer_id, $root_path, $is_question_bank) { 342 343 $questions = array(); 344 345 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 346 347 if (!$is_question_bank) { 348 $questions_items = $xpath->query('/xmlns:questestinterop/xmlns:assessment/xmlns:section/xmlns:item'); 349 } else { 350 $questions_items = $xpath->query('/xmlns:questestinterop/xmlns:objectbank/xmlns:item'); 351 } 352 353 foreach ($questions_items as $question_item) { 354 355 $count_questions = $xpath->evaluate('count(xmlns:presentation/xmlns:flow/xmlns:material/xmlns:mattext)', $question_item); 356 357 if ($count_questions == 0) { 358 $question_title = $xpath->query('xmlns:presentation/xmlns:material/xmlns:mattext', $question_item); 359 } else { 360 $question_title = $xpath->query('xmlns:presentation/xmlns:flow/xmlns:material/xmlns:mattext', $question_item); 361 } 362 363 $question_title = !empty($question_title->item(0)->nodeValue) ? $question_title->item(0)->nodeValue : ''; 364 365 $question_identifier = $xpath->query('@ident', $question_item); 366 $question_identifier = !empty($question_identifier->item(0)->nodeValue) ? $question_identifier->item(0)->nodeValue : ''; 367 368 if (!empty($question_identifier)) { 369 370 $question_type = $this->get_question_type($question_identifier, $assessment); 371 372 if (!empty($question_type['moodle'])) { 373 374 $last_question_id++; 375 376 $questions[$question_identifier]['id'] = $last_question_id; 377 378 $question_title = $this->update_sources($question_title, $root_path); 379 $question_title = !empty($question_title) ? str_replace("%24", "\$", $this->include_titles($question_title)) : ''; 380 381 $questions[$question_identifier]['title'] = $question_title; 382 $questions[$question_identifier]['identifier'] = $question_identifier; 383 $questions[$question_identifier]['moodle_type'] = $question_type['moodle']; 384 $questions[$question_identifier]['cc_type'] = $question_type['cc']; 385 $questions[$question_identifier]['feedback'] = $this->get_general_feedback($assessment, $question_identifier); 386 $questions[$question_identifier]['defaultgrade'] = $this->get_defaultgrade($assessment, $question_identifier); 387 $questions[$question_identifier]['answers'] = $this->get_answers($question_identifier, $assessment, $last_answer_id); 388 389 } 390 } 391 } 392 393 $questions = !empty($questions) ? $questions : ''; 394 395 return $questions; 396 } 397 398 private function str_replace_once ($search, $replace, $subject) { 399 400 $first_char = strpos($subject, $search); 401 402 if ($first_char !== false) { 403 404 $before_str = substr($subject, 0, $first_char); 405 $after_str = substr($subject, $first_char + strlen($search)); 406 407 return $before_str . $replace . $after_str; 408 409 } else { 410 return $subject; 411 } 412 } 413 414 private function get_defaultgrade($assessment, $question_identifier) { 415 $result = 1; 416 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 417 $query = '//xmlns:item[@ident="' . $question_identifier . '"]'; 418 $query .= '//xmlns:qtimetadatafield[xmlns:fieldlabel="cc_weighting"]/xmlns:fieldentry'; 419 $defgrade = $xpath->query($query); 420 if (!empty($defgrade) && ($defgrade->length > 0)) { 421 $resp = (int)$defgrade->item(0)->nodeValue; 422 if ($resp >= 0 && $resp <= 99) { 423 $result = $resp; 424 } 425 } 426 return $result; 427 } 428 429 private function get_general_feedback ($assessment, $question_identifier) { 430 431 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 432 433 $respconditions = $xpath->query('//xmlns:item[@ident="' . $question_identifier . '"]/xmlns:resprocessing/xmlns:respcondition'); 434 435 if (!empty($respconditions)) { 436 437 foreach ($respconditions as $respcondition) { 438 439 $continue = $respcondition->getAttributeNode('continue'); 440 $continue = !empty($continue->nodeValue) ? strtolower($continue->nodeValue) : ''; 441 442 if ($continue == 'yes') { 443 444 $display_feedback = $xpath->query('xmlns:displayfeedback', $respcondition); 445 446 if (!empty($display_feedback)) { 447 foreach ($display_feedback as $feedback) { 448 449 $feedback_identifier = $feedback->getAttributeNode('linkrefid'); 450 $feedback_identifier = !empty($feedback_identifier->nodeValue) ? $feedback_identifier->nodeValue : ''; 451 452 if (!empty($feedback_identifier)) { 453 $feedbacks_identifiers[] = $feedback_identifier; 454 } 455 } 456 } 457 } 458 } 459 } 460 461 $feedback = ''; 462 $feedbacks_identifiers = empty($feedbacks_identifiers) ? '' : $feedbacks_identifiers; 463 464 if (!empty($feedbacks_identifiers)) { 465 foreach ($feedbacks_identifiers as $feedback_identifier) { 466 $feedbacks = $xpath->query('//xmlns:item[@ident="' . $question_identifier . '"]/xmlns:itemfeedback[@ident="' . $feedback_identifier . '"]/xmlns:flow_mat/xmlns:material/xmlns:mattext'); 467 $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue . ' ' : ''; 468 } 469 } 470 471 return $feedback; 472 } 473 474 private function get_feedback ($assessment, $identifier, $item_identifier, $question_type) { 475 476 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 477 478 $resource_processing = $xpath->query('//xmlns:item[@ident="' . $item_identifier . '"]/xmlns:resprocessing/xmlns:respcondition'); 479 480 if (!empty($resource_processing)) { 481 482 foreach ($resource_processing as $response) { 483 484 $varequal = $xpath->query('xmlns:conditionvar/xmlns:varequal', $response); 485 $varequal = !empty($varequal->item(0)->nodeValue) ? $varequal->item(0)->nodeValue : ''; 486 487 if (strtolower($varequal) == strtolower($identifier) || ($question_type == CC_QUIZ_ESSAY)) { 488 489 $display_feedback = $xpath->query('xmlns:displayfeedback', $response); 490 491 if (!empty($display_feedback)) { 492 foreach ($display_feedback as $feedback) { 493 494 $feedback_identifier = $feedback->getAttributeNode('linkrefid'); 495 $feedback_identifier = !empty($feedback_identifier->nodeValue) ? $feedback_identifier->nodeValue : ''; 496 497 if (!empty($feedback_identifier)) { 498 $feedbacks_identifiers[] = $feedback_identifier; 499 } 500 } 501 } 502 } 503 } 504 } 505 506 $feedback = ''; 507 $feedbacks_identifiers = empty($feedbacks_identifiers) ? '' : $feedbacks_identifiers; 508 509 if (!empty($feedbacks_identifiers)) { 510 foreach ($feedbacks_identifiers as $feedback_identifier) { 511 $feedbacks = $xpath->query('//xmlns:item[@ident="' . $item_identifier . '"]/xmlns:itemfeedback[@ident="' . $feedback_identifier . '"]/xmlns:flow_mat/xmlns:material/xmlns:mattext'); 512 $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue . ' ' : ''; 513 } 514 } 515 516 return $feedback; 517 } 518 519 private function get_answers_fib ($question_identifier, $identifier, $assessment, &$last_answer_id) { 520 521 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 522 523 $answers_fib = array(); 524 525 $response_items = $xpath->query('//xmlns:item[@ident="' . $question_identifier . '"]/xmlns:resprocessing/xmlns:respcondition'); 526 527 foreach ($response_items as $response_item) { 528 529 $setvar = $xpath->query('xmlns:setvar', $response_item); 530 $setvar = is_object($setvar->item(0)) ? $setvar->item(0)->nodeValue : ''; 531 532 if ($setvar != '') { 533 534 $last_answer_id++; 535 536 $answer_title = $xpath->query('xmlns:conditionvar/xmlns:varequal[@respident="' . $identifier . '"]', $response_item); 537 $answer_title = !empty($answer_title->item(0)->nodeValue) ? $answer_title->item(0)->nodeValue : ''; 538 539 $case = $xpath->query('xmlns:conditionvar/xmlns:varequal/@case', $response_item); 540 $case = is_object($case->item(0)) ? $case->item(0)->nodeValue : 'no' 541 ; 542 $case = strtolower($case) == 'yes' ? 1 : 543 0; 544 545 $display_feedback = $xpath->query('xmlns:displayfeedback', $response_item); 546 547 unset($feedbacks_identifiers); 548 549 if (!empty($display_feedback)) { 550 551 foreach ($display_feedback as $feedback) { 552 553 $feedback_identifier = $feedback->getAttributeNode('linkrefid'); 554 $feedback_identifier = !empty($feedback_identifier->nodeValue) ? $feedback_identifier->nodeValue : ''; 555 556 if (!empty($feedback_identifier)) { 557 $feedbacks_identifiers[] = $feedback_identifier; 558 } 559 } 560 } 561 562 $feedback = ''; 563 $feedbacks_identifiers = empty($feedbacks_identifiers) ? '' : $feedbacks_identifiers; 564 565 if (!empty($feedbacks_identifiers)) { 566 foreach ($feedbacks_identifiers as $feedback_identifier) { 567 $feedbacks = $xpath->query('//xmlns:item[@ident="' . $question_identifier . '"]/xmlns:itemfeedback[@ident="' . $feedback_identifier . '"]/xmlns:flow_mat/xmlns:material/xmlns:mattext'); 568 $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue . ' ' : ''; 569 } 570 } 571 572 $answers_fib[] = array('id' => $last_answer_id, 573 'title' => $answer_title, 574 'score' => $setvar, 575 'feedback' => $feedback, 576 'case' => $case); 577 } 578 } 579 580 $answers_fib = empty($answers_fib) ? '' : $answers_fib; 581 582 return $answers_fib; 583 } 584 585 private function get_answers_pattern_match ($question_identifier, $identifier, $assessment, &$last_answer_id) { 586 587 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 588 589 $answers_fib = array(); 590 591 $response_items = $xpath->query('//xmlns:item[@ident="' . $question_identifier . '"]/xmlns:resprocessing/xmlns:respcondition'); 592 593 foreach ($response_items as $response_item) { 594 595 $setvar = $xpath->query('xmlns:setvar', $response_item); 596 $setvar = is_object($setvar->item(0)) ? $setvar->item(0)->nodeValue : ''; 597 598 if ($setvar != '') { 599 600 $last_answer_id++; 601 602 $answer_title = $xpath->query('xmlns:conditionvar/xmlns:varequal[@respident="' . $identifier . '"]', $response_item); 603 $answer_title = !empty($answer_title->item(0)->nodeValue) ? $answer_title->item(0)->nodeValue : ''; 604 605 if (empty($answer_title)) { 606 $answer_title = $xpath->query('xmlns:conditionvar/xmlns:varsubstring[@respident="' . $identifier . '"]', $response_item); 607 $answer_title = !empty($answer_title->item(0)->nodeValue) ? '*' . $answer_title->item(0)->nodeValue . '*' : ''; 608 } 609 610 if (empty($answer_title)) { 611 $answer_title = '*'; 612 } 613 614 $case = $xpath->query('xmlns:conditionvar/xmlns:varequal/@case', $response_item); 615 $case = is_object($case->item(0)) ? $case->item(0)->nodeValue : 'no' 616 ; 617 $case = strtolower($case) == 'yes' ? 1 : 618 0; 619 620 $display_feedback = $xpath->query('xmlns:displayfeedback', $response_item); 621 622 unset($feedbacks_identifiers); 623 624 if (!empty($display_feedback)) { 625 626 foreach ($display_feedback as $feedback) { 627 628 $feedback_identifier = $feedback->getAttributeNode('linkrefid'); 629 $feedback_identifier = !empty($feedback_identifier->nodeValue) ? $feedback_identifier->nodeValue : ''; 630 631 if (!empty($feedback_identifier)) { 632 $feedbacks_identifiers[] = $feedback_identifier; 633 } 634 } 635 } 636 637 $feedback = ''; 638 $feedbacks_identifiers = empty($feedbacks_identifiers) ? '' : $feedbacks_identifiers; 639 640 if (!empty($feedbacks_identifiers)) { 641 foreach ($feedbacks_identifiers as $feedback_identifier) { 642 $feedbacks = $xpath->query('//xmlns:item[@ident="' . $question_identifier . '"]/xmlns:itemfeedback[@ident="' . $feedback_identifier . '"]/xmlns:flow_mat/xmlns:material/xmlns:mattext'); 643 $feedback .= !empty($feedbacks->item(0)->nodeValue) ? $feedbacks->item(0)->nodeValue . ' ' : ''; 644 } 645 } 646 647 $answers_fib[] = array('id' => $last_answer_id, 648 'title' => $answer_title, 649 'score' => $setvar, 650 'feedback' => $feedback, 651 'case' => $case); 652 } 653 } 654 655 $answers_fib = empty($answers_fib) ? '' : $answers_fib; 656 657 return $answers_fib; 658 } 659 660 661 private function get_answers ($identifier, $assessment, &$last_answer_id) { 662 663 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 664 665 $answers = array(); 666 667 $question_cc_type = $this->get_question_type($identifier, $assessment); 668 $question_cc_type = $question_cc_type['cc']; 669 $is_multiresponse = ($question_cc_type == CC_QUIZ_MULTIPLE_RESPONSE); 670 671 if ($question_cc_type == CC_QUIZ_MULTIPLE_CHOICE || $is_multiresponse || $question_cc_type == CC_QUIZ_TRUE_FALSE) { 672 673 $query_answers = '//xmlns:item[@ident="' . $identifier . '"]/xmlns:presentation/xmlns:response_lid/xmlns:render_choice/xmlns:response_label'; 674 $query_answers_with_flow = '//xmlns:item[@ident="' . $identifier . '"]/xmlns:presentation/xmlns:flow/xmlns:response_lid/xmlns:render_choice/xmlns:response_label'; 675 676 $query_indentifer = '@ident'; 677 $query_title = 'xmlns:material/xmlns:mattext'; 678 } 679 680 if ($question_cc_type == CC_QUIZ_ESSAY) { 681 682 $query_answers = '//xmlns:item[@ident="' . $identifier . '"]/xmlns:presentation/xmlns:response_str'; 683 $query_answers_with_flow = '//xmlns:item[@ident="' . $identifier . '"]/xmlns:presentation/xmlns:flow/xmlns:response_str'; 684 685 $query_indentifer = '@ident'; 686 $query_title = 'xmlns:render_fib'; 687 } 688 689 if ($question_cc_type == CC_QUIZ_FIB || $question_cc_type == CC_QUIZ_PATTERN_MACHT) { 690 691 $xpath_query = '//xmlns:item[@ident="' . $identifier . '"]/xmlns:presentation/xmlns:response_str/@ident'; 692 $xpath_query_with_flow = '//xmlns:item[@ident="' . $identifier . '"]/xmlns:presentation/xmlns:flow/xmlns:response_str/@ident'; 693 694 $count_response = $xpath->evaluate('count(' . $xpath_query_with_flow . ')'); 695 696 if ($count_response == 0) { 697 $answer_identifier = $xpath->query($xpath_query); 698 } else { 699 $answer_identifier = $xpath->query($xpath_query_with_flow); 700 } 701 702 $answer_identifier = !empty($answer_identifier->item(0)->nodeValue) ? $answer_identifier->item(0)->nodeValue : ''; 703 704 if ($question_cc_type == CC_QUIZ_FIB) { 705 $answers = $this->get_answers_fib ($identifier, $answer_identifier, $assessment, $last_answer_id); 706 } else { 707 $answers = $this->get_answers_pattern_match ($identifier, $answer_identifier, $assessment, $last_answer_id); 708 } 709 710 } else { 711 712 $count_response = $xpath->evaluate('count(' . $query_answers_with_flow . ')'); 713 714 if ($count_response == 0) { 715 $response_items = $xpath->query($query_answers); 716 } else { 717 $response_items = $xpath->query($query_answers_with_flow); 718 } 719 720 if (!empty($response_items)) { 721 if ($is_multiresponse) { 722 $correct_answer_score = 0; 723 //get the correct answers count 724 $canswers_query = "//xmlns:item[@ident='{$identifier}']//xmlns:setvar[@varname='SCORE'][.=100]/../xmlns:conditionvar//xmlns:varequal[@case='Yes'][not(parent::xmlns:not)]"; 725 $canswers = $xpath->query($canswers_query); 726 if ($canswers->length > 0) { 727 $correct_answer_score = round(1.0 / (float)$canswers->length, 7); //weird 728 $correct_answers_ident = array(); 729 foreach ($canswers as $cnode) { 730 $correct_answers_ident[$cnode->nodeValue] = true; 731 } 732 } 733 } 734 foreach ($response_items as $response_item) { 735 736 $last_answer_id++; 737 738 $answer_identifier = $xpath->query($query_indentifer, $response_item); 739 $answer_identifier = !empty($answer_identifier->item(0)->nodeValue) ? $answer_identifier->item(0)->nodeValue : ''; 740 741 $answer_title = $xpath->query($query_title, $response_item); 742 $answer_title = !empty($answer_title->item(0)->nodeValue) ? $answer_title->item(0)->nodeValue : ''; 743 744 $answer_feedback = $this->get_feedback($assessment, $answer_identifier, $identifier, $question_cc_type); 745 746 $answer_score = $this->get_score($assessment, $answer_identifier, $identifier); 747 748 if ($is_multiresponse && isset($correct_answers_ident[$answer_identifier])) { 749 $answer_score = $correct_answer_score; 750 } 751 752 $answers[] = array('id' => $last_answer_id, 753 'title' => $answer_title, 754 'score' => $answer_score, 755 'identifier' => $answer_identifier, 756 'feedback' => $answer_feedback); 757 } 758 } 759 } 760 761 $answers = empty($answers) ? '' : $answers; 762 763 return $answers; 764 765 } 766 767 private function get_score ($assessment, $identifier, $question_identifier) { 768 769 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 770 771 $resource_processing = $xpath->query('//xmlns:item[@ident="' . $question_identifier . '"]/xmlns:resprocessing/xmlns:respcondition'); 772 773 if (!empty($resource_processing)) { 774 775 foreach ($resource_processing as $response) { 776 777 $question_cc_type = $this->get_question_type($question_identifier, $assessment); 778 $question_cc_type = $question_cc_type['cc']; 779 780 $varequal = $xpath->query('xmlns:conditionvar/xmlns:varequal', $response); 781 $varequal = !empty($varequal->item(0)->nodeValue) ? $varequal->item(0)->nodeValue : ''; 782 783 if (strtolower($varequal) == strtolower($identifier)) { 784 $score = $xpath->query('xmlns:setvar', $response); 785 $score = !empty($score->item(0)->nodeValue) ? $score->item(0)->nodeValue : ''; 786 } 787 } 788 } 789 790 $score = empty($score) ? 0 : sprintf("%.7F", $score); 791 792 return $score; 793 } 794 795 private function create_node_course_question_categories_question_category_question_multiple_choice ($question) { 796 797 $node_course_question_categories_question_answer = ''; 798 $sheet_question_categories_question = cc2moodle::loadsheet(SHEET_COURSE_QUESTION_CATEGORIES_QUESTION_CATEGORY_QUESTION_MULTIPLE_CHOICE); 799 800 if (!empty($question['answers'])) { 801 foreach ($question['answers'] as $answer) { 802 $node_course_question_categories_question_answer .= $this->create_node_course_question_categories_question_category_question_answer($answer); 803 } 804 } 805 806 $answer_string = $this->get_answers_string($question['answers']); 807 808 $is_single = ($question['cc_type'] == CC_QUIZ_MULTIPLE_CHOICE) ? 1 : 0; 809 810 $find_tags = array('[#node_course_question_categories_question_category_question_answer#]', 811 '[#answer_string#]', 812 '[#is_single#]'); 813 814 $replace_values = array($node_course_question_categories_question_answer, 815 self::safexml($answer_string), 816 $is_single); 817 818 $node_question_categories_question = str_replace($find_tags, $replace_values, $sheet_question_categories_question); 819 820 return $node_question_categories_question; 821 } 822 823 private function create_node_course_question_categories_question_category_question_eesay ($question) { 824 825 $node_course_question_categories_question_answer = ''; 826 827 $sheet_question_categories_question = cc2moodle::loadsheet(SHEET_COURSE_QUESTION_CATEGORIES_QUESTION_CATEGORY_QUESTION_EESAY); 828 829 if (!empty($question['answers'])) { 830 foreach ($question['answers'] as $answer) { 831 $node_course_question_categories_question_answer .= $this->create_node_course_question_categories_question_category_question_answer($answer); 832 } 833 } 834 835 $find_tags = array('[#node_course_question_categories_question_category_question_answer#]'); 836 $replace_values = array($node_course_question_categories_question_answer); 837 838 $node_question_categories_question = str_replace($find_tags, $replace_values, $sheet_question_categories_question); 839 840 return $node_question_categories_question; 841 } 842 843 private function create_node_course_question_categories_question_category_question_shortanswer ($question) { //, &$fib_questions) { 844 845 $sheet_question_categories_question = cc2moodle::loadsheet(SHEET_COURSE_QUESTION_CATEGORIES_QUESTION_CATEGORY_QUESTION_SHORTANSWER); 846 $node_course_question_categories_question_answer = ''; 847 848 if (!empty($question['answers'])) { 849 foreach ($question['answers'] as $answer) { 850 $node_course_question_categories_question_answer .= $this->create_node_course_question_categories_question_category_question_answer($answer); 851 } 852 } 853 854 $answers_string = $this->get_answers_string($question['answers']); 855 856 $use_case = 0; 857 858 foreach ($question['answers'] as $answer) { 859 860 if ($answer['case'] == 1) { 861 $use_case = 1; 862 } 863 864 } 865 866 $find_tags = array('[#answers_string#]', 867 '[#use_case#]', 868 '[#node_course_question_categories_question_category_question_answer#]'); 869 870 $replace_values = array(self::safexml($answers_string), 871 self::safexml($use_case), 872 $node_course_question_categories_question_answer); 873 874 875 876 $node_question_categories_question = str_replace($find_tags, $replace_values, $sheet_question_categories_question); 877 878 return $node_question_categories_question; 879 880 } 881 882 private function create_node_course_question_categories_question_category_question_true_false ($question) { 883 884 $node_course_question_categories_question_answer = ''; 885 886 $sheet_question_categories_question = cc2moodle::loadsheet(SHEET_COURSE_QUESTION_CATEGORIES_QUESTION_CATEGORY_QUESTION_TRUE_FALSE); 887 888 $trueanswer = null; 889 $falseanswer = null; 890 891 if (!empty($question['answers'])) { 892 893 // Identify the true and false answers. 894 foreach ($question['answers'] as $answer) { 895 if ($answer['identifier'] == 'true') { 896 $trueanswer = $answer; 897 } else if ($answer['identifier'] == 'false') { 898 $falseanswer = $answer; 899 } else { 900 // Should not happen, but just in case. 901 throw new coding_exception("Unknown answer identifier detected" . 902 " in true/false quiz question with id {$question['id']}."); 903 } 904 905 $node_course_question_categories_question_answer .= $this->create_node_course_question_categories_question_category_question_answer($answer); 906 } 907 908 // Make sure the true and false answer was found. 909 if (is_null($trueanswer) || is_null($falseanswer)) { 910 throw new coding_exception("Unable to correctly identify the " . 911 "true and false answers in the question with id {$question['id']}."); 912 } 913 } 914 915 $find_tags = array('[#node_course_question_categories_question_category_question_answer#]', 916 '[#true_answer_id#]', 917 '[#false_answer_id#]'); 918 919 $replace_values = array($node_course_question_categories_question_answer, 920 $trueanswer['id'], 921 $falseanswer['id']); 922 923 $node_question_categories_question = str_replace($find_tags, $replace_values, $sheet_question_categories_question); 924 925 return $node_question_categories_question; 926 } 927 928 private function get_answers_string ($answers) { 929 930 $answer_string = ''; 931 932 if (!empty($answers)) { 933 foreach ($answers as $answer) { 934 $answer_string .= $answer['id'] . ','; 935 } 936 } 937 938 $answer_string = !empty($answer_string) ? substr($answer_string, 0, strlen($answer_string) - 1) : ''; 939 940 return $answer_string; 941 942 } 943 944 private function create_node_course_question_categories_question_category_question_answer ($answer) { 945 946 $sheet_question_categories_question_answer = cc2moodle::loadsheet(SHEET_COURSE_QUESTION_CATEGORIES_QUESTION_CATEGORY_QUESTION_ANSWER); 947 948 $find_tags = array('[#answer_id#]', 949 '[#answer_text#]', 950 '[#answer_score#]', 951 '[#answer_feedback#]'); 952 953 $replace_values = array($answer['id'], 954 self::safexml($answer['title']), 955 $answer['score'], 956 self::safexml($answer['feedback'])); 957 958 $node_question_categories_question_answer = str_replace($find_tags, $replace_values, $sheet_question_categories_question_answer); 959 960 return $node_question_categories_question_answer; 961 } 962 963 private function get_question_type ($identifier, $assessment) { 964 965 $xpath = cc2moodle::newx_path($assessment, cc2moodle::getquizns()); 966 967 $metadata = $xpath->query('//xmlns:item[@ident="' . $identifier . '"]/xmlns:itemmetadata/xmlns:qtimetadata/xmlns:qtimetadatafield'); 968 969 foreach ($metadata as $field) { 970 971 $field_label = $xpath->query('xmlns:fieldlabel', $field); 972 $field_label = !empty($field_label->item(0)->nodeValue) ? $field_label->item(0)->nodeValue : ''; 973 974 if ($field_label == 'cc_profile') { 975 $field_entry = $xpath->query('xmlns:fieldentry', $field); 976 $type = !empty($field_entry->item(0)->nodeValue) ? $field_entry->item(0)->nodeValue : ''; 977 } 978 } 979 980 $return_type = array(); 981 982 $return_type['moodle'] = ''; 983 $return_type['cc'] = $type; 984 985 if ($type == CC_QUIZ_MULTIPLE_CHOICE) { 986 $return_type['moodle'] = MOODLE_QUIZ_MULTIPLE_CHOICE; 987 } 988 if ($type == CC_QUIZ_MULTIPLE_RESPONSE) { 989 $return_type['moodle'] = MOODLE_QUIZ_MULTIPLE_CHOICE; 990 } 991 if ($type == CC_QUIZ_TRUE_FALSE) { 992 $return_type['moodle'] = MOODLE_QUIZ_TRUE_FALSE; 993 } 994 if ($type == CC_QUIZ_ESSAY) { 995 $return_type['moodle'] = MOODLE_QUIZ_ESSAY; 996 } 997 if ($type == CC_QUIZ_FIB) { 998 $return_type['moodle'] = MOODLE_QUIZ_SHORTANSWER; 999 } 1000 if ($type == CC_QUIZ_PATTERN_MACHT) { 1001 $return_type['moodle'] = MOODLE_QUIZ_SHORTANSWER; 1002 } 1003 1004 return $return_type; 1005 1006 } 1007 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body