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