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