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