ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
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
8
12/*
13
14 - move dom related code to PageDom class/interface
15 - move ilDB dependency to ar object
16 - move internal links related code to extra class
17 - make factory available through DIC, opt allow decentralized factory parts
18 - PC types
19 -- internal links used/implemented?
20 -- styles used/implemented?
21 - application classes need
22 -- page object
23 --- page object should return php5 domdoc (getDom() vs getDomDoc()?)
24 esp. plugins should use this
25 -- remove content element hook, if content is not allowed
26 - PC types could move to components (e.g. blog, login)
27 - How to modularize xsl?
28 -- read from db?
29 -- xml entries say that xslt code is used -> read file and include in
30 main xslt file
31
32*/
33
45abstract class ilPageObject
46{
50 protected $obj_definition;
51
52 public static $exists = array();
53
57 protected $db;
58
62 protected $user;
63
67 protected $lng;
68
72 protected $tree;
73
77 protected $id;
78 public $dom;
79 public $xml;
80 public $encoding;
81 public $node;
82 public $cur_dtd = "ilias_pg_5_4.dtd";
86 public $parent_id;
92
96 protected $language = "-";
97
101 protected static $activation_data = array();
102
106 protected $import_mode = false;
107
111 protected $log;
112
116 protected $page_record = array();
117
121 protected $active = false;
122
126 protected $page_config;
127
132 final public function __construct($a_id = 0, $a_old_nr = 0, $a_lang = "-")
133 {
134 global $DIC;
135 $this->obj_definition = $DIC["objDefinition"];
136 $this->db = $DIC->database();
137 $this->user = $DIC->user();
138 $this->lng = $DIC->language();
139 $this->tree = $DIC->repositoryTree();
140 $this->log = ilLoggerFactory::getLogger('copg');
141
142 $this->parent_type = $this->getParentType();
143 $this->id = $a_id;
144 $this->setLanguage($a_lang);
145
146 $this->contains_int_link = false;
147 $this->needs_parsing = false;
148 $this->update_listeners = array();
149 $this->update_listener_cnt = 0;
150 $this->dom_builded = false;
151 $this->page_not_found = false;
152 $this->old_nr = $a_old_nr;
153 $this->encoding = "UTF-8";
154 $this->id_elements =
155 array("PageContent", "TableRow", "TableData", "ListItem", "FileItem",
156 "Section", "Tab", "ContentPopup", "GridCell");
157 $this->setActive(true);
158 $this->show_page_act_info = false;
159
160 if ($a_id != 0) {
161 $this->read();
162 }
163
164 $this->initPageConfig();
165
166 $this->afterConstructor();
167 }
168
172 public function afterConstructor()
173 {
174 }
175
176
182 abstract public function getParentType();
183
184
188 final public function initPageConfig()
189 {
190 include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
192 $this->setPageConfig($cfg);
193 }
194
200 public function setLanguage($a_val)
201 {
202 $this->language = $a_val;
203 }
204
210 public function getLanguage()
211 {
212 return $this->language;
213 }
214
220 public function setPageConfig($a_val)
221 {
222 $this->page_config = $a_val;
223 }
224
230 public function getPageConfig()
231 {
232 return $this->page_config;
233 }
234
240 public function setRenderMd5($a_rendermd5)
241 {
242 $this->rendermd5 = $a_rendermd5;
243 }
244
250 public function getRenderMd5()
251 {
252 return $this->rendermd5;
253 }
254
260 public function setRenderedContent($a_renderedcontent)
261 {
262 $this->renderedcontent = $a_renderedcontent;
263 }
264
270 public function getRenderedContent()
271 {
272 return $this->renderedcontent;
273 }
274
280 public function setRenderedTime($a_renderedtime)
281 {
282 $this->renderedtime = $a_renderedtime;
283 }
284
290 public function getRenderedTime()
291 {
292 return $this->renderedtime;
293 }
294
300 public function setLastChange($a_lastchange)
301 {
302 $this->lastchange = $a_lastchange;
303 }
304
310 public function getLastChange()
311 {
312 return $this->lastchange;
313 }
314
320 public function setLastChangeUser($a_val)
321 {
322 $this->last_change_user = $a_val;
323 }
324
330 public function getLastChangeUser()
331 {
332 return $this->last_change_user;
333 }
334
340 public function setShowActivationInfo($a_val)
341 {
342 $this->show_page_act_info = $a_val;
343 }
344
350 public function getShowActivationInfo()
351 {
352 return $this->show_page_act_info;
353 }
354
358 public function read()
359 {
360 $this->setActive(true);
361 if ($this->old_nr == 0) {
362 $query = "SELECT * FROM page_object" .
363 " WHERE page_id = " . $this->db->quote($this->id, "integer") .
364 " AND parent_type=" . $this->db->quote($this->getParentType(), "text") .
365 " AND lang = " . $this->db->quote($this->getLanguage(), "text");
366 $pg_set = $this->db->query($query);
367 $this->page_record = $this->db->fetchAssoc($pg_set);
368 $this->setActive($this->page_record["active"]);
369 $this->setActivationStart($this->page_record["activation_start"]);
370 $this->setActivationEnd($this->page_record["activation_end"]);
371 $this->setShowActivationInfo($this->page_record["show_activation_info"]);
372 } else {
373 $query = "SELECT * FROM page_history" .
374 " WHERE page_id = " . $this->db->quote($this->id, "integer") .
375 " AND parent_type=" . $this->db->quote($this->getParentType(), "text") .
376 " AND nr = " . $this->db->quote((int) $this->old_nr, "integer") .
377 " AND lang = " . $this->db->quote($this->getLanguage(), "text");
378 $pg_set = $this->db->query($query);
379 $this->page_record = $this->db->fetchAssoc($pg_set);
380 }
381 if (!$this->page_record) {
382 include_once("./Services/COPage/exceptions/class.ilCOPageNotFoundException.php");
383 throw new ilCOPageNotFoundException("Error: Page " . $this->id . " is not in database" .
384 " (parent type " . $this->getParentType() . ", lang: " . $this->getLanguage() . ").");
385 }
386
387 $this->xml = $this->page_record["content"];
388 $this->setParentId($this->page_record["parent_id"]);
389 $this->last_change_user = $this->page_record["last_change_user"];
390 $this->create_user = $this->page_record["create_user"];
391 $this->setRenderedContent($this->page_record["rendered_content"]);
392 $this->setRenderMd5($this->page_record["render_md5"]);
393 $this->setRenderedTime($this->page_record["rendered_time"]);
394 $this->setLastChange($this->page_record["last_change"]);
395 }
396
404 public static function _exists($a_parent_type, $a_id, $a_lang = "", $a_no_cache = false)
405 {
406 global $DIC;
407
408 $db = $DIC->database();
409
410 if (!$a_no_cache && isset(self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang])) {
411 return self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang];
412 }
413
414 $and_lang = "";
415 if ($a_lang != "") {
416 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
417 }
418
419 $query = "SELECT page_id FROM page_object WHERE page_id = " . $db->quote($a_id, "integer") . " " .
420 "AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang;
421 $set = $db->query($query);
422 if ($row = $db->fetchAssoc($set)) {
423 self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang] = true;
424 return true;
425 } else {
426 self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang] = false;
427 return false;
428 }
429 }
430
438 public static function _existsAndNotEmpty($a_parent_type, $a_id, $a_lang = "-")
439 {
440 include_once("./Services/COPage/classes/class.ilPageUtil.php");
441 return ilPageUtil::_existsAndNotEmpty($a_parent_type, $a_id, $a_lang);
442 }
443
444 public function buildDom($a_force = false)
445 {
446 if ($this->dom_builded && !$a_force) {
447 return;
448 }
449
450 //echo "\n<br>buildDomWith:".$this->getId().":xml:".$this->getXMLContent(true).":<br>";
451
452 $options = 0;
453 //$options = DOMXML_LOAD_VALIDATING;
454 //$options = LIBXML_DTDLOAD;
455 //$options = LIBXML_NOXMLDECL;
456 //echo htmlentities($this->getXMLContent(true))."<br>";
457 $this->dom = @domxml_open_mem($this->getXMLContent(true), $options, $error);
458 //var_dump($error);
459 $xpc = xpath_new_context($this->dom);
460 $path = "//PageObject";
461 $res = xpath_eval($xpc, $path);
462 if (count($res->nodeset) == 1) {
463 // echo "h";
464 $this->node = $res->nodeset[0];
465 }
466 //echo htmlentities($this->dom->dump_node($this->node)); exit;
467
468 if (empty($error)) {
469 $this->dom_builded = true;
470 return true;
471 } else {
472 return $error;
473 }
474 }
475
476 public function freeDom()
477 {
478 //$this->dom->free();
479 unset($this->dom);
480 }
481
485 public function getDom()
486 {
487 return $this->dom;
488 }
489
496 public function getDomDoc()
497 {
498 if ($this->dom instanceof php4DOMDocument) {
499 return $this->dom->myDOMDocument;
500 }
501
502 return $this->dom;
503 }
504
505
509 public function setId($a_id)
510 {
511 $this->id = $a_id;
512 }
513
514 public function getId()
515 {
516 return $this->id;
517 }
518
519 public function setParentId($a_id)
520 {
521 $this->parent_id = $a_id;
522 }
523
524 public function getParentId()
525 {
526 return $this->parent_id;
527 }
528
529 public function addUpdateListener(&$a_object, $a_method, $a_parameters = "")
530 {
532 $this->update_listeners[$cnt]["object"] = $a_object;
533 $this->update_listeners[$cnt]["method"] = $a_method;
534 $this->update_listeners[$cnt]["parameters"] = $a_parameters;
535 $this->update_listener_cnt++;
536 }
537
538 public function callUpdateListeners()
539 {
540 for ($i = 0; $i < $this->update_listener_cnt; $i++) {
541 $object = $this->update_listeners[$i]["object"];
542 $method = $this->update_listeners[$i]["method"];
543 $parameters = $this->update_listeners[$i]["parameters"];
544 $object->$method($parameters);
545 }
546 }
547
553 public function setActive($a_active)
554 {
555 $this->active = $a_active;
556 }
557
563 public function getActive($a_check_scheduled_activation = false)
564 {
565 if ($a_check_scheduled_activation && !$this->active) {
566 include_once("./Services/Calendar/classes/class.ilDateTime.php");
567 $start = new ilDateTime($this->getActivationStart(), IL_CAL_DATETIME);
568 $end = new ilDateTime($this->getActivationEnd(), IL_CAL_DATETIME);
569 $now = new ilDateTime(time(), IL_CAL_UNIX);
570 if (!ilDateTime::_before($now, $start) && !ilDateTime::_after($now, $end)) {
571 return true;
572 }
573 }
574 return $this->active;
575 }
576
582 public static function preloadActivationDataByParentId($a_parent_id)
583 {
584 global $DIC;
585
586 $db = $DIC->database();
587 $set = $db->query(
588 "SELECT page_id, parent_type, lang, active, activation_start, activation_end, show_activation_info FROM page_object " .
589 " WHERE parent_id = " . $db->quote($a_parent_id, "integer")
590 );
591 while ($rec = $db->fetchAssoc($set)) {
592 self::$activation_data[$rec["page_id"] . ":" . $rec["parent_type"] . ":" . $rec["lang"]] = $rec;
593 }
594 }
595
596
600 public static function _lookupActive($a_id, $a_parent_type, $a_check_scheduled_activation = false, $a_lang = "-")
601 {
602 global $DIC;
603
604 $db = $DIC->database();
605
606 // language must be set at least to "-"
607 if ($a_lang == "") {
608 $a_lang = "-";
609 }
610
611 if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
612 $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
613 } else {
614 $set = $db->queryF(
615 "SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s" .
616 " AND parent_type = %s AND lang = %s",
617 array("integer", "text", "text"),
618 array($a_id, $a_parent_type, $a_lang)
619 );
620 $rec = $db->fetchAssoc($set);
621 }
622
623
624 $rec["n"] = ilUtil::now();
625
626 if (!$rec["active"] && $a_check_scheduled_activation) {
627 if ($rec["n"] >= $rec["activation_start"] &&
628 $rec["n"] <= $rec["activation_end"]) {
629 return true;
630 }
631 }
632
633 return $rec["active"];
634 }
635
639 public static function _isScheduledActivation($a_id, $a_parent_type, $a_lang = "-")
640 {
641 global $DIC;
642
643 $db = $DIC->database();
644
645 // language must be set at least to "-"
646 if ($a_lang == "") {
647 $a_lang = "-";
648 }
649
650 //echo "<br>";
651 //var_dump(self::$activation_data); exit;
652 if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
653 $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
654 } else {
655 $set = $db->queryF(
656 "SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s" .
657 " AND parent_type = %s AND lang = %s",
658 array("integer", "text", "text"),
659 array($a_id, $a_parent_type, $a_lang)
660 );
661 $rec = $db->fetchAssoc($set);
662 }
663
664 if (!$rec["active"] && $rec["activation_start"] != "") {
665 return true;
666 }
667
668 return false;
669 }
670
674 public static function _writeActive($a_id, $a_parent_type, $a_active, $a_reset_scheduled_activation = true, $a_lang = "-")
675 {
676 global $DIC;
677
678 $db = $DIC->database();
679
680 // language must be set at least to "-"
681 if ($a_lang == "") {
682 $a_lang = "-";
683 }
684
685 if ($a_reset_scheduled_activation) {
686 $st = $db->manipulateF(
687 "UPDATE page_object SET active = %s, activation_start = %s, " .
688 " activation_end = %s WHERE page_id = %s" .
689 " AND parent_type = %s AND lang = %s",
690 array("boolean", "timestamp", "timestamp", "integer", "text", "text"),
691 array($a_active, null, null, $a_id, $a_parent_type, $a_lang)
692 );
693 } else {
694 $st = $db->prepareManip(
695 "UPDATE page_object SET active = %s WHERE page_id = %s" .
696 " AND parent_type = %s AND lang = %s",
697 array("boolean", "integer", "text", "text"),
698 array($a_active, $a_id, $a_parent_type, $a_lang)
699 );
700 }
701 }
702
706 public static function _lookupActivationData($a_id, $a_parent_type, $a_lang = "-")
707 {
708 global $DIC;
709
710 $db = $DIC->database();
711
712 // language must be set at least to "-"
713 if ($a_lang == "") {
714 $a_lang = "-";
715 }
716
717 if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
718 $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
719 } else {
720 $set = $db->queryF(
721 "SELECT active, activation_start, activation_end, show_activation_info FROM page_object WHERE page_id = %s" .
722 " AND parent_type = %s AND lang = %s",
723 array("integer", "text", "text"),
724 array($a_id, $a_parent_type, $a_lang)
725 );
726 $rec = $db->fetchAssoc($set);
727 }
728
729 return $rec;
730 }
731
732
736 public static function lookupParentId($a_id, $a_type)
737 {
738 global $DIC;
739
740 $db = $DIC->database();
741
742 $res = $db->query("SELECT parent_id FROM page_object WHERE page_id = " . $db->quote($a_id, "integer") . " " .
743 "AND parent_type=" . $db->quote($a_type, "text"));
744 $rec = $db->fetchAssoc($res);
745 return $rec["parent_id"];
746 }
747
751 public static function _writeParentId($a_parent_type, $a_pg_id, $a_par_id)
752 {
753 global $DIC;
754
755 $db = $DIC->database();
756 $db->manipulateF(
757 "UPDATE page_object SET parent_id = %s WHERE page_id = %s" .
758 " AND parent_type = %s",
759 array("integer", "integer", "text"),
760 array($a_par_id, $a_pg_id, $a_parent_type)
761 );
762 }
763
769 public function setActivationStart($a_activationstart)
770 {
771 if ($a_activationstart == "") {
772 $a_activationstart = null;
773 }
774 $this->activationstart = $a_activationstart;
775 }
776
782 public function getActivationStart()
783 {
784 return $this->activationstart;
785 }
786
792 public function setActivationEnd($a_activationend)
793 {
794 if ($a_activationend == "") {
795 $a_activationend = null;
796 }
797 $this->activationend = $a_activationend;
798 }
799
805 public function getActivationEnd()
806 {
807 return $this->activationend;
808 }
809
818 public function getContentObject($a_hier_id, $a_pc_id = "")
819 {
820 $cont_node = $this->getContentNode($a_hier_id, $a_pc_id);
821 if (!is_object($cont_node)) {
822 return false;
823 }
824 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
825 $node_name = $cont_node->node_name();
826 if ($node_name == "PageObject") {
827 return null;
828 }
829 if ($node_name == "PageContent") {
830 $child_node = $cont_node->first_child();
831 $node_name = $child_node->node_name();
832 }
833
834 // table extra handling (@todo: get rid of it)
835 if ($node_name == "Table") {
836 if ($child_node->get_attribute("DataTable") == "y") {
837 require_once("./Services/COPage/classes/class.ilPCDataTable.php");
838 $tab = new ilPCDataTable($this);
839 $tab->setNode($cont_node);
840 $tab->setHierId($a_hier_id);
841 } else {
842 require_once("./Services/COPage/classes/class.ilPCTable.php");
843 $tab = new ilPCTable($this);
844 $tab->setNode($cont_node);
845 $tab->setHierId($a_hier_id);
846 }
847 $tab->setPcId($a_pc_id);
848 return $tab;
849 }
850
851 // media extra handling (@todo: get rid of it)
852 if ($node_name == "MediaObject") {
853 if ($_GET["pgEdMediaMode"] != "") {
854 echo "ilPageObject::error media";
855 exit;
856 }
857
858 //require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
859 require_once("./Services/COPage/classes/class.ilPCMediaObject.php");
860
861 $mal_node = $child_node->first_child();
862 //echo "ilPageObject::getContentObject:nodename:".$mal_node->node_name().":<br>";
863 $id_arr = explode("_", $mal_node->get_attribute("OriginId"));
864 $mob_id = $id_arr[count($id_arr) - 1];
865
866 // allow deletion of non-existing media objects
867 if (!ilObject::_exists($mob_id) && in_array("delete", $_POST)) {
868 $mob_id = 0;
869 }
870
871 //$mob = new ilObjMediaObject($mob_id);
872 $mob = new ilPCMediaObject($this);
873 $mob->readMediaObject($mob_id);
874
875 //$mob->setDom($this->dom);
876 $mob->setNode($cont_node);
877 $mob->setHierId($a_hier_id);
878 $mob->setPcId($a_pc_id);
879 return $mob;
880 }
881
882 //
883 // generic procedure
884 //
885
886 $pc_def = ilCOPagePCDef::getPCDefinitionByName($node_name);
887
888 // check if pc definition has been found
889 if (!is_array($pc_def)) {
890 include_once("./Services/COPage/exceptions/class.ilCOPageUnknownPCTypeException.php");
891 throw new ilCOPageUnknownPCTypeException('Unknown PC Name "' . $node_name . '".');
892 }
893 $pc_class = "ilPC" . $pc_def["name"];
894 $pc_path = "./" . $pc_def["component"] . "/" . $pc_def["directory"] . "/class." . $pc_class . ".php";
895 require_once($pc_path);
896 $pc = new $pc_class($this);
897 $pc->setNode($cont_node);
898 $pc->setHierId($a_hier_id);
899 $pc->setPcId($a_pc_id);
900 return $pc;
901 }
902
909 public function &getContentNode($a_hier_id, $a_pc_id = "")
910 {
911 $xpc = xpath_new_context($this->dom);
912 if ($a_hier_id == "pg") {
913 return $this->node;
914 } else {
915 // get per pc id
916 if ($a_pc_id != "") {
917 $path = "//*[@PCID = '$a_pc_id']";
918 $res = xpath_eval($xpc, $path);
919 if (count($res->nodeset) == 1) {
920 $cont_node = $res->nodeset[0];
921 return $cont_node;
922 }
923 }
924
925 // fall back to hier id
926 $path = "//*[@HierId = '$a_hier_id']";
927 $res = xpath_eval($xpc, $path);
928 if (count($res->nodeset) == 1) {
929 $cont_node = $res->nodeset[0];
930 return $cont_node;
931 }
932 }
933 }
934
941 public function checkForTag($a_content_tag, $a_hier_id, $a_pc_id = "")
942 {
943 $xpc = xpath_new_context($this->dom);
944 // get per pc id
945 if ($a_pc_id != "") {
946 $path = "//*[@PCID = '$a_pc_id']//" . $a_content_tag;
947 $res = xpath_eval($xpc, $path);
948 if (count($res->nodeset) > 0) {
949 return true;
950 }
951 }
952
953 // fall back to hier id
954 $path = "//*[@HierId = '$a_hier_id']//" . $a_content_tag;
955 $res = xpath_eval($xpc, $path);
956 if (count($res->nodeset) > 0) {
957 return true;
958 }
959 return false;
960 }
961
962 // only for test purposes
963 public function lookforhier($a_hier_id)
964 {
965 $xpc = xpath_new_context($this->dom);
966 $path = "//*[@HierId = '$a_hier_id']";
967 $res = xpath_eval($xpc, $path);
968 if (count($res->nodeset) == 1) {
969 return "YES";
970 } else {
971 return "NO";
972 }
973 }
974
975
976 public function &getNode()
977 {
978 return $this->node;
979 }
980
981
990 public function setXMLContent($a_xml, $a_encoding = "UTF-8")
991 {
992 $this->encoding = $a_encoding;
993 $this->xml = $a_xml;
994 }
995
1002 public function appendXMLContent($a_xml)
1003 {
1004 $this->xml .= $a_xml;
1005 }
1006
1007
1011 public function getXMLContent($a_incl_head = false)
1012 {
1013 // build full http path for XML DOCTYPE header.
1014 // Under windows a relative path doesn't work :-(
1015 if ($a_incl_head) {
1016 //echo "+".$this->encoding."+";
1017 $enc_str = (!empty($this->encoding))
1018 ? "encoding=\"" . $this->encoding . "\""
1019 : "";
1020 return "<?xml version=\"1.0\" $enc_str ?>" .
1021 "<!DOCTYPE PageObject SYSTEM \"" . ILIAS_ABSOLUTE_PATH . "/xml/" . $this->cur_dtd . "\">" .
1022 $this->xml;
1023 } else {
1024 return $this->xml;
1025 }
1026 }
1027
1032 public function copyXmlContent($a_clone_mobs = false)
1033 {
1034 $xml = $this->getXmlContent();
1035 $temp_dom = domxml_open_mem(
1036 '<?xml version="1.0" encoding="UTF-8"?>' . $xml,
1038 $error
1039 );
1040 if (empty($error)) {
1041 $this->handleCopiedContent($temp_dom, true, $a_clone_mobs);
1042 }
1043 $xml = $temp_dom->dump_mem(0, $this->encoding);
1044 $xml = preg_replace('/<\?xml[^>]*>/i', "", $xml);
1045 $xml = preg_replace('/<!DOCTYPE[^>]*>/i', "", $xml);
1046
1047 return $xml;
1048 }
1049
1050 // @todo 1: begin: generalize, remove concrete dependencies
1051
1067 public function handleCopiedContent($a_dom, $a_self_ass = true, $a_clone_mobs = false)
1068 {
1069 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1071
1072 // handle question elements
1073 if ($a_self_ass) {
1074 $this->newQuestionCopies($a_dom);
1075 } else {
1076 $this->removeQuestions($a_dom);
1077 }
1078
1079 // handle interactive images
1080 $this->newIIMCopies($a_dom);
1081
1082 // handle media objects
1083 if ($a_clone_mobs) {
1084 $this->newMobCopies($a_dom);
1085 }
1086
1087 // @todo 1: move all functions from above to the new domdoc
1088 if ($a_dom instanceof php4DOMDocument) {
1089 $a_dom = $a_dom->myDOMDocument;
1090 }
1091 foreach ($defs as $def) {
1093 $cl = $def["pc_class"];
1094 if ($cl == 'ilPCPlugged') {
1095 // the page object is provided for ilPageComponentPlugin
1096 ilPCPlugged::handleCopiedPluggedContent($this, $a_dom);
1097 } else {
1098 $cl::handleCopiedContent($a_dom, $a_self_ass, $a_clone_mobs);
1099 }
1100 }
1101 }
1102
1110 public function handleDeleteContent($a_node = null)
1111 {
1112 if (!isset($a_node)) {
1113 $xpc = xpath_new_context($this->dom);
1114 $path = "//PageContent";
1115 $res = xpath_eval($xpc, $path);
1116 $nodes = $res->nodeset;
1117 } else {
1118 $nodes = array($a_node);
1119 }
1120
1121 require_once('Services/COPage/classes/class.ilPCPlugged.php');
1122 foreach ($nodes as $node) {
1123 if ($node instanceof php4DOMNode) {
1124 $node = $node->myDOMNode;
1125 }
1126
1128 if ($node->firstChild->nodeName == 'Plugged') {
1129 ilPCPlugged::handleDeletedPluggedNode($this, $node->firstChild);
1130 }
1131 }
1132 }
1133
1138 public function newIIMCopies($temp_dom)
1139 {
1140 // Get question IDs
1141 $path = "//InteractiveImage/MediaAlias";
1142 $xpc = xpath_new_context($temp_dom);
1143 $res = &xpath_eval($xpc, $path);
1144
1145 $q_ids = array();
1146 include_once("./Services/Link/classes/class.ilInternalLink.php");
1147 for ($i = 0; $i < count($res->nodeset); $i++) {
1148 $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1149
1150 $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1151 $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1152
1153 if (!($inst_id > 0)) {
1154 if ($mob_id > 0) {
1155 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1156 $media_object = new ilObjMediaObject($mob_id);
1157
1158 // now copy this question and change reference to
1159 // new question id
1160 $new_mob = $media_object->duplicate();
1161
1162 $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $new_mob->getId());
1163 }
1164 }
1165 }
1166 }
1167
1171 public function newMobCopies($temp_dom)
1172 {
1173 // Get question IDs
1174 $path = "//MediaObject/MediaAlias";
1175 $xpc = xpath_new_context($temp_dom);
1176 $res = &xpath_eval($xpc, $path);
1177
1178 $q_ids = array();
1179 include_once("./Services/Link/classes/class.ilInternalLink.php");
1180 for ($i = 0; $i < count($res->nodeset); $i++) {
1181 $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1182
1183 $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1184 $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1185
1186 if (!($inst_id > 0)) {
1187 if ($mob_id > 0) {
1188 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1189 $media_object = new ilObjMediaObject($mob_id);
1190
1191 // now copy this question and change reference to
1192 // new question id
1193 $new_mob = $media_object->duplicate();
1194
1195 $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $new_mob->getId());
1196 }
1197 }
1198 }
1199 }
1200
1205 public function newQuestionCopies(&$temp_dom)
1206 {
1207 // Get question IDs
1208 $path = "//Question";
1209 $xpc = xpath_new_context($temp_dom);
1210 $res = &xpath_eval($xpc, $path);
1211
1212 $q_ids = array();
1213 include_once("./Services/Link/classes/class.ilInternalLink.php");
1214 for ($i = 0; $i < count($res->nodeset); $i++) {
1215 $qref = $res->nodeset[$i]->get_attribute("QRef");
1216
1217 $inst_id = ilInternalLink::_extractInstOfTarget($qref);
1219
1220 if (!($inst_id > 0)) {
1221 if ($q_id > 0) {
1222 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1223 $question = assQuestion::_instantiateQuestion($q_id);
1224 // check due to #16557
1225 if (is_object($question) && $question->isComplete()) {
1226 // check if page for question exists
1227 // due to a bug in early 4.2.x version this is possible
1228 if (!ilPageObject::_exists("qpl", $q_id)) {
1229 $question->createPageObject();
1230 }
1231
1232 // now copy this question and change reference to
1233 // new question id
1234 $duplicate_id = $question->duplicate(false);
1235 $res->nodeset[$i]->set_attribute("QRef", "il__qst_" . $duplicate_id);
1236 }
1237 }
1238 }
1239 }
1240 }
1241
1248 public function removeQuestions(&$temp_dom)
1249 {
1250 // Get question IDs
1251 $path = "//Question";
1252 $xpc = xpath_new_context($temp_dom);
1253 $res = &xpath_eval($xpc, $path);
1254 for ($i = 0; $i < count($res->nodeset); $i++) {
1255 $parent_node = $res->nodeset[$i]->parent_node();
1256 $parent_node->unlink_node($parent_node);
1257 }
1258 }
1259
1260 // @todo: end
1261
1268 public function countPageContents()
1269 {
1270 // Get question IDs
1271 $this->buildDom();
1272 $path = "//PageContent";
1273 $xpc = xpath_new_context($this->dom);
1274 $res = &xpath_eval($xpc, $path);
1275 return count($res->nodeset);
1276 }
1277
1282 public function getXMLFromDom(
1283 $a_incl_head = false,
1284 $a_append_mobs = false,
1285 $a_append_bib = false,
1286 $a_append_str = "",
1287 $a_omit_pageobject_tag = false
1288 ) {
1289 if ($a_incl_head) {
1290 //echo "\n<br>#".$this->encoding."#";
1291 return $this->dom->dump_mem(0, $this->encoding);
1292 } else {
1293 // append multimedia object elements
1294 if ($a_append_mobs || $a_append_bib || $a_append_link_info) {
1295 $mobs = "";
1296 $bibs = "";
1297 if ($a_append_mobs) {
1298 $mobs = $this->getMultimediaXML();
1299 }
1300 if ($a_append_bib) {
1301 // deprecated
1302// $bibs = $this->getBibliographyXML();
1303 }
1304 $trans = $this->getLanguageVariablesXML();
1305 //echo htmlentities($this->dom->dump_node($this->node)); exit;
1306 return "<dummy>" . $this->dom->dump_node($this->node) . $mobs . $bibs . $trans . $a_append_str . "</dummy>";
1307 } else {
1308 if (is_object($this->dom)) {
1309 if ($a_omit_pageobject_tag) {
1310 $xml = "";
1311 $childs = $this->node->child_nodes();
1312 for ($i = 0; $i < count($childs); $i++) {
1313 $xml .= $this->dom->dump_node($childs[$i]);
1314 }
1315 return $xml;
1316 } else {
1317 $xml = $this->dom->dump_mem(0, $this->encoding);
1318 $xml = preg_replace('/<\?xml[^>]*>/i', "", $xml);
1319 $xml = preg_replace('/<!DOCTYPE[^>]*>/i', "", $xml);
1320 return $xml;
1321
1322 // don't use dump_node. This gives always entities.
1323 //return $this->dom->dump_node($this->node);
1324 }
1325 } else {
1326 return "";
1327 }
1328 }
1329 }
1330 }
1331
1335 public function getLanguageVariablesXML()
1336 {
1337 $xml = "<LVs>";
1338 $lang_vars = array(
1339 "ed_paste_clip", "ed_edit", "ed_edit_prop", "ed_delete", "ed_moveafter",
1340 "ed_movebefore", "ed_go", "ed_class", "ed_width", "ed_align_left",
1341 "ed_align_right", "ed_align_center", "ed_align_left_float",
1342 "ed_align_right_float", "ed_delete_item", "ed_new_item_before",
1343 "ed_new_item_after", "ed_copy_clip", "please_select", "ed_split_page",
1344 "ed_item_up", "ed_item_down", "ed_split_page_next","ed_enable",
1345 "de_activate", "ed_paste", "ed_edit_multiple", "ed_cut", "ed_copy", "ed_insert_templ",
1346 "ed_click_to_add_pg", "download");
1347
1348 // collect lang vars from pc elements
1349 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1351 foreach ($defs as $def) {
1352 $lang_vars[] = "pc_" . $def["pc_type"];
1353 $lang_vars[] = "ed_insert_" . $def["pc_type"];
1354
1356 $cl = $def["pc_class"];
1357 $lvs = call_user_func($def["pc_class"] . '::getLangVars');
1358 foreach ($lvs as $lv) {
1359 $lang_vars[] = $lv;
1360 }
1361 }
1362
1363 foreach ($lang_vars as $lang_var) {
1364 $this->appendLangVarXML($xml, $lang_var);
1365 }
1366
1367 $xml .= "</LVs>";
1368 return $xml;
1369 }
1370
1371 public function appendLangVarXML(&$xml, $var)
1372 {
1373 $val = $this->lng->txt("cont_" . $var);
1374 $val = str_replace('"', "&quot;", $val);
1375 $xml .= "<LV name=\"$var\" value=\"" . $val . "\"/>";
1376 }
1377
1378 // @todo begin: move this to paragraph class
1379
1380 public function getFirstParagraphText()
1381 {
1382 if ($this->dom) {
1383 require_once("./Services/COPage/classes/class.ilPCParagraph.php");
1384 $xpc = xpath_new_context($this->dom);
1385 $path = "//Paragraph[1]";
1386 $res = xpath_eval($xpc, $path);
1387 if (count($res->nodeset) > 0) {
1388 $cont_node = $res->nodeset[0]->parent_node();
1389 $par = new ilPCParagraph($this);
1390 $par->setNode($cont_node);
1391 $text = $par->getText();
1392
1393 return $text;
1394 }
1395 }
1396 return "";
1397 }
1398
1405 public function setParagraphContent($a_hier_id, $a_content)
1406 {
1407 $node = $this->getContentNode($a_hier_id);
1408 if (is_object($node)) {
1409 $node->set_content($a_content);
1410 }
1411 }
1412
1413 // @todo end
1414
1415
1424 // @todo: can we do this better
1425 public function setContainsIntLink($a_contains_link)
1426 {
1427 $this->contains_int_link = $a_contains_link;
1428 }
1429
1434 // @todo: can we do this better
1435 public function containsIntLink()
1436 {
1438 }
1439
1445 public function setImportMode($a_val)
1446 {
1447 $this->import_mode = $a_val;
1448 }
1449
1455 public function getImportMode()
1456 {
1457 return $this->import_mode;
1458 }
1459
1460 public function needsImportParsing($a_parse = "")
1461 {
1462 if ($a_parse === true) {
1463 $this->needs_parsing = true;
1464 }
1465 if ($a_parse === false) {
1466 $this->needs_parsing = false;
1467 }
1468 return $this->needs_parsing;
1469 }
1470
1476 // @todo: can we do this better
1477 public function setContainsQuestion($a_val)
1478 {
1479 $this->contains_question = $a_val;
1480 }
1481
1487 public function getContainsQuestion()
1488 {
1489 return $this->contains_question;
1490 }
1491
1492
1497 // @todo: move to media class
1498 public function collectMediaObjects($a_inline_only = true)
1499 {
1500 //echo htmlentities($this->getXMLFromDom());
1501 // determine all media aliases of the page
1502 $xpc = xpath_new_context($this->dom);
1503 $path = "//MediaObject/MediaAlias";
1504 $res = xpath_eval($xpc, $path);
1505 $mob_ids = array();
1506 for ($i = 0; $i < count($res->nodeset); $i++) {
1507 $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1508 $mob_id = $id_arr[count($id_arr) - 1];
1509 $mob_ids[$mob_id] = $mob_id;
1510 }
1511
1512 // determine all media aliases of interactive images
1513 $xpc = xpath_new_context($this->dom);
1514 $path = "//InteractiveImage/MediaAlias";
1515 $res = xpath_eval($xpc, $path);
1516 for ($i = 0; $i < count($res->nodeset); $i++) {
1517 $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1518 $mob_id = $id_arr[count($id_arr) - 1];
1519 $mob_ids[$mob_id] = $mob_id;
1520 }
1521
1522 // determine all inline internal media links
1523 $xpc = xpath_new_context($this->dom);
1524 $path = "//IntLink[@Type = 'MediaObject']";
1525 $res = xpath_eval($xpc, $path);
1526
1527 for ($i = 0; $i < count($res->nodeset); $i++) {
1528 if (($res->nodeset[$i]->get_attribute("TargetFrame") == "") ||
1529 (!$a_inline_only)) {
1530 $target = $res->nodeset[$i]->get_attribute("Target");
1531 $id_arr = explode("_", $target);
1532 if (($id_arr[1] == IL_INST_ID) ||
1533 (substr($target, 0, 4) == "il__")) {
1534 $mob_id = $id_arr[count($id_arr) - 1];
1535 if (ilObject::_exists($mob_id)) {
1536 $mob_ids[$mob_id] = $mob_id;
1537 }
1538 }
1539 }
1540 }
1541
1542 return $mob_ids;
1543 }
1544
1545
1549 // @todo: can we do this better?
1550 public function getInternalLinks($a_cnt_multiple = false)
1551 {
1552 // get all internal links of the page
1553 $xpc = xpath_new_context($this->dom);
1554 $path = "//IntLink";
1555 $res = xpath_eval($xpc, $path);
1556
1557 $links = array();
1558 $cnt_multiple = 1;
1559 for ($i = 0; $i < count($res->nodeset); $i++) {
1560 $add = "";
1561 if ($a_cnt_multiple) {
1562 $add = ":" . $cnt_multiple;
1563 }
1564 $target = $res->nodeset[$i]->get_attribute("Target");
1565 $type = $res->nodeset[$i]->get_attribute("Type");
1566 $targetframe = $res->nodeset[$i]->get_attribute("TargetFrame");
1567 $anchor = $res->nodeset[$i]->get_attribute("Anchor");
1568 $links[$target . ":" . $type . ":" . $targetframe . ":" . $anchor . $add] =
1569 array("Target" => $target, "Type" => $type,
1570 "TargetFrame" => $targetframe, "Anchor" => $anchor);
1571
1572 // get links (image map areas) for inline media objects
1573 if ($type == "MediaObject" && $targetframe == "") {
1574 if (substr($target, 0, 4) == "il__") {
1575 $id_arr = explode("_", $target);
1576 $id = $id_arr[count($id_arr) - 1];
1577
1579 foreach ($med_links as $key => $med_link) {
1580 $links[$key] = $med_link;
1581 }
1582 }
1583 }
1584 //echo "<br>-:".$target.":".$type.":".$targetframe.":-";
1585 $cnt_multiple++;
1586 }
1587 unset($xpc);
1588
1589 // get all media aliases
1590 $xpc = xpath_new_context($this->dom);
1591 $path = "//MediaAlias";
1592 $res = xpath_eval($xpc, $path);
1593
1594 require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
1595 for ($i = 0; $i < count($res->nodeset); $i++) {
1596 $oid = $res->nodeset[$i]->get_attribute("OriginId");
1597 if (substr($oid, 0, 4) == "il__") {
1598 $id_arr = explode("_", $oid);
1599 $id = $id_arr[count($id_arr) - 1];
1600
1602 foreach ($med_links as $key => $med_link) {
1603 $links[$key] = $med_link;
1604 }
1605 }
1606 }
1607 unset($xpc);
1608
1609 return $links;
1610 }
1611
1616 // @todo: move to media class
1617 public function getMultimediaXML()
1618 {
1619 $mob_ids = $this->collectMediaObjects();
1620
1621 // get xml of corresponding media objects
1622 $mobs_xml = "";
1623 require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1624 foreach ($mob_ids as $mob_id => $dummy) {
1625 if (ilObject::_lookupType($mob_id) == "mob") {
1626 $mob_obj = new ilObjMediaObject($mob_id);
1627 $mobs_xml .= $mob_obj->getXML(IL_MODE_OUTPUT, $a_inst = 0, true);
1628 }
1629 }
1630 //var_dump($mobs_xml);
1631 return $mobs_xml;
1632 }
1633
1637 // @todo: move to media class
1638 public function getMediaAliasElement($a_mob_id, $a_nr = 1)
1639 {
1640 $xpc = xpath_new_context($this->dom);
1641 $path = "//MediaObject/MediaAlias[@OriginId='il__mob_$a_mob_id']";
1642 $res = xpath_eval($xpc, $path);
1643 $mal_node = $res->nodeset[$a_nr - 1];
1644 $mob_node = $mal_node->parent_node();
1645
1646 return $this->dom->dump_node($mob_node);
1647 }
1648
1654 public function validateDom()
1655 {
1656 $this->stripHierIDs();
1657
1658 // possible fix for #14820
1659 libxml_disable_entity_loader(false);
1660
1661 @$this->dom->validate($error);
1662 //var_dump($this->dom); exit;
1663 return $error;
1664 }
1665
1681 // @todo: can we do this better? remove dependencies?
1682 public function addHierIDs()
1683 {
1684 $this->hier_ids = array();
1685 $this->first_row_ids = array();
1686 $this->first_col_ids = array();
1687 $this->list_item_ids = array();
1688 $this->file_item_ids = array();
1689
1690 // set hierarchical ids for Paragraphs, Tables, TableRows and TableData elements
1691 $xpc = xpath_new_context($this->dom);
1692 //$path = "//Paragraph | //Table | //TableRow | //TableData";
1693
1694 $sep = $path = "";
1695 foreach ($this->id_elements as $el) {
1696 $path .= $sep . "//" . $el;
1697 $sep = " | ";
1698 }
1699
1700 $res = xpath_eval($xpc, $path);
1701 for ($i = 0; $i < count($res->nodeset); $i++) {
1702 $cnode = $res->nodeset[$i];
1703 $ctag = $cnode->node_name();
1704
1705 // get hierarchical id of previous sibling
1706 $sib_hier_id = "";
1707 while ($cnode = $cnode->previous_sibling()) {
1708 if (($cnode->node_type() == XML_ELEMENT_NODE)
1709 && $cnode->has_attribute("HierId")) {
1710 $sib_hier_id = $cnode->get_attribute("HierId");
1711 //$sib_hier_id = $id_attr->value();
1712 break;
1713 }
1714 }
1715
1716 if ($sib_hier_id != "") { // set id to sibling id "+ 1"
1717 require_once("./Services/COPage/classes/class.ilPageContent.php");
1718 $node_hier_id = ilPageContent::incEdId($sib_hier_id);
1719 $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1720 $this->hier_ids[] = $node_hier_id;
1721 if ($ctag == "TableData") {
1722 if (substr($par_hier_id, strlen($par_hier_id) - 2) == "_1") {
1723 $this->first_row_ids[] = $node_hier_id;
1724 }
1725 }
1726 if ($ctag == "ListItem") {
1727 $this->list_item_ids[] = $node_hier_id;
1728 }
1729 if ($ctag == "FileItem") {
1730 $this->file_item_ids[] = $node_hier_id;
1731 }
1732 } else { // no sibling -> node is first child
1733 // get hierarchical id of next parent
1734 $cnode = $res->nodeset[$i];
1735 $par_hier_id = "";
1736 while ($cnode = $cnode->parent_node()) {
1737 if (($cnode->node_type() == XML_ELEMENT_NODE)
1738 && $cnode->has_attribute("HierId")) {
1739 $par_hier_id = $cnode->get_attribute("HierId");
1740 //$par_hier_id = $id_attr->value();
1741 break;
1742 }
1743 }
1744 //echo "<br>par:".$par_hier_id." ($ctag)";
1745 if (($par_hier_id != "") && ($par_hier_id != "pg")) { // set id to parent_id."_1"
1746 $node_hier_id = $par_hier_id . "_1";
1747 $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1748 $this->hier_ids[] = $node_hier_id;
1749 if ($ctag == "TableData") {
1750 $this->first_col_ids[] = $node_hier_id;
1751 if (substr($par_hier_id, strlen($par_hier_id) - 2) == "_1") {
1752 $this->first_row_ids[] = $node_hier_id;
1753 }
1754 }
1755 if ($ctag == "ListItem") {
1756 $this->list_item_ids[] = $node_hier_id;
1757 }
1758 if ($ctag == "FileItem") {
1759 $this->file_item_ids[] = $node_hier_id;
1760 }
1761 } else { // no sibling, no parent -> first node
1762 $node_hier_id = "1";
1763 $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1764 $this->hier_ids[] = $node_hier_id;
1765 }
1766 }
1767 }
1768
1769 // set special hierarchical id "pg" for pageobject
1770 $xpc = xpath_new_context($this->dom);
1771 $path = "//PageObject";
1772 $res = xpath_eval($xpc, $path);
1773 for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1774 $res->nodeset[$i]->set_attribute("HierId", "pg");
1775 $this->hier_ids[] = "pg";
1776 }
1777 unset($xpc);
1778 }
1779
1783 public function getHierIds()
1784 {
1785 return $this->hier_ids;
1786 }
1787
1791 // @todo: move to table classes
1792 public function getFirstRowIds()
1793 {
1794 return $this->first_row_ids;
1795 }
1796
1800 // @todo: move to table classes
1801 public function getFirstColumnIds()
1802 {
1803 return $this->first_col_ids;
1804 }
1805
1809 // @todo: move to list class
1810 public function getListItemIds()
1811 {
1812 return $this->list_item_ids;
1813 }
1814
1818 // @todo: move to file item class
1819 public function getFileItemIds()
1820 {
1821 return $this->file_item_ids;
1822 }
1823
1827 public function stripHierIDs()
1828 {
1829 if (is_object($this->dom)) {
1830 $xpc = xpath_new_context($this->dom);
1831 $path = "//*[@HierId]";
1832 $res = xpath_eval($xpc, $path);
1833 for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1834 if ($res->nodeset[$i]->has_attribute("HierId")) {
1835 $res->nodeset[$i]->remove_attribute("HierId");
1836 }
1837 }
1838 unset($xpc);
1839 }
1840 }
1841
1845 public function getHierIdsForPCIds($a_pc_ids)
1846 {
1847 if (!is_array($a_pc_ids) || count($a_pc_ids) == 0) {
1848 return array();
1849 }
1850 $ret = array();
1851
1852 if (is_object($this->dom)) {
1853 $xpc = xpath_new_context($this->dom);
1854 $path = "//*[@PCID]";
1855 $res = xpath_eval($xpc, $path);
1856 for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1857 $pc_id = $res->nodeset[$i]->get_attribute("PCID");
1858 if (in_array($pc_id, $a_pc_ids)) {
1859 $ret[$pc_id] = $res->nodeset[$i]->get_attribute("HierId");
1860 }
1861 }
1862 unset($xpc);
1863 }
1864 //var_dump($ret);
1865 return $ret;
1866 }
1867
1871 // @todo: move to file item class
1872 public function addFileSizes()
1873 {
1874 $xpc = xpath_new_context($this->dom);
1875 $path = "//FileItem";
1876 $res = xpath_eval($xpc, $path);
1877 for ($i = 0; $i < count($res->nodeset); $i++) {
1878 $cnode = $res->nodeset[$i];
1879 $size_node = $this->dom->create_element("Size");
1880 $size_node = $cnode->append_child($size_node);
1881
1882 $childs = $cnode->child_nodes();
1883 $size = "";
1884 for ($j = 0; $j < count($childs); $j++) {
1885 if ($childs[$j]->node_name() == "Identifier") {
1886 if ($childs[$j]->has_attribute("Entry")) {
1887 $entry = $childs[$j]->get_attribute("Entry");
1888 $entry_arr = explode("_", $entry);
1889 $id = $entry_arr[count($entry_arr) - 1];
1890 require_once("./Modules/File/classes/class.ilObjFile.php");
1892 }
1893 }
1894 }
1895 $size_node->set_content($size);
1896 }
1897
1898 unset($xpc);
1899 }
1900
1905 // @todo: possible to improve this?
1906 public function resolveIntLinks($a_link_map = null)
1907 {
1908 $changed = false;
1909
1910 $this->log->debug("start");
1911
1912 // resolve normal internal links
1913 $xpc = xpath_new_context($this->dom);
1914 $path = "//IntLink";
1915 $res = xpath_eval($xpc, $path);
1916 for ($i = 0; $i < count($res->nodeset); $i++) {
1917 $target = $res->nodeset[$i]->get_attribute("Target");
1918 $type = $res->nodeset[$i]->get_attribute("Type");
1919
1920 if ($a_link_map == null) {
1921 $new_target = ilInternalLink::_getIdForImportId($type, $target);
1922 $this->log->debug("no map, type: " . $type . ", target: " . $target . ", new target: " . $new_target);
1923 // echo "-".$new_target."-".$type."-".$target."-"; exit;
1924 } else {
1925 $nt = explode("_", $a_link_map[$target]);
1926 $new_target = false;
1927 if ($nt[1] == IL_INST_ID) {
1928 $new_target = "il__" . $nt[2] . "_" . $nt[3];
1929 }
1930 $this->log->debug("map, type: " . $type . ", target: " . $target . ", new target: " . $new_target);
1931 }
1932 if ($new_target !== false) {
1933 $res->nodeset[$i]->set_attribute("Target", $new_target);
1934 $changed = true;
1935 } else { // check wether link target is same installation
1936 if (ilInternalLink::_extractInstOfTarget($target) == IL_INST_ID &&
1937 IL_INST_ID > 0 && $type != "RepositoryItem") {
1938 $new_target = ilInternalLink::_removeInstFromTarget($target);
1939 if (ilInternalLink::_exists($type, $new_target)) {
1940 $res->nodeset[$i]->set_attribute("Target", $new_target);
1941 $changed = true;
1942 }
1943 }
1944 }
1945 }
1946 unset($xpc);
1947
1948 // resolve internal links in map areas
1949 $xpc = xpath_new_context($this->dom);
1950 $path = "//MediaAlias";
1951 $res = xpath_eval($xpc, $path);
1952 //echo "<br><b>page::resolve</b><br>";
1953 //echo "Content:".htmlentities($this->getXMLFromDOM()).":<br>";
1954 for ($i = 0; $i < count($res->nodeset); $i++) {
1955 $orig_id = $res->nodeset[$i]->get_attribute("OriginId");
1956 $id_arr = explode("_", $orig_id);
1957 $mob_id = $id_arr[count($id_arr) - 1];
1959 }
1960 return $changed;
1961 }
1962
1969 // @todo: move to media classes?
1970 public function resolveMediaAliases($a_mapping, $a_reuse_existing_by_import = false)
1971 {
1972 // resolve normal internal links
1973 $xpc = xpath_new_context($this->dom);
1974 $path = "//MediaAlias";
1975 $res = xpath_eval($xpc, $path);
1976 $changed = false;
1977 for ($i = 0; $i < count($res->nodeset); $i++) {
1978 // get the ID of the import file from the xml
1979 $old_id = $res->nodeset[$i]->get_attribute("OriginId");
1980 $old_id = explode("_", $old_id);
1981 $old_id = $old_id[count($old_id) - 1];
1982 $new_id = "";
1983 $import_id = "";
1984 // get the new id from the current mapping
1985 if ($a_mapping[$old_id] > 0) {
1986 $new_id = $a_mapping[$old_id];
1987 if ($a_reuse_existing_by_import) {
1988 // this should work, if the lm has been imported in a translation installation and re-exported
1989 $import_id = ilObject::_lookupImportId($new_id);
1990 $imp = explode("_", $import_id);
1991 if ($imp[1] == IL_INST_ID && $imp[2] == "mob" && ilObject::_lookupType($imp[3]) == "mob") {
1992 $new_id = $imp[3];
1993 }
1994 }
1995 }
1996 // now check, if the translation has been done just by changing text in the exported
1997 // translation file
1998 if ($import_id == "" && $a_reuse_existing_by_import) {
1999 // if the old_id is also referred by the page content of the default language
2000 // we assume that this media object is unchanged
2001 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2002 $med_of_def_lang = ilObjMediaObject::_getMobsOfObject($this->getParentType() . ":pg", $this->getId(), 0, "-");
2003 if (in_array($old_id, $med_of_def_lang)) {
2004 $new_id = $old_id;
2005 }
2006 }
2007 if ($new_id != "") {
2008 $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $new_id);
2009 $changed = true;
2010 }
2011 }
2012 unset($xpc);
2013 return $changed;
2014 }
2015
2022 // @todo: move to iim classes?
2023 public function resolveIIMMediaAliases($a_mapping)
2024 {
2025 // resolve normal internal links
2026 $xpc = xpath_new_context($this->dom);
2027 $path = "//InteractiveImage/MediaAlias";
2028 $res = xpath_eval($xpc, $path);
2029 $changed = false;
2030 for ($i = 0; $i < count($res->nodeset); $i++) {
2031 $old_id = $res->nodeset[$i]->get_attribute("OriginId");
2032 if ($a_mapping[$old_id] > 0) {
2033 $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $a_mapping[$old_id]);
2034 $changed = true;
2035 }
2036 }
2037 unset($xpc);
2038
2039 return $changed;
2040 }
2041
2048 // @todo: move to file classes?
2049 public function resolveFileItems($a_mapping)
2050 {
2051 // resolve normal internal links
2052 $xpc = xpath_new_context($this->dom);
2053 $path = "//FileItem/Identifier";
2054 $res = xpath_eval($xpc, $path);
2055 $changed = false;
2056 for ($i = 0; $i < count($res->nodeset); $i++) {
2057 $old_id = $res->nodeset[$i]->get_attribute("Entry");
2058 $old_id = explode("_", $old_id);
2059 $old_id = $old_id[count($old_id) - 1];
2060 if ($a_mapping[$old_id] > 0) {
2061 $res->nodeset[$i]->set_attribute("Entry", "il__file_" . $a_mapping[$old_id]);
2062 $changed = true;
2063 }
2064 }
2065 unset($xpc);
2066
2067 return $changed;
2068 }
2069
2074 // @todo: move to question classes
2075 public function resolveQuestionReferences($a_mapping)
2076 {
2077 // resolve normal internal links
2078 $xpc = xpath_new_context($this->dom);
2079 $path = "//Question";
2080 $res = xpath_eval($xpc, $path);
2081 $updated = false;
2082 for ($i = 0; $i < count($res->nodeset); $i++) {
2083 $qref = $res->nodeset[$i]->get_attribute("QRef");
2084
2085 if (isset($a_mapping[$qref])) {
2086 $res->nodeset[$i]->set_attribute("QRef", "il__qst_" . $a_mapping[$qref]["pool"]);
2087 $updated = true;
2088 }
2089 }
2090 unset($xpc);
2091
2092 return $updated;
2093 }
2094
2095
2102 // @todo: generalize, internal links usage info
2103 public function moveIntLinks($a_from_to)
2104 {
2105 $this->buildDom();
2106
2107 $changed = false;
2108
2109 // resolve normal internal links
2110 $xpc = xpath_new_context($this->dom);
2111 $path = "//IntLink";
2112 $res = xpath_eval($xpc, $path);
2113 for ($i = 0; $i < count($res->nodeset); $i++) {
2114 $target = $res->nodeset[$i]->get_attribute("Target");
2115 $type = $res->nodeset[$i]->get_attribute("Type");
2116 $obj_id = ilInternalLink::_extractObjIdOfTarget($target);
2117 if ($a_from_to[$obj_id] > 0 && is_int(strpos($target, "__"))) {
2118 if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg") {
2119 $res->nodeset[$i]->set_attribute("Target", "il__pg_" . $a_from_to[$obj_id]);
2120 $changed = true;
2121 }
2122 if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st") {
2123 $res->nodeset[$i]->set_attribute("Target", "il__st_" . $a_from_to[$obj_id]);
2124 $changed = true;
2125 }
2126 if ($type == "PortfolioPage") {
2127 $res->nodeset[$i]->set_attribute("Target", "il__ppage_" . $a_from_to[$obj_id]);
2128 $changed = true;
2129 }
2130 }
2131 }
2132 unset($xpc);
2133
2134 // map areas
2135 $this->addHierIDs();
2136 $xpc = xpath_new_context($this->dom);
2137 $path = "//MediaAlias";
2138 $res = xpath_eval($xpc, $path);
2139
2140 require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
2141 require_once("Services/COPage/classes/class.ilMediaAliasItem.php");
2142
2143 for ($i = 0; $i < count($res->nodeset); $i++) {
2144 $media_object_node = $res->nodeset[$i]->parent_node();
2145 $page_content_node = $media_object_node->parent_node();
2146 $c_hier_id = $page_content_node->get_attribute("HierId");
2147
2148 // first check, wheter we got instance map areas -> take these
2149 $std_alias_item = new ilMediaAliasItem(
2150 $this->dom,
2151 $c_hier_id,
2152 "Standard"
2153 );
2154 $areas = $std_alias_item->getMapAreas();
2155 $correction_needed = false;
2156 if (count($areas) > 0) {
2157 // check if correction needed
2158 foreach ($areas as $area) {
2159 if ($area["Type"] == "PageObject" ||
2160 $area["Type"] == "StructureObject") {
2161 $t = $area["Target"];
2162 $tid = _extractObjIdOfTarget($t);
2163 if ($a_from_to[$tid] > 0) {
2164 $correction_needed = true;
2165 }
2166 }
2167 }
2168 } else {
2169 $areas = array();
2170
2171 // get object map areas and check whether at least one must
2172 // be corrected
2173 $oid = $res->nodeset[$i]->get_attribute("OriginId");
2174 if (substr($oid, 0, 4) == "il__") {
2175 $id_arr = explode("_", $oid);
2176 $id = $id_arr[count($id_arr) - 1];
2177
2178 $mob = new ilObjMediaObject($id);
2179 $med_item = $mob->getMediaItem("Standard");
2180 $med_areas = $med_item->getMapAreas();
2181
2182 foreach ($med_areas as $area) {
2183 $link_type = ($area->getLinkType() == "int")
2184 ? "IntLink"
2185 : "ExtLink";
2186
2187 $areas[] = array(
2188 "Nr" => $area->getNr(),
2189 "Shape" => $area->getShape(),
2190 "Coords" => $area->getCoords(),
2191 "Link" => array(
2192 "LinkType" => $link_type,
2193 "Href" => $area->getHref(),
2194 "Title" => $area->getTitle(),
2195 "Target" => $area->getTarget(),
2196 "Type" => $area->getType(),
2197 "TargetFrame" => $area->getTargetFrame()
2198 )
2199 );
2200
2201 if ($area->getType() == "PageObject" ||
2202 $area->getType() == "StructureObject") {
2203 $t = $area->getTarget();
2205 if ($a_from_to[$tid] > 0) {
2206 $correction_needed = true;
2207 }
2208 //var_dump($a_from_to);
2209 }
2210 }
2211 }
2212 }
2213
2214 // correct map area links
2215 if ($correction_needed) {
2216 $changed = true;
2217 $std_alias_item->deleteAllMapAreas();
2218 foreach ($areas as $area) {
2219 if ($area["Link"]["LinkType"] == "IntLink") {
2220 $target = $area["Link"]["Target"];
2221 $type = $area["Link"]["Type"];
2222 $obj_id = ilInternalLink::_extractObjIdOfTarget($target);
2223 if ($a_from_to[$obj_id] > 0) {
2224 if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg") {
2225 $area["Link"]["Target"] = "il__pg_" . $a_from_to[$obj_id];
2226 }
2227 if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st") {
2228 $area["Link"]["Target"] = "il__st_" . $a_from_to[$obj_id];
2229 }
2230 }
2231 }
2232
2233 $std_alias_item->addMapArea(
2234 $area["Shape"],
2235 $area["Coords"],
2236 $area["Link"]["Title"],
2237 array( "Type" => $area["Link"]["Type"],
2238 "TargetFrame" => $area["Link"]["TargetFrame"],
2239 "Target" => $area["Link"]["Target"],
2240 "Href" => $area["Link"]["Href"],
2241 "LinkType" => $area["Link"]["LinkType"],
2242 )
2243 );
2244 }
2245 }
2246 }
2247 unset($xpc);
2248
2249 return $changed;
2250 }
2251
2257 // @todo: generalize, internal links usage info
2258 public static function _handleImportRepositoryLinks($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2259 {
2260 include_once("./Services/Link/classes/class.ilInternalLink.php");
2261
2262 //echo "-".$a_rep_import_id."-".$a_rep_ref_id."-";
2264 "obj",
2265 ilInternalLink::_extractObjIdOfTarget($a_rep_import_id),
2266 ilInternalLink::_extractInstOfTarget($a_rep_import_id)
2267 );
2268 //var_dump($sources);
2269 foreach ($sources as $source) {
2270 //echo "A";
2271 if ($source["type"] == "lm:pg") {
2272 //echo "B";
2273 include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
2274 if (self::_exists("lm", $source["id"], $source["lang"])) {
2275 $page_obj = new ilLMPage($source["id"], 0, $source["lang"]);
2276 if (!$page_obj->page_not_found) {
2277 //echo "C";
2278 $page_obj->handleImportRepositoryLink(
2279 $a_rep_import_id,
2280 $a_rep_type,
2281 $a_rep_ref_id
2282 );
2283 }
2284 $page_obj->update();
2285 }
2286 }
2287 }
2288 }
2289
2290 // @todo: generalize, internal links usage info
2291 public function handleImportRepositoryLink($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2292 {
2293 $this->buildDom();
2294
2295 // resolve normal internal links
2296 $xpc = xpath_new_context($this->dom);
2297 $path = "//IntLink";
2298 $res = xpath_eval($xpc, $path);
2299 //echo "1";
2300 for ($i = 0; $i < count($res->nodeset); $i++) {
2301 //echo "2";
2302 $target = $res->nodeset[$i]->get_attribute("Target");
2303 $type = $res->nodeset[$i]->get_attribute("Type");
2304 if ($target == $a_rep_import_id && $type == "RepositoryItem") {
2305 //echo "setting:"."il__".$a_rep_type."_".$a_rep_ref_id;
2306 $res->nodeset[$i]->set_attribute(
2307 "Target",
2308 "il__" . $a_rep_type . "_" . $a_rep_ref_id
2309 );
2310 }
2311 }
2312 unset($xpc);
2313 }
2314
2320 public function handleRepositoryLinksOnCopy($a_mapping, $a_source_ref_id)
2321 {
2323 $objDefinition = $this->obj_definition;
2324
2325 $this->buildDom();
2326 $this->log->debug("Handle repository links...");
2327
2328 // resolve normal internal links
2329 $xpc = xpath_new_context($this->dom);
2330 $path = "//IntLink";
2331 $res = xpath_eval($xpc, $path);
2332 for ($i = 0; $i < count($res->nodeset); $i++) {
2333 $target = $res->nodeset[$i]->get_attribute("Target");
2334 $type = $res->nodeset[$i]->get_attribute("Type");
2335 $this->log->debug("Target: " . $target);
2336 $t = explode("_", $target);
2337 if ($type == "RepositoryItem" && ((int) $t[1] == 0 || (int) $t[1] == IL_INST_ID)) {
2338 if (isset($a_mapping[$t[3]])) {
2339 // we have a mapping -> replace the ID
2340 $this->log->debug("... replace " . $t[3] . " with " . $a_mapping[$t[3]] . ".");
2341 $res->nodeset[$i]->set_attribute(
2342 "Target",
2343 "il__obj_" . $a_mapping[$t[3]]
2344 );
2345 } elseif ($this->tree->isGrandChild($a_source_ref_id, $t[3])) {
2346 // we have no mapping, but the linked object is child of the original node -> remove link
2347 $this->log->debug("... remove links.");
2348 if ($res->nodeset[$i]->parent_node()->node_name() == "MapArea") { // simply remove map areas
2349 $parent = $res->nodeset[$i]->parent_node();
2350 $parent->unlink_node($parent);
2351 } else { // replace link by content of the link for other internal links
2352 $source_node = $res->nodeset[$i];
2353 $new_node = $source_node->clone_node(true);
2354 $new_node->unlink_node($new_node);
2355 $childs = $new_node->child_nodes();
2356 for ($j = 0; $j < count($childs); $j++) {
2357 $this->log->debug("... move node $j " . $childs[$j]->node_name() . " before " . $source_node->node_name());
2358 $source_node->insert_before($childs[$j], $source_node);
2359 }
2360 $source_node->unlink_node($source_node);
2361 }
2362 }
2363 }
2364 }
2365 unset($xpc);
2366
2367 // resolve normal external links
2368 $ilias_url = parse_url(ILIAS_HTTP_PATH);
2369 $xpc = xpath_new_context($this->dom);
2370 $path = "//ExtLink";
2371 $res = xpath_eval($xpc, $path);
2372 for ($i = 0; $i < count($res->nodeset); $i++) {
2373 $href = $res->nodeset[$i]->get_attribute("Href");
2374 $this->log->debug("Href: " . $href);
2375
2376 $url = parse_url($href);
2377
2378 // only handle links on same host
2379 $this->log->debug("Host: " . $url["host"]);
2380 if ($url["host"] != "" && $url["host"] != $ilias_url["host"]) {
2381 continue;
2382 }
2383
2384 // get parameters
2385 $par = array();
2386 foreach (explode("&", $url["query"]) as $p) {
2387 $p = explode("=", $p);
2388 $par[$p[0]] = $p[1];
2389 }
2390
2391 $target_client_id = $par["client_id"];
2392 if ($target_client_id != "" && $target_client_id != CLIENT_ID) {
2393 continue;
2394 }
2395
2396 // get ref id
2397 $ref_id = 0;
2398 if (is_int(strpos($href, "goto.php"))) {
2399 $t = explode("_", $par["target"]);
2400 if ($objDefinition->isRBACObject($t[0])) {
2401 $ref_id = (int) $t[1];
2402 $type = $t[0];
2403 }
2404 } elseif (is_int(strpos($href, "ilias.php"))) {
2405 $ref_id = (int) $par["ref_id"];
2406 }
2407
2408
2409 if ($ref_id > 0) {
2410 if (isset($a_mapping[$ref_id])) {
2411 $new_ref_id = $a_mapping[$ref_id];
2412 $new_href = "";
2413 // we have a mapping -> replace the ID
2414 if (is_int(strpos($href, "goto.php"))) {
2415 $nt = str_replace($type . "_" . $ref_id, $type . "_" . $new_ref_id, $par["target"]);
2416 $new_href = str_replace("target=" . $par["target"], "target=" . $nt, $href);
2417 } elseif (is_int(strpos($href, "ilias.php"))) {
2418 $new_href = str_replace("ref_id=" . $par["ref_id"], "ref_id=" . $new_ref_id, $href);
2419 }
2420 if ($new_href != "") {
2421 $this->log->debug("... ext link replace " . $href . " with " . $new_href . ".");
2422 $res->nodeset[$i]->set_attribute("Href", $new_href);
2423 }
2424 } elseif ($tree->isGrandChild($a_source_ref_id, $ref_id)) {
2425 // we have no mapping, but the linked object is child of the original node -> remove link
2426 $this->log->debug("... remove ext links.");
2427 if ($res->nodeset[$i]->parent_node()->node_name() == "MapArea") { // simply remove map areas
2428 $parent = $res->nodeset[$i]->parent_node();
2429 $parent->unlink_node($parent);
2430 } else { // replace link by content of the link for other internal links
2431 $source_node = $res->nodeset[$i];
2432 $new_node = $source_node->clone_node(true);
2433 $new_node->unlink_node($new_node);
2434 $childs = $new_node->child_nodes();
2435 for ($j = 0; $j < count($childs); $j++) {
2436 $this->log->debug("... move node $j " . $childs[$j]->node_name() . " before " . $source_node->node_name());
2437 $source_node->insert_before($childs[$j], $source_node);
2438 }
2439 $source_node->unlink_node($source_node);
2440 }
2441 }
2442 }
2443 }
2444 unset($xpc);
2445 }
2446
2447
2451 public function createFromXML()
2452 {
2453 $empty = false;
2454 if ($this->getXMLContent() == "") {
2455 $this->setXMLContent("<PageObject></PageObject>");
2456 $empty = true;
2457 }
2458
2459 $content = $this->getXMLContent();
2460 $this->buildDom(true);
2461 $dom_doc = $this->getDomDoc();
2462
2463 $iel = $this->containsDeactivatedElements($content);
2464 $inl = $this->containsIntLinks($content);
2465
2466 // create object
2467 $this->db->insert("page_object", array(
2468 "page_id" => array("integer", $this->getId()),
2469 "parent_id" => array("integer", $this->getParentId()),
2470 "lang" => array("text", $this->getLanguage()),
2471 "content" => array("clob", $content),
2472 "parent_type" => array("text", $this->getParentType()),
2473 "create_user" => array("integer", $this->user->getId()),
2474 "last_change_user" => array("integer", $this->user->getId()),
2475 "active" => array("integer", (int) $this->getActive()),
2476 "activation_start" => array("timestamp", $this->getActivationStart()),
2477 "activation_end" => array("timestamp", $this->getActivationEnd()),
2478 "show_activation_info" => array("integer", (int) $this->getShowActivationInfo()),
2479 "inactive_elements" => array("integer", $iel),
2480 "int_links" => array("integer", $inl),
2481 "created" => array("timestamp", ilUtil::now()),
2482 "last_change" => array("timestamp", ilUtil::now()),
2483 "is_empty" => array("integer", $empty)
2484 ));
2485
2486 // after update event
2487 $this->__afterUpdate($dom_doc, $content, true, $empty);
2488 }
2489
2490
2499 public function updateFromXML()
2500 {
2501 $this->log->debug("ilPageObject, updateFromXML(): start, id: " . $this->getId());
2502
2503 $content = $this->getXMLContent();
2504
2505 $this->log->debug("ilPageObject, updateFromXML(): content: " . substr($content, 0, 100));
2506
2507 $this->buildDom(true);
2508 $dom_doc = $this->getDomDoc();
2509
2510 $iel = $this->containsDeactivatedElements($content);
2511 $inl = $this->containsIntLinks($content);
2512
2513 $this->db->update("page_object", array(
2514 "content" => array("clob", $content),
2515 "parent_id" => array("integer", $this->getParentId()),
2516 "last_change_user" => array("integer", $this->user->getId()),
2517 "last_change" => array("timestamp", ilUtil::now()),
2518 "active" => array("integer", $this->getActive()),
2519 "activation_start" => array("timestamp", $this->getActivationStart()),
2520 "activation_end" => array("timestamp", $this->getActivationEnd()),
2521 "inactive_elements" => array("integer", $iel),
2522 "int_links" => array("integer", $inl),
2523 ), array(
2524 "page_id" => array("integer", $this->getId()),
2525 "parent_type" => array("text", $this->getParentType()),
2526 "lang" => array("text", $this->getLanguage())
2527 ));
2528
2529 // after update event
2530 $this->__afterUpdate($dom_doc, $content);
2531
2532 $this->log->debug("ilPageObject, updateFromXML(): end");
2533
2534 return true;
2535 }
2536
2543 final protected function __afterUpdate($a_domdoc, $a_xml, $a_creation = false, $a_empty = false)
2544 {
2545 // we do not need this if we are creating an empty page
2546 if (!$a_creation || !$a_empty) {
2547 // save internal link information
2548 // the page object is responsible to do this, since it "offers" the
2549 // internal link feature pc and page classes
2550 $this->saveInternalLinks($a_domdoc);
2551
2552 // save style usage
2553 $this->saveStyleUsage($a_domdoc);
2554
2555 // pc classes hook
2556 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2558 foreach ($defs as $def) {
2560 $cl = $def["pc_class"];
2561 call_user_func($def["pc_class"] . '::afterPageUpdate', $this, $a_domdoc, $a_xml, $a_creation);
2562 }
2563 }
2564
2565 // call page hook
2566 $this->afterUpdate($a_domdoc, $a_xml);
2567
2568 // call update listeners
2569 $this->callUpdateListeners();
2570 }
2571
2578 public function afterUpdate()
2579 {
2580 }
2581
2582
2587 public function update($a_validate = true, $a_no_history = false)
2588 {
2589 $this->log->debug("ilPageObject, update(): start, id: " . $this->getId());
2590
2591 $lm_set = new ilSetting("lm");
2592
2593 // add missing pc ids
2594 if (!$this->checkPCIds()) {
2595 $this->insertPCIds();
2596 }
2597
2598 // test validating
2599 if ($a_validate) {
2600 $errors = $this->validateDom();
2601 }
2602 //var_dump($errors); exit;
2603 if (empty($errors) && !$this->getEditLock()) {
2604 include_once("./Services/User/classes/class.ilUserUtil.php");
2605 $lock = $this->getEditLockInfo();
2606 $errors[0] = array(0 => 0,
2607 1 => "nocontent#" . $this->lng->txt("cont_not_saved_edit_lock_expired") . "<br />" .
2608 $this->lng->txt("obj_usr") . ": " .
2609 ilUserUtil::getNamePresentation($lock["edit_lock_user"]) . "<br />" .
2610 $this->lng->txt("content_until") . ": " .
2611 ilDatePresentation::formatDate(new ilDateTime($lock["edit_lock_until"], IL_CAL_UNIX))
2612 );
2613 }
2614
2615 if (!empty($errors)) {
2616 $this->log->debug("ilPageObject, update(): errors: " . print_r($errors, true));
2617 }
2618
2619 //echo "-".htmlentities($this->getXMLFromDom())."-"; exit;
2620 if (empty($errors)) {
2621 // @todo 1: is this page type or pc content type
2622 // related -> plugins should be able to hook in!?
2624
2625 // get xml content
2626 $content = $this->getXMLFromDom();
2627 $dom_doc = $this->getDomDoc();
2628
2629 // this needs to be locked
2630
2631 // write history entry
2632 $old_set = $this->db->query("SELECT * FROM page_object WHERE " .
2633 "page_id = " . $this->db->quote($this->getId(), "integer") . " AND " .
2634 "parent_type = " . $this->db->quote($this->getParentType(), "text") . " AND " .
2635 "lang = " . $this->db->quote($this->getLanguage(), "text"));
2636 $last_nr_set = $this->db->query("SELECT max(nr) as mnr FROM page_history WHERE " .
2637 "page_id = " . $this->db->quote($this->getId(), "integer") . " AND " .
2638 "parent_type = " . $this->db->quote($this->getParentType(), "text") . " AND " .
2639 "lang = " . $this->db->quote($this->getLanguage(), "text"));
2640 $last_nr = $this->db->fetchAssoc($last_nr_set);
2641 if ($old_rec = $this->db->fetchAssoc($old_set)) {
2642 // only save, if something has changed
2643 // added user id to the check for ilias 5.0, 7.10.2014
2644 if (($content != $old_rec["content"] || $this->user->getId() != $old_rec["last_change_user"]) &&
2645 !$a_no_history && !$this->history_saved && $lm_set->get("page_history", 1)) {
2646 if ($old_rec["content"] != "<PageObject></PageObject>") {
2647 $this->db->manipulateF(
2648 "DELETE FROM page_history WHERE " .
2649 "page_id = %s AND parent_type = %s AND hdate = %s AND lang = %s",
2650 array("integer", "text", "timestamp", "text"),
2651 array($old_rec["page_id"], $old_rec["parent_type"], $old_rec["last_change"], $old_rec["lang"])
2652 );
2653
2654 // the following lines are a workaround for
2655 // bug 6741
2656 $last_c = $old_rec["last_change"];
2657 if ($last_c == "") {
2658 $last_c = ilUtil::now();
2659 }
2660
2661 $this->db->insert("page_history", array(
2662 "page_id" => array("integer", $old_rec["page_id"]),
2663 "parent_type" => array("text", $old_rec["parent_type"]),
2664 "lang" => array("text", $old_rec["lang"]),
2665 "hdate" => array("timestamp", $last_c),
2666 "parent_id" => array("integer", $old_rec["parent_id"]),
2667 "content" => array("clob", $old_rec["content"]),
2668 "user_id" => array("integer", $old_rec["last_change_user"]),
2669 "ilias_version" => array("text", ILIAS_VERSION_NUMERIC),
2670 "nr" => array("integer", (int) $last_nr["mnr"] + 1)
2671 ));
2672
2673 $old_content = $old_rec["content"];
2674 $old_domdoc = new DOMDocument();
2675 $old_nr = $last_nr["mnr"] + 1;
2676 $old_domdoc->loadXML('<?xml version="1.0" encoding="UTF-8"?>' . $old_content);
2677
2678 // after history entry creation event
2679 $this->__afterHistoryEntry($old_domdoc, $old_content, $old_nr);
2680
2681 $this->history_saved = true; // only save one time
2682 } else {
2683 $this->history_saved = true; // do not save on first change
2684 }
2685 }
2686 }
2687 //echo htmlentities($content);
2688 $em = (trim($content) == "<PageObject/>")
2689 ? 1
2690 : 0;
2691
2692 // @todo: pass dom instead?
2693 $iel = $this->containsDeactivatedElements($content);
2694 $inl = $this->containsIntLinks($content);
2695
2696 $this->db->update("page_object", array(
2697 "content" => array("clob", $content),
2698 "parent_id" => array("integer", $this->getParentId()),
2699 "last_change_user" => array("integer", $this->user->getId()),
2700 "last_change" => array("timestamp", ilUtil::now()),
2701 "is_empty" => array("integer", $em),
2702 "active" => array("integer", $this->getActive()),
2703 "activation_start" => array("timestamp", $this->getActivationStart()),
2704 "activation_end" => array("timestamp", $this->getActivationEnd()),
2705 "show_activation_info" => array("integer", $this->getShowActivationInfo()),
2706 "inactive_elements" => array("integer", $iel),
2707 "int_links" => array("integer", $inl),
2708 ), array(
2709 "page_id" => array("integer", $this->getId()),
2710 "parent_type" => array("text", $this->getParentType()),
2711 "lang" => array("text", $this->getLanguage())
2712 ));
2713
2714 // after update event
2715 $this->__afterUpdate($dom_doc, $content);
2716
2717 $this->log->debug("ilPageObject, update(): updated and returning true, content: " . substr($this->getXMLContent(), 0, 100));
2718
2719 //echo "<br>PageObject::update:".htmlentities($this->getXMLContent()).":";
2720 return true;
2721 } else {
2722 return $errors;
2723 }
2724 }
2725
2726
2727
2731 public function delete()
2732 {
2733 $copg_logger = ilLoggerFactory::getLogger('copg');
2734 $copg_logger->debug(
2735 "ilPageObject: Delete called for ID '" . $this->getId() . "'," .
2736 " parent type: '" . $this->getParentType() . "', " .
2737 " hist nr: '" . $this->old_nr . "', " .
2738 " lang: '" . $this->getLanguage() . "', "
2739 );
2740
2741 $mobs = array();
2742 $files = array();
2743
2744 if (!$this->page_not_found) {
2745 $this->buildDom();
2746 $mobs = $this->collectMediaObjects(false);
2747 }
2748 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2749 $mobs2 = ilObjMediaObject::_getMobsOfObject($this->getParentType() . ":pg", $this->getId(), false);
2750 foreach ($mobs2 as $m) {
2751 if (!in_array($m, $mobs)) {
2752 $mobs[] = $m;
2753 }
2754 }
2755
2756 $copg_logger->debug("ilPageObject: ... found " . count($mobs) . " media objects.");
2757
2758 $this->__beforeDelete();
2759
2760 // treat plugged content
2761 $this->handleDeleteContent();
2762
2763 // delete style usages
2764 $this->deleteStyleUsages(false);
2765
2766 // delete internal links
2767 $this->deleteInternalLinks();
2768
2769 // delete all mob usages
2770 ilObjMediaObject::_deleteAllUsages($this->getParentType() . ":pg", $this->getId());
2771
2772 // delete news
2773 include_once("./Services/News/classes/class.ilNewsItem.php");
2775 $this->getParentId(),
2776 $this->getParentType(),
2777 $this->getId(),
2778 "pg"
2779 );
2780
2781 // delete page_object entry
2782 $this->db->manipulate("DELETE FROM page_object " .
2783 "WHERE page_id = " . $this->db->quote($this->getId(), "integer") .
2784 " AND parent_type= " . $this->db->quote($this->getParentType(), "text"));
2785
2786 // delete media objects
2787 foreach ($mobs as $mob_id) {
2788 $copg_logger->debug("ilPageObject: ... processing mob " . $mob_id . ".");
2789
2790 if (ilObject::_lookupType($mob_id) != 'mob') {
2791 $copg_logger->debug("ilPageObject: ... type mismatch. Ignoring mob " . $mob_id . ".");
2792 continue;
2793 }
2794
2795 if (ilObject::_exists($mob_id)) {
2796 $copg_logger->debug("ilPageObject: ... delete mob " . $mob_id . ".");
2797
2798 $mob_obj = new ilObjMediaObject($mob_id);
2799 $mob_obj->delete();
2800 } else {
2801 $copg_logger->debug("ilPageObject: ... missing mob " . $mob_id . ".");
2802 }
2803 }
2804 }
2805
2811 final protected function __beforeDelete()
2812 {
2813 // pc classes hook
2814 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2816 foreach ($defs as $def) {
2818 $cl = $def["pc_class"];
2819 call_user_func($def["pc_class"] . '::beforePageDelete', $this);
2820 }
2821 }
2822
2828 final protected function __afterHistoryEntry($a_old_domdoc, $a_old_content, $a_old_nr)
2829 {
2830 // save style usage
2831 $this->saveStyleUsage($a_old_domdoc, $a_old_nr);
2832
2833 // pc classes hook
2834 include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2836 foreach ($defs as $def) {
2838 $cl = $def["pc_class"];
2839 call_user_func($def["pc_class"] . '::afterPageHistoryEntry', $this, $a_old_domdoc, $a_old_content, $a_old_nr);
2840 }
2841 }
2842
2848 public function saveStyleUsage($a_domdoc, $a_old_nr = 0)
2849 {
2850 // media aliases
2851 $xpath = new DOMXPath($a_domdoc);
2852 $path = "//Paragraph | //Section | //MediaAlias | //FileItem" .
2853 " | //Table | //TableData | //Tabs | //List";
2854 $nodes = $xpath->query($path);
2855 $usages = array();
2856 foreach ($nodes as $node) {
2857 switch ($node->localName) {
2858 case "Paragraph":
2859 $sname = $node->getAttribute("Characteristic");
2860 $stype = "text_block";
2861 $template = 0;
2862 break;
2863
2864 case "Section":
2865 $sname = $node->getAttribute("Characteristic");
2866 $stype = "section";
2867 $template = 0;
2868 break;
2869
2870 case "MediaAlias":
2871 $sname = $node->getAttribute("Class");
2872 $stype = "media_cont";
2873 $template = 0;
2874 break;
2875
2876 case "FileItem":
2877 $sname = $node->getAttribute("Class");
2878 $stype = "flist_li";
2879 $template = 0;
2880 break;
2881
2882 case "Table":
2883 $sname = $node->getAttribute("Template");
2884 if ($sname == "") {
2885 $sname = $node->getAttribute("Class");
2886 $stype = "table";
2887 $template = 0;
2888 } else {
2889 $stype = "table";
2890 $template = 1;
2891 }
2892 break;
2893
2894 case "TableData":
2895 $sname = $node->getAttribute("Class");
2896 $stype = "table_cell";
2897 $template = 0;
2898 break;
2899
2900 case "Tabs":
2901 $sname = $node->getAttribute("Template");
2902 if ($sname != "") {
2903 if ($node->getAttribute("Type") == "HorizontalAccordion") {
2904 $stype = "haccordion";
2905 }
2906 if ($node->getAttribute("Type") == "VerticalAccordion") {
2907 $stype = "vaccordion";
2908 }
2909 }
2910 $template = 1;
2911 break;
2912
2913 case "List":
2914 $sname = $node->getAttribute("Class");
2915 if ($node->getAttribute("Type") == "Ordered") {
2916 $stype = "list_o";
2917 } else {
2918 $stype = "list_u";
2919 }
2920 $template = 0;
2921 break;
2922 }
2923 if ($sname != "" && $stype != "") {
2924 $usages[$sname . ":" . $stype . ":" . $template] = array("sname" => $sname,
2925 "stype" => $stype, "template" => $template);
2926 }
2927 }
2928
2929
2930 $this->deleteStyleUsages($a_old_nr);
2931
2932 foreach ($usages as $u) {
2933 $id = $this->db->nextId('page_style_usage');
2934
2935 $this->db->manipulate("INSERT INTO page_style_usage " .
2936 "(id, page_id, page_type, page_lang, page_nr, template, stype, sname) VALUES (" .
2937 $this->db->quote($id, "integer") . "," .
2938 $this->db->quote($this->getId(), "integer") . "," .
2939 $this->db->quote($this->getParentType(), "text") . "," .
2940 $this->db->quote($this->getLanguage(), "text") . "," .
2941 $this->db->quote($a_old_nr, "integer") . "," .
2942 $this->db->quote($u["template"], "integer") . "," .
2943 $this->db->quote($u["stype"], "text") . "," .
2944 $this->db->quote($u["sname"], "text") .
2945 ")");
2946 }
2947 }
2948
2955 public function deleteStyleUsages($a_old_nr = 0)
2956 {
2957 if ($a_old_nr !== false) {
2958 $and_old_nr = " AND page_nr = " . $this->db->quote($a_old_nr, "integer");
2959 }
2960
2961 $this->db->manipulate(
2962 "DELETE FROM page_style_usage WHERE " .
2963 " page_id = " . $this->db->quote($this->getId(), "integer") .
2964 " AND page_type = " . $this->db->quote($this->getParentType(), "text") .
2965 " AND page_lang = " . $this->db->quote($this->getLanguage(), "text") .
2966 $and_old_nr
2967 );
2968 }
2969
2970
2975 // @todo: move to content include class
2977 {
2978 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2979 include_once("./Modules/File/classes/class.ilObjFile.php");
2981 $this->getParentType() . ":pg",
2982 $this->getId()
2983 );
2985 $this->getParentType() . ":pg",
2986 $this->getId()
2987 );
2988 $objs = array_merge($mobs, $files);
2990 }
2991
2998 public function deleteInternalLinks()
2999 {
3000 include_once("./Services/Link/classes/class.ilInternalLink.php");
3002 $this->getParentType() . ":pg",
3003 $this->getId(),
3004 $this->getLanguage()
3005 );
3006 }
3007
3008
3014 // @todo: move to specific classes, internal link use info
3015 public function saveInternalLinks($a_domdoc)
3016 {
3017 $this->deleteInternalLinks();
3018
3019 // query IntLink elements
3020 $xpath = new DOMXPath($a_domdoc);
3021 $nodes = $xpath->query('//IntLink');
3022 foreach ($nodes as $node) {
3023 $link_type = $node->getAttribute("Type");
3024
3025 switch ($link_type) {
3026 case "StructureObject":
3027 $t_type = "st";
3028 break;
3029
3030 case "PageObject":
3031 $t_type = "pg";
3032 break;
3033
3034 case "GlossaryItem":
3035 $t_type = "git";
3036 break;
3037
3038 case "MediaObject":
3039 $t_type = "mob";
3040 break;
3041
3042 case "RepositoryItem":
3043 $t_type = "obj";
3044 break;
3045
3046 case "File":
3047 $t_type = "file";
3048 break;
3049
3050 case "WikiPage":
3051 $t_type = "wpage";
3052 break;
3053
3054 case "PortfolioPage":
3055 $t_type = "ppage";
3056 break;
3057
3058 case "User":
3059 $t_type = "user";
3060 break;
3061 }
3062
3063 $target = $node->getAttribute("Target");
3064 $target_arr = explode("_", $target);
3065 $t_id = $target_arr[count($target_arr) - 1];
3066
3067 // link to other internal object
3068 if (is_int(strpos($target, "__"))) {
3069 $t_inst = 0;
3070 } else { // link to unresolved object in other installation
3071 $t_inst = $target_arr[1];
3072 }
3073
3074 if ($t_id > 0) {
3076 $this->getParentType() . ":pg",
3077 $this->getId(),
3078 $t_type,
3079 $t_id,
3080 $t_inst,
3081 $this->getLanguage()
3082 );
3083 }
3084 }
3085 }
3086
3090 public function create()
3091 {
3092 $this->createFromXML();
3093 }
3094
3102 public function deleteContent($a_hid, $a_update = true, $a_pcid = "")
3103 {
3104 $curr_node = $this->getContentNode($a_hid, $a_pcid);
3105 $this->handleDeleteContent($curr_node);
3106 $curr_node->unlink_node($curr_node);
3107 if ($a_update) {
3108 return $this->update();
3109 }
3110 }
3111
3112
3120 public function deleteContents($a_hids, $a_update = true, $a_self_ass = false)
3121 {
3122 if (!is_array($a_hids)) {
3123 return;
3124 }
3125 foreach ($a_hids as $a_hid) {
3126 $a_hid = explode(":", $a_hid);
3127 //echo "-".$a_hid[0]."-".$a_hid[1]."-";
3128
3129 // @todo 1: hook
3130 // do not delete question nodes in assessment pages
3131 if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass) {
3132 $curr_node = $this->getContentNode($a_hid[0], $a_hid[1]);
3133 if (is_object($curr_node)) {
3134 $parent_node = $curr_node->parent_node();
3135 if ($parent_node->node_name() != "TableRow") {
3136 $this->handleDeleteContent($curr_node);
3137 $curr_node->unlink_node($curr_node);
3138 }
3139 }
3140 }
3141 }
3142 if ($a_update) {
3143 return $this->update();
3144 }
3145 }
3146
3152 public function cutContents($a_hids)
3153 {
3154 $this->copyContents($a_hids);
3155 return $this->deleteContents($a_hids, true, $this->getPageConfig()->getEnableSelfAssessment());
3156 }
3157
3163 public function copyContents($a_hids)
3164 {
3166
3167 if (!is_array($a_hids)) {
3168 return;
3169 }
3170
3171 $time = date("Y-m-d H:i:s", time());
3172
3173 $hier_ids = array();
3174 $skip = array();
3175 foreach ($a_hids as $a_hid) {
3176 if ($a_hid == "") {
3177 continue;
3178 }
3179 $a_hid = explode(":", $a_hid);
3180
3181 // check, whether new hid is child of existing one or vice versa
3182 reset($hier_ids);
3183 foreach ($hier_ids as $h) {
3184 if ($h . "_" == substr($a_hid[0], 0, strlen($h) + 1)) {
3185 $skip[] = $a_hid[0];
3186 }
3187 if ($a_hid[0] . "_" == substr($h, 0, strlen($a_hid[0]) + 1)) {
3188 $skip[] = $h;
3189 }
3190 }
3191 $pc_id[$a_hid[0]] = $a_hid[1];
3192 if ($a_hid[0] != "") {
3193 $hier_ids[$a_hid[0]] = $a_hid[0];
3194 }
3195 }
3196 foreach ($skip as $s) {
3197 unset($hier_ids[$s]);
3198 }
3199 include_once("./Services/COPage/classes/class.ilPageContent.php");
3200 $hier_ids = ilPageContent::sortHierIds($hier_ids);
3201 $nr = 1;
3202 foreach ($hier_ids as $hid) {
3203 $curr_node = $this->getContentNode($hid, $pc_id[$hid]);
3204 if (is_object($curr_node)) {
3205 if ($curr_node->node_name() == "PageContent") {
3206 $content = $this->dom->dump_node($curr_node);
3207 // remove pc and hier ids
3208 $content = preg_replace('/PCID=\"[a-z0-9]*\"/i', "", $content);
3209 $content = preg_replace('/HierId=\"[a-z0-9_]*\"/i', "", $content);
3210
3211 $user->addToPCClipboard($content, $time, $nr);
3212 $nr++;
3213 }
3214 }
3215 }
3216 include_once("./Modules/LearningModule/classes/class.ilEditClipboard.php");
3218 }
3219
3223 public function pasteContents($a_hier_id, $a_self_ass = false)
3224 {
3226
3227 $a_hid = explode(":", $a_hier_id);
3228 $content = $user->getPCClipboardContent();
3229
3230 // we insert from last to first, because we insert all at the
3231 // same hier_id
3232 for ($i = count($content) - 1; $i >= 0; $i--) {
3233 $c = $content[$i];
3234 $temp_dom = domxml_open_mem(
3235 '<?xml version="1.0" encoding="UTF-8"?>' . $c,
3237 $error
3238 );
3239 if (empty($error)) {
3240 $this->handleCopiedContent($temp_dom, $a_self_ass);
3241 $xpc = xpath_new_context($temp_dom);
3242 $path = "//PageContent";
3243 $res = xpath_eval($xpc, $path);
3244 if (count($res->nodeset) > 0) {
3245 $new_pc_node = $res->nodeset[0];
3246 $cloned_pc_node = $new_pc_node->clone_node(true);
3247 $cloned_pc_node->unlink_node($cloned_pc_node);
3248 $this->insertContentNode(
3249 $cloned_pc_node,
3250 $a_hid[0],
3252 $a_hid[1]
3253 );
3254 }
3255 } else {
3256 //var_dump($error);
3257 }
3258 }
3259 $e = $this->update();
3260 //var_dump($e);
3261 }
3262
3266 public function switchEnableMultiple($a_hids, $a_update = true, $a_self_ass = false)
3267 {
3268 if (!is_array($a_hids)) {
3269 return;
3270 }
3271 $obj = &$this->content_obj;
3272
3273 foreach ($a_hids as $a_hid) {
3274 $a_hid = explode(":", $a_hid);
3275 $curr_node = $this->getContentNode($a_hid[0], $a_hid[1]);
3276 if (is_object($curr_node)) {
3277 if ($curr_node->node_name() == "PageContent") {
3278 $cont_obj = $this->getContentObject($a_hid[0], $a_hid[1]);
3279 if ($cont_obj->isEnabled()) {
3280 // do not deactivate question nodes in assessment pages
3281 if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass) {
3282 $cont_obj->disable();
3283 }
3284 } else {
3285 $cont_obj->enable();
3286 }
3287 }
3288 }
3289 }
3290
3291 if ($a_update) {
3292 return $this->update();
3293 }
3294 }
3295
3296
3304 public function deleteContentFromHierId($a_hid, $a_update = true)
3305 {
3306 $hier_ids = $this->getHierIds();
3307
3308 // iterate all hierarchical ids
3309 foreach ($hier_ids as $hier_id) {
3310 // delete top level nodes only
3311 if (!is_int(strpos($hier_id, "_"))) {
3312 if ($hier_id != "pg" && $hier_id >= $a_hid) {
3313 $curr_node = $this->getContentNode($hier_id);
3314 $this->handleDeleteContent($curr_node);
3315 $curr_node->unlink_node($curr_node);
3316 }
3317 }
3318 }
3319 if ($a_update) {
3320 return $this->update();
3321 }
3322 }
3323
3331 public function deleteContentBeforeHierId($a_hid, $a_update = true)
3332 {
3333 $hier_ids = $this->getHierIds();
3334
3335 // iterate all hierarchical ids
3336 foreach ($hier_ids as $hier_id) {
3337 // delete top level nodes only
3338 if (!is_int(strpos($hier_id, "_"))) {
3339 if ($hier_id != "pg" && $hier_id < $a_hid) {
3340 $curr_node = $this->getContentNode($hier_id);
3341 $this->handleDeleteContent($curr_node);
3342 $curr_node->unlink_node($curr_node);
3343 }
3344 }
3345 }
3346 if ($a_update) {
3347 return $this->update();
3348 }
3349 }
3350
3351
3359 public static function _moveContentAfterHierId(&$a_source_page, &$a_target_page, $a_hid)
3360 {
3361 $hier_ids = $a_source_page->getHierIds();
3362
3363 $copy_ids = array();
3364
3365 // iterate all hierarchical ids
3366 foreach ($hier_ids as $hier_id) {
3367 // move top level nodes only
3368 if (!is_int(strpos($hier_id, "_"))) {
3369 if ($hier_id != "pg" && $hier_id >= $a_hid) {
3370 $copy_ids[] = $hier_id;
3371 }
3372 }
3373 }
3374 asort($copy_ids);
3375
3376 $parent_node = $a_target_page->getContentNode("pg");
3377 $target_dom = $a_target_page->getDom();
3378 $parent_childs = $parent_node->child_nodes();
3379 $cnt_parent_childs = count($parent_childs);
3380 //echo "-$cnt_parent_childs-";
3381 $first_child = $parent_childs[0];
3382 foreach ($copy_ids as $copy_id) {
3383 $source_node = $a_source_page->getContentNode($copy_id);
3384
3385 $new_node = $source_node->clone_node(true);
3386 $new_node->unlink_node($new_node);
3387
3388 $source_node->unlink_node($source_node);
3389
3390 if ($cnt_parent_childs == 0) {
3391 $new_node = $parent_node->append_child($new_node);
3392 } else {
3393 //$target_dom->import_node($new_node);
3394 $new_node = $first_child->insert_before($new_node, $first_child);
3395 }
3396 $parent_childs = $parent_node->child_nodes();
3397
3398 //$cnt_parent_childs++;
3399 }
3400
3401 $a_target_page->update();
3402 $a_source_page->update();
3403 }
3404
3408 public function insertContent(&$a_cont_obj, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "")
3409 {
3410 // move mode into container elements is always INSERT_CHILD
3411 $curr_node = $this->getContentNode($a_pos, $a_pcid);
3412 $curr_name = $curr_node->node_name();
3413
3414 // @todo: try to generalize this
3415 if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3416 ($curr_name == "ListItem") || ($curr_name == "Section")
3417 || ($curr_name == "Tab") || ($curr_name == "ContentPopup")
3418 || ($curr_name == "GridCell")) {
3419 $a_mode = IL_INSERT_CHILD;
3420 }
3421
3422 $hid = $curr_node->get_attribute("HierId");
3423 if ($hid != "") {
3424 //echo "-".$a_pos."-".$hid."-";
3425 $a_pos = $hid;
3426 }
3427
3428 if ($a_mode != IL_INSERT_CHILD) { // determine parent hierarchical id
3429 // of sibling at $a_pos
3430 $pos = explode("_", $a_pos);
3431 $target_pos = array_pop($pos);
3432 $parent_pos = implode("_", $pos);
3433 } else { // if we should insert a child, $a_pos is alreade the hierarchical id
3434 // of the parent node
3435 $parent_pos = $a_pos;
3436 }
3437
3438 // get the parent node
3439 if ($parent_pos != "") {
3440 $parent_node = $this->getContentNode($parent_pos);
3441 } else {
3442 $parent_node = $this->getNode();
3443 }
3444
3445 // count the parent children
3446 $parent_childs = $parent_node->child_nodes();
3447 $cnt_parent_childs = count($parent_childs);
3448 //echo "ZZ$a_mode";
3449 switch ($a_mode) {
3450 // insert new node after sibling at $a_pos
3451 case IL_INSERT_AFTER:
3452 $new_node = $a_cont_obj->getNode();
3453 //$a_pos = ilPageContent::incEdId($a_pos);
3454 //$curr_node = $this->getContentNode($a_pos);
3455//echo "behind $a_pos:";
3456 if ($succ_node = $curr_node->next_sibling()) {
3457 $new_node = $succ_node->insert_before($new_node, $succ_node);
3458 } else {
3459 //echo "movin doin append_child";
3460 $new_node = $parent_node->append_child($new_node);
3461 }
3462 $a_cont_obj->setNode($new_node);
3463 break;
3464
3465 case IL_INSERT_BEFORE:
3466//echo "INSERT_BEF";
3467 $new_node = $a_cont_obj->getNode();
3468 $succ_node = $this->getContentNode($a_pos);
3469 $new_node = $succ_node->insert_before($new_node, $succ_node);
3470 $a_cont_obj->setNode($new_node);
3471 break;
3472
3473 // insert new node as first child of parent $a_pos (= $a_parent)
3474 case IL_INSERT_CHILD:
3475//echo "insert as child:parent_childs:$cnt_parent_childs:<br>";
3476 $new_node = $a_cont_obj->getNode();
3477 if ($cnt_parent_childs == 0) {
3478 $new_node = $parent_node->append_child($new_node);
3479 } else {
3480 $new_node = $parent_childs[0]->insert_before($new_node, $parent_childs[0]);
3481 }
3482 $a_cont_obj->setNode($new_node);
3483//echo "PP";
3484 break;
3485 }
3486
3487 //check for PlaceHolder to remove in EditMode-keep in Layout Mode
3488 if (!$this->getPageConfig()->getEnablePCType("PlaceHolder")) {
3489 $sub_nodes = $curr_node->child_nodes() ;
3490 foreach ($sub_nodes as $sub_node) {
3491 if ($sub_node->node_name() == "PlaceHolder") {
3492 $curr_node->unlink_node();
3493 }
3494 }
3495 }
3496 }
3497
3501 public function insertContentNode(&$a_cont_node, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "")
3502 {
3503 // move mode into container elements is always INSERT_CHILD
3504 $curr_node = $this->getContentNode($a_pos, $a_pcid);
3505 $curr_name = $curr_node->node_name();
3506
3507 // @todo: try to generalize
3508 if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3509 ($curr_name == "ListItem") || ($curr_name == "Section")
3510 || ($curr_name == "Tab") || ($curr_name == "ContentPopup")
3511 || ($curr_name == "GridCell")) {
3512 $a_mode = IL_INSERT_CHILD;
3513 }
3514
3515 $hid = $curr_node->get_attribute("HierId");
3516 if ($hid != "") {
3517 $a_pos = $hid;
3518 }
3519
3520 if ($a_mode != IL_INSERT_CHILD) { // determine parent hierarchical id
3521 // of sibling at $a_pos
3522 $pos = explode("_", $a_pos);
3523 $target_pos = array_pop($pos);
3524 $parent_pos = implode("_", $pos);
3525 } else { // if we should insert a child, $a_pos is alreade the hierarchical id
3526 // of the parent node
3527 $parent_pos = $a_pos;
3528 }
3529
3530 // get the parent node
3531 if ($parent_pos != "") {
3532 $parent_node = $this->getContentNode($parent_pos);
3533 } else {
3534 $parent_node = $this->getNode();
3535 }
3536
3537 // count the parent children
3538 $parent_childs = $parent_node->child_nodes();
3539 $cnt_parent_childs = count($parent_childs);
3540
3541 switch ($a_mode) {
3542 // insert new node after sibling at $a_pos
3543 case IL_INSERT_AFTER:
3544 //$new_node = $a_cont_obj->getNode();
3545 if ($succ_node = $curr_node->next_sibling()) {
3546 $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3547 } else {
3548 $a_cont_node = $parent_node->append_child($a_cont_node);
3549 }
3550 //$a_cont_obj->setNode($new_node);
3551 break;
3552
3553 case IL_INSERT_BEFORE:
3554 //$new_node = $a_cont_obj->getNode();
3555 $succ_node = $this->getContentNode($a_pos);
3556 $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3557 //$a_cont_obj->setNode($new_node);
3558 break;
3559
3560 // insert new node as first child of parent $a_pos (= $a_parent)
3561 case IL_INSERT_CHILD:
3562 //$new_node = $a_cont_obj->getNode();
3563 if ($cnt_parent_childs == 0) {
3564 $a_cont_node = $parent_node->append_child($a_cont_node);
3565 } else {
3566 $a_cont_node = $parent_childs[0]->insert_before($a_cont_node, $parent_childs[0]);
3567 }
3568 //$a_cont_obj->setNode($new_node);
3569 break;
3570 }
3571 }
3572
3577 public function moveContentBefore($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3578 {
3579 if ($a_source == $a_target) {
3580 return;
3581 }
3582
3583 // clone the node
3584 $content = $this->getContentObject($a_source, $a_spcid);
3585 $source_node = $content->getNode();
3586 $clone_node = $source_node->clone_node(true);
3587
3588 // delete source node
3589 $this->deleteContent($a_source, false, $a_spcid);
3590
3591 // insert cloned node at target
3592 $content->setNode($clone_node);
3593 $this->insertContent($content, $a_target, IL_INSERT_BEFORE, $a_tpcid);
3594 return $this->update();
3595 }
3596
3601 public function moveContentAfter($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3602 {
3603 if ($a_source == $a_target) {
3604 return;
3605 }
3606
3607 // clone the node
3608 $content = $this->getContentObject($a_source, $a_spcid);
3609 $source_node = $content->getNode();
3610 $clone_node = $source_node->clone_node(true);
3611
3612 // delete source node
3613 $this->deleteContent($a_source, false, $a_spcid);
3614
3615 // insert cloned node at target
3616 $content->setNode($clone_node);
3617 $this->insertContent($content, $a_target, IL_INSERT_AFTER, $a_tpcid);
3618 return $this->update();
3619 }
3620
3624 // @todo: move to paragraph
3625 public function bbCode2XML(&$a_content)
3626 {
3627 $a_content = preg_replace('/\[com\]/i', "<Comment>", $a_content);
3628 $a_content = preg_replace('/\[\/com\]/i', "</Comment>", $a_content);
3629 $a_content = preg_replace('/\[emp]/i', "<Emph>", $a_content);
3630 $a_content = preg_replace('/\[\/emp\]/i', "</Emph>", $a_content);
3631 $a_content = preg_replace('/\[str]/i', "<Strong>", $a_content);
3632 $a_content = preg_replace('/\[\/str\]/i', "</Strong>", $a_content);
3633 }
3634
3639 public function insertInstIntoIDs($a_inst, $a_res_ref_to_obj_id = true)
3640 {
3641 // insert inst id into internal links
3642 $xpc = xpath_new_context($this->dom);
3643 $path = "//IntLink";
3644 $res = xpath_eval($xpc, $path);
3645 for ($i = 0; $i < count($res->nodeset); $i++) {
3646 $target = $res->nodeset[$i]->get_attribute("Target");
3647 $type = $res->nodeset[$i]->get_attribute("Type");
3648
3649 if (substr($target, 0, 4) == "il__") {
3650 $id = substr($target, 4, strlen($target) - 4);
3651
3652 // convert repository links obj_<ref_id> to <type>_<obj_id>
3653 // this leads to bug 6685.
3654 if ($a_res_ref_to_obj_id && $type == "RepositoryItem") {
3655 $id_arr = explode("_", $id);
3656
3657 // changed due to bug 6685
3658 $ref_id = $id_arr[1];
3659 $obj_id = ilObject::_lookupObjId($id_arr[1]);
3660
3661 $otype = ilObject::_lookupType($obj_id);
3662 if ($obj_id > 0) {
3663 // changed due to bug 6685
3664 // the ref_id should be used, if the content is
3665 // imported on the same installation
3666 // the obj_id should be used, if a different
3667 // installation imports, but has an import_id for
3668 // the object id.
3669 $id = $otype . "_" . $obj_id . "_" . $ref_id;
3670 //$id = $otype."_".$ref_id;
3671 }
3672 }
3673 $new_target = "il_" . $a_inst . "_" . $id;
3674 $res->nodeset[$i]->set_attribute("Target", $new_target);
3675 }
3676 }
3677 unset($xpc);
3678
3679 // @todo: move to media/fileitems/questions, ...
3680
3681 // insert inst id into media aliases
3682 $xpc = xpath_new_context($this->dom);
3683 $path = "//MediaAlias";
3684 $res = xpath_eval($xpc, $path);
3685 for ($i = 0; $i < count($res->nodeset); $i++) {
3686 $origin_id = $res->nodeset[$i]->get_attribute("OriginId");
3687 if (substr($origin_id, 0, 4) == "il__") {
3688 $new_id = "il_" . $a_inst . "_" . substr($origin_id, 4, strlen($origin_id) - 4);
3689 $res->nodeset[$i]->set_attribute("OriginId", $new_id);
3690 }
3691 }
3692 unset($xpc);
3693
3694 // insert inst id file item identifier entries
3695 $xpc = xpath_new_context($this->dom);
3696 $path = "//FileItem/Identifier";
3697 $res = xpath_eval($xpc, $path);
3698 for ($i = 0; $i < count($res->nodeset); $i++) {
3699 $origin_id = $res->nodeset[$i]->get_attribute("Entry");
3700 if (substr($origin_id, 0, 4) == "il__") {
3701 $new_id = "il_" . $a_inst . "_" . substr($origin_id, 4, strlen($origin_id) - 4);
3702 $res->nodeset[$i]->set_attribute("Entry", $new_id);
3703 }
3704 }
3705 unset($xpc);
3706
3707 // insert inst id into question references
3708 $xpc = xpath_new_context($this->dom);
3709 $path = "//Question";
3710 $res = xpath_eval($xpc, $path);
3711 for ($i = 0; $i < count($res->nodeset); $i++) {
3712 $qref = $res->nodeset[$i]->get_attribute("QRef");
3713 //echo "<br>setted:".$qref;
3714 if (substr($qref, 0, 4) == "il__") {
3715 $new_id = "il_" . $a_inst . "_" . substr($qref, 4, strlen($qref) - 4);
3716 //echo "<br>setting:".$new_id;
3717 $res->nodeset[$i]->set_attribute("QRef", $new_id);
3718 }
3719 }
3720 unset($xpc);
3721
3722 // insert inst id into content snippets
3723 $xpc = xpath_new_context($this->dom);
3724 $path = "//ContentInclude";
3725 $res = xpath_eval($xpc, $path);
3726 for ($i = 0; $i < count($res->nodeset); $i++) {
3727 $ci = $res->nodeset[$i]->get_attribute("InstId");
3728 if ($ci == "") {
3729 $res->nodeset[$i]->set_attribute("InstId", $a_inst);
3730 }
3731 }
3732 unset($xpc);
3733 }
3734
3738 public function checkPCIds()
3739 {
3740 $this->builddom();
3741 $mydom = $this->dom;
3742
3743 $sep = $path = "";
3744 foreach ($this->id_elements as $el) {
3745 $path .= $sep . "//" . $el . "[not(@PCID)]";
3746 $sep = " | ";
3747 $path .= $sep . "//" . $el . "[@PCID='']";
3748 }
3749
3750 $xpc = xpath_new_context($mydom);
3751 $res = &xpath_eval($xpc, $path);
3752
3753 if (count($res->nodeset) > 0) {
3754 return false;
3755 }
3756 return true;
3757 }
3758
3765 public function getAllPCIds()
3766 {
3767 $this->builddom();
3768 $mydom = $this->dom;
3769
3770 $pcids = array();
3771
3772 $sep = $path = "";
3773 foreach ($this->id_elements as $el) {
3774 $path .= $sep . "//" . $el . "[@PCID]";
3775 $sep = " | ";
3776 }
3777
3778 // get existing ids
3779 $xpc = xpath_new_context($mydom);
3780 $res = &xpath_eval($xpc, $path);
3781
3782 for ($i = 0; $i < count($res->nodeset); $i++) {
3783 $node = $res->nodeset[$i];
3784 $pcids[] = $node->get_attribute("PCID");
3785 }
3786 return $pcids;
3787 }
3788
3795 public function existsPCId($a_pc_id)
3796 {
3797 $this->builddom();
3798 $mydom = $this->dom;
3799
3800 $pcids = array();
3801
3802 $sep = $path = "";
3803 foreach ($this->id_elements as $el) {
3804 $path .= $sep . "//" . $el . "[@PCID='" . $a_pc_id . "']";
3805 $sep = " | ";
3806 }
3807
3808 // get existing ids
3809 $xpc = xpath_new_context($mydom);
3810 $res = &xpath_eval($xpc, $path);
3811 return (count($res->nodeset) > 0);
3812 }
3813
3820 public function generatePcId($a_pc_ids = false)
3821 {
3822 if ($a_pc_ids === false) {
3823 $a_pc_ids = $this->getAllPCIds();
3824 }
3825 $id = ilUtil::randomHash(10, $a_pc_ids);
3826 return $id;
3827 }
3828
3829
3833 public function insertPCIds()
3834 {
3835 $this->builddom();
3836 $mydom = $this->dom;
3837
3838 $pcids = $this->getAllPCIds();
3839
3840 // add missing ones
3841 $sep = $path = "";
3842 foreach ($this->id_elements as $el) {
3843 $path .= $sep . "//" . $el . "[not(@PCID)]";
3844 $sep = " | ";
3845 $path .= $sep . "//" . $el . "[@PCID='']";
3846 $sep = " | ";
3847 }
3848 $xpc = xpath_new_context($mydom);
3849 $res = &xpath_eval($xpc, $path);
3850
3851 for ($i = 0; $i < count($res->nodeset); $i++) {
3852 $node = $res->nodeset[$i];
3853 $id = ilUtil::randomHash(10, $pcids);
3854 $pcids[] = $id;
3855 //echo "setting-".$id."-";
3856 $res->nodeset[$i]->set_attribute("PCID", $id);
3857 }
3858 }
3859
3863 public function getPageContentsHashes()
3864 {
3865 $this->builddom();
3866 $this->addHierIds();
3867 $mydom = $this->dom;
3868
3869 // get existing ids
3870 $path = "//PageContent";
3871 $xpc = xpath_new_context($mydom);
3872 $res = &xpath_eval($xpc, $path);
3873
3874 $hashes = array();
3875 require_once("./Services/COPage/classes/class.ilPCParagraph.php");
3876 for ($i = 0; $i < count($res->nodeset); $i++) {
3877 $hier_id = $res->nodeset[$i]->get_attribute("HierId");
3878 $pc_id = $res->nodeset[$i]->get_attribute("PCID");
3879 $dump = $mydom->dump_node($res->nodeset[$i]);
3880 if (($hpos = strpos($dump, ' HierId="' . $hier_id . '"')) > 0) {
3881 $dump = substr($dump, 0, $hpos) .
3882 substr($dump, $hpos + strlen(' HierId="' . $hier_id . '"'));
3883 }
3884
3885 $childs = $res->nodeset[$i]->child_nodes();
3886 $content = "";
3887 if ($childs[0] && $childs[0]->node_name() == "Paragraph") {
3888 $content = $mydom->dump_node($childs[0]);
3889 $content = substr(
3890 $content,
3891 strpos($content, ">") + 1,
3892 strrpos($content, "<") - (strpos($content, ">") + 1)
3893 );
3894 //var_dump($content);
3895 $content = ilPCParagraph::xml2output($content);
3896 //var_dump($content);
3897 }
3898 //$hashes[$hier_id] =
3899 // array("PCID" => $pc_id, "hash" => md5($dump));
3900 $hashes[$pc_id] =
3901 array("hier_id" => $hier_id, "hash" => md5($dump), "content" => $content);
3902 }
3903
3904 return $hashes;
3905 }
3906
3910 // @todo: move to questions
3911 public function getQuestionIds()
3912 {
3913 $this->builddom();
3914 $mydom = $this->dom;
3915
3916 // Get question IDs
3917 $path = "//Question";
3918 $xpc = xpath_new_context($mydom);
3919 $res = &xpath_eval($xpc, $path);
3920
3921 $q_ids = array();
3922 include_once("./Services/Link/classes/class.ilInternalLink.php");
3923 for ($i = 0; $i < count($res->nodeset); $i++) {
3924 $qref = $res->nodeset[$i]->get_attribute("QRef");
3925
3926 $inst_id = ilInternalLink::_extractInstOfTarget($qref);
3928
3929 if (!($inst_id > 0)) {
3930 if ($obj_id > 0) {
3931 $q_ids[] = $obj_id;
3932 }
3933 }
3934 }
3935 return $q_ids;
3936 }
3937
3938 // @todo: move to paragraph
3939 public function send_paragraph($par_id, $filename)
3940 {
3941 $this->builddom();
3942
3943 $mydom = $this->dom;
3944
3945 $xpc = xpath_new_context($mydom);
3946
3947 //$path = "//PageContent[position () = $par_id]/Paragraph";
3948 //$path = "//Paragraph[$par_id]";
3949 $path = "/descendant::Paragraph[position() = $par_id]";
3950
3951 $res = xpath_eval($xpc, $path);
3952
3953 if (count($res->nodeset) != 1) {
3954 die("Should not happen");
3955 }
3956
3957 $context_node = $res->nodeset[0];
3958
3959 // get plain text
3960
3961 $childs = $context_node->child_nodes();
3962
3963 for ($j = 0; $j < count($childs); $j++) {
3964 $content .= $mydom->dump_node($childs[$j]);
3965 }
3966
3967 $content = str_replace("<br />", "\n", $content);
3968 $content = str_replace("<br/>", "\n", $content);
3969
3970 $plain_content = html_entity_decode($content);
3971
3972 ilUtil::deliverData($plain_content, $filename);
3973 /*
3974 $file_type = "application/octet-stream";
3975 header("Content-type: ".$file_type);
3976 header("Content-disposition: attachment; filename=\"$filename\"");
3977 echo $plain_content;*/
3978 exit();
3979 }
3980
3984 // @todo: deprecated?
3985 public function getFO()
3986 {
3987 $xml = $this->getXMLFromDom(false, true, true);
3988 $xsl = file_get_contents("./Services/COPage/xsl/page_fo.xsl");
3989 $args = array( '/_xml' => $xml, '/_xsl' => $xsl );
3990 $xh = xslt_create();
3991
3992 $params = array();
3993
3994
3995 $fo = xslt_process($xh, "arg:/_xml", "arg:/_xsl", null, $args, $params);
3996 var_dump($fo);
3997 // do some replacements
3998 $fo = str_replace("\n", "", $fo);
3999 $fo = str_replace("<br/>", "<br>", $fo);
4000 $fo = str_replace("<br>", "\n", $fo);
4001
4002 xslt_free($xh);
4003
4004 //
4005 $fo = substr($fo, strpos($fo, ">") + 1);
4006 //echo "<br><b>fo:</b><br>".htmlentities($fo); flush();
4007 return $fo;
4008 }
4009
4010 public function registerOfflineHandler($handler)
4011 {
4012 $this->offline_handler = $handler;
4013 }
4014
4021 public function getOfflineHandler()
4022 {
4024 }
4025
4026
4030 public static function _lookupContainsDeactivatedElements($a_id, $a_parent_type, $a_lang = "-")
4031 {
4032 global $DIC;
4033
4034 $db = $DIC->database();
4035
4036 if ($a_lang == "") {
4037 $a_lang = "-";
4038 }
4039
4040 $query = "SELECT * FROM page_object WHERE page_id = " .
4041 $db->quote($a_id, "integer") . " AND " .
4042 " parent_type = " . $db->quote($a_parent_type, "text") . " AND " .
4043 " lang = " . $db->quote($a_lang, "text") . " AND " .
4044 " inactive_elements = " . $db->quote(1, "integer");
4045 $obj_set = $db->query($query);
4046
4047 if ($obj_rec = $obj_set->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
4048 return true;
4049 }
4050
4051 return false;
4052 }
4053
4061 {
4062 if (strpos($a_content, " Enabled=\"False\"")) {
4063 return true;
4064 }
4065 return false;
4066 }
4067
4071 public function getHistoryEntries()
4072 {
4073 $db = $this->db;
4074
4075 $h_query = "SELECT * FROM page_history " .
4076 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4077 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4078 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4079 " ORDER BY hdate DESC";
4080
4081 $hset = $db->query($h_query);
4082 $hentries = array();
4083
4084 while ($hrec = $db->fetchAssoc($hset)) {
4085 $hrec["sortkey"] = (int) $hrec["nr"];
4086 $hrec["user"] = (int) $hrec["user_id"];
4087 $hentries[] = $hrec;
4088 }
4089 //var_dump($hentries);
4090 return $hentries;
4091 }
4092
4096 public function getHistoryEntry($a_old_nr)
4097 {
4098 $db = $this->db;
4099
4100 $res = $db->queryF(
4101 "SELECT * FROM page_history " .
4102 " WHERE page_id = %s " .
4103 " AND parent_type = %s " .
4104 " AND nr = %s" .
4105 " AND lang = %s",
4106 array("integer", "text", "integer", "text"),
4107 array($this->getId(), $this->getParentType(), $a_old_nr, $this->getLanguage())
4108 );
4109 if ($hrec = $db->fetchAssoc($res)) {
4110 return $hrec;
4111 }
4112
4113 return false;
4114 }
4115
4116
4123 public function getHistoryInfo($a_nr)
4124 {
4125 $db = $this->db;
4126
4127 // determine previous entry
4128 $and_nr = ($a_nr > 0)
4129 ? " AND nr < " . $db->quote((int) $a_nr, "integer")
4130 : "";
4131 $res = $db->query("SELECT MAX(nr) mnr FROM page_history " .
4132 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4133 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4134 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4135 $and_nr);
4136 $row = $db->fetchAssoc($res);
4137 if ($row["mnr"] > 0) {
4138 $res = $db->query("SELECT * FROM page_history " .
4139 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4140 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4141 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4142 " AND nr = " . $db->quote((int) $row["mnr"], "integer"));
4143 $row = $db->fetchAssoc($res);
4144 $ret["previous"] = $row;
4145 }
4146
4147 // determine next entry
4148 $res = $db->query("SELECT MIN(nr) mnr FROM page_history " .
4149 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4150 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4151 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4152 " AND nr > " . $db->quote((int) $a_nr, "integer"));
4153 $row = $db->fetchAssoc($res);
4154 if ($row["mnr"] > 0) {
4155 $res = $db->query("SELECT * FROM page_history " .
4156 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4157 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4158 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4159 " AND nr = " . $db->quote((int) $row["mnr"], "integer"));
4160 $row = $db->fetchAssoc($res);
4161 $ret["next"] = $row;
4162 }
4163
4164 // current
4165 if ($a_nr > 0) {
4166 $res = $db->query("SELECT * FROM page_history " .
4167 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4168 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4169 " AND lang = " . $db->quote($this->getLanguage(), "text") .
4170 " AND nr = " . $db->quote((int) $a_nr, "integer"));
4171 $row = $db->fetchAssoc($res);
4172 } else {
4173 $res = $db->query("SELECT page_id, last_change hdate, parent_type, parent_id, last_change_user user_id, content, lang FROM page_object " .
4174 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4175 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4176 " AND lang = " . $db->quote($this->getLanguage(), "text"));
4177 $row = $db->fetchAssoc($res);
4178 }
4179 $ret["current"] = $row;
4180
4181 return $ret;
4182 }
4183
4184 public function addChangeDivClasses($a_hashes)
4185 {
4186 $xpc = xpath_new_context($this->dom);
4187 $path = "/*[1]";
4188 $res = xpath_eval($xpc, $path);
4189 $rnode = $res->nodeset[0];
4190
4191 //echo "A";
4192 foreach ($a_hashes as $pc_id => $h) {
4193 //echo "B";
4194 if ($h["change"] != "") {
4195 $dc_node = $this->dom->create_element("DivClass");
4196 $dc_node->set_attribute("HierId", $h["hier_id"]);
4197 $dc_node->set_attribute("Class", "ilEdit" . $h["change"]);
4198 $dc_node = $rnode->append_child($dc_node);
4199 }
4200 }
4201 //echo "<br><br><br><br><br><br>".htmlentities($this->getXMLFromDom());
4202 }
4203
4210 public function compareVersion($a_left, $a_right)
4211 {
4212 // get page objects
4213 include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4214 $l_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_left);
4215 $r_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_right);
4216
4217 $l_hashes = $l_page->getPageContentsHashes();
4218 $r_hashes = $r_page->getPageContentsHashes();
4219 // determine all deleted and changed page elements
4220 foreach ($l_hashes as $pc_id => $h) {
4221 if (!isset($r_hashes[$pc_id])) {
4222 $l_hashes[$pc_id]["change"] = "Deleted";
4223 } else {
4224 if ($l_hashes[$pc_id]["hash"] != $r_hashes[$pc_id]["hash"]) {
4225 $l_hashes[$pc_id]["change"] = "Modified";
4226 $r_hashes[$pc_id]["change"] = "Modified";
4227
4228 include_once("./Services/COPage/mediawikidiff/class.WordLevelDiff.php");
4229 // if modified element is a paragraph, highlight changes
4230 if ($l_hashes[$pc_id]["content"] != "" &&
4231 $r_hashes[$pc_id]["content"] != "") {
4232 $new_left = str_replace("\n", "<br />", $l_hashes[$pc_id]["content"]);
4233 $new_right = str_replace("\n", "<br />", $r_hashes[$pc_id]["content"]);
4234 $wldiff = new WordLevelDiff(
4235 array($new_left),
4236 array($new_right)
4237 );
4238 $new_left = $wldiff->orig();
4239 $new_right = $wldiff->closing();
4240 $l_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_left[0]);
4241 $r_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_right[0]);
4242 }
4243 }
4244 }
4245 }
4246
4247 // determine all new paragraphs
4248 foreach ($r_hashes as $pc_id => $h) {
4249 if (!isset($l_hashes[$pc_id])) {
4250 $r_hashes[$pc_id]["change"] = "New";
4251 }
4252 }
4253 $l_page->addChangeDivClasses($l_hashes);
4254 $r_page->addChangeDivClasses($r_hashes);
4255
4256 return array("l_page" => $l_page, "r_page" => $r_page,
4257 "l_changes" => $l_hashes, "r_changes" => $r_hashes);
4258 }
4259
4263 public function increaseViewCnt()
4264 {
4265 $db = $this->db;
4266
4267 $db->manipulate("UPDATE page_object " .
4268 " SET view_cnt = view_cnt + 1 " .
4269 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4270 " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4271 " AND lang = " . $db->quote($this->getLanguage(), "text"));
4272 }
4273
4281 public static function getRecentChanges($a_parent_type, $a_parent_id, $a_period = 30, $a_lang = "")
4282 {
4283 global $DIC;
4284
4285 $db = $DIC->database();
4286
4287 $and_lang = "";
4288 if ($a_lang != "") {
4289 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4290 }
4291
4292 $page_changes = array();
4293 $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4294 $q = "SELECT * FROM page_object " .
4295 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4296 " AND parent_type = " . $db->quote($a_parent_type, "text") .
4297 " AND last_change >= " . $db->quote($limit_ts, "timestamp") . $and_lang;
4298 // " AND (TO_DAYS(now()) - TO_DAYS(last_change)) <= ".((int)$a_period);
4299 $set = $db->query($q);
4300 while ($page = $db->fetchAssoc($set)) {
4301 $page_changes[] = array(
4302 "date" => $page["last_change"],
4303 "id" => $page["page_id"],
4304 "lang" => $page["lang"],
4305 "type" => "page",
4306 "user" => $page["last_change_user"]);
4307 }
4308
4309 $and_str = "";
4310 if ($a_period > 0) {
4311 $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4312 $and_str = " AND hdate >= " . $db->quote($limit_ts, "timestamp") . " ";
4313 }
4314
4315 $q = "SELECT * FROM page_history " .
4316 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4317 " AND parent_type = " . $db->quote($a_parent_type, "text") .
4318 $and_str . $and_lang;
4319 $set = $db->query($q);
4320 while ($page = $db->fetchAssoc($set)) {
4321 $page_changes[] = array(
4322 "date" => $page["hdate"],
4323 "id" => $page["page_id"],
4324 "lang" => $page["lang"],
4325 "type" => "hist",
4326 "nr" => $page["nr"],
4327 "user" => $page["user_id"]);
4328 }
4329
4330 $page_changes = ilUtil::sortArray($page_changes, "date", "desc");
4331
4332 return $page_changes;
4333 }
4334
4343 public static function getAllPages($a_parent_type, $a_parent_id, $a_lang = "-")
4344 {
4345 global $DIC;
4346
4347 $db = $DIC->database();
4348
4349 $and_lang = "";
4350 if ($a_lang != "") {
4351 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4352 }
4353
4354 $q = "SELECT * FROM page_object " .
4355 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4356 " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang;
4357 $set = $db->query($q);
4358 $pages = array();
4359 while ($page = $db->fetchAssoc($set)) {
4360 $key_add = ($a_lang == "")
4361 ? ":" . $page["lang"]
4362 : "";
4363 $pages[$page["page_id"] . $key_add] = array(
4364 "date" => $page["last_change"],
4365 "id" => $page["page_id"],
4366 "lang" => $page["lang"],
4367 "user" => $page["last_change_user"]);
4368 }
4369
4370 return $pages;
4371 }
4372
4379 public static function getNewPages($a_parent_type, $a_parent_id, $a_lang = "-")
4380 {
4381 global $DIC;
4382
4383 $db = $DIC->database();
4384
4385 $and_lang = "";
4386 if ($a_lang != "") {
4387 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4388 }
4389
4390 $pages = array();
4391
4392 $q = "SELECT * FROM page_object " .
4393 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4394 " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang .
4395 " ORDER BY created DESC";
4396 $set = $db->query($q);
4397 while ($page = $db->fetchAssoc($set)) {
4398 if ($page["created"] != "") {
4399 $pages[] = array(
4400 "created" => $page["created"],
4401 "id" => $page["page_id"],
4402 "lang" => $page["lang"],
4403 "user" => $page["create_user"],
4404 );
4405 }
4406 }
4407
4408 return $pages;
4409 }
4410
4417 public static function getParentObjectContributors($a_parent_type, $a_parent_id, $a_lang = "-")
4418 {
4419 global $DIC;
4420
4421 $db = $DIC->database();
4422
4423 $and_lang = "";
4424 if ($a_lang != "") {
4425 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4426 }
4427
4428 $contributors = array();
4429 $set = $db->queryF(
4430 "SELECT last_change_user, lang, page_id FROM page_object " .
4431 " WHERE parent_id = %s AND parent_type = %s " .
4432 " AND last_change_user != %s" . $and_lang,
4433 array("integer", "text", "integer"),
4434 array($a_parent_id, $a_parent_type, 0)
4435 );
4436
4437 while ($page = $db->fetchAssoc($set)) {
4438 if ($a_lang == "") {
4439 $contributors[$page["last_change_user"]][$page["page_id"]][$page["lang"]] = 1;
4440 } else {
4441 $contributors[$page["last_change_user"]][$page["page_id"]] = 1;
4442 }
4443 }
4444
4445 $set = $db->queryF(
4446 "SELECT count(*) as cnt, lang, page_id, user_id FROM page_history " .
4447 " WHERE parent_id = %s AND parent_type = %s AND user_id != %s " . $and_lang .
4448 " GROUP BY page_id, user_id, lang ",
4449 array("integer", "text", "integer"),
4450 array($a_parent_id, $a_parent_type, 0)
4451 );
4452 while ($hpage = $db->fetchAssoc($set)) {
4453 if ($a_lang == "") {
4454 $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] =
4455 $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] + $hpage["cnt"];
4456 } else {
4457 $contributors[$hpage["user_id"]][$hpage["page_id"]] =
4458 $contributors[$hpage["user_id"]][$hpage["page_id"]] + $hpage["cnt"];
4459 }
4460 }
4461
4462 $c = array();
4463 foreach ($contributors as $k => $co) {
4464 if (ilObject::_lookupType($k) == "usr") {
4466 $c[] = array("user_id" => $k, "pages" => $co,
4467 "lastname" => $name["lastname"], "firstname" => $name["firstname"]);
4468 }
4469 }
4470
4471 return $c;
4472 }
4473
4480 public static function getPageContributors($a_parent_type, $a_page_id, $a_lang = "-")
4481 {
4482 global $DIC;
4483
4484 $db = $DIC->database();
4485
4486 $and_lang = "";
4487 if ($a_lang != "") {
4488 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4489 }
4490
4491 $contributors = array();
4492 $set = $db->queryF(
4493 "SELECT last_change_user, lang FROM page_object " .
4494 " WHERE page_id = %s AND parent_type = %s " .
4495 " AND last_change_user != %s" . $and_lang,
4496 array("integer", "text", "integer"),
4497 array($a_page_id, $a_parent_type, 0)
4498 );
4499
4500 while ($page = $db->fetchAssoc($set)) {
4501 if ($a_lang == "") {
4502 $contributors[$page["last_change_user"]][$page["lang"]] = 1;
4503 } else {
4504 $contributors[$page["last_change_user"]] = 1;
4505 }
4506 }
4507
4508 $set = $db->queryF(
4509 "SELECT count(*) as cnt, lang, page_id, user_id FROM page_history " .
4510 " WHERE page_id = %s AND parent_type = %s AND user_id != %s " . $and_lang .
4511 " GROUP BY user_id, page_id, lang ",
4512 array("integer", "text", "integer"),
4513 array($a_page_id, $a_parent_type, 0)
4514 );
4515 while ($hpage = $db->fetchAssoc($set)) {
4516 if ($a_lang == "") {
4517 $contributors[$hpage["user_id"]][$page["lang"]] =
4518 $contributors[$hpage["user_id"]][$page["lang"]] + $hpage["cnt"];
4519 } else {
4520 $contributors[$hpage["user_id"]] =
4521 $contributors[$hpage["user_id"]] + $hpage["cnt"];
4522 }
4523 }
4524
4525 $c = array();
4526 foreach ($contributors as $k => $co) {
4527 include_once "Services/User/classes/class.ilObjUser.php";
4529 $c[] = array("user_id" => $k, "pages" => $co,
4530 "lastname" => $name["lastname"], "firstname" => $name["firstname"]);
4531 }
4532
4533 return $c;
4534 }
4535
4539 public function writeRenderedContent($a_content, $a_md5)
4540 {
4541 global $DIC;
4542
4543 $db = $DIC->database();
4544
4545 $db->update("page_object", array(
4546 "rendered_content" => array("clob", $a_content),
4547 "render_md5" => array("text", $a_md5),
4548 "rendered_time" => array("timestamp", ilUtil::now())
4549 ), array(
4550 "page_id" => array("integer", $this->getId()),
4551 "lang" => array("text", $this->getLanguage()),
4552 "parent_type" => array("text", $this->getParentType())
4553 ));
4554 }
4555
4563 public static function getPagesWithLinks($a_parent_type, $a_parent_id, $a_lang = "-")
4564 {
4565 global $DIC;
4566
4567 $db = $DIC->database();
4568
4569 $and_lang = "";
4570 if ($a_lang != "") {
4571 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4572 }
4573
4574 $q = "SELECT * FROM page_object " .
4575 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4576 " AND parent_type = " . $db->quote($a_parent_type, "text") .
4577 " AND int_links = " . $db->quote(1, "integer") . $and_lang;
4578 $set = $db->query($q);
4579 $pages = array();
4580 while ($page = $db->fetchAssoc($set)) {
4581 $key_add = ($a_lang == "")
4582 ? ":" . $page["lang"]
4583 : "";
4584 $pages[$page["page_id"] . $key_add] = array(
4585 "date" => $page["last_change"],
4586 "id" => $page["page_id"],
4587 "lang" => $page["lang"],
4588 "user" => $page["last_change_user"]);
4589 }
4590
4591 return $pages;
4592 }
4593
4601 {
4602 if (strpos($a_content, "IntLink")) {
4603 return true;
4604 }
4605 return false;
4606 }
4607
4612 {
4613 }
4614
4620 // @todo begin: generalize
4621 public function saveInitialOpenedContent($a_type, $a_id, $a_target)
4622 {
4623 $this->buildDom();
4624
4625 $link_type = "";
4626
4627 switch ($a_type) {
4628 case "media":
4629 $link_type = "MediaObject";
4630 $a_id = "il__mob_" . $a_id;
4631 break;
4632
4633 case "page":
4634 $link_type = "PageObject";
4635 $a_id = "il__pg_" . $a_id;
4636 break;
4637
4638 case "term":
4639 $link_type = "GlossaryItem";
4640 $a_id = "il__git_" . $a_id;
4641 $a_target = "Glossary";
4642 break;
4643 }
4644
4645 // if type or id missing -> delete InitOpenedContent, if existing
4646 if ($link_type == "" || $a_id == "") {
4647 $xpc = xpath_new_context($this->dom);
4648 $path = "//PageObject/InitOpenedContent";
4649 $res = xpath_eval($xpc, $path);
4650 if (count($res->nodeset) > 0) {
4651 $res->nodeset[0]->unlink_node($res->nodeset[0]);
4652 }
4653 } else {
4654 $xpc = xpath_new_context($this->dom);
4655 $path = "//PageObject/InitOpenedContent";
4656 $res = xpath_eval($xpc, $path);
4657 if (count($res->nodeset) > 0) {
4658 $init_node = $res->nodeset[0];
4659 $childs = $init_node->child_nodes();
4660 for ($i = 0; $i < count($childs); $i++) {
4661 if ($childs[$i]->node_name() == "IntLink") {
4662 $il_node = $childs[$i];
4663 }
4664 }
4665 } else {
4666 $path = "//PageObject";
4667 $res = xpath_eval($xpc, $path);
4668 $page_node = $res->nodeset[0];
4669 $init_node = $this->dom->create_element("InitOpenedContent");
4670 $init_node = $page_node->append_child($init_node);
4671 $il_node = $this->dom->create_element("IntLink");
4672 $il_node = $init_node->append_child($il_node);
4673 }
4674 $il_node->set_attribute("Target", $a_id);
4675 $il_node->set_attribute("Type", $link_type);
4676 $il_node->set_attribute("TargetFrame", $a_target);
4677 }
4678
4679 $this->update();
4680 }
4681
4682
4688 public function getInitialOpenedContent()
4689 {
4690 $this->buildDom();
4691
4692 $xpc = xpath_new_context($this->dom);
4693 $path = "//PageObject/InitOpenedContent";
4694 $res = xpath_eval($xpc, $path);
4695 $il_node = null;
4696 if (count($res->nodeset) > 0) {
4697 $init_node = $res->nodeset[0];
4698 $childs = $init_node->child_nodes();
4699 for ($i = 0; $i < count($childs); $i++) {
4700 if ($childs[$i]->node_name() == "IntLink") {
4701 $il_node = $childs[$i];
4702 }
4703 }
4704 }
4705 if (!is_null($il_node)) {
4706 $id = $il_node->get_attribute("Target");
4707 $link_type = $il_node->get_attribute("Type");
4708 $target = $il_node->get_attribute("TargetFrame");
4709
4710 switch ($link_type) {
4711 case "MediaObject":
4712 $type = "media";
4713 break;
4714
4715 case "PageObject":
4716 $type = "page";
4717 break;
4718
4719 case "GlossaryItem":
4720 $type = "term";
4721 break;
4722 }
4723 include_once("./Services/Link/classes/class.ilInternalLink.php");
4725 return array("id" => $id, "type" => $type, "target" => $target);
4726 }
4727
4728 return array();
4729 }
4730 // @todo end
4731
4742 public function beforePageContentUpdate($a_page_content)
4743 {
4744 }
4745
4753 public function copy($a_id, $a_parent_type = "", $a_parent_id = 0, $a_clone_mobs = false)
4754 {
4755 if ($a_parent_type == "") {
4756 $a_parent_type = $this->getParentType();
4757 if ($a_parent_id == 0) {
4758 $a_parent_id = $this->getParentId();
4759 }
4760 }
4761
4762 include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4763 foreach (self::lookupTranslations($this->getParentType(), $this->getId()) as $l) {
4764 $existed = false;
4765 $orig_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), 0, $l);
4766 if (ilPageObject::_exists($a_parent_type, $a_id, $l)) {
4767 $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, $a_id, 0, $l);
4768 $existed = true;
4769 } else {
4770 $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, 0, 0, $l);
4771 $new_page_object->setParentId($a_parent_id);
4772 $new_page_object->setId($a_id);
4773 }
4774 $new_page_object->setXMLContent($orig_page->copyXMLContent($a_clone_mobs));
4775 $new_page_object->setActive($orig_page->getActive());
4776 $new_page_object->setActivationStart($orig_page->getActivationStart());
4777 $new_page_object->setActivationEnd($orig_page->getActivationEnd());
4778 if ($existed) {
4779 $new_page_object->buildDom();
4780 $new_page_object->update();
4781 } else {
4782 $new_page_object->create();
4783 }
4784 }
4785 }
4786
4794 public static function lookupTranslations($a_parent_type, $a_id)
4795 {
4796 global $DIC;
4797
4798 $db = $DIC->database();
4799
4800 $set = $db->query(
4801 "SELECT lang FROM page_object " .
4802 " WHERE page_id = " . $db->quote($a_id, "integer") .
4803 " AND parent_type = " . $db->quote($a_parent_type, "text")
4804 );
4805 $langs = array();
4806 while ($rec = $db->fetchAssoc($set)) {
4807 $langs[] = $rec["lang"];
4808 }
4809 return $langs;
4810 }
4811
4812
4818 public function copyPageToTranslation($a_target_lang)
4819 {
4820 $transl_page = ilPageObjectFactory::getInstance(
4821 $this->getParentType(),
4822 0,
4823 0,
4824 $a_target_lang
4825 );
4826 $transl_page->setId($this->getId());
4827 $transl_page->setParentId($this->getParentId());
4828 $transl_page->setXMLContent($this->copyXMLContent());
4829 $transl_page->setActive($this->getActive());
4830 $transl_page->setActivationStart($this->getActivationStart());
4831 $transl_page->setActivationEnd($this->getActivationEnd());
4832 $transl_page->create();
4833 }
4834
4838
4842 public function getEditLock()
4843 {
4844 $db = $this->db;
4846
4847 $min = (int) $this->getEffectiveEditLockTime();
4848 if ($min > 0) {
4849 // try to set the lock for the user
4850 $ts = time();
4851 $db->manipulate(
4852 "UPDATE page_object SET " .
4853 " edit_lock_user = " . $db->quote($user->getId(), "integer") . "," .
4854 " edit_lock_ts = " . $db->quote($ts, "integer") .
4855 " WHERE (edit_lock_user = " . $db->quote($user->getId(), "integer") . " OR " .
4856 " edit_lock_ts < " . $db->quote(time() - ($min * 60), "integer") . ") " .
4857 " AND page_id = " . $db->quote($this->getId(), "integer") .
4858 " AND parent_type = " . $db->quote($this->getParentType(), "text")
4859 );
4860
4861 $set = $db->query(
4862 "SELECT edit_lock_user FROM page_object " .
4863 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4864 " AND parent_type = " . $db->quote($this->getParentType(), "text")
4865 );
4866 $rec = $db->fetchAssoc($set);
4867 if ($rec["edit_lock_user"] != $user->getId()) {
4868 return false;
4869 }
4870 }
4871
4872 return true;
4873 }
4874
4878 public function releasePageLock()
4879 {
4880 $db = $this->db;
4882 $aset = new ilSetting("adve");
4883
4884 $min = (int) $aset->get("block_mode_minutes") ;
4885 if ($min > 0) {
4886 // try to set the lock for the user
4887 $ts = time();
4888 $db->manipulate(
4889 "UPDATE page_object SET " .
4890 " edit_lock_user = " . $db->quote($user->getId(), "integer") . "," .
4891 " edit_lock_ts = 0" .
4892 " WHERE edit_lock_user = " . $db->quote($user->getId(), "integer") .
4893 " AND page_id = " . $db->quote($this->getId(), "integer") .
4894 " AND parent_type = " . $db->quote($this->getParentType(), "text")
4895 );
4896
4897 $set = $db->query(
4898 "SELECT edit_lock_user FROM page_object " .
4899 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4900 " AND parent_type = " . $db->quote($this->getParentType(), "text")
4901 );
4902 $rec = $db->fetchAssoc($set);
4903 if ($rec["edit_lock_user"] != $user->getId()) {
4904 return false;
4905 }
4906 }
4907
4908 return true;
4909 }
4910
4916 public function getEditLockInfo()
4917 {
4918 $db = $this->db;
4919
4920 $aset = new ilSetting("adve");
4921 $min = (int) $aset->get("block_mode_minutes");
4922
4923 $set = $db->query(
4924 "SELECT edit_lock_user, edit_lock_ts FROM page_object " .
4925 " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4926 " AND parent_type = " . $db->quote($this->getParentType(), "text")
4927 );
4928 $rec = $db->fetchAssoc($set);
4929 $rec["edit_lock_until"] = $rec["edit_lock_ts"] + $min * 60;
4930
4931 return $rec;
4932 }
4933
4946 public static function truncateHTML($a_text, $a_length = 100, $a_ending = '...', $a_exact = false, $a_consider_html = true)
4947 {
4948 include_once "Services/Utilities/classes/class.ilStr.php";
4949
4950 if ($a_consider_html) {
4951 // if the plain text is shorter than the maximum length, return the whole text
4952 if (strlen(preg_replace('/<.*?>/', '', $a_text)) <= $a_length) {
4953 return $a_text;
4954 }
4955
4956 // splits all html-tags to scanable lines
4957 $total_length = strlen($a_ending);
4958 $open_tags = array();
4959 $truncate = '';
4960 preg_match_all('/(<.+?>)?([^<>]*)/s', $a_text, $lines, PREG_SET_ORDER);
4961 foreach ($lines as $line_matchings) {
4962 // if there is any html-tag in this line, handle it and add it (uncounted) to the output
4963 if (!empty($line_matchings[1])) {
4964 // if it's an "empty element" with or without xhtml-conform closing slash
4965 if (preg_match('/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is', $line_matchings[1])) {
4966 // do nothing
4967 }
4968 // if tag is a closing tag
4969 elseif (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line_matchings[1], $tag_matchings)) {
4970 // delete tag from $open_tags list
4971 $pos = array_search($tag_matchings[1], $open_tags);
4972 if ($pos !== false) {
4973 unset($open_tags[$pos]);
4974 }
4975 }
4976 // if tag is an opening tag
4977 elseif (preg_match('/^<\s*([^\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings)) {
4978 // add tag to the beginning of $open_tags list
4979 array_unshift($open_tags, strtolower($tag_matchings[1]));
4980 }
4981 // add html-tag to $truncate'd text
4982 $truncate .= $line_matchings[1];
4983 }
4984
4985 // calculate the length of the plain text part of the line; handle entities as one character
4986 $content_length = strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
4987 if ($total_length + $content_length > $a_length) {
4988 // the number of characters which are left
4989 $left = $a_length - $total_length;
4990 $entities_length = 0;
4991 // search for html entities
4992 if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', $line_matchings[2], $entities, PREG_OFFSET_CAPTURE)) {
4993 // calculate the real length of all entities in the legal range
4994 foreach ($entities[0] as $entity) {
4995 if ($entity[1] + 1 - $entities_length <= $left) {
4996 $left--;
4997 $entities_length += strlen($entity[0]);
4998 } else {
4999 // no more characters left
5000 break;
5001 }
5002 }
5003 }
5004
5005 // $truncate .= substr($line_matchings[2], 0, $left+$entities_length);
5006 $truncate .= ilStr::shortenText($line_matchings[2], 0, $left + $entities_length);
5007
5008 // maximum lenght is reached, so get off the loop
5009 break;
5010 } else {
5011 $truncate .= $line_matchings[2];
5012 $total_length += $content_length;
5013 }
5014
5015 // if the maximum length is reached, get off the loop
5016 if ($total_length >= $a_length) {
5017 break;
5018 }
5019 }
5020 } else {
5021 if (strlen($a_text) <= $a_length) {
5022 return $a_text;
5023 } else {
5024 // $truncate = substr($a_text, 0, $a_length - strlen($a_ending));
5025 $truncate = ilStr::shortenText($a_text, 0, $a_length - strlen($a_ending));
5026 }
5027 }
5028
5029 // THIS IS BUGGY AS IT MIGHT BREAK AN OPEN TAG AT THE END
5030 if (!sizeof($open_tags)) {
5031 // if the words shouldn't be cut in the middle...
5032 if (!$a_exact) {
5033 // ...search the last occurance of a space...
5034 $spacepos = strrpos($truncate, ' ');
5035 if ($spacepos !== false) {
5036 // ...and cut the text in this position
5037 // $truncate = substr($truncate, 0, $spacepos);
5038 $truncate = ilStr::shortenText($truncate, 0, $spacepos);
5039 }
5040 }
5041 }
5042
5043 // add the defined ending to the text
5044 $truncate .= $a_ending;
5045
5046 if ($a_consider_html) {
5047 // close all unclosed html-tags
5048 foreach ($open_tags as $tag) {
5049 $truncate .= '</' . $tag . '>';
5050 }
5051 }
5052
5053 return $truncate;
5054 }
5055
5061 public function getContentTemplates()
5062 {
5063 return array();
5064 }
5065
5073 public static function getLastChangeByParent($a_parent_type, $a_parent_id, $a_lang = "")
5074 {
5075 global $DIC;
5076
5077 $db = $DIC->database();
5078
5079 $and_lang = "";
5080 if ($a_lang != "") {
5081 $and_lang = " AND lang = " . $db->quote($a_lang, "text");
5082 }
5083
5084 $db->setLimit(1);
5085 $q = "SELECT last_change FROM page_object " .
5086 " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
5087 " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang .
5088 " ORDER BY last_change DESC";
5089
5090 $set = $db->query($q);
5091 $rec = $db->fetchAssoc($set);
5092
5093 return $rec["last_change"];
5094 }
5095
5097 {
5098 if ($this->getPageConfig()->getEditLockSupport() == false) {
5099 return 0;
5100 }
5101
5102 $aset = new ilSetting("adve");
5103 $min = (int) $aset->get("block_mode_minutes") ;
5104
5105 return $min;
5106 }
5107
5113 public function getAllFileObjIds()
5114 {
5115 $file_obj_ids = array();
5116
5117 // insert inst id file item identifier entries
5118 $xpc = xpath_new_context($this->dom);
5119 $path = "//FileItem/Identifier";
5120 $res = xpath_eval($xpc, $path);
5121 for ($i = 0; $i < count($res->nodeset); $i++) {
5122 $file_obj_ids[] = $res->nodeset[$i]->get_attribute("Entry");
5123 }
5124 unset($xpc);
5125 return $file_obj_ids;
5126 }
5127
5132 public function resolveResources($ref_mapping)
5133 {
5134 include_once("./Services/COPage/classes/class.ilPCResources.php");
5135 ilPCResources::resolveResources($this, $ref_mapping);
5136 }
5137
5142 public function getRepoObjId()
5143 {
5144 return $this->getParentId();
5145 }
5146
5147}
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)
Lookups the file size of the file in bytes.
static _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_usage_lang="-")
get all files of an object
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 ilPCMediaObject.
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 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.
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.
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).
static truncateHTML($a_text, $a_length=100, $a_ending='...', $a_exact=false, $a_consider_html=true)
Truncate (html) string.
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.
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.
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.
addUpdateListener(&$a_object, $a_method, $a_parameters="")
insertInstIntoIDs($a_inst, $a_res_ref_to_obj_id=true)
inserts installation id into ids (e.g.
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
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.
insertContent(&$a_cont_obj, $a_pos, $a_mode=IL_INSERT_AFTER, $a_pcid="")
insert a content node before/after a sibling or as first child of a parent
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
validateDom()
Validate the page content agains page DTD.
cutContents($a_hids)
Copy contents to clipboard and cut them from the page.
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...
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.
getFO()
get fo page content
getXMLFromDom( $a_incl_head=false, $a_append_mobs=false, $a_append_bib=false, $a_append_str="", $a_omit_pageobject_tag=false)
get xml content of page from dom (use this, if any changes are made to the document)
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
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.
writeRenderedContent($a_content, $a_md5)
Write rendered content.
getLanguageVariablesXML()
Get language variables as XML.
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).
static _writeActive($a_id, $a_parent_type, $a_active, $a_reset_scheduled_activation=true, $a_lang="-")
write activation status
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.
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
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.
$target_arr
Definition: goto.php:47
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
$mobs
$errors
$a_content
Definition: workflow.php:93
$a_type
Definition: workflow.php:92
$DIC
Definition: xapitoken.php:46