Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 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      /** @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  }