ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilPageObject.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4define("IL_INSERT_BEFORE", 0);
5define("IL_INSERT_AFTER", 1);
6define("IL_INSERT_CHILD", 2);
7
11/*
12
13 - move dom related code to PageDom class/interface
14 - move ilDB dependency to ar object
15 - move internal links related code to extra class
16 - make factory available through DIC, opt allow decentralized factory parts
17 - PC types
18 -- internal links used/implemented?
19 -- styles used/implemented?
20 - application classes need
21 -- page object
22 --- page object should return php5 domdoc (getDom() vs getDomDoc()?)
23 esp. plugins should use this
24 -- remove content element hook, if content is not allowed
25 - PC types could move to components (e.g. blog, login)
26 - How to modularize xsl?
27 -- read from db?
28 -- xml entries say that xslt code is used -> read file and include in
29 main xslt file
30
31*/
32
40abstract class ilPageObject
41{
45 protected $obj_definition;
46
47 public static $exists = array();
48
52 protected $db;
53
57 protected $user;
58
62 protected $lng;
63
67 protected $tree;
68
72 protected $id;
73 public $dom;
74 public $xml;
75 public $encoding;
76 public $node;
77 public $cur_dtd = "ilias_pg_5_4.dtd";
81 public $parent_id;
87
91 protected $language = "-";
92
96 protected static $activation_data = array();
97
101 protected $import_mode = false;
102
106 protected $log;
107
111 protected $page_record = array();
112
116 protected $active = false;
117
121 protected $page_config;
122
123 protected $concrete_lang;
124
129 final public function __construct($a_id = 0, $a_old_nr = 0, $a_lang = "-")
130 {
131 global $DIC;
132 $this->obj_definition = $DIC["objDefinition"];
133 $this->db = $DIC->database();
134 $this->user = $DIC->user();
135 $this->lng = $DIC->language();
136 $this->tree = $DIC->repositoryTree();
137 $this->log = ilLoggerFactory::getLogger('copg');
138
139 $this->parent_type = $this->getParentType();
140 $this->id = $a_id;
141 $this->setLanguage($a_lang);
142
143 $this->contains_int_link = false;
144 $this->needs_parsing = false;
145 $this->update_listeners = array();
146 $this->update_listener_cnt = 0;
147 $this->dom_builded = false;
148 $this->page_not_found = false;
149 $this->old_nr = $a_old_nr;
150 $this->encoding = "UTF-8";
151 $this->id_elements =
152 array("PageContent",
153 "TableRow",
154 "TableData",
155 "ListItem",
156 "FileItem",
157 "Section",
158 "Tab",
159 "ContentPopup",
160 "GridCell"
161 );
162 $this->setActive(true);
163 $this->show_page_act_info = false;
164
165 if ($a_id != 0) {
166 $this->read();
167 }
168
169 $this->initPageConfig();
170
171 $this->afterConstructor();
172 }
173
177 public function afterConstructor()
178 {
179 }
180
185 abstract public function getParentType();
186
190 final public function initPageConfig()
191 {
192 include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
194 $this->setPageConfig($cfg);
195 }
196
201 public function setLanguage($a_val)
202 {
203 $this->language = $a_val;
204 }
205
210 public function getLanguage()
211 {
212 return $this->language;
213 }
214
215 public function setConcreteLang($a_val)
216 {
217 $this->concrete_lang = $a_val;
218 }
219
220 public function getConcreteLang()
221 {
223 }
224
225
230 public function setPageConfig($a_val)
231 {
232 $this->page_config = $a_val;
233 }
234
239 public function getPageConfig()
240 {
241 return $this->page_config;
242 }
243
248 public function setRenderMd5($a_rendermd5)
249 {
250 $this->rendermd5 = $a_rendermd5;
251 }
252
257 public function getRenderMd5()
258 {
259 return $this->rendermd5;
260 }
261
266 public function setRenderedContent($a_renderedcontent)
267 {
268 $this->renderedcontent = $a_renderedcontent;
269 }
270
275 public function getRenderedContent()
276 {
277 return $this->renderedcontent;
278 }
279
284 public function setRenderedTime($a_renderedtime)
285 {
286 $this->renderedtime = $a_renderedtime;
287 }
288
293 public function getRenderedTime()
294 {
295 return $this->renderedtime;
296 }
297
302 public function setLastChange($a_lastchange)
303 {
304 $this->lastchange = $a_lastchange;
305 }
306
311 public function getLastChange()
312 {
313 return $this->lastchange;
314 }
315
320 public function setLastChangeUser($a_val)
321 {
322 $this->last_change_user = $a_val;
323 }
324
329 public function getLastChangeUser()
330 {
331 return $this->last_change_user;
332 }
333
338 public function setShowActivationInfo($a_val)
339 {
340 $this->show_page_act_info = $a_val;
341 }
342
347 public function getShowActivationInfo()
348 {
349 return $this->show_page_act_info;
350 }
351
355 public function read()
356 {
357 $this->setActive(true);
358 if ($this->old_nr == 0) {
359 $query = "SELECT * FROM page_object" .
360 " WHERE page_id = " . $this->db->quote($this->id, "integer") .
361 " AND parent_type=" . $this->db->quote($this->getParentType(), "text") .
362 " AND lang = " . $this->db->quote($this->getLanguage(), "text");
363 $pg_set = $this->db->query($query);
364 $this->page_record = $this->db->fetchAssoc($pg_set);
365 $this->setActive($this->page_record["active"]);
366 $this->setActivationStart($this->page_record["activation_start"]);
367 $this->setActivationEnd($this->page_record["activation_end"]);
368 $this->setShowActivationInfo($this->page_record["show_activation_info"]);
369 } else {
370 $query = "SELECT * FROM page_history" .
371 " WHERE page_id = " . $this->db->quote($this->id, "integer") .
372 " AND parent_type=" . $this->db->quote($this->getParentType(), "text") .
373 " AND nr = " . $this->db->quote((int) $this->old_nr, "integer") .
374 " AND lang = " . $this->db->quote($this->getLanguage(), "text");
375 $pg_set = $this->db->query($query);
376 $this->page_record = $this->db->fetchAssoc($pg_set);
377 }
378 if (!$this->page_record) {
379 include_once("./Services/COPage/exceptions/class.ilCOPageNotFoundException.php");
380 throw new ilCOPageNotFoundException("Error: Page " . $this->id . " is not in database" .
381 " (parent type " . $this->getParentType() . ", lang: " . $this->getLanguage() . ").");
382 }
383
384 $this->xml = $this->page_record["content"];
385 $this->setParentId($this->page_record["parent_id"]);
386 $this->last_change_user = $this->page_record["last_change_user"];
387 $this->create_user = $this->page_record["create_user"];
388 $this->setRenderedContent($this->page_record["rendered_content"]);
389 $this->setRenderMd5($this->page_record["render_md5"]);
390 $this->setRenderedTime($this->page_record["rendered_time"]);
391 $this->setLastChange($this->page_record["last_change"]);
392 }
393
400 public static function _exists($a_parent_type, $a_id, $a_lang = "", $a_no_cache = false)
401 {
402 global $DIC;
403
404 $db = $DIC->database();
405
406 if (!$a_no_cache && isset(self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang])) {
407 return self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang];
408 }
409
410 $and_lang = "";
411 if ($a_lang != "") {
412 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
413 }
414
415 $query = "SELECT page_id FROM page_object WHERE page_id = " . $db->quote($a_id, "integer") . " " .
416 "AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang;
417 $set = $db->query($query);
418 if ($row = $db->fetchAssoc($set)) {
419 self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang] = true;
420 return true;
421 } else {
422 self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang] = false;
423 return false;
424 }
425 }
426
433 public static function _existsAndNotEmpty($a_parent_type, $a_id, $a_lang = "-")
434 {
435 include_once("./Services/COPage/classes/class.ilPageUtil.php");
436 return ilPageUtil::_existsAndNotEmpty($a_parent_type, $a_id, $a_lang);
437 }
438
439 public function buildDom($a_force = false)
440 {
441 if ($this->dom_builded && !$a_force) {
442 return;
443 }
444
445 //echo "\n<br>buildDomWith:".$this->getId().":xml:".$this->getXMLContent(true).":<br>";
446
447 $options = 0;
448 //$options = DOMXML_LOAD_VALIDATING;
449 //$options = LIBXML_DTDLOAD;
450 //$options = LIBXML_NOXMLDECL;
451 //echo htmlentities($this->getXMLContent(true))."<br>";
452 $this->dom = @domxml_open_mem($this->getXMLContent(true), $options, $error);
453 //var_dump($error);
454 $xpc = xpath_new_context($this->dom);
455 $path = "//PageObject";
456 $res = xpath_eval($xpc, $path);
457 if (count($res->nodeset) == 1) {
458 // echo "h";
459 $this->node = $res->nodeset[0];
460 }
461 //echo htmlentities($this->dom->dump_node($this->node)); exit;
462
463 if (empty($error)) {
464 $this->dom_builded = true;
465 return true;
466 } else {
467 return $error;
468 }
469 }
470
471 public function freeDom()
472 {
473 //$this->dom->free();
474 unset($this->dom);
475 }
476
480 public function getDom()
481 {
482 return $this->dom;
483 }
484
490 public function getDomDoc()
491 {
492 if ($this->dom instanceof php4DOMDocument) {
493 return $this->dom->myDOMDocument;
494 }
495
496 return $this->dom;
497 }
498
502 public function setId($a_id)
503 {
504 $this->id = $a_id;
505 }
506
507 public function getId()
508 {
509 return $this->id;
510 }
511
512 public function setParentId($a_id)
513 {
514 $this->parent_id = $a_id;
515 }
516
517 public function getParentId()
518 {
519 return $this->parent_id;
520 }
521
522 public function addUpdateListener(&$a_object, $a_method, $a_parameters = "")
523 {
525 $this->update_listeners[$cnt]["object"] = $a_object;
526 $this->update_listeners[$cnt]["method"] = $a_method;
527 $this->update_listeners[$cnt]["parameters"] = $a_parameters;
528 $this->update_listener_cnt++;
529 }
530
531 public function callUpdateListeners()
532 {
533 for ($i = 0; $i < $this->update_listener_cnt; $i++) {
534 $object = $this->update_listeners[$i]["object"];
535 $method = $this->update_listeners[$i]["method"];
536 $parameters = $this->update_listeners[$i]["parameters"];
537 $object->$method($parameters);
538 }
539 }
540
545 public function setActive($a_active)
546 {
547 $this->active = $a_active;
548 }
549
554 public function getActive($a_check_scheduled_activation = false)
555 {
556 if ($a_check_scheduled_activation && !$this->active) {
557 include_once("./Services/Calendar/classes/class.ilDateTime.php");
558 $start = new ilDateTime($this->getActivationStart(), IL_CAL_DATETIME);
559 $end = new ilDateTime($this->getActivationEnd(), IL_CAL_DATETIME);
560 $now = new ilDateTime(time(), IL_CAL_UNIX);
561 if (!ilDateTime::_before($now, $start) && !ilDateTime::_after($now, $end)) {
562 return true;
563 }
564 }
565 return $this->active;
566 }
567
572 public static function preloadActivationDataByParentId($a_parent_id)
573 {
574 global $DIC;
575
576 $db = $DIC->database();
577 $set = $db->query(
578 "SELECT page_id, parent_type, lang, active, activation_start, activation_end, show_activation_info FROM page_object " .
579 " WHERE parent_id = " . $db->quote($a_parent_id, "integer")
580 );
581 while ($rec = $db->fetchAssoc($set)) {
582 self::$activation_data[$rec["page_id"] . ":" . $rec["parent_type"] . ":" . $rec["lang"]] = $rec;
583 }
584 }
585
589 public static function _lookupActive($a_id, $a_parent_type, $a_check_scheduled_activation = false, $a_lang = "-")
590 {
591 global $DIC;
592
593 $db = $DIC->database();
594
595 // language must be set at least to "-"
596 if ($a_lang == "") {
597 $a_lang = "-";
598 }
599
600 if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
601 $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
602 } else {
603 $set = $db->queryF(
604 "SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s" .
605 " AND parent_type = %s AND lang = %s",
606 array("integer", "text", "text"),
607 array($a_id, $a_parent_type, $a_lang)
608 );
609 $rec = $db->fetchAssoc($set);
610 }
611
612 $rec["n"] = ilUtil::now();
613
614 if (!$rec["active"] && $a_check_scheduled_activation) {
615 if ($rec["n"] >= $rec["activation_start"] &&
616 $rec["n"] <= $rec["activation_end"]) {
617 return true;
618 }
619 }
620
621 return $rec["active"];
622 }
623
627 public static function _isScheduledActivation($a_id, $a_parent_type, $a_lang = "-")
628 {
629 global $DIC;
630
631 $db = $DIC->database();
632
633 // language must be set at least to "-"
634 if ($a_lang == "") {
635 $a_lang = "-";
636 }
637
638 //echo "<br>";
639 //var_dump(self::$activation_data); exit;
640 if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
641 $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
642 } else {
643 $set = $db->queryF(
644 "SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s" .
645 " AND parent_type = %s AND lang = %s",
646 array("integer", "text", "text"),
647 array($a_id, $a_parent_type, $a_lang)
648 );
649 $rec = $db->fetchAssoc($set);
650 }
651
652 if (!$rec["active"] && $rec["activation_start"] != "") {
653 return true;
654 }
655
656 return false;
657 }
658
662 public static function _writeActive(
663 $a_id,
664 $a_parent_type,
665 $a_active,
666 $a_reset_scheduled_activation = true,
667 $a_lang = "-"
668 ) {
669 global $DIC;
670
671 $db = $DIC->database();
672
673 // language must be set at least to "-"
674 if ($a_lang == "") {
675 $a_lang = "-";
676 }
677
678 if ($a_reset_scheduled_activation) {
679 $st = $db->manipulateF(
680 "UPDATE page_object SET active = %s, activation_start = %s, " .
681 " activation_end = %s WHERE page_id = %s" .
682 " AND parent_type = %s AND lang = %s",
683 array("boolean", "timestamp", "timestamp", "integer", "text", "text"),
684 array($a_active, null, null, $a_id, $a_parent_type, $a_lang)
685 );
686 } else {
687 $st = $db->prepareManip(
688 "UPDATE page_object SET active = %s WHERE page_id = %s" .
689 " AND parent_type = %s AND lang = %s",
690 array("boolean", "integer", "text", "text"),
691 array($a_active, $a_id, $a_parent_type, $a_lang)
692 );
693 }
694 }
695
699 public static function _lookupActivationData($a_id, $a_parent_type, $a_lang = "-")
700 {
701 global $DIC;
702
703 $db = $DIC->database();
704
705 // language must be set at least to "-"
706 if ($a_lang == "") {
707 $a_lang = "-";
708 }
709
710 if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
711 $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
712 } else {
713 $set = $db->queryF(
714 "SELECT active, activation_start, activation_end, show_activation_info FROM page_object WHERE page_id = %s" .
715 " AND parent_type = %s AND lang = %s",
716 array("integer", "text", "text"),
717 array($a_id, $a_parent_type, $a_lang)
718 );
719 $rec = $db->fetchAssoc($set);
720 }
721
722 return $rec;
723 }
724
728 public static function lookupParentId($a_id, $a_type)
729 {
730 global $DIC;
731
732 $db = $DIC->database();
733
734 $res = $db->query("SELECT parent_id FROM page_object WHERE page_id = " . $db->quote($a_id, "integer") . " " .
735 "AND parent_type=" . $db->quote($a_type, "text"));
736 $rec = $db->fetchAssoc($res);
737 return $rec["parent_id"];
738 }
739
743 public static function _writeParentId($a_parent_type, $a_pg_id, $a_par_id)
744 {
745 global $DIC;
746
747 $db = $DIC->database();
748 $db->manipulateF(
749 "UPDATE page_object SET parent_id = %s WHERE page_id = %s" .
750 " AND parent_type = %s",
751 array("integer", "integer", "text"),
752 array($a_par_id, $a_pg_id, $a_parent_type)
753 );
754 }
755
760 public function setActivationStart($a_activationstart)
761 {
762 if ($a_activationstart == "") {
763 $a_activationstart = null;
764 }
765 $this->activationstart = $a_activationstart;
766 }
767
772 public function getActivationStart()
773 {
774 return $this->activationstart;
775 }
776
781 public function setActivationEnd($a_activationend)
782 {
783 if ($a_activationend == "") {
784 $a_activationend = null;
785 }
786 $this->activationend = $a_activationend;
787 }
788
793 public function getActivationEnd()
794 {
795 return $this->activationend;
796 }
797
804 public function getContentObject($a_hier_id, $a_pc_id = "")
805 {
806 $cont_node = $this->getContentNode($a_hier_id, $a_pc_id);
807 if (!is_object($cont_node)) {
808 return false;
809 }
810 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
811 $node_name = $cont_node->node_name();
812 if (in_array($node_name, ["PageObject", "TableRow"])) {
813 return null;
814 }
815 if ($node_name == "PageContent") {
816 $child_node = $cont_node->first_child();
817 $node_name = $child_node->node_name();
818 }
819
820 // table extra handling (@todo: get rid of it)
821 if ($node_name == "Table") {
822 if ($child_node->get_attribute("DataTable") == "y") {
823 require_once("./Services/COPage/classes/class.ilPCDataTable.php");
824 $tab = new ilPCDataTable($this);
825 $tab->setNode($cont_node);
826 $tab->setHierId($a_hier_id);
827 } else {
828 require_once("./Services/COPage/classes/class.ilPCTable.php");
829 $tab = new ilPCTable($this);
830 $tab->setNode($cont_node);
831 $tab->setHierId($a_hier_id);
832 }
833 $tab->setPcId($a_pc_id);
834 return $tab;
835 }
836
837 // media extra handling (@todo: get rid of it)
838 if ($node_name == "MediaObject") {
839 if ($_GET["pgEdMediaMode"] != "") {
840 echo "ilPageObject::error media";
841 exit;
842 }
843
844 //require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
845 require_once("./Services/COPage/classes/class.ilPCMediaObject.php");
846
847 $mal_node = $child_node->first_child();
848 //echo "ilPageObject::getContentObject:nodename:".$mal_node->node_name().":<br>";
849 $id_arr = explode("_", $mal_node->get_attribute("OriginId"));
850 $mob_id = $id_arr[count($id_arr) - 1];
851
852 // allow deletion of non-existing media objects
853 if (!ilObject::_exists($mob_id) && in_array("delete", $_POST)) {
854 $mob_id = 0;
855 }
856
857 // see also #32331
858 if (ilObject::_lookupType($mob_id) !== "mob") {
859 $mob_id = 0;
860 }
861
862 //$mob = new ilObjMediaObject($mob_id);
863 $mob = new ilPCMediaObject($this);
864 $mob->readMediaObject($mob_id);
865
866 //$mob->setDom($this->dom);
867 $mob->setNode($cont_node);
868 $mob->setHierId($a_hier_id);
869 $mob->setPcId($a_pc_id);
870 return $mob;
871 }
872
873 //
874 // generic procedure
875 //
876
877 $pc_def = ilCOPagePCDef::getPCDefinitionByName($node_name);
878
879 // check if pc definition has been found
880 if (!is_array($pc_def)) {
881 include_once("./Services/COPage/exceptions/class.ilCOPageUnknownPCTypeException.php");
882 throw new ilCOPageUnknownPCTypeException('Unknown PC Name "' . $node_name . '".');
883 }
884 $pc_class = "ilPC" . $pc_def["name"];
885 $pc_path = "./" . $pc_def["component"] . "/" . $pc_def["directory"] . "/class." . $pc_class . ".php";
886 require_once($pc_path);
887 $pc = new $pc_class($this);
888 $pc->setNode($cont_node);
889 $pc->setHierId($a_hier_id);
890 $pc->setPcId($a_pc_id);
891 return $pc;
892 }
893
899 public function getContentObjectForPcId($pcid)
900 {
901 $hier_ids = $this->getHierIdsForPCIds([$pcid]);
902 return $this->getContentObject($hier_ids[$pcid], $pcid);
903 }
904
911 public function getParentContentObjectForPcId($pcid)
912 {
913 $content_object = $this->getContentObjectForPcId($pcid);
914 $node = $content_object->getNode();
915 $node = $node->parent_node();
916 while ($node) {
917 if ($node->node_name() == "PageContent") {
918 $pcid = $node->get_attribute("PCID");
919 if ($pcid != "") {
920 return $this->getContentObjectForPcId($pcid);
921 }
922 }
923 $node = $node->parent_node();
924 }
925 return null;
926 }
927
928
934 public function &getContentNode($a_hier_id, $a_pc_id = "")
935 {
936 $xpc = xpath_new_context($this->dom);
937 if ($a_hier_id == "pg") {
938 return $this->node;
939 } else {
940 // get per pc id
941 if ($a_pc_id != "") {
942 $path = "//*[@PCID = '$a_pc_id']";
943 $res = xpath_eval($xpc, $path);
944 if (count($res->nodeset) == 1) {
945 $cont_node = $res->nodeset[0];
946 return $cont_node;
947 }
948 }
949
950 // fall back to hier id
951 $path = "//*[@HierId = '$a_hier_id']";
952 $res = xpath_eval($xpc, $path);
953 if (count($res->nodeset) == 1) {
954 $cont_node = $res->nodeset[0];
955 return $cont_node;
956 }
957 }
958 }
959
960
966 public function checkForTag($a_content_tag, $a_hier_id, $a_pc_id = "")
967 {
968 $xpc = xpath_new_context($this->dom);
969 // get per pc id
970 if ($a_pc_id != "") {
971 $path = "//*[@PCID = '$a_pc_id']//" . $a_content_tag;
972 $res = xpath_eval($xpc, $path);
973 if (count($res->nodeset) > 0) {
974 return true;
975 }
976 }
977
978 // fall back to hier id
979 $path = "//*[@HierId = '$a_hier_id']//" . $a_content_tag;
980 $res = xpath_eval($xpc, $path);
981 if (count($res->nodeset) > 0) {
982 return true;
983 }
984 return false;
985 }
986
987 // only for test purposes
988 public function lookforhier($a_hier_id)
989 {
990 $xpc = xpath_new_context($this->dom);
991 $path = "//*[@HierId = '$a_hier_id']";
992 $res = xpath_eval($xpc, $path);
993 if (count($res->nodeset) == 1) {
994 return "YES";
995 } else {
996 return "NO";
997 }
998 }
999
1000 public function &getNode()
1001 {
1002 return $this->node;
1003 }
1004
1012 public function setXMLContent($a_xml, $a_encoding = "UTF-8")
1013 {
1014 $this->encoding = $a_encoding;
1015 $this->xml = $a_xml;
1016 }
1017
1023 public function appendXMLContent($a_xml)
1024 {
1025 $this->xml .= $a_xml;
1026 }
1027
1031 public function getXMLContent($a_incl_head = false)
1032 {
1033 // build full http path for XML DOCTYPE header.
1034 // Under windows a relative path doesn't work :-(
1035 if ($a_incl_head) {
1036 //echo "+".$this->encoding."+";
1037 $enc_str = (!empty($this->encoding))
1038 ? "encoding=\"" . $this->encoding . "\""
1039 : "";
1040 return "<?xml version=\"1.0\" $enc_str ?>" .
1041 "<!DOCTYPE PageObject SYSTEM \"" . ILIAS_ABSOLUTE_PATH . "/xml/" . $this->cur_dtd . "\">" .
1042 $this->xml;
1043 } else {
1044 return $this->xml;
1045 }
1046 }
1047
1052 public function copyXmlContent($a_clone_mobs = false)
1053 {
1054 $xml = $this->getXmlContent();
1055 $temp_dom = domxml_open_mem(
1056 '<?xml version="1.0" encoding="UTF-8"?>' . $xml,
1058 $error
1059 );
1060 if (empty($error)) {
1061 $this->handleCopiedContent($temp_dom, true, $a_clone_mobs);
1062 }
1063 $xml = $temp_dom->dump_mem(0, $this->encoding);
1064 $xml = preg_replace('/<\?xml[^>]*>/i', "", $xml);
1065 $xml = preg_replace('/<!DOCTYPE[^>]*>/i', "", $xml);
1066
1067 return $xml;
1068 }
1069
1070 // @todo 1: begin: generalize, remove concrete dependencies
1071
1084 public function handleCopiedContent($a_dom, $a_self_ass = true, $a_clone_mobs = false)
1085 {
1086 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1088
1089 // handle question elements
1090 if ($a_self_ass) {
1091 $this->newQuestionCopies($a_dom);
1092 } else {
1093 $this->removeQuestions($a_dom);
1094 }
1095
1096 // handle interactive images
1097 $this->newIIMCopies($a_dom);
1098
1099 // handle media objects
1100 if ($a_clone_mobs) {
1101 $this->newMobCopies($a_dom);
1102 }
1103
1104 // @todo 1: move all functions from above to the new domdoc
1105 if ($a_dom instanceof php4DOMDocument) {
1106 $a_dom = $a_dom->myDOMDocument;
1107 }
1108 foreach ($defs as $def) {
1110 $cl = $def["pc_class"];
1111 if ($cl == 'ilPCPlugged') {
1112 // the page object is provided for ilPageComponentPlugin
1113 ilPCPlugged::handleCopiedPluggedContent($this, $a_dom);
1114 } else {
1115 $cl::handleCopiedContent($a_dom, $a_self_ass, $a_clone_mobs);
1116 }
1117 }
1118 }
1119
1126 public function handleDeleteContent($a_node = null)
1127 {
1128 if (!isset($a_node)) {
1129 $xpc = xpath_new_context($this->dom);
1130 $path = "//PageContent";
1131 $res = xpath_eval($xpc, $path);
1132 $nodes = $res->nodeset;
1133 } else {
1134 $nodes = array($a_node);
1135 }
1136
1137 require_once('Services/COPage/classes/class.ilPCPlugged.php');
1138 foreach ($nodes as $node) {
1139 if ($node instanceof php4DOMNode) {
1140 $node = $node->myDOMNode;
1141 }
1142
1144 if ($node->firstChild->nodeName == 'Plugged') {
1145 ilPCPlugged::handleDeletedPluggedNode($this, $node->firstChild);
1146 }
1147 }
1148 }
1149
1154 public function newIIMCopies($temp_dom)
1155 {
1156 // Get question IDs
1157 $path = "//InteractiveImage/MediaAlias";
1158 $xpc = xpath_new_context($temp_dom);
1159 $res = &xpath_eval($xpc, $path);
1160
1161 $q_ids = array();
1162 include_once("./Services/Link/classes/class.ilInternalLink.php");
1163 for ($i = 0; $i < count($res->nodeset); $i++) {
1164 $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1165
1166 $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1167 $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1168
1169 if (!($inst_id > 0)) {
1170 if ($mob_id > 0) {
1171 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1172 $media_object = new ilObjMediaObject($mob_id);
1173
1174 // now copy this question and change reference to
1175 // new question id
1176 $new_mob = $media_object->duplicate();
1177
1178 $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $new_mob->getId());
1179 }
1180 }
1181 }
1182 }
1183
1187 public function newMobCopies($temp_dom)
1188 {
1189 // Get question IDs
1190 $path = "//MediaObject/MediaAlias";
1191 $xpc = xpath_new_context($temp_dom);
1192 $res = &xpath_eval($xpc, $path);
1193
1194 $q_ids = array();
1195 include_once("./Services/Link/classes/class.ilInternalLink.php");
1196 for ($i = 0; $i < count($res->nodeset); $i++) {
1197 $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1198
1199 $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1200 $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1201
1202 if (!($inst_id > 0)) {
1203 if ($mob_id > 0) {
1204 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1205 $media_object = new ilObjMediaObject($mob_id);
1206
1207 // now copy this question and change reference to
1208 // new question id
1209 $new_mob = $media_object->duplicate();
1210
1211 $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $new_mob->getId());
1212 }
1213 }
1214 }
1215 }
1216
1221 public function newQuestionCopies(&$temp_dom)
1222 {
1223 // Get question IDs
1224 $path = "//Question";
1225 $xpc = xpath_new_context($temp_dom);
1226 $res = &xpath_eval($xpc, $path);
1227
1228 $q_ids = array();
1229 include_once("./Services/Link/classes/class.ilInternalLink.php");
1230 for ($i = 0; $i < count($res->nodeset); $i++) {
1231 $qref = $res->nodeset[$i]->get_attribute("QRef");
1232
1233 $inst_id = ilInternalLink::_extractInstOfTarget($qref);
1235
1236 if (!($inst_id > 0)) {
1237 if ($q_id > 0) {
1238 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1239 $question = assQuestion::_instantiateQuestion($q_id);
1240 // check due to #16557
1241 if (is_object($question) && $question->isComplete()) {
1242 // check if page for question exists
1243 // due to a bug in early 4.2.x version this is possible
1244 if (!ilPageObject::_exists("qpl", $q_id)) {
1245 $question->createPageObject();
1246 }
1247
1248 // now copy this question and change reference to
1249 // new question id
1250 $duplicate_id = $question->duplicate(false);
1251 $res->nodeset[$i]->set_attribute("QRef", "il__qst_" . $duplicate_id);
1252 }
1253 }
1254 }
1255 }
1256 }
1257
1263 public function removeQuestions(&$temp_dom)
1264 {
1265 // Get question IDs
1266 $path = "//Question";
1267 $xpc = xpath_new_context($temp_dom);
1268 $res = &xpath_eval($xpc, $path);
1269 for ($i = 0; $i < count($res->nodeset); $i++) {
1270 $parent_node = $res->nodeset[$i]->parent_node();
1271 $parent_node->unlink_node($parent_node);
1272 }
1273 }
1274
1275 // @todo: end
1276
1282 public function countPageContents()
1283 {
1284 // Get question IDs
1285 $this->buildDom();
1286 $path = "//PageContent";
1287 $xpc = xpath_new_context($this->dom);
1288 $res = &xpath_eval($xpc, $path);
1289 return count($res->nodeset);
1290 }
1291
1296 public function getXMLFromDom(
1297 $a_incl_head = false,
1298 $a_append_mobs = false,
1299 $a_append_bib = false,
1300 $a_append_str = "",
1301 $a_omit_pageobject_tag = false,
1302 $style_id = 0
1303 ) {
1304 if ($a_incl_head) {
1305 //echo "\n<br>#".$this->encoding."#";
1306 return $this->dom->dump_mem(0, $this->encoding);
1307 } else {
1308 // append multimedia object elements
1309 if ($a_append_mobs || $a_append_bib || $a_append_link_info) {
1310 $mobs = "";
1311 $bibs = "";
1312 if ($a_append_mobs) {
1313 $mobs = $this->getMultimediaXML();
1314 }
1315 if ($a_append_bib) {
1316 // deprecated
1317// $bibs = $this->getBibliographyXML();
1318 }
1319 $trans = $this->getLanguageVariablesXML($style_id);
1320 //echo htmlentities($this->dom->dump_node($this->node)); exit;
1321 return "<dummy>" . $this->dom->dump_node($this->node) . $mobs . $bibs . $trans . $a_append_str . "</dummy>";
1322 } else {
1323 if (is_object($this->dom)) {
1324 if ($a_omit_pageobject_tag) {
1325 $xml = "";
1326 $childs = $this->node->child_nodes();
1327 for ($i = 0; $i < count($childs); $i++) {
1328 $xml .= $this->dom->dump_node($childs[$i]);
1329 }
1330 return $xml;
1331 } else {
1332 $xml = $this->dom->dump_mem(0, $this->encoding);
1333 $xml = preg_replace('/<\?xml[^>]*>/i', "", $xml);
1334 $xml = preg_replace('/<!DOCTYPE[^>]*>/i', "", $xml);
1335 return $xml;
1336
1337 // don't use dump_node. This gives always entities.
1338 //return $this->dom->dump_node($this->node);
1339 }
1340 } else {
1341 return "";
1342 }
1343 }
1344 }
1345 }
1346
1350 public function getLanguageVariablesXML($style_id = 0)
1351 {
1352 $xml = "<LVs>";
1353 $lang_vars = array(
1354 "ed_paste_clip",
1355 "ed_edit",
1356 "ed_edit_prop",
1357 "ed_delete",
1358 "ed_moveafter",
1359 "ed_movebefore",
1360 "ed_go",
1361 "ed_class",
1362 "ed_width",
1363 "ed_align_left",
1364 "ed_align_right",
1365 "ed_align_center",
1366 "ed_align_left_float",
1367 "ed_align_right_float",
1368 "ed_delete_item",
1369 "ed_new_item_before",
1370 "ed_new_item_after",
1371 "ed_copy_clip",
1372 "please_select",
1373 "ed_split_page",
1374 "ed_item_up",
1375 "ed_item_down",
1376 "ed_split_page_next",
1377 "ed_enable",
1378 "de_activate",
1379 "ed_paste",
1380 "ed_edit_multiple",
1381 "ed_cut",
1382 "ed_copy",
1383 "ed_insert_templ",
1384 "ed_click_to_add_pg",
1385 "download"
1386 );
1387
1388 // collect lang vars from pc elements
1389 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1391 foreach ($defs as $def) {
1392 $lang_vars[] = "pc_" . $def["pc_type"];
1393 $lang_vars[] = "ed_insert_" . $def["pc_type"];
1394
1396 $cl = $def["pc_class"];
1397 $lvs = call_user_func($def["pc_class"] . '::getLangVars');
1398 foreach ($lvs as $lv) {
1399 $lang_vars[] = $lv;
1400 }
1401 }
1402
1403 // workaround for #30561, should go to characteristic manager
1404 $dummy_pc = new ilPCSectionGUI($this, null, "");
1405 $dummy_pc->setStyleId($style_id);
1406 foreach (["section", "table", "flist_li", "list_u", "list_o",
1407 "table", "table_cell"] as $type) {
1408 $dummy_pc->getCharacteristicsOfCurrentStyle($type);
1409 foreach ($dummy_pc->getCharacteristics() as $char => $txt) {
1410 $xml .= "<LV name=\"char_" . $type . "_" . $char . "\" value=\"" . $txt . "\"/>";
1411 }
1412 }
1413 $type = "media_cont";
1414 $dummy_pc = new ilPCMediaObjectGUI($this, null, "");
1415 $dummy_pc->setStyleId($style_id);
1416 $dummy_pc->getCharacteristicsOfCurrentStyle($type);
1417 foreach ($dummy_pc->getCharacteristics() as $char => $txt) {
1418 $xml .= "<LV name=\"char_" . $type . "_" . $char . "\" value=\"" . $txt . "\"/>";
1419 }
1420 foreach (["text_block", "heading1", "heading2", "heading3"] as $type) {
1421 $dummy_pc = new ilPCParagraphGUI($this, null, "");
1422 $dummy_pc->setStyleId($style_id);
1423 $dummy_pc->getCharacteristicsOfCurrentStyle($type);
1424 foreach ($dummy_pc->getCharacteristics() as $char => $txt) {
1425 $xml .= "<LV name=\"char_" . $type . "_" . $char . "\" value=\"" . $txt . "\"/>";
1426 }
1427 }
1428 foreach ($lang_vars as $lang_var) {
1429 $this->appendLangVarXML($xml, $lang_var);
1430 }
1431 $xml .= "</LVs>";
1432 return $xml;
1433 }
1434
1435 public function appendLangVarXML(&$xml, $var)
1436 {
1437 $val = $this->lng->txt("cont_" . $var);
1438 $val = str_replace('"', "&quot;", $val);
1439 $xml .= "<LV name=\"$var\" value=\"" . $val . "\"/>";
1440 }
1441
1442 // @todo begin: move this to paragraph class
1443
1444 public function getFirstParagraphText()
1445 {
1446 if ($this->dom) {
1447 require_once("./Services/COPage/classes/class.ilPCParagraph.php");
1448 $xpc = xpath_new_context($this->dom);
1449 $path = "//Paragraph[1]";
1450 $res = xpath_eval($xpc, $path);
1451 if (count($res->nodeset) > 0) {
1452 $cont_node = $res->nodeset[0]->parent_node();
1453 $par = new ilPCParagraph($this);
1454 $par->setNode($cont_node);
1455 $text = $par->getText();
1456
1457 return $text;
1458 }
1459 }
1460 return "";
1461 }
1462
1463 public function getParagraphForPCID($pcid)
1464 {
1465 if ($this->dom) {
1466 require_once("./Services/COPage/classes/class.ilPCParagraph.php");
1467 $xpc = xpath_new_context($this->dom);
1468 $path = "//PageContent[@PCID='" . $pcid . "']/Paragraph[1]";
1469 $res = xpath_eval($xpc, $path);
1470 if (count($res->nodeset) > 0) {
1471 $cont_node = $res->nodeset[0]->parent_node();
1472 $par = new ilPCParagraph($this);
1473 $par->setNode($cont_node);
1474 return $par;
1475 }
1476 }
1477 return null;
1478 }
1479
1480
1486 public function setParagraphContent($a_hier_id, $a_content)
1487 {
1488 $node = $this->getContentNode($a_hier_id);
1489 if (is_object($node)) {
1490 $node->set_content($a_content);
1491 }
1492 }
1493
1494 // @todo end
1495
1502 // @todo: can we do this better
1503 public function setContainsIntLink($a_contains_link)
1504 {
1505 $this->contains_int_link = $a_contains_link;
1506 }
1507
1512 // @todo: can we do this better
1513 public function containsIntLink()
1514 {
1516 }
1517
1522 public function setImportMode($a_val)
1523 {
1524 $this->import_mode = $a_val;
1525 }
1526
1531 public function getImportMode()
1532 {
1533 return $this->import_mode;
1534 }
1535
1536 public function needsImportParsing($a_parse = "")
1537 {
1538 if ($a_parse === true) {
1539 $this->needs_parsing = true;
1540 }
1541 if ($a_parse === false) {
1542 $this->needs_parsing = false;
1543 }
1544 return $this->needs_parsing;
1545 }
1546
1551 // @todo: can we do this better
1552 public function setContainsQuestion($a_val)
1553 {
1554 $this->contains_question = $a_val;
1555 }
1556
1561 public function getContainsQuestion()
1562 {
1563 return $this->contains_question;
1564 }
1565
1566
1571 // @todo: move to media class
1572 public function collectMediaObjects($a_inline_only = true)
1573 {
1574 //echo htmlentities($this->getXMLFromDom());
1575 // determine all media aliases of the page
1576 $xpc = xpath_new_context($this->dom);
1577 $path = "//MediaObject/MediaAlias";
1578 $res = xpath_eval($xpc, $path);
1579 $mob_ids = array();
1580 for ($i = 0; $i < count($res->nodeset); $i++) {
1581 $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1582 $mob_id = $id_arr[count($id_arr) - 1];
1583 $mob_ids[$mob_id] = $mob_id;
1584 }
1585
1586 // determine all media aliases of interactive images
1587 $xpc = xpath_new_context($this->dom);
1588 $path = "//InteractiveImage/MediaAlias";
1589 $res = xpath_eval($xpc, $path);
1590 for ($i = 0; $i < count($res->nodeset); $i++) {
1591 $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1592 $mob_id = $id_arr[count($id_arr) - 1];
1593 $mob_ids[$mob_id] = $mob_id;
1594 }
1595
1596 // determine all inline internal media links
1597 $xpc = xpath_new_context($this->dom);
1598 $path = "//IntLink[@Type = 'MediaObject']";
1599 $res = xpath_eval($xpc, $path);
1600
1601 for ($i = 0; $i < count($res->nodeset); $i++) {
1602 if (($res->nodeset[$i]->get_attribute("TargetFrame") == "") ||
1603 (!$a_inline_only)) {
1604 $target = $res->nodeset[$i]->get_attribute("Target");
1605 $id_arr = explode("_", $target);
1606 if (($id_arr[1] == IL_INST_ID) ||
1607 (substr($target, 0, 4) == "il__")) {
1608 $mob_id = $id_arr[count($id_arr) - 1];
1609 if (ilObject::_exists($mob_id)) {
1610 $mob_ids[$mob_id] = $mob_id;
1611 }
1612 }
1613 }
1614 }
1615
1616 return $mob_ids;
1617 }
1618
1619
1623 // @todo: can we do this better?
1624 public function getInternalLinks($a_cnt_multiple = false)
1625 {
1626 // get all internal links of the page
1627 $xpc = xpath_new_context($this->dom);
1628 $path = "//IntLink";
1629 $res = xpath_eval($xpc, $path);
1630
1631 $links = array();
1632 $cnt_multiple = 1;
1633 for ($i = 0; $i < count($res->nodeset); $i++) {
1634 $add = "";
1635 if ($a_cnt_multiple) {
1636 $add = ":" . $cnt_multiple;
1637 }
1638 $target = $res->nodeset[$i]->get_attribute("Target");
1639 $type = $res->nodeset[$i]->get_attribute("Type");
1640 $targetframe = $res->nodeset[$i]->get_attribute("TargetFrame");
1641 $anchor = $res->nodeset[$i]->get_attribute("Anchor");
1642 $links[$target . ":" . $type . ":" . $targetframe . ":" . $anchor . $add] =
1643 array("Target" => $target,
1644 "Type" => $type,
1645 "TargetFrame" => $targetframe,
1646 "Anchor" => $anchor
1647 );
1648
1649 // get links (image map areas) for inline media objects
1650 if ($type == "MediaObject" && $targetframe == "") {
1651 if (substr($target, 0, 4) == "il__") {
1652 $id_arr = explode("_", $target);
1653 $id = $id_arr[count($id_arr) - 1];
1654
1656 foreach ($med_links as $key => $med_link) {
1657 $links[$key] = $med_link;
1658 }
1659 }
1660 }
1661 //echo "<br>-:".$target.":".$type.":".$targetframe.":-";
1662 $cnt_multiple++;
1663 }
1664 unset($xpc);
1665
1666 // get all media aliases
1667 $xpc = xpath_new_context($this->dom);
1668 $path = "//MediaAlias";
1669 $res = xpath_eval($xpc, $path);
1670
1671 require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
1672 for ($i = 0; $i < count($res->nodeset); $i++) {
1673 $oid = $res->nodeset[$i]->get_attribute("OriginId");
1674 if (substr($oid, 0, 4) == "il__") {
1675 $id_arr = explode("_", $oid);
1676 $id = $id_arr[count($id_arr) - 1];
1677
1679 foreach ($med_links as $key => $med_link) {
1680 $links[$key] = $med_link;
1681 }
1682 }
1683 }
1684 unset($xpc);
1685
1686 return $links;
1687 }
1688
1693 // @todo: move to media class
1694 public function getMultimediaXML()
1695 {
1696 $mob_ids = $this->collectMediaObjects();
1697
1698 // get xml of corresponding media objects
1699 $mobs_xml = "";
1700 require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1701 foreach ($mob_ids as $mob_id => $dummy) {
1702 if (ilObject::_lookupType($mob_id) == "mob") {
1703 $mob_obj = new ilObjMediaObject($mob_id);
1704 $mobs_xml .= $mob_obj->getXML(IL_MODE_OUTPUT, $a_inst = 0, true);
1705 }
1706 }
1707 //var_dump($mobs_xml);
1708 return $mobs_xml;
1709 }
1710
1714 // @todo: move to media class
1715 public function getMediaAliasElement($a_mob_id, $a_nr = 1)
1716 {
1717 $xpc = xpath_new_context($this->dom);
1718 $path = "//MediaObject/MediaAlias[@OriginId='il__mob_$a_mob_id']";
1719 $res = xpath_eval($xpc, $path);
1720 $mal_node = $res->nodeset[$a_nr - 1];
1721 $mob_node = $mal_node->parent_node();
1722
1723 return $this->dom->dump_node($mob_node);
1724 }
1725
1730 public function validateDom(bool $throw = false)
1731 {
1732 $this->stripHierIDs();
1733
1734 // possible fix for #14820
1735 libxml_disable_entity_loader(false);
1736
1737 $error = null;
1738 $this->dom->validate($error, $throw);
1739 //var_dump($this->dom); exit;
1740 return $error;
1741 }
1742
1755 // @todo: can we do this better? remove dependencies?
1756 public function addHierIDs()
1757 {
1758 $this->hier_ids = array();
1759 $this->first_row_ids = array();
1760 $this->first_col_ids = array();
1761 $this->list_item_ids = array();
1762 $this->file_item_ids = array();
1763
1764 // set hierarchical ids for Paragraphs, Tables, TableRows and TableData elements
1765 $xpc = xpath_new_context($this->dom);
1766 //$path = "//Paragraph | //Table | //TableRow | //TableData";
1767
1768 $sep = $path = "";
1769 foreach ($this->id_elements as $el) {
1770 $path .= $sep . "//" . $el;
1771 $sep = " | ";
1772 }
1773
1774 $res = xpath_eval($xpc, $path);
1775 for ($i = 0; $i < count($res->nodeset); $i++) {
1776 $cnode = $res->nodeset[$i];
1777 $ctag = $cnode->node_name();
1778
1779 // get hierarchical id of previous sibling
1780 $sib_hier_id = "";
1781 while ($cnode = $cnode->previous_sibling()) {
1782 if (($cnode->node_type() == XML_ELEMENT_NODE)
1783 && $cnode->has_attribute("HierId")) {
1784 $sib_hier_id = $cnode->get_attribute("HierId");
1785 //$sib_hier_id = $id_attr->value();
1786 break;
1787 }
1788 }
1789
1790 if ($sib_hier_id != "") { // set id to sibling id "+ 1"
1791 require_once("./Services/COPage/classes/class.ilPageContent.php");
1792 $node_hier_id = ilPageContent::incEdId($sib_hier_id);
1793 $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1794 $this->hier_ids[] = $node_hier_id;
1795 if ($ctag == "TableData") {
1796 if (substr($par_hier_id, strlen($par_hier_id) - 2) == "_1") {
1797 $this->first_row_ids[] = $node_hier_id;
1798 }
1799 }
1800 if ($ctag == "ListItem") {
1801 $this->list_item_ids[] = $node_hier_id;
1802 }
1803 if ($ctag == "FileItem") {
1804 $this->file_item_ids[] = $node_hier_id;
1805 }
1806 } else { // no sibling -> node is first child
1807 // get hierarchical id of next parent
1808 $cnode = $res->nodeset[$i];
1809 $par_hier_id = "";
1810 while ($cnode = $cnode->parent_node()) {
1811 if (($cnode->node_type() == XML_ELEMENT_NODE)
1812 && $cnode->has_attribute("HierId")) {
1813 $par_hier_id = $cnode->get_attribute("HierId");
1814 //$par_hier_id = $id_attr->value();
1815 break;
1816 }
1817 }
1818 //echo "<br>par:".$par_hier_id." ($ctag)";
1819 if (($par_hier_id != "") && ($par_hier_id != "pg")) { // set id to parent_id."_1"
1820 $node_hier_id = $par_hier_id . "_1";
1821 $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1822 $this->hier_ids[] = $node_hier_id;
1823 if ($ctag == "TableData") {
1824 $this->first_col_ids[] = $node_hier_id;
1825 if (substr($par_hier_id, strlen($par_hier_id) - 2) == "_1") {
1826 $this->first_row_ids[] = $node_hier_id;
1827 }
1828 }
1829 if ($ctag == "ListItem") {
1830 $this->list_item_ids[] = $node_hier_id;
1831 }
1832 if ($ctag == "FileItem") {
1833 $this->file_item_ids[] = $node_hier_id;
1834 }
1835 } else { // no sibling, no parent -> first node
1836 $node_hier_id = "1";
1837 $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1838 $this->hier_ids[] = $node_hier_id;
1839 }
1840 }
1841 }
1842
1843 // set special hierarchical id "pg" for pageobject
1844 $xpc = xpath_new_context($this->dom);
1845 $path = "//PageObject";
1846 $res = xpath_eval($xpc, $path);
1847 for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1848 $res->nodeset[$i]->set_attribute("HierId", "pg");
1849 $this->hier_ids[] = "pg";
1850 }
1851 unset($xpc);
1852 }
1853
1857 public function getHierIds()
1858 {
1859 return $this->hier_ids;
1860 }
1861
1865 // @todo: move to table classes
1866 public function getFirstRowIds()
1867 {
1868 return $this->first_row_ids;
1869 }
1870
1874 // @todo: move to table classes
1875 public function getFirstColumnIds()
1876 {
1877 return $this->first_col_ids;
1878 }
1879
1883 // @todo: move to list class
1884 public function getListItemIds()
1885 {
1886 return $this->list_item_ids;
1887 }
1888
1892 // @todo: move to file item class
1893 public function getFileItemIds()
1894 {
1895 return $this->file_item_ids;
1896 }
1897
1901 public function stripHierIDs()
1902 {
1903 if (is_object($this->dom)) {
1904 $xpc = xpath_new_context($this->dom);
1905 $path = "//*[@HierId]";
1906 $res = xpath_eval($xpc, $path);
1907 for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1908 if ($res->nodeset[$i]->has_attribute("HierId")) {
1909 $res->nodeset[$i]->remove_attribute("HierId");
1910 }
1911 }
1912 unset($xpc);
1913 }
1914 }
1915
1919 public function getHierIdsForPCIds($a_pc_ids)
1920 {
1921 if (!is_array($a_pc_ids) || count($a_pc_ids) == 0) {
1922 return array();
1923 }
1924 $ret = array();
1925
1926 if (is_object($this->dom)) {
1927 $xpc = xpath_new_context($this->dom);
1928 $path = "//*[@PCID]";
1929 $res = xpath_eval($xpc, $path);
1930 for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1931 $pc_id = $res->nodeset[$i]->get_attribute("PCID");
1932 if (in_array($pc_id, $a_pc_ids)) {
1933 $ret[$pc_id] = $res->nodeset[$i]->get_attribute("HierId");
1934 }
1935 }
1936 unset($xpc);
1937 }
1938 //var_dump($ret);
1939 return $ret;
1940 }
1941
1942 public function getHierIdForPcId($pcid)
1943 {
1944 $hier_ids = $this->getHierIdsForPCIds([$pcid]);
1945 return $hier_ids[$pcid];
1946 }
1947
1951 public function getPCIdsForHierIds($hier_ids)
1952 {
1953 if (!is_array($hier_ids) || count($hier_ids) == 0) {
1954 return [];
1955 }
1956 $ret = [];
1957 $this->addHierIDs();
1958 if (is_object($this->dom)) {
1959 $xpc = xpath_new_context($this->dom);
1960 $path = "//*[@HierId]";
1961 $res = xpath_eval($xpc, $path);
1962 for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1963 $hier_id = $res->nodeset[$i]->get_attribute("HierId");
1964 if (in_array($hier_id, $hier_ids)) {
1965 $ret[$hier_id] = $res->nodeset[$i]->get_attribute("PCID");
1966 }
1967 }
1968 unset($xpc);
1969 }
1970 return $ret;
1971 }
1972
1973 public function getPCIdForHierId($hier_id)
1974 {
1975 $hier_ids = $this->getPCIdsForHierIds([$hier_id]);
1976 return $hier_ids[$hier_id];
1977 }
1978
1982 // @todo: move to file item class
1983 public function addFileSizes()
1984 {
1985 $xpc = xpath_new_context($this->dom);
1986 $path = "//FileItem";
1987 $res = xpath_eval($xpc, $path);
1988 for ($i = 0; $i < count($res->nodeset); $i++) {
1989 $cnode = $res->nodeset[$i];
1990 $size_node = $this->dom->create_element("Size");
1991 $size_node = $cnode->append_child($size_node);
1992
1993 $childs = $cnode->child_nodes();
1994 $size = "";
1995 for ($j = 0; $j < count($childs); $j++) {
1996 if ($childs[$j]->node_name() == "Identifier") {
1997 if ($childs[$j]->has_attribute("Entry")) {
1998 $entry = $childs[$j]->get_attribute("Entry");
1999 $entry_arr = explode("_", $entry);
2000 $id = $entry_arr[count($entry_arr) - 1];
2001 require_once("./Modules/File/classes/class.ilObjFile.php");
2003 }
2004 }
2005 }
2006 $size_node->set_content($size);
2007 }
2008
2009 unset($xpc);
2010 }
2011
2016 // @todo: possible to improve this?
2017 public function resolveIntLinks($a_link_map = null)
2018 {
2019 $changed = false;
2020
2021 $this->log->debug("start");
2022
2023 // resolve normal internal links
2024 $xpc = xpath_new_context($this->dom);
2025 $path = "//IntLink";
2026 $res = xpath_eval($xpc, $path);
2027 for ($i = 0; $i < count($res->nodeset); $i++) {
2028 $target = $res->nodeset[$i]->get_attribute("Target");
2029 $type = $res->nodeset[$i]->get_attribute("Type");
2030
2031 if ($a_link_map == null) {
2032 $new_target = ilInternalLink::_getIdForImportId($type, $target);
2033 $this->log->debug("no map, type: " . $type . ", target: " . $target . ", new target: " . $new_target);
2034 } else {
2035 $nt = explode("_", $a_link_map[$target]);
2036 $new_target = false;
2037 if ($nt[1] == IL_INST_ID) {
2038 $new_target = "il__" . $nt[2] . "_" . $nt[3];
2039 }
2040 $this->log->debug("map, type: " . $type . ", target: " . $target . ", new target: " . $new_target);
2041 }
2042 if ($new_target !== false) {
2043 $res->nodeset[$i]->set_attribute("Target", $new_target);
2044 $changed = true;
2045 } else { // check wether link target is same installation
2047 IL_INST_ID > 0 && $type != "RepositoryItem") {
2048 $new_target = ilInternalLink::_removeInstFromTarget($target);
2049 if (ilInternalLink::_exists($type, $new_target)) {
2050 $res->nodeset[$i]->set_attribute("Target", $new_target);
2051 $changed = true;
2052 }
2053 }
2054 }
2055 }
2056 unset($xpc);
2057
2058 // resolve internal links in map areas
2059 $xpc = xpath_new_context($this->dom);
2060 $path = "//MediaAlias";
2061 $res = xpath_eval($xpc, $path);
2062 //echo "<br><b>page::resolve</b><br>";
2063 //echo "Content:".htmlentities($this->getXMLFromDOM()).":<br>";
2064 for ($i = 0; $i < count($res->nodeset); $i++) {
2065 $orig_id = $res->nodeset[$i]->get_attribute("OriginId");
2066 $id_arr = explode("_", $orig_id);
2067 $mob_id = $id_arr[count($id_arr) - 1];
2069 }
2070 return $changed;
2071 }
2072
2078 // @todo: move to media classes?
2079 public function resolveMediaAliases($a_mapping, $a_reuse_existing_by_import = false)
2080 {
2081 // resolve normal internal links
2082 $xpc = xpath_new_context($this->dom);
2083 $path = "//MediaAlias";
2084 $res = xpath_eval($xpc, $path);
2085 $changed = false;
2086 for ($i = 0; $i < count($res->nodeset); $i++) {
2087 // get the ID of the import file from the xml
2088 $old_id = $res->nodeset[$i]->get_attribute("OriginId");
2089 $old_id = explode("_", $old_id);
2090 $old_id = $old_id[count($old_id) - 1];
2091 $new_id = "";
2092 $import_id = "";
2093 // get the new id from the current mapping
2094 if ($a_mapping[$old_id] > 0) {
2095 $new_id = $a_mapping[$old_id];
2096 if ($a_reuse_existing_by_import) {
2097 // this should work, if the lm has been imported in a translation installation and re-exported
2098 $import_id = ilObject::_lookupImportId($new_id);
2099 $imp = explode("_", $import_id);
2100 if ($imp[1] == IL_INST_ID && $imp[2] == "mob" && ilObject::_lookupType($imp[3]) == "mob") {
2101 $new_id = $imp[3];
2102 }
2103 }
2104 }
2105 // now check, if the translation has been done just by changing text in the exported
2106 // translation file
2107 if ($import_id == "" && $a_reuse_existing_by_import) {
2108 // if the old_id is also referred by the page content of the default language
2109 // we assume that this media object is unchanged
2110 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2111 $med_of_def_lang = ilObjMediaObject::_getMobsOfObject(
2112 $this->getParentType() . ":pg",
2113 $this->getId(),
2114 0,
2115 "-"
2116 );
2117 if (in_array($old_id, $med_of_def_lang)) {
2118 $new_id = $old_id;
2119 }
2120 }
2121 if ($new_id != "") {
2122 $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $new_id);
2123 $changed = true;
2124 }
2125 }
2126 unset($xpc);
2127 return $changed;
2128 }
2129
2135 // @todo: move to iim classes?
2136 public function resolveIIMMediaAliases($a_mapping)
2137 {
2138 // resolve normal internal links
2139 $xpc = xpath_new_context($this->dom);
2140 $path = "//InteractiveImage/MediaAlias";
2141 $res = xpath_eval($xpc, $path);
2142 $changed = false;
2143 for ($i = 0; $i < count($res->nodeset); $i++) {
2144 $old_id = $res->nodeset[$i]->get_attribute("OriginId");
2145 if ($a_mapping[$old_id] > 0) {
2146 $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $a_mapping[$old_id]);
2147 $changed = true;
2148 }
2149 }
2150 unset($xpc);
2151
2152 return $changed;
2153 }
2154
2160 // @todo: move to file classes?
2161 public function resolveFileItems($a_mapping)
2162 {
2163 // resolve normal internal links
2164 $xpc = xpath_new_context($this->dom);
2165 $path = "//FileItem/Identifier";
2166 $res = xpath_eval($xpc, $path);
2167 $changed = false;
2168 for ($i = 0; $i < count($res->nodeset); $i++) {
2169 $old_id = $res->nodeset[$i]->get_attribute("Entry");
2170 $old_id = explode("_", $old_id);
2171 $old_id = $old_id[count($old_id) - 1];
2172 if ($a_mapping[$old_id] > 0) {
2173 $res->nodeset[$i]->set_attribute("Entry", "il__file_" . $a_mapping[$old_id]);
2174 $changed = true;
2175 }
2176 }
2177 unset($xpc);
2178
2179 return $changed;
2180 }
2181
2186 // @todo: move to question classes
2187 public function resolveQuestionReferences($a_mapping)
2188 {
2189 // resolve normal internal links
2190 $xpc = xpath_new_context($this->dom);
2191 $path = "//Question";
2192 $res = xpath_eval($xpc, $path);
2193 $updated = false;
2194 for ($i = 0; $i < count($res->nodeset); $i++) {
2195 $qref = $res->nodeset[$i]->get_attribute("QRef");
2196
2197 if (isset($a_mapping[$qref])) {
2198 $res->nodeset[$i]->set_attribute("QRef", "il__qst_" . $a_mapping[$qref]["pool"]);
2199 $updated = true;
2200 }
2201 }
2202 unset($xpc);
2203
2204 return $updated;
2205 }
2206
2207
2213 // @todo: generalize, internal links usage info
2214 public function moveIntLinks($a_from_to)
2215 {
2216 $this->buildDom();
2217
2218 $changed = false;
2219 // resolve normal internal links
2220 $xpc = xpath_new_context($this->dom);
2221 $path = "//IntLink";
2222 $res = xpath_eval($xpc, $path);
2223 for ($i = 0; $i < count($res->nodeset); $i++) {
2224 $target = $res->nodeset[$i]->get_attribute("Target");
2225 $type = $res->nodeset[$i]->get_attribute("Type");
2226 $obj_id = ilInternalLink::_extractObjIdOfTarget($target);
2227 if ($a_from_to[$obj_id] > 0 && is_int(strpos($target, "__"))) {
2228 if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg") {
2229 $res->nodeset[$i]->set_attribute("Target", "il__pg_" . $a_from_to[$obj_id]);
2230 $changed = true;
2231 }
2232 if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st") {
2233 $res->nodeset[$i]->set_attribute("Target", "il__st_" . $a_from_to[$obj_id]);
2234 $changed = true;
2235 }
2236 if ($type == "PortfolioPage") {
2237 $res->nodeset[$i]->set_attribute("Target", "il__ppage_" . $a_from_to[$obj_id]);
2238 $changed = true;
2239 }
2240 if ($type == "WikiPage") {
2241 $res->nodeset[$i]->set_attribute("Target", "il__wpage_" . $a_from_to[$obj_id]);
2242 $changed = true;
2243 }
2244 }
2245 }
2246 unset($xpc);
2247
2248 // map areas
2249 $this->addHierIDs();
2250 $xpc = xpath_new_context($this->dom);
2251 $path = "//MediaAlias";
2252 $res = xpath_eval($xpc, $path);
2253
2254 require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
2255 require_once("Services/COPage/classes/class.ilMediaAliasItem.php");
2256
2257 for ($i = 0; $i < count($res->nodeset); $i++) {
2258 $media_object_node = $res->nodeset[$i]->parent_node();
2259 $page_content_node = $media_object_node->parent_node();
2260 $c_hier_id = $page_content_node->get_attribute("HierId");
2261
2262 // first check, wheter we got instance map areas -> take these
2263 $std_alias_item = new ilMediaAliasItem(
2264 $this->dom,
2265 $c_hier_id,
2266 "Standard"
2267 );
2268 $areas = $std_alias_item->getMapAreas();
2269 $correction_needed = false;
2270 if (count($areas) > 0) {
2271 // check if correction needed
2272 foreach ($areas as $area) {
2273 if ($area["Type"] == "PageObject" ||
2274 $area["Type"] == "StructureObject") {
2275 $t = $area["Target"];
2276 $tid = _extractObjIdOfTarget($t);
2277 if ($a_from_to[$tid] > 0) {
2278 $correction_needed = true;
2279 }
2280 }
2281 }
2282 } else {
2283 $areas = array();
2284
2285 // get object map areas and check whether at least one must
2286 // be corrected
2287 $oid = $res->nodeset[$i]->get_attribute("OriginId");
2288 if (substr($oid, 0, 4) == "il__") {
2289 $id_arr = explode("_", $oid);
2290 $id = $id_arr[count($id_arr) - 1];
2291
2292 $mob = new ilObjMediaObject($id);
2293 $med_item = $mob->getMediaItem("Standard");
2294 $med_areas = $med_item->getMapAreas();
2295
2296 foreach ($med_areas as $area) {
2297 $link_type = ($area->getLinkType() == "int")
2298 ? "IntLink"
2299 : "ExtLink";
2300
2301 $areas[] = array(
2302 "Nr" => $area->getNr(),
2303 "Shape" => $area->getShape(),
2304 "Coords" => $area->getCoords(),
2305 "Link" => array(
2306 "LinkType" => $link_type,
2307 "Href" => $area->getHref(),
2308 "Title" => $area->getTitle(),
2309 "Target" => $area->getTarget(),
2310 "Type" => $area->getType(),
2311 "TargetFrame" => $area->getTargetFrame()
2312 )
2313 );
2314
2315 if ($area->getType() == "PageObject" ||
2316 $area->getType() == "StructureObject") {
2317 $t = $area->getTarget();
2319 if ($a_from_to[$tid] > 0) {
2320 $correction_needed = true;
2321 }
2322 //var_dump($a_from_to);
2323 }
2324 }
2325 }
2326 }
2327
2328 // correct map area links
2329 if ($correction_needed) {
2330 $changed = true;
2331 $std_alias_item->deleteAllMapAreas();
2332 foreach ($areas as $area) {
2333 if ($area["Link"]["LinkType"] == "IntLink") {
2334 $target = $area["Link"]["Target"];
2335 $type = $area["Link"]["Type"];
2336 $obj_id = ilInternalLink::_extractObjIdOfTarget($target);
2337 if ($a_from_to[$obj_id] > 0) {
2338 if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg") {
2339 $area["Link"]["Target"] = "il__pg_" . $a_from_to[$obj_id];
2340 }
2341 if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st") {
2342 $area["Link"]["Target"] = "il__st_" . $a_from_to[$obj_id];
2343 }
2344 }
2345 }
2346
2347 $std_alias_item->addMapArea(
2348 $area["Shape"],
2349 $area["Coords"],
2350 $area["Link"]["Title"],
2351 array("Type" => $area["Link"]["Type"],
2352 "TargetFrame" => $area["Link"]["TargetFrame"],
2353 "Target" => $area["Link"]["Target"],
2354 "Href" => $area["Link"]["Href"],
2355 "LinkType" => $area["Link"]["LinkType"],
2356 )
2357 );
2358 }
2359 }
2360 }
2361 unset($xpc);
2362
2363 return $changed;
2364 }
2365
2370 // @todo: generalize, internal links usage info
2371 public static function _handleImportRepositoryLinks($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2372 {
2373 include_once("./Services/Link/classes/class.ilInternalLink.php");
2374
2375 //echo "-".$a_rep_import_id."-".$a_rep_ref_id."-";
2377 "obj",
2378 ilInternalLink::_extractObjIdOfTarget($a_rep_import_id),
2379 ilInternalLink::_extractInstOfTarget($a_rep_import_id)
2380 );
2381 //var_dump($sources);
2382 foreach ($sources as $source) {
2383 //echo "A";
2384 if ($source["type"] == "lm:pg") {
2385 //echo "B";
2386 include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
2387 if (self::_exists("lm", $source["id"], $source["lang"])) {
2388 $page_obj = new ilLMPage($source["id"], 0, $source["lang"]);
2389 if (!$page_obj->page_not_found) {
2390 //echo "C";
2391 $page_obj->handleImportRepositoryLink(
2392 $a_rep_import_id,
2393 $a_rep_type,
2394 $a_rep_ref_id
2395 );
2396 }
2397 $page_obj->update();
2398 }
2399 }
2400 }
2401 }
2402
2403 // @todo: generalize, internal links usage info
2404 public function handleImportRepositoryLink($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2405 {
2406 $this->buildDom();
2407
2408 // resolve normal internal links
2409 $xpc = xpath_new_context($this->dom);
2410 $path = "//IntLink";
2411 $res = xpath_eval($xpc, $path);
2412 //echo "1";
2413 for ($i = 0; $i < count($res->nodeset); $i++) {
2414 //echo "2";
2415 $target = $res->nodeset[$i]->get_attribute("Target");
2416 $type = $res->nodeset[$i]->get_attribute("Type");
2417 if ($target == $a_rep_import_id && $type == "RepositoryItem") {
2418 //echo "setting:"."il__".$a_rep_type."_".$a_rep_ref_id;
2419 $res->nodeset[$i]->set_attribute(
2420 "Target",
2421 "il__" . $a_rep_type . "_" . $a_rep_ref_id
2422 );
2423 }
2424 }
2425 unset($xpc);
2426 }
2427
2433 public function handleRepositoryLinksOnCopy($a_mapping, $a_source_ref_id)
2434 {
2436 $objDefinition = $this->obj_definition;
2437
2438 $this->buildDom();
2439 $this->log->debug("Handle repository links...");
2440
2441 // resolve normal internal links
2442 $xpc = xpath_new_context($this->dom);
2443 $path = "//IntLink";
2444 $res = xpath_eval($xpc, $path);
2445 for ($i = 0; $i < count($res->nodeset); $i++) {
2446 $target = $res->nodeset[$i]->get_attribute("Target");
2447 $type = $res->nodeset[$i]->get_attribute("Type");
2448 $this->log->debug("Target: " . $target);
2449 $t = explode("_", $target);
2450 if ($type == "RepositoryItem" && ((int) $t[1] == 0 || (int) $t[1] == IL_INST_ID)) {
2451 if (isset($a_mapping[$t[3]])) {
2452 // we have a mapping -> replace the ID
2453 $this->log->debug("... replace " . $t[3] . " with " . $a_mapping[$t[3]] . ".");
2454 $res->nodeset[$i]->set_attribute(
2455 "Target",
2456 "il__obj_" . $a_mapping[$t[3]]
2457 );
2458 } elseif ($this->tree->isGrandChild($a_source_ref_id, $t[3])) {
2459 // we have no mapping, but the linked object is child of the original node -> remove link
2460 $this->log->debug("... remove links.");
2461 if ($res->nodeset[$i]->parent_node()->node_name() == "MapArea") { // simply remove map areas
2462 $parent = $res->nodeset[$i]->parent_node();
2463 $parent->unlink_node($parent);
2464 } else { // replace link by content of the link for other internal links
2465 $source_node = $res->nodeset[$i];
2466 $new_node = $source_node->clone_node(true);
2467 $new_node->unlink_node($new_node);
2468 $childs = $new_node->child_nodes();
2469 for ($j = 0; $j < count($childs); $j++) {
2470 $this->log->debug("... move node $j " . $childs[$j]->node_name() . " before " . $source_node->node_name());
2471 $source_node->insert_before($childs[$j], $source_node);
2472 }
2473 $source_node->unlink_node($source_node);
2474 }
2475 }
2476 }
2477 }
2478 unset($xpc);
2479
2480 // resolve normal external links
2481 $ilias_url = parse_url(ILIAS_HTTP_PATH);
2482 $xpc = xpath_new_context($this->dom);
2483 $path = "//ExtLink";
2484 $res = xpath_eval($xpc, $path);
2485 for ($i = 0; $i < count($res->nodeset); $i++) {
2486 $href = $res->nodeset[$i]->get_attribute("Href");
2487 $this->log->debug("Href: " . $href);
2488
2489 $url = parse_url($href);
2490
2491 // only handle links on same host
2492 $this->log->debug("Host: " . $url["host"]);
2493 if ($url["host"] != "" && $url["host"] != $ilias_url["host"]) {
2494 continue;
2495 }
2496
2497 // get parameters
2498 $par = [];
2499 if (substr($href, strlen($href) - 5) === ".html") {
2500 $parts = explode(
2501 "_",
2502 basename(
2503 substr($url["path"], 0, strlen($url["path"]) - 5)
2504 )
2505 );
2506 if (array_shift($parts) !== "goto") {
2507 continue;
2508 }
2509 $par["client_id"] = array_shift($parts);
2510 $par["target"] = implode("_", $parts);
2511 } else {
2512 foreach (explode("&", $url["query"]) as $p) {
2513 $p = explode("=", $p);
2514 $par[$p[0]] = $p[1];
2515 }
2516 }
2517
2518 $target_client_id = $par["client_id"];
2519 if ($target_client_id != "" && $target_client_id != CLIENT_ID) {
2520 continue;
2521 }
2522
2523 // get ref id
2524 $ref_id = 0;
2525 if (is_int(strpos($href, "ilias.php"))) {
2526 $ref_id = (int) $par["ref_id"];
2527 } elseif ($par["target"] !== "") {
2528 $t = explode("_", $par["target"]);
2529 if ($objDefinition->isRBACObject($t[0])) {
2530 $ref_id = (int) $t[1];
2531 $type = $t[0];
2532 }
2533 }
2534 if ($ref_id > 0) {
2535 if (isset($a_mapping[$ref_id])) {
2536 $new_ref_id = $a_mapping[$ref_id];
2537 // we have a mapping -> replace the ID
2538 if (is_int(strpos($href, "ilias.php"))) {
2539 $new_href = str_replace("ref_id=" . $par["ref_id"], "ref_id=" . $new_ref_id, $href);
2540 } else {
2541 $nt = str_replace($type . "_" . $ref_id, $type . "_" . $new_ref_id, $par["target"]);
2542 $new_href = str_replace($par["target"], $nt, $href);
2543 }
2544 if ($new_href != "") {
2545 $this->log->debug("... ext link replace " . $href . " with " . $new_href . ".");
2546 $res->nodeset[$i]->set_attribute("Href", $new_href);
2547 }
2548 } elseif ($tree->isGrandChild($a_source_ref_id, $ref_id)) {
2549 // we have no mapping, but the linked object is child of the original node -> remove link
2550 $this->log->debug("... remove ext links.");
2551 if ($res->nodeset[$i]->parent_node()->node_name() == "MapArea") { // simply remove map areas
2552 $parent = $res->nodeset[$i]->parent_node();
2553 $parent->unlink_node($parent);
2554 } else { // replace link by content of the link for other internal links
2555 $source_node = $res->nodeset[$i];
2556 $new_node = $source_node->clone_node(true);
2557 $new_node->unlink_node($new_node);
2558 $childs = $new_node->child_nodes();
2559 for ($j = 0; $j < count($childs); $j++) {
2560 $this->log->debug("... move node $j " . $childs[$j]->node_name() . " before " . $source_node->node_name());
2561 $source_node->insert_before($childs[$j], $source_node);
2562 }
2563 $source_node->unlink_node($source_node);
2564 }
2565 }
2566 }
2567 }
2568 unset($xpc);
2569 }
2570
2574 public function createFromXML()
2575 {
2576 $empty = false;
2577 if ($this->getXMLContent() == "") {
2578 $this->setXMLContent("<PageObject></PageObject>");
2579 $empty = true;
2580 }
2581
2582 $content = $this->getXMLContent();
2583 $this->buildDom(true);
2584 $dom_doc = $this->getDomDoc();
2585
2586 $errors = $this->validateDom(true);
2587
2588 $iel = $this->containsDeactivatedElements($content);
2589 $inl = $this->containsIntLinks($content);
2590
2591 // create object
2592 $this->db->insert("page_object", array(
2593 "page_id" => array("integer", $this->getId()),
2594 "parent_id" => array("integer", $this->getParentId()),
2595 "lang" => array("text", $this->getLanguage()),
2596 "content" => array("clob", $content),
2597 "parent_type" => array("text", $this->getParentType()),
2598 "create_user" => array("integer", $this->user->getId()),
2599 "last_change_user" => array("integer", $this->user->getId()),
2600 "active" => array("integer", (int) $this->getActive()),
2601 "activation_start" => array("timestamp", $this->getActivationStart()),
2602 "activation_end" => array("timestamp", $this->getActivationEnd()),
2603 "show_activation_info" => array("integer", (int) $this->getShowActivationInfo()),
2604 "inactive_elements" => array("integer", $iel),
2605 "int_links" => array("integer", $inl),
2606 "created" => array("timestamp", ilUtil::now()),
2607 "last_change" => array("timestamp", ilUtil::now()),
2608 "is_empty" => array("integer", $empty)
2609 ));
2610
2611 // after update event
2612 $this->__afterUpdate($dom_doc, $content, true, $empty);
2613 }
2614
2622 public function updateFromXML()
2623 {
2624 $this->log->debug("ilPageObject, updateFromXML(): start, id: " . $this->getId());
2625
2626 $content = $this->getXMLContent();
2627
2628 $this->log->debug("ilPageObject, updateFromXML(): content: " . substr($content, 0, 100));
2629
2630 $this->buildDom(true);
2631 $dom_doc = $this->getDomDoc();
2632
2633 $errors = $this->validateDom(true);
2634 $iel = $this->containsDeactivatedElements($content);
2635 $inl = $this->containsIntLinks($content);
2636
2637 $this->db->update("page_object", array(
2638 "content" => array("clob", $content),
2639 "parent_id" => array("integer", $this->getParentId()),
2640 "last_change_user" => array("integer", $this->user->getId()),
2641 "last_change" => array("timestamp", ilUtil::now()),
2642 "active" => array("integer", $this->getActive()),
2643 "activation_start" => array("timestamp", $this->getActivationStart()),
2644 "activation_end" => array("timestamp", $this->getActivationEnd()),
2645 "inactive_elements" => array("integer", $iel),
2646 "int_links" => array("integer", $inl),
2647 ), array(
2648 "page_id" => array("integer", $this->getId()),
2649 "parent_type" => array("text", $this->getParentType()),
2650 "lang" => array("text", $this->getLanguage())
2651 ));
2652
2653 // after update event
2654 $this->__afterUpdate($dom_doc, $content);
2655
2656 $this->log->debug("ilPageObject, updateFromXML(): end");
2657
2658 return true;
2659 }
2660
2666 final protected function __afterUpdate($a_domdoc, $a_xml, $a_creation = false, $a_empty = false)
2667 {
2668 // we do not need this if we are creating an empty page
2669 if (!$a_creation || !$a_empty) {
2670 // save internal link information
2671 // the page object is responsible to do this, since it "offers" the
2672 // internal link feature pc and page classes
2673 $this->saveInternalLinks($a_domdoc);
2674
2675 // save style usage
2676 $this->saveStyleUsage($a_domdoc);
2677
2678 // pc classes hook
2679 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2681 foreach ($defs as $def) {
2683 $cl = $def["pc_class"];
2684 call_user_func($def["pc_class"] . '::afterPageUpdate', $this, $a_domdoc, $a_xml, $a_creation);
2685 }
2686 }
2687
2688 // call page hook
2689 $this->afterUpdate($a_domdoc, $a_xml);
2690
2691 // call update listeners
2692 $this->callUpdateListeners();
2693 }
2694
2700 public function afterUpdate()
2701 {
2702 }
2703
2707 public function update($a_validate = true, $a_no_history = false)
2708 {
2709 $this->log->debug("start..., id: " . $this->getId());
2710
2711 $lm_set = new ilSetting("lm");
2712
2713 // add missing pc ids
2714 if (!$this->checkPCIds()) {
2715 $this->insertPCIds();
2716 }
2717
2718 // test validating
2719 if ($a_validate) {
2720 $errors = $this->validateDom();
2721 }
2722 //var_dump($errors); exit;
2723 if (empty($errors) && !$this->getEditLock()) {
2724 include_once("./Services/User/classes/class.ilUserUtil.php");
2725 $lock = $this->getEditLockInfo();
2726 $errors[0] = array(0 => 0,
2727 1 => $this->lng->txt("cont_not_saved_edit_lock_expired") . "<br />" .
2728 $this->lng->txt("obj_usr") . ": " .
2729 ilUserUtil::getNamePresentation($lock["edit_lock_user"]) . "<br />" .
2730 $this->lng->txt("content_until") . ": " .
2731 ilDatePresentation::formatDate(new ilDateTime($lock["edit_lock_until"], IL_CAL_UNIX))
2732 );
2733 }
2734
2735 // check for duplicate pc ids
2736 $this->log->debug("checking duplicate ids");
2737 if ($this->hasDuplicatePCIds()) {
2738 $errors[0] = $this->lng->txt("cont_could_not_save_duplicate_pc_ids") .
2739 " (" . implode(", ", $this->getDuplicatePCIds()) . ")";
2740 }
2741
2742 if (!empty($errors)) {
2743 $this->log->debug("ilPageObject, update(): errors: " . print_r($errors, true));
2744 }
2745
2746 //echo "-".htmlentities($this->getXMLFromDom())."-"; exit;
2747 if (empty($errors)) {
2748 // @todo 1: is this page type or pc content type
2749 // related -> plugins should be able to hook in!?
2750
2751 $this->log->debug("perform automatic modifications");
2753
2754 // get xml content
2755 $content = $this->getXMLFromDom();
2756 $dom_doc = $this->getDomDoc();
2757
2758 // this needs to be locked
2759
2760 // write history entry
2761 $old_set = $this->db->query("SELECT * FROM page_object WHERE " .
2762 "page_id = " . $this->db->quote($this->getId(), "integer") . " AND " .
2763 "parent_type = " . $this->db->quote($this->getParentType(), "text") . " AND " .
2764 "lang = " . $this->db->quote($this->getLanguage(), "text"));
2765 $last_nr_set = $this->db->query("SELECT max(nr) as mnr FROM page_history WHERE " .
2766 "page_id = " . $this->db->quote($this->getId(), "integer") . " AND " .
2767 "parent_type = " . $this->db->quote($this->getParentType(), "text") . " AND " .
2768 "lang = " . $this->db->quote($this->getLanguage(), "text"));
2769 $last_nr = $this->db->fetchAssoc($last_nr_set);
2770 if ($old_rec = $this->db->fetchAssoc($old_set)) {
2771 // only save, if something has changed
2772 // added user id to the check for ilias 5.0, 7.10.2014
2773 if (($content != $old_rec["content"] || $this->user->getId() != $old_rec["last_change_user"]) &&
2774 !$a_no_history && !$this->history_saved && $lm_set->get("page_history", 1)) {
2775 if ($old_rec["content"] != "<PageObject></PageObject>") {
2776 $this->db->manipulateF(
2777 "DELETE FROM page_history WHERE " .
2778 "page_id = %s AND parent_type = %s AND hdate = %s AND lang = %s",
2779 array("integer", "text", "timestamp", "text"),
2780 array($old_rec["page_id"],
2781 $old_rec["parent_type"],
2782 $old_rec["last_change"],
2783 $old_rec["lang"]
2784 )
2785 );
2786
2787 // the following lines are a workaround for
2788 // bug 6741
2789 $last_c = $old_rec["last_change"];
2790 if ($last_c == "") {
2791 $last_c = ilUtil::now();
2792 }
2793
2794 $this->db->insert("page_history", array(
2795 "page_id" => array("integer", $old_rec["page_id"]),
2796 "parent_type" => array("text", $old_rec["parent_type"]),
2797 "lang" => array("text", $old_rec["lang"]),
2798 "hdate" => array("timestamp", $last_c),
2799 "parent_id" => array("integer", $old_rec["parent_id"]),
2800 "content" => array("clob", $old_rec["content"]),
2801 "user_id" => array("integer", $old_rec["last_change_user"]),
2802 "ilias_version" => array("text", ILIAS_VERSION_NUMERIC),
2803 "nr" => array("integer", (int) $last_nr["mnr"] + 1)
2804 ));
2805
2806 $old_content = $old_rec["content"];
2807 $old_domdoc = new DOMDocument();
2808 $old_nr = $last_nr["mnr"] + 1;
2809 $old_domdoc->loadXML('<?xml version="1.0" encoding="UTF-8"?>' . $old_content);
2810
2811 // after history entry creation event
2812 $this->log->debug("calling __afterHistoryEntry");
2813 $this->__afterHistoryEntry($old_domdoc, $old_content, $old_nr);
2814
2815 $this->history_saved = true; // only save one time
2816 } else {
2817 $this->history_saved = true; // do not save on first change
2818 }
2819 }
2820 }
2821 //echo htmlentities($content);
2822 $em = (trim($content) == "<PageObject/>")
2823 ? 1
2824 : 0;
2825
2826 // @todo: pass dom instead?
2827 $this->log->debug("checking deactivated elements");
2828 $iel = $this->containsDeactivatedElements($content);
2829 $this->log->debug("checking internal links");
2830 $inl = $this->containsIntLinks($content);
2831
2832 $this->db->update("page_object", array(
2833 "content" => array("clob", $content),
2834 "parent_id" => array("integer", $this->getParentId()),
2835 "last_change_user" => array("integer", $this->user->getId()),
2836 "last_change" => array("timestamp", ilUtil::now()),
2837 "is_empty" => array("integer", $em),
2838 "active" => array("integer", $this->getActive()),
2839 "activation_start" => array("timestamp", $this->getActivationStart()),
2840 "activation_end" => array("timestamp", $this->getActivationEnd()),
2841 "show_activation_info" => array("integer", $this->getShowActivationInfo()),
2842 "inactive_elements" => array("integer", $iel),
2843 "int_links" => array("integer", $inl),
2844 ), array(
2845 "page_id" => array("integer", $this->getId()),
2846 "parent_type" => array("text", $this->getParentType()),
2847 "lang" => array("text", $this->getLanguage())
2848 ));
2849
2850 // after update event
2851 $this->log->debug("calling __afterUpdate()");
2852 $this->__afterUpdate($dom_doc, $content);
2853
2854 $this->log->debug(
2855 "...ending, updated and returning true, content: " . substr(
2856 $this->getXMLContent(),
2857 0,
2858 100
2859 )
2860 );
2861
2862 //echo "<br>PageObject::update:".htmlentities($this->getXMLContent()).":";
2863 return true;
2864 } else {
2865 return $errors;
2866 }
2867 }
2868
2872 public function delete()
2873 {
2874 $copg_logger = ilLoggerFactory::getLogger('copg');
2875 $copg_logger->debug(
2876 "ilPageObject: Delete called for ID '" . $this->getId() . "'," .
2877 " parent type: '" . $this->getParentType() . "', " .
2878 " hist nr: '" . $this->old_nr . "', " .
2879 " lang: '" . $this->getLanguage() . "', "
2880 );
2881
2882 $mobs = array();
2883 $files = array();
2884
2885 if (!$this->page_not_found) {
2886 $this->buildDom();
2887 $mobs = $this->collectMediaObjects(false);
2888 }
2889 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2890 $mobs2 = ilObjMediaObject::_getMobsOfObject($this->getParentType() . ":pg", $this->getId(), false);
2891 foreach ($mobs2 as $m) {
2892 if (!in_array($m, $mobs)) {
2893 $mobs[] = $m;
2894 }
2895 }
2896
2897 $copg_logger->debug("ilPageObject: ... found " . count($mobs) . " media objects.");
2898
2899 $this->__beforeDelete();
2900
2901 // treat plugged content
2902 $this->handleDeleteContent();
2903
2904 // delete style usages
2905 $this->deleteStyleUsages(false);
2906
2907 // delete internal links
2908 $this->deleteInternalLinks();
2909
2910 // delete all mob usages
2911 ilObjMediaObject::_deleteAllUsages($this->getParentType() . ":pg", $this->getId());
2912
2913 // delete news
2914 include_once("./Services/News/classes/class.ilNewsItem.php");
2916 $this->getParentId(),
2917 $this->getParentType(),
2918 $this->getId(),
2919 "pg"
2920 );
2921
2922 // delete page_object entry
2923 $this->db->manipulate("DELETE FROM page_object " .
2924 "WHERE page_id = " . $this->db->quote($this->getId(), "integer") .
2925 " AND parent_type= " . $this->db->quote($this->getParentType(), "text"));
2926
2927 // delete media objects
2928 foreach ($mobs as $mob_id) {
2929 $copg_logger->debug("ilPageObject: ... processing mob " . $mob_id . ".");
2930
2931 if (ilObject::_lookupType($mob_id) != 'mob') {
2932 $copg_logger->debug("ilPageObject: ... type mismatch. Ignoring mob " . $mob_id . ".");
2933 continue;
2934 }
2935
2936 if (ilObject::_exists($mob_id)) {
2937 $copg_logger->debug("ilPageObject: ... delete mob " . $mob_id . ".");
2938
2939 $mob_obj = new ilObjMediaObject($mob_id);
2940 $mob_obj->delete();
2941 } else {
2942 $copg_logger->debug("ilPageObject: ... missing mob " . $mob_id . ".");
2943 }
2944 }
2945 }
2946
2951 final protected function __beforeDelete()
2952 {
2953 // pc classes hook
2954 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2956 foreach ($defs as $def) {
2958 $cl = $def["pc_class"];
2959 call_user_func($def["pc_class"] . '::beforePageDelete', $this);
2960 }
2961 }
2962
2967 final protected function __afterHistoryEntry($a_old_domdoc, $a_old_content, $a_old_nr)
2968 {
2969 // save style usage
2970 $this->saveStyleUsage($a_old_domdoc, $a_old_nr);
2971
2972 // pc classes hook
2973 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2975 foreach ($defs as $def) {
2977 $cl = $def["pc_class"];
2978 call_user_func(
2979 $def["pc_class"] . '::afterPageHistoryEntry',
2980 $this,
2981 $a_old_domdoc,
2982 $a_old_content,
2983 $a_old_nr
2984 );
2985 }
2986 }
2987
2992 public function saveStyleUsage($a_domdoc, $a_old_nr = 0)
2993 {
2994 // media aliases
2995 $xpath = new DOMXPath($a_domdoc);
2996 $path = "//Paragraph | //Section | //MediaAlias | //FileItem" .
2997 " | //Table | //TableData | //Tabs | //List";
2998 $nodes = $xpath->query($path);
2999 $usages = array();
3000 foreach ($nodes as $node) {
3001 switch ($node->localName) {
3002 case "Paragraph":
3003 $sname = $node->getAttribute("Characteristic");
3004 $stype = "text_block";
3005 $template = 0;
3006 break;
3007
3008 case "Section":
3009 $sname = $node->getAttribute("Characteristic");
3010 $stype = "section";
3011 $template = 0;
3012 break;
3013
3014 case "MediaAlias":
3015 $sname = $node->getAttribute("Class");
3016 $stype = "media_cont";
3017 $template = 0;
3018 break;
3019
3020 case "FileItem":
3021 $sname = $node->getAttribute("Class");
3022 $stype = "flist_li";
3023 $template = 0;
3024 break;
3025
3026 case "Table":
3027 $sname = $node->getAttribute("Template");
3028 if ($sname == "") {
3029 $sname = $node->getAttribute("Class");
3030 $stype = "table";
3031 $template = 0;
3032 } else {
3033 $stype = "table";
3034 $template = 1;
3035 }
3036 break;
3037
3038 case "TableData":
3039 $sname = $node->getAttribute("Class");
3040 $stype = "table_cell";
3041 $template = 0;
3042 break;
3043
3044 case "Tabs":
3045 $sname = $node->getAttribute("Template");
3046 if ($sname != "") {
3047 if ($node->getAttribute("Type") == "HorizontalAccordion") {
3048 $stype = "haccordion";
3049 }
3050 if ($node->getAttribute("Type") == "VerticalAccordion") {
3051 $stype = "vaccordion";
3052 }
3053 }
3054 $template = 1;
3055 break;
3056
3057 case "List":
3058 $sname = $node->getAttribute("Class");
3059 if ($node->getAttribute("Type") == "Ordered") {
3060 $stype = "list_o";
3061 } else {
3062 $stype = "list_u";
3063 }
3064 $template = 0;
3065 break;
3066 }
3067 if ($sname != "" && $stype != "") {
3068 $usages[$sname . ":" . $stype . ":" . $template] = array("sname" => $sname,
3069 "stype" => $stype,
3070 "template" => $template
3071 );
3072 }
3073 }
3074
3075 $this->deleteStyleUsages($a_old_nr);
3076
3077 foreach ($usages as $u) {
3078 $id = $this->db->nextId('page_style_usage');
3079
3080 $this->db->manipulate("INSERT INTO page_style_usage " .
3081 "(id, page_id, page_type, page_lang, page_nr, template, stype, sname) VALUES (" .
3082 $this->db->quote($id, "integer") . "," .
3083 $this->db->quote($this->getId(), "integer") . "," .
3084 $this->db->quote($this->getParentType(), "text") . "," .
3085 $this->db->quote($this->getLanguage(), "text") . "," .
3086 $this->db->quote($a_old_nr, "integer") . "," .
3087 $this->db->quote($u["template"], "integer") . "," .
3088 $this->db->quote($u["stype"], "text") . "," .
3089 $this->db->quote($u["sname"], "text") .
3090 ")");
3091 }
3092 }
3093
3099 public function deleteStyleUsages($a_old_nr = 0)
3100 {
3101 if ($a_old_nr !== false) {
3102 $and_old_nr = " AND page_nr = " . $this->db->quote($a_old_nr, "integer");
3103 }
3104
3105 $this->db->manipulate(
3106 "DELETE FROM page_style_usage WHERE " .
3107 " page_id = " . $this->db->quote($this->getId(), "integer") .
3108 " AND page_type = " . $this->db->quote($this->getParentType(), "text") .
3109 " AND page_lang = " . $this->db->quote($this->getLanguage(), "text") .
3110 $and_old_nr
3111 );
3112 }
3113
3114
3119 // @todo: move to content include class
3121 {
3122 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
3123 include_once("./Modules/File/classes/class.ilObjFile.php");
3125 $this->getParentType() . ":pg",
3126 $this->getId()
3127 );
3128 $files = ilObjFile::_getFilesOfObject(
3129 $this->getParentType() . ":pg",
3130 $this->getId()
3131 );
3132 $objs = array_merge($mobs, $files);
3134 }
3135
3141 public function deleteInternalLinks()
3142 {
3143 include_once("./Services/Link/classes/class.ilInternalLink.php");
3145 $this->getParentType() . ":pg",
3146 $this->getId(),
3147 $this->getLanguage()
3148 );
3149 }
3150
3151
3156 // @todo: move to specific classes, internal link use info
3157 public function saveInternalLinks($a_domdoc)
3158 {
3159 $this->deleteInternalLinks();
3160
3161 // query IntLink elements
3162 $xpath = new DOMXPath($a_domdoc);
3163 $nodes = $xpath->query('//IntLink');
3164 foreach ($nodes as $node) {
3165 $link_type = $node->getAttribute("Type");
3166
3167 switch ($link_type) {
3168 case "StructureObject":
3169 $t_type = "st";
3170 break;
3171
3172 case "PageObject":
3173 $t_type = "pg";
3174 break;
3175
3176 case "GlossaryItem":
3177 $t_type = "git";
3178 break;
3179
3180 case "MediaObject":
3181 $t_type = "mob";
3182 break;
3183
3184 case "RepositoryItem":
3185 $t_type = "obj";
3186 break;
3187
3188 case "File":
3189 $t_type = "file";
3190 break;
3191
3192 case "WikiPage":
3193 $t_type = "wpage";
3194 break;
3195
3196 case "PortfolioPage":
3197 $t_type = "ppage";
3198 break;
3199
3200 case "User":
3201 $t_type = "user";
3202 break;
3203 }
3204
3205 $target = $node->getAttribute("Target");
3206 $target_arr = explode("_", $target);
3207 $t_id = $target_arr[count($target_arr) - 1];
3208
3209 // link to other internal object
3210 if (is_int(strpos($target, "__"))) {
3211 $t_inst = 0;
3212 } else { // link to unresolved object in other installation
3213 $t_inst = $target_arr[1];
3214 }
3215
3216 if ($t_id > 0) {
3218 $this->getParentType() . ":pg",
3219 $this->getId(),
3220 $t_type,
3221 $t_id,
3222 $t_inst,
3223 $this->getLanguage()
3224 );
3225 }
3226 }
3227 }
3228
3232 public function create()
3233 {
3234 $this->createFromXML();
3235 }
3236
3243 public function deleteContent($a_hid, $a_update = true, $a_pcid = "")
3244 {
3245 $curr_node = $this->getContentNode($a_hid, $a_pcid);
3246 $this->handleDeleteContent($curr_node);
3247 $curr_node->unlink_node($curr_node);
3248 if ($a_update) {
3249 return $this->update();
3250 }
3251 }
3252
3259 public function deleteContents($a_hids, $a_update = true, $a_self_ass = false)
3260 {
3261 if (!is_array($a_hids)) {
3262 return true;
3263 }
3264 foreach ($a_hids as $a_hid) {
3265 $a_hid = explode(":", $a_hid);
3266 //echo "-".$a_hid[0]."-".$a_hid[1]."-";
3267
3268 // @todo 1: hook
3269 // do not delete question nodes in assessment pages
3270 if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass) {
3271 $curr_node = $this->getContentNode($a_hid[0], $a_hid[1]);
3272 if (is_object($curr_node)) {
3273 $parent_node = $curr_node->parent_node();
3274 if ($parent_node->node_name() != "TableRow") {
3275 $this->handleDeleteContent($curr_node);
3276 $curr_node->unlink_node($curr_node);
3277 }
3278 }
3279 }
3280 }
3281 if ($a_update) {
3282 return $this->update();
3283 }
3284 return true;
3285 }
3286
3291 public function cutContents($a_hids)
3292 {
3293 $this->copyContents($a_hids);
3294 return $this->deleteContents($a_hids, true, $this->getPageConfig()->getEnableSelfAssessment());
3295 }
3296
3301 public function copyContents($a_hids)
3302 {
3304
3305 if (!is_array($a_hids)) {
3306 return;
3307 }
3308
3309 $time = date("Y-m-d H:i:s", time());
3310
3311 $hier_ids = array();
3312 $skip = array();
3313 foreach ($a_hids as $a_hid) {
3314 if ($a_hid == "") {
3315 continue;
3316 }
3317 $a_hid = explode(":", $a_hid);
3318
3319 // check, whether new hid is child of existing one or vice versa
3320 reset($hier_ids);
3321 foreach ($hier_ids as $h) {
3322 if ($h . "_" == substr($a_hid[0], 0, strlen($h) + 1)) {
3323 $skip[] = $a_hid[0];
3324 }
3325 if ($a_hid[0] . "_" == substr($h, 0, strlen($a_hid[0]) + 1)) {
3326 $skip[] = $h;
3327 }
3328 }
3329 $pc_id[$a_hid[0]] = $a_hid[1];
3330 if ($a_hid[0] != "") {
3331 $hier_ids[$a_hid[0]] = $a_hid[0];
3332 }
3333 }
3334 foreach ($skip as $s) {
3335 unset($hier_ids[$s]);
3336 }
3337 include_once("./Services/COPage/classes/class.ilPageContent.php");
3338 $hier_ids = ilPageContent::sortHierIds($hier_ids);
3339 $nr = 1;
3340 foreach ($hier_ids as $hid) {
3341 $curr_node = $this->getContentNode($hid, $pc_id[$hid]);
3342 if (is_object($curr_node)) {
3343 if ($curr_node->node_name() == "PageContent") {
3344 $content = $this->dom->dump_node($curr_node);
3345 // remove pc and hier ids
3346 $content = preg_replace('/PCID=\"[a-z0-9]*\"/i', "", $content);
3347 $content = preg_replace('/HierId=\"[a-z0-9_]*\"/i', "", $content);
3348
3349 $user->addToPCClipboard($content, $time, $nr);
3350 $nr++;
3351 }
3352 }
3353 }
3354 include_once("./Modules/LearningModule/classes/class.ilEditClipboard.php");
3356 }
3357
3361 public function pasteContents($a_hier_id, $a_self_ass = false)
3362 {
3364
3365 $a_hid = explode(":", $a_hier_id);
3366 $content = $user->getPCClipboardContent();
3367
3368 // we insert from last to first, because we insert all at the
3369 // same hier_id
3370 for ($i = count($content) - 1; $i >= 0; $i--) {
3371 $c = $content[$i];
3372 $temp_dom = domxml_open_mem(
3373 '<?xml version="1.0" encoding="UTF-8"?>' . $c,
3375 $error
3376 );
3377 if (empty($error)) {
3378 $this->handleCopiedContent($temp_dom, $a_self_ass);
3379 $xpc = xpath_new_context($temp_dom);
3380 $path = "//PageContent";
3381 $res = xpath_eval($xpc, $path);
3382 if (count($res->nodeset) > 0) {
3383 $new_pc_node = $res->nodeset[0];
3384 $cloned_pc_node = $new_pc_node->clone_node(true);
3385 $cloned_pc_node->unlink_node($cloned_pc_node);
3386 $this->insertContentNode(
3387 $cloned_pc_node,
3388 $a_hid[0],
3390 $a_hid[1]
3391 );
3392 }
3393 } else {
3394 //var_dump($error);
3395 }
3396 }
3397 return $this->update();
3398 }
3399
3403 public function switchEnableMultiple($a_hids, $a_update = true, $a_self_ass = false)
3404 {
3405 if (!is_array($a_hids)) {
3406 return true;
3407 }
3408
3409 foreach ($a_hids as $a_hid) {
3410 $a_hid = explode(":", $a_hid);
3411 $curr_node = $this->getContentNode($a_hid[0], $a_hid[1]);
3412 if (is_object($curr_node)) {
3413 if ($curr_node->node_name() == "PageContent") {
3414 $cont_obj = $this->getContentObject($a_hid[0], $a_hid[1]);
3415 if ($cont_obj->isEnabled()) {
3416 // do not deactivate question nodes in assessment pages
3417 if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass) {
3418 $cont_obj->disable();
3419 }
3420 } else {
3421 $cont_obj->enable();
3422 }
3423 }
3424 }
3425 }
3426
3427 if ($a_update) {
3428 return $this->update();
3429 }
3430 return true;
3431 }
3432
3439 public function deleteContentFromHierId($a_hid, $a_update = true)
3440 {
3441 $hier_ids = $this->getHierIds();
3442
3443 // iterate all hierarchical ids
3444 foreach ($hier_ids as $hier_id) {
3445 // delete top level nodes only
3446 if (!is_int(strpos($hier_id, "_"))) {
3447 if ($hier_id != "pg" && $hier_id >= $a_hid) {
3448 $curr_node = $this->getContentNode($hier_id);
3449 $this->handleDeleteContent($curr_node);
3450 $curr_node->unlink_node($curr_node);
3451 }
3452 }
3453 }
3454 if ($a_update) {
3455 return $this->update();
3456 }
3457 }
3458
3465 public function deleteContentBeforeHierId($a_hid, $a_update = true)
3466 {
3467 $hier_ids = $this->getHierIds();
3468
3469 // iterate all hierarchical ids
3470 foreach ($hier_ids as $hier_id) {
3471 // delete top level nodes only
3472 if (!is_int(strpos($hier_id, "_"))) {
3473 if ($hier_id != "pg" && $hier_id < $a_hid) {
3474 $curr_node = $this->getContentNode($hier_id);
3475 $this->handleDeleteContent($curr_node);
3476 $curr_node->unlink_node($curr_node);
3477 }
3478 }
3479 }
3480 if ($a_update) {
3481 return $this->update();
3482 }
3483 }
3484
3491 public static function _moveContentAfterHierId(&$a_source_page, &$a_target_page, $a_hid)
3492 {
3493 $hier_ids = $a_source_page->getHierIds();
3494
3495 $copy_ids = array();
3496
3497 // iterate all hierarchical ids
3498 foreach ($hier_ids as $hier_id) {
3499 // move top level nodes only
3500 if (!is_int(strpos($hier_id, "_"))) {
3501 if ($hier_id != "pg" && $hier_id >= $a_hid) {
3502 $copy_ids[] = $hier_id;
3503 }
3504 }
3505 }
3506 asort($copy_ids);
3507
3508 $parent_node = $a_target_page->getContentNode("pg");
3509 $target_dom = $a_target_page->getDom();
3510 $parent_childs = $parent_node->child_nodes();
3511 $cnt_parent_childs = count($parent_childs);
3512 //echo "-$cnt_parent_childs-";
3513 $first_child = $parent_childs[0];
3514 foreach ($copy_ids as $copy_id) {
3515 $source_node = $a_source_page->getContentNode($copy_id);
3516
3517 $new_node = $source_node->clone_node(true);
3518 $new_node->unlink_node($new_node);
3519
3520 $source_node->unlink_node($source_node);
3521
3522 if ($cnt_parent_childs == 0) {
3523 $new_node = $parent_node->append_child($new_node);
3524 } else {
3525 //$target_dom->import_node($new_node);
3526 $new_node = $first_child->insert_before($new_node, $first_child);
3527 }
3528 $parent_childs = $parent_node->child_nodes();
3529
3530 //$cnt_parent_childs++;
3531 }
3532
3533 $a_target_page->update();
3534 $a_source_page->update();
3535 }
3536
3540 public function insertContent(&$a_cont_obj, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "", bool $remove_placeholder = true)
3541 {
3542 if ($a_pcid == "" && $a_pos == "") {
3543 $a_pos = "pg";
3544 }
3545 // move mode into container elements is always INSERT_CHILD
3546 $curr_node = $this->getContentNode($a_pos, $a_pcid);
3547 $curr_name = $curr_node->node_name();
3548
3549 // @todo: try to generalize this
3550 if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3551 ($curr_name == "ListItem") || ($curr_name == "Section")
3552 || ($curr_name == "Tab") || ($curr_name == "ContentPopup")
3553 || ($curr_name == "GridCell")) {
3554 $a_mode = IL_INSERT_CHILD;
3555 }
3556
3557 $hid = $curr_node->get_attribute("HierId");
3558 if ($hid != "") {
3559 //echo "-".$a_pos."-".$hid."-";
3560 $a_pos = $hid;
3561 }
3562
3563 if ($a_mode != IL_INSERT_CHILD) { // determine parent hierarchical id
3564 // of sibling at $a_pos
3565 $pos = explode("_", $a_pos);
3566 $target_pos = array_pop($pos);
3567 $parent_pos = implode("_", $pos);
3568 } else { // if we should insert a child, $a_pos is alreade the hierarchical id
3569 // of the parent node
3570 $parent_pos = $a_pos;
3571 }
3572
3573 // get the parent node
3574 if ($parent_pos != "") {
3575 $parent_node = $this->getContentNode($parent_pos);
3576 } else {
3577 $parent_node = $this->getNode();
3578 }
3579
3580 // count the parent children
3581 $parent_childs = $parent_node->child_nodes();
3582 $cnt_parent_childs = count($parent_childs);
3583 //echo "ZZ$a_mode";
3584 switch ($a_mode) {
3585 // insert new node after sibling at $a_pos
3586 case IL_INSERT_AFTER:
3587 $new_node = $a_cont_obj->getNode();
3588 //$a_pos = ilPageContent::incEdId($a_pos);
3589 //$curr_node = $this->getContentNode($a_pos);
3590//echo "behind $a_pos:";
3591 if ($succ_node = $curr_node->next_sibling()) {
3592 $new_node = $succ_node->insert_before($new_node, $succ_node);
3593 } else {
3594 //echo "movin doin append_child";
3595 $new_node = $parent_node->append_child($new_node);
3596 }
3597 $a_cont_obj->setNode($new_node);
3598 break;
3599
3600 case IL_INSERT_BEFORE:
3601//echo "INSERT_BEF";
3602 $new_node = $a_cont_obj->getNode();
3603 $succ_node = $this->getContentNode($a_pos);
3604 $new_node = $succ_node->insert_before($new_node, $succ_node);
3605 $a_cont_obj->setNode($new_node);
3606 break;
3607
3608 // insert new node as first child of parent $a_pos (= $a_parent)
3609 case IL_INSERT_CHILD:
3610//echo "insert as child:parent_childs:$cnt_parent_childs:<br>";
3611 $new_node = $a_cont_obj->getNode();
3612 if ($cnt_parent_childs == 0) {
3613 $new_node = $parent_node->append_child($new_node);
3614 } else {
3615 $new_node = $parent_childs[0]->insert_before($new_node, $parent_childs[0]);
3616 }
3617 $a_cont_obj->setNode($new_node);
3618//echo "PP";
3619 break;
3620 }
3621
3622 //check for PlaceHolder to remove in EditMode-keep in Layout Mode
3623 if ($remove_placeholder && !$this->getPageConfig()->getEnablePCType("PlaceHolder")) {
3624 $sub_nodes = $curr_node->child_nodes();
3625 foreach ($sub_nodes as $sub_node) {
3626 if ($sub_node->node_name() == "PlaceHolder") {
3627 $curr_node->unlink_node();
3628 }
3629 }
3630 }
3631 }
3632
3636 public function insertContentNode(&$a_cont_node, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "")
3637 {
3638 // move mode into container elements is always INSERT_CHILD
3639 $curr_node = $this->getContentNode($a_pos, $a_pcid);
3640 $curr_name = $curr_node->node_name();
3641 // @todo: try to generalize
3642 if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3643 ($curr_name == "ListItem") || ($curr_name == "Section")
3644 || ($curr_name == "Tab") || ($curr_name == "ContentPopup")
3645 || ($curr_name == "GridCell")) {
3646 $a_mode = IL_INSERT_CHILD;
3647 }
3648
3649 $hid = $curr_node->get_attribute("HierId");
3650 if ($hid != "") {
3651 $a_pos = $hid;
3652 }
3653
3654 if ($a_mode != IL_INSERT_CHILD) { // determine parent hierarchical id
3655 // of sibling at $a_pos
3656 $pos = explode("_", $a_pos);
3657 $target_pos = array_pop($pos);
3658 $parent_pos = implode("_", $pos);
3659 } else { // if we should insert a child, $a_pos is alreade the hierarchical id
3660 // of the parent node
3661 $parent_pos = $a_pos;
3662 }
3663
3664 // get the parent node
3665 if ($parent_pos != "") {
3666 $parent_node = $this->getContentNode($parent_pos);
3667 } else {
3668 $parent_node = $this->getNode();
3669 }
3670
3671 // count the parent children
3672 $parent_childs = $parent_node->child_nodes();
3673 $cnt_parent_childs = count($parent_childs);
3674 switch ($a_mode) {
3675 // insert new node after sibling at $a_pos
3676 case IL_INSERT_AFTER:
3677 //$new_node = $a_cont_obj->getNode();
3678 if ($succ_node = $curr_node->next_sibling()) {
3679 $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3680 } else {
3681 $a_cont_node = $parent_node->append_child($a_cont_node);
3682 }
3683 //$a_cont_obj->setNode($new_node);
3684 break;
3685
3686 case IL_INSERT_BEFORE:
3687 //$new_node = $a_cont_obj->getNode();
3688 $succ_node = $this->getContentNode($a_pos);
3689 $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3690 //$a_cont_obj->setNode($new_node);
3691 break;
3692
3693 // insert new node as first child of parent $a_pos (= $a_parent)
3694 case IL_INSERT_CHILD:
3695 //$new_node = $a_cont_obj->getNode();
3696 if ($cnt_parent_childs == 0) {
3697 $a_cont_node = $parent_node->append_child($a_cont_node);
3698 } else {
3699 $a_cont_node = $parent_childs[0]->insert_before($a_cont_node, $parent_childs[0]);
3700 }
3701 //$a_cont_obj->setNode($new_node);
3702 break;
3703 }
3704 }
3705
3710 public function moveContentBefore($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3711 {
3712 if ($a_source == $a_target) {
3713 return;
3714 }
3715
3716 // clone the node
3717 $content = $this->getContentObject($a_source, $a_spcid);
3718 $source_node = $content->getNode();
3719 $clone_node = $source_node->clone_node(true);
3720
3721 // delete source node
3722 $this->deleteContent($a_source, false, $a_spcid);
3723
3724 // insert cloned node at target
3725 $content->setNode($clone_node);
3726 $this->insertContent($content, $a_target, IL_INSERT_BEFORE, $a_tpcid);
3727 return $this->update();
3728 }
3729
3734 public function moveContentAfter($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3735 {
3736 if ($a_source == $a_target) {
3737 return true;
3738 }
3739
3740 // clone the node
3741 $content = $this->getContentObject($a_source, $a_spcid);
3742 $source_node = $content->getNode();
3743 $clone_node = $source_node->clone_node(true);
3744
3745 // delete source node
3746 $this->deleteContent($a_source, false, $a_spcid);
3747
3748 // insert cloned node at target
3749 $content->setNode($clone_node);
3750 $this->insertContent($content, $a_target, IL_INSERT_AFTER, $a_tpcid);
3751 return $this->update();
3752 }
3753
3757 // @todo: move to paragraph
3758 public function bbCode2XML(&$a_content)
3759 {
3760 $a_content = preg_replace('/\[com\]/i', "<Comment>", $a_content);
3761 $a_content = preg_replace('/\[\/com\]/i', "</Comment>", $a_content);
3762 $a_content = preg_replace('/\[emp]/i', "<Emph>", $a_content);
3763 $a_content = preg_replace('/\[\/emp\]/i', "</Emph>", $a_content);
3764 $a_content = preg_replace('/\[str]/i', "<Strong>", $a_content);
3765 $a_content = preg_replace('/\[\/str\]/i', "</Strong>", $a_content);
3766 }
3767
3772 public function insertInstIntoIDs($a_inst, $a_res_ref_to_obj_id = true)
3773 {
3774 // insert inst id into internal links
3775 $xpc = xpath_new_context($this->dom);
3776 $path = "//IntLink";
3777 $res = xpath_eval($xpc, $path);
3778 for ($i = 0; $i < count($res->nodeset); $i++) {
3779 $target = $res->nodeset[$i]->get_attribute("Target");
3780 $type = $res->nodeset[$i]->get_attribute("Type");
3781
3782 if (substr($target, 0, 4) == "il__") {
3783 $id = substr($target, 4, strlen($target) - 4);
3784
3785 // convert repository links obj_<ref_id> to <type>_<obj_id>
3786 // this leads to bug 6685.
3787 if ($a_res_ref_to_obj_id && $type == "RepositoryItem") {
3788 $id_arr = explode("_", $id);
3789
3790 // changed due to bug 6685
3791 $ref_id = $id_arr[1];
3792 $obj_id = ilObject::_lookupObjId($id_arr[1]);
3793
3794 $otype = ilObject::_lookupType($obj_id);
3795 if ($obj_id > 0) {
3796 // changed due to bug 6685
3797 // the ref_id should be used, if the content is
3798 // imported on the same installation
3799 // the obj_id should be used, if a different
3800 // installation imports, but has an import_id for
3801 // the object id.
3802 $id = $otype . "_" . $obj_id . "_" . $ref_id;
3803 //$id = $otype."_".$ref_id;
3804 }
3805 }
3806 $new_target = "il_" . $a_inst . "_" . $id;
3807 $res->nodeset[$i]->set_attribute("Target", $new_target);
3808 }
3809 }
3810 unset($xpc);
3811
3812 // @todo: move to media/fileitems/questions, ...
3813
3814 // insert inst id into media aliases
3815 $xpc = xpath_new_context($this->dom);
3816 $path = "//MediaAlias";
3817 $res = xpath_eval($xpc, $path);
3818 for ($i = 0; $i < count($res->nodeset); $i++) {
3819 $origin_id = $res->nodeset[$i]->get_attribute("OriginId");
3820 if (substr($origin_id, 0, 4) == "il__") {
3821 $new_id = "il_" . $a_inst . "_" . substr($origin_id, 4, strlen($origin_id) - 4);
3822 $res->nodeset[$i]->set_attribute("OriginId", $new_id);
3823 }
3824 }
3825 unset($xpc);
3826
3827 // insert inst id file item identifier entries
3828 $xpc = xpath_new_context($this->dom);
3829 $path = "//FileItem/Identifier";
3830 $res = xpath_eval($xpc, $path);
3831 for ($i = 0; $i < count($res->nodeset); $i++) {
3832 $origin_id = $res->nodeset[$i]->get_attribute("Entry");
3833 if (substr($origin_id, 0, 4) == "il__") {
3834 $new_id = "il_" . $a_inst . "_" . substr($origin_id, 4, strlen($origin_id) - 4);
3835 $res->nodeset[$i]->set_attribute("Entry", $new_id);
3836 }
3837 }
3838 unset($xpc);
3839
3840 // insert inst id into question references
3841 $xpc = xpath_new_context($this->dom);
3842 $path = "//Question";
3843 $res = xpath_eval($xpc, $path);
3844 for ($i = 0; $i < count($res->nodeset); $i++) {
3845 $qref = $res->nodeset[$i]->get_attribute("QRef");
3846 //echo "<br>setted:".$qref;
3847 if (substr($qref, 0, 4) == "il__") {
3848 $new_id = "il_" . $a_inst . "_" . substr($qref, 4, strlen($qref) - 4);
3849 //echo "<br>setting:".$new_id;
3850 $res->nodeset[$i]->set_attribute("QRef", $new_id);
3851 }
3852 }
3853 unset($xpc);
3854
3855 // insert inst id into content snippets
3856 $xpc = xpath_new_context($this->dom);
3857 $path = "//ContentInclude";
3858 $res = xpath_eval($xpc, $path);
3859 for ($i = 0; $i < count($res->nodeset); $i++) {
3860 $ci = $res->nodeset[$i]->get_attribute("InstId");
3861 if ($ci == "") {
3862 $res->nodeset[$i]->set_attribute("InstId", $a_inst);
3863 }
3864 }
3865 unset($xpc);
3866 }
3867
3871 public function checkPCIds()
3872 {
3873 $this->builddom();
3874 $mydom = $this->dom;
3875
3876 $sep = $path = "";
3877 foreach ($this->id_elements as $el) {
3878 $path .= $sep . "//" . $el . "[not(@PCID)]";
3879 $sep = " | ";
3880 $path .= $sep . "//" . $el . "[@PCID='']";
3881 }
3882
3883 $xpc = xpath_new_context($mydom);
3884 $res = &xpath_eval($xpc, $path);
3885
3886 if (count($res->nodeset) > 0) {
3887 return false;
3888 }
3889 return true;
3890 }
3891
3897 public function getAllPCIds()
3898 {
3899 $this->builddom();
3900 $mydom = $this->dom;
3901
3902 $pcids = array();
3903
3904 $sep = $path = "";
3905 foreach ($this->id_elements as $el) {
3906 $path .= $sep . "//" . $el . "[@PCID]";
3907 $sep = " | ";
3908 }
3909
3910 // get existing ids
3911 $xpc = xpath_new_context($mydom);
3912 $res = &xpath_eval($xpc, $path);
3913
3914 for ($i = 0; $i < count($res->nodeset); $i++) {
3915 $node = $res->nodeset[$i];
3916 $pcids[] = $node->get_attribute("PCID");
3917 }
3918 return $pcids;
3919 }
3920
3926 public function hasDuplicatePCIds() : bool
3927 {
3928 $duplicates = $this->getDuplicatePCIds();
3929 return count($duplicates) > 0;
3930 }
3931
3936 public function getDuplicatePCIds() : array
3937 {
3938 $this->builddom();
3939 $mydom = $this->dom;
3940
3941 $pcids = [];
3942 $duplicates = [];
3943
3944 $sep = $path = "";
3945 foreach ($this->id_elements as $el) {
3946 $path .= $sep . "//" . $el . "[@PCID]";
3947 $sep = " | ";
3948 }
3949
3950 // get existing ids
3951 $xpc = xpath_new_context($mydom);
3952 $res = xpath_eval($xpc, $path);
3953
3954 for ($i = 0; $i < count($res->nodeset); $i++) {
3955 $node = $res->nodeset[$i];
3956 $pc_id = $node->get_attribute("PCID");
3957 if ($pc_id != "") {
3958 if (isset($pcids[$pc_id])) {
3959 $duplicates[] = $pc_id;
3960 }
3961 $pcids[$pc_id] = $pc_id;
3962 }
3963 }
3964 return $duplicates;
3965 }
3966
3972 public function existsPCId($a_pc_id)
3973 {
3974 $this->builddom();
3975 $mydom = $this->dom;
3976
3977 $pcids = array();
3978
3979 $sep = $path = "";
3980 foreach ($this->id_elements as $el) {
3981 $path .= $sep . "//" . $el . "[@PCID='" . $a_pc_id . "']";
3982 $sep = " | ";
3983 }
3984
3985 // get existing ids
3986 $xpc = xpath_new_context($mydom);
3987 $res = &xpath_eval($xpc, $path);
3988 return (count($res->nodeset) > 0);
3989 }
3990
3996 public function generatePcId($a_pc_ids = false)
3997 {
3998 if ($a_pc_ids === false) {
3999 $a_pc_ids = $this->getAllPCIds();
4000 }
4001 $id = ilUtil::randomHash(10, $a_pc_ids);
4002 return $id;
4003 }
4004
4008 public function insertPCIds()
4009 {
4010 $this->builddom();
4011 $mydom = $this->dom;
4012
4013 $pcids = $this->getAllPCIds();
4014
4015 // add missing ones
4016 $sep = $path = "";
4017 foreach ($this->id_elements as $el) {
4018 $path .= $sep . "//" . $el . "[not(@PCID)]";
4019 $sep = " | ";
4020 $path .= $sep . "//" . $el . "[@PCID='']";
4021 $sep = " | ";
4022 }
4023 $xpc = xpath_new_context($mydom);
4024 $res = &xpath_eval($xpc, $path);
4025
4026 for ($i = 0; $i < count($res->nodeset); $i++) {
4027 $node = $res->nodeset[$i];
4028 $id = ilUtil::randomHash(10, $pcids);
4029 $pcids[] = $id;
4030 //echo "setting-".$id."-";
4031 $res->nodeset[$i]->set_attribute("PCID", $id);
4032 }
4033 }
4034
4038 public function getPageContentsHashes()
4039 {
4040 $this->builddom();
4041 $this->addHierIds();
4042 $mydom = $this->dom;
4043
4044 // get existing ids
4045 $path = "//PageContent";
4046 $xpc = xpath_new_context($mydom);
4047 $res = &xpath_eval($xpc, $path);
4048
4049 $hashes = array();
4050 require_once("./Services/COPage/classes/class.ilPCParagraph.php");
4051 for ($i = 0; $i < count($res->nodeset); $i++) {
4052 $hier_id = $res->nodeset[$i]->get_attribute("HierId");
4053 $pc_id = $res->nodeset[$i]->get_attribute("PCID");
4054 $dump = $mydom->dump_node($res->nodeset[$i]);
4055 if (($hpos = strpos($dump, ' HierId="' . $hier_id . '"')) > 0) {
4056 $dump = substr($dump, 0, $hpos) .
4057 substr($dump, $hpos + strlen(' HierId="' . $hier_id . '"'));
4058 }
4059
4060 $childs = $res->nodeset[$i]->child_nodes();
4061 $content = "";
4062 if ($childs[0] && $childs[0]->node_name() == "Paragraph") {
4063 $content = $mydom->dump_node($childs[0]);
4064 $content = substr(
4065 $content,
4066 strpos($content, ">") + 1,
4067 strrpos($content, "<") - (strpos($content, ">") + 1)
4068 );
4069 //var_dump($content);
4070 $content = ilPCParagraph::xml2output($content);
4071 //var_dump($content);
4072 }
4073 //$hashes[$hier_id] =
4074 // array("PCID" => $pc_id, "hash" => md5($dump));
4075 $hashes[$pc_id] =
4076 array("hier_id" => $hier_id, "hash" => md5($dump), "content" => $content);
4077 }
4078
4079 return $hashes;
4080 }
4081
4085 // @todo: move to questions
4086 public function getQuestionIds()
4087 {
4088 $this->builddom();
4089 $mydom = $this->dom;
4090
4091 // Get question IDs
4092 $path = "//Question";
4093 $xpc = xpath_new_context($mydom);
4094 $res = &xpath_eval($xpc, $path);
4095
4096 $q_ids = array();
4097 include_once("./Services/Link/classes/class.ilInternalLink.php");
4098 for ($i = 0; $i < count($res->nodeset); $i++) {
4099 $qref = $res->nodeset[$i]->get_attribute("QRef");
4100
4101 $inst_id = ilInternalLink::_extractInstOfTarget($qref);
4103
4104 if (!($inst_id > 0)) {
4105 if ($obj_id > 0) {
4106 $q_ids[] = $obj_id;
4107 }
4108 }
4109 }
4110 return $q_ids;
4111 }
4112
4113 // @todo: move to paragraph
4114 public function send_paragraph($par_id, $filename)
4115 {
4116 $this->builddom();
4117
4118 $mydom = $this->dom;
4119
4120 $xpc = xpath_new_context($mydom);
4121 $path = "/descendant::Paragraph[position() = $par_id]";
4122
4123 $res = xpath_eval($xpc, $path);
4124
4125 if (count($res->nodeset) != 1) {
4126 die("Should not happen");
4127 }
4128
4129 $context_node = $res->nodeset[0];
4130
4131 // get plain text
4132
4133 $childs = $context_node->child_nodes();
4134
4135 for ($j = 0; $j < count($childs); $j++) {
4136 $content .= $mydom->dump_node($childs[$j]);
4137 }
4138
4139 $content = str_replace("<br />", "\n", $content);
4140 $content = str_replace("<br/>", "\n", $content);
4141
4142 $plain_content = html_entity_decode($content);
4143
4144 ilUtil::deliverData($plain_content, $filename);
4145 /*
4146 $file_type = "application/octet-stream";
4147 header("Content-type: ".$file_type);
4148 header("Content-disposition: attachment; filename=\"$filename\"");
4149 echo $plain_content;*/
4150 exit();
4151 }
4152
4156 // @todo: deprecated?
4157 public function getFO()
4158 {
4159 $xml = $this->getXMLFromDom(false, true, true);
4160 $xsl = file_get_contents("./Services/COPage/xsl/page_fo.xsl");
4161 $args = array('/_xml' => $xml, '/_xsl' => $xsl);
4162 $xh = xslt_create();
4163
4164 $params = array();
4165
4166 $fo = xslt_process($xh, "arg:/_xml", "arg:/_xsl", null, $args, $params);
4167 var_dump($fo);
4168 // do some replacements
4169 $fo = str_replace("\n", "", $fo);
4170 $fo = str_replace("<br/>", "<br>", $fo);
4171 $fo = str_replace("<br>", "\n", $fo);
4172
4173 xslt_free($xh);
4174
4175 //
4176 $fo = substr($fo, strpos($fo, ">") + 1);
4177 //echo "<br><b>fo:</b><br>".htmlentities($fo); flush();
4178 return $fo;
4179 }
4180
4181 public function registerOfflineHandler($handler)
4182 {
4183 $this->offline_handler = $handler;
4184 }
4185
4191 public function getOfflineHandler()
4192 {
4194 }
4195
4199 public static function _lookupContainsDeactivatedElements($a_id, $a_parent_type, $a_lang = "-")
4200 {
4201 global $DIC;
4202
4203 $db = $DIC->database();
4204
4205 if ($a_lang == "") {
4206 $a_lang = "-";
4207 }
4208
4209 $query = "SELECT * FROM page_object WHERE page_id = " .
4210 $db->quote($a_id, "integer") . " AND " .
4211 " parent_type = " . $db->quote($a_parent_type, "text") . " AND " .
4212 " lang = " . $db->quote($a_lang, "text") . " AND " .
4213 " inactive_elements = " . $db->quote(1, "integer");
4214 $obj_set = $db->query($query);
4215
4216 if ($obj_rec = $obj_set->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
4217 return true;
4218 }
4219
4220 return false;
4221 }
4222
4228 public function containsDeactivatedElements($a_content)
4229 {
4230 if (strpos($a_content, " Enabled=\"False\"")) {
4231 return true;
4232 }
4233 return false;
4234 }
4235
4239 public function getHistoryEntries()
4240 {
4241 $db = $this->db;
4242
4243 $h_query = "SELECT * FROM page_history " .
4244 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4245 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4246 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4247 " ORDER BY hdate DESC";
4248
4249 $hset = $db->query($h_query);
4250 $hentries = array();
4251
4252 while ($hrec = $db->fetchAssoc($hset)) {
4253 $hrec["sortkey"] = (int) $hrec["nr"];
4254 $hrec["user"] = (int) $hrec["user_id"];
4255 $hentries[] = $hrec;
4256 }
4257 //var_dump($hentries);
4258 return $hentries;
4259 }
4260
4264 public function getHistoryEntry($a_old_nr)
4265 {
4266 $db = $this->db;
4267
4268 $res = $db->queryF(
4269 "SELECT * FROM page_history " .
4270 " WHERE page_id = %s " .
4271 " AND parent_type = %s " .
4272 " AND nr = %s" .
4273 " AND lang = %s",
4274 array("integer", "text", "integer", "text"),
4275 array($this->getId(), $this->getParentType(), $a_old_nr, $this->getLanguage())
4276 );
4277 if ($hrec = $db->fetchAssoc($res)) {
4278 return $hrec;
4279 }
4280
4281 return false;
4282 }
4283
4289 public function getHistoryInfo($a_nr)
4290 {
4291 $db = $this->db;
4292
4293 // determine previous entry
4294 $and_nr = ($a_nr > 0)
4295 ? " AND nr < " . $db->quote((int) $a_nr, "integer")
4296 : "";
4297 $res = $db->query("SELECT MAX(nr) mnr FROM page_history " .
4298 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4299 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4300 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4301 $and_nr);
4302 $row = $db->fetchAssoc($res);
4303 if ($row["mnr"] > 0) {
4304 $res = $db->query("SELECT * FROM page_history " .
4305 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4306 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4307 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4308 " AND nr = " . $db->quote((int) $row["mnr"], "integer"));
4309 $row = $db->fetchAssoc($res);
4310 $ret["previous"] = $row;
4311 }
4312
4313 // determine next entry
4314 $res = $db->query("SELECT MIN(nr) mnr FROM page_history " .
4315 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4316 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4317 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4318 " AND nr > " . $db->quote((int) $a_nr, "integer"));
4319 $row = $db->fetchAssoc($res);
4320 if ($row["mnr"] > 0) {
4321 $res = $db->query("SELECT * FROM page_history " .
4322 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4323 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4324 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4325 " AND nr = " . $db->quote((int) $row["mnr"], "integer"));
4326 $row = $db->fetchAssoc($res);
4327 $ret["next"] = $row;
4328 }
4329
4330 // current
4331 if ($a_nr > 0) {
4332 $res = $db->query("SELECT * FROM page_history " .
4333 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4334 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4335 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4336 " AND nr = " . $db->quote((int) $a_nr, "integer"));
4337 $row = $db->fetchAssoc($res);
4338 } else {
4339 $res = $db->query("SELECT page_id, last_change hdate, parent_type, parent_id, last_change_user user_id, content, lang FROM page_object " .
4340 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4341 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4342 " AND lang = " . $db->quote($this->getLanguage(), "text"));
4343 $row = $db->fetchAssoc($res);
4344 }
4345 $ret["current"] = $row;
4346
4347 return $ret;
4348 }
4349
4350 public function addChangeDivClasses($a_hashes)
4351 {
4352 $xpc = xpath_new_context($this->dom);
4353 $path = "/*[1]";
4354 $res = xpath_eval($xpc, $path);
4355 $rnode = $res->nodeset[0];
4356
4357 //echo "A";
4358 foreach ($a_hashes as $pc_id => $h) {
4359 //echo "B";
4360 if ($h["change"] != "") {
4361 $dc_node = $this->dom->create_element("DivClass");
4362 $dc_node->set_attribute("HierId", $h["hier_id"]);
4363 $dc_node->set_attribute("Class", "ilEdit" . $h["change"]);
4364 $dc_node = $rnode->append_child($dc_node);
4365 }
4366 }
4367 //echo "<br><br><br><br><br><br>".htmlentities($this->getXMLFromDom());
4368 }
4369
4375 public function compareVersion($a_left, $a_right)
4376 {
4377 // get page objects
4378 include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4379 $l_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_left);
4380 $r_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_right);
4381
4382 $l_hashes = $l_page->getPageContentsHashes();
4383 $r_hashes = $r_page->getPageContentsHashes();
4384 // determine all deleted and changed page elements
4385 foreach ($l_hashes as $pc_id => $h) {
4386 if (!isset($r_hashes[$pc_id])) {
4387 $l_hashes[$pc_id]["change"] = "Deleted";
4388 } else {
4389 if ($l_hashes[$pc_id]["hash"] != $r_hashes[$pc_id]["hash"]) {
4390 $l_hashes[$pc_id]["change"] = "Modified";
4391 $r_hashes[$pc_id]["change"] = "Modified";
4392
4393 include_once("./Services/COPage/mediawikidiff/class.WordLevelDiff.php");
4394 // if modified element is a paragraph, highlight changes
4395 if ($l_hashes[$pc_id]["content"] != "" &&
4396 $r_hashes[$pc_id]["content"] != "") {
4397 $new_left = str_replace("\n", "<br />", $l_hashes[$pc_id]["content"]);
4398 $new_right = str_replace("\n", "<br />", $r_hashes[$pc_id]["content"]);
4399 $wldiff = new WordLevelDiff(
4400 array($new_left),
4401 array($new_right)
4402 );
4403 $new_left = $wldiff->orig();
4404 $new_right = $wldiff->closing();
4405 $l_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_left[0]);
4406 $r_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_right[0]);
4407 }
4408 }
4409 }
4410 }
4411
4412 // determine all new paragraphs
4413 foreach ($r_hashes as $pc_id => $h) {
4414 if (!isset($l_hashes[$pc_id])) {
4415 $r_hashes[$pc_id]["change"] = "New";
4416 }
4417 }
4418 $l_page->addChangeDivClasses($l_hashes);
4419 $r_page->addChangeDivClasses($r_hashes);
4420
4421 return array("l_page" => $l_page,
4422 "r_page" => $r_page,
4423 "l_changes" => $l_hashes,
4424 "r_changes" => $r_hashes
4425 );
4426 }
4427
4431 public function increaseViewCnt()
4432 {
4433 $db = $this->db;
4434
4435 $db->manipulate("UPDATE page_object " .
4436 " SET view_cnt = view_cnt + 1 " .
4437 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4438 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4439 " AND lang = " . $db->quote($this->getLanguage(), "text"));
4440 }
4441
4448 public static function getRecentChanges($a_parent_type, $a_parent_id, $a_period = 30, $a_lang = "")
4449 {
4450 global $DIC;
4451
4452 $db = $DIC->database();
4453
4454 $and_lang = "";
4455 if ($a_lang != "") {
4456 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4457 }
4458
4459 $page_changes = array();
4460 $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4461 $q = "SELECT * FROM page_object " .
4462 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4463 " AND parent_type = " . $db->quote($a_parent_type, "text") .
4464 " AND last_change >= " . $db->quote($limit_ts, "timestamp") . $and_lang;
4465 // " AND (TO_DAYS(now()) - TO_DAYS(last_change)) <= ".((int)$a_period);
4466 $set = $db->query($q);
4467 while ($page = $db->fetchAssoc($set)) {
4468 $page_changes[] = array(
4469 "date" => $page["last_change"],
4470 "id" => $page["page_id"],
4471 "lang" => $page["lang"],
4472 "type" => "page",
4473 "user" => $page["last_change_user"]
4474 );
4475 }
4476
4477 $and_str = "";
4478 if ($a_period > 0) {
4479 $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4480 $and_str = " AND hdate >= " . $db->quote($limit_ts, "timestamp") . " ";
4481 }
4482
4483 $q = "SELECT * FROM page_history " .
4484 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4485 " AND parent_type = " . $db->quote($a_parent_type, "text") .
4486 $and_str . $and_lang;
4487 $set = $db->query($q);
4488 while ($page = $db->fetchAssoc($set)) {
4489 $page_changes[] = array(
4490 "date" => $page["hdate"],
4491 "id" => $page["page_id"],
4492 "lang" => $page["lang"],
4493 "type" => "hist",
4494 "nr" => $page["nr"],
4495 "user" => $page["user_id"]
4496 );
4497 }
4498
4499 $page_changes = ilUtil::sortArray($page_changes, "date", "desc");
4500
4501 return $page_changes;
4502 }
4503
4511 public static function getAllPages($a_parent_type, $a_parent_id, $a_lang = "-")
4512 {
4513 global $DIC;
4514
4515 $db = $DIC->database();
4516
4517 $and_lang = "";
4518 if ($a_lang != "") {
4519 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4520 }
4521
4522 $q = "SELECT * FROM page_object " .
4523 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4524 " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang;
4525 $set = $db->query($q);
4526 $pages = array();
4527 while ($page = $db->fetchAssoc($set)) {
4528 $key_add = ($a_lang == "")
4529 ? ":" . $page["lang"]
4530 : "";
4531 $pages[$page["page_id"] . $key_add] = array(
4532 "date" => $page["last_change"],
4533 "id" => $page["page_id"],
4534 "lang" => $page["lang"],
4535 "user" => $page["last_change_user"]
4536 );
4537 }
4538
4539 return $pages;
4540 }
4541
4547 public static function getNewPages($a_parent_type, $a_parent_id, $a_lang = "-")
4548 {
4549 global $DIC;
4550
4551 $db = $DIC->database();
4552
4553 $and_lang = "";
4554 if ($a_lang != "") {
4555 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4556 }
4557
4558 $pages = array();
4559
4560 $q = "SELECT * FROM page_object " .
4561 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4562 " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang .
4563 " ORDER BY created DESC";
4564 $set = $db->query($q);
4565 while ($page = $db->fetchAssoc($set)) {
4566 if ($page["created"] != "") {
4567 $pages[] = array(
4568 "created" => $page["created"],
4569 "id" => $page["page_id"],
4570 "lang" => $page["lang"],
4571 "user" => $page["create_user"],
4572 );
4573 }
4574 }
4575
4576 return $pages;
4577 }
4578
4584 public static function getParentObjectContributors($a_parent_type, $a_parent_id, $a_lang = "-")
4585 {
4586 global $DIC;
4587
4588 $db = $DIC->database();
4589
4590 $and_lang = "";
4591 if ($a_lang != "") {
4592 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4593 }
4594
4595 $contributors = array();
4596 $set = $db->queryF(
4597 "SELECT last_change_user, lang, page_id FROM page_object " .
4598 " WHERE parent_id = %s AND parent_type = %s " .
4599 " AND last_change_user != %s" . $and_lang,
4600 array("integer", "text", "integer"),
4601 array($a_parent_id, $a_parent_type, 0)
4602 );
4603
4604 while ($page = $db->fetchAssoc($set)) {
4605 if ($a_lang == "") {
4606 $contributors[$page["last_change_user"]][$page["page_id"]][$page["lang"]] = 1;
4607 } else {
4608 $contributors[$page["last_change_user"]][$page["page_id"]] = 1;
4609 }
4610 }
4611
4612 $set = $db->queryF(
4613 "SELECT count(*) as cnt, lang, page_id, user_id FROM page_history " .
4614 " WHERE parent_id = %s AND parent_type = %s AND user_id != %s " . $and_lang .
4615 " GROUP BY page_id, user_id, lang ",
4616 array("integer", "text", "integer"),
4617 array($a_parent_id, $a_parent_type, 0)
4618 );
4619 while ($hpage = $db->fetchAssoc($set)) {
4620 if ($a_lang == "") {
4621 $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] =
4622 $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] + $hpage["cnt"];
4623 } else {
4624 $contributors[$hpage["user_id"]][$hpage["page_id"]] =
4625 $contributors[$hpage["user_id"]][$hpage["page_id"]] + $hpage["cnt"];
4626 }
4627 }
4628
4629 $c = array();
4630 foreach ($contributors as $k => $co) {
4631 if (ilObject::_lookupType($k) == "usr") {
4633 $c[] = array("user_id" => $k,
4634 "pages" => $co,
4635 "lastname" => $name["lastname"],
4636 "firstname" => $name["firstname"]
4637 );
4638 }
4639 }
4640
4641 return $c;
4642 }
4643
4649 public static function getPageContributors($a_parent_type, $a_page_id, $a_lang = "-")
4650 {
4651 global $DIC;
4652
4653 $db = $DIC->database();
4654
4655 $and_lang = "";
4656 if ($a_lang != "") {
4657 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4658 }
4659
4660 $contributors = array();
4661 $set = $db->queryF(
4662 "SELECT last_change_user, lang FROM page_object " .
4663 " WHERE page_id = %s AND parent_type = %s " .
4664 " AND last_change_user != %s" . $and_lang,
4665 array("integer", "text", "integer"),
4666 array($a_page_id, $a_parent_type, 0)
4667 );
4668
4669 while ($page = $db->fetchAssoc($set)) {
4670 if ($a_lang == "") {
4671 $contributors[$page["last_change_user"]][$page["lang"]] = 1;
4672 } else {
4673 $contributors[$page["last_change_user"]] = 1;
4674 }
4675 }
4676
4677 $set = $db->queryF(
4678 "SELECT count(*) as cnt, lang, page_id, user_id FROM page_history " .
4679 " WHERE page_id = %s AND parent_type = %s AND user_id != %s " . $and_lang .
4680 " GROUP BY user_id, page_id, lang ",
4681 array("integer", "text", "integer"),
4682 array($a_page_id, $a_parent_type, 0)
4683 );
4684 while ($hpage = $db->fetchAssoc($set)) {
4685 if ($a_lang == "") {
4686 $contributors[$hpage["user_id"]][$page["lang"]] =
4687 $contributors[$hpage["user_id"]][$page["lang"]] + $hpage["cnt"];
4688 } else {
4689 $contributors[$hpage["user_id"]] =
4690 $contributors[$hpage["user_id"]] + $hpage["cnt"];
4691 }
4692 }
4693
4694 $c = array();
4695 foreach ($contributors as $k => $co) {
4696 include_once "Services/User/classes/class.ilObjUser.php";
4698 $c[] = array("user_id" => $k,
4699 "pages" => $co,
4700 "lastname" => $name["lastname"],
4701 "firstname" => $name["firstname"]
4702 );
4703 }
4704
4705 return $c;
4706 }
4707
4711 public function writeRenderedContent($a_content, $a_md5)
4712 {
4713 global $DIC;
4714
4715 $db = $DIC->database();
4716
4717 $db->update("page_object", array(
4718 "rendered_content" => array("clob", $a_content),
4719 "render_md5" => array("text", $a_md5),
4720 "rendered_time" => array("timestamp", ilUtil::now())
4721 ), array(
4722 "page_id" => array("integer", $this->getId()),
4723 "lang" => array("text", $this->getLanguage()),
4724 "parent_type" => array("text", $this->getParentType())
4725 ));
4726 }
4727
4734 public static function getPagesWithLinks($a_parent_type, $a_parent_id, $a_lang = "-")
4735 {
4736 global $DIC;
4737
4738 $db = $DIC->database();
4739
4740 $and_lang = "";
4741 if ($a_lang != "") {
4742 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4743 }
4744
4745 $q = "SELECT * FROM page_object " .
4746 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4747 " AND parent_type = " . $db->quote($a_parent_type, "text") .
4748 " AND int_links = " . $db->quote(1, "integer") . $and_lang;
4749 $set = $db->query($q);
4750 $pages = array();
4751 while ($page = $db->fetchAssoc($set)) {
4752 $key_add = ($a_lang == "")
4753 ? ":" . $page["lang"]
4754 : "";
4755 $pages[$page["page_id"] . $key_add] = array(
4756 "date" => $page["last_change"],
4757 "id" => $page["page_id"],
4758 "lang" => $page["lang"],
4759 "user" => $page["last_change_user"]
4760 );
4761 }
4762
4763 return $pages;
4764 }
4765
4771 public function containsIntLinks($a_content)
4772 {
4773 if (strpos($a_content, "IntLink")) {
4774 return true;
4775 }
4776 return false;
4777 }
4778
4783 {
4784 }
4785
4790 // @todo begin: generalize
4791 public function saveInitialOpenedContent($a_type, $a_id, $a_target)
4792 {
4793 $this->buildDom();
4794
4795 $link_type = "";
4796
4797 switch ($a_type) {
4798 case "media":
4799 $link_type = "MediaObject";
4800 $a_id = "il__mob_" . $a_id;
4801 break;
4802
4803 case "page":
4804 $link_type = "PageObject";
4805 $a_id = "il__pg_" . $a_id;
4806 break;
4807
4808 case "term":
4809 $link_type = "GlossaryItem";
4810 $a_id = "il__git_" . $a_id;
4811 $a_target = "Glossary";
4812 break;
4813 }
4814
4815 // if type or id missing -> delete InitOpenedContent, if existing
4816 if ($link_type == "" || $a_id == "") {
4817 $xpc = xpath_new_context($this->dom);
4818 $path = "//PageObject/InitOpenedContent";
4819 $res = xpath_eval($xpc, $path);
4820 if (count($res->nodeset) > 0) {
4821 $res->nodeset[0]->unlink_node($res->nodeset[0]);
4822 }
4823 } else {
4824 $xpc = xpath_new_context($this->dom);
4825 $path = "//PageObject/InitOpenedContent";
4826 $res = xpath_eval($xpc, $path);
4827 if (count($res->nodeset) > 0) {
4828 $init_node = $res->nodeset[0];
4829 $childs = $init_node->child_nodes();
4830 for ($i = 0; $i < count($childs); $i++) {
4831 if ($childs[$i]->node_name() == "IntLink") {
4832 $il_node = $childs[$i];
4833 }
4834 }
4835 } else {
4836 $path = "//PageObject";
4837 $res = xpath_eval($xpc, $path);
4838 $page_node = $res->nodeset[0];
4839 $init_node = $this->dom->create_element("InitOpenedContent");
4840 $init_node = $page_node->append_child($init_node);
4841 $il_node = $this->dom->create_element("IntLink");
4842 $il_node = $init_node->append_child($il_node);
4843 }
4844 $il_node->set_attribute("Target", $a_id);
4845 $il_node->set_attribute("Type", $link_type);
4846 $il_node->set_attribute("TargetFrame", $a_target);
4847 }
4848
4849 $this->update();
4850 }
4851
4856 public function getInitialOpenedContent()
4857 {
4858 $this->buildDom();
4859
4860 $xpc = xpath_new_context($this->dom);
4861 $path = "//PageObject/InitOpenedContent";
4862 $res = xpath_eval($xpc, $path);
4863 $il_node = null;
4864 if (count($res->nodeset) > 0) {
4865 $init_node = $res->nodeset[0];
4866 $childs = $init_node->child_nodes();
4867 for ($i = 0; $i < count($childs); $i++) {
4868 if ($childs[$i]->node_name() == "IntLink") {
4869 $il_node = $childs[$i];
4870 }
4871 }
4872 }
4873 if (!is_null($il_node)) {
4874 $id = $il_node->get_attribute("Target");
4875 $link_type = $il_node->get_attribute("Type");
4876 $target = $il_node->get_attribute("TargetFrame");
4877
4878 switch ($link_type) {
4879 case "MediaObject":
4880 $type = "media";
4881 break;
4882
4883 case "PageObject":
4884 $type = "page";
4885 break;
4886
4887 case "GlossaryItem":
4888 $type = "term";
4889 break;
4890 }
4891 include_once("./Services/Link/classes/class.ilInternalLink.php");
4893 return array("id" => $id, "type" => $type, "target" => $target);
4894 }
4895
4896 return array();
4897 }
4898 // @todo end
4899
4908 public function beforePageContentUpdate($a_page_content)
4909 {
4910 }
4911
4918 public function copy($a_id, $a_parent_type = "", $a_parent_id = 0, $a_clone_mobs = false)
4919 {
4920 if ($a_parent_type == "") {
4921 $a_parent_type = $this->getParentType();
4922 if ($a_parent_id == 0) {
4923 $a_parent_id = $this->getParentId();
4924 }
4925 }
4926
4927 include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4928 foreach (self::lookupTranslations($this->getParentType(), $this->getId()) as $l) {
4929 $existed = false;
4930 $orig_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), 0, $l);
4931 if (ilPageObject::_exists($a_parent_type, $a_id, $l)) {
4932 $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, $a_id, 0, $l);
4933 $existed = true;
4934 } else {
4935 $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, 0, 0, $l);
4936 $new_page_object->setParentId($a_parent_id);
4937 $new_page_object->setId($a_id);
4938 }
4939 $new_page_object->setXMLContent($orig_page->copyXMLContent($a_clone_mobs));
4940 $new_page_object->setActive($orig_page->getActive());
4941 $new_page_object->setActivationStart($orig_page->getActivationStart());
4942 $new_page_object->setActivationEnd($orig_page->getActivationEnd());
4943 if ($existed) {
4944 $new_page_object->buildDom();
4945 $new_page_object->update();
4946 } else {
4947 $new_page_object->create();
4948 }
4949 }
4950 }
4951
4958 public static function lookupTranslations($a_parent_type, $a_id)
4959 {
4960 global $DIC;
4961
4962 $db = $DIC->database();
4963
4964 $set = $db->query(
4965 "SELECT lang FROM page_object " .
4966 " WHERE page_id = " . $db->quote($a_id, "integer") .
4967 " AND parent_type = " . $db->quote($a_parent_type, "text")
4968 );
4969 $langs = array();
4970 while ($rec = $db->fetchAssoc($set)) {
4971 $langs[] = $rec["lang"];
4972 }
4973 return $langs;
4974 }
4975
4980 public function copyPageToTranslation($a_target_lang)
4981 {
4982 $transl_page = ilPageObjectFactory::getInstance(
4983 $this->getParentType(),
4984 0,
4985 0,
4986 $a_target_lang
4987 );
4988 $transl_page->setId($this->getId());
4989 $transl_page->setParentId($this->getParentId());
4990 $transl_page->setXMLContent($this->copyXMLContent());
4991 $transl_page->setActive($this->getActive());
4992 $transl_page->setActivationStart($this->getActivationStart());
4993 $transl_page->setActivationEnd($this->getActivationEnd());
4994 $transl_page->create();
4995 }
4996
5000
5004 public function getEditLock()
5005 {
5006 $db = $this->db;
5008
5009 $min = (int) $this->getEffectiveEditLockTime();
5010 if ($min > 0) {
5011 // try to set the lock for the user
5012 $ts = time();
5013 $db->manipulate(
5014 "UPDATE page_object SET " .
5015 " edit_lock_user = " . $db->quote($user->getId(), "integer") . "," .
5016 " edit_lock_ts = " . $db->quote($ts, "integer") .
5017 " WHERE (edit_lock_user = " . $db->quote($user->getId(), "integer") . " OR " .
5018 " edit_lock_ts < " . $db->quote(time() - ($min * 60), "integer") . ") " .
5019 " AND page_id = " . $db->quote($this->getId(), "integer") .
5020 " AND parent_type = " . $db->quote($this->getParentType(), "text")
5021 );
5022
5023 $set = $db->query(
5024 "SELECT edit_lock_user FROM page_object " .
5025 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
5026 " AND parent_type = " . $db->quote($this->getParentType(), "text")
5027 );
5028 $rec = $db->fetchAssoc($set);
5029 if ($rec["edit_lock_user"] != $user->getId()) {
5030 return false;
5031 }
5032 }
5033
5034 return true;
5035 }
5036
5040 public function releasePageLock()
5041 {
5042 $db = $this->db;
5044 $aset = new ilSetting("adve");
5045
5046 $min = (int) $aset->get("block_mode_minutes");
5047 if ($min > 0) {
5048 // try to set the lock for the user
5049 $ts = time();
5050 $db->manipulate(
5051 "UPDATE page_object SET " .
5052 " edit_lock_user = " . $db->quote($user->getId(), "integer") . "," .
5053 " edit_lock_ts = 0" .
5054 " WHERE edit_lock_user = " . $db->quote($user->getId(), "integer") .
5055 " AND page_id = " . $db->quote($this->getId(), "integer") .
5056 " AND parent_type = " . $db->quote($this->getParentType(), "text")
5057 );
5058
5059 $set = $db->query(
5060 "SELECT edit_lock_user FROM page_object " .
5061 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
5062 " AND parent_type = " . $db->quote($this->getParentType(), "text")
5063 );
5064 $rec = $db->fetchAssoc($set);
5065 if ($rec["edit_lock_user"] != $user->getId()) {
5066 return false;
5067 }
5068 }
5069
5070 return true;
5071 }
5072
5077 public function getEditLockInfo()
5078 {
5079 $db = $this->db;
5080
5081 $aset = new ilSetting("adve");
5082 $min = (int) $aset->get("block_mode_minutes");
5083
5084 $set = $db->query(
5085 "SELECT edit_lock_user, edit_lock_ts FROM page_object " .
5086 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
5087 " AND parent_type = " . $db->quote($this->getParentType(), "text")
5088 );
5089 $rec = $db->fetchAssoc($set);
5090 $rec["edit_lock_until"] = $rec["edit_lock_ts"] + $min * 60;
5091
5092 return $rec;
5093 }
5094
5105 public static function truncateHTML(
5106 $a_text,
5107 $a_length = 100,
5108 $a_ending = '...',
5109 $a_exact = false,
5110 $a_consider_html = true
5111 ) {
5112 include_once "Services/Utilities/classes/class.ilStr.php";
5113
5114 if ($a_consider_html) {
5115 // if the plain text is shorter than the maximum length, return the whole text
5116 if (strlen(preg_replace('/<.*?>/', '', $a_text)) <= $a_length) {
5117 return $a_text;
5118 }
5119
5120 // splits all html-tags to scanable lines
5121 $total_length = strlen($a_ending);
5122 $open_tags = array();
5123 $truncate = '';
5124 preg_match_all('/(<.+?>)?([^<>]*)/s', $a_text, $lines, PREG_SET_ORDER);
5125 foreach ($lines as $line_matchings) {
5126 // if there is any html-tag in this line, handle it and add it (uncounted) to the output
5127 if (!empty($line_matchings[1])) {
5128 // if it's an "empty element" with or without xhtml-conform closing slash
5129 if (preg_match(
5130 '/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is',
5131 $line_matchings[1]
5132 )) {
5133 // do nothing
5134 } // if tag is a closing tag
5135 elseif (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line_matchings[1], $tag_matchings)) {
5136 // delete tag from $open_tags list
5137 $pos = array_search($tag_matchings[1], $open_tags);
5138 if ($pos !== false) {
5139 unset($open_tags[$pos]);
5140 }
5141 } // if tag is an opening tag
5142 elseif (preg_match('/^<\s*([^\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings)) {
5143 // add tag to the beginning of $open_tags list
5144 array_unshift($open_tags, strtolower($tag_matchings[1]));
5145 }
5146 // add html-tag to $truncate'd text
5147 $truncate .= $line_matchings[1];
5148 }
5149
5150 // calculate the length of the plain text part of the line; handle entities as one character
5151 $content_length = strlen(preg_replace(
5152 '/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i',
5153 ' ',
5154 $line_matchings[2]
5155 ));
5156 if ($total_length + $content_length > $a_length) {
5157 // the number of characters which are left
5158 $left = $a_length - $total_length;
5159 $entities_length = 0;
5160 // search for html entities
5161 if (preg_match_all(
5162 '/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i',
5163 $line_matchings[2],
5164 $entities,
5165 PREG_OFFSET_CAPTURE
5166 )) {
5167 // calculate the real length of all entities in the legal range
5168 foreach ($entities[0] as $entity) {
5169 if ($entity[1] + 1 - $entities_length <= $left) {
5170 $left--;
5171 $entities_length += strlen($entity[0]);
5172 } else {
5173 // no more characters left
5174 break;
5175 }
5176 }
5177 }
5178
5179 // $truncate .= substr($line_matchings[2], 0, $left+$entities_length);
5180 $truncate .= ilStr::shortenText($line_matchings[2], 0, $left + $entities_length);
5181
5182 // maximum lenght is reached, so get off the loop
5183 break;
5184 } else {
5185 $truncate .= $line_matchings[2];
5186 $total_length += $content_length;
5187 }
5188
5189 // if the maximum length is reached, get off the loop
5190 if ($total_length >= $a_length) {
5191 break;
5192 }
5193 }
5194 } else {
5195 if (strlen($a_text) <= $a_length) {
5196 return $a_text;
5197 } else {
5198 // $truncate = substr($a_text, 0, $a_length - strlen($a_ending));
5199 $truncate = ilStr::shortenText($a_text, 0, $a_length - strlen($a_ending));
5200 }
5201 }
5202
5203 // THIS IS BUGGY AS IT MIGHT BREAK AN OPEN TAG AT THE END
5204 if (!sizeof($open_tags)) {
5205 // if the words shouldn't be cut in the middle...
5206 if (!$a_exact) {
5207 // ...search the last occurance of a space...
5208 $spacepos = strrpos($truncate, ' ');
5209 if ($spacepos !== false) {
5210 // ...and cut the text in this position
5211 // $truncate = substr($truncate, 0, $spacepos);
5212 $truncate = ilStr::shortenText($truncate, 0, $spacepos);
5213 }
5214 }
5215 }
5216
5217 // add the defined ending to the text
5218 $truncate .= $a_ending;
5219
5220 if ($a_consider_html) {
5221 // close all unclosed html-tags
5222 foreach ($open_tags as $tag) {
5223 $truncate .= '</' . $tag . '>';
5224 }
5225 }
5226
5227 return $truncate;
5228 }
5229
5234 public function getContentTemplates()
5235 {
5236 return array();
5237 }
5238
5245 public static function getLastChangeByParent($a_parent_type, $a_parent_id, $a_lang = "")
5246 {
5247 global $DIC;
5248
5249 $db = $DIC->database();
5250
5251 $and_lang = "";
5252 if ($a_lang != "") {
5253 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
5254 }
5255
5256 $db->setLimit(1);
5257 $q = "SELECT last_change FROM page_object " .
5258 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
5259 " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang .
5260 " ORDER BY last_change DESC";
5261
5262 $set = $db->query($q);
5263 $rec = $db->fetchAssoc($set);
5264
5265 return $rec["last_change"];
5266 }
5267
5269 {
5270 if ($this->getPageConfig()->getEditLockSupport() == false) {
5271 return 0;
5272 }
5273
5274 $aset = new ilSetting("adve");
5275 $min = (int) $aset->get("block_mode_minutes");
5276
5277 return $min;
5278 }
5279
5284 public function getAllFileObjIds()
5285 {
5286 $file_obj_ids = array();
5287
5288 // insert inst id file item identifier entries
5289 $xpc = xpath_new_context($this->dom);
5290 $path = "//FileItem/Identifier";
5291 $res = xpath_eval($xpc, $path);
5292 for ($i = 0; $i < count($res->nodeset); $i++) {
5293 $file_obj_ids[] = $res->nodeset[$i]->get_attribute("Entry");
5294 }
5295 unset($xpc);
5296 return $file_obj_ids;
5297 }
5298
5303 public function resolveResources($ref_mapping) : bool
5304 {
5305 include_once("./Services/COPage/classes/class.ilPCResources.php");
5306 return ilPCResources::resolveResources($this, $ref_mapping);
5307 }
5308
5313 public function getRepoObjId()
5314 {
5315 return $this->getParentId();
5316 }
5317
5323 public function getPCModel()
5324 {
5325 $model = [];
5326 foreach ($this->getAllPCIds() as $pc_id) {
5327 $co = $this->getContentObjectForPcId($pc_id);
5328 if ($co !== null && $co !== false) {
5329 $co_model = $co->getModel();
5330 if ($co_model !== null) {
5331 $model[$pc_id] = $co_model;
5332 }
5333 }
5334 }
5335 return $model;
5336 }
5337
5341 public function assignCharacteristic($targets, $char_par, $char_sec, $char_med)
5342 {
5343 if (is_array($targets)) {
5344 foreach ($targets as $t) {
5345 $tarr = explode(":", $t);
5346 $cont_obj = $this->getContentObject($tarr[0], $tarr[1]);
5347 if (is_object($cont_obj) && $cont_obj->getType() == "par") {
5348 $cont_obj->setCharacteristic($char_par);
5349 }
5350 if (is_object($cont_obj) && $cont_obj->getType() == "sec") {
5351 $cont_obj->setCharacteristic($char_sec);
5352 }
5353 if (is_object($cont_obj) && $cont_obj->getType() == "media") {
5354 $cont_obj->setClass($char_med);
5355 }
5356 }
5357 return $this->update();
5358 }
5359 return true;
5360 }
5361}
user()
Definition: user.php:4
$size
Definition: RandomTest.php:84
$filename
Definition: buildRTE.php:89
$_GET["client_id"]
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
const IL_CAL_UNIX
const IL_CAL_DATETIME
const IL_MODE_OUTPUT
const IL_INSERT_BEFORE
const IL_INSERT_CHILD
const IL_INSERT_AFTER
static _instantiateQuestion($question_id)
static getPCDefinitions()
Get PC definitions.
static getPCDefinitionByName($a_pc_name)
Get PC definition by name.
static requirePCClassByName($a_name)
Get instance.
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date @access public.
@classDescription Date and time handling
static _after(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
compare two dates and check start is after end This method does not consider tz offsets.
static _before(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.
static setAction($a_action)
static _lookupType($a_obj_id, $a_lm_id=0)
Lookup type.
Extension of ilPageObject for learning modules.
static getLogger($a_component_id)
Get component logger.
Class ilMediaAliasItem.
static _resolveMapAreaLinks($a_mob_id)
resolve internal links of all media items of a media object
static _getMapAreasIntLinks($a_mob_id)
get all internal links of map areas of a mob
static deleteNewsOfContext( $a_context_obj_id, $a_context_obj_type, $a_context_sub_obj_id=0, $a_context_sub_obj_type="")
Delete all news of a context.
static _lookupFileSize($a_id)
Class ilObjMediaObject.
static _deleteAllUsages($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
static
static _getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
static _lookupName($a_user_id)
lookup user name
static _lookupObjId($a_id)
static _lookupImportId($a_obj_id)
static _exists($a_id, $a_reference=false, $a_type=null)
checks if an object exists in object_data@access public
static _getLastUpdateOfObjects($a_objs)
Get last update for a set of media objects.
static _lookupType($a_id, $a_reference=false)
lookup object type
Class ilPCDataTable.
Class ilPCMediaObjectGUI.
Class ilPCMediaObject.
Class ilPCParagraphGUI.
Class ilPCParagraph.
static xml2output($a_text, $a_wysiwyg=false, $a_replace_lists=true, $unmask=true)
Converts xml from DB to output in edit textarea.
static resolveResources(ilPageObject $page, $ref_mappings)
Resolve resources.
Class ilPCSectionGUI.
Class ilPCTable.
static incEdId($ed_id)
Increases an hierarchical editing id at lowest level (last number)
static sortHierIds($a_array)
Sort an array of Hier IDS in ascending order.
static getInstance($a_parent_type, $a_id=0, $a_old_nr=0, $a_lang="-")
Get page object instance.
static getConfigInstance($a_parent_type)
Get page config instance.
Class ilPageObject Handles PageObjects of ILIAS Learning Modules (see ILIAS DTD)
releasePageLock()
Release page lock.
stripHierIDs()
strip all hierarchical id attributes out of the dom tree
switchEnableMultiple($a_hids, $a_update=true, $a_self_ass=false)
(De-)activate elements
moveContentBefore($a_source, $a_target, $a_spcid="", $a_tpcid="")
move content object from position $a_source before position $a_target (both hierarchical content ids)
getEditLockInfo()
Get edit lock info.
hasDuplicatePCIds()
Get all pc ids.
getRenderedContent()
Get Rendered Content.
resolveResources($ref_mapping)
Resolve resources.
removeQuestions(&$temp_dom)
Remove questions from document.
setRenderedContent($a_renderedcontent)
Set Rendered Content.
getOfflineHandler()
Get offline handler.
__beforeDelete()
Before deletion handler (internal).
getRenderMd5()
Get Render MD5.
deleteStyleUsages($a_old_nr=0)
Delete style usages.
__construct($a_id=0, $a_old_nr=0, $a_lang="-")
Constructor @access public.
initPageConfig()
Init page config.
read()
Read page data.
getRepoObjId()
Get object id of repository object that contains this page, return 0 if page does not belong to a rep...
getLastChangeUser()
Get last change user.
static _writeActive( $a_id, $a_parent_type, $a_active, $a_reset_scheduled_activation=true, $a_lang="-")
write activation status
containsIntLinks($a_content)
Check whether content contains internal links.
static getPageContributors($a_parent_type, $a_page_id, $a_lang="-")
Get all contributors for parent object.
registerOfflineHandler($handler)
static getNewPages($a_parent_type, $a_parent_id, $a_lang="-")
Get new pages.
static _existsAndNotEmpty($a_parent_type, $a_id, $a_lang="-")
Checks whether page exists and is not empty (may return true on some empty pages)
getFirstColumnIds()
get ids of all first table columns
setActivationEnd($a_activationend)
Set Activation End.
getHistoryInfo($a_nr)
Get information about a history entry, its predecessor and its successor.
saveInitialOpenedContent($a_type, $a_id, $a_target)
Save initial opened content.
addFileSizes()
add file sizes
deleteInternalLinks()
Delete internal links.
deleteContent($a_hid, $a_update=true, $a_pcid="")
delete content object with hierarchical id $a_hid
static _lookupActive($a_id, $a_parent_type, $a_check_scheduled_activation=false, $a_lang="-")
lookup activation status
getLanguage()
Get language.
static truncateHTML( $a_text, $a_length=100, $a_ending='...', $a_exact=false, $a_consider_html=true)
Truncate (html) string.
getPageConfig()
Get page config object.
setContainsIntLink($a_contains_link)
lm parser set this flag to true, if the page contains intern links (this method should only be called...
pasteContents($a_hier_id, $a_self_ass=false)
Paste contents from pc clipboard.
__afterHistoryEntry($a_old_domdoc, $a_old_content, $a_old_nr)
Before deletion handler (internal).
getEditLock()
Get page lock.
setImportMode($a_val)
Set import mode.
getParentContentObjectForPcId($pcid)
Get parent content object for pc id.
addUpdateListener(&$a_object, $a_method, $a_parameters="")
insertInstIntoIDs($a_inst, $a_res_ref_to_obj_id=true)
inserts installation id into ids (e.g.
getXMLFromDom( $a_incl_head=false, $a_append_mobs=false, $a_append_bib=false, $a_append_str="", $a_omit_pageobject_tag=false, $style_id=0)
get xml content of page from dom (use this, if any changes are made to the document)
afterUpdate()
After update.
setLanguage($a_val)
Set language.
newMobCopies($temp_dom)
Replaces media objects with copies.
getInitialOpenedContent()
Get initial opened content.
create()
create new page (with current xml data)
countPageContents()
Remove questions from document.
saveStyleUsage($a_domdoc, $a_old_nr=0)
Save all style class/template usages.
setActivationStart($a_activationstart)
Set Activation Start.
insertContentNode(&$a_cont_node, $a_pos, $a_mode=IL_INSERT_AFTER, $a_pcid="")
insert a content node before/after a sibling or as first child of a parent
getDuplicatePCIds()
Get all duplicate PC Ids.
deleteContentBeforeHierId($a_hid, $a_update=true)
delete content object with hierarchical id < $a_hid
increaseViewCnt()
Increase view cnt.
static _handleImportRepositoryLinks($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
Change targest of repository links.
updateFromXML()
Updates page object with current xml content This function is currently (4.4.0 alpha) called by:
getPCModel()
Get page component model.
buildDom($a_force=false)
setRenderedTime($a_renderedtime)
Set Rendered Time.
getContainsQuestion()
Get contains question.
existsPCId($a_pc_id)
existsPCId
getActivationEnd()
Get Activation End.
deleteContentFromHierId($a_hid, $a_update=true)
delete content object with hierarchical id >= $a_hid
getXMLContent($a_incl_head=false)
get xml content of page
getLastUpdateOfIncludedElements()
Get last update of included elements (media objects and files).
afterConstructor()
After constructor.
static _lookupContainsDeactivatedElements($a_id, $a_parent_type, $a_lang="-")
lookup whether page contains deactivated elements
cutContents($a_hids)
Copy contents to clipboard and cut them from the page.
getPCIdForHierId($hier_id)
getLanguageVariablesXML($style_id=0)
Get language variables as XML.
resolveFileItems($a_mapping)
Resolve file items (after import)
setLastChange($a_lastchange)
Set Last Change.
resolveMediaAliases($a_mapping, $a_reuse_existing_by_import=false)
Resolve media aliases (after import)
handleImportRepositoryLink($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
static lookupParentId($a_id, $a_type)
Lookup parent id.
getHierIds()
get all hierarchical ids
resolveIntLinks($a_link_map=null)
Resolves all internal link targets of the page, if targets are available (after import)
appendLangVarXML(&$xml, $var)
containsIntLink()
returns true, if page was marked as containing an intern link (via setContainsIntLink) (this method s...
getPCIdsForHierIds($hier_ids)
Get hier ids for a set of pc ids.
setShowActivationInfo($a_val)
Set show page activation info.
generatePcId($a_pc_ids=false)
Generate new pc id.
setRenderMd5($a_rendermd5)
Set Render MD5.
newQuestionCopies(&$temp_dom)
Replaces existing question content elements with new copies.
getActivationStart()
Get Activation Start.
getMultimediaXML()
get a xml string that contains all media object elements, that are referenced by any media alias in t...
getParentType()
Get parent type.
static _lookupActivationData($a_id, $a_parent_type, $a_lang="-")
Lookup activation data.
static lookupTranslations($a_parent_type, $a_id)
Lookup translations.
getContentObject($a_hier_id, $a_pc_id="")
Get a content object of the page.
saveInternalLinks($a_domdoc)
save internal links of page
handleRepositoryLinksOnCopy($a_mapping, $a_source_ref_id)
Handle repository links on copy process.
static getPagesWithLinks($a_parent_type, $a_parent_id, $a_lang="-")
Get all pages for parent object that contain internal links.
getPageContentsHashes()
Get page contents hashes.
getHistoryEntry($a_old_nr)
Get History Entry.
getContentTemplates()
Get content templates.
static _exists($a_parent_type, $a_id, $a_lang="", $a_no_cache=false)
Checks whether page exists.
static getAllPages($a_parent_type, $a_parent_id, $a_lang="-")
Get all pages for parent object.
setXMLContent($a_xml, $a_encoding="UTF-8")
set xml content of page, start with <PageObject...>, end with </PageObject>, comply with ILIAS DTD,...
setPageConfig($a_val)
Set page config object.
collectMediaObjects($a_inline_only=true)
get all media objects, that are referenced and used within the page
getAllFileObjIds()
Get all file object ids.
moveIntLinks($a_from_to)
Move internal links from one destination to another.
getFirstRowIds()
get ids of all first table rows
getMediaAliasElement($a_mob_id, $a_nr=1)
get complete media object (alias) element
getQuestionIds()
Get question ids.
checkPCIds()
Check, whether (all) page content hashes are set.
getDom()
Deprecated php4DomDocument.
getDomDoc()
Get dom doc (php5 dom document)
copy($a_id, $a_parent_type="", $a_parent_id=0, $a_clone_mobs=false)
Copy page.
copyXmlContent($a_clone_mobs=false)
Copy content of page; replace page components with copies where necessary (e.g.
getContentObjectForPcId($pcid)
Get content object for pc id.
getFO()
get fo page content
copyPageToTranslation($a_target_lang)
Copy page to translation.
setActive($a_active)
set activation
addHierIDs()
Add hierarchical ID (e.g.
checkForTag($a_content_tag, $a_hier_id, $a_pc_id="")
Get content node from dom.
setId($a_id)
set id
validateDom(bool $throw=false)
Validate the page content agains page DTD.
insertPCIds()
Insert Page Content IDs.
containsDeactivatedElements($a_content)
Check whether content contains deactivated elements.
compareVersion($a_left, $a_right)
Compares to revisions of the page.
getAllPCIds()
Get all pc ids.
performAutomaticModifications()
Perform automatic modifications (may be overwritten by sub classes)
getFileItemIds()
get ids of all file items
getHistoryEntries()
Get History Entries.
static getParentObjectContributors($a_parent_type, $a_parent_id, $a_lang="-")
Get all contributors for parent object.
getLastChange()
Get Last Change.
lookforhier($a_hier_id)
getShowActivationInfo()
Get show page activation info.
resolveQuestionReferences($a_mapping)
Resolve all quesion references (after import)
bbCode2XML(&$a_content)
transforms bbCode to corresponding xml
& getContentNode($a_hier_id, $a_pc_id="")
Get content node from dom.
static getRecentChanges($a_parent_type, $a_parent_id, $a_period=30, $a_lang="")
Get recent pages changes for parent object.
handleCopiedContent($a_dom, $a_self_ass=true, $a_clone_mobs=false)
Handle copied content This function copies items, that must be copied, if page content is duplicated.
assignCharacteristic($targets, $char_par, $char_sec, $char_med)
Assign characteristic.
writeRenderedContent($a_content, $a_md5)
Write rendered content.
needsImportParsing($a_parse="")
static preloadActivationDataByParentId($a_parent_id)
Preload activation data by Parent Id.
addChangeDivClasses($a_hashes)
getListItemIds()
get ids of all list items
static getLastChangeByParent($a_parent_type, $a_parent_id, $a_lang="")
Get all pages for parent object.
createFromXML()
Create new page object with current xml content.
newIIMCopies($temp_dom)
Replaces media objects in interactive images with copies of the interactive images.
__afterUpdate($a_domdoc, $a_xml, $a_creation=false, $a_empty=false)
After update event handler (internal).
getHierIdsForPCIds($a_pc_ids)
Get hier ids for a set of pc ids.
static _isScheduledActivation($a_id, $a_parent_type, $a_lang="-")
Check whether page is activated by time schedule.
copyContents($a_hids)
Copy contents to clipboard.
beforePageContentUpdate($a_page_content)
Before page content update Note: This one is "work in progress", currently only text paragraphs call ...
update($a_validate=true, $a_no_history=false)
update complete page content in db (dom xml content is used)
static _writeParentId($a_parent_type, $a_pg_id, $a_par_id)
Write parent id.
getImportMode()
Get import mode.
appendXMLContent($a_xml)
append xml content to page setXMLContent must be called before and the same encoding must be used
deleteContents($a_hids, $a_update=true, $a_self_ass=false)
Delete multiple content objects.
getInternalLinks($a_cnt_multiple=false)
get all internal links that are used within the page
setContainsQuestion($a_val)
Set contains question.
moveContentAfter($a_source, $a_target, $a_spcid="", $a_tpcid="")
move content object from position $a_source before position $a_target (both hierarchical content ids)
getRenderedTime()
Get Rendered Time.
send_paragraph($par_id, $filename)
setLastChangeUser($a_val)
Set last change user.
resolveIIMMediaAliases($a_mapping)
Resolve iim media aliases (in ilContObjParse)
getActive($a_check_scheduled_activation=false)
get activation
insertContent(&$a_cont_obj, $a_pos, $a_mode=IL_INSERT_AFTER, $a_pcid="", bool $remove_placeholder=true)
insert a content node before/after a sibling or as first child of a parent
setParagraphContent($a_hier_id, $a_content)
Set content of paragraph.
static _moveContentAfterHierId(&$a_source_page, &$a_target_page, $a_hid)
move content of hierarchical id >= $a_hid to other page
static _existsAndNotEmpty($a_parent_type, $a_id, $a_lang="-")
checks whether page exists and is not empty (may return true on some empty pages)
ILIAS Setting Class.
static shortenText($a_string, $a_start_pos, $a_num_bytes, $a_encoding='UTF-8')
Shorten text to the given number of bytes.
static getNamePresentation( $a_user_id, $a_user_image=false, $a_profile_link=false, $a_profile_back_link="", $a_force_first_lastname=false, $a_omit_login=false, $a_sortable=true, $a_return_data_array=false, $a_ctrl_path="ilpublicuserprofilegui")
Default behaviour is:
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
static deliverData($a_data, $a_filename, $mime="application/octet-stream", $charset="")
deliver data for download via browser.
static now()
Return current timestamp in Y-m-d H:i:s format.
$c
Definition: cli.php:37
const CLIENT_ID
Definition: constants.php:39
const IL_INST_ID
Definition: constants.php:38
$txt
Definition: error.php:13
global $DIC
Definition: goto.php:24
$target_arr
Definition: goto.php:49
$mobs
Definition: imgupload.php:54
$errors
Definition: imgupload.php:49
const ILIAS_VERSION_NUMERIC
xslt_free(&$proc)
xslt_create()
xpath_eval($xpath_context, $eval_str, $contextnode=null)
domxml_open_mem($str, $mode=0, &$error=null)
xpath_new_context($dom_document)
const DOMXML_LOAD_PARSING
language()
Definition: language.php:2
exit
Definition: login.php:29
if($format !==null) $name
Definition: metadata.php:230
$i
Definition: metadata.php:24
$source
Definition: metadata.php:76
$ret
Definition: parser.php:6
$query
$type
$url
foreach($_POST as $key=> $value) $res
$lm_set