Differences Between: [Versions 311 and 402] [Versions 311 and 403]
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 public function __construct() { 1046 $this->set_setting(cc_qti_tags::ident, cc_helpers::uuidgen('I_')); 1047 $this->set_setting(cc_qti_tags::title); 1048 } 1049 1050 /** 1051 * @param string $value 1052 */ 1053 public function set_ident($value) { 1054 $this->set_setting(cc_qti_tags::ident, $value); 1055 } 1056 1057 /** 1058 * @param string $value 1059 */ 1060 public function set_title($value) { 1061 $this->set_setting(cc_qti_tags::title, $value); 1062 } 1063 1064 /** 1065 * @param cc_assesment_flow_mattype $object 1066 */ 1067 public function set_flow_mat(cc_assesment_flow_mattype $object) { 1068 $this->flow_mat = $object; 1069 } 1070 1071 /** 1072 * @param cc_assesment_material $object 1073 */ 1074 public function set_material(cc_assesment_material $object) { 1075 $this->material = $object; 1076 } 1077 1078 /** 1079 * @param cc_assesment_itemfeedback_solutiontype $object 1080 */ 1081 public function set_solution(cc_assesment_itemfeedback_solutiontype $object) { 1082 $this->solution = $object; 1083 } 1084 1085 public function set_hint($object) { 1086 $this->hint = $object; 1087 } 1088 1089 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1090 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::itemfeedback); 1091 $this->generate_attributes($doc, $node, $namespace); 1092 1093 if (!empty($this->flow_mat) && empty($this->material)) { 1094 $this->flow_mat->generate($doc, $node, $namespace); 1095 } 1096 1097 if (!empty($this->material) && empty($this->flow_mat)) { 1098 $this->material->generate($doc, $node, $namespace); 1099 } 1100 1101 if (!empty($this->solution)) { 1102 $this->solution->generate($doc, $node, $namespace); 1103 } 1104 1105 if (!empty($this->itemfeedback)) { 1106 $this->itemfeedback->generate($doc, $node, $namespace); 1107 } 1108 } 1109 } 1110 1111 class cc_assesment_section_item extends cc_assesment_section { 1112 1113 /** 1114 * @var cc_assesment_itemmetadata 1115 */ 1116 protected $itemmetadata = null; 1117 /** 1118 * @var cc_assesment_presentation 1119 */ 1120 protected $presentation = null; 1121 protected $resprocessing = array(); 1122 protected $itemfeedback = array(); 1123 1124 public function set_itemmetadata(cc_assesment_itemmetadata $object) { 1125 $this->itemmetadata = $object; 1126 } 1127 1128 public function set_presentation(cc_assesment_presentation $object) { 1129 $this->presentation = $object; 1130 } 1131 1132 public function add_resprocessing(cc_assesment_resprocessingtype $object) { 1133 $this->resprocessing[] = $object; 1134 } 1135 1136 public function add_itemfeedback(cc_assesment_itemfeedbacktype $object) { 1137 $this->itemfeedback[] = $object; 1138 } 1139 1140 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1141 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::item); 1142 $this->generate_attributes($doc, $node, $namespace); 1143 1144 if (!empty($this->itemmetadata)) { 1145 $this->itemmetadata->generate($doc, $node, $namespace); 1146 } 1147 1148 if (!empty($this->presentation)) { 1149 $this->presentation->generate($doc, $node, $namespace); 1150 } 1151 1152 if (!empty($this->resprocessing)) { 1153 foreach ($this->resprocessing as $resprocessing) { 1154 $resprocessing->generate($doc, $node, $namespace); 1155 } 1156 } 1157 1158 if (!empty($this->itemfeedback)) { 1159 foreach ($this->itemfeedback as $itemfeedback) { 1160 $itemfeedback->generate($doc, $node, $namespace); 1161 } 1162 } 1163 } 1164 } 1165 1166 class cc_assesment_render_choicetype extends cc_question_metadata_base { 1167 /** 1168 * @var array 1169 */ 1170 protected $materials = array(); 1171 1172 /** 1173 * @var array 1174 */ 1175 protected $material_refs = array(); 1176 1177 /** 1178 * @var array 1179 */ 1180 protected $response_labels = array(); 1181 /** 1182 * @var array 1183 */ 1184 protected $flow_labels = array(); 1185 1186 public function __construct() { 1187 $this->set_setting(cc_qti_tags::shuffle, cc_qti_values::No); 1188 $this->set_setting(cc_qti_tags::minnumber); 1189 $this->set_setting(cc_qti_tags::maxnumber); 1190 } 1191 1192 public function add_material(cc_assesment_material $object) { 1193 $this->materials[] = $object; 1194 } 1195 1196 public function add_material_ref(cc_assesment_response_matref $object) { 1197 $this->material_refs[] = $object; 1198 } 1199 1200 public function add_response_label(cc_assesment_response_labeltype $object) { 1201 $this->response_labels[] = $object; 1202 } 1203 1204 public function add_flow_label($object) { 1205 $this->flow_labels[] = $object; 1206 } 1207 1208 public function enable_shuffle($value = true) { 1209 $this->enable_setting_yesno(cc_qti_tags::shuffle, $value); 1210 } 1211 1212 public function set_limits($min = null, $max = null) { 1213 $this->set_setting(cc_qti_tags::minnumber, $min); 1214 $this->set_setting(cc_qti_tags::maxnumber, $max); 1215 } 1216 1217 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1218 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::render_choice); 1219 $this->generate_attributes($doc, $node, $namespace); 1220 1221 if (!empty($this->materials)) { 1222 foreach ($this->materials as $mattag) { 1223 $mattag->generate($doc, $node, $namespace); 1224 } 1225 } 1226 1227 if (!empty($this->material_refs)) { 1228 foreach ($this->material_refs as $matreftag) { 1229 $matreftag->generate($doc, $node, $namespace); 1230 } 1231 } 1232 1233 if (!empty($this->response_labels)) { 1234 foreach ($this->response_labels as $resplabtag) { 1235 $resplabtag->generate($doc, $node, $namespace); 1236 } 1237 } 1238 1239 if (!empty($this->flow_labels)) { 1240 foreach ($this->flow_labels as $flowlabtag) { 1241 $flowlabtag->generate($doc, $node, $namespace); 1242 } 1243 } 1244 } 1245 1246 } 1247 1248 class cc_assesment_flow_mattype extends cc_question_metadata_base { 1249 1250 /** 1251 * @var cc_assesment_material 1252 */ 1253 protected $material = null; 1254 /** 1255 * @var cc_assesment_response_matref 1256 */ 1257 protected $material_ref = null; 1258 /** 1259 * @var cc_assesment_flow_mattype 1260 */ 1261 protected $flow_mat = null; 1262 1263 public function __construct() { 1264 $this->set_setting(cc_qti_tags::t_class); 1265 } 1266 1267 public function set_class($value) { 1268 $this->set_setting(cc_qti_tags::t_class, $value); 1269 } 1270 1271 public function set_material(cc_assesment_material $object) { 1272 $this->material = $object; 1273 } 1274 1275 public function set_material_ref(cc_assesment_response_matref $object) { 1276 $this->material_ref = $object; 1277 } 1278 1279 public function set_flow_mat(cc_assesment_flow_mattype $object) { 1280 $this->flow_mat = $object; 1281 } 1282 1283 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1284 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::flow_mat); 1285 $this->generate_attributes($doc, $node, $namespace); 1286 1287 if (!empty($this->flow_mat)) { 1288 $this->flow_mat->generate($doc, $node, $namespace); 1289 } 1290 1291 if (!empty($this->material)) { 1292 $this->material->generate($doc, $node, $namespace); 1293 } 1294 1295 if (!empty($this->material_ref)) { 1296 $this->material_ref->generate($doc, $node, $namespace); 1297 } 1298 } 1299 } 1300 1301 class cc_assesment_response_labeltype extends cc_question_metadata_base { 1302 /** 1303 * @var cc_assesment_material 1304 */ 1305 protected $material = null; 1306 1307 /** 1308 * @var cc_assesment_response_matref 1309 */ 1310 protected $material_ref = null; 1311 1312 /** 1313 * @var cc_assesment_flow_mattype 1314 */ 1315 protected $flow_mat = null; 1316 1317 public function __construct() { 1318 $this->set_setting(cc_qti_tags::ident, cc_helpers::uuidgen('I_')); 1319 $this->set_setting(cc_qti_tags::labelrefid); 1320 $this->set_setting(cc_qti_tags::rshuffle); 1321 $this->set_setting(cc_qti_tags::match_group); 1322 $this->set_setting(cc_qti_tags::match_max); 1323 } 1324 1325 public function set_ident($value) { 1326 $this->set_setting(cc_qti_tags::ident, $value); 1327 } 1328 1329 public function get_ident() { 1330 return $this->get_setting(cc_qti_tags::ident); 1331 } 1332 1333 public function set_labelrefid($value) { 1334 $this->set_setting(cc_qti_tags::labelrefid, $value); 1335 } 1336 1337 public function enable_rshuffle($value = true) { 1338 $this->enable_setting_yesno(cc_qti_tags::rshuffle, $value); 1339 } 1340 1341 public function set_match_group($value) { 1342 $this->set_setting(cc_qti_tags::match_group, $value); 1343 } 1344 1345 public function set_match_max($value) { 1346 $this->set_setting(cc_qti_tags::match_max, $value); 1347 } 1348 1349 public function set_material(cc_assesment_material $object) { 1350 $this->material = $object; 1351 } 1352 1353 public function set_material_ref(cc_assesment_response_matref $object) { 1354 $this->material_ref = $object; 1355 } 1356 1357 public function set_flow_mat(cc_assesment_flow_mattype $object) { 1358 $this->flow_mat = $object; 1359 } 1360 1361 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1362 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::response_label); 1363 $this->generate_attributes($doc, $node, $namespace); 1364 1365 if (!empty($this->material)) { 1366 $this->material->generate($doc, $node, $namespace); 1367 } 1368 1369 if (!empty($this->material_ref)) { 1370 $this->material_ref->generate($doc, $node, $namespace); 1371 } 1372 1373 if (!empty($this->flow_mat)) { 1374 $this->flow_mat->generate($doc, $node, $namespace); 1375 } 1376 } 1377 } 1378 1379 class cc_assesment_flow_labeltype extends cc_question_metadata_base { 1380 /** 1381 * @var cc_assesment_flow_labeltype 1382 */ 1383 protected $flow_label = null; 1384 /** 1385 * @var cc_assesment_response_labeltype 1386 */ 1387 protected $response_label = null; 1388 1389 public function __construct() { 1390 $this->set_setting(cc_qti_tags::t_class); 1391 } 1392 1393 public function set_class($value) { 1394 $this->set_setting(cc_qti_tags::t_class, $value); 1395 } 1396 1397 public function set_flow_label(cc_assesment_flow_labeltype $object) { 1398 $this->flow_label = $object; 1399 } 1400 1401 public function set_response_label(cc_assesment_response_labeltype $object) { 1402 $this->response_label = $object; 1403 } 1404 1405 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1406 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::flow_label); 1407 $this->generate_attributes($doc, $node, $namespace); 1408 1409 if (!empty($this->material)) { 1410 $this->material->generate($doc, $node, $namespace); 1411 } 1412 1413 if (!empty($this->material_ref)) { 1414 $this->material_ref->generate($doc, $node, $namespace); 1415 } 1416 1417 if (!empty($this->response_label)) { 1418 $this->response_label->generate($doc, $node, $namespace); 1419 } 1420 1421 if (!empty($this->flow_label)) { 1422 $this->flow_label->generate($doc, $node, $namespace); 1423 } 1424 } 1425 1426 } 1427 1428 1429 class cc_assesment_render_fibtype extends cc_question_metadata_base { 1430 /** 1431 * @var cc_assesment_material 1432 */ 1433 protected $material = null; 1434 1435 /** 1436 * @var cc_assesment_response_matref 1437 */ 1438 protected $material_ref = null; 1439 /** 1440 * @var cc_assesment_response_labeltype 1441 */ 1442 protected $response_label = null; 1443 /** 1444 * 1445 * Enter description here ... 1446 * @var unknown_type 1447 */ 1448 protected $flow_label = null; 1449 1450 1451 public function __construct() { 1452 $this->set_setting(cc_qti_tags::encoding ); 1453 $this->set_setting(cc_qti_tags::charset ); 1454 $this->set_setting(cc_qti_tags::rows ); 1455 $this->set_setting(cc_qti_tags::columns ); 1456 $this->set_setting(cc_qti_tags::maxchars ); 1457 $this->set_setting(cc_qti_tags::minnumber); 1458 $this->set_setting(cc_qti_tags::maxnumber); 1459 $this->set_setting(cc_qti_tags::prompt, cc_qti_values::Box); 1460 $this->set_setting(cc_qti_tags::fibtype, cc_qti_values::String); 1461 } 1462 1463 public function set_encoding($value) { 1464 $this->set_setting(cc_qti_tags::encoding, $value); 1465 } 1466 public function set_charset($value) { 1467 $this->set_setting(cc_qti_tags::charset, $value); 1468 } 1469 1470 public function set_rows($value) { 1471 $this->set_setting(cc_qti_tags::rows, $value); 1472 } 1473 1474 public function set_columns($value) { 1475 $this->set_setting(cc_qti_tags::columns, $value); 1476 } 1477 1478 public function set_maxchars($value) { 1479 $this->set_setting(cc_qti_tags::columns, $value); 1480 } 1481 1482 public function set_limits($min = null, $max = null) { 1483 $this->set_setting(cc_qti_tags::minnumber, $min); 1484 $this->set_setting(cc_qti_tags::maxnumber, $max); 1485 } 1486 1487 public function set_prompt($value) { 1488 $this->set_setting(cc_qti_tags::prompt, $value); 1489 } 1490 1491 public function set_fibtype($value) { 1492 $this->set_setting(cc_qti_tags::fibtype, $value); 1493 } 1494 1495 public function set_material(cc_assesment_material $object) { 1496 $this->material = $object; 1497 } 1498 1499 public function set_material_ref(cc_assesment_response_matref $object) { 1500 $this->material_ref = $object; 1501 } 1502 1503 public function set_response_label(cc_assesment_response_labeltype $object) { 1504 $this->response_label = $object; 1505 } 1506 1507 public function set_flow_label($object) { 1508 $this->flow_label = $object; 1509 } 1510 1511 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1512 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::render_fib); 1513 $this->generate_attributes($doc, $node, $namespace); 1514 1515 if (!empty($this->material) && empty($this->material_ref)) { 1516 $this->material->generate($doc, $node, $namespace); 1517 } 1518 1519 if (!empty($this->material_ref) && empty($this->material)) { 1520 $this->material_ref->generate($doc, $node, $namespace); 1521 } 1522 1523 if (!empty($this->response_label)) { 1524 $this->response_label->generate($doc, $node, $namespace); 1525 } 1526 1527 if (!empty($this->flow_label)) { 1528 $this->flow_label->generate($doc, $node, $namespace); 1529 } 1530 } 1531 } 1532 1533 class cc_response_lidtype extends cc_question_metadata_base { 1534 /** 1535 * @var string 1536 */ 1537 protected $tagname = null; 1538 /** 1539 * @var cc_assesment_material 1540 */ 1541 protected $material = null; 1542 1543 /** 1544 * @var cc_assesment_response_matref 1545 */ 1546 protected $material_ref = null; 1547 1548 /** 1549 * @var cc_assesment_render_choicetype 1550 */ 1551 protected $render_choice = null; 1552 1553 /** 1554 * @var cc_assesment_render_fibtype 1555 */ 1556 protected $render_fib = null; 1557 1558 public function __construct() { 1559 $this->set_setting(cc_qti_tags::rcardinality, cc_qti_values::Single); 1560 $this->set_setting(cc_qti_tags::rtiming); 1561 $this->set_setting(cc_qti_tags::ident, cc_helpers::uuidgen('I_')); 1562 $this->tagname = cc_qti_tags::response_lid; 1563 } 1564 1565 public function set_rcardinality($value) { 1566 $this->set_setting(cc_qti_tags::rcardinality, $value); 1567 } 1568 1569 public function enable_rtiming($value = true) { 1570 $this->enable_setting_yesno(cc_qti_tags::rtiming, $value); 1571 } 1572 1573 public function set_ident($value) { 1574 $this->set_setting(cc_qti_tags::ident, $value); 1575 } 1576 1577 public function get_ident() { 1578 return $this->get_setting(cc_qti_tags::ident); 1579 } 1580 1581 public function set_material_ref(cc_assesment_response_matref $object) { 1582 $this->material_ref = $object; 1583 } 1584 1585 public function set_material(cc_assesment_material $object) { 1586 $this->material = $object; 1587 } 1588 1589 public function set_render_choice(cc_assesment_render_choicetype $object) { 1590 $this->render_choice = $object; 1591 } 1592 1593 public function set_render_fib(cc_assesment_render_fibtype $object) { 1594 $this->render_fib = $object; 1595 } 1596 1597 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1598 $node = $doc->append_new_element_ns($item, $namespace, $this->tagname); 1599 $this->generate_attributes($doc, $node, $namespace); 1600 1601 if (!empty($this->material) && empty($this->material_ref)) { 1602 $this->material->generate($doc, $node, $namespace); 1603 } 1604 1605 if (!empty($this->material_ref) && empty($this->material)) { 1606 $this->material_ref->generate($doc, $node, $namespace); 1607 } 1608 1609 if (!empty($this->render_choice) && empty($this->render_fib)) { 1610 $this->render_choice->generate($doc, $node, $namespace); 1611 } 1612 1613 if (!empty($this->render_fib) && empty($this->render_choice)) { 1614 $this->render_fib->generate($doc, $node, $namespace); 1615 } 1616 } 1617 } 1618 1619 class cc_assesment_response_strtype extends cc_response_lidtype { 1620 public function __construct() { 1621 $rtt = parent::__construct(); 1622 $this->tagname = cc_qti_tags::response_str; 1623 } 1624 } 1625 1626 class cc_assesment_flowtype extends cc_question_metadata_base { 1627 /** 1628 * @var cc_assesment_flowtype 1629 */ 1630 protected $flow = null; 1631 /** 1632 * @var cc_assesment_material 1633 */ 1634 protected $material = null; 1635 /** 1636 * @var cc_assesment_response_matref 1637 */ 1638 protected $material_ref = null; 1639 /** 1640 * @var cc_response_lidtype 1641 */ 1642 protected $response_lid = null; 1643 /** 1644 * @var cc_assesment_response_strtype 1645 */ 1646 protected $response_str = null; 1647 1648 public function __construct() { 1649 $this->set_setting(cc_qti_tags::t_class); 1650 } 1651 1652 public function set_class($value) { 1653 $this->set_setting(cc_qti_tags::t_class, $value); 1654 } 1655 1656 public function set_flow(cc_assesment_flowtype $object) { 1657 $this->flow = $object; 1658 } 1659 1660 public function set_material(cc_assesment_material $object) { 1661 $this->material = $object; 1662 } 1663 1664 public function set_material_ref(cc_assesment_response_matref $object) { 1665 $this->material_ref = $object; 1666 } 1667 1668 public function set_response_lid(cc_response_lidtype $object) { 1669 $this->response_lid = $object; 1670 } 1671 1672 public function set_response_str(cc_assesment_response_strtype $object) { 1673 $this->response_str = $object; 1674 } 1675 1676 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1677 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::flow); 1678 $this->generate_attributes($doc, $node, $namespace); 1679 1680 if (!empty($this->flow)) { 1681 $this->flow->generate($doc, $node, $namespace); 1682 } 1683 1684 if (!empty($this->material)) { 1685 $this->material->generate($doc, $node, $namespace); 1686 } 1687 1688 if (!empty($this->response_lid)) { 1689 $this->response_lid->generate($doc, $node, $namespace); 1690 } 1691 1692 if (!empty($this->response_str)) { 1693 $this->response_str->generate($doc, $node, $namespace); 1694 } 1695 } 1696 } 1697 1698 class cc_assesment_presentation extends cc_question_metadata_base { 1699 /** 1700 * @var cc_assesment_flowtype 1701 */ 1702 protected $flow = null; 1703 /** 1704 * @var cc_assesment_material 1705 */ 1706 protected $material = null; 1707 /** 1708 * @var cc_response_lidtype 1709 */ 1710 protected $response_lid = null; 1711 /** 1712 * @var cc_assesment_response_strtype 1713 */ 1714 protected $response_str = null; 1715 1716 public function __construct() { 1717 $this->set_setting(cc_qti_tags::label); 1718 $this->set_setting_wns(cc_qti_tags::xml_lang , cc_xml_namespace::xml); 1719 $this->set_setting(cc_qti_tags::x0); 1720 $this->set_setting(cc_qti_tags::y0); 1721 $this->set_setting(cc_qti_tags::width); 1722 $this->set_setting(cc_qti_tags::height); 1723 } 1724 1725 public function set_label($value) { 1726 $this->set_setting(cc_qti_tags::label, $value); 1727 } 1728 1729 public function set_lang($value) { 1730 $this->set_setting_wns(cc_qti_tags::xml_lang , cc_xml_namespace::xml, $value); 1731 } 1732 1733 public function set_coor($x = null, $y = null) { 1734 $this->set_setting(cc_qti_tags::x0, $x); 1735 $this->set_setting(cc_qti_tags::y0, $y); 1736 } 1737 1738 public function set_size($width = null, $height = null) { 1739 $this->set_setting(cc_qti_tags::width, $width); 1740 $this->set_setting(cc_qti_tags::height, $height); 1741 } 1742 1743 public function set_flow(cc_assesment_flowtype $object) { 1744 $this->flow = $object; 1745 } 1746 1747 public function set_material(cc_assesment_material $object) { 1748 $this->material = $object; 1749 } 1750 1751 public function set_response_lid(cc_response_lidtype $object) { 1752 $this->response_lid = $object; 1753 } 1754 1755 public function set_response_str(cc_assesment_response_strtype $object) { 1756 $this->response_str = $object; 1757 } 1758 1759 public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) { 1760 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags::presentation); 1761 $this->generate_attributes($doc, $node, $namespace); 1762 1763 if (!empty($this->flow)) { 1764 $this->flow->generate($doc, $node, $namespace); 1765 } 1766 1767 if (!empty($this->material) && empty($this->flow)) { 1768 $this->material->generate($doc, $node, $namespace); 1769 } 1770 1771 if (!empty($this->response_lid) && empty($this->flow)) { 1772 $this->response_lid->generate($doc, $node, $namespace); 1773 } 1774 1775 if (!empty($this->response_str) && empty($this->flow)) { 1776 $this->response_str->generate($doc, $node, $namespace); 1777 } 1778 } 1779 } 1780 1781 class assesment1_resurce_file extends general_cc_file { 1782 const deafultname = 'assesment.xml'; 1783 1784 protected $rootns = 'xmlns'; 1785 protected $rootname = cc_qti_tags::questestinterop; 1786 protected $ccnamespaces = array('xmlns' => 'http://www.imsglobal.org/xsd/ims_qtiasiv1p2', 1787 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance'); 1788 protected $ccnsnames = array('xmlns' => 'http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_4/ims_qtiasiv1p2_localised.xsd'); 1789 1790 /** 1791 * @var string 1792 */ 1793 protected $assessment_title = 'Untitled'; 1794 /** 1795 * @var cc_assesment_metadata 1796 */ 1797 protected $metadata = null; 1798 /** 1799 * @var cc_assesment_rubric_base 1800 */ 1801 protected $rubric = null; 1802 1803 /** 1804 * @var cc_assesment_presentation_material_base 1805 */ 1806 protected $presentation_material = null; 1807 1808 /** 1809 * @var cc_assesment_section 1810 */ 1811 protected $section = null; 1812 1813 public function set_metadata(cc_assesment_metadata $object) { 1814 $this->metadata = $object; 1815 } 1816 1817 public function set_rubric(cc_assesment_rubric_base $object) { 1818 $this->rubric = $object; 1819 } 1820 1821 public function set_presentation_material(cc_assesment_presentation_material_base $object) { 1822 $this->presentation_material = $object; 1823 } 1824 1825 public function set_section(cc_assesment_section $object) { 1826 $this->section = $object; 1827 } 1828 1829 public function set_title($value) { 1830 $this->assessment_title = self::safexml($value); 1831 } 1832 1833 protected function on_save() { 1834 $rns = $this->ccnamespaces[$this->rootns]; 1835 //root assesment element - required 1836 $assessment = $this->append_new_element_ns($this->root, $rns, cc_qti_tags::assessment); 1837 $this->append_new_attribute_ns($assessment, $rns, cc_qti_tags::ident, cc_helpers::uuidgen('QDB_')); 1838 $this->append_new_attribute_ns($assessment, $rns, cc_qti_tags::title, $this->assessment_title); 1839 1840 //metadata - optional 1841 if (!empty($this->metadata)) { 1842 $this->metadata->generate($this, $assessment, $rns); 1843 } 1844 1845 //rubric - optional 1846 if (!empty($this->rubric)) { 1847 $this->rubric->generate($this, $assessment, $rns); 1848 } 1849 1850 //presentation_material - optional 1851 if (!empty($this->presentation_material)) { 1852 $this->presentation_material->generate($this, $assessment, $rns); 1853 } 1854 1855 //section - required 1856 if (!empty($this->section)) { 1857 $this->section->generate($this, $assessment, $rns); 1858 } 1859 1860 return true; 1861 } 1862 } 1863 1864 1865 class assesment11_resurce_file extends assesment1_resurce_file { 1866 protected $ccnsnames = array('xmlns' => 'http://www.imsglobal.org/profile/cc/ccv1p1/ccv1p1_qtiasiv1p2p1_v1p0.xsd'); 1867 } 1868 1869 abstract class cc_assesment_helper { 1870 1871 public static $correct_fb = null; 1872 public static $incorrect_fb = null; 1873 1874 public static function add_feedback($qitem, $content, $content_type, $ident) { 1875 if (empty($content)) { 1876 return false; 1877 } 1878 $qitemfeedback = new cc_assesment_itemfeedbacktype(); 1879 $qitem->add_itemfeedback($qitemfeedback); 1880 if (!empty($ident)) { 1881 $qitemfeedback->set_ident($ident); 1882 } 1883 $qflowmat = new cc_assesment_flow_mattype(); 1884 $qitemfeedback->set_flow_mat($qflowmat); 1885 $qmaterialfb = new cc_assesment_material(); 1886 $qflowmat->set_material($qmaterialfb); 1887 $qmattext = new cc_assesment_mattext(); 1888 $qmaterialfb->set_mattext($qmattext); 1889 $qmattext->set_content($content, $content_type); 1890 return true; 1891 } 1892 1893 public static function add_answer($qresponse_choice, $content, $content_type) { 1894 $qresponse_label = new cc_assesment_response_labeltype(); 1895 $qresponse_choice->add_response_label($qresponse_label); 1896 $qrespmaterial = new cc_assesment_material(); 1897 $qresponse_label->set_material($qrespmaterial); 1898 $qrespmattext = new cc_assesment_mattext(); 1899 $qrespmaterial->set_mattext($qrespmattext); 1900 $qrespmattext->set_content($content, $content_type); 1901 return $qresponse_label; 1902 } 1903 1904 public static function add_response_condition($node, $title, $ident, $feedback_refid, $respident) { 1905 $qrespcondition = new cc_assesment_respconditiontype(); 1906 $node->add_respcondition($qrespcondition); 1907 //define rest of the conditions 1908 $qconditionvar = new cc_assignment_conditionvar(); 1909 $qrespcondition->set_conditionvar($qconditionvar); 1910 $qvarequal = new cc_assignment_conditionvar_varequaltype($ident); 1911 $qvarequal->enable_case(); 1912 $qconditionvar->set_varequal($qvarequal); 1913 $qvarequal->set_respident($respident); 1914 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 1915 $qrespcondition->add_displayfeedback($qdisplayfeedback); 1916 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 1917 $qdisplayfeedback->set_linkrefid($feedback_refid); 1918 } 1919 1920 public static function add_assesment_description($rt, $content, $contenttype) { 1921 if (empty($rt) || empty($content)) { 1922 return; 1923 } 1924 $activity_rubric = new cc_assesment_rubric_base(); 1925 $rubric_material = new cc_assesment_material(); 1926 $activity_rubric->set_material($rubric_material); 1927 $rubric_mattext = new cc_assesment_mattext(); 1928 $rubric_material->set_label('Summary'); 1929 $rubric_material->set_mattext($rubric_mattext); 1930 $rubric_mattext->set_content($content, $contenttype); 1931 $rt->set_rubric($activity_rubric); 1932 } 1933 1934 public static function add_respcondition($node, $title, $feedback_refid, $grade_value = null, $continue = false ) { 1935 $qrespcondition = new cc_assesment_respconditiontype(); 1936 $qrespcondition->set_title($title); 1937 $node->add_respcondition($qrespcondition); 1938 $qrespcondition->enable_continue($continue); 1939 //Add setvar if grade present 1940 if ($grade_value !== null) { 1941 $qsetvar = new cc_assignment_setvartype($grade_value); 1942 $qrespcondition->add_setvar($qsetvar); 1943 } 1944 //define the condition for success 1945 $qconditionvar = new cc_assignment_conditionvar(); 1946 $qrespcondition->set_conditionvar($qconditionvar); 1947 $qother = new cc_assignment_conditionvar_othertype(); 1948 $qconditionvar->set_other($qother); 1949 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 1950 $qrespcondition->add_displayfeedback($qdisplayfeedback); 1951 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 1952 $qdisplayfeedback->set_linkrefid($feedback_refid); 1953 } 1954 1955 /** 1956 * 1957 * Enter description here ... 1958 * @param XMLGenericDocument $qdoc 1959 * @param unknown_type $manifest 1960 * @param cc_assesment_section $section 1961 * @param unknown_type $rootpath 1962 * @param unknown_type $contextid 1963 * @param unknown_type $outdir 1964 */ 1965 public static function process_questions(&$qdoc, &$manifest, cc_assesment_section &$section, $rootpath, $contextid, $outdir) { 1966 $question_file = $rootpath . DIRECTORY_SEPARATOR . 'questions.xml'; 1967 //load questions file 1968 $questions = new XMLGenericDocument(); 1969 if (!$questions->load($question_file)) { 1970 return false; 1971 } 1972 1973 pkg_resource_dependencies::instance()->reset(); 1974 $questioncount = 0; 1975 $questionforexport = 0; 1976 $qids = $qdoc->nodeList('//question_instances//questionid'); 1977 foreach ($qids as $qid) { 1978 /** @var DOMNode $qid */ 1979 $value = $qid->nodeValue; 1980 if (intval($value) == 0) { 1981 continue; 1982 } 1983 $question_node = $questions->node("//question_category/questions/question[@id='{$value}']"); 1984 if (empty($question_node)) { 1985 continue; 1986 } 1987 ++$questionforexport; 1988 //process question 1989 //question type 1990 $qtype = $questions->nodeValue('qtype', $question_node); 1991 $question_processor = null; 1992 switch ($qtype) { 1993 case 'multichoice': 1994 $single_correct_answer = (int)$questions->nodeValue('plugin_qtype_multichoice_question/multichoice/single', $question_node) > 0; 1995 //TODO: Add checking for the nunmber of valid responses 1996 //If question is marked as multi response but contains only one valid answer it 1997 //should be handle as single response - classic multichoice 1998 if ($single_correct_answer) { 1999 $question_processor = new cc_assesment_question_multichoice($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2000 } else { 2001 $question_processor = new cc_assesment_question_multichoice_multiresponse($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2002 } 2003 $question_processor->generate(); 2004 ++$questioncount; 2005 break; 2006 case 'truefalse': 2007 $question_processor = new cc_assesment_question_truefalse($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2008 $question_processor->generate(); 2009 ++$questioncount; 2010 break; 2011 case 'essay': 2012 $question_processor = new cc_assesment_question_essay($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2013 $question_processor->generate(); 2014 ++$questioncount; 2015 break; 2016 case 'shortanswer': 2017 //This is rather ambiguos since shortanswer supports partial pattern match 2018 //In order to detect pattern match we need to scan for all the responses 2019 //if at least one of the responses uses wildcards it should be treated as 2020 //pattern match, otherwise it should be simple fill in the blank 2021 if (self::has_matching_element($questions, $question_node)) { 2022 //$question_processor = new cc_assesment_question_patternmatch($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2023 $questionforexport--; 2024 } else { 2025 $question_processor = new cc_assesment_question_sfib($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2026 } 2027 if (!empty($question_processor)) { 2028 $question_processor->generate(); 2029 ++$questioncount; 2030 } 2031 break; 2032 default: 2033 ; 2034 break; 2035 } 2036 2037 } 2038 2039 //return dependencies 2040 return ($questioncount == 0) || ($questioncount != $questionforexport)? 2041 false: pkg_resource_dependencies::instance()->get_deps(); 2042 } 2043 2044 /** 2045 * 2046 * Checks if question has matching element 2047 * @param XMLGenericDocument $questions 2048 * @param object $question_node 2049 * @return bool 2050 */ 2051 public static function has_matching_element(XMLGenericDocument $questions, $question_node) { 2052 $answers = $questions->nodeList('plugin_qtype_shortanswer_question//answertext', $question_node); 2053 $result = false; 2054 foreach ($answers as $answer) { 2055 $prepare = str_replace('\*', '\#', $answer->nodeValue); 2056 $result = (strpos($prepare, '*') !== false); 2057 if ($result) { 2058 break; 2059 } 2060 } 2061 return $result; 2062 } 2063 2064 } 2065 2066 class cc_assesment_question_proc_base { 2067 /** 2068 * @var XMLGenericDocument 2069 */ 2070 protected $quiz = null; 2071 2072 /** 2073 * @var XMLGenericDocument 2074 */ 2075 protected $questions = null; 2076 2077 /** 2078 * @var cc_manifest 2079 */ 2080 protected $manifest = null; 2081 2082 /** 2083 * @var cc_assesment_section 2084 */ 2085 protected $section = null; 2086 2087 /** 2088 * @var DOMElement 2089 */ 2090 protected $question_node = null; 2091 2092 /** 2093 * @var string 2094 */ 2095 protected $rootpath = null; 2096 2097 /** 2098 * @var string 2099 */ 2100 protected $contextid = null; 2101 2102 /** 2103 * @var string 2104 */ 2105 protected $outdir = null; 2106 2107 /** 2108 * @var string 2109 */ 2110 protected $qtype = null; 2111 2112 /** 2113 * @var cc_question_metadata 2114 */ 2115 protected $qmetadata = null; 2116 2117 /** 2118 * @var cc_assesment_section_item 2119 */ 2120 protected $qitem = null; 2121 2122 /** 2123 * @var cc_assesment_presentation 2124 */ 2125 protected $qpresentation = null; 2126 2127 /** 2128 * @var cc_response_lidtype 2129 */ 2130 protected $qresponse_lid = null; 2131 2132 protected $qresprocessing = null; 2133 2134 protected $correct_grade_value = null; 2135 protected $correct_answer_node_id = null; 2136 protected $correct_answer_ident = null; 2137 2138 protected $total_grade_value = null; 2139 2140 protected $answerlist = null; 2141 2142 protected $general_feedback = null; 2143 protected $correct_feedbacks = array(); 2144 protected $incorrect_feedbacks = array(); 2145 2146 /** 2147 * @param XMLGenericDocument $questions 2148 * @param cc_manifest $manifest 2149 * @param cc_assesment_section $section 2150 * @param DOMElement $question_node 2151 * @param string $rootpath 2152 * @param string $contextid 2153 * @param string $outdir 2154 */ 2155 public function __construct(XMLGenericDocument &$quiz, XMLGenericDocument &$questions, cc_manifest &$manifest, cc_assesment_section &$section, &$question_node, $rootpath, $contextid, $outdir) { 2156 $this->quiz = $quiz; 2157 $this->questions = $questions; 2158 $this->manifest = $manifest; 2159 $this->section = $section; 2160 $this->question_node = $question_node; 2161 $this->rootpath = $rootpath; 2162 $this->contextid = $contextid; 2163 $this->outdir = $outdir; 2164 2165 // 2166 $qitem = new cc_assesment_section_item(); 2167 $this->section->add_item($qitem); 2168 $qitem->set_title($this->questions->nodeValue('name', $this->question_node)); 2169 $this->qitem = $qitem; 2170 } 2171 2172 public function on_generate_metadata() { 2173 if (empty($this->qmetadata)) { 2174 $this->qmetadata = new cc_question_metadata($this->qtype); 2175 //Get weighting value 2176 $weighting_value = (int)$this->questions->nodeValue('defaultmark', $this->question_node); 2177 if ($weighting_value > 1) { 2178 $this->qmetadata->set_weighting($weighting_value); 2179 } 2180 //Get category 2181 $question_category = $this->questions->nodeValue('../../name', $this->question_node); 2182 if (!empty($question_category)) { 2183 $this->qmetadata->set_category($question_category); 2184 } 2185 $rts = new cc_assesment_itemmetadata(); 2186 $rts->add_metadata($this->qmetadata); 2187 $this->qitem->set_itemmetadata($rts); 2188 } 2189 } 2190 2191 public function on_generate_presentation() { 2192 if (empty($this->qpresentation)) { 2193 $qpresentation = new cc_assesment_presentation(); 2194 $this->qitem->set_presentation($qpresentation); 2195 //add question text 2196 $qmaterial = new cc_assesment_material(); 2197 $qmattext = new cc_assesment_mattext(); 2198 $question_text = $this->questions->nodeValue('questiontext', $this->question_node); 2199 $result = cc_helpers::process_linked_files( $question_text, 2200 $this->manifest, 2201 $this->rootpath, 2202 $this->contextid, 2203 $this->outdir); 2204 $qmattext->set_content($result[0], cc_qti_values::htmltype); 2205 $qmaterial->set_mattext($qmattext); 2206 $qpresentation->set_material($qmaterial); 2207 $this->qpresentation = $qpresentation; 2208 pkg_resource_dependencies::instance()->add($result[1]); 2209 } 2210 } 2211 2212 public function on_generate_answers() {} 2213 public function on_generate_feedbacks() { 2214 $general_question_feedback = $this->questions->nodeValue('generalfeedback', $this->question_node); 2215 if (empty($general_question_feedback)) { 2216 return; 2217 } 2218 $name = 'general_fb'; 2219 //Add question general feedback - the one that should be always displayed 2220 $result = cc_helpers::process_linked_files( $general_question_feedback, 2221 $this->manifest, 2222 $this->rootpath, 2223 $this->contextid, 2224 $this->outdir); 2225 2226 cc_assesment_helper::add_feedback($this->qitem, 2227 $result[0], 2228 cc_qti_values::htmltype, 2229 $name); 2230 pkg_resource_dependencies::instance()->add($result[1]); 2231 $this->general_feedback = $name; 2232 } 2233 2234 public function on_generate_response_processing() { 2235 2236 $qresprocessing = new cc_assesment_resprocessingtype(); 2237 $this->qitem->add_resprocessing($qresprocessing); 2238 $qdecvar = new cc_assesment_decvartype(); 2239 $qresprocessing->set_decvar($qdecvar); 2240 //according to the Common Cartridge 1.1 Profile: Implementation document 2241 //this should always be set to 0, 100 in case of question type that is not essay 2242 $qdecvar->set_limits(0,100); 2243 $qdecvar->set_vartype(cc_qti_values::Decimal); 2244 2245 $this->qresprocessing = $qresprocessing; 2246 2247 } 2248 2249 public function generate() { 2250 $this->on_generate_metadata(); 2251 2252 $this->on_generate_presentation(); 2253 2254 $this->on_generate_answers(); 2255 2256 $this->on_generate_feedbacks(); 2257 2258 $this->on_generate_response_processing(); 2259 } 2260 2261 } 2262 2263 class cc_assesment_question_multichoice extends cc_assesment_question_proc_base { 2264 public function __construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir) { 2265 parent::__construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2266 $this->qtype = cc_qti_profiletype::multiple_choice; 2267 2268 /** 2269 * 2270 * What is needed is a maximum grade value taken from the answer fraction 2271 * It is supposed to always be between 1 and 0 in decimal representation, 2272 * however that is not always the case so a change in test was needed 2273 * but since we support here one correct answer type 2274 * correct answer would always have to be 1 2275 */ 2276 $correct_answer_node = $this->questions->node("plugin_qtype_multichoice_question/answers/answer[fraction > 0]", $this->question_node); 2277 if (empty($correct_answer_node)) { 2278 throw new RuntimeException('No correct answer!'); 2279 } 2280 $this->correct_answer_node_id = $this->questions->nodeValue('@id', $correct_answer_node); 2281 $maximum_quiz_grade = (int)$this->quiz->nodeValue('/activity/quiz/grade'); 2282 $this->total_grade_value = ($maximum_quiz_grade + 1).'.0000000'; 2283 } 2284 2285 public function on_generate_answers() { 2286 //add responses holder 2287 $qresponse_lid = new cc_response_lidtype(); 2288 $this->qresponse_lid = $qresponse_lid; 2289 $this->qpresentation->set_response_lid($qresponse_lid); 2290 $qresponse_choice = new cc_assesment_render_choicetype(); 2291 $qresponse_lid->set_render_choice($qresponse_choice); 2292 //Mark that question has only one correct answer - 2293 //which applies for multiple choice and yes/no questions 2294 $qresponse_lid->set_rcardinality(cc_qti_values::Single); 2295 //are we to shuffle the responses? 2296 $shuffle_answers = (int)$this->quiz->nodeValue('/activity/quiz/shuffleanswers') > 0; 2297 $qresponse_choice->enable_shuffle($shuffle_answers); 2298 $answerlist = array(); 2299 $qa_responses = $this->questions->nodeList('plugin_qtype_multichoice_question/answers/answer', $this->question_node); 2300 foreach ($qa_responses as $node) { 2301 $answer_content = $this->questions->nodeValue('answertext', $node); 2302 $id = ((int)$this->questions->nodeValue('@id', $node) == $this->correct_answer_node_id); 2303 $result = cc_helpers::process_linked_files( $answer_content, 2304 $this->manifest, 2305 $this->rootpath, 2306 $this->contextid, 2307 $this->outdir); 2308 $qresponse_label = cc_assesment_helper::add_answer( $qresponse_choice, 2309 $result[0], 2310 cc_qti_values::htmltype); 2311 pkg_resource_dependencies::instance()->add($result[1]); 2312 $answer_ident = $qresponse_label->get_ident(); 2313 $feedback_ident = $answer_ident.'_fb'; 2314 if (empty($this->correct_answer_ident) && $id) { 2315 $this->correct_answer_ident = $answer_ident; 2316 } 2317 //add answer specific feedbacks if not empty 2318 $content = $this->questions->nodeValue('feedback', $node); 2319 if (!empty($content)) { 2320 $result = cc_helpers::process_linked_files( $content, 2321 $this->manifest, 2322 $this->rootpath, 2323 $this->contextid, 2324 $this->outdir); 2325 2326 2327 cc_assesment_helper::add_feedback( $this->qitem, 2328 $result[0], 2329 cc_qti_values::htmltype, 2330 $feedback_ident); 2331 2332 pkg_resource_dependencies::instance()->add($result[1]); 2333 2334 $answerlist[$answer_ident] = $feedback_ident; 2335 } 2336 } 2337 2338 $this->answerlist = $answerlist; 2339 2340 } 2341 2342 public function on_generate_feedbacks() { 2343 parent::on_generate_feedbacks(); 2344 //Question combined feedbacks 2345 $correct_question_fb = $this->questions->nodeValue('plugin_qtype_multichoice_question/multichoice/correctfeedback', $this->question_node); 2346 $incorrect_question_fb = $this->questions->nodeValue('plugin_qtype_multichoice_question/multichoice/incorrectfeedback', $this->question_node); 2347 $proc = array('correct_fb' => $correct_question_fb, 'general_incorrect_fb' => $incorrect_question_fb); 2348 foreach ($proc as $ident => $content) { 2349 if (empty($content)) { 2350 continue; 2351 } 2352 $result = cc_helpers::process_linked_files( $content, 2353 $this->manifest, 2354 $this->rootpath, 2355 $this->contextid, 2356 $this->outdir); 2357 2358 cc_assesment_helper::add_feedback( $this->qitem, 2359 $result[0], 2360 cc_qti_values::htmltype, 2361 $ident); 2362 2363 pkg_resource_dependencies::instance()->add($result[1]); 2364 if ($ident == 'correct_fb') { 2365 $this->correct_feedbacks[] = $ident; 2366 } else { 2367 $this->incorrect_feedbacks[] = $ident; 2368 } 2369 } 2370 2371 } 2372 2373 public function on_generate_response_processing() { 2374 parent::on_generate_response_processing(); 2375 2376 //respconditions 2377 /** 2378 * General unconditional feedback must be added as a first respcondition 2379 * without any condition and just displayfeedback (if exists) 2380 */ 2381 if (!empty($this->general_feedback)) { 2382 $qrespcondition = new cc_assesment_respconditiontype(); 2383 $qrespcondition->set_title('General feedback'); 2384 $this->qresprocessing->add_respcondition($qrespcondition); 2385 $qrespcondition->enable_continue(); 2386 //define the condition for success 2387 $qconditionvar = new cc_assignment_conditionvar(); 2388 $qrespcondition->set_conditionvar($qconditionvar); 2389 $qother = new cc_assignment_conditionvar_othertype(); 2390 $qconditionvar->set_other($qother); 2391 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2392 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2393 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2394 $qdisplayfeedback->set_linkrefid('general_fb'); 2395 } 2396 2397 //success condition 2398 /** 2399 * For all question types outside of the Essay question, scoring is done in a 2400 * single <respcondition> with a continue flag set to No. The outcome is always 2401 * a variable named SCORE which value must be set to 100 in case of correct answer. 2402 * Partial scores (not 0 or 100) are not supported. 2403 */ 2404 $qrespcondition = new cc_assesment_respconditiontype(); 2405 $qrespcondition->set_title('Correct'); 2406 $this->qresprocessing->add_respcondition($qrespcondition); 2407 $qrespcondition->enable_continue(false); 2408 $qsetvar = new cc_assignment_setvartype(100); 2409 $qrespcondition->add_setvar($qsetvar); 2410 //define the condition for success 2411 $qconditionvar = new cc_assignment_conditionvar(); 2412 $qrespcondition->set_conditionvar($qconditionvar); 2413 $qvarequal = new cc_assignment_conditionvar_varequaltype($this->correct_answer_ident); 2414 $qconditionvar->set_varequal($qvarequal); 2415 $qvarequal->set_respident($this->qresponse_lid->get_ident()); 2416 2417 if (array_key_exists($this->correct_answer_ident, $this->answerlist)) { 2418 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2419 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2420 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2421 $qdisplayfeedback->set_linkrefid($this->answerlist[$this->correct_answer_ident]); 2422 } 2423 2424 foreach ($this->correct_feedbacks as $ident) { 2425 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2426 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2427 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2428 $qdisplayfeedback->set_linkrefid($ident); 2429 } 2430 2431 //rest of the conditions 2432 foreach ($this->answerlist as $ident => $refid) { 2433 if ($ident == $this->correct_answer_ident) { 2434 continue; 2435 } 2436 2437 $qrespcondition = new cc_assesment_respconditiontype(); 2438 $this->qresprocessing->add_respcondition($qrespcondition); 2439 $qsetvar = new cc_assignment_setvartype(0); 2440 $qrespcondition->add_setvar($qsetvar); 2441 //define the condition for fail 2442 $qconditionvar = new cc_assignment_conditionvar(); 2443 $qrespcondition->set_conditionvar($qconditionvar); 2444 $qvarequal = new cc_assignment_conditionvar_varequaltype($ident); 2445 $qconditionvar->set_varequal($qvarequal); 2446 $qvarequal->set_respident($this->qresponse_lid->get_ident()); 2447 2448 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2449 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2450 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2451 $qdisplayfeedback->set_linkrefid($refid); 2452 2453 foreach ($this->incorrect_feedbacks as $ident) { 2454 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2455 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2456 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2457 $qdisplayfeedback->set_linkrefid($ident); 2458 } 2459 } 2460 } 2461 } 2462 2463 class cc_assesment_question_multichoice_multiresponse extends cc_assesment_question_proc_base { 2464 /** 2465 * @var DOMNodeList 2466 */ 2467 protected $correct_answers = null; 2468 2469 public function __construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir) { 2470 parent::__construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir); 2471 $this->qtype = cc_qti_profiletype::multiple_response; 2472 2473 $correct_answer_nodes = $this->questions->nodeList("plugin_qtype_multichoice_question/answers/answer[fraction > 0]", $this->question_node); 2474 if ($correct_answer_nodes->length == 0) { 2475 throw new RuntimeException('No correct answer!'); 2476 } 2477 $this->correct_answers = $correct_answer_nodes; 2478 //$this->correct_answer_node_id = $this->questions->nodeValue('@id', $correct_answer_node); 2479 $maximum_quiz_grade = (int)$this->quiz->nodeValue('/activity/quiz/grade'); 2480 $this->total_grade_value = ($maximum_quiz_grade + 1).'.0000000'; 2481 } 2482 2483 public function on_generate_answers() { 2484 //add responses holder 2485 $qresponse_lid = new cc_response_lidtype(); 2486 $this->qresponse_lid = $qresponse_lid; 2487 $this->qpresentation->set_response_lid($qresponse_lid); 2488 $qresponse_choice = new cc_assesment_render_choicetype(); 2489 $qresponse_lid->set_render_choice($qresponse_choice); 2490 //Mark that question has more than one correct answer 2491 $qresponse_lid->set_rcardinality(cc_qti_values::Multiple); 2492 //are we to shuffle the responses? 2493 $shuffle_answers = (int)$this->quiz->nodeValue('/activity/quiz/shuffleanswers') > 0; 2494 $qresponse_choice->enable_shuffle($shuffle_answers); 2495 $answerlist = array(); 2496 $qa_responses = $this->questions->nodeList('plugin_qtype_multichoice_question/answers/answer', $this->question_node); 2497 foreach ($qa_responses as $node) { 2498 $answer_content = $this->questions->nodeValue('answertext', $node); 2499 $answer_grade_fraction = (float)$this->questions->nodeValue('fraction', $node); 2500 $result = cc_helpers::process_linked_files( $answer_content, 2501 $this->manifest, 2502 $this->rootpath, 2503 $this->contextid, 2504 $this->outdir); 2505 $qresponse_label = cc_assesment_helper::add_answer( $qresponse_choice, 2506 $result[0], 2507 cc_qti_values::htmltype); 2508 pkg_resource_dependencies::instance()->add($result[1]); 2509 $answer_ident = $qresponse_label->get_ident(); 2510 $feedback_ident = $answer_ident.'_fb'; 2511 //add answer specific feedbacks if not empty 2512 $content = $this->questions->nodeValue('feedback', $node); 2513 if (!empty($content)) { 2514 $result = cc_helpers::process_linked_files( $content, 2515 $this->manifest, 2516 $this->rootpath, 2517 $this->contextid, 2518 $this->outdir); 2519 2520 2521 cc_assesment_helper::add_feedback( $this->qitem, 2522 $result[0], 2523 cc_qti_values::htmltype, 2524 $feedback_ident); 2525 2526 pkg_resource_dependencies::instance()->add($result[1]); 2527 2528 } 2529 $answerlist[$answer_ident] = array($feedback_ident, ($answer_grade_fraction > 0)); 2530 } 2531 2532 $this->answerlist = $answerlist; 2533 2534 } 2535 2536 public function on_generate_feedbacks() { 2537 parent::on_generate_feedbacks(); 2538 //Question combined feedbacks 2539 $correct_question_fb = $this->questions->nodeValue('plugin_qtype_multichoice_question/multichoice/correctfeedback', $this->question_node); 2540 $incorrect_question_fb = $this->questions->nodeValue('plugin_qtype_multichoice_question/multichoice/incorrectfeedback', $this->question_node); 2541 if (empty($correct_question_fb)) { 2542 //Hardcode some text for now 2543 $correct_question_fb = 'Well done!'; 2544 } 2545 if (empty($incorrect_question_fb)) { 2546 //Hardcode some text for now 2547 $incorrect_question_fb = 'Better luck next time!'; 2548 } 2549 2550 $proc = array('correct_fb' => $correct_question_fb, 'incorrect_fb' => $incorrect_question_fb); 2551 foreach ($proc as $ident => $content) { 2552 if (empty($content)) { 2553 continue; 2554 } 2555 $result = cc_helpers::process_linked_files( $content, 2556 $this->manifest, 2557 $this->rootpath, 2558 $this->contextid, 2559 $this->outdir); 2560 2561 cc_assesment_helper::add_feedback( $this->qitem, 2562 $result[0], 2563 cc_qti_values::htmltype, 2564 $ident); 2565 2566 pkg_resource_dependencies::instance()->add($result[1]); 2567 if ($ident == 'correct_fb') { 2568 $this->correct_feedbacks[$ident] = $ident; 2569 } else { 2570 $this->incorrect_feedbacks[$ident] = $ident; 2571 } 2572 } 2573 2574 } 2575 2576 public function on_generate_response_processing() { 2577 parent::on_generate_response_processing(); 2578 2579 //respconditions 2580 /** 2581 * General unconditional feedback must be added as a first respcondition 2582 * without any condition and just displayfeedback (if exists) 2583 */ 2584 cc_assesment_helper::add_respcondition( $this->qresprocessing, 2585 'General feedback', 2586 $this->general_feedback, 2587 null, 2588 true 2589 ); 2590 2591 //success condition 2592 /** 2593 * For all question types outside of the Essay question, scoring is done in a 2594 * single <respcondition> with a continue flag set to No. The outcome is always 2595 * a variable named SCORE which value must be set to 100 in case of correct answer. 2596 * Partial scores (not 0 or 100) are not supported. 2597 */ 2598 $qrespcondition = new cc_assesment_respconditiontype(); 2599 $qrespcondition->set_title('Correct'); 2600 $this->qresprocessing->add_respcondition($qrespcondition); 2601 $qrespcondition->enable_continue(false); 2602 $qsetvar = new cc_assignment_setvartype(100); 2603 $qrespcondition->add_setvar($qsetvar); 2604 //define the condition for success 2605 $qconditionvar = new cc_assignment_conditionvar(); 2606 $qrespcondition->set_conditionvar($qconditionvar); 2607 //create root and condition 2608 $qandcondition = new cc_assignment_conditionvar_andtype(); 2609 $qconditionvar->set_and($qandcondition); 2610 foreach ($this->answerlist as $ident => $refid) { 2611 $qvarequal = new cc_assignment_conditionvar_varequaltype($ident); 2612 $qvarequal->enable_case(); 2613 if ($refid[1]) { 2614 $qandcondition->set_varequal($qvarequal); 2615 } else { 2616 $qandcondition->set_not($qvarequal); 2617 } 2618 $qvarequal->set_respident($this->qresponse_lid->get_ident()); 2619 } 2620 2621 $qdisplayfeedback = new cc_assignment_displayfeedbacktype(); 2622 $qrespcondition->add_displayfeedback($qdisplayfeedback); 2623 $qdisplayfeedback->set_feedbacktype(cc_qti_values::Response); 2624 //TODO: this needs to be fixed 2625 reset($this->correct_feedbacks); 2626 $ident = key($this->correct_feedbacks); 2627 $qdisplayfeedback->set_linkrefid($ident); 2628 2629 2630 //rest of the conditions 2631 foreach ($this->answerlist as $ident => $refid) { 2632 cc_assesment_helper::add_response_condition( $this->qresprocessing, 2633 'Incorrect feedback', 2634 $refid[0], 2635 $this->general_feedback, 2636 $this->qresponse_lid->get_ident() 2637 ); 2638 } 2639 2640 //Final element for incorrect feedback 2641 reset($this->incorrect_feedbacks); 2642 $ident = key($this->incorrect_feedbacks); 2643 cc_assesment_helper::add_respcondition( $this->qresprocessing, 2644 'Incorrect feedback', 2645 $ident, 2646 0 2647 ); 2648 2649 } 2650 2651 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body