1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4
5/**
6* Content Object Parser
7*
8* @author Alex Killing <alex.killing@gmx.de>
9* @version $Id$
10*
11* @ingroup ModulesIliasLearningModule
12*/
13class ilContObjParser extends ilMDSaxParser
14{
15    public $lng;
16    public $tree;
17    public $cnt;				// counts open elements
18    public $current_element;	// store current element type
19    public $learning_module;	// current learning module
20    public $page_object;		// current page object
21    public $lm_page_object;
22    public $structure_objects;	// array of current structure objects
23    public $media_object;
24    public $current_object;	// at the time a LearningModule, PageObject or StructureObject
25    public $meta_data;			// current meta data object
26    public $paragraph;
27    public $table;
28    public $lm_tree;
29    public $pg_into_tree;
30    public $st_into_tree;
31    public $container = [];
32    public $in_page_object;	// are we currently within a PageObject? true/false
33    public $in_meta_data;		// are we currently within MetaData? true/false
34    public $in_media_object;
35    public $in_file_item;
36    public $in_glossary;
37    public $in_map_area;
38    public $content_object;
39    public $glossary_object;
40    public $file_item;
41    public $keyword_language;
42    public $pages_to_parse;
43    public $mob_mapping;
44    public $file_item_mapping;
45    public $subdir;
46    public $media_item;		// current media item
47    public $loc_type;			// current location type
48    public $map_area;			// current map area
49    public $link_targets;		// stores all objects by import id
50    public $qst_mapping;
51    public $metadata_parsing_disabled;
52    public $in_meta_meta_data = false;
53    protected $glossary_term_map = array();
54
55    /**
56     * @var ilLogger
57     */
58    protected $log;
59
60    /**
61    * Constructor
62    *
63    * @param	object		$a_content_object	must be of type ilObjContentObject
64    *											ilObjTest or ilObjQuestionPool
65    * @param	string		$a_xml_file			xml file
66    * @param	string		$a_subdir			subdirectory in import directory
67    * @access	public
68    */
69    public function __construct(&$a_content_object, $a_xml_file, $a_subdir, $a_import_dir = "")
70    {
71        global $DIC;
72
73        $this->log = $DIC["ilLog"];
74        $lng = $DIC->language();
75        $tree = $DIC->repositoryTree();
76
77        $this->log = ilLoggerFactory::getLogger('lm');
78
79        $this->import_dir = ($a_import_dir != "")
80            ? $a_import_dir
81            : $a_content_object->getImportDirectory();
82
83        parent::__construct($a_xml_file);
84        $this->cnt = array();
85        $this->current_element = array();
86        $this->structure_objects = array();
87        $this->content_object = $a_content_object;
88        //$this->lm_id = $a_lm_id;
89        $this->st_into_tree = array();
90        $this->pg_into_tree = array();
91        $this->pages_to_parse = array();
92        $this->mobs_with_int_links = array();
93        $this->mob_mapping = array();
94        $this->file_item_mapping = array();
95        $this->pg_mapping = array();
96        $this->link_targets = array();
97        $this->subdir = $a_subdir;
98        $this->lng = $lng;
99        $this->tree = $tree;
100        $this->inside_code = false;
101        $this->qst_mapping = array();
102        $this->coType = $this->content_object->getType();
103        $this->metadata_parsing_disabled = false;
104
105        if (($this->coType != "tst") and ($this->coType != "qpl")) {
106            $this->lm_tree = new ilTree($this->content_object->getId());
107            $this->lm_tree->setTreeTablePK("lm_id");
108            $this->lm_tree->setTableNames('lm_tree', 'lm_data');
109        }
110        //$this->lm_tree->addTree($a_lm_id, 1); happens in ilObjLearningModuleGUI
111    }
112
113    /**
114    * set event handlers
115    *
116    * @param	resource	reference to the xml parser
117    * @access	private
118    */
119    public function setHandlers($a_xml_parser)
120    {
121        xml_set_object($a_xml_parser, $this);
122        xml_set_element_handler($a_xml_parser, 'handlerBeginTag', 'handlerEndTag');
123        xml_set_character_data_handler($a_xml_parser, 'handlerCharacterData');
124    }
125
126    /**
127     * Set import mapping
128     * @param ilImportMapping $mapping
129     */
130    public function setImportMapping(ilImportMapping $mapping = null)
131    {
132        $this->mapping = $mapping;
133    }
134
135
136    /**
137    * start parser
138    */
139    public function startParsing()
140    {
141        $this->log->debug("start");
142
143        //echo "<b>start parsing</b><br>";
144        parent::startParsing();
145        //echo "<b>storeTree</b><br>";
146        $this->storeTree();
147        //echo "<b>processPagesToParse</b><br>";
148        $this->processPagesToParse();
149        //echo "<b>copyMobFiles</b><br>";
150        $this->copyMobFiles();
151        //echo "<b>copyFileItems</b><br>";
152        $this->copyFileItems();
153        //echo "<br>END Parsing"; exit;
154    }
155
156
157    /**
158    * insert StructureObjects and PageObjects into tree
159    */
160    public function storeTree()
161    {
162        $ilLog = $this->log;
163
164        //echo "<b>Storing the tree</b><br>";
165        foreach ($this->st_into_tree as $st) {
166            //echo "insert st id: ".$st["id"].", parent:".$st["parent"]."<br>";
167            $this->lm_tree->insertNode($st["id"], $st["parent"]);
168            //echo "done<br>";
169            //var_dump($this->pg_into_tree[$st["id"]]);
170            //echo "<br>";
171            if (is_array($this->pg_into_tree[$st["id"]])) {
172                foreach ($this->pg_into_tree[$st["id"]] as $pg) {
173                    switch ($pg["type"]) {
174                        case "pg_alias":
175                            if ($this->pg_mapping[$pg["id"]] == "") {
176                                $ilLog->write("LM Import: No PageObject for PageAlias " .
177                                              $pg["id"] . " found! (Please update export installation to ILIAS 3.3.0)");
178
179                                // Jump two levels up. First level is switch
180                                continue 2;
181                            }
182                            $pg_id = $this->pg_mapping[$pg["id"]];
183                            break;
184
185                        case "pg":
186                            $pg_id = $pg["id"];
187                            break;
188                    }
189                    if (!$this->lm_tree->isInTree($pg_id)) {
190                        $this->lm_tree->insertNode($pg_id, $st["id"]);
191                    }
192                }
193            }
194        }
195        //echo "<b>END: storing the tree</b>";
196//exit;
197    }
198
199
200    /**
201    * parse pages that contain files, mobs and/or internal links
202    */
203    public function processPagesToParse()
204    {
205        /*
206        $pg_mapping = array();
207        foreach($this->pg_mapping as $key => $value)
208        {
209            $pg_mapping[$key] = "il__pg_".$value;
210        }*/
211        //echo "<br><b>processIntLinks</b>"; flush();
212
213        // outgoin internal links
214        foreach ($this->pages_to_parse as $page_id) {
215            $page_arr = explode(":", $page_id);
216            //echo "<br>resolve:".$this->content_object->getType().":".$page_id; flush();
217            switch ($page_arr[0]) {
218                case "lm":
219                    switch ($this->content_object->getType()) {
220                        case "lm":
221                            $page_obj = new ilLMPage($page_arr[1]);
222                            break;
223
224                        default:
225                            die("Unknown content type " . $this->content_object->getType());
226                    }
227
228                    break;
229
230                case "gdf":
231                    $page_obj = new ilGlossaryDefPage($page_arr[1]);
232                    break;
233
234                case "qpl":
235                    $page_obj = new ilAssQuestionPage($page_arr[1]);
236                    break;
237            }
238            $page_obj->buildDom();
239            $page_obj->resolveIntLinks();
240            $page_obj->resolveIIMMediaAliases($this->mob_mapping);
241            if (in_array($this->coType, array("lm"))) {
242                $page_obj->resolveQuestionReferences($this->qst_mapping);
243            }
244            $page_obj->update(false);
245
246            if ($page_arr[0] == "gdf") {
247                $def = new ilGlossaryDefinition($page_arr[1]);
248                $def->updateShortText();
249            }
250
251            unset($page_obj);
252        }
253
254        //echo "<br><b>map area internal links</b>"; flush();
255        // outgoins map area (mob) internal links
256        foreach ($this->mobs_with_int_links as $mob_id) {
257            ilMediaItem::_resolveMapAreaLinks($mob_id);
258        }
259
260        //echo "<br><b>incoming interna links</b>"; flush();
261        // incoming internal links
262        $done = array();
263        foreach ($this->link_targets as $link_target) {
264            //echo "doin link target:".$link_target.":<br>";
265            $link_arr = explode("_", $link_target);
266            $target_inst = $link_arr[1];
267            $target_type = $link_arr[2];
268            $target_id = $link_arr[3];
269            //echo "<br>-".$target_type."-".$target_id."-".$target_inst."-";
270            $sources = ilInternalLink::_getSourcesOfTarget($target_type, $target_id, $target_inst);
271            foreach ($sources as $key => $source) {
272                //echo "got source:".$key.":<br>";
273                if (in_array($key, $done)) {
274                    continue;
275                }
276                $type_arr = explode(":", $source["type"]);
277
278                // content object pages
279                if ($type_arr[1] == "pg") {
280                    if (ilPageObject::_exists($type_arr[0], $source["id"])) {
281                        $page_object = ilPageObjectFactory::getInstance($type_arr[0], $source["id"]);
282                        $page_object->buildDom();
283                        $page_object->resolveIntLinks();
284                        $page_object->update();
285                        unset($page_object);
286                    }
287                }
288
289                // eventually correct links in questions to learning modules
290                if ($type_arr[0] == "qst") {
291                    assQuestion::_resolveIntLinks($source["id"]);
292                }
293                // eventually correct links in survey questions to learning modules
294                if ($type_arr[0] == "sqst") {
295                    SurveyQuestion::_resolveIntLinks($source["id"]);
296                }
297                $done[$key] = $key;
298            }
299        }
300    }
301
302
303    /**
304    * copy multimedia object files from import zip file to mob directory
305    */
306    public function copyMobFiles()
307    {
308        $imp_dir = $this->import_dir;
309        foreach ($this->mob_mapping as $origin_id => $mob_id) {
310            if (empty($origin_id)) {
311                continue;
312            }
313
314            /*
315            $origin_arr = explode("_", $origin_id);
316            if ($origin_arr[2] == "el") // imagemap
317            {
318                $obj_dir = "imagemap".$origin_arr[3];
319            }
320            else // normal media object
321            {
322                $obj_dir = "mm".$origin_arr[3];
323            }*/
324
325            $obj_dir = $origin_id;
326            $source_dir = $imp_dir . "/" . $this->subdir . "/objects/" . $obj_dir;
327            $target_dir = ilUtil::getWebspaceDir() . "/mobs/mm_" . $mob_id;
328
329            if (@is_dir($source_dir)) {
330                // make target directory
331                ilUtil::makeDir($target_dir);
332                //@mkdir($target_dir);
333                //@chmod($target_dir, 0755);
334
335                if (@is_dir($target_dir)) {
336                    ilLoggerFactory::getLogger("mob")->debug("s:-$source_dir-,t:-$target_dir-");
337                    ilUtil::rCopy(realpath($source_dir), realpath($target_dir));
338                }
339            }
340        }
341    }
342
343    /**
344    * copy files of file items
345    */
346    public function copyFileItems()
347    {
348        $imp_dir = $this->import_dir;
349        foreach ($this->file_item_mapping as $origin_id => $file_id) {
350            if (empty($origin_id)) {
351                continue;
352            }
353            $obj_dir = $origin_id;
354            $source_dir = $imp_dir . "/" . $this->subdir . "/objects/" . $obj_dir;
355
356            $file_obj = new ilObjFile($file_id, false);
357            //$target_dir = ilUtil::getDataDir()."/files/file_".$file_id;
358            $target_dir = $file_obj->getDirectory();
359            if (@is_dir($source_dir)) {
360                // make target directory
361                ilUtil::makeDir($target_dir);
362                //@mkdir($target_dir);
363                //@chmod($target_dir, 0755);
364
365                if (@is_dir($target_dir)) {
366                    ilUtil::rCopy(realpath($source_dir), realpath($target_dir));
367                }
368            }
369            $test = $file_obj->determineFilesize();
370            $file_obj->update();
371        }
372    }
373
374    /**
375    * set question import ident to pool/test question id mapping
376    */
377    public function setQuestionMapping($a_map)
378    {
379        $this->qst_mapping = $a_map;
380    }
381
382
383    /*
384    * update parsing status for a element begin
385    */
386    public function beginElement($a_name)
387    {
388        if (!isset($this->status["$a_name"])) {
389            $this->cnt[$a_name] == 1;
390        } else {
391            $this->cnt[$a_name]++;
392        }
393        $this->current_element[count($this->current_element)] = $a_name;
394    }
395
396    /*
397    * update parsing status for an element ending
398    *
399    * @param	string	$a_name		element name
400    */
401    public function endElement($a_name)
402    {
403        $this->cnt[$a_name]--;
404        unset($this->current_element[count($this->current_element) - 1]);
405    }
406
407    /*
408    * returns current element
409    */
410    public function getCurrentElement()
411    {
412        return ($this->current_element[count($this->current_element) - 1]);
413    }
414
415    /*
416    * returns number of current open elements of type $a_name
417    *
418    * @param	string	$a_name		element name
419    */
420    public function getOpenCount($a_name)
421    {
422        if (isset($this->cnt[$a_name])) {
423            return $this->cnt[$a_name];
424        } else {
425            return 0;
426        }
427    }
428
429    /**
430    * generate a tag with given name and attributes
431    *
432    * @param	string		"start" | "end" for starting or ending tag
433    * @param	string		element/tag name
434    * @param	array		array of attributes
435    */
436    public function buildTag($type, $name, $attr = "")
437    {
438        $tag = "<";
439
440        if ($type == "end") {
441            $tag .= "/";
442        }
443
444        $tag .= $name;
445
446        if (is_array($attr)) {
447            foreach ($attr as $k => $v) {
448                $tag .= " " . $k . "=\"$v\"";
449            }
450        }
451
452        $tag .= ">";
453
454        return $tag;
455    }
456
457    /**
458    * handler for begin of element
459    *
460    * @param	resource	$a_xml_parser		xml parser
461    * @param	string		$a_name				element name
462    * @param	array		$a_attribs			element attributes array
463    */
464    public function handlerBeginTag($a_xml_parser, $a_name, $a_attribs)
465    {
466        //echo "<b>BEGIN TAG: $a_name <br></b>"; flush();
467        switch ($a_name) {
468            case "ContentObject":
469                $this->current_object = $this->content_object;
470//echo "<br>Parser:CObjType:".$a_attribs["Type"];
471                if ($a_attribs["Type"] == "Glossary") {
472                    $this->glossary_object = $this->content_object;
473                }
474                break;
475
476            case "StructureObject":
477//echo "<br><br>StructureOB-SET-".count($this->structure_objects)."<br>";
478                $this->structure_objects[count($this->structure_objects)]
479                    = new ilStructureObject($this->content_object);
480                $this->current_object = $this->structure_objects[count($this->structure_objects) - 1];
481                $this->current_object->setLMId($this->content_object->getId());
482                // new meta data handling: we create the structure
483                // object already here, this should also create a
484                // md entry
485                $this->current_object->create(true);
486                break;
487
488            case "PageObject":
489                $this->in_page_object = true;
490                $this->cur_qid = "";
491                if (($this->coType != "tst") and ($this->coType != "qpl")) {
492                    $this->lm_page_object = new ilLMPageObject($this->content_object);
493                    $this->page_object = new ilLMPage();
494                    $this->lm_page_object->setLMId($this->content_object->getId());
495                    $this->lm_page_object->assignPageObject($this->page_object);
496                    $this->current_object = $this->lm_page_object;
497                } else {
498                    $this->page_object = new ilAssQuestionPage();
499                }
500                break;
501
502            case "PageAlias":
503                if (($this->coType != "tst") and ($this->coType != "qpl")) {
504                    $this->lm_page_object->setAlias(true);
505                    $this->lm_page_object->setOriginID($a_attribs["OriginId"]);
506                }
507                break;
508
509            case "MediaObject":
510                $this->in_media_object = true;
511                // no break
512            case "InteractiveImage":
513
514                $this->media_meta_start = true;
515                $this->media_meta_cache = array();
516                $this->media_object = new ilObjMediaObject();
517                break;
518
519            case "MediaAlias":
520//echo "<br>---NEW MEDIAALIAS---<br>";
521                $this->media_object->setAlias(true);
522                $this->media_object->setImportId($a_attribs["OriginId"]);
523                if (is_object($this->page_object)) {
524                    $this->page_object->needsImportParsing(true);
525                }
526                break;
527
528            case "MediaItem":
529            case "MediaAliasItem":
530                $this->in_media_item = true;
531                $this->media_item = new ilMediaItem();
532                $this->media_item->setPurpose($a_attribs["Purpose"]);
533                /*if ($a_name == "MediaItem")
534                {
535                    $this->media_item->setHighlightMode($a_attribs["MapHighlightMode"]);
536                    $this->media_item->setHighlightClass($a_attribs["MapHighlightClass"]);
537                }*/
538                break;
539
540            case "Layout":
541                if (is_object($this->media_object) && $this->in_media_object) {
542                    $this->media_item->setWidth($a_attribs["Width"]);
543                    $this->media_item->setHeight($a_attribs["Height"]);
544                    $this->media_item->setHAlign($a_attribs["HorizontalAlign"]);
545                }
546                break;
547
548            case "Parameter":
549                if (is_object($this->media_object) && $this->in_media_object) {
550                    $this->media_item->setParameter($a_attribs["Name"], $a_attribs["Value"]);
551                }
552                break;
553
554            case "MapArea":
555                $this->in_map_area = true;
556                $this->map_area = new ilMapArea();
557                $this->map_area->setShape($a_attribs["Shape"]);
558                $this->map_area->setCoords($a_attribs["Coords"]);
559                $this->map_area->setHighlightMode($a_attribs["HighlightMode"]);
560                $this->map_area->setHighlightClass($a_attribs["HighlightClass"]);
561                break;
562
563            case "Glossary":
564                $this->in_glossary = true;
565                if ($this->content_object->getType() != "glo") {
566                    $this->glossary_object = new ilObjGlossary();
567                    $this->glossary_object->setTitle("");
568                    $this->glossary_object->setDescription("");
569                    $this->glossary_object->create(true);
570                    $this->glossary_object->createReference();
571                    $parent = $this->tree->getParentNodeData($this->content_object->getRefId());
572                    $this->glossary_object->putInTree($parent["child"]);
573                    $this->glossary_object->setPermissions($parent["child"]);
574                }
575                $this->current_object = $this->glossary_object;
576                break;
577
578            case "GlossaryItem":
579                $this->glossary_term = new ilGlossaryTerm();
580                $this->glossary_term->setGlossaryId($this->glossary_object->getId());
581                $this->glossary_term->setLanguage($a_attribs["Language"]);
582                $this->glossary_term->setImportId($a_attribs["Id"]);
583                $this->link_targets[$a_attribs["Id"]] = $a_attribs["Id"];
584                break;
585
586            case "Definition":
587                $this->in_glossary_definition = true;
588                $this->glossary_definition = new ilGlossaryDefinition();
589                $this->page_object = new ilGlossaryDefPage();
590                $this->page_object->setParentId($this->glossary_term->getGlossaryId());
591                $this->glossary_definition->setTermId($this->glossary_term->getId());
592                $this->glossary_definition->assignPageObject($this->page_object);
593                $this->current_object = $this->glossary_definition;
594                $this->glossary_definition->create(true);
595                // see bug #12465, we need to clear xml after creation, since it will be <PageObject></PageObject>
596                // otherwise, and appendXML calls will lead to "<PageObject></PageObject><PageObject>....</PageObject>"
597                $this->page_object->setXMLContent("");
598                break;
599
600            case "FileItem":
601                $this->in_file_item = true;
602                $this->file_item = new ilObjFile();
603                $this->file_item->setTitle("dummy");
604                $this->file_item->setMode("filelist");
605                if (is_object($this->page_object)) {
606                    $this->page_object->needsImportParsing(true);
607                }
608                break;
609
610            case "Paragraph":
611                if ($a_attribs["Characteristic"] == "Code") {
612                    $this->inside_code = true;
613                }
614                break;
615
616            case "Properties":
617                $this->in_properties = true;
618                break;
619
620            case "Property":
621                if ($this->content_object->getType() == "lm") {
622                    switch ($a_attribs["Name"]) {
623                        case "Layout":
624                            $this->content_object->setLayout($a_attribs["Value"]);
625                            break;
626
627                        case "PageHeader":
628                            $this->content_object->setPageHeader($a_attribs["Value"]);
629                            break;
630
631                        case "TOCMode":
632                            $this->content_object->setTOCMode($a_attribs["Value"]);
633                            break;
634
635                        case "ActiveLMMenu":
636                            $this->content_object->setActiveLMMenu(
637                                ilUtil::yn2tf($a_attribs["Value"])
638                            );
639                            break;
640
641                        case "ActiveNumbering":
642                            $this->content_object->setActiveNumbering(
643                                ilUtil::yn2tf($a_attribs["Value"])
644                            );
645                            break;
646
647                        case "ActiveTOC":
648                            $this->content_object->setActiveTOC(
649                                ilUtil::yn2tf($a_attribs["Value"])
650                            );
651                            break;
652
653                        case "ActivePrintView":
654                            $this->content_object->setActivePrintView(
655                                ilUtil::yn2tf($a_attribs["Value"])
656                            );
657                            break;
658
659                        case "CleanFrames":
660                            $this->content_object->setCleanFrames(
661                                ilUtil::yn2tf($a_attribs["Value"])
662                            );
663                            break;
664
665                        case "PublicNotes":
666                            $this->content_object->setPublicNotes(
667                                ilUtil::yn2tf($a_attribs["Value"])
668                            );
669                            break;
670
671                        case "HistoryUserComments":
672                            $this->content_object->setHistoryUserComments(
673                                ilUtil::yn2tf($a_attribs["Value"])
674                            );
675                            break;
676
677                        case "Rating":
678                            $this->content_object->setRating(
679                                ilUtil::yn2tf($a_attribs["Value"])
680                            );
681                            break;
682
683                        case "RatingPages":
684                            $this->content_object->setRatingPages(
685                                ilUtil::yn2tf($a_attribs["Value"])
686                            );
687                            break;
688
689                        case "HeaderPage":
690                            if ($a_attribs["Value"] != "") {
691                                if ($this->pg_mapping[$a_attribs["Value"]] > 0) {
692                                    $this->content_object->setHeaderPage(
693                                        $this->pg_mapping[$a_attribs["Value"]]
694                                    );
695                                }
696                            }
697                            break;
698
699                        case "FooterPage":
700                            if ($a_attribs["Value"] != "") {
701                                if ($this->pg_mapping[$a_attribs["Value"]] > 0) {
702                                    $this->content_object->setFooterPage(
703                                        $this->pg_mapping[$a_attribs["Value"]]
704                                    );
705                                }
706                            }
707                            break;
708
709                        case "LayoutPerPage":
710                            $this->content_object->setLayoutPerPage($a_attribs["Value"]);
711                            break;
712
713                        case "ProgressIcons":
714                            $this->content_object->setProgressIcons($a_attribs["Value"]);
715                            break;
716
717                        case "StoreTries":
718                            $this->content_object->setStoreTries($a_attribs["Value"]);
719                            break;
720
721                        case "RestrictForwardNavigation":
722                            $this->content_object->setRestrictForwardNavigation($a_attribs["Value"]);
723                            break;
724
725                        case "DisableDefaultFeedback":
726                            $this->content_object->setDisableDefaultFeedback($a_attribs["Value"]);
727                            break;
728
729                    }
730                    //echo "<br>+".$a_attribs["Name"]."+";
731                }
732                break;
733
734            ////////////////////////////////////////////////
735            /// Meta Data Section
736            ////////////////////////////////////////////////
737            case "MetaData":
738                $this->in_meta_data = true;
739//echo "<br>begin meta data section -".$this->current_object->getType()."-";
740                // media obejct meta data handling
741                // is done in the "Identifier" begin tag processing
742                // the rest is done here
743                if (!$this->in_media_object) {
744                    if (($this->coType != "tst") and ($this->coType != "qpl")) {
745                        // type pg/st
746                        if ($this->current_object->getType() == "st" ||
747                            $this->current_object->getType() == "pg") {
748                            // late creation of page object
749                            if ($this->current_object->getType() == "pg") {
750                                $this->lm_page_object->create(true);
751                            }
752                            $this->md = new ilMD(
753                                $this->content_object->getId(),
754                                $this->current_object->getId(),
755                                $this->current_object->getType()
756                            );
757                        }
758                        // type gdf
759                        elseif ($this->current_object->getType() == "gdf") {
760                            $this->md = new ilMD(
761                                $this->glossary_object->getId(),
762                                $this->current_object->getId(),
763                                $this->current_object->getType()
764                            );
765                        }
766                        // type lm, dbk, glo
767                        else {
768                            if ($this->processMeta()) {
769                                $this->md = new ilMD(
770                                    $this->current_object->getId(),
771                                    0,
772                                    $this->current_object->getType()
773                                );
774                            }
775                        }
776                    } else {
777                        // type qpl or tst
778                        $this->md = new ilMD(
779                            $this->content_object->getId(),
780                            0,
781                            $this->current_object->getType()
782                        );
783                        if ($this->md->getGeneral() != false) {
784                            $this->metadata_parsing_disabled = true;
785                            $this->enableMDParsing(false);
786                        }
787                    }
788                }
789                break;
790
791            // Identifier
792            case "Identifier":
793
794                // begin-patch optes_lok_export
795                if ($this->in_meta_data && $this->current_object instanceof ilStructureObject) {
796                    if ($this->mapping instanceof ilImportMapping) {
797                        $import_id_parsed = ilUtil::parseImportId($a_attribs['Entry']);
798                        if ($import_id_parsed['type'] == 'st') {
799                            $this->mapping->addMapping(
800                                'Modules/LearningModule',
801                                'lm_tree',
802                                $import_id_parsed['id'],
803                                $this->current_object->getId()
804                            );
805                        }
806                    }
807                }
808                // end-patch optes_lok_export
809
810                // please note: Meta-Metadata and MetaData are different tags!
811                if (!$this->in_meta_meta_data) {
812                    if ($this->in_meta_data && !$this->in_glossary_definition) {
813                        if (!$this->in_media_object) {
814                            $this->current_object->setImportId($a_attribs["Entry"]);
815                        }
816                        $this->link_targets[$a_attribs["Entry"]] = $a_attribs["Entry"];
817                    }
818                    if ($this->in_file_item) {
819                        if ($this->file_item_mapping[$a_attribs["Entry"]] == "") {
820                            $this->file_item->create();
821                            $this->file_item->setImportId($a_attribs["Entry"]);
822                            $this->file_item_mapping[$a_attribs["Entry"]] = $this->file_item->getId();
823                        }
824                    }
825                    if ($this->in_meta_data && $this->in_media_object) {
826                        //echo "looking for -".$a_attribs["Entry"]."-<br>";
827
828                        $mob_id = $this->mob_mapping[$a_attribs["Entry"]];
829
830                        // within learning module import, usually a media object
831                        // has already been created with a media alias tag
832                        if ($mob_id > 0) {
833                            $this->media_object = new ilObjMediaObject($mob_id);
834                        } else {	// in glossaries the media objects precede the definitions
835                            // so we don't have an object already
836                            $this->media_object = new ilObjMediaObject();
837                            $this->media_object->create(true, false);
838                            $this->mob_mapping[$a_attribs["Entry"]]
839                                = $this->media_object->getId();
840                        }
841                        $this->media_object->setImportId($a_attribs["Entry"]);
842                        $this->md = new ilMD(
843                            0,
844                            $this->media_object->getId(),
845                            "mob"
846                        );
847                        $this->emptyMediaMetaCache($a_xml_parser);
848                    }
849                }
850                break;
851
852            case "Meta-Metadata":
853                $this->in_meta_meta_data = true;
854                break;
855
856            // Internal Link
857            case "IntLink":
858                if (is_object($this->page_object)) {
859                    $this->page_object->setContainsIntLink(true);
860                }
861                if ($this->in_map_area) {
862                    //echo "intlink:maparea:<br>";
863                    $this->map_area->setLinkType(IL_INT_LINK);
864                    $this->map_area->setTarget($a_attribs["Target"]);
865                    $this->map_area->setType($a_attribs["Type"]);
866                    $this->map_area->setTargetFrame($a_attribs["TargetFrame"]);
867                    if (is_object($this->media_object)) {
868                        //echo ":setContainsLink:<br>";
869                        $this->media_object->setContainsIntLink(true);
870                    }
871                }
872                break;
873
874            // External Link
875            case "ExtLink":
876                if ($this->in_map_area) {
877                    $this->map_area->setLinkType(IL_EXT_LINK);
878                    $this->map_area->setHref($a_attribs["Href"]);
879                    $this->map_area->setExtTitle($a_attribs["Title"]);
880                }
881                break;
882
883            // Question
884            case "Question":
885                $this->cur_qid = $a_attribs["QRef"];
886                $this->page_object->setContainsQuestion(true);
887                break;
888
889            case "Location":
890                $this->loc_type = $a_attribs["Type"];
891                break;
892
893        }
894        $this->beginElement($a_name);
895
896        // append content to page xml content
897        if (($this->in_page_object || $this->in_glossary_definition)
898            && !$this->in_meta_data && !$this->in_media_object) {
899            if ($a_name == "Definition") {
900                $app_name = "PageObject";
901                $app_attribs = array();
902            } else {
903                $app_name = $a_name;
904                $app_attribs = $a_attribs;
905            }
906
907            // change identifier entry of file items to new local file id
908            if ($this->in_file_item && $app_name == "Identifier") {
909                $app_attribs["Entry"] = "il__file_" . $this->file_item_mapping[$a_attribs["Entry"]];
910                //$app_attribs["Entry"] = "il__file_".$this->file_item->getId();
911            }
912
913            $this->page_object->appendXMLContent($this->buildTag("start", $app_name, $app_attribs));
914            //echo "&nbsp;&nbsp;after append, xml:".$this->page_object->getXMLContent().":<br>";
915        }
916
917
918        // call meta data handler
919        if ($this->in_meta_data && $this->processMeta()) {
920            // cache beginning of meta data within media object tags
921            // (we need to know the id at the begin of meta elements within
922            // media objects, after the "Identifier" tag has been processed
923            // we send the cached data to the meta xml handler)
924            if ($this->in_media_object && $this->media_meta_start) {
925                $this->media_meta_cache[] =
926                    array("type" => "handlerBeginTag", "par1" => $a_name, "par2" => $a_attribs);
927            } else {
928                if ($a_name == "Identifier") {
929                    if (!$this->in_media_object) {
930                        $a_attribs["Entry"] = "il__" . $this->current_object->getType() .
931                            "_" . $this->current_object->getId();
932                    } else {
933                        $a_attribs["Entry"] = "il__mob" .
934                            "_" . $this->media_object->getId();
935                    }
936                    $a_attribs["Catalog"] = "ILIAS";
937                }
938
939                parent::handlerBeginTag($a_xml_parser, $a_name, $a_attribs);
940            }
941        }
942    }
943
944    /**
945    * check whether meta data should be processed
946    */
947    public function processMeta()
948    {
949        // do not process second meta block in (ilias3) glossaries
950        // which comes right after the "Glossary" tag
951        if ($this->content_object->getType() == "glo" &&
952            $this->in_glossary && !$this->in_media_object
953            && !$this->in_glossary_definition) {
954            return false;
955        }
956
957        return true;
958    }
959
960
961    /**
962    * handler for end of element
963    *
964    * @param	resource	$a_xml_parser		xml parser
965    * @param	string		$a_name				element name
966    */
967    public function handlerEndTag($a_xml_parser, $a_name)
968    {
969        // call meta data handler
970        if ($this->in_meta_data && $this->processMeta()) {
971            // cache beginning of meta data within media object tags
972            // (we need to know the id, after that we send the cached data
973            // to the meta xml handler)
974            if ($this->in_media_object && $this->media_meta_start) {
975                $this->media_meta_cache[] =
976                    array("type" => "handlerEndTag", "par1" => $a_name);
977            } else {
978                parent::handlerEndTag($a_xml_parser, $a_name);
979            }
980        }
981
982        //echo "<b>END TAG: $a_name <br></b>"; flush();
983        // append content to page xml content
984        if (($this->in_page_object || $this->in_glossary_definition)
985            && !$this->in_meta_data && !$this->in_media_object) {
986            $app_name = ($a_name == "Definition")
987                ? "PageObject"
988                : $a_name;
989            $this->page_object->appendXMLContent($this->buildTag("end", $app_name));
990        }
991
992        switch ($a_name) {
993            case "StructureObject":
994                //unset($this->meta_data);
995                unset($this->structure_objects[count($this->structure_objects) - 1]);
996                break;
997
998            case "PageObject":
999
1000                $this->in_page_object = false;
1001                if (($this->coType != "tst") and ($this->coType != "qpl")) {
1002                    if (!$this->lm_page_object->isAlias()) {
1003                        //$this->page_object->createFromXML();
1004                        $this->page_object->updateFromXML();
1005                        $this->pg_mapping[$this->lm_page_object->getImportId()]
1006                            = $this->lm_page_object->getId();
1007
1008                        if ($this->mapping instanceof ilImportMapping) {
1009                            $import_id_parsed = ilUtil::parseImportId($this->lm_page_object->getImportId());
1010                            if ($import_id_parsed['type'] == 'pg') {
1011                                $this->mapping->addMapping(
1012                                    'Modules/LearningModule',
1013                                    'pg',
1014                                    $import_id_parsed['id'],
1015                                    $this->lm_page_object->getId()
1016                                );
1017                            }
1018                        }
1019
1020                        // collect pages with internal links
1021                        if ($this->page_object->containsIntLink()) {
1022                            $this->pages_to_parse["lm:" . $this->page_object->getId()] = "lm:" . $this->page_object->getId();
1023                        }
1024
1025                        // collect pages with mobs or files
1026                        if ($this->page_object->needsImportParsing()) {
1027                            $this->pages_to_parse["lm:" . $this->page_object->getId()] = "lm:" . $this->page_object->getId();
1028                        }
1029
1030                        // collect pages with questions
1031                        if ($this->page_object->getContainsQuestion()) {
1032                            $this->pages_to_parse["lm:" . $this->page_object->getId()] = "lm:" . $this->page_object->getId();
1033                        }
1034                    }
1035                } else {
1036                    $xml = $this->page_object->getXMLContent();
1037                    if ($this->cur_qid != "") {
1038                        $ids = $this->qst_mapping[$this->cur_qid];
1039                        if ($ids["pool"] > 0) {
1040                            // question pool question
1041                            $page = new ilAssQuestionPage($ids["pool"]);
1042                            $xmlcontent = str_replace(
1043                                $this->cur_qid,
1044                                "il__qst_" . $ids["pool"],
1045                                $xml
1046                            );
1047                            $page->setXMLContent($xmlcontent);
1048                            $page->updateFromXML();
1049                            if ($this->page_object->needsImportParsing()) {
1050                                $this->pages_to_parse["qpl:" . $page->getId()] = "qpl:" . $page->getId();
1051                            }
1052                            unset($page);
1053                        }
1054                        if ($ids["test"] > 0) {
1055                            // test question
1056                            $page = new ilAssQuestionPage($ids["test"]);
1057                            $xmlcontent = str_replace(
1058                                $this->cur_qid,
1059                                "il__qst_" . $ids["test"],
1060                                $xml
1061                            );
1062                            $page->setXMLContent($xmlcontent);
1063                            $page->updateFromXML();
1064                            if ($this->page_object->needsImportParsing()) {
1065                                $this->pages_to_parse["qpl:" . $page->getId()] = "qpl:" . $page->getId();
1066                            }
1067                            unset($page);
1068                        }
1069                    }
1070                }
1071
1072                // if we are within a structure object: put page in tree
1073                $cnt = count($this->structure_objects);
1074//echo "1";
1075                if ($cnt > 0) {
1076                    //echo "B-$cnt-<br>";
1077                    //echo "<br>"; var_dump($this->structure_objects); echo "<br>";
1078                    $parent_id = $this->structure_objects[$cnt - 1]->getId();
1079                    if ($this->lm_page_object->isAlias()) {
1080                        //echo "3";
1081                        $this->pg_into_tree[$parent_id][] = array("type" => "pg_alias", "id" => $this->lm_page_object->getOriginId());
1082                    //echo "<br>"; var_dump($this->pg_into_tree); echo "<br>";
1083                    } else {
1084                        //echo "4";
1085                        $this->pg_into_tree[$parent_id][] = array("type" => "pg", "id" => $this->lm_page_object->getId());
1086                    }
1087                }
1088
1089                unset($this->page_object);
1090                unset($this->lm_page_object);
1091                unset($this->container[count($this->container) - 1]);
1092                break;
1093
1094            case "MediaObject":
1095                $this->in_media_object = false;
1096                // no break
1097case "InteractiveImage":
1098
1099//echo "ENDMediaObject:ImportId:".$this->media_object->getImportId()."<br>";
1100                // create media object on first occurence of an Id
1101
1102
1103                if (empty($this->mob_mapping[$this->media_object->getImportId()])) {
1104                    //echo "No mapping found --creating media object:title:".$this->media_object->getTitle().":<br>";
1105
1106                    // create media object
1107                    // media items are saves for mobs outside of
1108                    // pages only
1109                    $this->media_object->create(true, false);
1110
1111                    //echo "<br>creating mob ".$this->media_object->getId().":".$this->media_object->getTitle().":";
1112
1113                    // collect mobs with internal links
1114                    if ($this->media_object->containsIntLink()) {
1115                        //echo "got int link :".$this->media_object->getId().":<br>";
1116                        $this->mobs_with_int_links[] = $this->media_object->getId();
1117                    }
1118
1119                    $this->mob_mapping[$this->media_object->getImportId()]
1120                            = $this->media_object->getId();
1121                //echo "create:import_id:".$this->media_object->getImportId().":ID:".$this->mob_mapping[$this->media_object->getImportId()]."<br>";
1122                } else {
1123                    //echo "Mapping found<br>";
1124                    // get the id from mapping
1125                    $this->media_object->setId($this->mob_mapping[$this->media_object->getImportId()]);
1126
1127                    // update "real" (no alias) media object
1128                    // (note: we overwrite any data from the media object
1129                    // created by an MediaAlias, only the data of the real
1130                    // object is stored in db separately; data of the
1131                    // MediaAliases are within the page XML
1132                    if (!$this->media_object->isAlias()) {
1133                        // now the media items are saved within the db
1134                        $this->media_object->update();
1135
1136                        //echo "<br>update media object :".$this->media_object->getId().":";
1137
1138                        // collect mobs with internal links
1139                        if ($this->media_object->containsIntLink()) {
1140                            //echo "got int link :".$this->media_object->getId().":<br>";
1141                            $this->mobs_with_int_links[] = $this->media_object->getId();
1142                        }
1143                    }
1144                }
1145
1146                // append media alias to page, if we are in a page
1147                if ($this->in_page_object || $this->in_glossary_definition) {
1148                    if ($a_name != "InteractiveImage") {
1149                        $this->page_object->appendXMLContent($this->media_object->getXML(IL_MODE_ALIAS));
1150                        //echo "Appending:".htmlentities($this->media_object->getXML(IL_MODE_ALIAS))."<br>";
1151                    }
1152                }
1153
1154                break;
1155
1156            case "MediaItem":
1157            case "MediaAliasItem":
1158                $this->in_media_item = false;
1159                $this->media_object->addMediaItem($this->media_item);
1160//echo "adding media item -".$this->media_item->getId()."-".$this->media_item->getLocation()."- to object -".$this->media_object->getId()."-";
1161                break;
1162
1163            case "MapArea":
1164                $this->in_map_area = false;
1165                $this->media_item->addMapArea($this->map_area);
1166                break;
1167
1168            case "Properties":
1169                $this->in_properties = false;
1170                if ($this->content_object->getType() == "lm") {
1171                    $this->content_object->update();
1172                }
1173                break;
1174
1175            case "MetaData":
1176                $this->in_meta_data = false;
1177                if (strtolower(get_class($this->current_object)) == "illmpageobject" && !$this->in_media_object) {
1178                    // Metadaten eines PageObjects sichern in NestedSet
1179                    if (is_object($this->lm_page_object)) {
1180                        // update title/description of page object
1181                        $this->current_object->MDUpdateListener('General');
1182                        ilLMObject::_writeImportId(
1183                            $this->current_object->getId(),
1184                            $this->current_object->getImportId()
1185                        );
1186                    }
1187                } elseif ((strtolower(get_class($this->current_object)) == "ilobjquestionpool" ||
1188                    strtolower(get_class($this->current_object)) == "ilobjtest") &&
1189                    !$this->in_media_object) {
1190                    //					!$this->in_media_object && !$this->in_page_object)
1191                    // changed for imports of ILIAS 2 Tests where PageObjects could have
1192                    // Metadata sections (Helmut Schottmüller, 2005-12-02)
1193                    if ($this->metadata_parsing_disabled) {
1194                        $this->enableMDParsing(true);
1195                    } else {
1196                        if ($this->in_page_object) {
1197                            $this->page_object->MDUpdateListener('General');
1198                            ilLMObject::_writeImportId(
1199                                $this->page_object->getId(),
1200                                $this->page_object->getImportId()
1201                            );
1202                        } else {
1203                            $this->current_object->MDUpdateListener('General');
1204                            ilLMObject::_writeImportId(
1205                                $this->current_object->getId(),
1206                                $this->current_object->getImportId()
1207                            );
1208                        }
1209                    }
1210                } elseif (strtolower(get_class($this->current_object)) == "ilstructureobject") {    // save structure object at the end of its meta block
1211                    // determine parent
1212                    $cnt = count($this->structure_objects);
1213                    if ($cnt > 1) {
1214                        $parent_id = $this->structure_objects[$cnt - 2]->getId();
1215                    } else {
1216                        $parent_id = $this->lm_tree->getRootId();
1217                    }
1218
1219                    // create structure object and put it in tree
1220                    //$this->current_object->create(true); // now on top
1221                    $this->st_into_tree[] = array("id" => $this->current_object->getId(),
1222                        "parent" => $parent_id);
1223
1224                    // update title/description of structure object
1225                    $this->current_object->MDUpdateListener('General');
1226                    ilLMObject::_writeImportId(
1227                        $this->current_object->getId(),
1228                        $this->current_object->getImportId()
1229                    );
1230                } elseif (strtolower(get_class($this->current_object)) == "ilobjlearningmodule" ||
1231                    strtolower(get_class($this->current_object)) == "ilobjcontentobject" ||
1232                    (strtolower(get_class($this->current_object)) == "ilobjglossary" && $this->in_glossary)) {
1233                    // todo: saving of md? getting title/descr and
1234                    // set it for current object
1235                } elseif (strtolower(get_class($this->current_object)) == "ilglossarydefinition" && !$this->in_media_object) {
1236                    // now on top
1237                    //$this->glossary_definition->create();
1238
1239                    $this->page_object->setId($this->glossary_definition->getId());
1240                    $this->page_object->updateFromXML();
1241
1242                    // todo: saving of md? getting title/descr and
1243                    // set it for current object
1244                }
1245
1246
1247                if (strtolower(get_class($this->current_object)) == "ilobjlearningmodule" ||
1248                    strtolower(get_class($this->current_object)) == "ilobjglossary") {
1249                    if (strtolower(get_class($this->current_object)) == "ilobjglossary" &&
1250                        $this->content_object->getType() != "glo") {
1251                        //echo "<br><b>getting2: ".$this->content_object->getTitle()."</b>";
1252                        $this->current_object->setTitle($this->content_object->getTitle() . " - " .
1253                            $this->lng->txt("glossary"));
1254                    }
1255
1256                    $this->current_object->MDUpdateListener('General');
1257                    /*
1258                    if (!$this->in_media_object && $this->processMeta())
1259                    {
1260                        $this->current_object->update();
1261                    }
1262                    */
1263                }
1264
1265                if ($this->in_media_object) {
1266                    //echo "<br>call media object update listener";
1267                    $this->media_object->MDUpdateListener('General');
1268                }
1269
1270                if ($this->in_glossary_definition) {
1271                    $this->glossary_definition->MDUpdateListener('General');
1272                }
1273
1274                break;
1275
1276            case "Meta-Metadata":
1277                $this->in_meta_meta_data = false;
1278                break;
1279
1280            case "FileItem":
1281                $this->in_file_item = false;
1282                // only update new file items
1283                if ($this->file_item->getImportId($a_attribs["Entry"] != "")) {
1284                    $this->file_item->update();
1285                }
1286                break;
1287
1288
1289            case "Table":
1290                unset($this->container[count($this->container) - 1]);
1291                break;
1292
1293            case "Glossary":
1294                $this->in_glossary = false;
1295                break;
1296
1297            case "GlossaryTerm":
1298                $term = trim($this->chr_data);
1299                $term = str_replace("&lt;", "<", $term);
1300                $term = str_replace("&gt;", ">", $term);
1301                $this->glossary_term->setTerm($term);
1302                $this->glossary_term->create();
1303                $iia = explode("_", $this->glossary_term->getImportId());
1304                $this->glossary_term_map[(int) $iia[count($iia) - 1]] = $this->glossary_term->getId();
1305                break;
1306
1307            case "Paragraph":
1308                $this->inside_code = false;
1309                break;
1310
1311            case "Definition":
1312                $this->in_glossary_definition = false;
1313                $this->page_object->updateFromXML();
1314//echo "&nbsp;&nbsp;after def update, xml:".htmlentities($this->page_object->getXMLContent()).":<br>";
1315//echo "<br>".$this->page_object->getId()."-".$this->page_object->getParentType()."-";
1316                $this->page_object->buildDom();
1317                $this->glossary_definition->setShortText($this->page_object->getFirstParagraphText());
1318                $this->glossary_definition->update();
1319                //$this->pg_mapping[$this->lm_page_object->getImportId()]
1320                //	= $this->lm_page_object->getId();
1321                if ($this->page_object->containsIntLink()) {
1322                    //echo "<br>Definition contains Int Link:".$this->page_object->getId();
1323                    $this->pages_to_parse["gdf:" . $this->page_object->getId()] = "gdf:" . $this->page_object->getId();
1324                }
1325                if ($this->page_object->needsImportParsing()) {
1326                    $this->pages_to_parse["gdf:" . $this->page_object->getId()] = "gdf:" . $this->page_object->getId();
1327                }
1328                break;
1329
1330            case "Format":
1331                if ($this->in_media_item) {
1332                    $this->media_item->setFormat(trim($this->chr_data));
1333                }
1334                if ($this->in_file_item) {
1335                    $this->file_item->setFileType(trim($this->chr_data));
1336                }
1337                break;
1338
1339            case "Title":
1340                if (!$this->in_media_object) {
1341                    $this->current_object->setTitle(trim($this->chr_data));
1342                //$this->meta_data->setTitle(trim($this->chr_data));
1343                } else {
1344                    $this->media_object->setTitle(trim($this->chr_data));
1345                    //$this->meta_data->setTitle(trim($this->chr_data));
1346                }
1347                break;
1348
1349            case "Language":
1350                /*
1351                if (is_object($this->meta_data))
1352                {
1353                    $this->meta_data->setLanguage(trim($this->chr_data));
1354                }*/
1355
1356                break;
1357
1358            case "Description":
1359                //$this->meta_data->setDescription(trim($this->chr_data));
1360                break;
1361
1362            case "Caption":
1363                if ($this->in_media_object) {
1364                    $this->media_item->setCaption(trim($this->chr_data));
1365                }
1366                break;
1367
1368            case "TextRepresentation":
1369                if ($this->in_media_object) {
1370                    $this->media_item->setTextRepresentation(trim($this->chr_data));
1371                }
1372                break;
1373
1374            // Location
1375            case "Location":
1376                // TODO: adapt for files in "real" subdirectories
1377                if ($this->in_media_item) {
1378                    $this->media_item->setLocationType($this->loc_type);
1379                    if ($this->loc_type == "Reference") {
1380                        $this->media_item->setLocation(str_replace("&", "&amp;", trim($this->chr_data)));
1381                    } else {
1382                        $this->media_item->setLocation(trim($this->chr_data));
1383                    }
1384                    //echo "-".$this->media_item->getLocation()."-";
1385                }
1386                if ($this->in_file_item) {
1387                    // set file name from xml file
1388                    $this->file_item->setFileName(trim($this->chr_data));
1389
1390                    // special handling for file names with special characters
1391                    // (e.g. "&gt;")
1392                    if ($this->file_item->getType() == "file" &&
1393                        is_int(strpos($this->chr_data, "&")) &&
1394                        is_int(strpos($this->chr_data, ";"))) {
1395                        $imp_dir = $this->import_dir;
1396                        $source_dir = $imp_dir . "/" . $this->subdir . "/objects/" .
1397                            $this->file_item->getImportId();
1398
1399                        // read "physical" file name from directory
1400                        if ($dir = opendir($source_dir)) {
1401                            while (false !== ($file = readdir($dir))) {
1402                                if ($file != "." && $file != "..") {
1403                                    $this->file_item->setFileName($file);
1404                                }
1405                            }
1406                            closedir($dir);
1407                        }
1408                    }
1409
1410                    // set file item title
1411                    $this->file_item->setTitle(trim($this->chr_data));
1412                }
1413                break;
1414
1415        }
1416        $this->endElement($a_name);
1417        $this->chr_data = "";
1418    }
1419
1420    /**
1421    * handler for character data
1422    *
1423    * @param	resource	$a_xml_parser		xml parser
1424    * @param	string		$a_data				character data
1425    */
1426    public function handlerCharacterData($a_xml_parser, $a_data)
1427    {
1428        // call meta data handler
1429        if ($this->in_meta_data && $this->processMeta()) {
1430            // cache beginning of meta data within media object tags
1431            // (we need to know the id, after that we send the cached data
1432            // to the meta xml handler)
1433            if ($this->in_media_object && $this->media_meta_start) {
1434                $this->media_meta_cache[] =
1435                    array("type" => "handlerCharacterData", "par1" => $a_data);
1436            } else {
1437                parent::handlerCharacterData($a_xml_parser, $a_data);
1438            }
1439        }
1440
1441        // the parser converts "&gt;" to ">" and "&lt;" to "<"
1442        // in character data, but we don't want that, because it's the
1443        // way we mask user html in our content, so we convert back...
1444
1445        $a_data = str_replace("<", "&lt;", $a_data);
1446        $a_data = str_replace(">", "&gt;", $a_data);
1447
1448
1449        // DELETE WHITESPACES AND NEWLINES OF CHARACTER DATA
1450        $a_data = preg_replace("/\n/", "", $a_data);
1451        if (!$this->inside_code) {
1452            $a_data = preg_replace("/\t+/", "", $a_data);
1453        }
1454
1455        $this->chr_data .= $a_data;
1456
1457        if (!empty($a_data) || $a_data === "0") {
1458            // append all data to page, if we are within PageObject,
1459            // but not within MetaData or MediaObject
1460            if (($this->in_page_object || $this->in_glossary_definition)
1461                && !$this->in_meta_data && !$this->in_media_object) {
1462                $this->page_object->appendXMLContent($a_data);
1463            }
1464
1465            if ($this->in_meta_data) {
1466                //$this->meta_data->appendXMLContent($a_data);
1467//echo "<br>".$a_data;
1468            }
1469
1470            switch ($this->getCurrentElement()) {
1471
1472                case "IntLink":
1473                case "ExtLink":
1474                    if ($this->in_map_area) {
1475                        $this->map_area->appendTitle($a_data);
1476                    }
1477                    break;
1478
1479            }
1480        }
1481    }
1482
1483
1484    /**
1485    * send all cached tags to the meta data parser and
1486    * clear the cache
1487    */
1488    public function emptyMediaMetaCache(&$a_xml_parser)
1489    {
1490        foreach ($this->media_meta_cache as $cache_entry) {
1491            switch ($cache_entry["type"]) {
1492                case "handlerBeginTag":
1493                    parent::handlerBeginTag(
1494                        $a_xml_parser,
1495                        $cache_entry["par1"],
1496                        $cache_entry["par2"]
1497                    );
1498                    break;
1499
1500                case "handlerEndTag":
1501                    parent::handlerEndTag(
1502                        $a_xml_parser,
1503                        $cache_entry["par1"]
1504                    );
1505                    break;
1506
1507                case "handlerCharacterData":
1508                    parent::handlerCharacterData(
1509                        $a_xml_parser,
1510                        $cache_entry["par1"]
1511                    );
1512                    break;
1513            }
1514        }
1515
1516        $this->media_meta_start = false;
1517        $this->media_meta_cache[] = array();
1518    }
1519
1520    /**
1521     * Get glossary term map (imported ids to new ids)
1522     *
1523     * @param
1524     * @return
1525     */
1526    public function getGlossaryTermMap()
1527    {
1528        return $this->glossary_term_map;
1529    }
1530}
1531