ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.SurveyImportParser.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2006 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 require_once("./classes/class.ilSaxParser.php");
25 
36 {
37  var $path;
38  var $depth;
40  var $spl;
46  var $size;
47  var $elements;
49  var $texts;
53  var $material;
54  var $metadata;
58  var $matrix;
64  var $survey;
76 
84  function SurveyImportParser(&$a_spl, $a_xml_file = '', $spl_exists = FALSE)
85  {
86  parent::ilSaxParser($a_xml_file);
87  $this->spl =& $a_spl;
88  $this->has_error = FALSE;
89  $this->characterbuffer = "";
90  $this->activetag = "";
91  $this->material = array();
92  $this->depth = array();
93  $this->path = array();
94  $this->metadata = array();
95  $this->responses = array();
96  $this->variables = array();
97  $this->response_id = "";
98  $this->matrix = array();
99  $this->is_matrix = FALSE;
100  $this->adjectives = array();
101  $this->spl_exists = $spl_exists;
102  $this->survey = NULL;
103  $this->in_survey = FALSE;
104  $this->anonymisation = 0;
105  $this->surveyaccess = "restricted";
106  $this->questions = array();
107  $this->original_question_id = "";
108  $this->constraints = array();
109  $this->textblock = "";
110  $this->textblocks = array();
111  $this->in_questionblock = FALSE;
112  $this->questionblocks = array();
113  $this->questionblock = array();
114  $this->showQuestiontext = 1;
115  $this->questionblocktitle = "";
116  }
117 
122  function setSurveyObject(&$a_svy)
123  {
124  $this->survey =& $a_svy;
125  }
126 
132  function setHandlers($a_xml_parser)
133  {
134  xml_set_object($a_xml_parser,$this);
135  xml_set_element_handler($a_xml_parser,'handlerBeginTag','handlerEndTag');
136  xml_set_character_data_handler($a_xml_parser,'handlerCharacterData');
137  }
138 
142  function startParsing()
143  {
145  }
146 
152  function parse($a_xml_parser,$a_fp = null)
153  {
154  switch($this->getInputType())
155  {
156  case 'file':
157 
158  while($data = fread($a_fp,4096))
159  {
160  $parseOk = xml_parse($a_xml_parser,$data,feof($a_fp));
161  }
162  break;
163 
164  case 'string':
165  $parseOk = xml_parse($a_xml_parser,$this->getXMLContent());
166  break;
167  }
168  if(!$parseOk
169  && (xml_get_error_code($a_xml_parser) != XML_ERROR_NONE))
170  {
171  $this->error_code = xml_get_error_code($a_xml_parser);
172  $this->error_line = xml_get_current_line_number($a_xml_parser);
173  $this->error_col = xml_get_current_column_number($a_xml_parser);
174  $this->error_msg = xml_error_string($a_xml_parser);
175  $this->has_error = TRUE;
176  return false;
177  }
178  return true;
179  }
180 
181  function getParent($a_xml_parser)
182  {
183  if ($this->depth[$a_xml_parser] > 0)
184  {
185  return $this->path[$this->depth[$a_xml_parser]-1];
186  }
187  else
188  {
189  return "";
190  }
191  }
192 
196  function handlerBeginTag($a_xml_parser, $a_name, $a_attribs)
197  {
198  $this->depth[$a_xml_parser]++;
199  $this->path[$this->depth[$a_xml_parser]] = strtolower($a_name);
200  $this->characterbuffer = "";
201  $this->activetag = $a_name;
202  $this->elements++;
203  $this->attributes+=count($a_attribs);
204  switch ($a_name)
205  {
206  case "questionblock":
207  $this->in_questionblock = TRUE;
208  $this->questionblock = array();
209  $this->questionblocktitle = "";
210  $this->showQuestiontext = 1;
211  foreach ($a_attribs as $attrib => $value)
212  {
213  switch ($attrib)
214  {
215  case "showQuestiontext":
216  $this->showQuestiontext = $value;
217  break;
218  }
219  }
220  break;
221  case "survey":
222  $this->in_survey = TRUE;
223  foreach ($a_attribs as $attrib => $value)
224  {
225  switch ($attrib)
226  {
227  case "title":
228  if (is_object($this->survey))
229  {
230  $this->survey->setTitle($value);
231  }
232  break;
233  }
234  }
235  break;
236  case "anonymisation":
237  foreach ($a_attribs as $attrib => $value)
238  {
239  switch ($attrib)
240  {
241  case "enabled":
242  $this->anonymisation = $value;
243  break;
244  }
245  }
246  break;
247  case "access":
248  foreach ($a_attribs as $attrib => $value)
249  {
250  switch ($attrib)
251  {
252  case "type":
253  $this->surveyaccess = $value;
254  break;
255  }
256  }
257  break;
258  case "constraint":
259  array_push($this->constraints,
260  array(
261  "sourceref" => $a_attribs["sourceref"],
262  "destref" => $a_attribs["destref"],
263  "relation" => $a_attribs["relation"],
264  "value" => $a_attribs["value"]
265  )
266  );
267  break;
268  case "question":
269  // start with a new survey question
270  $type = $a_attribs["type"];
271  // patch due to changes in question types
272  switch ($type)
273  {
274  case 'SurveyNominalQuestion':
275  $type = 'SurveyMultipleChoiceQuestion';
276  foreach ($a_attribs as $key => $value)
277  {
278  switch ($key)
279  {
280  case "subtype":
281  if ($value == 1)
282  {
283  $type = 'SurveySingleChoiceQuestion';
284  }
285  else
286  {
287  $type = 'SurveyMultipleChoiceQuestion';
288  }
289  break;
290  }
291  }
292  break;
293  case 'SurveyOrdinalQuestion':
294  $type = 'SurveySingleChoiceQuestion';
295  break;
296  }
297  if (strlen($type))
298  {
299  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
301  {
302  $this->activequestion = new $type();
303  $this->activequestion->setObjId($this->spl->getId());
304  }
305  }
306  else
307  {
308  $this->activequestion = NULL;
309  }
310  $this->original_question_id = $a_attribs["id"];
311  if ($this->in_questionblock)
312  {
313  array_push($this->questionblock, $this->original_question_id);
314  }
315  if (is_object($this->activequestion))
316  {
317  foreach ($a_attribs as $key => $value)
318  {
319  switch ($key)
320  {
321  case "title":
322  $this->activequestion->setTitle($value);
323  break;
324  case "subtype":
325  $this->activequestion->setSubtype($value);
326  break;
327  case "obligatory":
328  $this->activequestion->setObligatory($value);
329  break;
330  }
331  }
332  }
333  break;
334  case "material":
335  switch ($this->getParent($a_xml_parser))
336  {
337  case "question":
338  case "questiontext":
339  $this->material = array();
340  break;
341  }
342  array_push($this->material, array("text" => "", "image" => "", "label" => $a_attribs["label"]));
343  break;
344  case "matimage":
345  case "label":
346  if (array_key_exists("label", $a_attribs))
347  {
348  if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $a_attribs["label"], $matches))
349  {
350  // import an mediaobject which was inserted using tiny mce
351  if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
352  array_push($_SESSION["import_mob_xhtml"], array("mob" => $a_attribs["label"], "uri" => $a_attribs["uri"]));
353  }
354  }
355  break;
356  case "metadata":
357  $this->metadata = array();
358  break;
359  case "metadatafield":
360  array_push($this->metadata, array("label" => "", "entry" => ""));
361  break;
362  case "matrix":
363  $this->is_matrix = TRUE;
364  $this->matrix = array();
365  break;
366  case "matrixrow":
367  $this->material = array();
368  array_push($this->matrix, "");
369  $this->matrixrowattribs = array("id" => $a_attribs["id"], "label" => $a_attribs["label"], "other" => $a_attribs["other"]);
370  break;
371  case "responses":
372  $this->material = array();
373  $this->responses = array();
374  break;
375  case "variables":
376  $this->variables = array();
377  break;
378  case "response_single":
379  $this->material = array();
380  $this->responses[$a_attribs["id"]] = array("type" => "single", "id" => $a_attribs["id"], "label" => $a_attribs["label"], "other" => $a_attribs["other"], "neutral" => $a_attribs["neutral"], "scale" => $a_attribs["scale"]);
381  $this->response_id = $a_attribs["id"];
382  break;
383  case "response_multiple":
384  $this->material = array();
385  $this->responses[$a_attribs["id"]] = array("type" => "multiple", "id" => $a_attribs["id"], "label" => $a_attribs["label"], "other" => $a_attribs["other"], "neutral" => $a_attribs["neutral"], "scale" => $a_attribs["scale"]);
386  $this->response_id = $a_attribs["id"];
387  break;
388  case "response_text":
389  $this->material = array();
390  $this->responses[$a_attribs["id"]] = array("type" => "text", "id" => $a_attribs["id"], "columns" => $a_attribs["columns"], "maxlength" => $a_attribs["maxlength"], "rows" => $a_attribs["rows"], "label" => $a_attribs["label"]);
391  $this->response_id = $a_attribs["id"];
392  break;
393  case "response_num":
394  $this->material = array();
395  $this->responses[$a_attribs["id"]] = array("type" => "num", "id" => $a_attribs["id"], "format" => $a_attribs["format"], "max" => $a_attribs["max"], "min" => $a_attribs["min"], "size" => $a_attribs["size"], "label" => $a_attribs["label"]);
396  $this->response_id = $a_attribs["id"];
397  break;
398  case "response_time":
399  $this->material = array();
400  $this->responses[$a_attribs["id"]] = array("type" => "time", "id" => $a_attribs["id"], "format" => $a_attribs["format"], "max" => $a_attribs["max"], "min" => $a_attribs["min"], "label" => $a_attribs["label"]);
401  $this->response_id = $a_attribs["id"];
402  break;
403  case "bipolar_adjectives":
404  $this->adjectives = array();
405  break;
406  case "adjective":
407  array_push($this->adjectives, array("label" => $a_attribs["label"], "text" => ""));
408  break;
409  }
410  }
411 
415  function handlerCharacterData($a_xml_parser, $a_data)
416  {
417  $this->texts++;
418  $this->text_size+=strlen($a_data);
419  $this->characterbuffer .= $a_data;
420  $a_data = $this->characterbuffer;
421  }
422 
426  function handlerEndTag($a_xml_parser, $a_name)
427  {
428  switch ($a_name)
429  {
430  case "surveyobject":
431  if (is_object($this->survey))
432  {
433  // write constraints
434  if (count($this->constraints))
435  {
436  $relations = $this->survey->getAllRelations(TRUE);
437  foreach ($this->constraints as $constraint)
438  {
439  $constraint_id= $this->survey->addConstraint($this->questions[$constraint["destref"]], $relations[$constraint["relation"]]["id"], $constraint["value"], 0);
440  $this->survey->addConstraintToQuestion($this->questions[$constraint["sourceref"]], $constraint_id);
441  }
442  }
443  // write question blocks
444  if (count($this->questionblocks))
445  {
446  foreach ($this->questionblocks as $data)
447  {
448  $questionblock = $data["questions"];
449  $title = $data["title"];
450  $qblock = array();
451  foreach ($questionblock as $question_id)
452  {
453  array_push($qblock, $this->questions[$question_id]);
454  }
455  $this->survey->createQuestionblock($title, $this->showQuestiontext, $qblock);
456  }
457  }
458  $this->survey->saveToDb();
459 
460  // write textblocks
461  if (count($this->textblocks))
462  {
463  foreach ($this->textblocks as $original_id => $textblock)
464  {
465  $this->survey->saveHeading($textblock, $this->questions[$original_id]);
466  }
467  }
468  }
469  break;
470  case "survey":
471  $this->in_survey = FALSE;
472  if (is_object($this->survey))
473  {
474  if (strcmp($this->surveyaccess, "free") == 0)
475  {
476  $this->survey->setAnonymize(2);
477  }
478  else
479  {
480  if ($this->anonymisation == 0)
481  {
482  $this->survey->setAnonymize(0);
483  }
484  else
485  {
486  $this->survey->setAnonymize(1);
487  }
488  }
489  }
490  break;
491  case "startingtime":
492  if (preg_match("/(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2}).*/", $this->characterbuffer, $matches))
493  {
494  if (is_object($this->survey))
495  {
496  $this->survey->setStartDate(sprintf("%04d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
497  $this->survey->setStartDateEnabled(1);
498  }
499  }
500  break;
501  case "endingtime":
502  if (preg_match("/(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2}).*/", $this->characterbuffer, $matches))
503  {
504  if (is_object($this->survey))
505  {
506  $this->survey->setEndDate(sprintf("%04d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
507  $this->survey->setEndDateEnabled(1);
508  }
509  }
510  break;
511  case "description":
512  if ($this->in_survey)
513  {
514  if (is_object($this->survey))
515  {
516  $this->survey->setDescription($this->characterbuffer);
517  }
518  }
519  else
520  {
521  if (is_object($this->activequestion))
522  {
523  $this->activequestion->setDescription($this->characterbuffer);
524  }
525  }
526  break;
527  case "question":
528  if (is_object($this->activequestion))
529  {
530  if (strlen($this->textblock))
531  {
532  $this->textblocks[$this->original_question_id] = $this->textblock;
533  }
534  $this->activequestion->saveToDb();
535  if (is_object($this->survey))
536  {
537  // duplicate the question for the survey
538  $question_id = $this->activequestion->duplicate(TRUE);
539  $this->survey->addQuestion($question_id);
540  $this->questions[$this->original_question_id] = $question_id;
541  }
542  $this->activequestion = NULL;
543  }
544  $this->textblock = "";
545  break;
546  case "author":
547  if ($this->in_survey)
548  {
549  if (is_object($this->survey))
550  {
551  $this->survey->setAuthor($this->characterbuffer);
552  }
553  }
554  else
555  {
556  if (is_object($this->activequestion))
557  {
558  $this->activequestion->setAuthor($this->characterbuffer);
559  }
560  }
561  break;
562  case "mattext":
563  $this->material[count($this->material)-1]["text"] = $this->characterbuffer;
564  break;
565  case "matimage":
566  $this->material[count($this->material)-1]["image"] = $this->characterbuffer;
567  break;
568  case "material":
569  if ($this->in_survey)
570  {
571  if (strcmp($this->getParent($a_xml_parser), "objectives") == 0)
572  {
573  if (strcmp($this->material[0]["label"], "introduction") == 0)
574  {
575  if (is_object($this->survey))
576  {
577  $this->survey->setIntroduction($this->material[0]["text"]);
578  }
579  }
580  if (strcmp($this->material[0]["label"], "outro") == 0)
581  {
582  if (is_object($this->survey))
583  {
584  $this->survey->setOutro($this->material[0]["text"]);
585  }
586  }
587  $this->material = array();
588  }
589  }
590  else
591  {
592  if (strcmp($this->getParent($a_xml_parser), "question") == 0)
593  {
594  $this->activequestion->setMaterial($this->material[0]["text"], TRUE, $this->material[0]["label"]);
595  }
596  }
597  break;
598  case "questiontext":
599  if (is_object($this->activequestion))
600  {
601  $questiontext = "";
602  foreach ($this->material as $matarray)
603  {
604  $questiontext .= $matarray["text"];
605  }
606  $this->activequestion->setQuestiontext($questiontext);
607  }
608  $this->material = array();
609  break;
610  case "fieldlabel":
611  $this->metadata[count($this->metadata)-1]["label"] = $this->characterbuffer;
612  break;
613  case "fieldentry":
614  $this->metadata[count($this->metadata)-1]["entry"] = $this->characterbuffer;
615  break;
616  case "metadata":
617  if (strcmp($this->getParent($a_xml_parser), "question") == 0)
618  {
619  if (is_object($this->activequestion))
620  {
621  $this->activequestion->importAdditionalMetadata($this->metadata);
622  }
623  }
624  if (strcmp($this->getParent($a_xml_parser), "survey") == 0)
625  {
626  foreach ($this->metadata as $key => $value)
627  {
628  switch ($value["label"])
629  {
630  case "SCORM":
631  if (strlen($value["entry"]))
632  {
633  if (is_object($this->survey))
634  {
635  include_once "./Services/MetaData/classes/class.ilMDSaxParser.php";
636  include_once "./Services/MetaData/classes/class.ilMD.php";
637  $md_sax_parser = new ilMDSaxParser();
638  $md_sax_parser->setXMLContent($value["entry"]);
639  $md_sax_parser->setMDObject($tmp = new ilMD($this->survey->getId(),0, "svy"));
640  $md_sax_parser->enableMDParsing(true);
641  $md_sax_parser->startParsing();
642  $this->survey->MDUpdateListener("General");
643  }
644  }
645  break;
646  case "display_question_titles":
647  if ($value["entry"] == 1)
648  {
649  $this->survey->showQuestionTitles();
650  }
651  else
652  {
653  $this->survey->hideQuestionTitles();
654  }
655  break;
656  case "status":
657  $this->survey->setStatus($value["entry"]);
658  break;
659  case "evaluation_access":
660  $this->survey->setEvaluationAccess($value["entry"]);
661  break;
662  }
663  }
664  }
665  if (!$this->spl_exists)
666  {
667  if (strcmp($this->getParent($a_xml_parser), "surveyquestions") == 0)
668  {
669  foreach ($this->metadata as $key => $value)
670  {
671  if (strcmp($value["label"], "SCORM") == 0)
672  {
673  if (strlen($value["entry"]))
674  {
675  include_once "./Services/MetaData/classes/class.ilMDSaxParser.php";
676  include_once "./Services/MetaData/classes/class.ilMD.php";
677  $md_sax_parser = new ilMDSaxParser();
678  $md_sax_parser->setXMLContent($value["entry"]);
679  $md_sax_parser->setMDObject($tmp = new ilMD($this->spl->getId(),0, "spl"));
680  $md_sax_parser->enableMDParsing(true);
681  $md_sax_parser->startParsing();
682  $this->spl->MDUpdateListener("General");
683  }
684  }
685  }
686  }
687  }
688  break;
689  case "responses":
690  if (is_object($this->activequestion))
691  {
692  $this->activequestion->importResponses($this->responses);
693  }
694  $this->is_matrix = FALSE;
695  break;
696  case "variable":
697  array_push($this->variables, $this->characterbuffer);
698  break;
699  case "variables":
700  if (is_object($this->activequestion))
701  {
702  $this->activequestion->importVariables($this->variables);
703  }
704  break;
705  case "response_single":
706  case "response_multiple":
707  case "response_text":
708  case "response_num":
709  case "response_time":
710  $this->responses[$this->response_id]["material"] = $this->material;
711  break;
712  case "adjective":
713  $this->adjectives[count($this->adjectives)-1]["text"] = $this->characterbuffer;
714  break;
715  case "bipolar_adjectives":
716  if (is_object($this->activequestion))
717  {
718  $this->activequestion->importAdjectives($this->adjectives);
719  }
720  break;
721  case "matrixrow":
722  $row = "";
723  foreach ($this->material as $material)
724  {
725  $row .= $material["text"];
726  }
727  $this->matrix[count($this->matrix)-1] = array('title' => $row, 'id' => $this->matrixrowattribs['id'], 'label' => $this->matrixrowattribs['label'], 'other' => $this->matrixrowattribs['other']);
728  break;
729  case "matrix":
730  if (is_object($this->activequestion))
731  {
732  $this->activequestion->importMatrix($this->matrix);
733  }
734  break;
735  case "textblock":
736  $this->textblock = $this->characterbuffer;
737  break;
738  case "questionblocktitle":
739  $this->questionblocktitle = $this->characterbuffer;
740  break;
741  case "questionblock":
742  $this->in_questionblock = FALSE;
743  array_push($this->questionblocks, array("title" => $this->questionblocktitle, "questions" => $this->questionblock));
744  break;
745  }
746  $this->depth[$a_xml_parser]--;
747  }
748 
749  function getErrorCode()
750  {
751  return $this->error_code;
752  }
753 
754  function getErrorLine()
755  {
756  return $this->error_line;
757  }
758 
759  function getErrorColumn()
760  {
761  return $this->error_col;
762  }
763 
764  function getErrorMessage()
765  {
766  return $this->error_msg;
767  }
768 
769  function getFullError()
770  {
771  return "Error: ".$this->error_msg." at line:".$this->error_line ." column:".$this->error_col;
772  }
773 
774  function getXMLSize()
775  {
776  return $this->size;
777  }
778 
779  function getXMLElements()
780  {
781  return $this->elements;
782  }
783 
784  function getXMLAttributes()
785  {
786  return $this->attributes;
787  }
788 
789  function getXMLTextSections()
790  {
791  return $this->texts;
792  }
793 
794  function getXMLTextSize()
795  {
796  return $this->text_size;
797  }
798 
799  function hasError()
800  {
801  return $this->has_error;
802  }
803 }
804 ?>