ILIAS  Release_4_0_x_branch Revision 61816
 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  }
963  }
964  }
965  break;
966  case "resprocessing":
967  include_once("./Services/QTI/classes/class.ilQTIResprocessing.php");
968  $this->resprocessing = new ilQTIResprocessing();
969  if (is_array($a_attribs))
970  {
971  foreach ($a_attribs as $attribute => $value)
972  {
973  switch (strtolower($attribute))
974  {
975  case "scoremodel":
976  $this->resprocessing->setScoremodel($value);
977  break;
978  }
979  }
980  }
981  break;
982  }
983  }
984 
988  function handlerEndTag($a_xml_parser,$a_name)
989  {
990  switch ($this->parser_mode)
991  {
992  case IL_MO_PARSE_QTI:
993  $this->handlerParseEndTag($a_xml_parser, $a_name);
994  break;
995  case IL_MO_VERIFY_QTI:
996  $this->handlerVerifyEndTag($a_xml_parser, $a_name);
997  break;
998  }
999  }
1000 
1004  function handlerParseEndTag($a_xml_parser,$a_name)
1005  {
1006  if (($this->do_nothing) && (strcmp(strtolower($a_name), "item") != 0)) return;
1007  switch (strtolower($a_name))
1008  {
1009  case "assessment":
1010  if (is_object($this->tst_object))
1011  {
1012  $this->tst_object->fromXML($this->assessment);
1013  }
1014  $this->in_assessment = FALSE;
1015  break;
1016  case "assessmentcontrol":
1017  $this->assessment->addAssessmentcontrol($this->assessmentcontrol);
1018  $this->assessmentcontrol = NULL;
1019  break;
1020  case "objectives":
1021  if (strcmp(strtolower($this->getParent($a_xml_parser)), "assessment") == 0)
1022  {
1023  $this->assessment->addObjectives($this->objectives);
1024  }
1025  $this->in_objectives = FALSE;
1026  break;
1027  case "itemmetadata":
1028  $this->in_itemmetadata = FALSE;
1029  break;
1030  case "qtimetadatafield":
1031  // handle only specific ILIAS metadata
1032  switch ($this->metadata["label"])
1033  {
1034  case "ILIAS_VERSION":
1035  break;
1036  case "QUESTIONTYPE":
1037  if ($this->item != NULL)
1038  {
1039  $this->item->setQuestiontype($this->metadata["entry"]);
1040  }
1041  break;
1042  case "AUTHOR":
1043  if ($this->item != NULL)
1044  {
1045  $this->item->setAuthor($this->metadata["entry"]);
1046  }
1047  default:
1048  if ($this->item != NULL)
1049  {
1050  $this->item->addMetadata($this->metadata);
1051  }
1052  break;
1053  }
1054  if ($this->in_assessment)
1055  {
1056  $this->assessment->addQtiMetadata($this->metadata);
1057  }
1058  $this->metadata = array("label" => "", "entry" => "");
1059  break;
1060  case "flow":
1061  $this->flow--;
1062  break;
1063  case "flow_mat":
1064  if (count($this->flow_mat))
1065  {
1066  $flow_mat = array_pop($this->flow_mat);
1067  if (count($this->flow_mat))
1068  {
1069  $this->flow_mat[count($this->flow_mat)-1]->addFlow_mat($flow_mat);
1070  }
1071  else if ($this->itemfeedback != NULL)
1072  {
1073  $this->itemfeedback->addFlow_mat($flow_mat);
1074  }
1075  else if ($this->response_label != NULL)
1076  {
1077  $this->response_label->addFlow_mat($flow_mat);
1078  }
1079  }
1080  break;
1081  case "itemfeedback":
1082  if ($this->item != NULL)
1083  {
1084  if ($this->itemfeedback != NULL)
1085  {
1086  $this->item->addItemfeedback($this->itemfeedback);
1087  }
1088  }
1089  $this->itemfeedback = NULL;
1090  break;
1091  case "displayfeedback":
1092  if ($this->respcondition != NULL)
1093  {
1094  if ($this->displayfeedback != NULL)
1095  {
1096  $this->respcondition->addDisplayfeedback($this->displayfeedback);
1097  }
1098  }
1099  $this->displayfeedback = NULL;
1100  break;
1101  case "setvar":
1102  if ($this->respcondition != NULL)
1103  {
1104  if ($this->setvar != NULL)
1105  {
1106  $this->respcondition->addSetvar($this->setvar);
1107  }
1108  }
1109  $this->setvar = NULL;
1110  break;
1111  case "conditionvar":
1112  if ($this->respcondition != NULL)
1113  {
1114  $this->respcondition->setConditionvar($this->conditionvar);
1115  }
1116  $this->conditionvar = NULL;
1117  break;
1118  case "varequal":
1119  case "varlt":
1120  case "varlte":
1121  case "vargt":
1122  case "vargte":
1123  case "varsubset":
1124  case "varinside":
1125  case "varsubstring":
1126  if ($this->conditionvar != NULL)
1127  {
1128  if ($this->responsevar != NULL)
1129  {
1130  $this->conditionvar->addResponseVar($this->responsevar);
1131  }
1132  }
1133  $this->responsevar = NULL;
1134  break;
1135  case "respcondition":
1136  if ($this->resprocessing != NULL)
1137  {
1138  $this->resprocessing->addRespcondition($this->respcondition);
1139  }
1140  $this->respcondition = NULL;
1141  break;
1142  case "outcomes":
1143  if ($this->resprocessing != NULL)
1144  {
1145  $this->resprocessing->setOutcomes($this->outcomes);
1146  }
1147  $this->outcomes = NULL;
1148  break;
1149  case "decvar":
1150  if ($this->outcomes != NULL)
1151  {
1152  $this->outcomes->addDecvar($this->decvar);
1153  }
1154  $this->decvar = NULL;
1155  break;
1156  case "presentation":
1157  $this->in_presentation = FALSE;
1158  if ($this->presentation != NULL)
1159  {
1160  if ($this->item != NULL)
1161  {
1162  $this->item->setPresentation($this->presentation);
1163  }
1164  }
1165  $this->presentation = NULL;
1166  break;
1167  case "response_label":
1168  if ($this->render_type != NULL)
1169  {
1170  $this->render_type->addResponseLabel($this->response_label);
1171  $this->response_label = NULL;
1172  }
1173  break;
1174  case "render_choice":
1175  case "render_hotspot":
1176  case "render_fib":
1177  if ($this->in_response)
1178  {
1179  if ($this->response != NULL)
1180  {
1181  if ($this->render_type != NULL)
1182  {
1183  $this->response->setRenderType($this->render_type);
1184  $this->render_type = NULL;
1185  }
1186  }
1187  }
1188  break;
1189  case "response_lid":
1190  case "response_xy":
1191  case "response_str":
1192  case "response_num":
1193  case "response_grp":
1194  $this->gap_index++;
1195  if ($this->presentation != NULL)
1196  {
1197  if ($this->response != NULL)
1198  {
1199  $this->presentation->addResponse($this->response);
1200  if ($this->item != NULL)
1201  {
1202  $this->item->addPresentationitem($this->response);
1203  }
1204  }
1205  }
1206  $this->response = NULL;
1207  $this->in_response = FALSE;
1208  break;
1209  case "item":
1210  if ($this->do_nothing)
1211  {
1212  $this->do_nothing = FALSE;
1213  return;
1214  }
1215  if (strlen($this->item->getQuestionType()))
1216  {
1217  // this is an ILIAS QTI question
1218  }
1219  else
1220  {
1221  // this is a QTI question which wasn't generated by ILIAS
1222  }
1223  global $ilDB;
1224  global $ilUser;
1225  // save the item directly to save memory
1226  // the database id's of the created items are exported. if the import fails
1227  // ILIAS can delete the already imported items
1228 
1229  // problems: the object id of the parent questionpool is not yet known. must be set later
1230  // the complete flag must be calculated?
1231  $qt = $this->item->determineQuestionType();
1232  $presentation = $this->item->getPresentation();
1233 
1234  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1236  $question = new $qt();
1237  $question->fromXML($this->item, $this->qpl_id, $this->tst_id, $this->tst_object, $this->question_counter, $this->import_mapping);
1238  break;
1239  case "material":
1240  if ($this->material)
1241  {
1242  $mat = $this->material->getMaterial(0);
1243  if ((strcmp($mat["type"], "mattext") == 0) && (strcmp($mat["material"]->getLabel(), "suggested_solution") == 0))
1244  {
1245  $this->item->addSuggestedSolution($mat["material"], $this->gap_index);
1246  }
1247  if ($this->in_objectives)
1248  {
1249  $this->objectives->addMaterial($this->material);
1250  }
1251  else if (($this->render_type != NULL) && (strcmp(strtolower($this->getParent($a_xml_parser)), "render_hotspot") == 0))
1252  {
1253  $this->render_type->addMaterial($this->material);
1254  }
1255  else if (count($this->flow_mat) && (strcmp(strtolower($this->getParent($a_xml_parser)), "flow_mat") == 0))
1256  {
1257  $this->flow_mat[count($this->flow_mat)-1]->addMaterial($this->material);
1258  }
1259  else if ($this->itemfeedback != NULL)
1260  {
1261  $this->itemfeedback->addMaterial($this->material);
1262  }
1263  else if ($this->response_label != NULL)
1264  {
1265  $this->response_label->addMaterial($this->material);
1266  }
1267  else if ($this->response != NULL)
1268  {
1269  if ($this->response->hasRendering())
1270  {
1271  $this->response->setMaterial2($this->material);
1272  }
1273  else
1274  {
1275  $this->response->setMaterial1($this->material);
1276  }
1277  }
1278  elseif (($this->in_presentation) && (!$this->in_response))
1279  {
1280  if (!is_object($this->item->getQuestiontext()))
1281  {
1282  $this->item->setQuestiontext($this->material);
1283  }
1284  $this->presentation->addMaterial($this->material);
1285  }
1286  else if ($this->presentation != NULL)
1287  {
1288  $this->presentation->addMaterial($this->material);
1289  if ($this->item != NULL)
1290  {
1291  $this->item->addPresentationitem($this->material);
1292  }
1293  }
1294  }
1295  $this->material = NULL;
1296  break;
1297  case "matimage";
1298  if ($this->material != NULL)
1299  {
1300  if ($this->matimage != NULL)
1301  {
1302  $this->material->addMatimage($this->matimage);
1303  }
1304  }
1305  $this->matimage = NULL;
1306  break;
1307  case "resprocessing":
1308  if ($this->item != NULL)
1309  {
1310  $this->item->addResprocessing($this->resprocessing);
1311  }
1312  $this->resprocessing = NULL;
1313  break;
1314  case "mattext":
1315  if ($this->material != NULL)
1316  {
1317  $this->material->addMattext($this->mattext);
1318  }
1319  $this->mattext = NULL;
1320  break;
1321  case "matapplet":
1322  if ($this->material != NULL)
1323  {
1324  $this->material->addMatapplet($this->matapplet);
1325  }
1326  $this->matapplet = NULL;
1327  break;
1328  }
1329  $this->depth[$a_xml_parser]--;
1330  }
1331 
1335  function handlerCharacterData($a_xml_parser,$a_data)
1336  {
1337  switch ($this->parser_mode)
1338  {
1339  case IL_MO_PARSE_QTI:
1340  $this->handlerParseCharacterData($a_xml_parser, $a_data);
1341  break;
1342  case IL_MO_VERIFY_QTI:
1343  $this->handlerVerifyCharacterData($a_xml_parser, $a_data);
1344  break;
1345  }
1346  }
1347 
1351  function handlerParseCharacterData($a_xml_parser,$a_data)
1352  {
1353  if ($this->do_nothing) return;
1354  $this->characterbuffer .= $a_data;
1355  $a_data = $this->characterbuffer;
1356  switch ($this->qti_element)
1357  {
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  {
1367  $this->response_label->setContent($a_data);
1368  }
1369  break;
1370  case "setvar":
1371  if ($this->setvar != NULL)
1372  {
1373  $this->setvar->setContent($a_data);
1374  }
1375  break;
1376  case "displayfeedback":
1377  if ($this->displayfeedback != NULL)
1378  {
1379  $this->displayfeedback->setContent($a_data);
1380  }
1381  break;
1382  case "varequal":
1383  case "varlt":
1384  case "varlte":
1385  case "vargt":
1386  case "vargte":
1387  case "varsubset":
1388  case "varinside":
1389  case "varsubstring":
1390  if ($this->responsevar != NULL)
1391  {
1392  $this->responsevar->setContent($a_data);
1393  }
1394  break;
1395  case "decvar":
1396  if (strlen($a_data))
1397  {
1398  if ($this->decvar != NULL)
1399  {
1400  $this->decvar->setContent($a_data);
1401  }
1402  }
1403  break;
1404  case "mattext":
1405  if ($this->mattext != NULL)
1406  {
1407  $this->mattext->setContent($a_data);
1408  }
1409  break;
1410  case "matapplet":
1411  if ($this->matapplet != NULL)
1412  {
1413  $this->matapplet->setContent($a_data);
1414  }
1415  break;
1416  case "matimage":
1417  if ($this->matimage != NULL)
1418  {
1419  $this->matimage->setContent($a_data);
1420  }
1421  break;
1422  case "duration":
1423  switch ($this->getParent($a_xml_parser))
1424  {
1425  case "assessment":
1426  // to be done
1427  break;
1428  case "section":
1429  // to be done
1430  break;
1431  case "item":
1432  $this->item->setDuration($a_data);
1433  break;
1434  }
1435  break;
1436  case "qticomment":
1437  switch ($this->getParent($a_xml_parser))
1438  {
1439  case "item":
1440  $this->item->setComment($a_data);
1441  break;
1442  case "assessment":
1443  $this->assessment->setComment($a_data);
1444  break;
1445  default:
1446  break;
1447  }
1448  break;
1449  }
1450  $this->sametag = TRUE;
1451  }
1452 
1456  function handlerVerifyBeginTag($a_xml_parser,$a_name,$a_attribs)
1457  {
1458  switch (strtolower($a_name))
1459  {
1460  case "questestinterop":
1461  $this->verifyroot = true;
1462  break;
1463  case "qtimetadatafield":
1464  $this->verifymetadatafield = 1;
1465  break;
1466  case "fieldlabel":
1467  $this->verifyfieldlabeltext = "";
1468  if ($this->verifymetadatafield == 1) $this->verifyfieldlabel = 1;
1469  break;
1470  case "fieldentry":
1471  $this->verifyfieldentrytext = "";
1472  if ($this->verifymetadatafield == 1) $this->verifyfieldentry = 1;
1473  break;
1474  case "item":
1475  $title = "";
1476  if (is_array($a_attribs))
1477  {
1478  foreach ($a_attribs as $attribute => $value)
1479  {
1480  switch (strtolower($attribute))
1481  {
1482  case "title":
1483  $title = $value;
1484  break;
1485  }
1486  }
1487  }
1488  array_push($this->founditems, array("title" => "$title", "type" => "", "ident" => $a_attribs["ident"]));
1489  break;
1490  case "response_lid":
1491  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1492  {
1493  // test for non ILIAS generated question types
1494  if (is_array($a_attribs))
1495  {
1496  foreach ($a_attribs as $attribute => $value)
1497  {
1498  switch (strtolower($attribute))
1499  {
1500  case "rcardinality":
1501  include_once "./Services/QTI/classes/class.ilQTIItem.php";
1502  switch (strtolower($value))
1503  {
1504  case "single":
1505  $this->founditems[count($this->founditems)-1]["type"] = QT_MULTIPLE_CHOICE_SR;
1506  break;
1507  case "multiple":
1508  $this->founditems[count($this->founditems)-1]["type"] = QT_MULTIPLE_CHOICE_MR;
1509  break;
1510  case "ordered":
1511  $this->founditems[count($this->founditems)-1]["type"] = QT_ORDERING;
1512  break;
1513  }
1514  break;
1515  }
1516  }
1517  }
1518  }
1519  break;
1520  case "response_str":
1521  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1522  {
1523  // test for non ILIAS generated question types
1524  if (is_array($a_attribs))
1525  {
1526  foreach ($a_attribs as $attribute => $value)
1527  {
1528  switch (strtolower($attribute))
1529  {
1530  case "rcardinality":
1531  include_once "./Services/QTI/classes/class.ilQTIItem.php";
1532  switch (strtolower($value))
1533  {
1534  case "single":
1535  $this->founditems[count($this->founditems)-1]["type"] = QT_CLOZE;
1536  break;
1537  case "ordered":
1538  $this->founditems[count($this->founditems)-1]["type"] = QT_TEXT;
1539  break;
1540  }
1541  break;
1542  }
1543  }
1544  }
1545  }
1546  break;
1547  case "response_xy":
1548  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1549  {
1550  $this->founditems[count($this->founditems)-1]["type"] = QT_IMAGEMAP;
1551  }
1552  break;
1553  case "response_num":
1554  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1555  {
1556  $this->founditems[count($this->founditems)-1]["type"] = QT_NUMERIC;
1557  }
1558  break;
1559  case "response_grp":
1560  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1561  {
1562  $this->founditems[count($this->founditems)-1]["type"] = QT_MATCHING;
1563  }
1564  break;
1565  case "qticomment":
1566  // check for "old" ILIAS qti format (not well formed)
1567  $this->verifyqticomment = 1;
1568  break;
1569  case "presentation":
1570  if (is_array($a_attribs))
1571  {
1572  foreach ($a_attribs as $attribute => $value)
1573  {
1574  switch (strtolower($attribute))
1575  {
1576  case "label":
1577  $this->founditems[count($this->founditems)-1]["title"] = $value;
1578  break;
1579  }
1580  }
1581  }
1582  break;
1583  }
1584  }
1585 
1589  function handlerVerifyEndTag($a_xml_parser,$a_name)
1590  {
1591  switch (strtolower($a_name))
1592  {
1593  case "qticomment":
1594  // check for "old" ILIAS qti format (not well formed)
1595  $this->verifyqticomment = 0;
1596  break;
1597  case "qtimetadatafield":
1598  $this->verifymetadatafield = 0;
1599  if (strcmp($this->verifyfieldlabeltext, "QUESTIONTYPE") == 0)
1600  {
1601  $this->founditems[count($this->founditems)-1]["type"] = $this->verifyfieldentrytext;
1602  }
1603  break;
1604  case "fieldlabel":
1605  $this->verifyfieldlabel = 0;
1606  break;
1607  case "fieldentry":
1608  $this->verifyfieldentry = 0;
1609  break;
1610  }
1611  }
1612 
1616  function handlerVerifyCharacterData($a_xml_parser,$a_data)
1617  {
1618  if ($this->verifyqticomment == 1)
1619  {
1620  if (preg_match("/Questiontype\=(.*)/", $a_data, $matches))
1621  {
1622  if (count($this->founditems))
1623  {
1624  $this->founditems[count($this->founditems)-1]["type"] = $matches[1];
1625  }
1626  }
1627  }
1628  else if ($this->verifyfieldlabel == 1)
1629  {
1630  $this->verifyfieldlabeltext = $a_data;
1631  }
1632  else if ($this->verifyfieldentry == 1)
1633  {
1634  $this->verifyfieldentrytext = $a_data;
1635  }
1636  }
1637 
1638  function &getFoundItems()
1639  {
1640  return $this->founditems;
1641  }
1642 
1647  function getImportMapping()
1648  {
1649  if (!is_array($this->import_mapping))
1650  {
1651  return array();
1652  }
1653  else
1654  {
1655  return $this->import_mapping;
1656  }
1657  }
1658 
1659 }
1660 ?>