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