Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
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 backup-convert 18 * @copyright 2011 Darko Miletic <dmiletic@moodlerooms.com> 19 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 20 */ 21 22 defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); 23 24 require_once ('cc_utils.php'); 25 require_once ('cc_general.php'); 26 27 abstract class cc_xml_namespace { 28 const xml = 'http://www.w3.org/XML/1998/namespace'; 29 } 30 31 abstract class cc_qti_metadata { 32 // Assessment. 33 const qmd_assessmenttype = 'qmd_assessmenttype'; 34 const qmd_scoretype = 'qmd_scoretype'; 35 const qmd_feedbackpermitted = 'qmd_feedbackpermitted'; 36 const qmd_hintspermitted = 'qmd_hintspermitted'; 37 const qmd_solutionspermitted = 'qmd_solutionspermitted'; 38 const qmd_timelimit = 'qmd_timelimit'; 39 const cc_allow_late_submission = 'cc_allow_late_submission'; 40 const cc_maxattempts = 'cc_maxattempts'; 41 const cc_profile = 'cc_profile'; 42 43 // Items. 44 const cc_weighting = 'cc_weighting'; 45 const qmd_scoringpermitted = 'qmd_scoringpermitted'; 46 const qmd_computerscored = 'qmd_computerscored'; 47 const cc_question_category = 'cc_question_category'; 48 } 49 50 abstract class cc_qti_profiletype { 51 const multiple_choice = 'cc.multiple_choice.v0p1'; 52 const multiple_response = 'cc.multiple_response.v0p1'; 53 const true_false = 'cc.true_false.v0p1'; 54 const field_entry = 'cc.fib.v0p1'; 55 const pattern_match = 'cc.pattern_match.v0p1'; 56 const essay = 'cc.essay.v0p1'; 57 58 /** 59 * 60 * validates a profile value 61 * @param string $value 62 * @return boolean 63 */ 64 public static function valid($value) { 65 static $verification_values = array( self::essay, 66 self::field_entry, 67 self::multiple_choice, 68 self::multiple_response, 69 self::pattern_match, 70 self::true_false 71 ); 72 return in_array($value, $verification_values); 73 } 74 75 } 76 77 abstract class cc_qti_values { 78 const exam_profile = 'cc.exam.v0p1'; 79 const Yes = 'Yes'; 80 const No = 'No'; 81 const Response = 'Response'; 82 const Solution = 'Solution'; 83 const Hint = 'Hint'; 84 const Examination = 'Examination'; 85 const Percentage = 'Percentage'; 86 const unlimited = 'unlimited'; 87 const Single = 'Single'; 88 const Multiple = 'Multiple'; 89 const Ordered = 'Ordered'; 90 const Asterisk = 'Asterisk'; 91 const Box = 'Box'; 92 const Dashline = 'Dashline'; 93 const Underline = 'Underline'; 94 const Decimal = 'Decimal'; 95 const Integer = 'Integer'; 96 const Scientific = 'Scientific'; 97 const String = 'String'; 98 const SCORE = 'SCORE'; 99 const Set = 'Set'; 100 const Complete = 'Complete'; 101 const texttype = 'text/plain'; 102 const htmltype = 'text/html'; 103 } 104 105 abstract class cc_qti_tags { 106 const questestinterop = 'questestinterop'; 107 const assessment = 'assessment'; 108 const qtimetadata = 'qtimetadata'; 109 const qtimetadatafield = 'qtimetadatafield'; 110 const fieldlabel = 'fieldlabel'; 111 const fieldentry = 'fieldentry'; 112 const section = 'section'; 113 const ident = 'ident'; 114 const item = 'item'; 115 const title = 'title'; 116 const itemmetadata = 'itemmetadata'; 117 const presentation = 'presentation'; 118 const material = 'material'; 119 const mattext = 'mattext'; 120 const matref = 'matref'; 121 const matbreak = 'matbreak'; 122 const texttype = 'texttype'; 123 const response_lid = 'response_lid'; 124 const render_choice = 'render_choice'; 125 const response_label = 'response_label'; 126 const resprocessing = 'resprocessing'; 127 const outcomes = 'outcomes'; 128 const decvar = 'decvar'; 129 const respcondition = 'respcondition'; 130 const conditionvar = 'conditionvar'; 131 const other = 'other'; 132 const displayfeedback = 'displayfeedback'; 133 const maxvalue = 'maxvalue'; 134 const minvalue = 'minvalue'; 135 const varname = 'varname'; 136 const vartype = 'vartype'; 137 const continue_ = 'continue'; 138 const feedbacktype = 'feedbacktype'; 139 const linkrefid = 'linkrefid'; 140 const varequal = 'varequal'; 141 const respident = 'respident'; 142 const itemfeedback = 'itemfeedback'; 143 const flow_mat = 'flow_mat'; 144 const rcardinality = 'rcardinality'; 145 const charset = 'charset'; 146 const label = 'label'; 147 const uri = 'uri'; 148 const width = 'width'; 149 const height = 'height'; 150 const x0 = 'x0'; 151 const y0 = 'y0'; 152 const xml_lang = 'lang'; 153 const xml_space = 'space'; 154 const rubric = 'rubric'; 155 const altmaterial = 'altmaterial'; 156 const presentation_material = 'presentation_material'; 157 const t_class = 'class'; 158 const material_ref = 'material_ref'; 159 const rtiming = 'rtiming'; 160 const render_fib = 'render_fib'; 161 const shuffle = 'shuffle'; 162 const minnumber = 'minnumber'; 163 const maxnumber = 'maxnumber'; 164 const encoding = 'encoding'; 165 const maxchars = 'maxchars'; 166 const prompt = 'prompt'; 167 const fibtype = 'fibtype'; 168 const rows = 'rows'; 169 const columns = 'columns'; 170 const labelrefid = 'labelrefid'; 171 const rshuffle = 'rshuffle'; 172 const match_group = 'match_group'; 173 const match_max = 'match_max'; 174 const flow = 'flow'; 175 const response_str = 'response_str'; 176 const flow_label = 'flow_label'; 177 const setvar = 'setvar'; 178 const action = 'action'; 179 const and_ = 'and'; 180 const not_ = 'not'; 181 const case_ = 'case'; 182 const varsubstring = 'varsubstring'; 183 const hint = 'hint'; 184 const solution = 'solution'; 185 const feedbackstyle = 'feedbackstyle'; 186 const solutionmaterial = 'solutionmaterial'; 187 const hintmaterial = 'hintmaterial'; 188 } 189 190 class cc_question_metadata_base { 191 /** 192 * @var array 193 */ 194 protected $metadata = array(); 195 196 /** 197 * @param string $setting 198 * @param mixed $value 199 */ 200 protected function set_setting($setting, $value = null) { 201 $this->metadata[$setting] = $value; 202 } 203 204 /** 205 * @param string $setting 206 * @return mixed 207 */ 208 protected function get_setting($setting) { 209 $result = null; 210 if (array_key_exists($setting, $this->metadata)) { 211 $result = $this->metadata[$setting]; 212 } 213 return $result; 214 } 215 216 /** 217 * @param string $setting 218 * @param string $namespace 219 * @param string $value 220 */ 221 protected function set_setting_wns($setting, $namespace, $value = null) { 222 $this->metadata[$setting] = array($namespace => $value); 223 } 224 225 /** 226 * @param string $setting 227 * @param boolean $value 228 */ 229 protected function enable_setting_yesno($setting, $value = true) { 230 $svalue = $value ? cc_qti_values::Yes : cc_qti_values::No; 231 $this->set_setting($setting, $svalue); 232 } 233 234 /** 235 * @param XMLGenericDocument $doc 236 * @param DOMNode $item 237 * @param string $namespace 238 */ 239 public function generate_attributes(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 240 foreach ($this->metadata as $attribute => $value) { 241 if (!is_null($value)) { 242 if (!is_array($value)) { 243 $doc->append_new_attribute_ns($item, $namespace, $attribute, $value); 244 } else { 245 $ns = key($value); 246 $nval = current($value); 247 if (!is_null($nval)) { 248 $doc->append_new_attribute_ns($item, $ns, $attribute, $nval); 249 } 250 } 251 } 252 } 253 } 254 255 /** 256 * @param XMLGenericDocument $doc 257 * @param DOMNode $item 258 * @param string $namespace 259 */ 260 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 261 $qtimetadata = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::qtimetadata); 262 foreach ($this->metadata as $label => $entry) { 263 if (!is_null($entry)) { 264 $qtimetadatafield = $doc->append_new_element_ns($qtimetadata, $namespace, cc_qti_tags::qtimetadatafield); 265 $doc->append_new_element_ns($qtimetadatafield, $namespace, cc_qti_tags::fieldlabel, $label); 266 $doc->append_new_element_ns($qtimetadatafield, $namespace, cc_qti_tags::fieldentry, $entry); 267 } 268 } 269 } 270 } 271 272 class cc_question_metadata extends cc_question_metadata_base { 273 274 public function set_category($value) { 275 $this->set_setting(cc_qti_metadata::cc_question_category, $value); 276 } 277 278 public function set_weighting($value) { 279 $this->set_setting(cc_qti_metadata::cc_weighting, $value); 280 } 281 282 public function enable_scoringpermitted($value = true) { 283 $this->enable_setting_yesno(cc_qti_metadata::qmd_scoringpermitted, $value); 284 } 285 286 public function enable_computerscored($value = true) { 287 $this->enable_setting_yesno(cc_qti_metadata::qmd_computerscored, $value); 288 } 289 290 /** 291 * 292 * Constructs metadata 293 * @param string $profile 294 * @throws InvalidArgumentException 295 */ 296 public function __construct($profile) { 297 if (!cc_qti_profiletype::valid($profile)) { 298 throw new InvalidArgumentException('Invalid profile type!'); 299 } 300 $this->set_setting(cc_qti_metadata::cc_profile, $profile); 301 $this->set_setting(cc_qti_metadata::cc_question_category); 302 $this->set_setting(cc_qti_metadata::cc_weighting ); 303 $this->set_setting(cc_qti_metadata::qmd_scoringpermitted); 304 $this->set_setting(cc_qti_metadata::qmd_computerscored ); 305 } 306 } 307 308 309 class cc_assesment_metadata extends cc_question_metadata_base { 310 311 public function enable_hints($value = true) { 312 $this->enable_setting_yesno(cc_qti_metadata::qmd_hintspermitted, $value); 313 } 314 315 public function enable_solutions($value = true) { 316 $this->enable_setting_yesno(cc_qti_metadata::qmd_solutionspermitted, $value); 317 } 318 319 public function enable_latesubmissions($value = true) { 320 $this->enable_setting_yesno(cc_qti_metadata::cc_allow_late_submission, $value); 321 } 322 323 public function enable_feedback($value = true) { 324 $this->enable_setting_yesno(cc_qti_metadata::qmd_feedbackpermitted, $value); 325 } 326 327 public function set_timelimit($value) { 328 $ivalue = (int)$value; 329 if (($ivalue < 0) || ($ivalue > 527401)) { 330 throw new OutOfRangeException('Time limit value out of permitted range!'); 331 } 332 333 $this->set_setting(cc_qti_metadata::qmd_timelimit, $value); 334 } 335 336 public function set_maxattempts($value) { 337 $valid_values = array(cc_qti_values::Examination, cc_qti_values::unlimited, 1, 2, 3, 4, 5); 338 if (!in_array($value, $valid_values)) { 339 throw new OutOfRangeException('Max attempts has invalid value'); 340 } 341 342 $this->set_setting(cc_qti_metadata::cc_maxattempts, $value); 343 } 344 345 public function __construct() { 346 //prepared default values 347 $this->set_setting(cc_qti_metadata::cc_profile , cc_qti_values::exam_profile); 348 $this->set_setting(cc_qti_metadata::qmd_assessmenttype, cc_qti_values::Examination ); 349 $this->set_setting(cc_qti_metadata::qmd_scoretype , cc_qti_values::Percentage ); 350 //optional empty values 351 $this->set_setting(cc_qti_metadata::qmd_feedbackpermitted ); 352 $this->set_setting(cc_qti_metadata::qmd_hintspermitted ); 353 $this->set_setting(cc_qti_metadata::qmd_solutionspermitted ); 354 $this->set_setting(cc_qti_metadata::qmd_timelimit ); 355 $this->set_setting(cc_qti_metadata::cc_allow_late_submission); 356 $this->set_setting(cc_qti_metadata::cc_maxattempts ); 357 } 358 359 } 360 361 class cc_assesment_mattext extends cc_question_metadata_base { 362 protected $value = null; 363 364 public function __construct($value = null) { 365 $this->set_setting(cc_qti_tags::texttype, cc_qti_values::texttype); 366 $this->set_setting(cc_qti_tags::charset);//, 'ascii-us'); 367 $this->set_setting(cc_qti_tags::label); 368 $this->set_setting(cc_qti_tags::uri); 369 $this->set_setting(cc_qti_tags::width); 370 $this->set_setting(cc_qti_tags::height); 371 $this->set_setting(cc_qti_tags::x0); 372 $this->set_setting(cc_qti_tags::y0); 373 $this->set_setting_wns(cc_qti_tags::xml_lang , cc_xml_namespace::xml); 374 $this->set_setting_wns(cc_qti_tags::xml_space, cc_xml_namespace::xml);//, 'default'); 375 $this->value = $value; 376 } 377 378 public function set_label($value) { 379 $this->set_setting(cc_qti_tags::label, $value); 380 } 381 382 public function set_uri($value) { 383 $this->set_setting(cc_qti_tags::uri, $value); 384 } 385 386 public function set_width_height($width = null, $height = null) { 387 $this->set_setting(cc_qti_tags::width, $width); 388 $this->set_setting(cc_qti_tags::height, $height); 389 } 390 391 public function set_coor($x = null, $y = null) { 392 $this->set_setting(cc_qti_tags::x0, $x); 393 $this->set_setting(cc_qti_tags::y0, $y); 394 } 395 396 public function set_lang($lang = null) { 397 $this->set_setting_wns(cc_qti_tags::xml_lang , cc_xml_namespace::xml, $lang); 398 } 399 400 public function set_content($content, $type = cc_qti_values::texttype, $charset = null) { 401 $this->value = $content; 402 $this->set_setting(cc_qti_tags::texttype, $type); 403 $this->set_setting(cc_qti_tags::charset, $charset); 404 } 405 406 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 407 $mattext = $doc->append_new_element_ns_cdata($item, $namespace, cc_qti_tags::mattext, $this->value); 408 $this->generate_attributes($doc, $mattext, $namespace); 409 } 410 } 411 412 class cc_assesment_matref { 413 protected $linkref = null; 414 415 public function __construct($linkref) { 416 $this->linkref = $linkref; 417 } 418 419 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 420 $doc->append_new_element_ns($item, $namespace, cc_qti_tags::matref, $this->linkref); 421 $doc->append_new_attribute_ns($node, $namespace, cc_qti_tags::linkrefid, $this->linkref); 422 } 423 } 424 425 class cc_assesment_response_matref extends cc_assesment_matref { 426 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 427 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::material_ref); 428 $doc->append_new_attribute_ns($node, $namespace, cc_qti_tags::linkrefid, $this->linkref); 429 } 430 } 431 432 class cc_assesment_matbreak { 433 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 434 $doc->append_new_element_ns($item, $namespace, cc_qti_tags::matbreak); 435 } 436 } 437 438 abstract class cc_assesment_material_base extends cc_question_metadata_base { 439 /** 440 * @var mixed 441 */ 442 protected $mattag = null; 443 protected $tagname = null; 444 445 protected function set_tag_value($object) { 446 $this->mattag = $object; 447 } 448 449 public function set_mattext(cc_assesment_mattext $object) { 450 $this->set_tag_value($object); 451 } 452 453 public function set_matref(cc_assesment_matref $object) { 454 $this->set_tag_value($object); 455 } 456 457 public function set_matbreak(cc_assesment_matbreak $object) { 458 $this->set_tag_value($object); 459 } 460 461 public function set_lang($value) { 462 $this->set_setting_wns(cc_qti_tags::xml_lang , cc_xml_namespace::xml, $value); 463 } 464 465 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 466 $material = $doc->append_new_element_ns($item, $namespace, $this->tagname); 467 $this->generate_attributes($doc, $material, $namespace); 468 if (!empty($this->mattag)) { 469 $this->mattag->generate($doc, $material, $namespace); 470 } 471 return $material; 472 } 473 } 474 475 class cc_assesment_altmaterial extends cc_assesment_material_base { 476 public function __construct($value = null) { 477 $this->set_setting_wns(cc_qti_tags::xml_lang , cc_xml_namespace::xml); 478 $this->tagname = cc_qti_tags::altmaterial; 479 } 480 } 481 482 class cc_assesment_material extends cc_assesment_material_base { 483 484 protected $altmaterial = null; 485 486 public function __construct($value = null) { 487 $this->set_setting(cc_qti_tags::label); 488 $this->set_setting_wns(cc_qti_tags::xml_lang , cc_xml_namespace::xml); 489 $this->tagname = cc_qti_tags::material; 490 } 491 492 public function set_label($value) { 493 $this->set_setting(cc_qti_tags::label, $value); 494 } 495 496 public function set_altmaterial(cc_assesment_altmaterial $object) { 497 $this->altmaterial = $object; 498 } 499 500 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 501 $material = parent::generate($doc, $item, $namespace); 502 if (!empty($this->altmaterial)) { 503 $this->altmaterial->generate($doc, $material, $namespace); 504 } 505 } 506 } 507 508 class cc_assesment_rubric_base extends cc_question_metadata_base { 509 510 protected $material = null; 511 512 public function set_material($object) { 513 $this->material = $object; 514 } 515 516 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 517 $rubric = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::rubric); 518 if (!empty($this->material)) { 519 $this->material->generate($doc, $rubric, $namespace); 520 } 521 } 522 } 523 524 class cc_assesment_presentation_material_base extends cc_question_metadata_base { 525 protected $flowmats = array(); 526 527 public function add_flow_mat($object) { 528 $this->flowmats[] = $object; 529 } 530 531 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 532 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::presentation_material); 533 if (!empty($this->flowmats)) { 534 foreach ($this->flowmats as $flow_mat) { 535 $flow_mat->generate($doc, $node, $namespace); 536 } 537 } 538 } 539 } 540 541 class cc_assesment_flow_mat_base extends cc_question_metadata_base { 542 543 protected $mattag = null; 544 545 protected function set_tag_value($object) { 546 $this->mattag = $object; 547 } 548 549 public function set_flow_mat(cc_assesment_flow_mat_base $object) { 550 $this->set_tag_value($object); 551 } 552 553 public function set_material(cc_assesment_material $object) { 554 $this->set_tag_value($object); 555 } 556 557 public function set_material_ref(cc_assesment_matref $object) { 558 $this->set_tag_value($object); 559 } 560 561 public function __construct($value = null) { 562 $this->set_setting(cc_qti_tags::t_class); 563 } 564 565 public function set_class($value) { 566 $this->set_setting(cc_qti_tags::t_class, $value); 567 } 568 569 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 570 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::flow_mat); 571 $this->generate_attributes($doc, $node, $namespace); 572 if (!empty($this->mattag)) { 573 $this->mattag->generate($doc, $node, $namespace); 574 } 575 } 576 577 } 578 579 class cc_assesment_section extends cc_question_metadata_base { 580 /** 581 * @var array 582 */ 583 protected $items = array(); 584 585 public function __construct() { 586 $this->set_setting(cc_qti_tags::ident, cc_helpers::uuidgen('I_')); 587 $this->set_setting(cc_qti_tags::title); 588 $this->set_setting_wns(cc_qti_tags::xml_lang, cc_xml_namespace::xml); 589 } 590 591 public function set_ident($value) { 592 $this->set_setting(cc_qti_tags::ident, $value); 593 } 594 595 public function set_title($value) { 596 $this->set_setting(cc_qti_tags::title, $value); 597 } 598 599 public function set_lang($value) { 600 $this->set_setting_wns(cc_qti_tags::xml_lang, cc_xml_namespace::xml, $value); 601 } 602 603 public function add_item(cc_assesment_section_item $object) { 604 $this->items[] = $object; 605 } 606 607 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 608 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::section); 609 $this->generate_attributes($doc, $node, $namespace); 610 if (!empty($this->items)) { 611 foreach ($this->items as $item) { 612 $item->generate($doc, $node, $namespace); 613 } 614 } 615 } 616 } 617 618 class cc_assesment_itemmetadata extends cc_question_metadata_base { 619 public function add_metadata($object) { 620 $this->metadata[] = $object; 621 } 622 623 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 624 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::itemmetadata); 625 if (!empty($this->metadata)) { 626 foreach ($this->metadata as $metaitem) { 627 $metaitem->generate($doc, $node, $namespace); 628 } 629 } 630 } 631 } 632 633 class cc_assesment_decvartype extends cc_question_metadata_base { 634 635 public function __construct() { 636 $this->set_setting(cc_qti_tags::varname, cc_qti_values::SCORE); 637 $this->set_setting(cc_qti_tags::vartype, cc_qti_values::Integer); 638 $this->set_setting(cc_qti_tags::minvalue); 639 $this->set_setting(cc_qti_tags::maxvalue); 640 } 641 642 public function set_vartype($value) { 643 $this->set_setting(cc_qti_tags::vartype, $value); 644 } 645 646 public function set_limits($min = null, $max = null) { 647 $this->set_setting(cc_qti_tags::minvalue, $min); 648 $this->set_setting(cc_qti_tags::maxvalue, $max); 649 } 650 651 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 652 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::decvar); 653 $this->generate_attributes($doc, $node, $namespace); 654 } 655 } 656 657 658 class cc_assignment_conditionvar_othertype extends cc_question_metadata_base { 659 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 660 $doc->append_new_element_ns($item, $namespace, cc_qti_tags::other); 661 } 662 } 663 664 class cc_assignment_conditionvar_varequaltype extends cc_question_metadata_base { 665 protected $tagname = null; 666 protected $answerid = null; 667 668 public function __construct($value = null) { 669 if (is_null($value)) { 670 throw new InvalidArgumentException('Must not pass null!'); 671 } 672 $this->answerid = $value; 673 $this->set_setting(cc_qti_tags::respident); 674 $this->set_setting(cc_qti_tags::case_);//, cc_qti_values::No ); 675 $this->tagname = cc_qti_tags::varequal; 676 } 677 678 public function set_respident($value) { 679 $this->set_setting(cc_qti_tags::respident, $value); 680 } 681 682 public function enable_case($value = true) { 683 $this->enable_setting_yesno(cc_qti_tags::case_, $value); 684 } 685 686 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 687 $node = $doc->append_new_element_ns($item, $namespace, $this->tagname, $this->answerid); 688 $this->generate_attributes($doc, $node, $namespace); 689 } 690 } 691 692 class cc_assignment_conditionvar_varsubstringtype extends cc_assignment_conditionvar_varequaltype { 693 public function __construct($value) { 694 parent::__construct($value); 695 $this->tagname = cc_qti_tags::varsubstring; 696 } 697 } 698 699 700 class cc_assignment_conditionvar_andtype extends cc_question_metadata_base { 701 protected $nots = array(); 702 protected $varequals = array(); 703 704 public function set_not(cc_assignment_conditionvar_varequaltype $object) { 705 $this->nots[] = $object; 706 } 707 708 public function set_varequal(cc_assignment_conditionvar_varequaltype $object) { 709 $this->varequals[] = $object; 710 } 711 712 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 713 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::and_); 714 if (!empty($this->nots)) { 715 foreach ($this->nots as $notv) { 716 $not = $doc->append_new_element_ns($node, $namespace, cc_qti_tags::not_); 717 $notv->generate($doc, $not, $namespace); 718 } 719 } 720 721 if (!empty($this->varequals)) { 722 foreach ($this->varequals as $varequal) { 723 $varequal->generate($doc, $node, $namespace); 724 } 725 } 726 } 727 } 728 729 class cc_assignment_conditionvar extends cc_question_metadata_base { 730 731 /** 732 * @var cc_assignment_conditionvar_andtype 733 */ 734 protected $and = null; 735 /** 736 * @var cc_assignment_conditionvar_othertype 737 */ 738 protected $other = null; 739 /** 740 * @var array 741 */ 742 protected $varequal = array(); 743 /** 744 * @var cc_assignment_conditionvar_varsubstringtype 745 */ 746 protected $varsubstring = null; 747 748 public function set_and(cc_assignment_conditionvar_andtype $object) { 749 $this->and = $object; 750 } 751 752 public function set_other(cc_assignment_conditionvar_othertype $object) { 753 $this->other = $object; 754 } 755 756 public function set_varequal(cc_assignment_conditionvar_varequaltype $object) { 757 $this->varequal[] = $object; 758 } 759 760 public function set_varsubstring(cc_assignment_conditionvar_varsubstringtype $object) { 761 $this->varsubstring = $object; 762 } 763 764 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 765 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::conditionvar); 766 767 if (!empty($this->and)) { 768 $this->and->generate($doc, $node, $namespace); 769 } 770 771 if (!empty($this->other)) { 772 $this->other->generate($doc, $node, $namespace); 773 } 774 775 if (!empty($this->varequal)) { 776 foreach ($this->varequal as $varequal) { 777 $varequal->generate($doc, $node, $namespace); 778 } 779 } 780 781 if (!empty($this->varsubstring)) { 782 $this->varsubstring->generate($doc, $node, $namespace); 783 } 784 } 785 } 786 787 class cc_assignment_displayfeedbacktype extends cc_question_metadata_base { 788 public function __construct() { 789 $this->set_setting(cc_qti_tags::feedbacktype); 790 $this->set_setting(cc_qti_tags::linkrefid); 791 } 792 793 public function set_feedbacktype($value) { 794 $this->set_setting(cc_qti_tags::feedbacktype, $value); 795 } 796 797 public function set_linkrefid($value) { 798 $this->set_setting(cc_qti_tags::linkrefid, $value); 799 } 800 801 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 802 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::displayfeedback); 803 $this->generate_attributes($doc, $node, $namespace); 804 } 805 } 806 807 808 class cc_assignment_setvartype extends cc_question_metadata_base { 809 /** 810 * @var integer 811 */ 812 protected $tagvalue = null; 813 814 public function __construct($tagvalue = 100) { 815 $this->set_setting(cc_qti_tags::varname, cc_qti_values::SCORE); 816 $this->set_setting(cc_qti_tags::action , cc_qti_values::Set ); 817 $this->tagvalue = $tagvalue; 818 } 819 820 public function set_varname($value) { 821 $this->set_setting(cc_qti_tags::varname, $value); 822 } 823 824 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 825 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::setvar, $this->tagvalue); 826 $this->generate_attributes($doc, $node, $namespace); 827 } 828 } 829 830 class cc_assesment_respconditiontype extends cc_question_metadata_base { 831 /** 832 * @var cc_assignment_conditionvar 833 */ 834 protected $conditionvar = null; 835 protected $setvar = array(); 836 protected $displayfeedback = array(); 837 838 public function __construct() { 839 $this->set_setting(cc_qti_tags::title); 840 $this->set_setting(cc_qti_tags::continue_, cc_qti_values::No); 841 } 842 843 public function set_title($value) { 844 $this->set_setting(cc_qti_tags::title, $value); 845 } 846 847 public function enable_continue($value = true) { 848 $this->enable_setting_yesno(cc_qti_tags::continue_, $value); 849 } 850 851 public function set_conditionvar(cc_assignment_conditionvar $object) { 852 $this->conditionvar = $object; 853 } 854 855 public function add_setvar(cc_assignment_setvartype $object) { 856 $this->setvar[] = $object; 857 } 858 859 public function add_displayfeedback(cc_assignment_displayfeedbacktype $object) { 860 $this->displayfeedback[] = $object; 861 } 862 863 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 864 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::respcondition); 865 $this->generate_attributes($doc, $node, $namespace); 866 867 if (!empty($this->conditionvar)) { 868 $this->conditionvar->generate($doc, $node, $namespace); 869 } 870 871 if (!empty($this->setvar)) { 872 foreach ($this->setvar as $setvar) { 873 $setvar->generate($doc, $node, $namespace); 874 } 875 } 876 877 if (!empty($this->displayfeedback)) { 878 foreach ($this->displayfeedback as $displayfeedback) { 879 $displayfeedback->generate($doc, $node, $namespace); 880 } 881 } 882 } 883 } 884 885 886 class cc_assesment_resprocessingtype extends cc_question_metadata_base { 887 /** 888 * @var cc_assesment_decvartype 889 */ 890 protected $decvar = null; 891 /** 892 * @var array 893 */ 894 protected $respconditions = array(); 895 896 public function set_decvar(cc_assesment_decvartype $object) { 897 $this->decvar = $object; 898 } 899 900 public function add_respcondition(cc_assesment_respconditiontype $object) { 901 $this->respconditions[] = $object; 902 } 903 904 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 905 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::resprocessing); 906 $outcomes = $doc->append_new_element_ns($node, $namespace, cc_qti_tags::outcomes); 907 if (!empty($this->decvar)) { 908 $this->decvar->generate($doc, $outcomes, $namespace); 909 } 910 if (!empty($this->respconditions)) { 911 foreach ($this->respconditions as $rcond) { 912 $rcond->generate($doc, $node, $namespace); 913 } 914 } 915 } 916 } 917 918 919 class cc_assesment_itemfeedback_shintmaterial_base extends cc_question_metadata_base { 920 /** 921 * @var string 922 */ 923 protected $tagname = null; 924 /** 925 * @var array 926 */ 927 protected $flow_mats = array(); 928 /** 929 * @var array 930 */ 931 protected $materials = array(); 932 933 /** 934 * @param cc_assesment_flow_mattype $object 935 */ 936 public function add_flow_mat(cc_assesment_flow_mattype $object) { 937 $this->flow_mats[] = $object; 938 } 939 940 /** 941 * @param cc_assesment_material $object 942 */ 943 public function add_material(cc_assesment_material $object) { 944 $this->materials[] = $object; 945 } 946 947 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 948 $node = $doc->append_new_element_ns($item, $namespace, $this->tagname); 949 950 if (!empty($this->flow_mats)) { 951 foreach ($this->flow_mats as $flow_mat) { 952 $flow_mat->generate($doc, $node, $namespace); 953 } 954 } 955 956 if (!empty($this->materials)) { 957 foreach ($this->materials as $material) { 958 $material->generate($doc, $node, $namespace); 959 } 960 } 961 } 962 } 963 964 class cc_assesment_itemfeedback_hintmaterial extends cc_assesment_itemfeedback_shintmaterial_base { 965 public function __construct() { 966 $this->tagname = cc_qti_tags::hint; 967 } 968 } 969 970 class cc_assesment_itemfeedback_solutionmaterial extends cc_assesment_itemfeedback_shintmaterial_base { 971 public function __construct() { 972 $this->tagname = cc_qti_tags::solutionmaterial; 973 } 974 } 975 976 class cc_assesment_itemfeedback_shintype_base extends cc_question_metadata_base { 977 /** 978 * @var string 979 */ 980 protected $tagname = null; 981 /** 982 * @var array 983 */ 984 protected $items = array(); 985 986 public function __construct() { 987 $this->set_setting(cc_qti_tags::feedbackstyle, cc_qti_values::Complete); 988 } 989 990 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 991 $node = $doc->append_new_element_ns($item, $namespace, $this->tagname); 992 $this->generate_attributes($doc, $node, $namespace); 993 994 if (!empty($this->items)) { 995 foreach ($this->items as $telement) { 996 $telement->generate($doc, $node, $namespace); 997 } 998 } 999 } 1000 } 1001 1002 class cc_assesment_itemfeedback_solutiontype extends cc_assesment_itemfeedback_shintype_base { 1003 public function __construct() { 1004 parent::__construct(); 1005 $this->tagname = cc_qti_tags::solution; 1006 } 1007 1008 /** 1009 * @param cc_assesment_itemfeedback_solutionmaterial $object 1010 */ 1011 public function add_solutionmaterial(cc_assesment_itemfeedback_solutionmaterial $object) { 1012 $this->items[] = $object; 1013 } 1014 } 1015 1016 class cc_assesment_itemfeedbac_hinttype extends cc_assesment_itemfeedback_shintype_base { 1017 public function __construct() { 1018 parent::__construct(); 1019 $this->tagname = cc_qti_tags::hint; 1020 } 1021 1022 /** 1023 * @param cc_assesment_itemfeedback_hintmaterial $object 1024 */ 1025 public function add_hintmaterial(cc_assesment_itemfeedback_hintmaterial $object) { 1026 $this->items[] = $object; 1027 } 1028 } 1029 1030 class cc_assesment_itemfeedbacktype extends cc_question_metadata_base { 1031 /** 1032 * @var cc_assesment_flow_mattype 1033 */ 1034 protected $flow_mat = null; 1035 /** 1036 * @var cc_assesment_material 1037 */ 1038 protected $material = null; 1039 /** 1040 * @var cc_assesment_itemfeedback_solutiontype 1041 */ 1042 protected $solution = null; 1043 protected $hint = null; 1044 1045 /** @var cc_assignment_displayfeedbacktype item feedback. */ 1046 protected $itemfeedback; 1047 1048 public function __construct() { 1049 $this->set_setting(cc_qti_tags::ident, cc_helpers::uuidgen('I_')); 1050 $this->set_setting(cc_qti_tags::title); 1051 } 1052 1053 /** 1054 * @param string $value 1055 */ 1056 public function set_ident($value) { 1057 $this->set_setting(cc_qti_tags::ident, $value); 1058 } 1059 1060 /** 1061 * @param string $value 1062 */ 1063 public function set_title($value) { 1064 $this->set_setting(cc_qti_tags::title, $value); 1065 } 1066 1067 /** 1068 * @param cc_assesment_flow_mattype $object 1069 */ 1070 public function set_flow_mat(cc_assesment_flow_mattype $object) { 1071 $this->flow_mat = $object; 1072 } 1073 1074 /** 1075 * @param cc_assesment_material $object 1076 */ 1077 public function set_material(cc_assesment_material $object) { 1078 $this->material = $object; 1079 } 1080 1081 /** 1082 * @param cc_assesment_itemfeedback_solutiontype $object 1083 */ 1084 public function set_solution(cc_assesment_itemfeedback_solutiontype $object) { 1085 $this->solution = $object; 1086 } 1087 1088 public function set_hint($object) { 1089 $this->hint = $object; 1090 } 1091 1092 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1093 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::itemfeedback); 1094 $this->generate_attributes($doc, $node, $namespace); 1095 1096 if (!empty($this->flow_mat) && empty($this->material)) { 1097 $this->flow_mat->generate($doc, $node, $namespace); 1098 } 1099 1100 if (!empty($this->material) && empty($this->flow_mat)) { 1101 $this->material->generate($doc, $node, $namespace); 1102 } 1103 1104 if (!empty($this->solution)) { 1105 $this->solution->generate($doc, $node, $namespace); 1106 } 1107 1108 if (!empty($this->itemfeedback)) { 1109 $this->itemfeedback->generate($doc, $node, $namespace); 1110 } 1111 } 1112 } 1113 1114 class cc_assesment_section_item extends cc_assesment_section { 1115 1116 /** 1117 * @var cc_assesment_itemmetadata 1118 */ 1119 protected $itemmetadata = null; 1120 /** 1121 * @var cc_assesment_presentation 1122 */ 1123 protected $presentation = null; 1124 protected $resprocessing = array(); 1125 protected $itemfeedback = array(); 1126 1127 public function set_itemmetadata(cc_assesment_itemmetadata $object) { 1128 $this->itemmetadata = $object; 1129 } 1130 1131 public function set_presentation(cc_assesment_presentation $object) { 1132 $this->presentation = $object; 1133 } 1134 1135 public function add_resprocessing(cc_assesment_resprocessingtype $object) { 1136 $this->resprocessing[] = $object; 1137 } 1138 1139 public function add_itemfeedback(cc_assesment_itemfeedbacktype $object) { 1140 $this->itemfeedback[] = $object; 1141 } 1142 1143 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1144 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::item); 1145 $this->generate_attributes($doc, $node, $namespace); 1146 1147 if (!empty($this->itemmetadata)) { 1148 $this->itemmetadata->generate($doc, $node, $namespace); 1149 } 1150 1151 if (!empty($this->presentation)) { 1152 $this->presentation->generate($doc, $node, $namespace); 1153 } 1154 1155 if (!empty($this->resprocessing)) { 1156 foreach ($this->resprocessing as $resprocessing) { 1157 $resprocessing->generate($doc, $node, $namespace); 1158 } 1159 } 1160 1161 if (!empty($this->itemfeedback)) { 1162 foreach ($this->itemfeedback as $itemfeedback) { 1163 $itemfeedback->generate($doc, $node, $namespace); 1164 } 1165 } 1166 } 1167 } 1168 1169 class cc_assesment_render_choicetype extends cc_question_metadata_base { 1170 /** 1171 * @var array 1172 */ 1173 protected $materials = array(); 1174 1175 /** 1176 * @var array 1177 */ 1178 protected $material_refs = array(); 1179 1180 /** 1181 * @var array 1182 */ 1183 protected $response_labels = array(); 1184 /** 1185 * @var array 1186 */ 1187 protected $flow_labels = array(); 1188 1189 public function __construct() { 1190 $this->set_setting(cc_qti_tags::shuffle, cc_qti_values::No); 1191 $this->set_setting(cc_qti_tags::minnumber); 1192 $this->set_setting(cc_qti_tags::maxnumber); 1193 } 1194 1195 public function add_material(cc_assesment_material $object) { 1196 $this->materials[] = $object; 1197 } 1198 1199 public function add_material_ref(cc_assesment_response_matref $object) { 1200 $this->material_refs[] = $object; 1201 } 1202 1203 public function add_response_label(cc_assesment_response_labeltype $object) { 1204 $this->response_labels[] = $object; 1205 } 1206 1207 public function add_flow_label($object) { 1208 $this->flow_labels[] = $object; 1209 } 1210 1211 public function enable_shuffle($value = true) { 1212 $this->enable_setting_yesno(cc_qti_tags::shuffle, $value); 1213 } 1214 1215 public function set_limits($min = null, $max = null) { 1216 $this->set_setting(cc_qti_tags::minnumber, $min); 1217 $this->set_setting(cc_qti_tags::maxnumber, $max); 1218 } 1219 1220 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1221 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::render_choice); 1222 $this->generate_attributes($doc, $node, $namespace); 1223 1224 if (!empty($this->materials)) { 1225 foreach ($this->materials as $mattag) { 1226 $mattag->generate($doc, $node, $namespace); 1227 } 1228 } 1229 1230 if (!empty($this->material_refs)) { 1231 foreach ($this->material_refs as $matreftag) { 1232 $matreftag->generate($doc, $node, $namespace); 1233 } 1234 } 1235 1236 if (!empty($this->response_labels)) { 1237 foreach ($this->response_labels as $resplabtag) { 1238 $resplabtag->generate($doc, $node, $namespace); 1239 } 1240 } 1241 1242 if (!empty($this->flow_labels)) { 1243 foreach ($this->flow_labels as $flowlabtag) { 1244 $flowlabtag->generate($doc, $node, $namespace); 1245 } 1246 } 1247 } 1248 1249 } 1250 1251 class cc_assesment_flow_mattype extends cc_question_metadata_base { 1252 1253 /** 1254 * @var cc_assesment_material 1255 */ 1256 protected $material = null; 1257 /** 1258 * @var cc_assesment_response_matref 1259 */ 1260 protected $material_ref = null; 1261 /** 1262 * @var cc_assesment_flow_mattype 1263 */ 1264 protected $flow_mat = null; 1265 1266 public function __construct() { 1267 $this->set_setting(cc_qti_tags::t_class); 1268 } 1269 1270 public function set_class($value) { 1271 $this->set_setting(cc_qti_tags::t_class, $value); 1272 } 1273 1274 public function set_material(cc_assesment_material $object) { 1275 $this->material = $object; 1276 } 1277 1278 public function set_material_ref(cc_assesment_response_matref $object) { 1279 $this->material_ref = $object; 1280 } 1281 1282 public function set_flow_mat(cc_assesment_flow_mattype $object) { 1283 $this->flow_mat = $object; 1284 } 1285 1286 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1287 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::flow_mat); 1288 $this->generate_attributes($doc, $node, $namespace); 1289 1290 if (!empty($this->flow_mat)) { 1291 $this->flow_mat->generate($doc, $node, $namespace); 1292 } 1293 1294 if (!empty($this->material)) { 1295 $this->material->generate($doc, $node, $namespace); 1296 } 1297 1298 if (!empty($this->material_ref)) { 1299 $this->material_ref->generate($doc, $node, $namespace); 1300 } 1301 } 1302 } 1303 1304 class cc_assesment_response_labeltype extends cc_question_metadata_base { 1305 /** 1306 * @var cc_assesment_material 1307 */ 1308 protected $material = null; 1309 1310 /** 1311 * @var cc_assesment_response_matref 1312 */ 1313 protected $material_ref = null; 1314 1315 /** 1316 * @var cc_assesment_flow_mattype 1317 */ 1318 protected $flow_mat = null; 1319 1320 public function __construct() { 1321 $this->set_setting(cc_qti_tags::ident, cc_helpers::uuidgen('I_')); 1322 $this->set_setting(cc_qti_tags::labelrefid); 1323 $this->set_setting(cc_qti_tags::rshuffle); 1324 $this->set_setting(cc_qti_tags::match_group); 1325 $this->set_setting(cc_qti_tags::match_max); 1326 } 1327 1328 public function set_ident($value) { 1329 $this->set_setting(cc_qti_tags::ident, $value); 1330 } 1331 1332 public function get_ident() { 1333 return $this->get_setting(cc_qti_tags::ident); 1334 } 1335 1336 public function set_labelrefid($value) { 1337 $this->set_setting(cc_qti_tags::labelrefid, $value); 1338 } 1339 1340 public function enable_rshuffle($value = true) { 1341 $this->enable_setting_yesno(cc_qti_tags::rshuffle, $value); 1342 } 1343 1344 public function set_match_group($value) { 1345 $this->set_setting(cc_qti_tags::match_group, $value); 1346 } 1347 1348 public function set_match_max($value) { 1349 $this->set_setting(cc_qti_tags::match_max, $value); 1350 } 1351 1352 public function set_material(cc_assesment_material $object) { 1353 $this->material = $object; 1354 } 1355 1356 public function set_material_ref(cc_assesment_response_matref $object) { 1357 $this->material_ref = $object; 1358 } 1359 1360 public function set_flow_mat(cc_assesment_flow_mattype $object) { 1361 $this->flow_mat = $object; 1362 } 1363 1364 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1365 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::response_label); 1366 $this->generate_attributes($doc, $node, $namespace); 1367 1368 if (!empty($this->material)) { 1369 $this->material->generate($doc, $node, $namespace); 1370 } 1371 1372 if (!empty($this->material_ref)) { 1373 $this->material_ref->generate($doc, $node, $namespace); 1374 } 1375 1376 if (!empty($this->flow_mat)) { 1377 $this->flow_mat->generate($doc, $node, $namespace); 1378 } 1379 } 1380 } 1381 1382 class cc_assesment_flow_labeltype extends cc_question_metadata_base { 1383 /** 1384 * @var cc_assesment_flow_labeltype 1385 */ 1386 protected $flow_label = null; 1387 /** 1388 * @var cc_assesment_response_labeltype 1389 */ 1390 protected $response_label = null; 1391 1392 /** @var cc_assesment_material assesment material. */ 1393 protected $material; 1394 1395 /** @var cc_assesment_response_matref assesment response material ref. */ 1396 protected $material_ref; 1397 1398 public function __construct() { 1399 $this->set_setting(cc_qti_tags::t_class); 1400 } 1401 1402 public function set_class($value) { 1403 $this->set_setting(cc_qti_tags::t_class, $value); 1404 } 1405 1406 public function set_flow_label(cc_assesment_flow_labeltype $object) { 1407 $this->flow_label = $object; 1408 } 1409 1410 public function set_response_label(cc_assesment_response_labeltype $object) { 1411 $this->response_label = $object; 1412 } 1413 1414 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1415 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::flow_label); 1416 $this->generate_attributes($doc, $node, $namespace); 1417 1418 if (!empty($this->material)) { 1419 $this->material->generate($doc, $node, $namespace); 1420 } 1421 1422 if (!empty($this->material_ref)) { 1423 $this->material_ref->generate($doc, $node, $namespace); 1424 } 1425 1426 if (!empty($this->response_label)) { 1427 $this->response_label->generate($doc, $node, $namespace); 1428 } 1429 1430 if (!empty($this->flow_label)) { 1431 $this->flow_label->generate($doc, $node, $namespace); 1432 } 1433 } 1434 1435 } 1436 1437 1438 class cc_assesment_render_fibtype extends cc_question_metadata_base { 1439 /** 1440 * @var cc_assesment_material 1441 */ 1442 protected $material = null; 1443 1444 /** 1445 * @var cc_assesment_response_matref 1446 */ 1447 protected $material_ref = null; 1448 /** 1449 * @var cc_assesment_response_labeltype 1450 */ 1451 protected $response_label = null; 1452 /** 1453 * 1454 * Enter description here ... 1455 * @var unknown_type 1456 */ 1457 protected $flow_label = null; 1458 1459 1460 public function __construct() { 1461 $this->set_setting(cc_qti_tags::encoding ); 1462 $this->set_setting(cc_qti_tags::charset ); 1463 $this->set_setting(cc_qti_tags::rows ); 1464 $this->set_setting(cc_qti_tags::columns ); 1465 $this->set_setting(cc_qti_tags::maxchars ); 1466 $this->set_setting(cc_qti_tags::minnumber); 1467 $this->set_setting(cc_qti_tags::maxnumber); 1468 $this->set_setting(cc_qti_tags::prompt, cc_qti_values::Box); 1469 $this->set_setting(cc_qti_tags::fibtype, cc_qti_values::String); 1470 } 1471 1472 public function set_encoding($value) { 1473 $this->set_setting(cc_qti_tags::encoding, $value); 1474 } 1475 public function set_charset($value) { 1476 $this->set_setting(cc_qti_tags::charset, $value); 1477 } 1478 1479 public function set_rows($value) { 1480 $this->set_setting(cc_qti_tags::rows, $value); 1481 } 1482 1483 public function set_columns($value) { 1484 $this->set_setting(cc_qti_tags::columns, $value); 1485 } 1486 1487 public function set_maxchars($value) { 1488 $this->set_setting(cc_qti_tags::columns, $value); 1489 } 1490 1491 public function set_limits($min = null, $max = null) { 1492 $this->set_setting(cc_qti_tags::minnumber, $min); 1493 $this->set_setting(cc_qti_tags::maxnumber, $max); 1494 } 1495 1496 public function set_prompt($value) { 1497 $this->set_setting(cc_qti_tags::prompt, $value); 1498 } 1499 1500 public function set_fibtype($value) { 1501 $this->set_setting(cc_qti_tags::fibtype, $value); 1502 } 1503 1504 public function set_material(cc_assesment_material $object) { 1505 $this->material = $object; 1506 } 1507 1508 public function set_material_ref(cc_assesment_response_matref $object) { 1509 $this->material_ref = $object; 1510 } 1511 1512 public function set_response_label(cc_assesment_response_labeltype $object) { 1513 $this->response_label = $object; 1514 } 1515 1516 public function set_flow_label($object) { 1517 $this->flow_label = $object; 1518 } 1519 1520 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1521 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::render_fib); 1522 $this->generate_attributes($doc, $node, $namespace); 1523 1524 if (!empty($this->material) && empty($this->material_ref)) { 1525 $this->material->generate($doc, $node, $namespace); 1526 } 1527 1528 if (!empty($this->material_ref) && empty($this->material)) { 1529 $this->material_ref->generate($doc, $node, $namespace); 1530 } 1531 1532 if (!empty($this->response_label)) { 1533 $this->response_label->generate($doc, $node, $namespace); 1534 } 1535 1536 if (!empty($this->flow_label)) { 1537 $this->flow_label->generate($doc, $node, $namespace); 1538 } 1539 } 1540 } 1541 1542 class cc_response_lidtype extends cc_question_metadata_base { 1543 /** 1544 * @var string 1545 */ 1546 protected $tagname = null; 1547 /** 1548 * @var cc_assesment_material 1549 */ 1550 protected $material = null; 1551 1552 /** 1553 * @var cc_assesment_response_matref 1554 */ 1555 protected $material_ref = null; 1556 1557 /** 1558 * @var cc_assesment_render_choicetype 1559 */ 1560 protected $render_choice = null; 1561 1562 /** 1563 * @var cc_assesment_render_fibtype 1564 */ 1565 protected $render_fib = null; 1566 1567 public function __construct() { 1568 $this->set_setting(cc_qti_tags::rcardinality, cc_qti_values::Single); 1569 $this->set_setting(cc_qti_tags::rtiming); 1570 $this->set_setting(cc_qti_tags::ident, cc_helpers::uuidgen('I_')); 1571 $this->tagname = cc_qti_tags::response_lid; 1572 } 1573 1574 public function set_rcardinality($value) { 1575 $this->set_setting(cc_qti_tags::rcardinality, $value); 1576 } 1577 1578 public function enable_rtiming($value = true) { 1579 $this->enable_setting_yesno(cc_qti_tags::rtiming, $value); 1580 } 1581 1582 public function set_ident($value) { 1583 $this->set_setting(cc_qti_tags::ident, $value); 1584 } 1585 1586 public function get_ident() { 1587 return $this->get_setting(cc_qti_tags::ident); 1588 } 1589 1590 public function set_material_ref(cc_assesment_response_matref $object) { 1591 $this->material_ref = $object; 1592 } 1593 1594 public function set_material(cc_assesment_material $object) { 1595 $this->material = $object; 1596 } 1597 1598 public function set_render_choice(cc_assesment_render_choicetype $object) { 1599 $this->render_choice = $object; 1600 } 1601 1602 public function set_render_fib(cc_assesment_render_fibtype $object) { 1603 $this->render_fib = $object; 1604 } 1605 1606 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1607 $node = $doc->append_new_element_ns($item, $namespace, $this->tagname); 1608 $this->generate_attributes($doc, $node, $namespace); 1609 1610 if (!empty($this->material) && empty($this->material_ref)) { 1611 $this->material->generate($doc, $node, $namespace); 1612 } 1613 1614 if (!empty($this->material_ref) && empty($this->material)) { 1615 $this->material_ref->generate($doc, $node, $namespace); 1616 } 1617 1618 if (!empty($this->render_choice) && empty($this->render_fib)) { 1619 $this->render_choice->generate($doc, $node, $namespace); 1620 } 1621 1622 if (!empty($this->render_fib) && empty($this->render_choice)) { 1623 $this->render_fib->generate($doc, $node, $namespace); 1624 } 1625 } 1626 } 1627 1628 class cc_assesment_response_strtype extends cc_response_lidtype { 1629 public function __construct() { 1630 $rtt = parent::__construct(); 1631 $this->tagname = cc_qti_tags::response_str; 1632 } 1633 } 1634 1635 class cc_assesment_flowtype extends cc_question_metadata_base { 1636 /** 1637 * @var cc_assesment_flowtype 1638 */ 1639 protected $flow = null; 1640 /** 1641 * @var cc_assesment_material 1642 */ 1643 protected $material = null; 1644 /** 1645 * @var cc_assesment_response_matref 1646 */ 1647 protected $material_ref = null; 1648 /** 1649 * @var cc_response_lidtype 1650 */ 1651 protected $response_lid = null; 1652 /** 1653 * @var cc_assesment_response_strtype 1654 */ 1655 protected $response_str = null; 1656 1657 public function __construct() { 1658 $this->set_setting(cc_qti_tags::t_class); 1659 } 1660 1661 public function set_class($value) { 1662 $this->set_setting(cc_qti_tags::t_class, $value); 1663 } 1664 1665 public function set_flow(cc_assesment_flowtype $object) { 1666 $this->flow = $object; 1667 } 1668 1669 public function set_material(cc_assesment_material $object) { 1670 $this->material = $object; 1671 } 1672 1673 public function set_material_ref(cc_assesment_response_matref $object) { 1674 $this->material_ref = $object; 1675 } 1676 1677 public function set_response_lid(cc_response_lidtype $object) { 1678 $this->response_lid = $object; 1679 } 1680 1681 public function set_response_str(cc_assesment_response_strtype $object) { 1682 $this->response_str = $object; 1683 } 1684 1685 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1686 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::flow); 1687 $this->generate_attributes($doc, $node, $namespace); 1688 1689 if (!empty($this->flow)) { 1690 $this->flow->generate($doc, $node, $namespace); 1691 } 1692 1693 if (!empty($this->material)) { 1694 $this->material->generate($doc, $node, $namespace); 1695 } 1696 1697 if (!empty($this->response_lid)) { 1698 $this->response_lid->generate($doc, $node, $namespace); 1699 } 1700 1701 if (!empty($this->response_str)) { 1702 $this->response_str->generate($doc, $node, $namespace); 1703 } 1704 } 1705 } 1706 1707 class cc_assesment_presentation extends cc_question_metadata_base { 1708 /** 1709 * @var cc_assesment_flowtype 1710 */ 1711 protected $flow = null; 1712 /** 1713 * @var cc_assesment_material 1714 */ 1715 protected $material = null; 1716 /** 1717 * @var cc_response_lidtype 1718 */ 1719 protected $response_lid = null; 1720 /** 1721 * @var cc_assesment_response_strtype 1722 */ 1723 protected $response_str = null; 1724 1725 public function __construct() { 1726 $this->set_setting(cc_qti_tags::label); 1727 $this->set_setting_wns(cc_qti_tags::xml_lang , cc_xml_namespace::xml); 1728 $this->set_setting(cc_qti_tags::x0); 1729 $this->set_setting(cc_qti_tags::y0); 1730 $this->set_setting(cc_qti_tags::width); 1731 $this->set_setting(cc_qti_tags::height); 1732 } 1733 1734 public function set_label($value) { 1735 $this->set_setting(cc_qti_tags::label, $value); 1736 } 1737 1738 public function set_lang($value) { 1739 $this->set_setting_wns(cc_qti_tags::xml_lang , cc_xml_namespace::xml, $value); 1740 } 1741 1742 public function set_coor($x = null, $y = null) { 1743 $this->set_setting(cc_qti_tags::x0, $x); 1744 $this->set_setting(cc_qti_tags::y0, $y); 1745 } 1746 1747 public function set_size($width = null, $height = null) { 1748 $this->set_setting(cc_qti_tags::width, $width); 1749 $this->set_setting(cc_qti_tags::height, $height); 1750 } 1751 1752 public function set_flow(cc_assesment_flowtype $object) { 1753 $this->flow = $object; 1754 } 1755 1756 public function set_material(cc_assesment_material $object) { 1757 $this->material = $object; 1758 } 1759 1760 public function set_response_lid(cc_response_lidtype $object) { 1761 $this->response_lid = $object; 1762 } 1763 1764 public function set_response_str(cc_assesment_response_strtype $object) { 1765 $this->response_str = $object; 1766 } 1767 1768 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1769 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::presentation); 1770 $this->generate_attributes($doc, $node, $namespace); 1771 1772 if (!empty($this->flow)) { 1773 $this->flow->generate($doc, $node, $namespace); 1774 } 1775 1776 if (!empty($this->material) && empty($this->flow)) { 1777 $this->material->generate($doc, $node, $namespace); 1778 } 1779 1780 if (!empty($this->response_lid) && empty($this->flow)) { 1781 $this->response_lid->generate($doc, $node, $namespace); 1782 } 1783 1784 if (!empty($this->response_str) && empty($this->flow)) { 1785 $this->response_str->generate($doc, $node, $namespace); 1786 } 1787 } 1788 } 1789 1790 class assesment1_resurce_file extends general_cc_file { 1791 const deafultname = 'assesment.xml'; 1792 1793 protected $rootns = 'xmlns'; 1794 protected $rootname = cc_qti_tags::questestinterop; 1795 protected $ccnamespaces = array('xmlns' => 'http://www.imsglobal.org/xsd/ims_qtiasiv1p2', 1796 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance'); 1797 protected $ccnsnames = array('xmlns' => 'http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_4/ims_qtiasiv1p2_localised.xsd'); 1798 1799 /** 1800 * @var string 1801 */ 1802 protected $assessment_title = 'Untitled'; 1803 /** 1804 * @var cc_assesment_metadata 1805 */ 1806 protected $metadata = null; 1807 /** 1808 * @var cc_assesment_rubric_base 1809 */ 1810 protected $rubric = null; 1811 1812 /** 1813 * @var cc_assesment_presentation_material_base 1814 */ 1815 protected $presentation_material = null; 1816 1817 /** 1818 * @var cc_assesment_section 1819 */ 1820 protected $section = null; 1821 1822 public function set_metadata(cc_assesment_metadata $object) { 1823 $this->metadata = $object; 1824 } 1825 1826 public function set_rubric(cc_assesment_rubric_base $object) { 1827 $this->rubric = $object; 1828 } 1829 1830 public function set_presentation_material(cc_assesment_presentation_material_base $object) { 1831 $this->presentation_material = $object; 1832 } 1833 1834 public function set_section(cc_assesment_section $object) { 1835 $this->section = $object; 1836 } 1837 1838 public function set_title($value) { 1839 $this->assessment_title = self::safexml($value); 1840 } 1841 1842 protected function on_save() { 1843 $rns = $this->ccnamespaces[$this->rootns]; 1844 //root assesment element - required 1845 $assessment = $this->append_new_element_ns($this->root, $rns, cc_qti_tags::assessment); 1846 $this->append_new_attribute_ns($assessment, $rns, cc_qti_tags::ident, cc_helpers::uuidgen('QDB_')); 1847 $this->append_new_attribute_ns($assessment, $rns, cc_qti_tags::title, $this->assessment_title); 1848 1849 //metadata - optional 1850 if (!empty($this->metadata)) { 1851 $this->metadata->generate($this, $assessment, $rns); 1852 } 1853 1854 //rubric - optional 1855 if (!empty($this->rubric)) { 1856 $this->rubric->generate($this, $assessment, $rns); 1857 } 1858 1859 //presentation_material - optional 1860 if (!empty($this->presentation_material)) { 1861 $this->presentation_material->generate($this, $assessment, $rns); 1862 } 1863 1864 //section - required 1865 if (!empty($this->section)) { 1866 $this->section->generate($this, $assessment, $rns); 1867 } 1868 1869 return true; 1870 } 1871 } 1872 1873 1874 class assesment11_resurce_file extends assesment1_resurce_file { 1875 protected $ccnsnames = array('xmlns' => 'http://www.imsglobal.org/profile/cc/ccv1p1/ccv1p1_qtiasiv1p2p1_v1p0.xsd'); 1876 } 1877 1878 abstract class cc_assesment_helper { 1879 1880 public static $correct_fb = null; 1881 public static $incorrect_fb = null; 1882 1883 public static function add_feedback($qitem, $content, $content_type, $ident) { 1884 if (empty($content)) { 1885 return false; 1886 } 1887 $qitemfeedback = new cc_assesment_itemfeedbacktype(); 1888 $qitem->add_itemfeedback($qitemfeedback); 1889 if (!empty($ident)) { 1890 $qitemfeedback->set_ident($ident); 1891 } 1892 $qflowmat = new cc_assesment_flow_mattype(); 1893 $qitemfeedback->set_flow_mat($qflowmat); 1894 $qmaterialfb = new cc_assesment_material(); 1895 $qflowmat->set_material($qmaterialfb); 1896 $qmattext = new cc_assesment_mattext(); 1897 $qmaterialfb->set_mattext($qmattext); 1898 $qmattext->set_content($content, $content_type); 1899 return true; 1900 } 1901 1902 public static function add_answer($qresponse_choice, $content, $content_type) { 1903 $qresponse_label = new cc_assesment_response_labeltype(); 1904 $qresponse_choice->add_response_label($qresponse_label); 1905 $qrespmaterial = new cc_assesment_material(); 1906 $qresponse_label->set_material($qrespmaterial); 1907 $qrespmattext = new cc_assesment_mattext(); 1908 $qrespmaterial->set_mattext($qrespmattext); 1909 $qrespmattext->set_content($content, $content_type); 1910 return $qresponse_label; 1911 } 1912 1913 public static function add_response_condition($node, $title, $ident, $feedback_refid, $respident) { 1914 $qrespcondition = new cc_assesment_respconditiontype(); 1915 $node->add_respcondition($qrespcondition); 1916 //define rest of the conditions 1917 $qconditionvar = new cc_assignment_conditionvar(); 1918 $qrespcondition->set_conditionvar($qconditionvar); 1919 $qvarequal = new cc_assignment_conditionvar_varequaltype($ident); 1920 $qvarequal->enable_case(); 1921 $qconditionvar->set_varequal($qvarequal); 1922 $qvarequal->set_respident($respident); 1923 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 1924 $qrespcondition->add_displayfeedback($qdisplayfeedback); 1925 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 1926 $qdisplayfeedback->set_linkrefid($feedback_refid); 1927 } 1928 1929 public static function add_assesment_description($rt, $content, $contenttype) { 1930 if (empty($rt) || empty($content)) { 1931 return; 1932 } 1933 $activity_rubric = new cc_assesment_rubric_base(); 1934 $rubric_material = new cc_assesment_material(); 1935 $activity_rubric->set_material($rubric_material); 1936 $rubric_mattext = new cc_assesment_mattext(); 1937 $rubric_material->set_label('Summary'); 1938 $rubric_material->set_mattext($rubric_mattext); 1939 $rubric_mattext->set_content($content, $contenttype); 1940 $rt->set_rubric($activity_rubric); 1941 } 1942 1943 public static function add_respcondition($node, $title, $feedback_refid, $grade_value = null, $continue = false ) { 1944 $qrespcondition = new cc_assesment_respconditiontype(); 1945 $qrespcondition->set_title($title); 1946 $node->add_respcondition($qrespcondition); 1947 $qrespcondition->enable_continue($continue); 1948 //Add setvar if grade present 1949 if ($grade_value !== null) { 1950 $qsetvar = new cc_assignment_setvartype($grade_value); 1951 $qrespcondition->add_setvar($qsetvar); 1952 } 1953 //define the condition for success 1954 $qconditionvar = new cc_assignment_conditionvar(); 1955 $qrespcondition->set_conditionvar($qconditionvar); 1956 $qother = new cc_assignment_conditionvar_othertype(); 1957 $qconditionvar->set_other($qother); 1958 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 1959 $qrespcondition->add_displayfeedback($qdisplayfeedback); 1960 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 1961 $qdisplayfeedback->set_linkrefid($feedback_refid); 1962 } 1963 1964 /** 1965 * 1966 * Enter description here ... 1967 * @param XMLGenericDocument $qdoc 1968 * @param unknown_type $manifest 1969 * @param cc_assesment_section $section 1970 * @param unknown_type $rootpath 1971 * @param unknown_type $contextid 1972 * @param unknown_type $outdir 1973 */ 1974 public static function process_questions(&$qdoc, &$manifest, cc_assesment_section &$section, $rootpath, $contextid, $outdir) { 1975 $question_file = $rootpath . DIRECTORY_SEPARATOR . 'questions.xml'; 1976 //load questions file 1977 $questions = new XMLGenericDocument(); 1978 if (!$questions->load($question_file)) { 1979 return false; 1980 } 1981 1982 pkg_resource_dependencies::instance()->reset(); 1983 $questioncount = 0; 1984 $questionforexport = 0; 1985 $qids = $qdoc->nodeList('//question_instances//questionid'); 1986 foreach ($qids as $qid) { 1987 /** @var DOMNode $qid */ 1988 $value = $qid->nodeValue; 1989 if (intval($value) == 0) { 1990 continue; 1991 } 1992 $question_node = $questions->node("//question_category/questions/question[@id='{$value}']"); 1993 if (empty($question_node)) { 1994 continue; 1995 } 1996 ++$questionforexport; 1997 //process question 1998 //question type 1999 $qtype = $questions->nodeValue('qtype', $question_node); 2000 $question_processor = null; 2001 switch ($qtype) { 2002 case 'multichoice': 2003 $single_correct_answer = (int)$questions->nodeValue('plugin_qtype_multichoice_question/multichoice/single', $question_node) > 0; 2004 //TODO: Add checking for the nunmber of valid responses 2005 //If question is marked as multi response but contains only one valid answer it 2006 //should be handle as single response - classic multichoice 2007 if ($single_correct_answer) { 2008 $question_processor = new cc_assesment_question_multichoice($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2009 } else { 2010 $question_processor = new cc_assesment_question_multichoice_multiresponse($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2011 } 2012 $question_processor->generate(); 2013 ++$questioncount; 2014 break; 2015 case 'truefalse': 2016 $question_processor = new cc_assesment_question_truefalse($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2017 $question_processor->generate(); 2018 ++$questioncount; 2019 break; 2020 case 'essay': 2021 $question_processor = new cc_assesment_question_essay($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2022 $question_processor->generate(); 2023 ++$questioncount; 2024 break; 2025 case 'shortanswer': 2026 //This is rather ambiguos since shortanswer supports partial pattern match 2027 //In order to detect pattern match we need to scan for all the responses 2028 //if at least one of the responses uses wildcards it should be treated as 2029 //pattern match, otherwise it should be simple fill in the blank 2030 if (self::has_matching_element($questions, $question_node)) { 2031 //$question_processor = new cc_assesment_question_patternmatch($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2032 $questionforexport--; 2033 } else { 2034 $question_processor = new cc_assesment_question_sfib($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2035 } 2036 if (!empty($question_processor)) { 2037 $question_processor->generate(); 2038 ++$questioncount; 2039 } 2040 break; 2041 default: 2042 ; 2043 break; 2044 } 2045 2046 } 2047 2048 //return dependencies 2049 return ($questioncount == 0) || ($questioncount != $questionforexport)? 2050 false: pkg_resource_dependencies::instance()->get_deps(); 2051 } 2052 2053 /** 2054 * 2055 * Checks if question has matching element 2056 * @param XMLGenericDocument $questions 2057 * @param object $question_node 2058 * @return bool 2059 */ 2060 public static function has_matching_element(XMLGenericDocument $questions, $question_node) { 2061 $answers = $questions->nodeList('plugin_qtype_shortanswer_question//answertext', $question_node); 2062 $result = false; 2063 foreach ($answers as $answer) { 2064 $prepare = str_replace('\*', '\#', $answer->nodeValue); 2065 $result = (strpos($prepare, '*') !== false); 2066 if ($result) { 2067 break; 2068 } 2069 } 2070 return $result; 2071 } 2072 2073 } 2074 2075 class cc_assesment_question_proc_base { 2076 /** 2077 * @var XMLGenericDocument 2078 */ 2079 protected $quiz = null; 2080 2081 /** 2082 * @var XMLGenericDocument 2083 */ 2084 protected $questions = null; 2085 2086 /** 2087 * @var cc_manifest 2088 */ 2089 protected $manifest = null; 2090 2091 /** 2092 * @var cc_assesment_section 2093 */ 2094 protected $section = null; 2095 2096 /** 2097 * @var DOMElement 2098 */ 2099 protected $question_node = null; 2100 2101 /** 2102 * @var string 2103 */ 2104 protected $rootpath = null; 2105 2106 /** 2107 * @var string 2108 */ 2109 protected $contextid = null; 2110 2111 /** 2112 * @var string 2113 */ 2114 protected $outdir = null; 2115 2116 /** 2117 * @var string 2118 */ 2119 protected $qtype = null; 2120 2121 /** 2122 * @var cc_question_metadata 2123 */ 2124 protected $qmetadata = null; 2125 2126 /** 2127 * @var cc_assesment_section_item 2128 */ 2129 protected $qitem = null; 2130 2131 /** 2132 * @var cc_assesment_presentation 2133 */ 2134 protected $qpresentation = null; 2135 2136 /** 2137 * @var cc_response_lidtype 2138 */ 2139 protected $qresponse_lid = null; 2140 2141 protected $qresprocessing = null; 2142 2143 protected $correct_grade_value = null; 2144 protected $correct_answer_node_id = null; 2145 protected $correct_answer_ident = null; 2146 2147 protected $total_grade_value = null; 2148 2149 protected $answerlist = null; 2150 2151 protected $general_feedback = null; 2152 protected $correct_feedbacks = array(); 2153 protected $incorrect_feedbacks = array(); 2154 2155 /** 2156 * @param XMLGenericDocument $questions 2157 * @param cc_manifest $manifest 2158 * @param cc_assesment_section $section 2159 * @param DOMElement $question_node 2160 * @param string $rootpath 2161 * @param string $contextid 2162 * @param string $outdir 2163 */ 2164 public function __construct(XMLGenericDocument &$quiz, XMLGenericDocument &$questions, cc_manifest &$manifest, cc_assesment_section &$section, &$question_node, $rootpath, $contextid, $outdir) { 2165 $this->quiz = $quiz; 2166 $this->questions = $questions; 2167 $this->manifest = $manifest; 2168 $this->section = $section; 2169 $this->question_node = $question_node; 2170 $this->rootpath = $rootpath; 2171 $this->contextid = $contextid; 2172 $this->outdir = $outdir; 2173 2174 // 2175 $qitem = new cc_assesment_section_item(); 2176 $this->section->add_item($qitem); 2177 $qitem->set_title($this->questions->nodeValue('name', $this->question_node)); 2178 $this->qitem = $qitem; 2179 } 2180 2181 public function on_generate_metadata() { 2182 if (empty($this->qmetadata)) { 2183 $this->qmetadata = new cc_question_metadata($this->qtype); 2184 //Get weighting value 2185 $weighting_value = (int)$this->questions->nodeValue('defaultmark', $this->question_node); 2186 if ($weighting_value > 1) { 2187 $this->qmetadata->set_weighting($weighting_value); 2188 } 2189 //Get category 2190 $question_category = $this->questions->nodeValue('../../name', $this->question_node); 2191 if (!empty($question_category)) { 2192 $this->qmetadata->set_category($question_category); 2193 } 2194 $rts = new cc_assesment_itemmetadata(); 2195 $rts->add_metadata($this->qmetadata); 2196 $this->qitem->set_itemmetadata($rts); 2197 } 2198 } 2199 2200 public function on_generate_presentation() { 2201 if (empty($this->qpresentation)) { 2202 $qpresentation = new cc_assesment_presentation(); 2203 $this->qitem->set_presentation($qpresentation); 2204 //add question text 2205 $qmaterial = new cc_assesment_material(); 2206 $qmattext = new cc_assesment_mattext(); 2207 $question_text = $this->questions->nodeValue('questiontext', $this->question_node); 2208 $result = cc_helpers::process_linked_files( $question_text, 2209 $this->manifest, 2210 $this->rootpath, 2211 $this->contextid, 2212 $this->outdir); 2213 $qmattext->set_content($result[0], cc_qti_values::htmltype); 2214 $qmaterial->set_mattext($qmattext); 2215 $qpresentation->set_material($qmaterial); 2216 $this->qpresentation = $qpresentation; 2217 pkg_resource_dependencies::instance()->add($result[1]); 2218 } 2219 } 2220 2221 public function on_generate_answers() {} 2222 public function on_generate_feedbacks() { 2223 $general_question_feedback = $this->questions->nodeValue('generalfeedback', $this->question_node); 2224 if (empty($general_question_feedback)) { 2225 return; 2226 } 2227 $name = 'general_fb'; 2228 //Add question general feedback - the one that should be always displayed 2229 $result = cc_helpers::process_linked_files( $general_question_feedback, 2230 $this->manifest, 2231 $this->rootpath, 2232 $this->contextid, 2233 $this->outdir); 2234 2235 cc_assesment_helper::add_feedback($this->qitem, 2236 $result[0], 2237 cc_qti_values::htmltype, 2238 $name); 2239 pkg_resource_dependencies::instance()->add($result[1]); 2240 $this->general_feedback = $name; 2241 } 2242 2243 public function on_generate_response_processing() { 2244 2245 $qresprocessing = new cc_assesment_resprocessingtype(); 2246 $this->qitem->add_resprocessing($qresprocessing); 2247 $qdecvar = new cc_assesment_decvartype(); 2248 $qresprocessing->set_decvar($qdecvar); 2249 //according to the Common Cartridge 1.1 Profile: Implementation document 2250 //this should always be set to 0, 100 in case of question type that is not essay 2251 $qdecvar->set_limits(0,100); 2252 $qdecvar->set_vartype(cc_qti_values::Decimal); 2253 2254 $this->qresprocessing = $qresprocessing; 2255 2256 } 2257 2258 public function generate() { 2259 $this->on_generate_metadata(); 2260 2261 $this->on_generate_presentation(); 2262 2263 $this->on_generate_answers(); 2264 2265 $this->on_generate_feedbacks(); 2266 2267 $this->on_generate_response_processing(); 2268 } 2269 2270 } 2271 2272 class cc_assesment_question_multichoice extends cc_assesment_question_proc_base { 2273 public function __construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir) { 2274 parent::__construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2275 $this->qtype = cc_qti_profiletype::multiple_choice; 2276 2277 /** 2278 * 2279 * What is needed is a maximum grade value taken from the answer fraction 2280 * It is supposed to always be between 1 and 0 in decimal representation, 2281 * however that is not always the case so a change in test was needed 2282 * but since we support here one correct answer type 2283 * correct answer would always have to be 1 2284 */ 2285 $correct_answer_node = $this->questions->node("plugin_qtype_multichoice_question/answers/answer[fraction > 0]", $this->question_node); 2286 if (empty($correct_answer_node)) { 2287 throw new RuntimeException('No correct answer!'); 2288 } 2289 $this->correct_answer_node_id = $this->questions->nodeValue('@id', $correct_answer_node); 2290 $maximum_quiz_grade = (int)$this->quiz->nodeValue('/activity/quiz/grade'); 2291 $this->total_grade_value = ($maximum_quiz_grade + 1).'.0000000'; 2292 } 2293 2294 public function on_generate_answers() { 2295 //add responses holder 2296 $qresponse_lid = new cc_response_lidtype(); 2297 $this->qresponse_lid = $qresponse_lid; 2298 $this->qpresentation->set_response_lid($qresponse_lid); 2299 $qresponse_choice = new cc_assesment_render_choicetype(); 2300 $qresponse_lid->set_render_choice($qresponse_choice); 2301 //Mark that question has only one correct answer - 2302 //which applies for multiple choice and yes/no questions 2303 $qresponse_lid->set_rcardinality(cc_qti_values::Single); 2304 //are we to shuffle the responses? 2305 $shuffle_answers = (int)$this->quiz->nodeValue('/activity/quiz/shuffleanswers') > 0; 2306 $qresponse_choice->enable_shuffle($shuffle_answers); 2307 $answerlist = array(); 2308 $qa_responses = $this->questions->nodeList('plugin_qtype_multichoice_question/answers/answer', $this->question_node); 2309 foreach ($qa_responses as $node) { 2310 $answer_content = $this->questions->nodeValue('answertext', $node); 2311 $id = ((int)$this->questions->nodeValue('@id', $node) == $this->correct_answer_node_id); 2312 $result = cc_helpers::process_linked_files( $answer_content, 2313 $this->manifest, 2314 $this->rootpath, 2315 $this->contextid, 2316 $this->outdir); 2317 $qresponse_label = cc_assesment_helper::add_answer( $qresponse_choice, 2318 $result[0], 2319 cc_qti_values::htmltype); 2320 pkg_resource_dependencies::instance()->add($result[1]); 2321 $answer_ident = $qresponse_label->get_ident(); 2322 $feedback_ident = $answer_ident.'_fb'; 2323 if (empty($this->correct_answer_ident) && $id) { 2324 $this->correct_answer_ident = $answer_ident; 2325 } 2326 //add answer specific feedbacks if not empty 2327 $content = $this->questions->nodeValue('feedback', $node); 2328 if (!empty($content)) { 2329 $result = cc_helpers::process_linked_files( $content, 2330 $this->manifest, 2331 $this->rootpath, 2332 $this->contextid, 2333 $this->outdir); 2334 2335 2336 cc_assesment_helper::add_feedback( $this->qitem, 2337 $result[0], 2338 cc_qti_values::htmltype, 2339 $feedback_ident); 2340 2341 pkg_resource_dependencies::instance()->add($result[1]); 2342 2343 $answerlist[$answer_ident] = $feedback_ident; 2344 } 2345 } 2346 2347 $this->answerlist = $answerlist; 2348 2349 } 2350 2351 public function on_generate_feedbacks() { 2352 parent::on_generate_feedbacks(); 2353 //Question combined feedbacks 2354 $correct_question_fb = $this->questions->nodeValue('plugin_qtype_multichoice_question/multichoice/correctfeedback', $this->question_node); 2355 $incorrect_question_fb = $this->questions->nodeValue('plugin_qtype_multichoice_question/multichoice/incorrectfeedback', $this->question_node); 2356 $proc = array('correct_fb' => $correct_question_fb, 'general_incorrect_fb' => $incorrect_question_fb); 2357 foreach ($proc as $ident => $content) { 2358 if (empty($content)) { 2359 continue; 2360 } 2361 $result = cc_helpers::process_linked_files( $content, 2362 $this->manifest, 2363 $this->rootpath, 2364 $this->contextid, 2365 $this->outdir); 2366 2367 cc_assesment_helper::add_feedback( $this->qitem, 2368 $result[0], 2369 cc_qti_values::htmltype, 2370 $ident); 2371 2372 pkg_resource_dependencies::instance()->add($result[1]); 2373 if ($ident == 'correct_fb') { 2374 $this->correct_feedbacks[] = $ident; 2375 } else { 2376 $this->incorrect_feedbacks[] = $ident; 2377 } 2378 } 2379 2380 } 2381 2382 public function on_generate_response_processing() { 2383 parent::on_generate_response_processing(); 2384 2385 //respconditions 2386 /** 2387 * General unconditional feedback must be added as a first respcondition 2388 * without any condition and just displayfeedback (if exists) 2389 */ 2390 if (!empty($this->general_feedback)) { 2391 $qrespcondition = new cc_assesment_respconditiontype(); 2392 $qrespcondition->set_title('General feedback'); 2393 $this->qresprocessing->add_respcondition($qrespcondition); 2394 $qrespcondition->enable_continue(); 2395 //define the condition for success 2396 $qconditionvar = new cc_assignment_conditionvar(); 2397 $qrespcondition->set_conditionvar($qconditionvar); 2398 $qother = new cc_assignment_conditionvar_othertype(); 2399 $qconditionvar->set_other($qother); 2400 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2401 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2402 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2403 $qdisplayfeedback->set_linkrefid('general_fb'); 2404 } 2405 2406 //success condition 2407 /** 2408 * For all question types outside of the Essay question, scoring is done in a 2409 * single <respcondition> with a continue flag set to No. The outcome is always 2410 * a variable named SCORE which value must be set to 100 in case of correct answer. 2411 * Partial scores (not 0 or 100) are not supported. 2412 */ 2413 $qrespcondition = new cc_assesment_respconditiontype(); 2414 $qrespcondition->set_title('Correct'); 2415 $this->qresprocessing->add_respcondition($qrespcondition); 2416 $qrespcondition->enable_continue(false); 2417 $qsetvar = new cc_assignment_setvartype(100); 2418 $qrespcondition->add_setvar($qsetvar); 2419 //define the condition for success 2420 $qconditionvar = new cc_assignment_conditionvar(); 2421 $qrespcondition->set_conditionvar($qconditionvar); 2422 $qvarequal = new cc_assignment_conditionvar_varequaltype($this->correct_answer_ident); 2423 $qconditionvar->set_varequal($qvarequal); 2424 $qvarequal->set_respident($this->qresponse_lid->get_ident()); 2425 2426 if (array_key_exists($this->correct_answer_ident, $this->answerlist)) { 2427 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2428 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2429 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2430 $qdisplayfeedback->set_linkrefid($this->answerlist[$this->correct_answer_ident]); 2431 } 2432 2433 foreach ($this->correct_feedbacks as $ident) { 2434 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2435 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2436 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2437 $qdisplayfeedback->set_linkrefid($ident); 2438 } 2439 2440 //rest of the conditions 2441 foreach ($this->answerlist as $ident => $refid) { 2442 if ($ident == $this->correct_answer_ident) { 2443 continue; 2444 } 2445 2446 $qrespcondition = new cc_assesment_respconditiontype(); 2447 $this->qresprocessing->add_respcondition($qrespcondition); 2448 $qsetvar = new cc_assignment_setvartype(0); 2449 $qrespcondition->add_setvar($qsetvar); 2450 //define the condition for fail 2451 $qconditionvar = new cc_assignment_conditionvar(); 2452 $qrespcondition->set_conditionvar($qconditionvar); 2453 $qvarequal = new cc_assignment_conditionvar_varequaltype($ident); 2454 $qconditionvar->set_varequal($qvarequal); 2455 $qvarequal->set_respident($this->qresponse_lid->get_ident()); 2456 2457 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2458 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2459 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2460 $qdisplayfeedback->set_linkrefid($refid); 2461 2462 foreach ($this->incorrect_feedbacks as $ident) { 2463 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2464 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2465 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2466 $qdisplayfeedback->set_linkrefid($ident); 2467 } 2468 } 2469 } 2470 } 2471 2472 class cc_assesment_question_multichoice_multiresponse extends cc_assesment_question_proc_base { 2473 /** 2474 * @var DOMNodeList 2475 */ 2476 protected $correct_answers = null; 2477 2478 public function __construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir) { 2479 parent::__construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2480 $this->qtype = cc_qti_profiletype::multiple_response; 2481 2482 $correct_answer_nodes = $this->questions->nodeList("plugin_qtype_multichoice_question/answers/answer[fraction > 0]", $this->question_node); 2483 if ($correct_answer_nodes->length == 0) { 2484 throw new RuntimeException('No correct answer!'); 2485 } 2486 $this->correct_answers = $correct_answer_nodes; 2487 //$this->correct_answer_node_id = $this->questions->nodeValue('@id', $correct_answer_node); 2488 $maximum_quiz_grade = (int)$this->quiz->nodeValue('/activity/quiz/grade'); 2489 $this->total_grade_value = ($maximum_quiz_grade + 1).'.0000000'; 2490 } 2491 2492 public function on_generate_answers() { 2493 //add responses holder 2494 $qresponse_lid = new cc_response_lidtype(); 2495 $this->qresponse_lid = $qresponse_lid; 2496 $this->qpresentation->set_response_lid($qresponse_lid); 2497 $qresponse_choice = new cc_assesment_render_choicetype(); 2498 $qresponse_lid->set_render_choice($qresponse_choice); 2499 //Mark that question has more than one correct answer 2500 $qresponse_lid->set_rcardinality(cc_qti_values::Multiple); 2501 //are we to shuffle the responses? 2502 $shuffle_answers = (int)$this->quiz->nodeValue('/activity/quiz/shuffleanswers') > 0; 2503 $qresponse_choice->enable_shuffle($shuffle_answers); 2504 $answerlist = array(); 2505 $qa_responses = $this->questions->nodeList('plugin_qtype_multichoice_question/answers/answer', $this->question_node); 2506 foreach ($qa_responses as $node) { 2507 $answer_content = $this->questions->nodeValue('answertext', $node); 2508 $answer_grade_fraction = (float)$this->questions->nodeValue('fraction', $node); 2509 $result = cc_helpers::process_linked_files( $answer_content, 2510 $this->manifest, 2511 $this->rootpath, 2512 $this->contextid, 2513 $this->outdir); 2514 $qresponse_label = cc_assesment_helper::add_answer( $qresponse_choice, 2515 $result[0], 2516 cc_qti_values::htmltype); 2517 pkg_resource_dependencies::instance()->add($result[1]); 2518 $answer_ident = $qresponse_label->get_ident(); 2519 $feedback_ident = $answer_ident.'_fb'; 2520 //add answer specific feedbacks if not empty 2521 $content = $this->questions->nodeValue('feedback', $node); 2522 if (!empty($content)) { 2523 $result = cc_helpers::process_linked_files( $content, 2524 $this->manifest, 2525 $this->rootpath, 2526 $this->contextid, 2527 $this->outdir); 2528 2529 2530 cc_assesment_helper::add_feedback( $this->qitem, 2531 $result[0], 2532 cc_qti_values::htmltype, 2533 $feedback_ident); 2534 2535 pkg_resource_dependencies::instance()->add($result[1]); 2536 2537 } 2538 $answerlist[$answer_ident] = array($feedback_ident, ($answer_grade_fraction > 0)); 2539 } 2540 2541 $this->answerlist = $answerlist; 2542 2543 } 2544 2545 public function on_generate_feedbacks() { 2546 parent::on_generate_feedbacks(); 2547 //Question combined feedbacks 2548 $correct_question_fb = $this->questions->nodeValue('plugin_qtype_multichoice_question/multichoice/correctfeedback', $this->question_node); 2549 $incorrect_question_fb = $this->questions->nodeValue('plugin_qtype_multichoice_question/multichoice/incorrectfeedback', $this->question_node); 2550 if (empty($correct_question_fb)) { 2551 //Hardcode some text for now 2552 $correct_question_fb = 'Well done!'; 2553 } 2554 if (empty($incorrect_question_fb)) { 2555 //Hardcode some text for now 2556 $incorrect_question_fb = 'Better luck next time!'; 2557 } 2558 2559 $proc = array('correct_fb' => $correct_question_fb, 'incorrect_fb' => $incorrect_question_fb); 2560 foreach ($proc as $ident => $content) { 2561 if (empty($content)) { 2562 continue; 2563 } 2564 $result = cc_helpers::process_linked_files( $content, 2565 $this->manifest, 2566 $this->rootpath, 2567 $this->contextid, 2568 $this->outdir); 2569 2570 cc_assesment_helper::add_feedback( $this->qitem, 2571 $result[0], 2572 cc_qti_values::htmltype, 2573 $ident); 2574 2575 pkg_resource_dependencies::instance()->add($result[1]); 2576 if ($ident == 'correct_fb') { 2577 $this->correct_feedbacks[$ident] = $ident; 2578 } else { 2579 $this->incorrect_feedbacks[$ident] = $ident; 2580 } 2581 } 2582 2583 } 2584 2585 public function on_generate_response_processing() { 2586 parent::on_generate_response_processing(); 2587 2588 //respconditions 2589 /** 2590 * General unconditional feedback must be added as a first respcondition 2591 * without any condition and just displayfeedback (if exists) 2592 */ 2593 cc_assesment_helper::add_respcondition( $this->qresprocessing, 2594 'General feedback', 2595 $this->general_feedback, 2596 null, 2597 true 2598 ); 2599 2600 //success condition 2601 /** 2602 * For all question types outside of the Essay question, scoring is done in a 2603 * single <respcondition> with a continue flag set to No. The outcome is always 2604 * a variable named SCORE which value must be set to 100 in case of correct answer. 2605 * Partial scores (not 0 or 100) are not supported. 2606 */ 2607 $qrespcondition = new cc_assesment_respconditiontype(); 2608 $qrespcondition->set_title('Correct'); 2609 $this->qresprocessing->add_respcondition($qrespcondition); 2610 $qrespcondition->enable_continue(false); 2611 $qsetvar = new cc_assignment_setvartype(100); 2612 $qrespcondition->add_setvar($qsetvar); 2613 //define the condition for success 2614 $qconditionvar = new cc_assignment_conditionvar(); 2615 $qrespcondition->set_conditionvar($qconditionvar); 2616 //create root and condition 2617 $qandcondition = new cc_assignment_conditionvar_andtype(); 2618 $qconditionvar->set_and($qandcondition); 2619 foreach ($this->answerlist as $ident => $refid) { 2620 $qvarequal = new cc_assignment_conditionvar_varequaltype($ident); 2621 $qvarequal->enable_case(); 2622 if ($refid[1]) { 2623 $qandcondition->set_varequal($qvarequal); 2624 } else { 2625 $qandcondition->set_not($qvarequal); 2626 } 2627 $qvarequal->set_respident($this->qresponse_lid->get_ident()); 2628 } 2629 2630 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2631 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2632 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2633 //TODO: this needs to be fixed 2634 reset($this->correct_feedbacks); 2635 $ident = key($this->correct_feedbacks); 2636 $qdisplayfeedback->set_linkrefid($ident); 2637 2638 2639 //rest of the conditions 2640 foreach ($this->answerlist as $ident => $refid) { 2641 cc_assesment_helper::add_response_condition( $this->qresprocessing, 2642 'Incorrect feedback', 2643 $refid[0], 2644 $this->general_feedback, 2645 $this->qresponse_lid->get_ident() 2646 ); 2647 } 2648 2649 //Final element for incorrect feedback 2650 reset($this->incorrect_feedbacks); 2651 $ident = key($this->incorrect_feedbacks); 2652 cc_assesment_helper::add_respcondition( $this->qresprocessing, 2653 'Incorrect feedback', 2654 $ident, 2655 0 2656 ); 2657 2658 } 2659 2660 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body