ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
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 
24 include_once("./classes/class.ilSaxParser.php");
25 
26 define ("IL_MO_PARSE_QTI", 1);
27 define ("IL_MO_VERIFY_QTI", 2);
28 
38 class ilQTIParser extends ilSaxParser
39 {
40  var $lng;
42  var $path;
43  var $items;
44  var $item;
45  var $depth;
51  var $material;
52  var $matimage;
53  var $response;
55  var $outcomes;
56  var $decvar;
58  var $setvar;
61  var $flow_mat;
62  var $flow;
64  var $mattext;
65  var $sametag;
70  var $qpl_id;
71  var $tst_id;
79  var $in_assessment = FALSE;
80  var $section;
84  var $in_objectives = FALSE;
85 
86  var $founditems = array();
87  var $verifyroot = false;
94 
102  // 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 ????
103  function ilQTIParser($a_xml_file, $a_mode = IL_MO_PARSE_QTI, $a_qpl_id = 0, $a_import_idents = "")
104  {
105  global $lng;
106 
107  $this->setParserMode($a_mode);
108 
109  parent::ilSaxParser($a_xml_file);
110 
111  $this->qpl_id = $a_qpl_id;
112  $this->import_idents = array();
113  if (is_array($a_import_idents))
114  {
115  $this->import_idents =& $a_import_idents;
116  }
117 
118  $this->lng =& $lng;
119  $this->hasRootElement = FALSE;
120  $this->import_mapping = array();
121  $this->assessments = array();
122  $this->assessment = NULL;
123  $this->section = NULL;
124  $this->path = array();
125  $this->items = array();
126  $this->item = NULL;
127  $this->depth = array();
128  $this->do_nothing = FALSE;
129  $this->qti_element = "";
130  $this->in_presentation = FALSE;
131  $this->in_objectives = FALSE;
132  $this->in_reponse = FALSE;
133  $this->render_type = NULL;
134  $this->render_hotspot = NULL;
135  $this->response_label = NULL;
136  $this->material = NULL;
137  $this->response = NULL;
138  $this->assessmentcontrol = NULL;
139  $this->objectives = NULL;
140  $this->matimage = NULL;
141  $this->resprocessing = NULL;
142  $this->outcomes = NULL;
143  $this->decvar = NULL;
144  $this->respcondition = NULL;
145  $this->setvar = NULL;
146  $this->displayfeedback = NULL;
147  $this->itemfeedback = NULL;
148  $this->flow_mat = array();
149  $this->question_counter = 1;
150  $this->flow = 0;
151  $this->gap_index = 0;
152  $this->presentation = NULL;
153  $this->mattext = NULL;
154  $this->matapplet = NULL;
155  $this->sametag = FALSE;
156  $this->in_assessment = FALSE;
157  $this->characterbuffer = "";
158  $this->metadata = array("label" => "", "entry" => "");
159  }
160 
161  function setTestObject(&$a_tst_object)
162  {
163  $this->tst_object =& $a_tst_object;
164  if (is_object($a_tst_object))
165  {
166  $this->tst_id = $this->tst_object->getId();
167  }
168  }
169 
170  function setParserMode($a_mode = IL_MO_PARSE_QTI)
171  {
172  $this->parser_mode = $a_mode;
173  $this->founditems = array();
174  $this->verifyroot = false;
175  $this->verifyqticomment = 0;
176  $this->verifymetadatafield = 0;
177  $this->verifyfieldlabel = 0;
178  $this->verifyfieldentry = 0;
179  $this->verifyfieldlabeltext = "";
180  $this->verifyfieldentrytext = "";
181  $this->question_counter = 1;
182  }
183 
189  function setHandlers($a_xml_parser)
190  {
191  xml_set_object($a_xml_parser,$this);
192  xml_set_element_handler($a_xml_parser,'handlerBeginTag','handlerEndTag');
193  xml_set_character_data_handler($a_xml_parser,'handlerCharacterData');
194  }
195 
196  function startParsing()
197  {
198  $this->question_counter = 1;
200  return FALSE;
201  }
202 
203  function getParent($a_xml_parser)
204  {
205  if ($this->depth[$a_xml_parser] > 0)
206  {
207  return $this->path[$this->depth[$a_xml_parser]-1];
208  }
209  else
210  {
211  return "";
212  }
213  }
214 
218  function handlerBeginTag($a_xml_parser,$a_name,$a_attribs)
219  {
220  switch ($this->parser_mode)
221  {
222  case IL_MO_PARSE_QTI:
223  $this->handlerParseBeginTag($a_xml_parser, $a_name, $a_attribs);
224  break;
225  case IL_MO_VERIFY_QTI:
226  $this->handlerVerifyBeginTag($a_xml_parser, $a_name, $a_attribs);
227  break;
228  }
229  }
230 
234  function handlerParseBeginTag($a_xml_parser,$a_name,$a_attribs)
235  {
236  if ($this->do_nothing) return;
237  $this->sametag = FALSE;
238  $this->characterbuffer = "";
239  $this->depth[$a_xml_parser]++;
240  $this->path[$this->depth[$a_xml_parser]] = strtolower($a_name);
241  $this->qti_element = $a_name;
242 
243  switch (strtolower($a_name))
244  {
245  case "assessment":
246  include_once ("./Services/QTI/classes/class.ilQTIAssessment.php");
247  $this->assessment =& $this->assessments[array_push($this->assessments, new ilQTIAssessment())-1];
248  $this->in_assessment = TRUE;
249  if (is_array($a_attribs))
250  {
251  foreach ($a_attribs as $attribute => $value)
252  {
253  switch (strtolower($attribute))
254  {
255  case "title":
256  $this->assessment->setTitle($value);
257  break;
258  case "ident":
259  $this->assessment->setIdent($value);
260  break;
261  }
262  }
263  }
264  break;
265  case "assessmentcontrol":
266  include_once ("./Services/QTI/classes/class.ilQTIAssessmentcontrol.php");
267  $this->assessmentcontrol = new ilQTIAssessmentcontrol();
268  if (is_array($a_attribs))
269  {
270  foreach ($a_attribs as $attribute => $value)
271  {
272  switch (strtolower($attribute))
273  {
274  case "solutionswitch":
275  $this->assessmentcontrol->setSolutionswitch($value);
276  break;
277  case "hintswitch":
278  $this->assessmentcontrol->setHintswitch($value);
279  break;
280  case "feedbackswitch":
281  $this->assessmentcontrol->setFeedbackswitch($value);
282  break;
283  }
284  }
285  }
286  break;
287  case "objectives":
288  include_once ("./Services/QTI/classes/class.ilQTIObjectives.php");
289  $this->objectives = new ilQTIObjectives();
290  $this->in_objectives = TRUE;
291  break;
292  case "section":
293  include_once ("./Services/QTI/classes/class.ilQTISection.php");
294  $this->section = new ilQTISection();
295  break;
296  case "itemmetadata":
297  $this->in_itemmetadata = TRUE;
298  break;
299  case "qtimetadatafield":
300  $this->metadata = array("label" => "", "entry" => "");
301  break;
302  case "flow":
303  include_once ("./Services/QTI/classes/class.ilQTIFlow.php");
304  $this->flow++;
305  break;
306  case "flow_mat":
307  include_once ("./Services/QTI/classes/class.ilQTIFlowMat.php");
308  array_push($this->flow_mat, new ilQTIFlowMat());
309  break;
310  case "itemfeedback":
311  include_once ("./Services/QTI/classes/class.ilQTIItemfeedback.php");
312  $this->itemfeedback = new ilQTIItemfeedback();
313  if (is_array($a_attribs))
314  {
315  foreach ($a_attribs as $attribute => $value)
316  {
317  switch (strtolower($attribute))
318  {
319  case "ident":
320  $this->itemfeedback->setIdent($value);
321  break;
322  case "view":
323  $this->itemfeedback->setView($value);
324  break;
325  }
326  }
327  }
328  break;
329  case "displayfeedback":
330  include_once ("./Services/QTI/classes/class.ilQTIDisplayfeedback.php");
331  $this->displayfeedback = new ilQTIDisplayfeedback();
332  if (is_array($a_attribs))
333  {
334  foreach ($a_attribs as $attribute => $value)
335  {
336  switch (strtolower($attribute))
337  {
338  case "feedbacktype":
339  $this->displayfeedback->setFeedbacktype($value);
340  break;
341  case "linkrefid":
342  $this->displayfeedback->setLinkrefid($value);
343  break;
344  }
345  }
346  }
347  break;
348  case "setvar":
349  include_once ("./Services/QTI/classes/class.ilQTISetvar.php");
350  $this->setvar = new ilQTISetvar();
351  if (is_array($a_attribs))
352  {
353  foreach ($a_attribs as $attribute => $value)
354  {
355  switch (strtolower($attribute))
356  {
357  case "action":
358  $this->setvar->setAction($value);
359  break;
360  case "varname":
361  $this->setvar->setVarname($value);
362  break;
363  }
364  }
365  }
366  break;
367  case "conditionvar":
368  include_once ("./Services/QTI/classes/class.ilQTIConditionvar.php");
369  $this->conditionvar = new ilQTIConditionvar();
370  break;
371  case "not":
372  if ($this->conditionvar != NULL)
373  {
374  $this->conditionvar->addNot();
375  }
376  break;
377  case "and":
378  if ($this->conditionvar != NULL)
379  {
380  $this->conditionvar->addAnd();
381  }
382  break;
383  case "or":
384  if ($this->conditionvar != NULL)
385  {
386  $this->conditionvar->addOr();
387  }
388  break;
389  case "varequal":
390  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
391  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_EQUAL);
392  if (is_array($a_attribs))
393  {
394  foreach ($a_attribs as $attribute => $value)
395  {
396  switch (strtolower($attribute))
397  {
398  case "case":
399  $this->responsevar->setCase($value);
400  break;
401  case "respident":
402  $this->responsevar->setRespident($value);
403  break;
404  case "index":
405  $this->responsevar->setIndex($value);
406  break;
407  }
408  }
409  }
410  break;
411  case "varlt":
412  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
413  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_LT);
414  if (is_array($a_attribs))
415  {
416  foreach ($a_attribs as $attribute => $value)
417  {
418  switch (strtolower($attribute))
419  {
420  case "respident":
421  $this->responsevar->setRespident($value);
422  break;
423  case "index":
424  $this->responsevar->setIndex($value);
425  break;
426  }
427  }
428  }
429  break;
430  case "varlte":
431  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
432  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_LTE);
433  if (is_array($a_attribs))
434  {
435  foreach ($a_attribs as $attribute => $value)
436  {
437  switch (strtolower($attribute))
438  {
439  case "respident":
440  $this->responsevar->setRespident($value);
441  break;
442  case "index":
443  $this->responsevar->setIndex($value);
444  break;
445  }
446  }
447  }
448  break;
449  case "vargt":
450  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
451  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_GT);
452  if (is_array($a_attribs))
453  {
454  foreach ($a_attribs as $attribute => $value)
455  {
456  switch (strtolower($attribute))
457  {
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 "vargte":
469  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
470  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_GTE);
471  if (is_array($a_attribs))
472  {
473  foreach ($a_attribs as $attribute => $value)
474  {
475  switch (strtolower($attribute))
476  {
477  case "respident":
478  $this->responsevar->setRespident($value);
479  break;
480  case "index":
481  $this->responsevar->setIndex($value);
482  break;
483  }
484  }
485  }
486  break;
487  case "varsubset":
488  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
489  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_SUBSET);
490  if (is_array($a_attribs))
491  {
492  foreach ($a_attribs as $attribute => $value)
493  {
494  switch (strtolower($attribute))
495  {
496  case "respident":
497  $this->responsevar->setRespident($value);
498  break;
499  case "setmatch":
500  $this->responsevar->setSetmatch($value);
501  break;
502  case "index":
503  $this->responsevar->setIndex($value);
504  break;
505  }
506  }
507  }
508  break;
509  case "varinside":
510  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
511  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_INSIDE);
512  if (is_array($a_attribs))
513  {
514  foreach ($a_attribs as $attribute => $value)
515  {
516  switch (strtolower($attribute))
517  {
518  case "respident":
519  $this->responsevar->setRespident($value);
520  break;
521  case "areatype":
522  $this->responsevar->setAreatype($value);
523  break;
524  case "index":
525  $this->responsevar->setIndex($value);
526  break;
527  }
528  }
529  }
530  break;
531  case "varsubstring":
532  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
533  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_SUBSTRING);
534  if (is_array($a_attribs))
535  {
536  foreach ($a_attribs as $attribute => $value)
537  {
538  switch (strtolower($attribute))
539  {
540  case "case":
541  $this->responsevar->setCase($value);
542  break;
543  case "respident":
544  $this->responsevar->setRespident($value);
545  break;
546  case "index":
547  $this->responsevar->setIndex($value);
548  break;
549  }
550  }
551  }
552  break;
553  case "respcondition":
554  include_once("./Services/QTI/classes/class.ilQTIRespcondition.php");
555  $this->respcondition = new ilQTIRespcondition();
556  if (is_array($a_attribs))
557  {
558  foreach ($a_attribs as $attribute => $value)
559  {
560  switch (strtolower($attribute))
561  {
562  case "continue":
563  $this->respcondition->setContinue($value);
564  break;
565  case "title":
566  $this->respcondition->setTitle($value);
567  break;
568  }
569  }
570  }
571  break;
572  case "outcomes":
573  include_once("./Services/QTI/classes/class.ilQTIOutcomes.php");
574  $this->outcomes = new ilQTIOutcomes();
575  break;
576  case "decvar":
577  include_once("./Services/QTI/classes/class.ilQTIDecvar.php");
578  $this->decvar = new ilQTIDecvar();
579  if (is_array($a_attribs))
580  {
581  foreach ($a_attribs as $attribute => $value)
582  {
583  switch (strtolower($attribute))
584  {
585  case "varname":
586  $this->decvar->setVarname($value);
587  break;
588  case "vartype":
589  $this->decvar->setVartype($value);
590  break;
591  case "defaultval":
592  $this->decvar->setDefaultval($value);
593  break;
594  case "minvalue":
595  $this->decvar->setMinvalue($value);
596  break;
597  case "maxvalue":
598  $this->decvar->setMaxvalue($value);
599  break;
600  case "members":
601  $this->decvar->setMembers($value);
602  break;
603  case "cutvalue":
604  $this->decvar->setCutvalue($value);
605  break;
606  }
607  }
608  }
609  break;
610  case "matimage":
611  include_once("./Services/QTI/classes/class.ilQTIMatimage.php");
612  $this->matimage = new ilQTIMatimage();
613  if (is_array($a_attribs))
614  {
615  foreach ($a_attribs as $attribute => $value)
616  {
617  switch (strtolower($attribute))
618  {
619  case "imagtype":
620  $this->matimage->setImagetype($value);
621  break;
622  case "label":
623  $this->matimage->setLabel($value);
624  break;
625  case "height":
626  $this->matimage->setHeight($value);
627  break;
628  case "width":
629  $this->matimage->setWidth($value);
630  break;
631  case "uri":
632  $this->matimage->setUri($value);
633  break;
634  case "embedded":
635  $this->matimage->setEmbedded($value);
636  break;
637  case "x0":
638  $this->matimage->setX0($value);
639  break;
640  case "y0":
641  $this->matimage->setY0($value);
642  break;
643  case "entityref":
644  $this->matimage->setEntityref($value);
645  break;
646  }
647  }
648  }
649  break;
650  case "material":
651  include_once("./Services/QTI/classes/class.ilQTIMaterial.php");
652  $this->material = new ilQTIMaterial();
653  $this->material->setFlow($this->flow);
654  if (is_array($a_attribs))
655  {
656  foreach ($a_attribs as $attribute => $value)
657  {
658  switch (strtolower($attribute))
659  {
660  case "label":
661  $this->material->setLabel($value);
662  break;
663  }
664  }
665  }
666  break;
667  case "mattext":
668  include_once ("./Services/QTI/classes/class.ilQTIMattext.php");
669  $this->mattext = new ilQTIMattext();
670  if (is_array($a_attribs))
671  {
672  foreach ($a_attribs as $attribute => $value)
673  {
674  switch (strtolower($attribute))
675  {
676  case "texttype":
677  $this->mattext->setTexttype($value);
678  break;
679  case "label":
680  $this->mattext->setLabel($value);
681  break;
682  case "charset":
683  $this->mattext->setCharset($value);
684  break;
685  case "uri":
686  $this->mattext->setUri($value);
687  break;
688  case "xml:space":
689  $this->mattext->setXmlspace($value);
690  break;
691  case "xml:lang":
692  $this->mattext->setXmllang($value);
693  break;
694  case "entityref":
695  $this->mattext->setEntityref($value);
696  break;
697  case "height":
698  $this->mattext->setHeight($value);
699  break;
700  case "width":
701  $this->mattext->setWidth($value);
702  break;
703  case "x0":
704  $this->mattext->setX0($value);
705  break;
706  case "y0":
707  $this->mattext->setY0($value);
708  break;
709  }
710  }
711  }
712  break;
713  case "matapplet":
714  include_once ("./Services/QTI/classes/class.ilQTIMatapplet.php");
715  $this->matapplet = New ilQTIMatapplet();
716  if (is_array($a_attribs))
717  {
718  foreach ($a_attribs as $attribute => $value)
719  {
720  switch (strtolower($attribute))
721  {
722  case "label":
723  $this->matapplet->setLabel($value);
724  break;
725  case "uri":
726  $this->matapplet->setUri($value);
727  break;
728  case "y0":
729  $this->matapplet->setY0($value);
730  break;
731  case "height":
732  $this->matapplet->setHeight($value);
733  break;
734  case "width":
735  $this->matapplet->setWidth($value);
736  break;
737  case "x0":
738  $this->matapplet->setX0($value);
739  break;
740  case "embedded":
741  $this->matapplet->setEmbedded($value);
742  break;
743  case "entityref":
744  $this->matapplet->setEntityref($value);
745  break;
746  }
747  }
748  }
749  break;
750  case "questestinterop":
751  $this->hasRootElement = TRUE;
752  break;
753  case "qticomment":
754  break;
755  case "objectbank":
756  // not implemented yet
757  break;
758  case "section":
759  if ($this->assessment != NULL)
760  {
761  $this->assessment->addSection($this->section);
762  }
763  $this->section = NULL;
764  break;
765  case "presentation":
766  $this->in_presentation = TRUE;
767  include_once ("./Services/QTI/classes/class.ilQTIPresentation.php");
768  $this->presentation = new ilQTIPresentation();
769  break;
770  case "response_label":
771  if ($this->render_type != NULL)
772  {
773  include_once("./Services/QTI/classes/class.ilQTIResponseLabel.php");
774  $this->response_label = new ilQTIResponseLabel();
775  foreach ($a_attribs as $attribute => $value)
776  {
777  switch (strtolower($attribute))
778  {
779  case "rshuffle":
780  $this->response_label->setRshuffle($value);
781  break;
782  case "rarea":
783  $this->response_label->setRarea($value);
784  break;
785  case "rrange":
786  $this->response_label->setRrange($value);
787  break;
788  case "labelrefid":
789  $this->response_label->setLabelrefid($value);
790  break;
791  case "ident":
792  $this->response_label->setIdent($value);
793  break;
794  case "match_group":
795  $this->response_label->setMatchGroup($value);
796  break;
797  case "match_max":
798  $this->response_label->setMatchMax($value);
799  break;
800  }
801  }
802  }
803  break;
804  case "render_choice":
805  if ($this->in_response)
806  {
807  include_once("./Services/QTI/classes/class.ilQTIRenderChoice.php");
808  $this->render_type = new ilQTIRenderChoice();
809  foreach ($a_attribs as $attribute => $value)
810  {
811  switch (strtolower($attribute))
812  {
813  case "shuffle":
814  $this->render_type->setShuffle($value);
815  break;
816  }
817  }
818  }
819  break;
820  case "render_hotspot":
821  if ($this->in_response)
822  {
823  include_once("./Services/QTI/classes/class.ilQTIRenderHotspot.php");
824  $this->render_type = new ilQTIRenderHotspot();
825  foreach ($a_attribs as $attribute => $value)
826  {
827  switch (strtolower($attribute))
828  {
829  case "showdraw":
830  $this->render_type->setShuffle($value);
831  break;
832  case "minnumber":
833  $this->render_type->setMinnumber($value);
834  break;
835  case "maxnumber":
836  $this->render_type->setMaxnumber($value);
837  break;
838  }
839  }
840  }
841  break;
842  case "render_fib":
843  if ($this->in_response)
844  {
845  include_once("./Services/QTI/classes/class.ilQTIRenderFib.php");
846  $this->render_type = new ilQTIRenderFib();
847  foreach ($a_attribs as $attribute => $value)
848  {
849  switch (strtolower($attribute))
850  {
851  case "encoding":
852  $this->render_type->setEncoding($value);
853  break;
854  case "fibtype":
855  $this->render_type->setFibtype($value);
856  break;
857  case "rows":
858  $this->render_type->setRows($value);
859  break;
860  case "maxchars":
861  $this->render_type->setMaxchars($value);
862  break;
863  case "prompt":
864  $this->render_type->setPrompt($value);
865  break;
866  case "columns":
867  $this->render_type->setColumns($value);
868  break;
869  case "charset":
870  $this->render_type->setCharset($value);
871  break;
872  case "maxnumber":
873  $this->render_type->setMaxnumber($value);
874  break;
875  case "minnumber":
876  $this->render_type->setMinnumber($value);
877  break;
878  }
879  }
880  }
881  break;
882  case "response_lid":
883  // Ordering Terms and Definitions or
884  // Ordering Terms and Pictures or
885  // Multiple choice single response or
886  // Multiple choice multiple response
887  case "response_xy":
888  // Imagemap question
889  case "response_str":
890  // Close question
891  case "response_num":
892  case "response_grp":
893  // Matching terms and definitions
894  // Matching terms and images
895  include_once "./Services/QTI/classes/class.ilQTIResponse.php";
896  switch (strtolower($a_name))
897  {
898  case "response_lid":
899  $response_type = RT_RESPONSE_LID;
900  break;
901  case "response_xy":
902  $response_type = RT_RESPONSE_XY;
903  break;
904  case "response_str":
905  $response_type = RT_RESPONSE_STR;
906  break;
907  case "response_num":
908  $response_type = RT_RESPONSE_NUM;
909  break;
910  case "response_grp":
911  $response_type = RT_RESPONSE_GRP;
912  break;
913  }
914  $this->in_response = TRUE;
915  $this->response = new ilQTIResponse($response_type);
916  $this->response->setFlow($this->flow);
917  if (is_array($a_attribs))
918  {
919  foreach ($a_attribs as $attribute => $value)
920  {
921  switch (strtolower($attribute))
922  {
923  case "ident":
924  $this->response->setIdent($value);
925  break;
926  case "rtiming":
927  $this->response->setRTiming($value);
928  break;
929  case "rcardinality":
930  $this->response->setRCardinality($value);
931  break;
932  case "numtype":
933  $this->response->setNumtype($value);
934  break;
935  }
936  }
937  }
938  break;
939  case "item":
940  include_once("./Services/QTI/classes/class.ilQTIItem.php");
941  $this->gap_index = 0;
942  $this->item =& $this->items[array_push($this->items, new ilQTIItem())-1];
943  if (is_array($a_attribs))
944  {
945  foreach ($a_attribs as $attribute => $value)
946  {
947  switch (strtolower($attribute))
948  {
949  case "ident":
950  $this->item->setIdent($value);
951  if (count($this->import_idents) > 0)
952  {
953  if (!in_array($value, $this->import_idents))
954  {
955  $this->do_nothing = TRUE;
956  }
957  }
958  break;
959  case "title":
960  $this->item->setTitle($value);
961  break;
962  case "maxattempts":
963  $this->item->setMaxattempts($value);
964  break;
965  }
966  }
967  }
968  break;
969  case "resprocessing":
970  include_once("./Services/QTI/classes/class.ilQTIResprocessing.php");
971  $this->resprocessing = new ilQTIResprocessing();
972  if (is_array($a_attribs))
973  {
974  foreach ($a_attribs as $attribute => $value)
975  {
976  switch (strtolower($attribute))
977  {
978  case "scoremodel":
979  $this->resprocessing->setScoremodel($value);
980  break;
981  }
982  }
983  }
984  break;
985  }
986  }
987 
991  function handlerEndTag($a_xml_parser,$a_name)
992  {
993  switch ($this->parser_mode)
994  {
995  case IL_MO_PARSE_QTI:
996  $this->handlerParseEndTag($a_xml_parser, $a_name);
997  break;
998  case IL_MO_VERIFY_QTI:
999  $this->handlerVerifyEndTag($a_xml_parser, $a_name);
1000  break;
1001  }
1002  }
1003 
1007  function handlerParseEndTag($a_xml_parser,$a_name)
1008  {
1009  if (($this->do_nothing) && (strcmp(strtolower($a_name), "item") != 0)) return;
1010  switch (strtolower($a_name))
1011  {
1012  case "assessment":
1013  if (is_object($this->tst_object))
1014  {
1015  $this->tst_object->fromXML($this->assessment);
1016  }
1017  $this->in_assessment = FALSE;
1018  break;
1019  case "assessmentcontrol":
1020  $this->assessment->addAssessmentcontrol($this->assessmentcontrol);
1021  $this->assessmentcontrol = NULL;
1022  break;
1023  case "objectives":
1024  if (strcmp(strtolower($this->getParent($a_xml_parser)), "assessment") == 0)
1025  {
1026  $this->assessment->addObjectives($this->objectives);
1027  }
1028  $this->in_objectives = FALSE;
1029  break;
1030  case "itemmetadata":
1031  $this->in_itemmetadata = FALSE;
1032  break;
1033  case "qtimetadatafield":
1034  // handle only specific ILIAS metadata
1035  switch ($this->metadata["label"])
1036  {
1037  case "ILIAS_VERSION":
1038  break;
1039  case "QUESTIONTYPE":
1040  if ($this->item != NULL)
1041  {
1042  $this->item->setQuestiontype($this->metadata["entry"]);
1043  }
1044  break;
1045  case "AUTHOR":
1046  if ($this->item != NULL)
1047  {
1048  $this->item->setAuthor($this->metadata["entry"]);
1049  }
1050  default:
1051  if ($this->item != NULL)
1052  {
1053  $this->item->addMetadata($this->metadata);
1054  }
1055  break;
1056  }
1057  if ($this->in_assessment)
1058  {
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  {
1069  $flow_mat = array_pop($this->flow_mat);
1070  if (count($this->flow_mat))
1071  {
1072  $this->flow_mat[count($this->flow_mat)-1]->addFlow_mat($flow_mat);
1073  }
1074  else if ($this->itemfeedback != NULL)
1075  {
1076  $this->itemfeedback->addFlow_mat($flow_mat);
1077  }
1078  else if ($this->response_label != NULL)
1079  {
1080  $this->response_label->addFlow_mat($flow_mat);
1081  }
1082  else
1083  {
1084  //Idee: Nicht als Material sondern gleich als Objective -> Suche nach $this->material
1085 
1086  include_once("./Services/QTI/classes/class.ilQTIMaterial.php");
1087  $finalStatementMat = new ilQTIMaterial();
1088  $finalStatementMat->setFlow($flow_mat->material[0]->flow);
1089  $finalStatementMat->addMattext($flow_mat->material[0]->materials[0]['material']);
1090  $this->assessment->setPresentationMaterial($finalStatementMat);
1091  }
1092  }
1093  break;
1094  case "itemfeedback":
1095  if ($this->item != NULL)
1096  {
1097  if ($this->itemfeedback != NULL)
1098  {
1099  $this->item->addItemfeedback($this->itemfeedback);
1100  }
1101  }
1102  $this->itemfeedback = NULL;
1103  break;
1104  case "displayfeedback":
1105  if ($this->respcondition != NULL)
1106  {
1107  if ($this->displayfeedback != NULL)
1108  {
1109  $this->respcondition->addDisplayfeedback($this->displayfeedback);
1110  }
1111  }
1112  $this->displayfeedback = NULL;
1113  break;
1114  case "setvar":
1115  if ($this->respcondition != NULL)
1116  {
1117  if ($this->setvar != NULL)
1118  {
1119  $this->respcondition->addSetvar($this->setvar);
1120  }
1121  }
1122  $this->setvar = NULL;
1123  break;
1124  case "conditionvar":
1125  if ($this->respcondition != NULL)
1126  {
1127  $this->respcondition->setConditionvar($this->conditionvar);
1128  }
1129  $this->conditionvar = NULL;
1130  break;
1131  case "varequal":
1132  case "varlt":
1133  case "varlte":
1134  case "vargt":
1135  case "vargte":
1136  case "varsubset":
1137  case "varinside":
1138  case "varsubstring":
1139  if ($this->conditionvar != NULL)
1140  {
1141  if ($this->responsevar != NULL)
1142  {
1143  $this->conditionvar->addResponseVar($this->responsevar);
1144  }
1145  }
1146  $this->responsevar = NULL;
1147  break;
1148  case "respcondition":
1149  if ($this->resprocessing != NULL)
1150  {
1151  $this->resprocessing->addRespcondition($this->respcondition);
1152  }
1153  $this->respcondition = NULL;
1154  break;
1155  case "outcomes":
1156  if ($this->resprocessing != NULL)
1157  {
1158  $this->resprocessing->setOutcomes($this->outcomes);
1159  }
1160  $this->outcomes = NULL;
1161  break;
1162  case "decvar":
1163  if ($this->outcomes != NULL)
1164  {
1165  $this->outcomes->addDecvar($this->decvar);
1166  }
1167  $this->decvar = NULL;
1168  break;
1169  case "presentation":
1170  $this->in_presentation = FALSE;
1171  if ($this->presentation != NULL)
1172  {
1173  if ($this->item != NULL)
1174  {
1175  $this->item->setPresentation($this->presentation);
1176  }
1177  }
1178  $this->presentation = NULL;
1179  break;
1180  case "response_label":
1181  if ($this->render_type != NULL)
1182  {
1183  $this->render_type->addResponseLabel($this->response_label);
1184  $this->response_label = NULL;
1185  }
1186  break;
1187  case "render_choice":
1188  case "render_hotspot":
1189  case "render_fib":
1190  if ($this->in_response)
1191  {
1192  if ($this->response != NULL)
1193  {
1194  if ($this->render_type != NULL)
1195  {
1196  $this->response->setRenderType($this->render_type);
1197  $this->render_type = NULL;
1198  }
1199  }
1200  }
1201  break;
1202  case "response_lid":
1203  case "response_xy":
1204  case "response_str":
1205  case "response_num":
1206  case "response_grp":
1207  $this->gap_index++;
1208  if ($this->presentation != NULL)
1209  {
1210  if ($this->response != NULL)
1211  {
1212  $this->presentation->addResponse($this->response);
1213  if ($this->item != NULL)
1214  {
1215  $this->item->addPresentationitem($this->response);
1216  }
1217  }
1218  }
1219  $this->response = NULL;
1220  $this->in_response = FALSE;
1221  break;
1222  case "item":
1223  if ($this->do_nothing)
1224  {
1225  $this->do_nothing = FALSE;
1226  return;
1227  }
1228  if (strlen($this->item->getQuestionType()))
1229  {
1230  // this is an ILIAS QTI question
1231  }
1232  else
1233  {
1234  // this is a QTI question which wasn't generated by ILIAS
1235  }
1236  global $ilDB;
1237  global $ilUser;
1238  // save the item directly to save memory
1239  // the database id's of the created items are exported. if the import fails
1240  // ILIAS can delete the already imported items
1241 
1242  // problems: the object id of the parent questionpool is not yet known. must be set later
1243  // the complete flag must be calculated?
1244  $qt = $this->item->determineQuestionType();
1245  $presentation = $this->item->getPresentation();
1246 
1247  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1249  $question = new $qt();
1250  $question->fromXML($this->item, $this->qpl_id, $this->tst_id, $this->tst_object, $this->question_counter, $this->import_mapping);
1251  break;
1252  case "material":
1253  if ($this->material)
1254  {
1255  $mat = $this->material->getMaterial(0);
1256  if ((strcmp($mat["type"], "mattext") == 0) && (strcmp($mat["material"]->getLabel(), "suggested_solution") == 0))
1257  {
1258  $this->item->addSuggestedSolution($mat["material"], $this->gap_index);
1259  }
1260  if ($this->in_objectives)
1261  {
1262  $this->objectives->addMaterial($this->material);
1263  }
1264  else if (($this->render_type != NULL) && (strcmp(strtolower($this->getParent($a_xml_parser)), "render_hotspot") == 0))
1265  {
1266  $this->render_type->addMaterial($this->material);
1267  }
1268  else if (count($this->flow_mat) && (strcmp(strtolower($this->getParent($a_xml_parser)), "flow_mat") == 0))
1269  {
1270  $this->flow_mat[count($this->flow_mat)-1]->addMaterial($this->material);
1271  }
1272  else if ($this->itemfeedback != NULL)
1273  {
1274  $this->itemfeedback->addMaterial($this->material);
1275  }
1276  else if ($this->response_label != NULL)
1277  {
1278  $this->response_label->addMaterial($this->material);
1279  }
1280  else if ($this->response != NULL)
1281  {
1282  if ($this->response->hasRendering())
1283  {
1284  $this->response->setMaterial2($this->material);
1285  }
1286  else
1287  {
1288  $this->response->setMaterial1($this->material);
1289  }
1290  }
1291  elseif (($this->in_presentation) && (!$this->in_response))
1292  {
1293  if (!is_object($this->item->getQuestiontext()))
1294  {
1295  $this->item->setQuestiontext($this->material);
1296  }
1297  $this->presentation->addMaterial($this->material);
1298  }
1299  else if ($this->presentation != NULL)
1300  {
1301  $this->presentation->addMaterial($this->material);
1302  if ($this->item != NULL)
1303  {
1304  $this->item->addPresentationitem($this->material);
1305  }
1306  }
1307  }
1308  $this->material = NULL;
1309  break;
1310  case "matimage";
1311  if ($this->material != NULL)
1312  {
1313  if ($this->matimage != NULL)
1314  {
1315  $this->material->addMatimage($this->matimage);
1316  }
1317  }
1318  $this->matimage = NULL;
1319  break;
1320  case "resprocessing":
1321  if ($this->item != NULL)
1322  {
1323  $this->item->addResprocessing($this->resprocessing);
1324  }
1325  $this->resprocessing = NULL;
1326  break;
1327  case "mattext":
1328  if ($this->material != NULL)
1329  {
1330  $this->material->addMattext($this->mattext);
1331  }
1332  $this->mattext = NULL;
1333  break;
1334  case "matapplet":
1335  if ($this->material != NULL)
1336  {
1337  $this->material->addMatapplet($this->matapplet);
1338  }
1339  $this->matapplet = NULL;
1340  break;
1341  }
1342  $this->depth[$a_xml_parser]--;
1343  }
1344 
1348  function handlerCharacterData($a_xml_parser,$a_data)
1349  {
1350  switch ($this->parser_mode)
1351  {
1352  case IL_MO_PARSE_QTI:
1353  $this->handlerParseCharacterData($a_xml_parser, $a_data);
1354  break;
1355  case IL_MO_VERIFY_QTI:
1356  $this->handlerVerifyCharacterData($a_xml_parser, $a_data);
1357  break;
1358  }
1359  }
1360 
1364  function handlerParseCharacterData($a_xml_parser,$a_data)
1365  {
1366  if ($this->do_nothing) return;
1367  $this->characterbuffer .= $a_data;
1368  $a_data = $this->characterbuffer;
1369  switch ($this->qti_element)
1370  {
1371  case "fieldlabel":
1372  $this->metadata["label"] = $a_data;
1373  break;
1374  case "fieldentry":
1375  $this->metadata["entry"] = $a_data;
1376  break;
1377  case "response_label":
1378  if ($this->response_label != NULL)
1379  {
1380  $this->response_label->setContent($a_data);
1381  }
1382  break;
1383  case "setvar":
1384  if ($this->setvar != NULL)
1385  {
1386  $this->setvar->setContent($a_data);
1387  }
1388  break;
1389  case "displayfeedback":
1390  if ($this->displayfeedback != NULL)
1391  {
1392  $this->displayfeedback->setContent($a_data);
1393  }
1394  break;
1395  case "varequal":
1396  case "varlt":
1397  case "varlte":
1398  case "vargt":
1399  case "vargte":
1400  case "varsubset":
1401  case "varinside":
1402  case "varsubstring":
1403  if ($this->responsevar != NULL)
1404  {
1405  $this->responsevar->setContent($a_data);
1406  }
1407  break;
1408  case "decvar":
1409  if (strlen($a_data))
1410  {
1411  if ($this->decvar != NULL)
1412  {
1413  $this->decvar->setContent($a_data);
1414  }
1415  }
1416  break;
1417  case "mattext":
1418  if ($this->mattext != NULL)
1419  {
1420  $this->mattext->setContent($a_data);
1421  }
1422  break;
1423  case "matapplet":
1424  if ($this->matapplet != NULL)
1425  {
1426  $this->matapplet->setContent($a_data);
1427  }
1428  break;
1429  case "matimage":
1430  if ($this->matimage != NULL)
1431  {
1432  $this->matimage->setContent($a_data);
1433  }
1434  break;
1435  case "duration":
1436  switch ($this->getParent($a_xml_parser))
1437  {
1438  case "assessment":
1439  // to be done
1440  break;
1441  case "section":
1442  // to be done
1443  break;
1444  case "item":
1445  $this->item->setDuration($a_data);
1446  break;
1447  }
1448  break;
1449  case "qticomment":
1450  switch ($this->getParent($a_xml_parser))
1451  {
1452  case "item":
1453  $this->item->setComment($a_data);
1454  break;
1455  case "assessment":
1456  $this->assessment->setComment($a_data);
1457  break;
1458  default:
1459  break;
1460  }
1461  break;
1462  }
1463  $this->sametag = TRUE;
1464  }
1465 
1469  function handlerVerifyBeginTag($a_xml_parser,$a_name,$a_attribs)
1470  {
1471  switch (strtolower($a_name))
1472  {
1473  case "questestinterop":
1474  $this->verifyroot = true;
1475  break;
1476  case "qtimetadatafield":
1477  $this->verifymetadatafield = 1;
1478  break;
1479  case "fieldlabel":
1480  $this->verifyfieldlabeltext = "";
1481  if ($this->verifymetadatafield == 1) $this->verifyfieldlabel = 1;
1482  break;
1483  case "fieldentry":
1484  $this->verifyfieldentrytext = "";
1485  if ($this->verifymetadatafield == 1) $this->verifyfieldentry = 1;
1486  break;
1487  case "item":
1488  $title = "";
1489  if (is_array($a_attribs))
1490  {
1491  foreach ($a_attribs as $attribute => $value)
1492  {
1493  switch (strtolower($attribute))
1494  {
1495  case "title":
1496  $title = $value;
1497  break;
1498  }
1499  }
1500  }
1501  array_push($this->founditems, array("title" => "$title", "type" => "", "ident" => $a_attribs["ident"]));
1502  break;
1503  case "response_lid":
1504  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1505  {
1506  // test for non ILIAS generated question types
1507  if (is_array($a_attribs))
1508  {
1509  foreach ($a_attribs as $attribute => $value)
1510  {
1511  switch (strtolower($attribute))
1512  {
1513  case "rcardinality":
1514  include_once "./Services/QTI/classes/class.ilQTIItem.php";
1515  switch (strtolower($value))
1516  {
1517  case "single":
1518  $this->founditems[count($this->founditems)-1]["type"] = QT_MULTIPLE_CHOICE_SR;
1519  break;
1520  case "multiple":
1521  $this->founditems[count($this->founditems)-1]["type"] = QT_MULTIPLE_CHOICE_MR;
1522  break;
1523  case "ordered":
1524  $this->founditems[count($this->founditems)-1]["type"] = QT_ORDERING;
1525  break;
1526  }
1527  break;
1528  }
1529  }
1530  }
1531  }
1532  break;
1533  case "response_str":
1534  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1535  {
1536  // test for non ILIAS generated question types
1537  if (is_array($a_attribs))
1538  {
1539  foreach ($a_attribs as $attribute => $value)
1540  {
1541  switch (strtolower($attribute))
1542  {
1543  case "rcardinality":
1544  include_once "./Services/QTI/classes/class.ilQTIItem.php";
1545  switch (strtolower($value))
1546  {
1547  case "single":
1548  $this->founditems[count($this->founditems)-1]["type"] = QT_CLOZE;
1549  break;
1550  case "ordered":
1551  $this->founditems[count($this->founditems)-1]["type"] = QT_TEXT;
1552  break;
1553  }
1554  break;
1555  }
1556  }
1557  }
1558  }
1559  break;
1560  case "response_xy":
1561  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1562  {
1563  $this->founditems[count($this->founditems)-1]["type"] = QT_IMAGEMAP;
1564  }
1565  break;
1566  case "response_num":
1567  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1568  {
1569  $this->founditems[count($this->founditems)-1]["type"] = QT_NUMERIC;
1570  }
1571  break;
1572  case "response_grp":
1573  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1574  {
1575  $this->founditems[count($this->founditems)-1]["type"] = QT_MATCHING;
1576  }
1577  break;
1578  case "qticomment":
1579  // check for "old" ILIAS qti format (not well formed)
1580  $this->verifyqticomment = 1;
1581  break;
1582  case "presentation":
1583  if (is_array($a_attribs))
1584  {
1585  foreach ($a_attribs as $attribute => $value)
1586  {
1587  switch (strtolower($attribute))
1588  {
1589  case "label":
1590  $this->founditems[count($this->founditems)-1]["title"] = $value;
1591  break;
1592  }
1593  }
1594  }
1595  break;
1596  }
1597  }
1598 
1602  function handlerVerifyEndTag($a_xml_parser,$a_name)
1603  {
1604  switch (strtolower($a_name))
1605  {
1606  case "qticomment":
1607  // check for "old" ILIAS qti format (not well formed)
1608  $this->verifyqticomment = 0;
1609  break;
1610  case "qtimetadatafield":
1611  $this->verifymetadatafield = 0;
1612  if (strcmp($this->verifyfieldlabeltext, "QUESTIONTYPE") == 0)
1613  {
1614  $this->founditems[count($this->founditems)-1]["type"] = $this->verifyfieldentrytext;
1615  }
1616  break;
1617  case "fieldlabel":
1618  $this->verifyfieldlabel = 0;
1619  break;
1620  case "fieldentry":
1621  $this->verifyfieldentry = 0;
1622  break;
1623  }
1624  }
1625 
1629  function handlerVerifyCharacterData($a_xml_parser,$a_data)
1630  {
1631  if ($this->verifyqticomment == 1)
1632  {
1633  if (preg_match("/Questiontype\=(.*)/", $a_data, $matches))
1634  {
1635  if (count($this->founditems))
1636  {
1637  $this->founditems[count($this->founditems)-1]["type"] = $matches[1];
1638  }
1639  }
1640  }
1641  else if ($this->verifyfieldlabel == 1)
1642  {
1643  $this->verifyfieldlabeltext = $a_data;
1644  }
1645  else if ($this->verifyfieldentry == 1)
1646  {
1647  $this->verifyfieldentrytext = $a_data;
1648  }
1649  }
1650 
1651  function &getFoundItems()
1652  {
1653  return $this->founditems;
1654  }
1655 
1660  function getImportMapping()
1661  {
1662  if (!is_array($this->import_mapping))
1663  {
1664  return array();
1665  }
1666  else
1667  {
1668  return $this->import_mapping;
1669  }
1670  }
1671 
1672 }
1673 ?>