ILIAS  release_8 Revision v8.24
class.ilQTIParser.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
31{
32 public const IL_MO_PARSE_QTI = 1;
33 public const IL_MO_VERIFY_QTI = 2;
34
35 public bool $hasRootElement = false;
36
40 public array $path = [];
41
45 public array $items = [];
46
47 public ?ilQTIItem $item = null;
48
52 public $depth;
53
54 public string $qti_element = "";
55
56 public bool $in_presentation = false;
57
58 public bool $in_response = false;
59
63 public $render_type = null;
64
66
67 public ?ilQTIMaterial $material = null;
68
69 public ?ilQTIMatimage $matimage = null;
70
71 public ?ilQTIResponse $response = null;
72
74
75 public ?ilQTIOutcomes $outcomes = null;
76
77 public ?ilQTIDecvar $decvar = null;
78
80
81 public ?ilQTISetvar $setvar = null;
82
84
86
90 public array $flow_mat = [];
91
92 public int $flow = 0;
93
95
96 public ?ilQTIMattext $mattext = null;
97
98 public bool $sametag = false;
99
100 public string $characterbuffer = "";
101
103
104 public int $parser_mode = 0;
105
106 protected $solutionhint = null;
107 public $solutionhints = [];
108
112 public array $import_idents = [];
113
114 public int $qpl_id = 0;
115
116 public ?int $tst_id = null;
117
118 public ?ilObjTest $tst_object = null;
119
120 public bool $do_nothing = false;
121
122 public int $gap_index = 0;
123
127 public array $assessments = [];
128
130
132
134
135 public bool $in_assessment = false;
136
137 public ?ilQTISection $section = null;
138
142 public array $import_mapping = [];
143
144 public int $question_counter = 1;
145
146 public bool $in_itemmetadata = false;
147
148 public bool $in_objectives = false;
149
153 public array $founditems = [];
154
155 public bool $verifyroot = false;
156
157 public int $verifyqticomment = 0;
158
159 public int $verifymetadatafield = 0;
160
161 public int $verifyfieldlabel = 0;
162
163 public string $verifyfieldlabeltext = "";
164
165 public int $verifyfieldentry = 0;
166
167 public string $verifyfieldentrytext = "";
168
169 protected int $numImportedItems = 0;
170
172
173 protected bool $in_prensentation_material = false;
174
175 protected bool $ignoreItemsEnabled = false;
176
177 private ?ilQTIMatapplet $matapplet = null;
178
182 private array $metadata = ["label" => "", "entry" => ""];
183
185
186 protected ?string $questionSetType = null;
187
188 public function __construct(?string $a_xml_file, int $a_mode = self::IL_MO_PARSE_QTI, int $a_qpl_id = 0, $a_import_idents = "")
189 {
190 global $lng;
191
192 $this->parser_mode = $a_mode;
193
194 parent::__construct($a_xml_file);
195
196 $this->qpl_id = $a_qpl_id;
197 $this->lng = $lng;
198 if (is_array($a_import_idents)) {
199 $this->import_idents = &$a_import_idents;
200 }
201
202 $this->depth = $this->createParserStorage();
203 }
204
205 public function isIgnoreItemsEnabled(): bool
206 {
208 }
209
210 public function setIgnoreItemsEnabled(bool $ignoreItemsEnabled): void
211 {
212 $this->ignoreItemsEnabled = $ignoreItemsEnabled;
213 }
214
215 public function getQuestionSetType(): ?string
216 {
218 }
219
220 public function setQuestionSetType(string $questionSetType): void
221 {
222 $this->questionSetType = $questionSetType;
223 }
224
225 public function setTestObject(ilObjTest $a_tst_object): void
226 {
227 $this->tst_object = $a_tst_object;
228 $this->tst_id = $this->tst_object->getId();
229 }
230
231 public function getTestObject(): ilObjTest
232 {
233 return $this->tst_object;
234 }
235
243 public function setHandlers($a_xml_parser): void
244 {
245 xml_set_object($a_xml_parser, $this);
246 xml_set_element_handler($a_xml_parser, 'handlerBeginTag', 'handlerEndTag');
247 xml_set_character_data_handler($a_xml_parser, 'handlerCharacterData');
248 }
249
250 public function startParsing(): void
251 {
252 $this->question_counter = 1;
253 parent::startParsing();
254 }
255
259 public function getParent($a_xml_parser): string
260 {
261 if ($this->depth[$a_xml_parser] > 0) {
262 return $this->path[$this->depth[$a_xml_parser] - 1];
263 }
264
265 return "";
266 }
267
272 public function handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs): void
273 {
274 switch ($this->parser_mode) {
276 $this->handlerParseBeginTag($a_xml_parser, $a_name, $a_attribs);
277 break;
279 $this->handlerVerifyBeginTag($a_xml_parser, $a_name, $a_attribs);
280 break;
281 }
282 }
283
288 public function handlerParseBeginTag($a_xml_parser, string $a_name, array $a_attribs): void
289 {
290 if ($this->do_nothing) {
291 return;
292 }
293 $this->sametag = false;
294 $this->characterbuffer = "";
295 $this->depth[$a_xml_parser] = ($this->depth[$a_xml_parser] ?? 0) + 1; // Issue with SplObjectStorage: Cannot use ++.
296 $this->path[$this->depth[$a_xml_parser]] = strtolower($a_name);
297 $this->qti_element = $a_name;
298
299 switch (strtolower($a_name)) {
300 case "assessment":
301 $this->assessmentBeginTag($a_attribs);
302 break;
303 case "assessmentcontrol":
304 $this->assessmentControlBeginTag($a_attribs);
305 break;
306 case "objectives":
307 $this->objectives = new ilQTIObjectives();
308 $this->in_objectives = true;
309 break;
310 case 'presentation_material':
311 $this->prensentation_material = new ilQTIPresentationMaterial();
312 $this->in_prensentation_material = true;
313 break;
314 case "section":
315 $this->section = new ilQTISection();
316 break;
317 case "itemmetadata":
318 $this->in_itemmetadata = true;
319 break;
320 case "qtimetadatafield":
321 $this->metadata = ["label" => "", "entry" => ""];
322 break;
323 case "flow":
324 $this->flow++;
325 break;
326 case "flow_mat":
327 $this->flow_mat[] = new ilQTIFlowMat();
328 break;
329 case "itemfeedback":
330 $this->itemFeedbackBeginTag($a_attribs);
331 break;
332 case "displayfeedback":
333 $this->displayFeedbackBeginTag($a_attribs);
334 break;
335 case "setvar":
336 $this->setVarBeginTag($a_attribs);
337 break;
338 case "conditionvar":
339 $this->conditionvar = new ilQTIConditionvar();
340 break;
341 case "not":
342 if ($this->conditionvar != null) {
343 $this->conditionvar->addNot();
344 }
345 break;
346 case "and":
347 if ($this->conditionvar != null) {
348 $this->conditionvar->addAnd();
349 }
350 break;
351 case "or":
352 if ($this->conditionvar != null) {
353 $this->conditionvar->addOr();
354 }
355 break;
356 case "varequal":
357 $this->varEqualBeginTag($a_attribs);
358 break;
359 case "varlt":
360 $this->responsevar = new ilQTIResponseVar(ilQTIResponseVar::RESPONSEVAR_LT);
361 foreach ($a_attribs as $attribute => $value) {
362 switch (strtolower($attribute)) {
363 case "respident":
364 $this->responsevar->setRespident($value);
365 break;
366 case "index":
367 $this->responsevar->setIndex($value);
368 break;
369 }
370 }
371 break;
372 case "varlte":
373 $this->responsevar = new ilQTIResponseVar(ilQTIResponseVar::RESPONSEVAR_LTE);
374 foreach ($a_attribs as $attribute => $value) {
375 switch (strtolower($attribute)) {
376 case "respident":
377 $this->responsevar->setRespident($value);
378 break;
379 case "index":
380 $this->responsevar->setIndex($value);
381 break;
382 }
383 }
384 break;
385 case "vargt":
386 $this->responsevar = new ilQTIResponseVar(ilQTIResponseVar::RESPONSEVAR_GT);
387 foreach ($a_attribs as $attribute => $value) {
388 switch (strtolower($attribute)) {
389 case "respident":
390 $this->responsevar->setRespident($value);
391 break;
392 case "index":
393 $this->responsevar->setIndex($value);
394 break;
395 }
396 }
397 break;
398 case "vargte":
399 $this->responsevar = new ilQTIResponseVar(ilQTIResponseVar::RESPONSEVAR_GTE);
400 foreach ($a_attribs as $attribute => $value) {
401 switch (strtolower($attribute)) {
402 case "respident":
403 $this->responsevar->setRespident($value);
404 break;
405 case "index":
406 $this->responsevar->setIndex($value);
407 break;
408 }
409 }
410 break;
411 case "varsubset":
413 foreach ($a_attribs as $attribute => $value) {
414 switch (strtolower($attribute)) {
415 case "respident":
416 $this->responsevar->setRespident($value);
417 break;
418 case "setmatch":
419 $this->responsevar->setSetmatch($value);
420 break;
421 case "index":
422 $this->responsevar->setIndex($value);
423 break;
424 }
425 }
426 break;
427 case "varinside":
429 foreach ($a_attribs as $attribute => $value) {
430 switch (strtolower($attribute)) {
431 case "respident":
432 $this->responsevar->setRespident($value);
433 break;
434 case "areatype":
435 $this->responsevar->setAreatype($value);
436 break;
437 case "index":
438 $this->responsevar->setIndex($value);
439 break;
440 }
441 }
442 break;
443 case "varsubstring":
445 foreach ($a_attribs as $attribute => $value) {
446 switch (strtolower($attribute)) {
447 case "case":
448 $this->responsevar->setCase($value);
449 break;
450 case "respident":
451 $this->responsevar->setRespident($value);
452 break;
453 case "index":
454 $this->responsevar->setIndex($value);
455 break;
456 }
457 }
458 break;
459 case "respcondition":
460 $this->respcondition = new ilQTIRespcondition();
461 foreach ($a_attribs as $attribute => $value) {
462 switch (strtolower($attribute)) {
463 case "continue":
464 $this->respcondition->setContinue($value);
465 break;
466 case "title":
467 $this->respcondition->setTitle($value);
468 break;
469 }
470 }
471 break;
472 case "outcomes":
473 $this->outcomes = new ilQTIOutcomes();
474 break;
475 case "decvar":
476 $this->decVarBeginTag($a_attribs);
477 break;
478 case "matimage":
479 $this->matImageBeginTag($a_attribs);
480 break;
481 case "material":
482 $this->materialBeginTag($a_attribs);
483 break;
484 case "mattext":
485 $this->matTextBeginTag($a_attribs);
486 break;
487 case "matapplet":
488 $this->matAppletBeginTag($a_attribs);
489 break;
490 case "questestinterop":
491 $this->hasRootElement = true;
492 break;
493 case "qticomment":
494 break;
495 case "objectbank":
496 // not implemented yet
497 break;
498 case "presentation":
499 $this->in_presentation = true;
500 $this->presentation = new ilQTIPresentation();
501 break;
502 case "response_label":
503 $this->responseLabelBeginTag($a_attribs);
504 break;
505 case "render_choice":
506 $this->renderChoiceBeginTag($a_attribs);
507 break;
508 case "render_hotspot":
509 $this->renderHotspotBeginTag($a_attribs);
510 break;
511 case "render_fib":
512 $this->renderFibBeginTag($a_attribs);
513 break;
514 case "response_lid":
515 // Ordering Terms and Definitions or
516 // Ordering Terms and Pictures or
517 // Multiple choice single response or
518 // Multiple choice multiple response
519 case "response_xy":
520 // Imagemap question
521 case "response_str":
522 // Close question
523 case "response_num":
524 case "response_grp":
525 // Matching terms and definitions
526 // Matching terms and images
527 $this->termsAndDefinitionsBeginTag($a_name, $a_attribs);
528 break;
529 case "item":
530 $this->itemBeginTag($a_attribs);
531 break;
532 case "resprocessing":
533 $this->resprocessingBeginTag($a_attribs);
534 break;
535 }
536 }
537
541 public function handlerEndTag($a_xml_parser, string $a_name): void
542 {
543 switch ($this->parser_mode) {
545 $this->handlerParseEndTag($a_xml_parser, $a_name);
546 break;
548 $this->handlerVerifyEndTag($a_xml_parser, $a_name);
549 break;
550 }
551 }
552
557 public function handlerParseEndTag($a_xml_parser, string $a_name): void
558 {
559 if ($this->do_nothing && strtolower($a_name) !== "item") {
560 return;
561 }
562 switch (strtolower($a_name)) {
563 case "assessment":
564 if (is_object($this->tst_object)) {
565 $this->tst_object->fromXML($this->assessment);
566 }
567 $this->in_assessment = false;
568 break;
569 case "assessmentcontrol":
570 $this->assessment->addAssessmentcontrol($this->assessmentcontrol);
571 $this->assessmentcontrol = null;
572 break;
573 case "objectives":
574 if (strtolower($this->getParent($a_xml_parser)) === "assessment") {
575 $this->assessment->addObjectives($this->objectives);
576 }
577 $this->in_objectives = false;
578 break;
579 case 'presentation_material':
580 $this->assessment->setPresentationMaterial($this->prensentation_material);
581 $this->in_prensentation_material = false;
582 break;
583 case "itemmetadata":
584 $this->in_itemmetadata = false;
585 break;
586 case "qtimetadatafield":
587 // handle only specific ILIAS metadata
588 switch ($this->metadata["label"]) {
589 case "ILIAS_VERSION":
590 if ($this->item != null) {
591 $this->item->setIliasSourceVersion(
592 $this->fetchNumericVersionFromVersionDateString($this->metadata["entry"])
593 );
594 }
595 break;
596 case "QUESTIONTYPE":
597 if ($this->item != null) {
598 $this->item->setQuestiontype($this->metadata["entry"]);
599 }
600 break;
601 case "AUTHOR":
602 if ($this->item != null) {
603 $this->item->setAuthor($this->metadata["entry"]);
604 }
605 // no break
606 default:
607 if ($this->item != null) {
608 $this->item->addMetadata($this->metadata);
609 }
610 break;
611 }
612 if ($this->in_assessment) {
613 $this->assessment->addQtiMetadata($this->metadata);
614 }
615 $this->metadata = ["label" => "", "entry" => ""];
616 break;
617 case "flow":
618 $this->flow--;
619 break;
620 case "flow_mat":
621 if (count($this->flow_mat)) {
622 $flow_mat = array_pop($this->flow_mat);
623 if (count($this->flow_mat)) {
624 $this->flow_mat[count($this->flow_mat) - 1]->addFlowMat($flow_mat);
625 } elseif ($this->in_prensentation_material) {
626 $this->prensentation_material->addFlowMat($flow_mat);
627 } elseif ($this->itemfeedback != null) {
628 $this->itemfeedback->addFlowMat($flow_mat);
629 } elseif ($this->response_label != null) {
630 $this->response_label->addFlow_mat($flow_mat);
631 }
632 }
633 break;
634 case "itemfeedback":
635 if ($this->item != null) {
636 if ($this->itemfeedback != null) {
637 $this->item->addItemfeedback($this->itemfeedback);
638 }
639 }
640 $this->itemfeedback = null;
641 break;
642 case "displayfeedback":
643 if ($this->respcondition != null) {
644 if ($this->displayfeedback != null) {
645 $this->respcondition->addDisplayfeedback($this->displayfeedback);
646 }
647 }
648 $this->displayfeedback = null;
649 break;
650 case "setvar":
651 if ($this->respcondition != null) {
652 if ($this->setvar != null) {
653 $this->respcondition->addSetvar($this->setvar);
654 }
655 }
656 $this->setvar = null;
657 break;
658 case "conditionvar":
659 if ($this->respcondition != null) {
660 $this->respcondition->setConditionvar($this->conditionvar);
661 }
662 $this->conditionvar = null;
663 break;
664 case "varequal":
665 case "varlt":
666 case "varlte":
667 case "vargt":
668 case "vargte":
669 case "varsubset":
670 case "varinside":
671 case "varsubstring":
672 if ($this->conditionvar != null) {
673 if ($this->responsevar != null) {
674 $this->conditionvar->addResponseVar($this->responsevar);
675 }
676 }
677 $this->responsevar = null;
678 break;
679 case "respcondition":
680 if ($this->resprocessing != null) {
681 $this->resprocessing->addRespcondition($this->respcondition);
682 }
683 $this->respcondition = null;
684 break;
685 case "outcomes":
686 if ($this->resprocessing != null) {
687 $this->resprocessing->setOutcomes($this->outcomes);
688 }
689 $this->outcomes = null;
690 break;
691 case "decvar":
692 if ($this->outcomes != null) {
693 $this->outcomes->addDecvar($this->decvar);
694 }
695 $this->decvar = null;
696 break;
697 case "presentation":
698 $this->in_presentation = false;
699 if ($this->presentation != null && $this->item != null) {
700 $this->item->setPresentation($this->presentation);
701 }
702 $this->presentation = null;
703 break;
704 case "response_label":
705 if ($this->render_type != null) {
706 $this->render_type->addResponseLabel($this->response_label);
707 $this->response_label = null;
708 }
709 break;
710 case "render_choice":
711 case "render_hotspot":
712 case "render_fib":
713 if ($this->in_response) {
714 if ($this->response != null) {
715 if ($this->render_type != null) {
716 $this->response->setRenderType($this->render_type);
717 $this->render_type = null;
718 }
719 }
720 }
721 break;
722 case "response_lid":
723 case "response_xy":
724 case "response_str":
725 case "response_num":
726 case "response_grp":
727 $this->gap_index++;
728 if ($this->presentation != null) {
729 if ($this->response != null) {
730 $this->presentation->addResponse($this->response);
731 if ($this->item != null) {
732 $this->item->addPresentationitem($this->response);
733 }
734 }
735 }
736 $this->response = null;
737 $this->in_response = false;
738 break;
739 case "item":
740 if ($this->do_nothing) {
741 $this->do_nothing = false;
742 return;
743 }
744 if ((string) $this->item->getQuestionType() !== '') {
745 // this is an ILIAS QTI question
746 } else {
747 // this is a QTI question which wasn't generated by ILIAS
748 }
749 global $ilDB;
750 global $ilUser;
751 // save the item directly to save memory
752 // the database id's of the created items are exported. if the import fails
753 // ILIAS can delete the already imported items
754
755 // problems: the object id of the parent questionpool is not yet known. must be set later
756 // the complete flag must be calculated?
757 $qt = $this->item->determineQuestionType();
758 $presentation = $this->item->getPresentation();
759
761 return;
762 }
764 $question = new $qt();
765 $fbt = str_replace('ass', 'ilAss', $qt) . 'Feedback';
766 $question->feedbackOBJ = new $fbt(
767 $question,
768 $GLOBALS['ilCtrl'],
769 $GLOBALS['ilDB'],
770 $GLOBALS['lng']
771 );
772 $this->import_mapping = $question->fromXML(
773 $this->item,
774 $this->qpl_id,
775 $this->tst_id,
776 $this->tst_object,
777 $this->question_counter,
778 $this->import_mapping,
779 $this->solutionhints
780 );
781
782 $this->solutionhints = [];
783
784 $this->numImportedItems++;
785
786 break;
787 case "material":
788 if ($this->material) {
789 $mat = $this->material->getMaterial(0);
790 if (!is_array($mat)) {
791 $this->material = null;
792 break;
793 }
794 if ($mat["type"] === "mattext" && $mat["material"]->getLabel() === "suggested_solution") {
795 $this->item->addSuggestedSolution($mat["material"], $this->gap_index);
796 }
797 if ($this->in_objectives) {
798 $this->objectives->addMaterial($this->material);
799 } elseif ($this->render_type != null && strtolower($this->getParent($a_xml_parser)) === "render_hotspot") {
800 $this->render_type->addMaterial($this->material);
801 } elseif (count($this->flow_mat) && strtolower($this->getParent($a_xml_parser)) === "flow_mat") {
802 $this->flow_mat[count($this->flow_mat) - 1]->addMaterial($this->material);
803 } elseif ($this->itemfeedback != null) {
804 $this->itemfeedback->addMaterial($this->material);
805 } elseif ($this->response_label != null) {
806 $this->response_label->addMaterial($this->material);
807 } elseif ($this->response != null) {
808 if ($this->response->hasRendering()) {
809 $this->response->setMaterial2($this->material);
810 } else {
811 $this->response->setMaterial1($this->material);
812 }
813 } elseif (($this->in_presentation) && (!$this->in_response)) {
814 if (!is_object($this->item->getQuestiontext())) {
815 $this->item->setQuestiontext($this->material);
816 }
817 $this->presentation->addMaterial($this->material);
818 } elseif ($this->presentation != null) {
819 $this->presentation->addMaterial($this->material);
820 if ($this->item != null) {
821 $this->item->addPresentationitem($this->material);
822 }
823 }
824 }
825 $this->material = null;
826 break;
827 case "matimage":
828
829 if (!$this->isMatImageAvailable()) {
830 break;
831 }
832
833 if ($this->virusDetected($this->matimage->getRawContent())) {
834 break;
835 }
836 try {
837 $matImageSecurity = new ilQtiMatImageSecurity($this->matimage);
838 $matImageSecurity->sanitizeLabel();
839 } catch (Exception $e) {
840 break;
841 }
842 if (!$matImageSecurity->validate()) {
843 break;
844 }
845
846 $this->material->addMatimage($this->matimage);
847 $this->matimage = null;
848 break;
849
850 // add support for matbreak element
851 case "matbreak":
852 $this->mattext = new ilQTIMattext();
853 $this->mattext->setContent('<br />');
854 $this->material->addMattext($this->mattext);
855 $this->mattext = null;
856 break;
857 case "resprocessing":
858 if ($this->item != null) {
859 $this->item->addResprocessing($this->resprocessing);
860 }
861 $this->resprocessing = null;
862 break;
863 case "mattext":
864 if ($this->material != null) {
865 $this->material->addMattext($this->mattext);
866 }
867 $this->mattext = null;
868 break;
869 case "matapplet":
870 if ($this->material != null) {
871 $this->material->addMatapplet($this->matapplet);
872 }
873 $this->matapplet = null;
874 break;
875
877 $this->solutionhint['txt'] = $this->characterbuffer;
878 $this->solutionhints[] = $this->solutionhint;
879 break;
880 }
881 $this->depth[$a_xml_parser] -= 1; // Issue with SplObjectStorage: Cannot use --.
882 }
883
887 public function handlerCharacterData($a_xml_parser, string $a_data): void
888 {
889 switch ($this->parser_mode) {
891 $this->handlerParseCharacterData($a_xml_parser, $a_data);
892 break;
894 $this->handlerVerifyCharacterData($a_xml_parser, $a_data);
895 break;
896 }
897 }
898
902 public function handlerParseCharacterData($a_xml_parser, string $a_data): void
903 {
904 if ($this->do_nothing) {
905 return;
906 }
907 $this->characterbuffer .= $a_data;
908 $a_data = $this->characterbuffer;
909 switch ($this->qti_element) {
910 case "fieldlabel":
911 $this->metadata["label"] = $a_data;
912 break;
913 case "fieldentry":
914 $this->metadata["entry"] = $a_data;
915 break;
916 case "response_label":
917 if ($this->response_label != null) {
918 $this->response_label->setContent($a_data);
919 }
920 break;
921 case "setvar":
922 if ($this->setvar != null) {
923 $this->setvar->setContent($a_data);
924 }
925 break;
926 case "displayfeedback":
927 if ($this->displayfeedback != null) {
928 $this->displayfeedback->setContent($a_data);
929 }
930 break;
931 case "varequal":
932 case "varlt":
933 case "varlte":
934 case "vargt":
935 case "vargte":
936 case "varsubset":
937 case "varinside":
938 case "varsubstring":
939 if ($this->responsevar != null) {
940 $this->responsevar->setContent($a_data);
941 }
942 break;
943 case "decvar":
944 if (strlen($a_data)) {
945 if ($this->decvar != null) {
946 $this->decvar->setContent($a_data);
947 }
948 }
949 break;
950 case "mattext":
951 if ($this->mattext != null) {
952 $this->mattext->setContent($a_data);
953 }
954 break;
955 case "matapplet":
956 if ($this->matapplet != null) {
957 $this->matapplet->setContent($a_data);
958 }
959 break;
960 case "matimage":
961 if ($this->matimage != null) {
962 $this->matimage->setContent($a_data);
963 }
964 break;
965 case "duration":
966 switch ($this->getParent($a_xml_parser)) {
967 case "assessment":
968 // to be done
969 break;
970 case "section":
971 // to be done
972 break;
973 case "item":
974 $this->item->setDuration($a_data);
975 break;
976 }
977 break;
978 case "qticomment":
979 switch ($this->getParent($a_xml_parser)) {
980 case "item":
981 $this->item->setComment($a_data);
982 break;
983 case "assessment":
984 $this->assessment->setComment($a_data);
985 break;
986 default:
987 break;
988 }
989 break;
990 }
991 $this->sametag = true;
992 }
993
998 public function handlerVerifyBeginTag($a_xml_parser, string $a_name, array $a_attribs): void
999 {
1000 $this->qti_element = $a_name;
1001
1002 switch (strtolower($a_name)) {
1003 case "assessment":
1004 $this->assessment = $this->assessments[] = new ilQTIAssessment();
1005 $this->in_assessment = true;
1006 foreach ($a_attribs as $attribute => $value) {
1007 switch (strtolower($attribute)) {
1008 case "title":
1009 $this->assessment->setTitle($value);
1010 break;
1011 case "ident":
1012 $this->assessment->setIdent($value);
1013 break;
1014 }
1015 }
1016 break;
1017 case "questestinterop":
1018 $this->verifyroot = true;
1019 break;
1020 case "qtimetadatafield":
1021 $this->metadata = ["label" => "", "entry" => ""];
1022 $this->verifymetadatafield = 1;
1023 break;
1024 case "fieldlabel":
1025 $this->verifyfieldlabeltext = "";
1026 if ($this->verifymetadatafield == 1) {
1027 $this->verifyfieldlabel = 1;
1028 }
1029 break;
1030 case "fieldentry":
1031 $this->verifyfieldentrytext = "";
1032 if ($this->verifymetadatafield == 1) {
1033 $this->verifyfieldentry = 1;
1034 }
1035 break;
1036 case "item":
1037 $title = "";
1038 foreach ($a_attribs as $attribute => $value) {
1039 switch (strtolower($attribute)) {
1040 case "title":
1041 $title = $value;
1042 break;
1043 }
1044 }
1045 $this->founditems[] = ["title" => "$title", "type" => "", "ident" => $a_attribs["ident"]];
1046 break;
1047 case "response_lid":
1048 if (strlen($this->founditems[count($this->founditems) - 1]["type"]) == 0) {
1049 // test for non ILIAS generated question types
1050 foreach ($a_attribs as $attribute => $value) {
1051 switch (strtolower($attribute)) {
1052 case "rcardinality":
1053 switch (strtolower($value)) {
1054 case "single":
1055 $this->founditems[count($this->founditems) - 1]["type"] = ilQTIItem::QT_MULTIPLE_CHOICE_SR;
1056 break;
1057 case "multiple":
1058 $this->founditems[count($this->founditems) - 1]["type"] = ilQTIItem::QT_MULTIPLE_CHOICE_MR;
1059 break;
1060 case "ordered":
1061 $this->founditems[count($this->founditems) - 1]["type"] = ilQTIItem::QT_ORDERING;
1062 break;
1063 }
1064 break;
1065 }
1066 }
1067 }
1068 break;
1069
1071 $this->solutionhint = array_map('intval', $a_attribs);
1072 $this->solutionhint['txt'] = '';
1073 break;
1074 case "response_str":
1075 if (strlen($this->founditems[count($this->founditems) - 1]["type"]) == 0) {
1076 // test for non ILIAS generated question types
1077 foreach ($a_attribs as $attribute => $value) {
1078 switch (strtolower($attribute)) {
1079 case "rcardinality":
1080 switch (strtolower($value)) {
1081 case "single":
1082 $this->founditems[count($this->founditems) - 1]["type"] = ilQTIItem::QT_CLOZE;
1083 break;
1084 case "ordered":
1085 $this->founditems[count($this->founditems) - 1]["type"] = ilQTIItem::QT_TEXT;
1086 break;
1087 }
1088 break;
1089 }
1090 }
1091 }
1092 break;
1093 case "response_xy":
1094 if (strlen($this->founditems[count($this->founditems) - 1]["type"]) == 0) {
1095 $this->founditems[count($this->founditems) - 1]["type"] = ilQTIItem::QT_IMAGEMAP;
1096 }
1097 break;
1098 case "response_num":
1099 if (strlen($this->founditems[count($this->founditems) - 1]["type"]) == 0) {
1100 $this->founditems[count($this->founditems) - 1]["type"] = ilQTIItem::QT_NUMERIC;
1101 }
1102 break;
1103 case "response_grp":
1104 if (strlen($this->founditems[count($this->founditems) - 1]["type"]) == 0) {
1105 $this->founditems[count($this->founditems) - 1]["type"] = ilQTIItem::QT_MATCHING;
1106 }
1107 break;
1108 case "qticomment":
1109 // check for "old" ILIAS qti format (not well formed)
1110 $this->verifyqticomment = 1;
1111 break;
1112 case "presentation":
1113 foreach ($a_attribs as $attribute => $value) {
1114 switch (strtolower($attribute)) {
1115 case "label":
1116 $this->founditems[count($this->founditems) - 1]["title"] = $value;
1117 break;
1118 }
1119 }
1120 break;
1121
1122 }
1123 }
1124
1128 public function handlerVerifyEndTag($a_xml_parser, string $a_name): void
1129 {
1130 switch (strtolower($a_name)) {
1131 case "assessment":
1132 foreach ($this->assessment->qtimetadata as $metaField) {
1133 if ($metaField['label'] == 'question_set_type') {
1134 $this->setQuestionSetType($metaField['entry']);
1135 break;
1136 }
1137
1138 if ($metaField['label'] == 'random_test') {
1139 if ($metaField['entry'] == 1) {
1141 } else {
1143 }
1144 break;
1145 }
1146 }
1147 $this->in_assessment = false;
1148 break;
1149 case "qticomment":
1150 // check for "old" ILIAS qti format (not well formed)
1151 $this->verifyqticomment = 0;
1152 break;
1153 case "qtimetadatafield":
1154 $this->verifymetadatafield = 0;
1155 if ($this->verifyfieldlabeltext === "QUESTIONTYPE") {
1156 $this->founditems[count($this->founditems) - 1]["type"] = $this->verifyfieldentrytext;
1157 }
1158 if ($this->in_assessment) {
1159 $this->assessment->addQtiMetadata($this->metadata);
1160 }
1161 $this->metadata = ["label" => "", "entry" => ""];
1162 break;
1163 case "fieldlabel":
1164 $this->verifyfieldlabel = 0;
1165 break;
1166 case "fieldentry":
1167 $this->verifyfieldentry = 0;
1168 break;
1169 }
1170 }
1171
1175 public function handlerVerifyCharacterData($a_xml_parser, string $a_data): void
1176 {
1177 if ($this->verifyqticomment == 1) {
1178 if (preg_match("/Questiontype\=(.*)/", $a_data, $matches)) {
1179 if (count($this->founditems)) {
1180 $this->founditems[count($this->founditems) - 1]["type"] = $matches[1];
1181 }
1182 }
1183 } elseif ($this->verifyfieldlabel == 1) {
1184 $this->verifyfieldlabeltext = $a_data;
1185 } elseif ($this->verifyfieldentry == 1) {
1186 $this->verifyfieldentrytext = $a_data;
1187 }
1188
1189 switch ($this->qti_element) {
1190 case "fieldlabel":
1191 $this->metadata["label"] = $a_data;
1192 break;
1193 case "fieldentry":
1194 $this->metadata["entry"] = $a_data;
1195 break;
1196 }
1197 }
1198
1202 public function &getFoundItems(): array
1203 {
1204 return $this->founditems;
1205 }
1206
1211 public function getImportMapping(): array
1212 {
1213 return $this->import_mapping;
1214 }
1215
1219 public function getQuestionIdMapping(): array
1220 {
1221 $questionIdMapping = [];
1222
1223 foreach ($this->getImportMapping() as $k => $v) {
1224 $oldQuestionId = substr($k, strpos($k, 'qst_') + strlen('qst_'));
1225 $newQuestionId = $v['test']; // yes, this is the new question id ^^
1226
1227 $questionIdMapping[$oldQuestionId] = $newQuestionId;
1228 }
1229
1230 return $questionIdMapping;
1231 }
1232
1233 public function setXMLContent(string $a_xml_content): void
1234 {
1235 $a_xml_content = $this->cleanInvalidXmlChars($a_xml_content);
1236
1237 parent::setXMLContent($a_xml_content);
1238 }
1239
1243 protected function openXMLFile()
1244 {
1245 $xmlContent = file_get_contents($this->xml_file);
1246 $xmlContent = $this->cleanInvalidXmlChars($xmlContent);
1247 file_put_contents($this->xml_file, $xmlContent);
1248
1249 return parent::openXMLFile();
1250 }
1251
1252 protected function fetchNumericVersionFromVersionDateString(string $versionDateString): ?string
1253 {
1254 $matches = null;
1255
1256 if (preg_match('/^(\d+\.\d+(?:\.\d+)?)(?: .*)?$/', $versionDateString, $matches)) {
1257 return $matches[1];
1258 }
1259
1260 return null;
1261 }
1262
1263 protected function fetchSourceNicFromItemIdent(string $itemIdent): ?string
1264 {
1265 $matches = null;
1266
1267 if (preg_match('/^il_(\d+?)_qst_\d+$/', $itemIdent, $matches)) {
1268 return $matches[1];
1269 }
1270
1271 return null;
1272 }
1273
1274 protected function cleanInvalidXmlChars(string $xmlContent): string
1275 {
1276 // http://www.w3.org/TR/xml/#charsets
1277
1278 // DOES ACTUALLY KILL CONTENT, SHOULD CLEAN NON ESCAPED ILLEGAL CHARS, DON'T KNOW
1279 //$reg = '/[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]/';
1280 //$xmlContent = preg_replace($reg, '', $xmlContent);
1281
1282 // remove illegal chars escaped to html entities
1283 $needles = [];
1284 for ($i = 0x00, $max = 0x08; $i <= $max; $i += 0x01) {
1285 $needles[] = "&#{$i};";
1286 }
1287 for ($i = 0x0b, $max = 0x0c; $i <= $max; $i += 0x01) {
1288 $needles[] = "&#{$i};";
1289 }
1290 for ($i = 0x0e, $max = 0x1f; $i <= $max; $i += 0x01) {
1291 $needles[] = "&#{$i};";
1292 }
1293 for ($i = 0xd800, $max = 0xdfff; $i <= $max; $i += 0x0001) {
1294 $needles[] = "&#{$i};";
1295 }
1296 for ($i = 0xfffe, $max = 0xffff; $i <= $max; $i += 0x0001) {
1297 $needles[] = "&#{$i};";
1298 }
1299 $reg = '/(' . implode('|', $needles) . ')/';
1300 $xmlContent = preg_replace($reg, '', $xmlContent);
1301
1302 return $xmlContent;
1303 }
1304
1305 public function getNumImportedItems(): int
1306 {
1308 }
1309
1310 protected function isMatImageAvailable(): bool
1311 {
1312 if (!$this->material) {
1313 return false;
1314 }
1315
1316 if (!$this->matimage) {
1317 return false;
1318 }
1319
1320 return true;
1321 }
1322
1323 protected function virusDetected(string $buffer): bool
1324 {
1326
1327 if ($vs === null) {
1328 return false; // no virus scan, no virus detected
1329 }
1330
1331 return $vs->scanBuffer($buffer);
1332 }
1333
1334 private function assessmentBeginTag(array $a_attribs): void
1335 {
1336 $this->assessment = $this->assessments[] = new ilQTIAssessment();
1337 $this->in_assessment = true;
1338 foreach ($a_attribs as $attribute => $value) {
1339 switch (strtolower($attribute)) {
1340 case "title":
1341 $this->assessment->setTitle($value);
1342 break;
1343 case "ident":
1344 $this->assessment->setIdent($value);
1345 break;
1346 }
1347 }
1348 }
1349
1350 private function assessmentControlBeginTag(array $a_attribs): void
1351 {
1352 $this->assessmentcontrol = new ilQTIAssessmentcontrol();
1353 foreach ($a_attribs as $attribute => $value) {
1354 switch (strtolower($attribute)) {
1355 case "solutionswitch":
1356 $this->assessmentcontrol->setSolutionswitch($value);
1357 break;
1358 case "hintswitch":
1359 $this->assessmentcontrol->setHintswitch($value);
1360 break;
1361 case "feedbackswitch":
1362 $this->assessmentcontrol->setFeedbackswitch($value);
1363 break;
1364 }
1365 }
1366 }
1367
1368 private function itemFeedbackBeginTag(array $a_attribs): void
1369 {
1370 $this->itemfeedback = new ilQTIItemfeedback();
1371 foreach ($a_attribs as $attribute => $value) {
1372 switch (strtolower($attribute)) {
1373 case "ident":
1374 $this->itemfeedback->setIdent($value);
1375 break;
1376 case "view":
1377 $this->itemfeedback->setView($value);
1378 break;
1379 }
1380 }
1381 }
1382
1383 private function displayFeedbackBeginTag(array $a_attribs): void
1384 {
1385 $this->displayfeedback = new ilQTIDisplayfeedback();
1386 foreach ($a_attribs as $attribute => $value) {
1387 switch (strtolower($attribute)) {
1388 case "feedbacktype":
1389 $this->displayfeedback->setFeedbacktype($value);
1390 break;
1391 case "linkrefid":
1392 $this->displayfeedback->setLinkrefid($value);
1393 break;
1394 }
1395 }
1396 }
1397
1398 private function setVarBeginTag(array $a_attribs): void
1399 {
1400 $this->setvar = new ilQTISetvar();
1401 foreach ($a_attribs as $attribute => $value) {
1402 switch (strtolower($attribute)) {
1403 case "action":
1404 $this->setvar->setAction($value);
1405 break;
1406 case "varname":
1407 $this->setvar->setVarname($value);
1408 break;
1409 }
1410 }
1411 }
1412
1413 private function varEqualBeginTag(array $a_attribs): void
1414 {
1415 $this->responsevar = new ilQTIResponseVar(ilQTIResponseVar::RESPONSEVAR_EQUAL);
1416 foreach ($a_attribs as $attribute => $value) {
1417 switch (strtolower($attribute)) {
1418 case "case":
1419 $this->responsevar->setCase($value);
1420 break;
1421 case "respident":
1422 $this->responsevar->setRespident($value);
1423 break;
1424 case "index":
1425 $this->responsevar->setIndex($value);
1426 break;
1427 }
1428 }
1429 }
1430
1431 private function termsAndDefinitionsBeginTag(string $a_name, array $a_attribs): void
1432 {
1433 $response_type = 0;
1434 switch (strtolower($a_name)) {
1435 case "response_lid":
1436 $response_type = ilQTIResponse::RT_RESPONSE_LID;
1437 break;
1438 case "response_xy":
1439 $response_type = ilQTIResponse::RT_RESPONSE_XY;
1440 break;
1441 case "response_str":
1442 $response_type = ilQTIResponse::RT_RESPONSE_STR;
1443 break;
1444 case "response_num":
1445 $response_type = ilQTIResponse::RT_RESPONSE_NUM;
1446 break;
1447 case "response_grp":
1448 $response_type = ilQTIResponse::RT_RESPONSE_GRP;
1449 break;
1450 }
1451 $this->in_response = true;
1452 $this->response = new ilQTIResponse($response_type);
1453 $this->response->setFlow($this->flow);
1454 foreach ($a_attribs as $attribute => $value) {
1455 switch (strtolower($attribute)) {
1456 case "ident":
1457 $this->response->setIdent($value);
1458 break;
1459 case "rtiming":
1460 $this->response->setRTiming($value);
1461 break;
1462 case "rcardinality":
1463 $this->response->setRCardinality($value);
1464 break;
1465 case "numtype":
1466 $this->response->setNumtype($value);
1467 break;
1468 }
1469 }
1470 }
1471
1472 private function itemBeginTag(array $a_attribs): void
1473 {
1474 $this->gap_index = 0;
1475 $this->item = $this->items[] = new ilQTIItem();
1476 foreach ($a_attribs as $attribute => $value) {
1477 switch (strtolower($attribute)) {
1478 case "ident":
1479 $this->item->setIdent($value);
1480 $this->item->setIliasSourceNic(
1481 $this->fetchSourceNicFromItemIdent($value)
1482 );
1483 if ($this->isIgnoreItemsEnabled()) {
1484 $this->do_nothing = true;
1485 } elseif (count($this->import_idents) > 0) {
1486 if (!in_array($value, $this->import_idents)) {
1487 $this->do_nothing = true;
1488 }
1489 }
1490 break;
1491 case "title":
1492 $this->item->setTitle($value);
1493 break;
1494 case "maxattempts":
1495 $this->item->setMaxattempts($value);
1496 break;
1497 }
1498 }
1499 }
1500
1501 private function resprocessingBeginTag(array $a_attribs): void
1502 {
1503 $this->resprocessing = new ilQTIResprocessing();
1504 foreach ($a_attribs as $attribute => $value) {
1505 switch (strtolower($attribute)) {
1506 case "scoremodel":
1507 $this->resprocessing->setScoremodel($value);
1508 break;
1509 }
1510 }
1511 }
1512
1513 private function renderFibBeginTag(array $a_attribs): void
1514 {
1515 if (!$this->in_response) {
1516 return;
1517 }
1518 $this->render_type = new ilQTIRenderFib();
1519 foreach ($a_attribs as $attribute => $value) {
1520 switch (strtolower($attribute)) {
1521 case "encoding":
1522 $this->render_type->setEncoding($value);
1523 break;
1524 case "fibtype":
1525 $this->render_type->setFibtype($value);
1526 break;
1527 case "rows":
1528 $this->render_type->setRows($value);
1529 break;
1530 case "maxchars":
1531 $this->render_type->setMaxchars($value);
1532 break;
1533 case "prompt":
1534 $this->render_type->setPrompt($value);
1535 break;
1536 case "columns":
1537 $this->render_type->setColumns($value);
1538 break;
1539 case "charset":
1540 $this->render_type->setCharset($value);
1541 break;
1542 case "maxnumber":
1543 $this->render_type->setMaxnumber($value);
1544 break;
1545 case "minnumber":
1546 $this->render_type->setMinnumber($value);
1547 break;
1548 }
1549 }
1550 }
1551
1552 private function renderHotspotBeginTag(array $a_attribs): void
1553 {
1554 if (!$this->in_response) {
1555 return;
1556 }
1557 $this->render_type = new ilQTIRenderHotspot();
1558 foreach ($a_attribs as $attribute => $value) {
1559 switch (strtolower($attribute)) {
1560 case "showdraw":
1561 $this->render_type->setShowdraw($value);
1562 break;
1563 case "minnumber":
1564 $this->render_type->setMinnumber($value);
1565 break;
1566 case "maxnumber":
1567 $this->render_type->setMaxnumber($value);
1568 break;
1569 }
1570 }
1571 }
1572
1573 private function renderChoiceBeginTag(array $a_attribs): void
1574 {
1575 if (!$this->in_response) {
1576 return;
1577 }
1578 $this->render_type = new ilQTIRenderChoice();
1579 foreach ($a_attribs as $attribute => $value) {
1580 switch (strtolower($attribute)) {
1581 case "shuffle":
1582 $this->render_type->setShuffle($value);
1583 break;
1584 case 'minnumber':
1585 $this->render_type->setMinnumber($value);
1586 break;
1587 case 'maxnumber':
1588 $this->render_type->setMaxnumber($value);
1589 break;
1590 }
1591 }
1592 }
1593
1594 private function responseLabelBeginTag(array $a_attribs): void
1595 {
1596 if ($this->render_type == null) {
1597 return;
1598 }
1599 $this->response_label = new ilQTIResponseLabel();
1600 foreach ($a_attribs as $attribute => $value) {
1601 switch (strtolower($attribute)) {
1602 case "rshuffle":
1603 $this->response_label->setRshuffle($value);
1604 break;
1605 case "rarea":
1606 $this->response_label->setRarea($value);
1607 break;
1608 case "rrange":
1609 $this->response_label->setRrange($value);
1610 break;
1611 case "labelrefid":
1612 $this->response_label->setLabelrefid($value);
1613 break;
1614 case "ident":
1615 $this->response_label->setIdent($value);
1616 break;
1617 case "match_group":
1618 $this->response_label->setMatchGroup($value);
1619 break;
1620 case "match_max":
1621 $this->response_label->setMatchMax($value);
1622 break;
1623 }
1624 }
1625 }
1626
1627 private function matAppletBeginTag(array $a_attribs): void
1628 {
1629 $this->matapplet = new ilQTIMatapplet();
1630 foreach ($a_attribs as $attribute => $value) {
1631 switch (strtolower($attribute)) {
1632 case "label":
1633 $this->matapplet->setLabel($value);
1634 break;
1635 case "uri":
1636 $this->matapplet->setUri($value);
1637 break;
1638 case "y0":
1639 $this->matapplet->setY0($value);
1640 break;
1641 case "height":
1642 $this->matapplet->setHeight($value);
1643 break;
1644 case "width":
1645 $this->matapplet->setWidth($value);
1646 break;
1647 case "x0":
1648 $this->matapplet->setX0($value);
1649 break;
1650 case "embedded":
1651 $this->matapplet->setEmbedded($value);
1652 break;
1653 case "entityref":
1654 $this->matapplet->setEntityref($value);
1655 break;
1656 }
1657 }
1658 }
1659
1660 private function matTextBeginTag(array $a_attribs): void
1661 {
1662 $this->mattext = new ilQTIMattext();
1663 foreach ($a_attribs as $attribute => $value) {
1664 switch (strtolower($attribute)) {
1665 case "texttype":
1666 $this->mattext->setTexttype($value);
1667 break;
1668 case "label":
1669 $this->mattext->setLabel($value);
1670 break;
1671 case "charset":
1672 $this->mattext->setCharset($value);
1673 break;
1674 case "uri":
1675 $this->mattext->setUri($value);
1676 break;
1677 case "xml:space":
1678 $this->mattext->setXmlspace($value);
1679 break;
1680 case "xml:lang":
1681 $this->mattext->setXmllang($value);
1682 break;
1683 case "entityref":
1684 $this->mattext->setEntityref($value);
1685 break;
1686 case "height":
1687 $this->mattext->setHeight($value);
1688 break;
1689 case "width":
1690 $this->mattext->setWidth($value);
1691 break;
1692 case "x0":
1693 $this->mattext->setX0($value);
1694 break;
1695 case "y0":
1696 $this->mattext->setY0($value);
1697 break;
1698 }
1699 }
1700 }
1701
1702 private function materialBeginTag(array $a_attribs): void
1703 {
1704 $this->material = new ilQTIMaterial();
1705 $this->material->setFlow($this->flow);
1706 foreach ($a_attribs as $attribute => $value) {
1707 switch (strtolower($attribute)) {
1708 case "label":
1709 $this->material->setLabel($value);
1710 break;
1711 }
1712 }
1713 }
1714
1715 private function matImageBeginTag(array $a_attribs): void
1716 {
1717 $this->matimage = new ilQTIMatimage();
1718 foreach ($a_attribs as $attribute => $value) {
1719 switch (strtolower($attribute)) {
1720 case "imagtype":
1721 $this->matimage->setImagetype($value);
1722 break;
1723 case "label":
1724 $this->matimage->setLabel($value);
1725 break;
1726 case "height":
1727 $this->matimage->setHeight($value);
1728 break;
1729 case "width":
1730 $this->matimage->setWidth($value);
1731 break;
1732 case "uri":
1733 $this->matimage->setUri($value);
1734 break;
1735 case "embedded":
1736 $this->matimage->setEmbedded($value);
1737 break;
1738 case "x0":
1739 $this->matimage->setX0($value);
1740 break;
1741 case "y0":
1742 $this->matimage->setY0($value);
1743 break;
1744 case "entityref":
1745 $this->matimage->setEntityref($value);
1746 break;
1747 }
1748 }
1749 if (!$this->matimage->getEmbedded() && strlen($this->matimage->getUri())) {
1750 $img_string = @file_get_contents(dirname($this->xml_file) . '/' . $this->matimage->getUri());
1751
1752 if (is_string($img_string)) {
1753 $this->matimage->setContent($img_string);
1754 }
1755 }
1756 }
1757
1758 private function decVarBeginTag(array $a_attribs): void
1759 {
1760 $this->decvar = new ilQTIDecvar();
1761 foreach ($a_attribs as $attribute => $value) {
1762 switch (strtolower($attribute)) {
1763 case "varname":
1764 $this->decvar->setVarname($value);
1765 break;
1766 case "vartype":
1767 $this->decvar->setVartype($value);
1768 break;
1769 case "defaultval":
1770 $this->decvar->setDefaultval($value);
1771 break;
1772 case "minvalue":
1773 $this->decvar->setMinvalue($value);
1774 break;
1775 case "maxvalue":
1776 $this->decvar->setMaxvalue($value);
1777 break;
1778 case "members":
1779 $this->decvar->setMembers($value);
1780 break;
1781 case "cutvalue":
1782 $this->decvar->setCutvalue($value);
1783 break;
1784 }
1785 }
1786 }
1787
1791 private function createParserStorage()
1792 {
1793 $parser = xml_parser_create();
1794 $is_resource = is_resource($parser);
1795 xml_parser_free($parser);
1796
1797 return $is_resource ? [] : new SplObjectStorage();
1798 }
1799}
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
static _includeClass(string $question_type, int $gui=0)
static isImportable($questionTypeTag)
const QUESTION_SET_TYPE_RANDOM
const QUESTION_SET_TYPE_FIXED
const QT_MULTIPLE_CHOICE_MR
const QT_MULTIPLE_CHOICE_SR
const QT_NUMERIC
const QT_MATCHING
const QT_ORDERING
const QT_IMAGEMAP
resprocessingBeginTag(array $a_attribs)
setIgnoreItemsEnabled(bool $ignoreItemsEnabled)
renderChoiceBeginTag(array $a_attribs)
setHandlers($a_xml_parser)
set event handler should be overwritten by inherited class @access private
displayFeedbackBeginTag(array $a_attribs)
ilQTIConditionvar $conditionvar
ilObjTest $tst_object
fetchNumericVersionFromVersionDateString(string $versionDateString)
assessmentControlBeginTag(array $a_attribs)
itemBeginTag(array $a_attribs)
matTextBeginTag(array $a_attribs)
ilQTIRespcondition $respcondition
ilQTIPresentation $presentation
decVarBeginTag(array $a_attribs)
ilQTIObjectives $objectives
openXMLFile()
resource
handlerParseCharacterData($a_xml_parser, string $a_data)
ilQTIResponse $response
ilQTIDisplayfeedback $displayfeedback
ilQTISection $section
handlerParseBeginTag($a_xml_parser, string $a_name, array $a_attribs)
materialBeginTag(array $a_attribs)
virusDetected(string $buffer)
ilQTIResponseLabel $response_label
cleanInvalidXmlChars(string $xmlContent)
setQuestionSetType(string $questionSetType)
ilQTIResponseVar $responsevar
getParent($a_xml_parser)
ilQTIItemfeedback $itemfeedback
ilQTISetvar $setvar
matAppletBeginTag(array $a_attribs)
handlerCharacterData($a_xml_parser, string $a_data)
handlerVerifyCharacterData($a_xml_parser, string $a_data)
string $verifyfieldentrytext
handlerVerifyBeginTag($a_xml_parser, string $a_name, array $a_attribs)
ilQTIDecvar $decvar
responseLabelBeginTag(array $a_attribs)
startParsing()
stores xml data in array
ilQTIPresentationMaterial $prensentation_material
setTestObject(ilObjTest $a_tst_object)
matImageBeginTag(array $a_attribs)
itemFeedbackBeginTag(array $a_attribs)
ilQTIMaterial $material
setVarBeginTag(array $a_attribs)
ilQTIOutcomes $outcomes
string $verifyfieldlabeltext
bool $in_prensentation_material
getImportMapping()
Get array of new created questions for import id.
termsAndDefinitionsBeginTag(string $a_name, array $a_attribs)
setXMLContent(string $a_xml_content)
handlerVerifyEndTag($a_xml_parser, string $a_name)
ilQTIMattext $mattext
ilQTIResprocessing $resprocessing
renderFibBeginTag(array $a_attribs)
handlerParseEndTag($a_xml_parser, string $a_name)
@noinspection NotOptimalIfConditionsInspection
ilQTIAssessment $assessment
ilQTIMatimage $matimage
ilQTIAssessmentcontrol $assessmentcontrol
__construct(?string $a_xml_file, int $a_mode=self::IL_MO_PARSE_QTI, int $a_qpl_id=0, $a_import_idents="")
ilQTIMatapplet $matapplet
handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs)
varEqualBeginTag(array $a_attribs)
fetchSourceNicFromItemIdent(string $itemIdent)
assessmentBeginTag(array $a_attribs)
renderHotspotBeginTag(array $a_attribs)
handlerEndTag($a_xml_parser, string $a_name)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
ilLanguage $lng
$ilUser
Definition: imgupload.php:34
$i
Definition: metadata.php:41
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...