ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 
4 define("IL_INSERT_BEFORE", 0);
5 define("IL_INSERT_AFTER", 1);
6 define("IL_INSERT_CHILD", 2);
7 
8 define("IL_CHAPTER_TITLE", "st_title");
9 define("IL_PAGE_TITLE", "pg_title");
10 define("IL_NO_HEADER", "none");
11 
15 /*
16 
17  - move dom related code to PageDom class/interface
18  - move ilDB dependency to ar object
19  - move internal links related code to extra class
20  - make factory available through DIC, opt allow decentralized factory parts
21  - PC types
22  -- internal links used/implemented?
23  -- styles used/implemented?
24  - application classes need
25  -- page object
26  --- page object should return php5 domdoc (getDom() vs getDomDoc()?)
27  esp. plugins should use this
28  -- remove content element hook, if content is not allowed
29  - PC types could move to components (e.g. blog, login)
30  - How to modularize xsl?
31  -- read from db?
32  -- xml entries say that xslt code is used -> read file and include in
33  main xslt file
34 
35 */
36 
48 abstract class ilPageObject
49 {
53  protected $obj_definition;
54 
55  public static $exists = array();
56 
60  protected $db;
61 
65  protected $user;
66 
70  protected $lng;
71 
75  protected $tree;
76 
80  protected $id;
81  public $dom;
82  public $xml;
83  public $encoding;
84  public $node;
85  public $cur_dtd = "ilias_pg_5_4.dtd";
88  public $parent_type;
89  public $parent_id;
93  public $dom_builded;
95 
99  protected $language = "-";
100 
104  protected static $activation_data = array();
105 
109  protected $import_mode = false;
110 
114  protected $log;
115 
119  protected $page_record = array();
120 
124  protected $active = false;
125 
129  protected $page_config;
130 
135  final public function __construct($a_id = 0, $a_old_nr = 0, $a_lang = "-")
136  {
137  global $DIC;
138  $this->obj_definition = $DIC["objDefinition"];
139  $this->db = $DIC->database();
140  $this->user = $DIC->user();
141  $this->lng = $DIC->language();
142  $this->tree = $DIC->repositoryTree();
143  $this->log = ilLoggerFactory::getLogger('copg');
144 
145  $this->parent_type = $this->getParentType();
146  $this->id = $a_id;
147  $this->setLanguage($a_lang);
148 
149  $this->contains_int_link = false;
150  $this->needs_parsing = false;
151  $this->update_listeners = array();
152  $this->update_listener_cnt = 0;
153  $this->dom_builded = false;
154  $this->page_not_found = false;
155  $this->old_nr = $a_old_nr;
156  $this->encoding = "UTF-8";
157  $this->id_elements =
158  array("PageContent", "TableRow", "TableData", "ListItem", "FileItem",
159  "Section", "Tab", "ContentPopup", "GridCell");
160  $this->setActive(true);
161  $this->show_page_act_info = false;
162 
163  if ($a_id != 0) {
164  $this->read();
165  }
166 
167  $this->initPageConfig();
168 
169  $this->afterConstructor();
170  }
171 
175  public function afterConstructor()
176  {
177  }
178 
179 
185  abstract public function getParentType();
186 
187 
191  final public function initPageConfig()
192  {
193  include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
195  $this->setPageConfig($cfg);
196  }
197 
203  public function setLanguage($a_val)
204  {
205  $this->language = $a_val;
206  }
207 
213  public function getLanguage()
214  {
215  return $this->language;
216  }
217 
223  public function setPageConfig($a_val)
224  {
225  $this->page_config = $a_val;
226  }
227 
233  public function getPageConfig()
234  {
235  return $this->page_config;
236  }
237 
243  public function setRenderMd5($a_rendermd5)
244  {
245  $this->rendermd5 = $a_rendermd5;
246  }
247 
253  public function getRenderMd5()
254  {
255  return $this->rendermd5;
256  }
257 
263  public function setRenderedContent($a_renderedcontent)
264  {
265  $this->renderedcontent = $a_renderedcontent;
266  }
267 
273  public function getRenderedContent()
274  {
275  return $this->renderedcontent;
276  }
277 
283  public function setRenderedTime($a_renderedtime)
284  {
285  $this->renderedtime = $a_renderedtime;
286  }
287 
293  public function getRenderedTime()
294  {
295  return $this->renderedtime;
296  }
297 
303  public function setLastChange($a_lastchange)
304  {
305  $this->lastchange = $a_lastchange;
306  }
307 
313  public function getLastChange()
314  {
315  return $this->lastchange;
316  }
317 
323  public function setLastChangeUser($a_val)
324  {
325  $this->last_change_user = $a_val;
326  }
327 
333  public function getLastChangeUser()
334  {
335  return $this->last_change_user;
336  }
337 
343  public function setShowActivationInfo($a_val)
344  {
345  $this->show_page_act_info = $a_val;
346  }
347 
353  public function getShowActivationInfo()
354  {
355  return $this->show_page_act_info;
356  }
357 
361  public function read()
362  {
363  $this->setActive(true);
364  if ($this->old_nr == 0) {
365  $query = "SELECT * FROM page_object" .
366  " WHERE page_id = " . $this->db->quote($this->id, "integer") .
367  " AND parent_type=" . $this->db->quote($this->getParentType(), "text") .
368  " AND lang = " . $this->db->quote($this->getLanguage(), "text");
369  $pg_set = $this->db->query($query);
370  $this->page_record = $this->db->fetchAssoc($pg_set);
371  $this->setActive($this->page_record["active"]);
372  $this->setActivationStart($this->page_record["activation_start"]);
373  $this->setActivationEnd($this->page_record["activation_end"]);
374  $this->setShowActivationInfo($this->page_record["show_activation_info"]);
375  } else {
376  $query = "SELECT * FROM page_history" .
377  " WHERE page_id = " . $this->db->quote($this->id, "integer") .
378  " AND parent_type=" . $this->db->quote($this->getParentType(), "text") .
379  " AND nr = " . $this->db->quote((int) $this->old_nr, "integer") .
380  " AND lang = " . $this->db->quote($this->getLanguage(), "text");
381  $pg_set = $this->db->query($query);
382  $this->page_record = $this->db->fetchAssoc($pg_set);
383  }
384  if (!$this->page_record) {
385  include_once("./Services/COPage/exceptions/class.ilCOPageNotFoundException.php");
386  throw new ilCOPageNotFoundException("Error: Page " . $this->id . " is not in database" .
387  " (parent type " . $this->getParentType() . ", lang: " . $this->getLanguage() . ").");
388  }
389 
390  $this->xml = $this->page_record["content"];
391  $this->setParentId($this->page_record["parent_id"]);
392  $this->last_change_user = $this->page_record["last_change_user"];
393  $this->create_user = $this->page_record["create_user"];
394  $this->setRenderedContent($this->page_record["rendered_content"]);
395  $this->setRenderMd5($this->page_record["render_md5"]);
396  $this->setRenderedTime($this->page_record["rendered_time"]);
397  $this->setLastChange($this->page_record["last_change"]);
398  }
399 
407  public static function _exists($a_parent_type, $a_id, $a_lang = "", $a_no_cache = false)
408  {
409  global $DIC;
410 
411  $db = $DIC->database();
412 
413  if (!$a_no_cache && isset(self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang])) {
414  return self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang];
415  }
416 
417  $and_lang = "";
418  if ($a_lang != "") {
419  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
420  }
421 
422  $query = "SELECT page_id FROM page_object WHERE page_id = " . $db->quote($a_id, "integer") . " " .
423  "AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang;
424  $set = $db->query($query);
425  if ($row = $db->fetchAssoc($set)) {
426  self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang] = true;
427  return true;
428  } else {
429  self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang] = false;
430  return false;
431  }
432  }
433 
441  public static function _existsAndNotEmpty($a_parent_type, $a_id, $a_lang = "-")
442  {
443  include_once("./Services/COPage/classes/class.ilPageUtil.php");
444  return ilPageUtil::_existsAndNotEmpty($a_parent_type, $a_id, $a_lang);
445  }
446 
447  public function buildDom($a_force = false)
448  {
449  if ($this->dom_builded && !$a_force) {
450  return;
451  }
452 
453  //echo "\n<br>buildDomWith:".$this->getId().":xml:".$this->getXMLContent(true).":<br>";
454 
455  $options = 0;
456  //$options = DOMXML_LOAD_VALIDATING;
457  //$options = LIBXML_DTDLOAD;
458  //$options = LIBXML_NOXMLDECL;
459  //echo htmlentities($this->getXMLContent(true))."<br>";
460  $this->dom = @domxml_open_mem($this->getXMLContent(true), $options, $error);
461  //var_dump($error);
462  $xpc = xpath_new_context($this->dom);
463  $path = "//PageObject";
464  $res = xpath_eval($xpc, $path);
465  if (count($res->nodeset) == 1) {
466  // echo "h";
467  $this->node = $res->nodeset[0];
468  }
469  //echo htmlentities($this->dom->dump_node($this->node)); exit;
470 
471  if (empty($error)) {
472  $this->dom_builded = true;
473  return true;
474  } else {
475  return $error;
476  }
477  }
478 
479  public function freeDom()
480  {
481  //$this->dom->free();
482  unset($this->dom);
483  }
484 
488  public function getDom()
489  {
490  return $this->dom;
491  }
492 
499  public function getDomDoc()
500  {
501  if ($this->dom instanceof php4DOMDocument) {
502  return $this->dom->myDOMDocument;
503  }
504 
505  return $this->dom;
506  }
507 
508 
512  public function setId($a_id)
513  {
514  $this->id = $a_id;
515  }
516 
517  public function getId()
518  {
519  return $this->id;
520  }
521 
522  public function setParentId($a_id)
523  {
524  $this->parent_id = $a_id;
525  }
526 
527  public function getParentId()
528  {
529  return $this->parent_id;
530  }
531 
532  public function addUpdateListener(&$a_object, $a_method, $a_parameters = "")
533  {
535  $this->update_listeners[$cnt]["object"] = $a_object;
536  $this->update_listeners[$cnt]["method"] = $a_method;
537  $this->update_listeners[$cnt]["parameters"] = $a_parameters;
538  $this->update_listener_cnt++;
539  }
540 
541  public function callUpdateListeners()
542  {
543  for ($i = 0; $i < $this->update_listener_cnt; $i++) {
544  $object = $this->update_listeners[$i]["object"];
545  $method = $this->update_listeners[$i]["method"];
546  $parameters = $this->update_listeners[$i]["parameters"];
547  $object->$method($parameters);
548  }
549  }
550 
556  public function setActive($a_active)
557  {
558  $this->active = $a_active;
559  }
560 
566  public function getActive($a_check_scheduled_activation = false)
567  {
568  if ($a_check_scheduled_activation && !$this->active) {
569  include_once("./Services/Calendar/classes/class.ilDateTime.php");
572  $now = new ilDateTime(time(), IL_CAL_UNIX);
573  if (!ilDateTime::_before($now, $start) && !ilDateTime::_after($now, $end)) {
574  return true;
575  }
576  }
577  return $this->active;
578  }
579 
585  public static function preloadActivationDataByParentId($a_parent_id)
586  {
587  global $DIC;
588 
589  $db = $DIC->database();
590  $set = $db->query(
591  "SELECT page_id, parent_type, lang, active, activation_start, activation_end, show_activation_info FROM page_object " .
592  " WHERE parent_id = " . $db->quote($a_parent_id, "integer")
593  );
594  while ($rec = $db->fetchAssoc($set)) {
595  self::$activation_data[$rec["page_id"] . ":" . $rec["parent_type"] . ":" . $rec["lang"]] = $rec;
596  }
597  }
598 
599 
603  public static function _lookupActive($a_id, $a_parent_type, $a_check_scheduled_activation = false, $a_lang = "-")
604  {
605  global $DIC;
606 
607  $db = $DIC->database();
608 
609  // language must be set at least to "-"
610  if ($a_lang == "") {
611  $a_lang = "-";
612  }
613 
614  if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
615  $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
616  } else {
617  $set = $db->queryF(
618  "SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s" .
619  " AND parent_type = %s AND lang = %s",
620  array("integer", "text", "text"),
621  array($a_id, $a_parent_type, $a_lang)
622  );
623  $rec = $db->fetchAssoc($set);
624  }
625 
626 
627  $rec["n"] = ilUtil::now();
628 
629  if (!$rec["active"] && $a_check_scheduled_activation) {
630  if ($rec["n"] >= $rec["activation_start"] &&
631  $rec["n"] <= $rec["activation_end"]) {
632  return true;
633  }
634  }
635 
636  return $rec["active"];
637  }
638 
642  public static function _isScheduledActivation($a_id, $a_parent_type, $a_lang = "-")
643  {
644  global $DIC;
645 
646  $db = $DIC->database();
647 
648  // language must be set at least to "-"
649  if ($a_lang == "") {
650  $a_lang = "-";
651  }
652 
653  //echo "<br>";
654  //var_dump(self::$activation_data); exit;
655  if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
656  $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
657  } else {
658  $set = $db->queryF(
659  "SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s" .
660  " AND parent_type = %s AND lang = %s",
661  array("integer", "text", "text"),
662  array($a_id, $a_parent_type, $a_lang)
663  );
664  $rec = $db->fetchAssoc($set);
665  }
666 
667  if (!$rec["active"] && $rec["activation_start"] != "") {
668  return true;
669  }
670 
671  return false;
672  }
673 
677  public static function _writeActive($a_id, $a_parent_type, $a_active, $a_reset_scheduled_activation = true, $a_lang = "-")
678  {
679  global $DIC;
680 
681  $db = $DIC->database();
682 
683  // language must be set at least to "-"
684  if ($a_lang == "") {
685  $a_lang = "-";
686  }
687 
688  if ($a_reset_scheduled_activation) {
689  $st = $db->manipulateF(
690  "UPDATE page_object SET active = %s, activation_start = %s, " .
691  " activation_end = %s WHERE page_id = %s" .
692  " AND parent_type = %s AND lang = %s",
693  array("boolean", "timestamp", "timestamp", "integer", "text", "text"),
694  array($a_active, null, null, $a_id, $a_parent_type, $a_lang)
695  );
696  } else {
697  $st = $db->prepareManip(
698  "UPDATE page_object SET active = %s WHERE page_id = %s" .
699  " AND parent_type = %s AND lang = %s",
700  array("boolean", "integer", "text", "text"),
701  array($a_active, $a_id, $a_parent_type, $a_lang)
702  );
703  }
704  }
705 
709  public static function _lookupActivationData($a_id, $a_parent_type, $a_lang = "-")
710  {
711  global $DIC;
712 
713  $db = $DIC->database();
714 
715  // language must be set at least to "-"
716  if ($a_lang == "") {
717  $a_lang = "-";
718  }
719 
720  if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
721  $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
722  } else {
723  $set = $db->queryF(
724  "SELECT active, activation_start, activation_end, show_activation_info FROM page_object WHERE page_id = %s" .
725  " AND parent_type = %s AND lang = %s",
726  array("integer", "text", "text"),
727  array($a_id, $a_parent_type, $a_lang)
728  );
729  $rec = $db->fetchAssoc($set);
730  }
731 
732  return $rec;
733  }
734 
735 
739  public static function lookupParentId($a_id, $a_type)
740  {
741  global $DIC;
742 
743  $db = $DIC->database();
744 
745  $res = $db->query("SELECT parent_id FROM page_object WHERE page_id = " . $db->quote($a_id, "integer") . " " .
746  "AND parent_type=" . $db->quote($a_type, "text"));
747  $rec = $db->fetchAssoc($res);
748  return $rec["parent_id"];
749  }
750 
754  public static function _writeParentId($a_parent_type, $a_pg_id, $a_par_id)
755  {
756  global $DIC;
757 
758  $db = $DIC->database();
759  $db->manipulateF(
760  "UPDATE page_object SET parent_id = %s WHERE page_id = %s" .
761  " AND parent_type = %s",
762  array("integer", "integer", "text"),
763  array($a_par_id, $a_pg_id, $a_parent_type)
764  );
765  }
766 
772  public function setActivationStart($a_activationstart)
773  {
774  if ($a_activationstart == "") {
775  $a_activationstart = null;
776  }
777  $this->activationstart = $a_activationstart;
778  }
779 
785  public function getActivationStart()
786  {
787  return $this->activationstart;
788  }
789 
795  public function setActivationEnd($a_activationend)
796  {
797  if ($a_activationend == "") {
798  $a_activationend = null;
799  }
800  $this->activationend = $a_activationend;
801  }
802 
808  public function getActivationEnd()
809  {
810  return $this->activationend;
811  }
812 
821  public function getContentObject($a_hier_id, $a_pc_id = "")
822  {
823  $cont_node = $this->getContentNode($a_hier_id, $a_pc_id);
824  if (!is_object($cont_node)) {
825  return false;
826  }
827  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
828  $node_name = $cont_node->node_name();
829  if ($node_name == "PageObject") {
830  return null;
831  }
832  if ($node_name == "PageContent") {
833  $child_node = $cont_node->first_child();
834  $node_name = $child_node->node_name();
835  }
836 
837  // table extra handling (@todo: get rid of it)
838  if ($node_name == "Table") {
839  if ($child_node->get_attribute("DataTable") == "y") {
840  require_once("./Services/COPage/classes/class.ilPCDataTable.php");
841  $tab = new ilPCDataTable($this);
842  $tab->setNode($cont_node);
843  $tab->setHierId($a_hier_id);
844  } else {
845  require_once("./Services/COPage/classes/class.ilPCTable.php");
846  $tab = new ilPCTable($this);
847  $tab->setNode($cont_node);
848  $tab->setHierId($a_hier_id);
849  }
850  $tab->setPcId($a_pc_id);
851  return $tab;
852  }
853 
854  // media extra handling (@todo: get rid of it)
855  if ($node_name == "MediaObject") {
856  if ($_GET["pgEdMediaMode"] != "") {
857  echo "ilPageObject::error media";
858  exit;
859  }
860 
861  //require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
862  require_once("./Services/COPage/classes/class.ilPCMediaObject.php");
863 
864  $mal_node = $child_node->first_child();
865  //echo "ilPageObject::getContentObject:nodename:".$mal_node->node_name().":<br>";
866  $id_arr = explode("_", $mal_node->get_attribute("OriginId"));
867  $mob_id = $id_arr[count($id_arr) - 1];
868 
869  // allow deletion of non-existing media objects
870  if (!ilObject::_exists($mob_id) && in_array("delete", $_POST)) {
871  $mob_id = 0;
872  }
873 
874  //$mob = new ilObjMediaObject($mob_id);
875  $mob = new ilPCMediaObject($this);
876  $mob->readMediaObject($mob_id);
877 
878  //$mob->setDom($this->dom);
879  $mob->setNode($cont_node);
880  $mob->setHierId($a_hier_id);
881  $mob->setPcId($a_pc_id);
882  return $mob;
883  }
884 
885  //
886  // generic procedure
887  //
888 
889  $pc_def = ilCOPagePCDef::getPCDefinitionByName($node_name);
890 
891  // check if pc definition has been found
892  if (!is_array($pc_def)) {
893  include_once("./Services/COPage/exceptions/class.ilCOPageUnknownPCTypeException.php");
894  throw new ilCOPageUnknownPCTypeException('Unknown PC Name "' . $node_name . '".');
895  }
896  $pc_class = "ilPC" . $pc_def["name"];
897  $pc_path = "./" . $pc_def["component"] . "/" . $pc_def["directory"] . "/class." . $pc_class . ".php";
898  require_once($pc_path);
899  $pc = new $pc_class($this);
900  $pc->setNode($cont_node);
901  $pc->setHierId($a_hier_id);
902  $pc->setPcId($a_pc_id);
903  return $pc;
904  }
905 
912  public function &getContentNode($a_hier_id, $a_pc_id = "")
913  {
914  $xpc = xpath_new_context($this->dom);
915  if ($a_hier_id == "pg") {
916  return $this->node;
917  } else {
918  // get per pc id
919  if ($a_pc_id != "") {
920  $path = "//*[@PCID = '$a_pc_id']";
921  $res = xpath_eval($xpc, $path);
922  if (count($res->nodeset) == 1) {
923  $cont_node = $res->nodeset[0];
924  return $cont_node;
925  }
926  }
927 
928  // fall back to hier id
929  $path = "//*[@HierId = '$a_hier_id']";
930  $res = xpath_eval($xpc, $path);
931  if (count($res->nodeset) == 1) {
932  $cont_node = $res->nodeset[0];
933  return $cont_node;
934  }
935  }
936  }
937 
944  public function checkForTag($a_content_tag, $a_hier_id, $a_pc_id = "")
945  {
946  $xpc = xpath_new_context($this->dom);
947  // get per pc id
948  if ($a_pc_id != "") {
949  $path = "//*[@PCID = '$a_pc_id']//" . $a_content_tag;
950  $res = xpath_eval($xpc, $path);
951  if (count($res->nodeset) > 0) {
952  return true;
953  }
954  }
955 
956  // fall back to hier id
957  $path = "//*[@HierId = '$a_hier_id']//" . $a_content_tag;
958  $res = xpath_eval($xpc, $path);
959  if (count($res->nodeset) > 0) {
960  return true;
961  }
962  return false;
963  }
964 
965  // only for test purposes
966  public function lookforhier($a_hier_id)
967  {
968  $xpc = xpath_new_context($this->dom);
969  $path = "//*[@HierId = '$a_hier_id']";
970  $res = xpath_eval($xpc, $path);
971  if (count($res->nodeset) == 1) {
972  return "YES";
973  } else {
974  return "NO";
975  }
976  }
977 
978 
979  public function &getNode()
980  {
981  return $this->node;
982  }
983 
984 
993  public function setXMLContent($a_xml, $a_encoding = "UTF-8")
994  {
995  $this->encoding = $a_encoding;
996  $this->xml = $a_xml;
997  }
998 
1005  public function appendXMLContent($a_xml)
1006  {
1007  $this->xml .= $a_xml;
1008  }
1009 
1010 
1014  public function getXMLContent($a_incl_head = false)
1015  {
1016  // build full http path for XML DOCTYPE header.
1017  // Under windows a relative path doesn't work :-(
1018  if ($a_incl_head) {
1019  //echo "+".$this->encoding."+";
1020  $enc_str = (!empty($this->encoding))
1021  ? "encoding=\"" . $this->encoding . "\""
1022  : "";
1023  return "<?xml version=\"1.0\" $enc_str ?>" .
1024  "<!DOCTYPE PageObject SYSTEM \"" . ILIAS_ABSOLUTE_PATH . "/xml/" . $this->cur_dtd . "\">" .
1025  $this->xml;
1026  } else {
1027  return $this->xml;
1028  }
1029  }
1030 
1035  public function copyXmlContent($a_clone_mobs = false)
1036  {
1037  $xml = $this->getXmlContent();
1038  $temp_dom = domxml_open_mem(
1039  '<?xml version="1.0" encoding="UTF-8"?>' . $xml,
1041  $error
1042  );
1043  if (empty($error)) {
1044  $this->handleCopiedContent($temp_dom, true, $a_clone_mobs);
1045  }
1046  $xml = $temp_dom->dump_mem(0, $this->encoding);
1047  $xml = preg_replace('/<\?xml[^>]*>/i', "", $xml);
1048  $xml = preg_replace('/<!DOCTYPE[^>]*>/i', "", $xml);
1049 
1050  return $xml;
1051  }
1052 
1053  // @todo 1: begin: generalize, remove concrete dependencies
1054 
1064  public function handleCopiedContent($a_dom, $a_self_ass = true, $a_clone_mobs = false)
1065  {
1066  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1068 
1069  // handle question elements
1070  if ($a_self_ass) {
1071  $this->newQuestionCopies($a_dom);
1072  } else {
1073  $this->removeQuestions($a_dom);
1074  }
1075 
1076  // handle interactive images
1077  $this->newIIMCopies($a_dom);
1078 
1079  // handle media objects
1080  if ($a_clone_mobs) {
1081  $this->newMobCopies($a_dom);
1082  }
1083 
1084  // @todo 1: move all functions from above to the new domdoc
1085  if ($a_dom instanceof php4DOMDocument) {
1086  $a_dom = $a_dom->myDOMDocument;
1087  }
1088  foreach ($defs as $def) {
1090  $cl = $def["pc_class"];
1091  if ($cl == 'ilPCPlugged') {
1092  // the page object is provided for ilPageComponentPlugin
1093  ilPCPlugged::handleCopiedPluggedContent($this, $a_dom);
1094  } else {
1095  $cl::handleCopiedContent($a_dom, $a_self_ass, $a_clone_mobs);
1096  }
1097  }
1098  }
1099 
1107  public function handleDeleteContent($a_node = null)
1108  {
1109  if (!isset($a_node)) {
1110  $xpc = xpath_new_context($this->dom);
1111  $path = "//PageContent";
1112  $res = xpath_eval($xpc, $path);
1113  $nodes = $res->nodeset;
1114  } else {
1115  $nodes = array($a_node);
1116  }
1117 
1118  require_once('Services/COPage/classes/class.ilPCPlugged.php');
1119  foreach ($nodes as $node) {
1120  if ($node instanceof php4DOMNode) {
1121  $node = $node->myDOMNode;
1122  }
1123 
1125  if ($node->firstChild->nodeName == 'Plugged') {
1126  ilPCPlugged::handleDeletedPluggedNode($this, $node->firstChild);
1127  }
1128  }
1129  }
1130 
1135  public function newIIMCopies($temp_dom)
1136  {
1137  // Get question IDs
1138  $path = "//InteractiveImage/MediaAlias";
1139  $xpc = xpath_new_context($temp_dom);
1140  $res = &xpath_eval($xpc, $path);
1141 
1142  $q_ids = array();
1143  include_once("./Services/Link/classes/class.ilInternalLink.php");
1144  for ($i = 0; $i < count($res->nodeset); $i++) {
1145  $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1146 
1147  $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1148  $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1149 
1150  if (!($inst_id > 0)) {
1151  if ($mob_id > 0) {
1152  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1153  $media_object = new ilObjMediaObject($mob_id);
1154 
1155  // now copy this question and change reference to
1156  // new question id
1157  $new_mob = $media_object->duplicate();
1158 
1159  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $new_mob->getId());
1160  }
1161  }
1162  }
1163  }
1164 
1168  public function newMobCopies($temp_dom)
1169  {
1170  // Get question IDs
1171  $path = "//MediaObject/MediaAlias";
1172  $xpc = xpath_new_context($temp_dom);
1173  $res = &xpath_eval($xpc, $path);
1174 
1175  $q_ids = array();
1176  include_once("./Services/Link/classes/class.ilInternalLink.php");
1177  for ($i = 0; $i < count($res->nodeset); $i++) {
1178  $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1179 
1180  $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1181  $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1182 
1183  if (!($inst_id > 0)) {
1184  if ($mob_id > 0) {
1185  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1186  $media_object = new ilObjMediaObject($mob_id);
1187 
1188  // now copy this question and change reference to
1189  // new question id
1190  $new_mob = $media_object->duplicate();
1191 
1192  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $new_mob->getId());
1193  }
1194  }
1195  }
1196  }
1197 
1202  public function newQuestionCopies(&$temp_dom)
1203  {
1204  // Get question IDs
1205  $path = "//Question";
1206  $xpc = xpath_new_context($temp_dom);
1207  $res = &xpath_eval($xpc, $path);
1208 
1209  $q_ids = array();
1210  include_once("./Services/Link/classes/class.ilInternalLink.php");
1211  for ($i = 0; $i < count($res->nodeset); $i++) {
1212  $qref = $res->nodeset[$i]->get_attribute("QRef");
1213 
1214  $inst_id = ilInternalLink::_extractInstOfTarget($qref);
1216 
1217  if (!($inst_id > 0)) {
1218  if ($q_id > 0) {
1219  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1220  $question = assQuestion::_instantiateQuestion($q_id);
1221  // check due to #16557
1222  if (is_object($question) && $question->isComplete()) {
1223  // check if page for question exists
1224  // due to a bug in early 4.2.x version this is possible
1225  if (!ilPageObject::_exists("qpl", $q_id)) {
1226  $question->createPageObject();
1227  }
1228 
1229  // now copy this question and change reference to
1230  // new question id
1231  $duplicate_id = $question->duplicate(false);
1232  $res->nodeset[$i]->set_attribute("QRef", "il__qst_" . $duplicate_id);
1233  }
1234  }
1235  }
1236  }
1237  }
1238 
1245  public function removeQuestions(&$temp_dom)
1246  {
1247  // Get question IDs
1248  $path = "//Question";
1249  $xpc = xpath_new_context($temp_dom);
1250  $res = &xpath_eval($xpc, $path);
1251  for ($i = 0; $i < count($res->nodeset); $i++) {
1252  $parent_node = $res->nodeset[$i]->parent_node();
1253  $parent_node->unlink_node($parent_node);
1254  }
1255  }
1256 
1257  // @todo: end
1258 
1265  public function countPageContents()
1266  {
1267  // Get question IDs
1268  $this->buildDom();
1269  $path = "//PageContent";
1270  $xpc = xpath_new_context($this->dom);
1271  $res = &xpath_eval($xpc, $path);
1272  return count($res->nodeset);
1273  }
1274 
1279  public function getXMLFromDom(
1280  $a_incl_head = false,
1281  $a_append_mobs = false,
1282  $a_append_bib = false,
1283  $a_append_str = "",
1284  $a_omit_pageobject_tag = false
1285  ) {
1286  if ($a_incl_head) {
1287  //echo "\n<br>#".$this->encoding."#";
1288  return $this->dom->dump_mem(0, $this->encoding);
1289  } else {
1290  // append multimedia object elements
1291  if ($a_append_mobs || $a_append_bib || $a_append_link_info) {
1292  $mobs = "";
1293  $bibs = "";
1294  if ($a_append_mobs) {
1295  $mobs = $this->getMultimediaXML();
1296  }
1297  if ($a_append_bib) {
1298  // deprecated
1299 // $bibs = $this->getBibliographyXML();
1300  }
1301  $trans = $this->getLanguageVariablesXML();
1302  //echo htmlentities($this->dom->dump_node($this->node)); exit;
1303  return "<dummy>" . $this->dom->dump_node($this->node) . $mobs . $bibs . $trans . $a_append_str . "</dummy>";
1304  } else {
1305  if (is_object($this->dom)) {
1306  if ($a_omit_pageobject_tag) {
1307  $xml = "";
1308  $childs = $this->node->child_nodes();
1309  for ($i = 0; $i < count($childs); $i++) {
1310  $xml .= $this->dom->dump_node($childs[$i]);
1311  }
1312  return $xml;
1313  } else {
1314  $xml = $this->dom->dump_mem(0, $this->encoding);
1315  $xml = preg_replace('/<\?xml[^>]*>/i', "", $xml);
1316  $xml = preg_replace('/<!DOCTYPE[^>]*>/i', "", $xml);
1317  return $xml;
1318 
1319  // don't use dump_node. This gives always entities.
1320  //return $this->dom->dump_node($this->node);
1321  }
1322  } else {
1323  return "";
1324  }
1325  }
1326  }
1327  }
1328 
1332  public function getLanguageVariablesXML()
1333  {
1334  $xml = "<LVs>";
1335  $lang_vars = array(
1336  "ed_paste_clip", "ed_edit", "ed_edit_prop", "ed_delete", "ed_moveafter",
1337  "ed_movebefore", "ed_go", "ed_class", "ed_width", "ed_align_left",
1338  "ed_align_right", "ed_align_center", "ed_align_left_float",
1339  "ed_align_right_float", "ed_delete_item", "ed_new_item_before",
1340  "ed_new_item_after", "ed_copy_clip", "please_select", "ed_split_page",
1341  "ed_item_up", "ed_item_down", "ed_split_page_next","ed_enable",
1342  "de_activate", "ed_paste", "ed_edit_multiple", "ed_cut", "ed_copy", "ed_insert_templ",
1343  "ed_click_to_add_pg", "download");
1344 
1345  // collect lang vars from pc elements
1346  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1348  foreach ($defs as $def) {
1349  $lang_vars[] = "pc_" . $def["pc_type"];
1350  $lang_vars[] = "ed_insert_" . $def["pc_type"];
1351 
1353  $cl = $def["pc_class"];
1354  $lvs = call_user_func($def["pc_class"] . '::getLangVars');
1355  foreach ($lvs as $lv) {
1356  $lang_vars[] = $lv;
1357  }
1358  }
1359 
1360  foreach ($lang_vars as $lang_var) {
1361  $this->appendLangVarXML($xml, $lang_var);
1362  }
1363 
1364  $xml .= "</LVs>";
1365  return $xml;
1366  }
1367 
1368  public function appendLangVarXML(&$xml, $var)
1369  {
1370  $val = $this->lng->txt("cont_" . $var);
1371  $val = str_replace('"', "&quot;", $val);
1372  $xml .= "<LV name=\"$var\" value=\"" . $val . "\"/>";
1373  }
1374 
1375  // @todo begin: move this to paragraph class
1376 
1377  public function getFirstParagraphText()
1378  {
1379  if ($this->dom) {
1380  require_once("./Services/COPage/classes/class.ilPCParagraph.php");
1381  $xpc = xpath_new_context($this->dom);
1382  $path = "//Paragraph[1]";
1383  $res = xpath_eval($xpc, $path);
1384  if (count($res->nodeset) > 0) {
1385  $cont_node = $res->nodeset[0]->parent_node();
1386  $par = new ilPCParagraph($this);
1387  $par->setNode($cont_node);
1388  $text = $par->getText();
1389 
1390  return $text;
1391  }
1392  }
1393  return "";
1394  }
1395 
1402  public function setParagraphContent($a_hier_id, $a_content)
1403  {
1404  $node = $this->getContentNode($a_hier_id);
1405  if (is_object($node)) {
1406  $node->set_content($a_content);
1407  }
1408  }
1409 
1410  // @todo end
1411 
1412 
1421  // @todo: can we do this better
1422  public function setContainsIntLink($a_contains_link)
1423  {
1424  $this->contains_int_link = $a_contains_link;
1425  }
1426 
1431  // @todo: can we do this better
1432  public function containsIntLink()
1433  {
1434  return $this->contains_int_link;
1435  }
1436 
1442  public function setImportMode($a_val)
1443  {
1444  $this->import_mode = $a_val;
1445  }
1446 
1452  public function getImportMode()
1453  {
1454  return $this->import_mode;
1455  }
1456 
1457  public function needsImportParsing($a_parse = "")
1458  {
1459  if ($a_parse === true) {
1460  $this->needs_parsing = true;
1461  }
1462  if ($a_parse === false) {
1463  $this->needs_parsing = false;
1464  }
1465  return $this->needs_parsing;
1466  }
1467 
1473  // @todo: can we do this better
1474  public function setContainsQuestion($a_val)
1475  {
1476  $this->contains_question = $a_val;
1477  }
1478 
1484  public function getContainsQuestion()
1485  {
1486  return $this->contains_question;
1487  }
1488 
1489 
1494  // @todo: move to media class
1495  public function collectMediaObjects($a_inline_only = true)
1496  {
1497  //echo htmlentities($this->getXMLFromDom());
1498  // determine all media aliases of the page
1499  $xpc = xpath_new_context($this->dom);
1500  $path = "//MediaObject/MediaAlias";
1501  $res = xpath_eval($xpc, $path);
1502  $mob_ids = array();
1503  for ($i = 0; $i < count($res->nodeset); $i++) {
1504  $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1505  $mob_id = $id_arr[count($id_arr) - 1];
1506  $mob_ids[$mob_id] = $mob_id;
1507  }
1508 
1509  // determine all media aliases of interactive images
1510  $xpc = xpath_new_context($this->dom);
1511  $path = "//InteractiveImage/MediaAlias";
1512  $res = xpath_eval($xpc, $path);
1513  for ($i = 0; $i < count($res->nodeset); $i++) {
1514  $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1515  $mob_id = $id_arr[count($id_arr) - 1];
1516  $mob_ids[$mob_id] = $mob_id;
1517  }
1518 
1519  // determine all inline internal media links
1520  $xpc = xpath_new_context($this->dom);
1521  $path = "//IntLink[@Type = 'MediaObject']";
1522  $res = xpath_eval($xpc, $path);
1523 
1524  for ($i = 0; $i < count($res->nodeset); $i++) {
1525  if (($res->nodeset[$i]->get_attribute("TargetFrame") == "") ||
1526  (!$a_inline_only)) {
1527  $target = $res->nodeset[$i]->get_attribute("Target");
1528  $id_arr = explode("_", $target);
1529  if (($id_arr[1] == IL_INST_ID) ||
1530  (substr($target, 0, 4) == "il__")) {
1531  $mob_id = $id_arr[count($id_arr) - 1];
1532  if (ilObject::_exists($mob_id)) {
1533  $mob_ids[$mob_id] = $mob_id;
1534  }
1535  }
1536  }
1537  }
1538 
1539  return $mob_ids;
1540  }
1541 
1542 
1546  // @todo: can we do this better?
1547  public function getInternalLinks($a_cnt_multiple = false)
1548  {
1549  // get all internal links of the page
1550  $xpc = xpath_new_context($this->dom);
1551  $path = "//IntLink";
1552  $res = xpath_eval($xpc, $path);
1553 
1554  $links = array();
1555  $cnt_multiple = 1;
1556  for ($i = 0; $i < count($res->nodeset); $i++) {
1557  $add = "";
1558  if ($a_cnt_multiple) {
1559  $add = ":" . $cnt_multiple;
1560  }
1561  $target = $res->nodeset[$i]->get_attribute("Target");
1562  $type = $res->nodeset[$i]->get_attribute("Type");
1563  $targetframe = $res->nodeset[$i]->get_attribute("TargetFrame");
1564  $anchor = $res->nodeset[$i]->get_attribute("Anchor");
1565  $links[$target . ":" . $type . ":" . $targetframe . ":" . $anchor . $add] =
1566  array("Target" => $target, "Type" => $type,
1567  "TargetFrame" => $targetframe, "Anchor" => $anchor);
1568 
1569  // get links (image map areas) for inline media objects
1570  if ($type == "MediaObject" && $targetframe == "") {
1571  if (substr($target, 0, 4) == "il__") {
1572  $id_arr = explode("_", $target);
1573  $id = $id_arr[count($id_arr) - 1];
1574 
1575  $med_links = ilMediaItem::_getMapAreasIntLinks($id);
1576  foreach ($med_links as $key => $med_link) {
1577  $links[$key] = $med_link;
1578  }
1579  }
1580  }
1581  //echo "<br>-:".$target.":".$type.":".$targetframe.":-";
1582  $cnt_multiple++;
1583  }
1584  unset($xpc);
1585 
1586  // get all media aliases
1587  $xpc = xpath_new_context($this->dom);
1588  $path = "//MediaAlias";
1589  $res = xpath_eval($xpc, $path);
1590 
1591  require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
1592  for ($i = 0; $i < count($res->nodeset); $i++) {
1593  $oid = $res->nodeset[$i]->get_attribute("OriginId");
1594  if (substr($oid, 0, 4) == "il__") {
1595  $id_arr = explode("_", $oid);
1596  $id = $id_arr[count($id_arr) - 1];
1597 
1598  $med_links = ilMediaItem::_getMapAreasIntLinks($id);
1599  foreach ($med_links as $key => $med_link) {
1600  $links[$key] = $med_link;
1601  }
1602  }
1603  }
1604  unset($xpc);
1605 
1606  return $links;
1607  }
1608 
1613  // @todo: move to media class
1614  public function getMultimediaXML()
1615  {
1616  $mob_ids = $this->collectMediaObjects();
1617 
1618  // get xml of corresponding media objects
1619  $mobs_xml = "";
1620  require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1621  foreach ($mob_ids as $mob_id => $dummy) {
1622  if (ilObject::_lookupType($mob_id) == "mob") {
1623  $mob_obj = new ilObjMediaObject($mob_id);
1624  $mobs_xml .= $mob_obj->getXML(IL_MODE_OUTPUT, $a_inst = 0, true);
1625  }
1626  }
1627  //var_dump($mobs_xml);
1628  return $mobs_xml;
1629  }
1630 
1634  // @todo: move to media class
1635  public function getMediaAliasElement($a_mob_id, $a_nr = 1)
1636  {
1637  $xpc = xpath_new_context($this->dom);
1638  $path = "//MediaObject/MediaAlias[@OriginId='il__mob_$a_mob_id']";
1639  $res = xpath_eval($xpc, $path);
1640  $mal_node = $res->nodeset[$a_nr - 1];
1641  $mob_node = $mal_node->parent_node();
1642 
1643  return $this->dom->dump_node($mob_node);
1644  }
1645 
1651  public function validateDom()
1652  {
1653  $this->stripHierIDs();
1654 
1655  // possible fix for #14820
1656  libxml_disable_entity_loader(false);
1657 
1658  @$this->dom->validate($error);
1659  //var_dump($this->dom); exit;
1660  return $error;
1661  }
1662 
1678  // @todo: can we do this better? remove dependencies?
1679  public function addHierIDs()
1680  {
1681  $this->hier_ids = array();
1682  $this->first_row_ids = array();
1683  $this->first_col_ids = array();
1684  $this->list_item_ids = array();
1685  $this->file_item_ids = array();
1686 
1687  // set hierarchical ids for Paragraphs, Tables, TableRows and TableData elements
1688  $xpc = xpath_new_context($this->dom);
1689  //$path = "//Paragraph | //Table | //TableRow | //TableData";
1690 
1691  $sep = $path = "";
1692  foreach ($this->id_elements as $el) {
1693  $path .= $sep . "//" . $el;
1694  $sep = " | ";
1695  }
1696 
1697  $res = xpath_eval($xpc, $path);
1698  for ($i = 0; $i < count($res->nodeset); $i++) {
1699  $cnode = $res->nodeset[$i];
1700  $ctag = $cnode->node_name();
1701 
1702  // get hierarchical id of previous sibling
1703  $sib_hier_id = "";
1704  while ($cnode = $cnode->previous_sibling()) {
1705  if (($cnode->node_type() == XML_ELEMENT_NODE)
1706  && $cnode->has_attribute("HierId")) {
1707  $sib_hier_id = $cnode->get_attribute("HierId");
1708  //$sib_hier_id = $id_attr->value();
1709  break;
1710  }
1711  }
1712 
1713  if ($sib_hier_id != "") { // set id to sibling id "+ 1"
1714  require_once("./Services/COPage/classes/class.ilPageContent.php");
1715  $node_hier_id = ilPageContent::incEdId($sib_hier_id);
1716  $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1717  $this->hier_ids[] = $node_hier_id;
1718  if ($ctag == "TableData") {
1719  if (substr($par_hier_id, strlen($par_hier_id) - 2) == "_1") {
1720  $this->first_row_ids[] = $node_hier_id;
1721  }
1722  }
1723  if ($ctag == "ListItem") {
1724  $this->list_item_ids[] = $node_hier_id;
1725  }
1726  if ($ctag == "FileItem") {
1727  $this->file_item_ids[] = $node_hier_id;
1728  }
1729  } else { // no sibling -> node is first child
1730  // get hierarchical id of next parent
1731  $cnode = $res->nodeset[$i];
1732  $par_hier_id = "";
1733  while ($cnode = $cnode->parent_node()) {
1734  if (($cnode->node_type() == XML_ELEMENT_NODE)
1735  && $cnode->has_attribute("HierId")) {
1736  $par_hier_id = $cnode->get_attribute("HierId");
1737  //$par_hier_id = $id_attr->value();
1738  break;
1739  }
1740  }
1741  //echo "<br>par:".$par_hier_id." ($ctag)";
1742  if (($par_hier_id != "") && ($par_hier_id != "pg")) { // set id to parent_id."_1"
1743  $node_hier_id = $par_hier_id . "_1";
1744  $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1745  $this->hier_ids[] = $node_hier_id;
1746  if ($ctag == "TableData") {
1747  $this->first_col_ids[] = $node_hier_id;
1748  if (substr($par_hier_id, strlen($par_hier_id) - 2) == "_1") {
1749  $this->first_row_ids[] = $node_hier_id;
1750  }
1751  }
1752  if ($ctag == "ListItem") {
1753  $this->list_item_ids[] = $node_hier_id;
1754  }
1755  if ($ctag == "FileItem") {
1756  $this->file_item_ids[] = $node_hier_id;
1757  }
1758  } else { // no sibling, no parent -> first node
1759  $node_hier_id = "1";
1760  $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1761  $this->hier_ids[] = $node_hier_id;
1762  }
1763  }
1764  }
1765 
1766  // set special hierarchical id "pg" for pageobject
1767  $xpc = xpath_new_context($this->dom);
1768  $path = "//PageObject";
1769  $res = xpath_eval($xpc, $path);
1770  for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1771  $res->nodeset[$i]->set_attribute("HierId", "pg");
1772  $this->hier_ids[] = "pg";
1773  }
1774  unset($xpc);
1775  }
1776 
1780  public function getHierIds()
1781  {
1782  return $this->hier_ids;
1783  }
1784 
1788  // @todo: move to table classes
1789  public function getFirstRowIds()
1790  {
1791  return $this->first_row_ids;
1792  }
1793 
1797  // @todo: move to table classes
1798  public function getFirstColumnIds()
1799  {
1800  return $this->first_col_ids;
1801  }
1802 
1806  // @todo: move to list class
1807  public function getListItemIds()
1808  {
1809  return $this->list_item_ids;
1810  }
1811 
1815  // @todo: move to file item class
1816  public function getFileItemIds()
1817  {
1818  return $this->file_item_ids;
1819  }
1820 
1824  public function stripHierIDs()
1825  {
1826  if (is_object($this->dom)) {
1827  $xpc = xpath_new_context($this->dom);
1828  $path = "//*[@HierId]";
1829  $res = xpath_eval($xpc, $path);
1830  for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1831  if ($res->nodeset[$i]->has_attribute("HierId")) {
1832  $res->nodeset[$i]->remove_attribute("HierId");
1833  }
1834  }
1835  unset($xpc);
1836  }
1837  }
1838 
1842  public function getHierIdsForPCIds($a_pc_ids)
1843  {
1844  if (!is_array($a_pc_ids) || count($a_pc_ids) == 0) {
1845  return array();
1846  }
1847  $ret = array();
1848 
1849  if (is_object($this->dom)) {
1850  $xpc = xpath_new_context($this->dom);
1851  $path = "//*[@PCID]";
1852  $res = xpath_eval($xpc, $path);
1853  for ($i = 0; $i < count($res->nodeset); $i++) { // should only be 1
1854  $pc_id = $res->nodeset[$i]->get_attribute("PCID");
1855  if (in_array($pc_id, $a_pc_ids)) {
1856  $ret[$pc_id] = $res->nodeset[$i]->get_attribute("HierId");
1857  }
1858  }
1859  unset($xpc);
1860  }
1861  //var_dump($ret);
1862  return $ret;
1863  }
1864 
1868  // @todo: move to file item class
1869  public function addFileSizes()
1870  {
1871  $xpc = xpath_new_context($this->dom);
1872  $path = "//FileItem";
1873  $res = xpath_eval($xpc, $path);
1874  for ($i = 0; $i < count($res->nodeset); $i++) {
1875  $cnode = $res->nodeset[$i];
1876  $size_node = $this->dom->create_element("Size");
1877  $size_node = $cnode->append_child($size_node);
1878 
1879  $childs = $cnode->child_nodes();
1880  $size = "";
1881  for ($j = 0; $j < count($childs); $j++) {
1882  if ($childs[$j]->node_name() == "Identifier") {
1883  if ($childs[$j]->has_attribute("Entry")) {
1884  $entry = $childs[$j]->get_attribute("Entry");
1885  $entry_arr = explode("_", $entry);
1886  $id = $entry_arr[count($entry_arr) - 1];
1887  require_once("./Modules/File/classes/class.ilObjFile.php");
1889  }
1890  }
1891  }
1892  $size_node->set_content($size);
1893  }
1894 
1895  unset($xpc);
1896  }
1897 
1902  // @todo: possible to improve this?
1903  public function resolveIntLinks($a_link_map = null)
1904  {
1905  $changed = false;
1906 
1907  $this->log->debug("start");
1908 
1909  // resolve normal internal links
1910  $xpc = xpath_new_context($this->dom);
1911  $path = "//IntLink";
1912  $res = xpath_eval($xpc, $path);
1913  for ($i = 0; $i < count($res->nodeset); $i++) {
1914  $target = $res->nodeset[$i]->get_attribute("Target");
1915  $type = $res->nodeset[$i]->get_attribute("Type");
1916 
1917  if ($a_link_map == null) {
1919  $this->log->debug("no map, type: " . $type . ", target: " . $target . ", new target: " . $new_target);
1920  // echo "-".$new_target."-".$type."-".$target."-"; exit;
1921  } else {
1922  $nt = explode("_", $a_link_map[$target]);
1923  $new_target = false;
1924  if ($nt[1] == IL_INST_ID) {
1925  $new_target = "il__" . $nt[2] . "_" . $nt[3];
1926  }
1927  $this->log->debug("map, type: " . $type . ", target: " . $target . ", new target: " . $new_target);
1928  }
1929  if ($new_target !== false) {
1930  $res->nodeset[$i]->set_attribute("Target", $new_target);
1931  $changed = true;
1932  } else { // check wether link target is same installation
1933  if (ilInternalLink::_extractInstOfTarget($target) == IL_INST_ID &&
1934  IL_INST_ID > 0 && $type != "RepositoryItem") {
1936  if (ilInternalLink::_exists($type, $new_target)) {
1937  $res->nodeset[$i]->set_attribute("Target", $new_target);
1938  $changed = true;
1939  }
1940  }
1941  }
1942  }
1943  unset($xpc);
1944 
1945  // resolve internal links in map areas
1946  $xpc = xpath_new_context($this->dom);
1947  $path = "//MediaAlias";
1948  $res = xpath_eval($xpc, $path);
1949  //echo "<br><b>page::resolve</b><br>";
1950  //echo "Content:".htmlentities($this->getXMLFromDOM()).":<br>";
1951  for ($i = 0; $i < count($res->nodeset); $i++) {
1952  $orig_id = $res->nodeset[$i]->get_attribute("OriginId");
1953  $id_arr = explode("_", $orig_id);
1954  $mob_id = $id_arr[count($id_arr) - 1];
1956  }
1957  return $changed;
1958  }
1959 
1966  // @todo: move to media classes?
1967  public function resolveMediaAliases($a_mapping, $a_reuse_existing_by_import = false)
1968  {
1969  // resolve normal internal links
1970  $xpc = xpath_new_context($this->dom);
1971  $path = "//MediaAlias";
1972  $res = xpath_eval($xpc, $path);
1973  $changed = false;
1974  for ($i = 0; $i < count($res->nodeset); $i++) {
1975  // get the ID of the import file from the xml
1976  $old_id = $res->nodeset[$i]->get_attribute("OriginId");
1977  $old_id = explode("_", $old_id);
1978  $old_id = $old_id[count($old_id) - 1];
1979  $new_id = "";
1980  $import_id = "";
1981  // get the new id from the current mapping
1982  if ($a_mapping[$old_id] > 0) {
1983  $new_id = $a_mapping[$old_id];
1984  if ($a_reuse_existing_by_import) {
1985  // this should work, if the lm has been imported in a translation installation and re-exported
1986  $import_id = ilObject::_lookupImportId($new_id);
1987  $imp = explode("_", $import_id);
1988  if ($imp[1] == IL_INST_ID && $imp[2] == "mob" && ilObject::_lookupType($imp[3]) == "mob") {
1989  $new_id = $imp[3];
1990  }
1991  }
1992  }
1993  // now check, if the translation has been done just by changing text in the exported
1994  // translation file
1995  if ($import_id == "" && $a_reuse_existing_by_import) {
1996  // if the old_id is also referred by the page content of the default language
1997  // we assume that this media object is unchanged
1998  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1999  $med_of_def_lang = ilObjMediaObject::_getMobsOfObject($this->getParentType() . ":pg", $this->getId(), 0, "-");
2000  if (in_array($old_id, $med_of_def_lang)) {
2001  $new_id = $old_id;
2002  }
2003  }
2004  if ($new_id != "") {
2005  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $new_id);
2006  $changed = true;
2007  }
2008  }
2009  unset($xpc);
2010  return $changed;
2011  }
2012 
2019  // @todo: move to iim classes?
2020  public function resolveIIMMediaAliases($a_mapping)
2021  {
2022  // resolve normal internal links
2023  $xpc = xpath_new_context($this->dom);
2024  $path = "//InteractiveImage/MediaAlias";
2025  $res = xpath_eval($xpc, $path);
2026  $changed = false;
2027  for ($i = 0; $i < count($res->nodeset); $i++) {
2028  $old_id = $res->nodeset[$i]->get_attribute("OriginId");
2029  if ($a_mapping[$old_id] > 0) {
2030  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_" . $a_mapping[$old_id]);
2031  $changed = true;
2032  }
2033  }
2034  unset($xpc);
2035 
2036  return $changed;
2037  }
2038 
2045  // @todo: move to file classes?
2046  public function resolveFileItems($a_mapping)
2047  {
2048  // resolve normal internal links
2049  $xpc = xpath_new_context($this->dom);
2050  $path = "//FileItem/Identifier";
2051  $res = xpath_eval($xpc, $path);
2052  $changed = false;
2053  for ($i = 0; $i < count($res->nodeset); $i++) {
2054  $old_id = $res->nodeset[$i]->get_attribute("Entry");
2055  $old_id = explode("_", $old_id);
2056  $old_id = $old_id[count($old_id) - 1];
2057  if ($a_mapping[$old_id] > 0) {
2058  $res->nodeset[$i]->set_attribute("Entry", "il__file_" . $a_mapping[$old_id]);
2059  $changed = true;
2060  }
2061  }
2062  unset($xpc);
2063 
2064  return $changed;
2065  }
2066 
2071  // @todo: move to question classes
2072  public function resolveQuestionReferences($a_mapping)
2073  {
2074  // resolve normal internal links
2075  $xpc = xpath_new_context($this->dom);
2076  $path = "//Question";
2077  $res = xpath_eval($xpc, $path);
2078  $updated = false;
2079  for ($i = 0; $i < count($res->nodeset); $i++) {
2080  $qref = $res->nodeset[$i]->get_attribute("QRef");
2081 
2082  if (isset($a_mapping[$qref])) {
2083  $res->nodeset[$i]->set_attribute("QRef", "il__qst_" . $a_mapping[$qref]["pool"]);
2084  $updated = true;
2085  }
2086  }
2087  unset($xpc);
2088 
2089  return $updated;
2090  }
2091 
2092 
2099  // @todo: generalize, internal links usage info
2100  public function moveIntLinks($a_from_to)
2101  {
2102  $this->buildDom();
2103 
2104  $changed = false;
2105 
2106  // resolve normal internal links
2107  $xpc = xpath_new_context($this->dom);
2108  $path = "//IntLink";
2109  $res = xpath_eval($xpc, $path);
2110  for ($i = 0; $i < count($res->nodeset); $i++) {
2111  $target = $res->nodeset[$i]->get_attribute("Target");
2112  $type = $res->nodeset[$i]->get_attribute("Type");
2114  if ($a_from_to[$obj_id] > 0 && is_int(strpos($target, "__"))) {
2115  if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg") {
2116  $res->nodeset[$i]->set_attribute("Target", "il__pg_" . $a_from_to[$obj_id]);
2117  $changed = true;
2118  }
2119  if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st") {
2120  $res->nodeset[$i]->set_attribute("Target", "il__st_" . $a_from_to[$obj_id]);
2121  $changed = true;
2122  }
2123  if ($type == "PortfolioPage") {
2124  $res->nodeset[$i]->set_attribute("Target", "il__ppage_" . $a_from_to[$obj_id]);
2125  $changed = true;
2126  }
2127  }
2128  }
2129  unset($xpc);
2130 
2131  // map areas
2132  $this->addHierIDs();
2133  $xpc = xpath_new_context($this->dom);
2134  $path = "//MediaAlias";
2135  $res = xpath_eval($xpc, $path);
2136 
2137  require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
2138  require_once("Services/COPage/classes/class.ilMediaAliasItem.php");
2139 
2140  for ($i = 0; $i < count($res->nodeset); $i++) {
2141  $media_object_node = $res->nodeset[$i]->parent_node();
2142  $page_content_node = $media_object_node->parent_node();
2143  $c_hier_id = $page_content_node->get_attribute("HierId");
2144 
2145  // first check, wheter we got instance map areas -> take these
2146  $std_alias_item = new ilMediaAliasItem(
2147  $this->dom,
2148  $c_hier_id,
2149  "Standard"
2150  );
2151  $areas = $std_alias_item->getMapAreas();
2152  $correction_needed = false;
2153  if (count($areas) > 0) {
2154  // check if correction needed
2155  foreach ($areas as $area) {
2156  if ($area["Type"] == "PageObject" ||
2157  $area["Type"] == "StructureObject") {
2158  $t = $area["Target"];
2159  $tid = _extractObjIdOfTarget($t);
2160  if ($a_from_to[$tid] > 0) {
2161  $correction_needed = true;
2162  }
2163  }
2164  }
2165  } else {
2166  $areas = array();
2167 
2168  // get object map areas and check whether at least one must
2169  // be corrected
2170  $oid = $res->nodeset[$i]->get_attribute("OriginId");
2171  if (substr($oid, 0, 4) == "il__") {
2172  $id_arr = explode("_", $oid);
2173  $id = $id_arr[count($id_arr) - 1];
2174 
2175  $mob = new ilObjMediaObject($id);
2176  $med_item = $mob->getMediaItem("Standard");
2177  $med_areas = $med_item->getMapAreas();
2178 
2179  foreach ($med_areas as $area) {
2180  $link_type = ($area->getLinkType() == "int")
2181  ? "IntLink"
2182  : "ExtLink";
2183 
2184  $areas[] = array(
2185  "Nr" => $area->getNr(),
2186  "Shape" => $area->getShape(),
2187  "Coords" => $area->getCoords(),
2188  "Link" => array(
2189  "LinkType" => $link_type,
2190  "Href" => $area->getHref(),
2191  "Title" => $area->getTitle(),
2192  "Target" => $area->getTarget(),
2193  "Type" => $area->getType(),
2194  "TargetFrame" => $area->getTargetFrame()
2195  )
2196  );
2197 
2198  if ($area->getType() == "PageObject" ||
2199  $area->getType() == "StructureObject") {
2200  $t = $area->getTarget();
2202  if ($a_from_to[$tid] > 0) {
2203  $correction_needed = true;
2204  }
2205  //var_dump($a_from_to);
2206  }
2207  }
2208  }
2209  }
2210 
2211  // correct map area links
2212  if ($correction_needed) {
2213  $changed = true;
2214  $std_alias_item->deleteAllMapAreas();
2215  foreach ($areas as $area) {
2216  if ($area["Link"]["LinkType"] == "IntLink") {
2217  $target = $area["Link"]["Target"];
2218  $type = $area["Link"]["Type"];
2220  if ($a_from_to[$obj_id] > 0) {
2221  if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg") {
2222  $area["Link"]["Target"] = "il__pg_" . $a_from_to[$obj_id];
2223  }
2224  if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st") {
2225  $area["Link"]["Target"] = "il__st_" . $a_from_to[$obj_id];
2226  }
2227  }
2228  }
2229 
2230  $std_alias_item->addMapArea(
2231  $area["Shape"],
2232  $area["Coords"],
2233  $area["Link"]["Title"],
2234  array( "Type" => $area["Link"]["Type"],
2235  "TargetFrame" => $area["Link"]["TargetFrame"],
2236  "Target" => $area["Link"]["Target"],
2237  "Href" => $area["Link"]["Href"],
2238  "LinkType" => $area["Link"]["LinkType"],
2239  )
2240  );
2241  }
2242  }
2243  }
2244  unset($xpc);
2245 
2246  return $changed;
2247  }
2248 
2254  // @todo: generalize, internal links usage info
2255  public static function _handleImportRepositoryLinks($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2256  {
2257  include_once("./Services/Link/classes/class.ilInternalLink.php");
2258 
2259  //echo "-".$a_rep_import_id."-".$a_rep_ref_id."-";
2261  "obj",
2262  ilInternalLink::_extractObjIdOfTarget($a_rep_import_id),
2263  ilInternalLink::_extractInstOfTarget($a_rep_import_id)
2264  );
2265  //var_dump($sources);
2266  foreach ($sources as $source) {
2267  //echo "A";
2268  if ($source["type"] == "lm:pg") {
2269  //echo "B";
2270  include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
2271  if (self::_exists("lm", $source["id"], $source["lang"])) {
2272  $page_obj = new ilLMPage($source["id"], 0, $source["lang"]);
2273  if (!$page_obj->page_not_found) {
2274  //echo "C";
2275  $page_obj->handleImportRepositoryLink(
2276  $a_rep_import_id,
2277  $a_rep_type,
2278  $a_rep_ref_id
2279  );
2280  }
2281  $page_obj->update();
2282  }
2283  }
2284  }
2285  }
2286 
2287  // @todo: generalize, internal links usage info
2288  public function handleImportRepositoryLink($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2289  {
2290  $this->buildDom();
2291 
2292  // resolve normal internal links
2293  $xpc = xpath_new_context($this->dom);
2294  $path = "//IntLink";
2295  $res = xpath_eval($xpc, $path);
2296  //echo "1";
2297  for ($i = 0; $i < count($res->nodeset); $i++) {
2298  //echo "2";
2299  $target = $res->nodeset[$i]->get_attribute("Target");
2300  $type = $res->nodeset[$i]->get_attribute("Type");
2301  if ($target == $a_rep_import_id && $type == "RepositoryItem") {
2302  //echo "setting:"."il__".$a_rep_type."_".$a_rep_ref_id;
2303  $res->nodeset[$i]->set_attribute(
2304  "Target",
2305  "il__" . $a_rep_type . "_" . $a_rep_ref_id
2306  );
2307  }
2308  }
2309  unset($xpc);
2310  }
2311 
2317  public function handleRepositoryLinksOnCopy($a_mapping, $a_source_ref_id)
2318  {
2319  $tree = $this->tree;
2320  $objDefinition = $this->obj_definition;
2321 
2322  $this->buildDom();
2323  $this->log->debug("Handle repository links...");
2324 
2325  // resolve normal internal links
2326  $xpc = xpath_new_context($this->dom);
2327  $path = "//IntLink";
2328  $res = xpath_eval($xpc, $path);
2329  for ($i = 0; $i < count($res->nodeset); $i++) {
2330  $target = $res->nodeset[$i]->get_attribute("Target");
2331  $type = $res->nodeset[$i]->get_attribute("Type");
2332  $this->log->debug("Target: " . $target);
2333  $t = explode("_", $target);
2334  if ($type == "RepositoryItem" && ((int) $t[1] == 0 || (int) $t[1] == IL_INST_ID)) {
2335  if (isset($a_mapping[$t[3]])) {
2336  // we have a mapping -> replace the ID
2337  $this->log->debug("... replace " . $t[3] . " with " . $a_mapping[$t[3]] . ".");
2338  $res->nodeset[$i]->set_attribute(
2339  "Target",
2340  "il__obj_" . $a_mapping[$t[3]]
2341  );
2342  } elseif ($this->tree->isGrandChild($a_source_ref_id, $t[3])) {
2343  // we have no mapping, but the linked object is child of the original node -> remove link
2344  $this->log->debug("... remove links.");
2345  if ($res->nodeset[$i]->parent_node()->node_name() == "MapArea") { // simply remove map areas
2346  $parent = $res->nodeset[$i]->parent_node();
2347  $parent->unlink_node($parent);
2348  } else { // replace link by content of the link for other internal links
2349  $source_node = $res->nodeset[$i];
2350  $new_node = $source_node->clone_node(true);
2351  $new_node->unlink_node($new_node);
2352  $childs = $new_node->child_nodes();
2353  for ($j = 0; $j < count($childs); $j++) {
2354  $this->log->debug("... move node $j " . $childs[$j]->node_name() . " before " . $source_node->node_name());
2355  $source_node->insert_before($childs[$j], $source_node);
2356  }
2357  $source_node->unlink_node($source_node);
2358  }
2359  }
2360  }
2361  }
2362  unset($xpc);
2363 
2364  // resolve normal external links
2365  $ilias_url = parse_url(ILIAS_HTTP_PATH);
2366  $xpc = xpath_new_context($this->dom);
2367  $path = "//ExtLink";
2368  $res = xpath_eval($xpc, $path);
2369  for ($i = 0; $i < count($res->nodeset); $i++) {
2370  $href = $res->nodeset[$i]->get_attribute("Href");
2371  $this->log->debug("Href: " . $href);
2372 
2373  $url = parse_url($href);
2374 
2375  // only handle links on same host
2376  $this->log->debug("Host: " . $url["host"]);
2377  if ($url["host"] != "" && $url["host"] != $ilias_url["host"]) {
2378  continue;
2379  }
2380 
2381  // get parameters
2382  $par = array();
2383  foreach (explode("&", $url["query"]) as $p) {
2384  $p = explode("=", $p);
2385  $par[$p[0]] = $p[1];
2386  }
2387 
2388  $target_client_id = $par["client_id"];
2389  if ($target_client_id != "" && $target_client_id != CLIENT_ID) {
2390  continue;
2391  }
2392 
2393  // get ref id
2394  $ref_id = 0;
2395  if (is_int(strpos($href, "goto.php"))) {
2396  $t = explode("_", $par["target"]);
2397  if ($objDefinition->isRBACObject($t[0])) {
2398  $ref_id = (int) $t[1];
2399  $type = $t[0];
2400  }
2401  } elseif (is_int(strpos($href, "ilias.php"))) {
2402  $ref_id = (int) $par["ref_id"];
2403  }
2404 
2405 
2406  if ($ref_id > 0) {
2407  if (isset($a_mapping[$ref_id])) {
2408  $new_ref_id = $a_mapping[$ref_id];
2409  $new_href = "";
2410  // we have a mapping -> replace the ID
2411  if (is_int(strpos($href, "goto.php"))) {
2412  $nt = str_replace($type . "_" . $ref_id, $type . "_" . $new_ref_id, $par["target"]);
2413  $new_href = str_replace("target=" . $par["target"], "target=" . $nt, $href);
2414  } elseif (is_int(strpos($href, "ilias.php"))) {
2415  $new_href = str_replace("ref_id=" . $par["ref_id"], "ref_id=" . $new_ref_id, $href);
2416  }
2417  if ($new_href != "") {
2418  $this->log->debug("... ext link replace " . $href . " with " . $new_href . ".");
2419  $res->nodeset[$i]->set_attribute("Href", $new_href);
2420  }
2421  } elseif ($tree->isGrandChild($a_source_ref_id, $ref_id)) {
2422  // we have no mapping, but the linked object is child of the original node -> remove link
2423  $this->log->debug("... remove ext links.");
2424  if ($res->nodeset[$i]->parent_node()->node_name() == "MapArea") { // simply remove map areas
2425  $parent = $res->nodeset[$i]->parent_node();
2426  $parent->unlink_node($parent);
2427  } else { // replace link by content of the link for other internal links
2428  $source_node = $res->nodeset[$i];
2429  $new_node = $source_node->clone_node(true);
2430  $new_node->unlink_node($new_node);
2431  $childs = $new_node->child_nodes();
2432  for ($j = 0; $j < count($childs); $j++) {
2433  $this->log->debug("... move node $j " . $childs[$j]->node_name() . " before " . $source_node->node_name());
2434  $source_node->insert_before($childs[$j], $source_node);
2435  }
2436  $source_node->unlink_node($source_node);
2437  }
2438  }
2439  }
2440  }
2441  unset($xpc);
2442  }
2443 
2444 
2448  public function createFromXML()
2449  {
2450  $empty = false;
2451  if ($this->getXMLContent() == "") {
2452  $this->setXMLContent("<PageObject></PageObject>");
2453  $empty = true;
2454  }
2455 
2456  $content = $this->getXMLContent();
2457  $this->buildDom(true);
2458  $dom_doc = $this->getDomDoc();
2459 
2460  $iel = $this->containsDeactivatedElements($content);
2461  $inl = $this->containsIntLinks($content);
2462 
2463  // create object
2464  $this->db->insert("page_object", array(
2465  "page_id" => array("integer", $this->getId()),
2466  "parent_id" => array("integer", $this->getParentId()),
2467  "lang" => array("text", $this->getLanguage()),
2468  "content" => array("clob", $content),
2469  "parent_type" => array("text", $this->getParentType()),
2470  "create_user" => array("integer", $this->user->getId()),
2471  "last_change_user" => array("integer", $this->user->getId()),
2472  "active" => array("integer", (int) $this->getActive()),
2473  "activation_start" => array("timestamp", $this->getActivationStart()),
2474  "activation_end" => array("timestamp", $this->getActivationEnd()),
2475  "show_activation_info" => array("integer", (int) $this->getShowActivationInfo()),
2476  "inactive_elements" => array("integer", $iel),
2477  "int_links" => array("integer", $inl),
2478  "created" => array("timestamp", ilUtil::now()),
2479  "last_change" => array("timestamp", ilUtil::now())
2480  ));
2481 
2482  // after update event
2483  $this->__afterUpdate($dom_doc, $content, true, $empty);
2484  }
2485 
2486 
2495  public function updateFromXML()
2496  {
2497  $this->log->debug("ilPageObject, updateFromXML(): start, id: " . $this->getId());
2498 
2499  $content = $this->getXMLContent();
2500 
2501  $this->log->debug("ilPageObject, updateFromXML(): content: " . substr($content, 0, 100));
2502 
2503  $this->buildDom(true);
2504  $dom_doc = $this->getDomDoc();
2505 
2506  $iel = $this->containsDeactivatedElements($content);
2507  $inl = $this->containsIntLinks($content);
2508 
2509  $this->db->update("page_object", array(
2510  "content" => array("clob", $content),
2511  "parent_id" => array("integer", $this->getParentId()),
2512  "last_change_user" => array("integer", $this->user->getId()),
2513  "last_change" => array("timestamp", ilUtil::now()),
2514  "active" => array("integer", $this->getActive()),
2515  "activation_start" => array("timestamp", $this->getActivationStart()),
2516  "activation_end" => array("timestamp", $this->getActivationEnd()),
2517  "inactive_elements" => array("integer", $iel),
2518  "int_links" => array("integer", $inl),
2519  ), array(
2520  "page_id" => array("integer", $this->getId()),
2521  "parent_type" => array("text", $this->getParentType()),
2522  "lang" => array("text", $this->getLanguage())
2523  ));
2524 
2525  // after update event
2526  $this->__afterUpdate($dom_doc, $content);
2527 
2528  $this->log->debug("ilPageObject, updateFromXML(): end");
2529 
2530  return true;
2531  }
2532 
2539  final protected function __afterUpdate($a_domdoc, $a_xml, $a_creation = false, $a_empty = false)
2540  {
2541  // we do not need this if we are creating an empty page
2542  if (!$a_creation || !$a_empty) {
2543  // save internal link information
2544  // the page object is responsible to do this, since it "offers" the
2545  // internal link feature pc and page classes
2546  $this->saveInternalLinks($a_domdoc);
2547 
2548  // save style usage
2549  $this->saveStyleUsage($a_domdoc);
2550 
2551  // pc classes hook
2552  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2554  foreach ($defs as $def) {
2556  $cl = $def["pc_class"];
2557  call_user_func($def["pc_class"] . '::afterPageUpdate', $this, $a_domdoc, $a_xml, $a_creation);
2558  }
2559  }
2560 
2561  // call page hook
2562  $this->afterUpdate($a_domdoc, $a_xml);
2563 
2564  // call update listeners
2565  $this->callUpdateListeners();
2566  }
2567 
2574  public function afterUpdate()
2575  {
2576  }
2577 
2578 
2583  public function update($a_validate = true, $a_no_history = false)
2584  {
2585  $this->log->debug("ilPageObject, update(): start, id: " . $this->getId());
2586 
2587  $lm_set = new ilSetting("lm");
2588 
2589  // add missing pc ids
2590  if (!$this->checkPCIds()) {
2591  $this->insertPCIds();
2592  }
2593 
2594  // test validating
2595  if ($a_validate) {
2596  $errors = $this->validateDom();
2597  }
2598  //var_dump($errors); exit;
2599  if (empty($errors) && !$this->getEditLock()) {
2600  include_once("./Services/User/classes/class.ilUserUtil.php");
2601  $lock = $this->getEditLockInfo();
2602  $errors[0] = array(0 => 0,
2603  1 => "nocontent#" . $this->lng->txt("cont_not_saved_edit_lock_expired") . "<br />" .
2604  $this->lng->txt("obj_usr") . ": " .
2605  ilUserUtil::getNamePresentation($lock["edit_lock_user"]) . "<br />" .
2606  $this->lng->txt("content_until") . ": " .
2607  ilDatePresentation::formatDate(new ilDateTime($lock["edit_lock_until"], IL_CAL_UNIX))
2608  );
2609  }
2610 
2611  if (!empty($errors)) {
2612  $this->log->debug("ilPageObject, update(): errors: " . print_r($errors, true));
2613  }
2614 
2615  //echo "-".htmlentities($this->getXMLFromDom())."-"; exit;
2616  if (empty($errors)) {
2617  // @todo 1: is this page type or pc content type
2618  // related -> plugins should be able to hook in!?
2620 
2621  // get xml content
2622  $content = $this->getXMLFromDom();
2623  $dom_doc = $this->getDomDoc();
2624 
2625  // this needs to be locked
2626 
2627  // write history entry
2628  $old_set = $this->db->query("SELECT * FROM page_object WHERE " .
2629  "page_id = " . $this->db->quote($this->getId(), "integer") . " AND " .
2630  "parent_type = " . $this->db->quote($this->getParentType(), "text") . " AND " .
2631  "lang = " . $this->db->quote($this->getLanguage(), "text"));
2632  $last_nr_set = $this->db->query("SELECT max(nr) as mnr FROM page_history 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 = $this->db->fetchAssoc($last_nr_set);
2637  if ($old_rec = $this->db->fetchAssoc($old_set)) {
2638  // only save, if something has changed
2639  // added user id to the check for ilias 5.0, 7.10.2014
2640  if (($content != $old_rec["content"] || $this->user->getId() != $old_rec["last_change_user"]) &&
2641  !$a_no_history && !$this->history_saved && $lm_set->get("page_history", 1)) {
2642  if ($old_rec["content"] != "<PageObject></PageObject>") {
2643  $this->db->manipulateF(
2644  "DELETE FROM page_history WHERE " .
2645  "page_id = %s AND parent_type = %s AND hdate = %s AND lang = %s",
2646  array("integer", "text", "timestamp", "text"),
2647  array($old_rec["page_id"], $old_rec["parent_type"], $old_rec["last_change"], $old_rec["lang"])
2648  );
2649 
2650  // the following lines are a workaround for
2651  // bug 6741
2652  $last_c = $old_rec["last_change"];
2653  if ($last_c == "") {
2654  $last_c = ilUtil::now();
2655  }
2656 
2657  $this->db->insert("page_history", array(
2658  "page_id" => array("integer", $old_rec["page_id"]),
2659  "parent_type" => array("text", $old_rec["parent_type"]),
2660  "lang" => array("text", $old_rec["lang"]),
2661  "hdate" => array("timestamp", $last_c),
2662  "parent_id" => array("integer", $old_rec["parent_id"]),
2663  "content" => array("clob", $old_rec["content"]),
2664  "user_id" => array("integer", $old_rec["last_change_user"]),
2665  "ilias_version" => array("text", ILIAS_VERSION_NUMERIC),
2666  "nr" => array("integer", (int) $last_nr["mnr"] + 1)
2667  ));
2668 
2669  $old_content = $old_rec["content"];
2670  $old_domdoc = new DOMDocument();
2671  $old_nr = $last_nr["mnr"] + 1;
2672  $old_domdoc->loadXML('<?xml version="1.0" encoding="UTF-8"?>' . $old_content);
2673 
2674  // after history entry creation event
2675  $this->__afterHistoryEntry($old_domdoc, $old_content, $old_nr);
2676 
2677  $this->history_saved = true; // only save one time
2678  } else {
2679  $this->history_saved = true; // do not save on first change
2680  }
2681  }
2682  }
2683  //echo htmlentities($content);
2684  $em = (trim($content) == "<PageObject/>")
2685  ? 1
2686  : 0;
2687 
2688  // @todo: pass dom instead?
2689  $iel = $this->containsDeactivatedElements($content);
2690  $inl = $this->containsIntLinks($content);
2691 
2692  $this->db->update("page_object", array(
2693  "content" => array("clob", $content),
2694  "parent_id" => array("integer", $this->getParentId()),
2695  "last_change_user" => array("integer", $this->user->getId()),
2696  "last_change" => array("timestamp", ilUtil::now()),
2697  "is_empty" => array("integer", $em),
2698  "active" => array("integer", $this->getActive()),
2699  "activation_start" => array("timestamp", $this->getActivationStart()),
2700  "activation_end" => array("timestamp", $this->getActivationEnd()),
2701  "show_activation_info" => array("integer", $this->getShowActivationInfo()),
2702  "inactive_elements" => array("integer", $iel),
2703  "int_links" => array("integer", $inl),
2704  ), array(
2705  "page_id" => array("integer", $this->getId()),
2706  "parent_type" => array("text", $this->getParentType()),
2707  "lang" => array("text", $this->getLanguage())
2708  ));
2709 
2710  // after update event
2711  $this->__afterUpdate($dom_doc, $content);
2712 
2713  $this->log->debug("ilPageObject, update(): updated and returning true, content: " . substr($this->getXMLContent(), 0, 100));
2714 
2715  //echo "<br>PageObject::update:".htmlentities($this->getXMLContent()).":";
2716  return true;
2717  } else {
2718  return $errors;
2719  }
2720  }
2721 
2722 
2723 
2727  public function delete()
2728  {
2729  $copg_logger = ilLoggerFactory::getLogger('copg');
2730  $copg_logger->debug(
2731  "ilPageObject: Delete called for ID '" . $this->getId() . "'," .
2732  " parent type: '" . $this->getParentType() . "', " .
2733  " hist nr: '" . $this->old_nr . "', " .
2734  " lang: '" . $this->getLanguage() . "', "
2735  );
2736 
2737  $mobs = array();
2738  $files = array();
2739 
2740  if (!$this->page_not_found) {
2741  $this->buildDom();
2742  $mobs = $this->collectMediaObjects(false);
2743  }
2744  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2745  $mobs2 = ilObjMediaObject::_getMobsOfObject($this->getParentType() . ":pg", $this->getId(), false);
2746  foreach ($mobs2 as $m) {
2747  if (!in_array($m, $mobs)) {
2748  $mobs[] = $m;
2749  }
2750  }
2751 
2752  $copg_logger->debug("ilPageObject: ... found " . count($mobs) . " media objects.");
2753 
2754  $this->__beforeDelete();
2755 
2756  // treat plugged content
2757  $this->handleDeleteContent();
2758 
2759  // delete style usages
2760  $this->deleteStyleUsages(false);
2761 
2762  // delete internal links
2763  $this->deleteInternalLinks();
2764 
2765  // delete all mob usages
2766  ilObjMediaObject::_deleteAllUsages($this->getParentType() . ":pg", $this->getId());
2767 
2768  // delete news
2769  include_once("./Services/News/classes/class.ilNewsItem.php");
2771  $this->getParentId(),
2772  $this->getParentType(),
2773  $this->getId(),
2774  "pg"
2775  );
2776 
2777  // delete page_object entry
2778  $this->db->manipulate("DELETE FROM page_object " .
2779  "WHERE page_id = " . $this->db->quote($this->getId(), "integer") .
2780  " AND parent_type= " . $this->db->quote($this->getParentType(), "text"));
2781 
2782  // delete media objects
2783  foreach ($mobs as $mob_id) {
2784  $copg_logger->debug("ilPageObject: ... processing mob " . $mob_id . ".");
2785 
2786  if (ilObject::_lookupType($mob_id) != 'mob') {
2787  $copg_logger->debug("ilPageObject: ... type mismatch. Ignoring mob " . $mob_id . ".");
2788  continue;
2789  }
2790 
2791  if (ilObject::_exists($mob_id)) {
2792  $copg_logger->debug("ilPageObject: ... delete mob " . $mob_id . ".");
2793 
2794  $mob_obj = new ilObjMediaObject($mob_id);
2795  $mob_obj->delete();
2796  } else {
2797  $copg_logger->debug("ilPageObject: ... missing mob " . $mob_id . ".");
2798  }
2799  }
2800  }
2801 
2807  final protected function __beforeDelete()
2808  {
2809  // pc classes hook
2810  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2812  foreach ($defs as $def) {
2814  $cl = $def["pc_class"];
2815  call_user_func($def["pc_class"] . '::beforePageDelete', $this);
2816  }
2817  }
2818 
2824  final protected function __afterHistoryEntry($a_old_domdoc, $a_old_content, $a_old_nr)
2825  {
2826  // save style usage
2827  $this->saveStyleUsage($a_old_domdoc, $a_old_nr);
2828 
2829  // pc classes hook
2830  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2832  foreach ($defs as $def) {
2834  $cl = $def["pc_class"];
2835  call_user_func($def["pc_class"] . '::afterPageHistoryEntry', $this, $a_old_domdoc, $a_old_content, $a_old_nr);
2836  }
2837  }
2838 
2844  public function saveStyleUsage($a_domdoc, $a_old_nr = 0)
2845  {
2846  // media aliases
2847  $xpath = new DOMXPath($a_domdoc);
2848  $path = "//Paragraph | //Section | //MediaAlias | //FileItem" .
2849  " | //Table | //TableData | //Tabs | //List";
2850  $nodes = $xpath->query($path);
2851  $usages = array();
2852  foreach ($nodes as $node) {
2853  switch ($node->localName) {
2854  case "Paragraph":
2855  $sname = $node->getAttribute("Characteristic");
2856  $stype = "text_block";
2857  $template = 0;
2858  break;
2859 
2860  case "Section":
2861  $sname = $node->getAttribute("Characteristic");
2862  $stype = "section";
2863  $template = 0;
2864  break;
2865 
2866  case "MediaAlias":
2867  $sname = $node->getAttribute("Class");
2868  $stype = "media_cont";
2869  $template = 0;
2870  break;
2871 
2872  case "FileItem":
2873  $sname = $node->getAttribute("Class");
2874  $stype = "flist_li";
2875  $template = 0;
2876  break;
2877 
2878  case "Table":
2879  $sname = $node->getAttribute("Template");
2880  if ($sname == "") {
2881  $sname = $node->getAttribute("Class");
2882  $stype = "table";
2883  $template = 0;
2884  } else {
2885  $stype = "table";
2886  $template = 1;
2887  }
2888  break;
2889 
2890  case "TableData":
2891  $sname = $node->getAttribute("Class");
2892  $stype = "table_cell";
2893  $template = 0;
2894  break;
2895 
2896  case "Tabs":
2897  $sname = $node->getAttribute("Template");
2898  if ($sname != "") {
2899  if ($node->getAttribute("Type") == "HorizontalAccordion") {
2900  $stype = "haccordion";
2901  }
2902  if ($node->getAttribute("Type") == "VerticalAccordion") {
2903  $stype = "vaccordion";
2904  }
2905  }
2906  $template = 1;
2907  break;
2908 
2909  case "List":
2910  $sname = $node->getAttribute("Class");
2911  if ($node->getAttribute("Type") == "Ordered") {
2912  $stype = "list_o";
2913  } else {
2914  $stype = "list_u";
2915  }
2916  $template = 0;
2917  break;
2918  }
2919  if ($sname != "" && $stype != "") {
2920  $usages[$sname . ":" . $stype . ":" . $template] = array("sname" => $sname,
2921  "stype" => $stype, "template" => $template);
2922  }
2923  }
2924 
2925 
2926  $this->deleteStyleUsages($a_old_nr);
2927 
2928  foreach ($usages as $u) {
2929  $id = $this->db->nextId('page_style_usage');
2930 
2931  $this->db->manipulate("INSERT INTO page_style_usage " .
2932  "(id, page_id, page_type, page_lang, page_nr, template, stype, sname) VALUES (" .
2933  $this->db->quote($id, "integer") . "," .
2934  $this->db->quote($this->getId(), "integer") . "," .
2935  $this->db->quote($this->getParentType(), "text") . "," .
2936  $this->db->quote($this->getLanguage(), "text") . "," .
2937  $this->db->quote($a_old_nr, "integer") . "," .
2938  $this->db->quote($u["template"], "integer") . "," .
2939  $this->db->quote($u["stype"], "text") . "," .
2940  $this->db->quote($u["sname"], "text") .
2941  ")");
2942  }
2943  }
2944 
2951  public function deleteStyleUsages($a_old_nr = 0)
2952  {
2953  if ($a_old_nr !== false) {
2954  $and_old_nr = " AND page_nr = " . $this->db->quote($a_old_nr, "integer");
2955  }
2956 
2957  $this->db->manipulate(
2958  "DELETE FROM page_style_usage WHERE " .
2959  " page_id = " . $this->db->quote($this->getId(), "integer") .
2960  " AND page_type = " . $this->db->quote($this->getParentType(), "text") .
2961  " AND page_lang = " . $this->db->quote($this->getLanguage(), "text") .
2962  $and_old_nr
2963  );
2964  }
2965 
2966 
2971  // @todo: move to content include class
2973  {
2974  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2975  include_once("./Modules/File/classes/class.ilObjFile.php");
2977  $this->getParentType() . ":pg",
2978  $this->getId()
2979  );
2981  $this->getParentType() . ":pg",
2982  $this->getId()
2983  );
2984  $objs = array_merge($mobs, $files);
2985  return ilObject::_getLastUpdateOfObjects($objs);
2986  }
2987 
2994  public function deleteInternalLinks()
2995  {
2996  include_once("./Services/Link/classes/class.ilInternalLink.php");
2998  $this->getParentType() . ":pg",
2999  $this->getId(),
3000  $this->getLanguage()
3001  );
3002  }
3003 
3004 
3010  // @todo: move to specific classes, internal link use info
3011  public function saveInternalLinks($a_domdoc)
3012  {
3013  $this->deleteInternalLinks();
3014 
3015  // query IntLink elements
3016  $xpath = new DOMXPath($a_domdoc);
3017  $nodes = $xpath->query('//IntLink');
3018  foreach ($nodes as $node) {
3019  $link_type = $node->getAttribute("Type");
3020 
3021  switch ($link_type) {
3022  case "StructureObject":
3023  $t_type = "st";
3024  break;
3025 
3026  case "PageObject":
3027  $t_type = "pg";
3028  break;
3029 
3030  case "GlossaryItem":
3031  $t_type = "git";
3032  break;
3033 
3034  case "MediaObject":
3035  $t_type = "mob";
3036  break;
3037 
3038  case "RepositoryItem":
3039  $t_type = "obj";
3040  break;
3041 
3042  case "File":
3043  $t_type = "file";
3044  break;
3045 
3046  case "WikiPage":
3047  $t_type = "wpage";
3048  break;
3049 
3050  case "PortfolioPage":
3051  $t_type = "ppage";
3052  break;
3053 
3054  case "User":
3055  $t_type = "user";
3056  break;
3057  }
3058 
3059  $target = $node->getAttribute("Target");
3060  $target_arr = explode("_", $target);
3061  $t_id = $target_arr[count($target_arr) - 1];
3062 
3063  // link to other internal object
3064  if (is_int(strpos($target, "__"))) {
3065  $t_inst = 0;
3066  } else { // link to unresolved object in other installation
3067  $t_inst = $target_arr[1];
3068  }
3069 
3070  if ($t_id > 0) {
3072  $this->getParentType() . ":pg",
3073  $this->getId(),
3074  $t_type,
3075  $t_id,
3076  $t_inst,
3077  $this->getLanguage()
3078  );
3079  }
3080  }
3081  }
3082 
3086  public function create()
3087  {
3088  $this->createFromXML();
3089  }
3090 
3098  public function deleteContent($a_hid, $a_update = true, $a_pcid = "")
3099  {
3100  $curr_node = $this->getContentNode($a_hid, $a_pcid);
3101  $this->handleDeleteContent($curr_node);
3102  $curr_node->unlink_node($curr_node);
3103  if ($a_update) {
3104  return $this->update();
3105  }
3106  }
3107 
3108 
3116  public function deleteContents($a_hids, $a_update = true, $a_self_ass = false)
3117  {
3118  if (!is_array($a_hids)) {
3119  return;
3120  }
3121  foreach ($a_hids as $a_hid) {
3122  $a_hid = explode(":", $a_hid);
3123  //echo "-".$a_hid[0]."-".$a_hid[1]."-";
3124 
3125  // @todo 1: hook
3126  // do not delete question nodes in assessment pages
3127  if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass) {
3128  $curr_node = $this->getContentNode($a_hid[0], $a_hid[1]);
3129  if (is_object($curr_node)) {
3130  $parent_node = $curr_node->parent_node();
3131  if ($parent_node->node_name() != "TableRow") {
3132  $this->handleDeleteContent($curr_node);
3133  $curr_node->unlink_node($curr_node);
3134  }
3135  }
3136  }
3137  }
3138  if ($a_update) {
3139  return $this->update();
3140  }
3141  }
3142 
3148  public function cutContents($a_hids)
3149  {
3150  $this->copyContents($a_hids);
3151  return $this->deleteContents($a_hids, true, $this->getPageConfig()->getEnableSelfAssessment());
3152  }
3153 
3159  public function copyContents($a_hids)
3160  {
3161  $user = $this->user;
3162 
3163  if (!is_array($a_hids)) {
3164  return;
3165  }
3166 
3167  $time = date("Y-m-d H:i:s", time());
3168 
3169  $hier_ids = array();
3170  $skip = array();
3171  foreach ($a_hids as $a_hid) {
3172  if ($a_hid == "") {
3173  continue;
3174  }
3175  $a_hid = explode(":", $a_hid);
3176 
3177  // check, whether new hid is child of existing one or vice versa
3178  reset($hier_ids);
3179  foreach ($hier_ids as $h) {
3180  if ($h . "_" == substr($a_hid[0], 0, strlen($h) + 1)) {
3181  $skip[] = $a_hid[0];
3182  }
3183  if ($a_hid[0] . "_" == substr($h, 0, strlen($a_hid[0]) + 1)) {
3184  $skip[] = $h;
3185  }
3186  }
3187  $pc_id[$a_hid[0]] = $a_hid[1];
3188  if ($a_hid[0] != "") {
3189  $hier_ids[$a_hid[0]] = $a_hid[0];
3190  }
3191  }
3192  foreach ($skip as $s) {
3193  unset($hier_ids[$s]);
3194  }
3195  include_once("./Services/COPage/classes/class.ilPageContent.php");
3196  $hier_ids = ilPageContent::sortHierIds($hier_ids);
3197  $nr = 1;
3198  foreach ($hier_ids as $hid) {
3199  $curr_node = $this->getContentNode($hid, $pc_id[$hid]);
3200  if (is_object($curr_node)) {
3201  if ($curr_node->node_name() == "PageContent") {
3202  $content = $this->dom->dump_node($curr_node);
3203  // remove pc and hier ids
3204  $content = preg_replace('/PCID=\"[a-z0-9]*\"/i', "", $content);
3205  $content = preg_replace('/HierId=\"[a-z0-9_]*\"/i', "", $content);
3206 
3207  $user->addToPCClipboard($content, $time, $nr);
3208  $nr++;
3209  }
3210  }
3211  }
3212  include_once("./Modules/LearningModule/classes/class.ilEditClipboard.php");
3214  }
3215 
3219  public function pasteContents($a_hier_id, $a_self_ass = false)
3220  {
3221  $user = $this->user;
3222 
3223  $a_hid = explode(":", $a_hier_id);
3224  $content = $user->getPCClipboardContent();
3225 
3226  // we insert from last to first, because we insert all at the
3227  // same hier_id
3228  for ($i = count($content) - 1; $i >= 0; $i--) {
3229  $c = $content[$i];
3230  $temp_dom = domxml_open_mem(
3231  '<?xml version="1.0" encoding="UTF-8"?>' . $c,
3233  $error
3234  );
3235  if (empty($error)) {
3236  $this->handleCopiedContent($temp_dom, $a_self_ass);
3237  $xpc = xpath_new_context($temp_dom);
3238  $path = "//PageContent";
3239  $res = xpath_eval($xpc, $path);
3240  if (count($res->nodeset) > 0) {
3241  $new_pc_node = $res->nodeset[0];
3242  $cloned_pc_node = $new_pc_node->clone_node(true);
3243  $cloned_pc_node->unlink_node($cloned_pc_node);
3244  $this->insertContentNode(
3245  $cloned_pc_node,
3246  $a_hid[0],
3248  $a_hid[1]
3249  );
3250  }
3251  } else {
3252  //var_dump($error);
3253  }
3254  }
3255  $e = $this->update();
3256  //var_dump($e);
3257  }
3258 
3262  public function switchEnableMultiple($a_hids, $a_update = true, $a_self_ass = false)
3263  {
3264  if (!is_array($a_hids)) {
3265  return;
3266  }
3267  $obj = &$this->content_obj;
3268 
3269  foreach ($a_hids as $a_hid) {
3270  $a_hid = explode(":", $a_hid);
3271  $curr_node = $this->getContentNode($a_hid[0], $a_hid[1]);
3272  if (is_object($curr_node)) {
3273  if ($curr_node->node_name() == "PageContent") {
3274  $cont_obj = $this->getContentObject($a_hid[0], $a_hid[1]);
3275  if ($cont_obj->isEnabled()) {
3276  // do not deactivate question nodes in assessment pages
3277  if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass) {
3278  $cont_obj->disable();
3279  }
3280  } else {
3281  $cont_obj->enable();
3282  }
3283  }
3284  }
3285  }
3286 
3287  if ($a_update) {
3288  return $this->update();
3289  }
3290  }
3291 
3292 
3300  public function deleteContentFromHierId($a_hid, $a_update = true)
3301  {
3302  $hier_ids = $this->getHierIds();
3303 
3304  // iterate all hierarchical ids
3305  foreach ($hier_ids as $hier_id) {
3306  // delete top level nodes only
3307  if (!is_int(strpos($hier_id, "_"))) {
3308  if ($hier_id != "pg" && $hier_id >= $a_hid) {
3309  $curr_node = $this->getContentNode($hier_id);
3310  $this->handleDeleteContent($curr_node);
3311  $curr_node->unlink_node($curr_node);
3312  }
3313  }
3314  }
3315  if ($a_update) {
3316  return $this->update();
3317  }
3318  }
3319 
3327  public function deleteContentBeforeHierId($a_hid, $a_update = true)
3328  {
3329  $hier_ids = $this->getHierIds();
3330 
3331  // iterate all hierarchical ids
3332  foreach ($hier_ids as $hier_id) {
3333  // delete top level nodes only
3334  if (!is_int(strpos($hier_id, "_"))) {
3335  if ($hier_id != "pg" && $hier_id < $a_hid) {
3336  $curr_node = $this->getContentNode($hier_id);
3337  $this->handleDeleteContent($curr_node);
3338  $curr_node->unlink_node($curr_node);
3339  }
3340  }
3341  }
3342  if ($a_update) {
3343  return $this->update();
3344  }
3345  }
3346 
3347 
3355  public static function _moveContentAfterHierId(&$a_source_page, &$a_target_page, $a_hid)
3356  {
3357  $hier_ids = $a_source_page->getHierIds();
3358 
3359  $copy_ids = array();
3360 
3361  // iterate all hierarchical ids
3362  foreach ($hier_ids as $hier_id) {
3363  // move top level nodes only
3364  if (!is_int(strpos($hier_id, "_"))) {
3365  if ($hier_id != "pg" && $hier_id >= $a_hid) {
3366  $copy_ids[] = $hier_id;
3367  }
3368  }
3369  }
3370  asort($copy_ids);
3371 
3372  $parent_node = $a_target_page->getContentNode("pg");
3373  $target_dom = $a_target_page->getDom();
3374  $parent_childs = $parent_node->child_nodes();
3375  $cnt_parent_childs = count($parent_childs);
3376  //echo "-$cnt_parent_childs-";
3377  $first_child = $parent_childs[0];
3378  foreach ($copy_ids as $copy_id) {
3379  $source_node = $a_source_page->getContentNode($copy_id);
3380 
3381  $new_node = $source_node->clone_node(true);
3382  $new_node->unlink_node($new_node);
3383 
3384  $source_node->unlink_node($source_node);
3385 
3386  if ($cnt_parent_childs == 0) {
3387  $new_node = $parent_node->append_child($new_node);
3388  } else {
3389  //$target_dom->import_node($new_node);
3390  $new_node = $first_child->insert_before($new_node, $first_child);
3391  }
3392  $parent_childs = $parent_node->child_nodes();
3393 
3394  //$cnt_parent_childs++;
3395  }
3396 
3397  $a_target_page->update();
3398  $a_source_page->update();
3399  }
3400 
3404  public function insertContent(&$a_cont_obj, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "")
3405  {
3406  //echo "-".$a_pos."-".$a_pcid."-";
3407  // move mode into container elements is always INSERT_CHILD
3408  $curr_node = $this->getContentNode($a_pos, $a_pcid);
3409  $curr_name = $curr_node->node_name();
3410 
3411  // @todo: try to generalize this
3412  if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3413  ($curr_name == "ListItem") || ($curr_name == "Section")
3414  || ($curr_name == "Tab") || ($curr_name == "ContentPopup")
3415  || ($curr_name == "GridCell")) {
3416  $a_mode = IL_INSERT_CHILD;
3417  }
3418 
3419  $hid = $curr_node->get_attribute("HierId");
3420  if ($hid != "") {
3421  //echo "-".$a_pos."-".$hid."-";
3422  $a_pos = $hid;
3423  }
3424 
3425  if ($a_mode != IL_INSERT_CHILD) { // determine parent hierarchical id
3426  // of sibling at $a_pos
3427  $pos = explode("_", $a_pos);
3428  $target_pos = array_pop($pos);
3429  $parent_pos = implode($pos, "_");
3430  } else { // if we should insert a child, $a_pos is alreade the hierarchical id
3431  // of the parent node
3432  $parent_pos = $a_pos;
3433  }
3434 
3435  // get the parent node
3436  if ($parent_pos != "") {
3437  $parent_node = $this->getContentNode($parent_pos);
3438  } else {
3439  $parent_node = $this->getNode();
3440  }
3441 
3442  // count the parent children
3443  $parent_childs = $parent_node->child_nodes();
3444  $cnt_parent_childs = count($parent_childs);
3445  //echo "ZZ$a_mode";
3446  switch ($a_mode) {
3447  // insert new node after sibling at $a_pos
3448  case IL_INSERT_AFTER:
3449  $new_node = $a_cont_obj->getNode();
3450  //$a_pos = ilPageContent::incEdId($a_pos);
3451  //$curr_node = $this->getContentNode($a_pos);
3452 //echo "behind $a_pos:";
3453  if ($succ_node = $curr_node->next_sibling()) {
3454  $new_node = $succ_node->insert_before($new_node, $succ_node);
3455  } else {
3456  //echo "movin doin append_child";
3457  $new_node = $parent_node->append_child($new_node);
3458  }
3459  $a_cont_obj->setNode($new_node);
3460  break;
3461 
3462  case IL_INSERT_BEFORE:
3463 //echo "INSERT_BEF";
3464  $new_node = $a_cont_obj->getNode();
3465  $succ_node = $this->getContentNode($a_pos);
3466  $new_node = $succ_node->insert_before($new_node, $succ_node);
3467  $a_cont_obj->setNode($new_node);
3468  break;
3469 
3470  // insert new node as first child of parent $a_pos (= $a_parent)
3471  case IL_INSERT_CHILD:
3472 //echo "insert as child:parent_childs:$cnt_parent_childs:<br>";
3473  $new_node = $a_cont_obj->getNode();
3474  if ($cnt_parent_childs == 0) {
3475  $new_node = $parent_node->append_child($new_node);
3476  } else {
3477  $new_node = $parent_childs[0]->insert_before($new_node, $parent_childs[0]);
3478  }
3479  $a_cont_obj->setNode($new_node);
3480 //echo "PP";
3481  break;
3482  }
3483 
3484  //check for PlaceHolder to remove in EditMode-keep in Layout Mode
3485  if (!$this->getPageConfig()->getEnablePCType("PlaceHolder")) {
3486  $sub_nodes = $curr_node->child_nodes() ;
3487  foreach ($sub_nodes as $sub_node) {
3488  if ($sub_node->node_name() == "PlaceHolder") {
3489  $curr_node->unlink_node();
3490  }
3491  }
3492  }
3493  }
3494 
3498  public function insertContentNode(&$a_cont_node, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "")
3499  {
3500  // move mode into container elements is always INSERT_CHILD
3501  $curr_node = $this->getContentNode($a_pos, $a_pcid);
3502  $curr_name = $curr_node->node_name();
3503 
3504  // @todo: try to generalize
3505  if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3506  ($curr_name == "ListItem") || ($curr_name == "Section")
3507  || ($curr_name == "Tab") || ($curr_name == "ContentPopup")
3508  || ($curr_name == "GridCell")) {
3509  $a_mode = IL_INSERT_CHILD;
3510  }
3511 
3512  $hid = $curr_node->get_attribute("HierId");
3513  if ($hid != "") {
3514  $a_pos = $hid;
3515  }
3516 
3517  if ($a_mode != IL_INSERT_CHILD) { // determine parent hierarchical id
3518  // of sibling at $a_pos
3519  $pos = explode("_", $a_pos);
3520  $target_pos = array_pop($pos);
3521  $parent_pos = implode($pos, "_");
3522  } else { // if we should insert a child, $a_pos is alreade the hierarchical id
3523  // of the parent node
3524  $parent_pos = $a_pos;
3525  }
3526 
3527  // get the parent node
3528  if ($parent_pos != "") {
3529  $parent_node = $this->getContentNode($parent_pos);
3530  } else {
3531  $parent_node = $this->getNode();
3532  }
3533 
3534  // count the parent children
3535  $parent_childs = $parent_node->child_nodes();
3536  $cnt_parent_childs = count($parent_childs);
3537 
3538  switch ($a_mode) {
3539  // insert new node after sibling at $a_pos
3540  case IL_INSERT_AFTER:
3541  //$new_node = $a_cont_obj->getNode();
3542  if ($succ_node = $curr_node->next_sibling()) {
3543  $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3544  } else {
3545  $a_cont_node = $parent_node->append_child($a_cont_node);
3546  }
3547  //$a_cont_obj->setNode($new_node);
3548  break;
3549 
3550  case IL_INSERT_BEFORE:
3551  //$new_node = $a_cont_obj->getNode();
3552  $succ_node = $this->getContentNode($a_pos);
3553  $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3554  //$a_cont_obj->setNode($new_node);
3555  break;
3556 
3557  // insert new node as first child of parent $a_pos (= $a_parent)
3558  case IL_INSERT_CHILD:
3559  //$new_node = $a_cont_obj->getNode();
3560  if ($cnt_parent_childs == 0) {
3561  $a_cont_node = $parent_node->append_child($a_cont_node);
3562  } else {
3563  $a_cont_node = $parent_childs[0]->insert_before($a_cont_node, $parent_childs[0]);
3564  }
3565  //$a_cont_obj->setNode($new_node);
3566  break;
3567  }
3568  }
3569 
3574  public function moveContentBefore($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3575  {
3576  if ($a_source == $a_target) {
3577  return;
3578  }
3579 
3580  // clone the node
3581  $content = $this->getContentObject($a_source, $a_spcid);
3582  $source_node = $content->getNode();
3583  $clone_node = $source_node->clone_node(true);
3584 
3585  // delete source node
3586  $this->deleteContent($a_source, false, $a_spcid);
3587 
3588  // insert cloned node at target
3589  $content->setNode($clone_node);
3590  $this->insertContent($content, $a_target, IL_INSERT_BEFORE, $a_tpcid);
3591  return $this->update();
3592  }
3593 
3598  public function moveContentAfter($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3599  {
3600  if ($a_source == $a_target) {
3601  return;
3602  }
3603 
3604  // clone the node
3605  $content = $this->getContentObject($a_source, $a_spcid);
3606  $source_node = $content->getNode();
3607  $clone_node = $source_node->clone_node(true);
3608 
3609  // delete source node
3610  $this->deleteContent($a_source, false, $a_spcid);
3611 
3612  // insert cloned node at target
3613  $content->setNode($clone_node);
3614  $this->insertContent($content, $a_target, IL_INSERT_AFTER, $a_tpcid);
3615  return $this->update();
3616  }
3617 
3621  // @todo: move to paragraph
3622  public function bbCode2XML(&$a_content)
3623  {
3624  $a_content = preg_replace('/\[com\]/i', "<Comment>", $a_content);
3625  $a_content = preg_replace('/\[\/com\]/i', "</Comment>", $a_content);
3626  $a_content = preg_replace('/\[emp]/i', "<Emph>", $a_content);
3627  $a_content = preg_replace('/\[\/emp\]/i', "</Emph>", $a_content);
3628  $a_content = preg_replace('/\[str]/i', "<Strong>", $a_content);
3629  $a_content = preg_replace('/\[\/str\]/i', "</Strong>", $a_content);
3630  }
3631 
3636  public function insertInstIntoIDs($a_inst, $a_res_ref_to_obj_id = true)
3637  {
3638  // insert inst id into internal links
3639  $xpc = xpath_new_context($this->dom);
3640  $path = "//IntLink";
3641  $res = xpath_eval($xpc, $path);
3642  for ($i = 0; $i < count($res->nodeset); $i++) {
3643  $target = $res->nodeset[$i]->get_attribute("Target");
3644  $type = $res->nodeset[$i]->get_attribute("Type");
3645 
3646  if (substr($target, 0, 4) == "il__") {
3647  $id = substr($target, 4, strlen($target) - 4);
3648 
3649  // convert repository links obj_<ref_id> to <type>_<obj_id>
3650  // this leads to bug 6685.
3651  if ($a_res_ref_to_obj_id && $type == "RepositoryItem") {
3652  $id_arr = explode("_", $id);
3653 
3654  // changed due to bug 6685
3655  $ref_id = $id_arr[1];
3656  $obj_id = ilObject::_lookupObjId($id_arr[1]);
3657 
3658  $otype = ilObject::_lookupType($obj_id);
3659  if ($obj_id > 0) {
3660  // changed due to bug 6685
3661  // the ref_id should be used, if the content is
3662  // imported on the same installation
3663  // the obj_id should be used, if a different
3664  // installation imports, but has an import_id for
3665  // the object id.
3666  $id = $otype . "_" . $obj_id . "_" . $ref_id;
3667  //$id = $otype."_".$ref_id;
3668  }
3669  }
3670  $new_target = "il_" . $a_inst . "_" . $id;
3671  $res->nodeset[$i]->set_attribute("Target", $new_target);
3672  }
3673  }
3674  unset($xpc);
3675 
3676  // @todo: move to media/fileitems/questions, ...
3677 
3678  // insert inst id into media aliases
3679  $xpc = xpath_new_context($this->dom);
3680  $path = "//MediaAlias";
3681  $res = xpath_eval($xpc, $path);
3682  for ($i = 0; $i < count($res->nodeset); $i++) {
3683  $origin_id = $res->nodeset[$i]->get_attribute("OriginId");
3684  if (substr($origin_id, 0, 4) == "il__") {
3685  $new_id = "il_" . $a_inst . "_" . substr($origin_id, 4, strlen($origin_id) - 4);
3686  $res->nodeset[$i]->set_attribute("OriginId", $new_id);
3687  }
3688  }
3689  unset($xpc);
3690 
3691  // insert inst id file item identifier entries
3692  $xpc = xpath_new_context($this->dom);
3693  $path = "//FileItem/Identifier";
3694  $res = xpath_eval($xpc, $path);
3695  for ($i = 0; $i < count($res->nodeset); $i++) {
3696  $origin_id = $res->nodeset[$i]->get_attribute("Entry");
3697  if (substr($origin_id, 0, 4) == "il__") {
3698  $new_id = "il_" . $a_inst . "_" . substr($origin_id, 4, strlen($origin_id) - 4);
3699  $res->nodeset[$i]->set_attribute("Entry", $new_id);
3700  }
3701  }
3702  unset($xpc);
3703 
3704  // insert inst id into question references
3705  $xpc = xpath_new_context($this->dom);
3706  $path = "//Question";
3707  $res = xpath_eval($xpc, $path);
3708  for ($i = 0; $i < count($res->nodeset); $i++) {
3709  $qref = $res->nodeset[$i]->get_attribute("QRef");
3710  //echo "<br>setted:".$qref;
3711  if (substr($qref, 0, 4) == "il__") {
3712  $new_id = "il_" . $a_inst . "_" . substr($qref, 4, strlen($qref) - 4);
3713  //echo "<br>setting:".$new_id;
3714  $res->nodeset[$i]->set_attribute("QRef", $new_id);
3715  }
3716  }
3717  unset($xpc);
3718 
3719  // insert inst id into content snippets
3720  $xpc = xpath_new_context($this->dom);
3721  $path = "//ContentInclude";
3722  $res = xpath_eval($xpc, $path);
3723  for ($i = 0; $i < count($res->nodeset); $i++) {
3724  $ci = $res->nodeset[$i]->get_attribute("InstId");
3725  if ($ci == "") {
3726  $res->nodeset[$i]->set_attribute("InstId", $a_inst);
3727  }
3728  }
3729  unset($xpc);
3730  }
3731 
3735  public function checkPCIds()
3736  {
3737  $this->builddom();
3738  $mydom = $this->dom;
3739 
3740  $sep = $path = "";
3741  foreach ($this->id_elements as $el) {
3742  $path .= $sep . "//" . $el . "[not(@PCID)]";
3743  $sep = " | ";
3744  $path .= $sep . "//" . $el . "[@PCID='']";
3745  }
3746 
3747  $xpc = xpath_new_context($mydom);
3748  $res = &xpath_eval($xpc, $path);
3749 
3750  if (count($res->nodeset) > 0) {
3751  return false;
3752  }
3753  return true;
3754  }
3755 
3762  public function getAllPCIds()
3763  {
3764  $this->builddom();
3765  $mydom = $this->dom;
3766 
3767  $pcids = array();
3768 
3769  $sep = $path = "";
3770  foreach ($this->id_elements as $el) {
3771  $path .= $sep . "//" . $el . "[@PCID]";
3772  $sep = " | ";
3773  }
3774 
3775  // get existing ids
3776  $xpc = xpath_new_context($mydom);
3777  $res = &xpath_eval($xpc, $path);
3778 
3779  for ($i = 0; $i < count($res->nodeset); $i++) {
3780  $node = $res->nodeset[$i];
3781  $pcids[] = $node->get_attribute("PCID");
3782  }
3783  return $pcids;
3784  }
3785 
3792  public function existsPCId($a_pc_id)
3793  {
3794  $this->builddom();
3795  $mydom = $this->dom;
3796 
3797  $pcids = array();
3798 
3799  $sep = $path = "";
3800  foreach ($this->id_elements as $el) {
3801  $path .= $sep . "//" . $el . "[@PCID='" . $a_pc_id . "']";
3802  $sep = " | ";
3803  }
3804 
3805  // get existing ids
3806  $xpc = xpath_new_context($mydom);
3807  $res = &xpath_eval($xpc, $path);
3808  return (count($res->nodeset) > 0);
3809  }
3810 
3817  public function generatePcId($a_pc_ids = false)
3818  {
3819  if ($a_pc_ids === false) {
3820  $a_pc_ids = $this->getAllPCIds();
3821  }
3822  $id = ilUtil::randomHash(10, $a_pc_ids);
3823  return $id;
3824  }
3825 
3826 
3830  public function insertPCIds()
3831  {
3832  $this->builddom();
3833  $mydom = $this->dom;
3834 
3835  $pcids = $this->getAllPCIds();
3836 
3837  // add missing ones
3838  $sep = $path = "";
3839  foreach ($this->id_elements as $el) {
3840  $path .= $sep . "//" . $el . "[not(@PCID)]";
3841  $sep = " | ";
3842  $path .= $sep . "//" . $el . "[@PCID='']";
3843  $sep = " | ";
3844  }
3845  $xpc = xpath_new_context($mydom);
3846  $res = &xpath_eval($xpc, $path);
3847 
3848  for ($i = 0; $i < count($res->nodeset); $i++) {
3849  $node = $res->nodeset[$i];
3850  $id = ilUtil::randomHash(10, $pcids);
3851  $pcids[] = $id;
3852  //echo "setting-".$id."-";
3853  $res->nodeset[$i]->set_attribute("PCID", $id);
3854  }
3855  }
3856 
3860  public function getPageContentsHashes()
3861  {
3862  $this->builddom();
3863  $this->addHierIds();
3864  $mydom = $this->dom;
3865 
3866  // get existing ids
3867  $path = "//PageContent";
3868  $xpc = xpath_new_context($mydom);
3869  $res = &xpath_eval($xpc, $path);
3870 
3871  $hashes = array();
3872  require_once("./Services/COPage/classes/class.ilPCParagraph.php");
3873  for ($i = 0; $i < count($res->nodeset); $i++) {
3874  $hier_id = $res->nodeset[$i]->get_attribute("HierId");
3875  $pc_id = $res->nodeset[$i]->get_attribute("PCID");
3876  $dump = $mydom->dump_node($res->nodeset[$i]);
3877  if (($hpos = strpos($dump, ' HierId="' . $hier_id . '"')) > 0) {
3878  $dump = substr($dump, 0, $hpos) .
3879  substr($dump, $hpos + strlen(' HierId="' . $hier_id . '"'));
3880  }
3881 
3882  $childs = $res->nodeset[$i]->child_nodes();
3883  $content = "";
3884  if ($childs[0] && $childs[0]->node_name() == "Paragraph") {
3885  $content = $mydom->dump_node($childs[0]);
3886  $content = substr(
3887  $content,
3888  strpos($content, ">") + 1,
3889  strrpos($content, "<") - (strpos($content, ">") + 1)
3890  );
3891  //var_dump($content);
3892  $content = ilPCParagraph::xml2output($content);
3893  //var_dump($content);
3894  }
3895  //$hashes[$hier_id] =
3896  // array("PCID" => $pc_id, "hash" => md5($dump));
3897  $hashes[$pc_id] =
3898  array("hier_id" => $hier_id, "hash" => md5($dump), "content" => $content);
3899  }
3900 
3901  return $hashes;
3902  }
3903 
3907  // @todo: move to questions
3908  public function getQuestionIds()
3909  {
3910  $this->builddom();
3911  $mydom = $this->dom;
3912 
3913  // Get question IDs
3914  $path = "//Question";
3915  $xpc = xpath_new_context($mydom);
3916  $res = &xpath_eval($xpc, $path);
3917 
3918  $q_ids = array();
3919  include_once("./Services/Link/classes/class.ilInternalLink.php");
3920  for ($i = 0; $i < count($res->nodeset); $i++) {
3921  $qref = $res->nodeset[$i]->get_attribute("QRef");
3922 
3923  $inst_id = ilInternalLink::_extractInstOfTarget($qref);
3924  $obj_id = ilInternalLink::_extractObjIdOfTarget($qref);
3925 
3926  if (!($inst_id > 0)) {
3927  if ($obj_id > 0) {
3928  $q_ids[] = $obj_id;
3929  }
3930  }
3931  }
3932  return $q_ids;
3933  }
3934 
3935  // @todo: move to paragraph
3936  public function send_paragraph($par_id, $filename)
3937  {
3938  $this->builddom();
3939 
3940  $mydom = $this->dom;
3941 
3942  $xpc = xpath_new_context($mydom);
3943 
3944  //$path = "//PageContent[position () = $par_id]/Paragraph";
3945  //$path = "//Paragraph[$par_id]";
3946  $path = "/descendant::Paragraph[position() = $par_id]";
3947 
3948  $res = &xpath_eval($xpc, $path);
3949 
3950  if (count($res->nodeset) != 1) {
3951  die("Should not happen");
3952  }
3953 
3954  $context_node = $res->nodeset[0];
3955 
3956  // get plain text
3957 
3958  $childs = $context_node->child_nodes();
3959 
3960  for ($j = 0; $j < count($childs); $j++) {
3961  $content .= $mydom->dump_node($childs[$j]);
3962  }
3963 
3964  $content = str_replace("<br />", "\n", $content);
3965  $content = str_replace("<br/>", "\n", $content);
3966 
3967  $plain_content = html_entity_decode($content);
3968 
3969  ilUtil::deliverData($plain_content, $filename);
3970  /*
3971  $file_type = "application/octet-stream";
3972  header("Content-type: ".$file_type);
3973  header("Content-disposition: attachment; filename=\"$filename\"");
3974  echo $plain_content;*/
3975  exit();
3976  }
3977 
3981  // @todo: deprecated?
3982  public function getFO()
3983  {
3984  $xml = $this->getXMLFromDom(false, true, true);
3985  $xsl = file_get_contents("./Services/COPage/xsl/page_fo.xsl");
3986  $args = array( '/_xml' => $xml, '/_xsl' => $xsl );
3987  $xh = xslt_create();
3988 
3989  $params = array();
3990 
3991 
3992  $fo = xslt_process($xh, "arg:/_xml", "arg:/_xsl", null, $args, $params);
3993  var_dump($fo);
3994  // do some replacements
3995  $fo = str_replace("\n", "", $fo);
3996  $fo = str_replace("<br/>", "<br>", $fo);
3997  $fo = str_replace("<br>", "\n", $fo);
3998 
3999  xslt_free($xh);
4000 
4001  //
4002  $fo = substr($fo, strpos($fo, ">") + 1);
4003  //echo "<br><b>fo:</b><br>".htmlentities($fo); flush();
4004  return $fo;
4005  }
4006 
4008  {
4009  $this->offline_handler = $handler;
4010  }
4011 
4018  public function getOfflineHandler()
4019  {
4020  return $this->offline_handler;
4021  }
4022 
4023 
4027  public static function _lookupContainsDeactivatedElements($a_id, $a_parent_type, $a_lang = "-")
4028  {
4029  global $DIC;
4030 
4031  $db = $DIC->database();
4032 
4033  if ($a_lang == "") {
4034  $a_lang = "-";
4035  }
4036 
4037  $query = "SELECT * FROM page_object WHERE page_id = " .
4038  $db->quote($a_id, "integer") . " AND " .
4039  " parent_type = " . $db->quote($a_parent_type, "text") . " AND " .
4040  " lang = " . $db->quote($a_lang, "text") . " AND " .
4041  " inactive_elements = " . $db->quote(1, "integer");
4042  $obj_set = $db->query($query);
4043 
4044  if ($obj_rec = $obj_set->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
4045  return true;
4046  }
4047 
4048  return false;
4049  }
4050 
4058  {
4059  if (strpos($a_content, " Enabled=\"False\"")) {
4060  return true;
4061  }
4062  return false;
4063  }
4064 
4068  public function getHistoryEntries()
4069  {
4070  $db = $this->db;
4071 
4072  $h_query = "SELECT * FROM page_history " .
4073  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4074  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4075  " AND lang = " . $db->quote($this->getLanguage(), "text") .
4076  " ORDER BY hdate DESC";
4077 
4078  $hset = $db->query($h_query);
4079  $hentries = array();
4080 
4081  while ($hrec = $db->fetchAssoc($hset)) {
4082  $hrec["sortkey"] = (int) $hrec["nr"];
4083  $hrec["user"] = (int) $hrec["user_id"];
4084  $hentries[] = $hrec;
4085  }
4086  //var_dump($hentries);
4087  return $hentries;
4088  }
4089 
4093  public function getHistoryEntry($a_old_nr)
4094  {
4095  $db = $this->db;
4096 
4097  $res = $db->queryF(
4098  "SELECT * FROM page_history " .
4099  " WHERE page_id = %s " .
4100  " AND parent_type = %s " .
4101  " AND nr = %s" .
4102  " AND lang = %s",
4103  array("integer", "text", "integer", "text"),
4104  array($this->getId(), $this->getParentType(), $a_old_nr, $this->getLanguage())
4105  );
4106  if ($hrec = $db->fetchAssoc($res)) {
4107  return $hrec;
4108  }
4109 
4110  return false;
4111  }
4112 
4113 
4120  public function getHistoryInfo($a_nr)
4121  {
4122  $db = $this->db;
4123 
4124  // determine previous entry
4125  $and_nr = ($a_nr > 0)
4126  ? " AND nr < " . $db->quote((int) $a_nr, "integer")
4127  : "";
4128  $res = $db->query("SELECT MAX(nr) mnr FROM page_history " .
4129  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4130  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4131  " AND lang = " . $db->quote($this->getLanguage(), "text") .
4132  $and_nr);
4133  $row = $db->fetchAssoc($res);
4134  if ($row["mnr"] > 0) {
4135  $res = $db->query("SELECT * FROM page_history " .
4136  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4137  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4138  " AND lang = " . $db->quote($this->getLanguage(), "text") .
4139  " AND nr = " . $db->quote((int) $row["mnr"], "integer"));
4140  $row = $db->fetchAssoc($res);
4141  $ret["previous"] = $row;
4142  }
4143 
4144  // determine next entry
4145  $res = $db->query("SELECT MIN(nr) mnr FROM page_history " .
4146  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4147  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4148  " AND lang = " . $db->quote($this->getLanguage(), "text") .
4149  " AND nr > " . $db->quote((int) $a_nr, "integer"));
4150  $row = $db->fetchAssoc($res);
4151  if ($row["mnr"] > 0) {
4152  $res = $db->query("SELECT * FROM page_history " .
4153  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4154  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4155  " AND lang = " . $db->quote($this->getLanguage(), "text") .
4156  " AND nr = " . $db->quote((int) $row["mnr"], "integer"));
4157  $row = $db->fetchAssoc($res);
4158  $ret["next"] = $row;
4159  }
4160 
4161  // current
4162  if ($a_nr > 0) {
4163  $res = $db->query("SELECT * FROM page_history " .
4164  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4165  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4166  " AND lang = " . $db->quote($this->getLanguage(), "text") .
4167  " AND nr = " . $db->quote((int) $a_nr, "integer"));
4168  $row = $db->fetchAssoc($res);
4169  } else {
4170  $res = $db->query("SELECT page_id, last_change hdate, parent_type, parent_id, last_change_user user_id, content, lang FROM page_object " .
4171  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4172  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4173  " AND lang = " . $db->quote($this->getLanguage(), "text"));
4174  $row = $db->fetchAssoc($res);
4175  }
4176  $ret["current"] = $row;
4177 
4178  return $ret;
4179  }
4180 
4181  public function addChangeDivClasses($a_hashes)
4182  {
4183  $xpc = xpath_new_context($this->dom);
4184  $path = "/*[1]";
4185  $res = xpath_eval($xpc, $path);
4186  $rnode = $res->nodeset[0];
4187 
4188  //echo "A";
4189  foreach ($a_hashes as $pc_id => $h) {
4190  //echo "B";
4191  if ($h["change"] != "") {
4192  $dc_node = $this->dom->create_element("DivClass");
4193  $dc_node->set_attribute("HierId", $h["hier_id"]);
4194  $dc_node->set_attribute("Class", "ilEdit" . $h["change"]);
4195  $dc_node = $rnode->append_child($dc_node);
4196  }
4197  }
4198  //echo "<br><br><br><br><br><br>".htmlentities($this->getXMLFromDom());
4199  }
4200 
4207  public function compareVersion($a_left, $a_right)
4208  {
4209  // get page objects
4210  include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4211  $l_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_left);
4212  $r_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_right);
4213 
4214  $l_hashes = $l_page->getPageContentsHashes();
4215  $r_hashes = $r_page->getPageContentsHashes();
4216  // determine all deleted and changed page elements
4217  foreach ($l_hashes as $pc_id => $h) {
4218  if (!isset($r_hashes[$pc_id])) {
4219  $l_hashes[$pc_id]["change"] = "Deleted";
4220  } else {
4221  if ($l_hashes[$pc_id]["hash"] != $r_hashes[$pc_id]["hash"]) {
4222  $l_hashes[$pc_id]["change"] = "Modified";
4223  $r_hashes[$pc_id]["change"] = "Modified";
4224 
4225  include_once("./Services/COPage/mediawikidiff/class.WordLevelDiff.php");
4226  // if modified element is a paragraph, highlight changes
4227  if ($l_hashes[$pc_id]["content"] != "" &&
4228  $r_hashes[$pc_id]["content"] != "") {
4229  $new_left = str_replace("\n", "<br />", $l_hashes[$pc_id]["content"]);
4230  $new_right = str_replace("\n", "<br />", $r_hashes[$pc_id]["content"]);
4231  $wldiff = new WordLevelDiff(
4232  array($new_left),
4233  array($new_right)
4234  );
4235  $new_left = $wldiff->orig();
4236  $new_right = $wldiff->closing();
4237  $l_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_left[0]);
4238  $r_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_right[0]);
4239  }
4240  }
4241  }
4242  }
4243 
4244  // determine all new paragraphs
4245  foreach ($r_hashes as $pc_id => $h) {
4246  if (!isset($l_hashes[$pc_id])) {
4247  $r_hashes[$pc_id]["change"] = "New";
4248  }
4249  }
4250  $l_page->addChangeDivClasses($l_hashes);
4251  $r_page->addChangeDivClasses($r_hashes);
4252 
4253  return array("l_page" => $l_page, "r_page" => $r_page,
4254  "l_changes" => $l_hashes, "r_changes" => $r_hashes);
4255  }
4256 
4260  public function increaseViewCnt()
4261  {
4262  $db = $this->db;
4263 
4264  $db->manipulate("UPDATE page_object " .
4265  " SET view_cnt = view_cnt + 1 " .
4266  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4267  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
4268  " AND lang = " . $db->quote($this->getLanguage(), "text"));
4269  }
4270 
4278  public static function getRecentChanges($a_parent_type, $a_parent_id, $a_period = 30, $a_lang = "")
4279  {
4280  global $DIC;
4281 
4282  $db = $DIC->database();
4283 
4284  $and_lang = "";
4285  if ($a_lang != "") {
4286  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4287  }
4288 
4289  $page_changes = array();
4290  $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4291  $q = "SELECT * FROM page_object " .
4292  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4293  " AND parent_type = " . $db->quote($a_parent_type, "text") .
4294  " AND last_change >= " . $db->quote($limit_ts, "timestamp") . $and_lang;
4295  // " AND (TO_DAYS(now()) - TO_DAYS(last_change)) <= ".((int)$a_period);
4296  $set = $db->query($q);
4297  while ($page = $db->fetchAssoc($set)) {
4298  $page_changes[] = array(
4299  "date" => $page["last_change"],
4300  "id" => $page["page_id"],
4301  "lang" => $page["lang"],
4302  "type" => "page",
4303  "user" => $page["last_change_user"]);
4304  }
4305 
4306  $and_str = "";
4307  if ($a_period > 0) {
4308  $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4309  $and_str = " AND hdate >= " . $db->quote($limit_ts, "timestamp") . " ";
4310  }
4311 
4312  $q = "SELECT * FROM page_history " .
4313  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4314  " AND parent_type = " . $db->quote($a_parent_type, "text") .
4315  $and_str . $and_lang;
4316  $set = $db->query($q);
4317  while ($page = $db->fetchAssoc($set)) {
4318  $page_changes[] = array(
4319  "date" => $page["hdate"],
4320  "id" => $page["page_id"],
4321  "lang" => $page["lang"],
4322  "type" => "hist",
4323  "nr" => $page["nr"],
4324  "user" => $page["user_id"]);
4325  }
4326 
4327  $page_changes = ilUtil::sortArray($page_changes, "date", "desc");
4328 
4329  return $page_changes;
4330  }
4331 
4340  public static function getAllPages($a_parent_type, $a_parent_id, $a_lang = "-")
4341  {
4342  global $DIC;
4343 
4344  $db = $DIC->database();
4345 
4346  $and_lang = "";
4347  if ($a_lang != "") {
4348  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4349  }
4350 
4351  $q = "SELECT * FROM page_object " .
4352  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4353  " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang;
4354  $set = $db->query($q);
4355  $pages = array();
4356  while ($page = $db->fetchAssoc($set)) {
4357  $key_add = ($a_lang == "")
4358  ? ":" . $page["lang"]
4359  : "";
4360  $pages[$page["page_id"] . $key_add] = array(
4361  "date" => $page["last_change"],
4362  "id" => $page["page_id"],
4363  "lang" => $page["lang"],
4364  "user" => $page["last_change_user"]);
4365  }
4366 
4367  return $pages;
4368  }
4369 
4376  public static function getNewPages($a_parent_type, $a_parent_id, $a_lang = "-")
4377  {
4378  global $DIC;
4379 
4380  $db = $DIC->database();
4381 
4382  $and_lang = "";
4383  if ($a_lang != "") {
4384  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4385  }
4386 
4387  $pages = array();
4388 
4389  $q = "SELECT * FROM page_object " .
4390  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4391  " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang .
4392  " ORDER BY created DESC";
4393  $set = $db->query($q);
4394  while ($page = $db->fetchAssoc($set)) {
4395  if ($page["created"] != "") {
4396  $pages[] = array(
4397  "created" => $page["created"],
4398  "id" => $page["page_id"],
4399  "lang" => $page["lang"],
4400  "user" => $page["create_user"],
4401  );
4402  }
4403  }
4404 
4405  return $pages;
4406  }
4407 
4414  public static function getParentObjectContributors($a_parent_type, $a_parent_id, $a_lang = "-")
4415  {
4416  global $DIC;
4417 
4418  $db = $DIC->database();
4419 
4420  $and_lang = "";
4421  if ($a_lang != "") {
4422  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4423  }
4424 
4425  $contributors = array();
4426  $set = $db->queryF(
4427  "SELECT last_change_user, lang, page_id FROM page_object " .
4428  " WHERE parent_id = %s AND parent_type = %s " .
4429  " AND last_change_user != %s" . $and_lang,
4430  array("integer", "text", "integer"),
4431  array($a_parent_id, $a_parent_type, 0)
4432  );
4433 
4434  while ($page = $db->fetchAssoc($set)) {
4435  if ($a_lang == "") {
4436  $contributors[$page["last_change_user"]][$page["page_id"]][$page["lang"]] = 1;
4437  } else {
4438  $contributors[$page["last_change_user"]][$page["page_id"]] = 1;
4439  }
4440  }
4441 
4442  $set = $db->queryF(
4443  "SELECT count(*) as cnt, lang, page_id, user_id FROM page_history " .
4444  " WHERE parent_id = %s AND parent_type = %s AND user_id != %s " . $and_lang .
4445  " GROUP BY page_id, user_id, lang ",
4446  array("integer", "text", "integer"),
4447  array($a_parent_id, $a_parent_type, 0)
4448  );
4449  while ($hpage = $db->fetchAssoc($set)) {
4450  if ($a_lang == "") {
4451  $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] =
4452  $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] + $hpage["cnt"];
4453  } else {
4454  $contributors[$hpage["user_id"]][$hpage["page_id"]] =
4455  $contributors[$hpage["user_id"]][$hpage["page_id"]] + $hpage["cnt"];
4456  }
4457  }
4458 
4459  $c = array();
4460  foreach ($contributors as $k => $co) {
4461  if (ilObject::_lookupType($k) == "usr") {
4463  $c[] = array("user_id" => $k, "pages" => $co,
4464  "lastname" => $name["lastname"], "firstname" => $name["firstname"]);
4465  }
4466  }
4467 
4468  return $c;
4469  }
4470 
4477  public static function getPageContributors($a_parent_type, $a_page_id, $a_lang = "-")
4478  {
4479  global $DIC;
4480 
4481  $db = $DIC->database();
4482 
4483  $and_lang = "";
4484  if ($a_lang != "") {
4485  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4486  }
4487 
4488  $contributors = array();
4489  $set = $db->queryF(
4490  "SELECT last_change_user, lang FROM page_object " .
4491  " WHERE page_id = %s AND parent_type = %s " .
4492  " AND last_change_user != %s" . $and_lang,
4493  array("integer", "text", "integer"),
4494  array($a_page_id, $a_parent_type, 0)
4495  );
4496 
4497  while ($page = $db->fetchAssoc($set)) {
4498  if ($a_lang == "") {
4499  $contributors[$page["last_change_user"]][$page["lang"]] = 1;
4500  } else {
4501  $contributors[$page["last_change_user"]] = 1;
4502  }
4503  }
4504 
4505  $set = $db->queryF(
4506  "SELECT count(*) as cnt, lang, page_id, user_id FROM page_history " .
4507  " WHERE page_id = %s AND parent_type = %s AND user_id != %s " . $and_lang .
4508  " GROUP BY user_id, page_id, lang ",
4509  array("integer", "text", "integer"),
4510  array($a_page_id, $a_parent_type, 0)
4511  );
4512  while ($hpage = $db->fetchAssoc($set)) {
4513  if ($a_lang == "") {
4514  $contributors[$hpage["user_id"]][$page["lang"]] =
4515  $contributors[$hpage["user_id"]][$page["lang"]] + $hpage["cnt"];
4516  } else {
4517  $contributors[$hpage["user_id"]] =
4518  $contributors[$hpage["user_id"]] + $hpage["cnt"];
4519  }
4520  }
4521 
4522  $c = array();
4523  foreach ($contributors as $k => $co) {
4524  include_once "Services/User/classes/class.ilObjUser.php";
4526  $c[] = array("user_id" => $k, "pages" => $co,
4527  "lastname" => $name["lastname"], "firstname" => $name["firstname"]);
4528  }
4529 
4530  return $c;
4531  }
4532 
4536  public function writeRenderedContent($a_content, $a_md5)
4537  {
4538  global $DIC;
4539 
4540  $db = $DIC->database();
4541 
4542  $db->update("page_object", array(
4543  "rendered_content" => array("clob", $a_content),
4544  "render_md5" => array("text", $a_md5),
4545  "rendered_time" => array("timestamp", ilUtil::now())
4546  ), array(
4547  "page_id" => array("integer", $this->getId()),
4548  "lang" => array("text", $this->getLanguage()),
4549  "parent_type" => array("text", $this->getParentType())
4550  ));
4551  }
4552 
4560  public static function getPagesWithLinks($a_parent_type, $a_parent_id, $a_lang = "-")
4561  {
4562  global $DIC;
4563 
4564  $db = $DIC->database();
4565 
4566  $and_lang = "";
4567  if ($a_lang != "") {
4568  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
4569  }
4570 
4571  $q = "SELECT * FROM page_object " .
4572  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
4573  " AND parent_type = " . $db->quote($a_parent_type, "text") .
4574  " AND int_links = " . $db->quote(1, "integer") . $and_lang;
4575  $set = $db->query($q);
4576  $pages = array();
4577  while ($page = $db->fetchAssoc($set)) {
4578  $key_add = ($a_lang == "")
4579  ? ":" . $page["lang"]
4580  : "";
4581  $pages[$page["page_id"] . $key_add] = array(
4582  "date" => $page["last_change"],
4583  "id" => $page["page_id"],
4584  "lang" => $page["lang"],
4585  "user" => $page["last_change_user"]);
4586  }
4587 
4588  return $pages;
4589  }
4590 
4597  public function containsIntLinks($a_content)
4598  {
4599  if (strpos($a_content, "IntLink")) {
4600  return true;
4601  }
4602  return false;
4603  }
4604 
4609  {
4610  }
4611 
4617  // @todo begin: generalize
4618  public function saveInitialOpenedContent($a_type, $a_id, $a_target)
4619  {
4620  $this->buildDom();
4621 
4622  $link_type = "";
4623 
4624  switch ($a_type) {
4625  case "media":
4626  $link_type = "MediaObject";
4627  $a_id = "il__mob_" . $a_id;
4628  break;
4629 
4630  case "page":
4631  $link_type = "PageObject";
4632  $a_id = "il__pg_" . $a_id;
4633  break;
4634 
4635  case "term":
4636  $link_type = "GlossaryItem";
4637  $a_id = "il__git_" . $a_id;
4638  $a_target = "Glossary";
4639  break;
4640  }
4641 
4642  // if type or id missing -> delete InitOpenedContent, if existing
4643  if ($link_type == "" || $a_id == "") {
4644  $xpc = xpath_new_context($this->dom);
4645  $path = "//PageObject/InitOpenedContent";
4646  $res = xpath_eval($xpc, $path);
4647  if (count($res->nodeset) > 0) {
4648  $res->nodeset[0]->unlink_node($res->nodeset[0]);
4649  }
4650  } else {
4651  $xpc = xpath_new_context($this->dom);
4652  $path = "//PageObject/InitOpenedContent";
4653  $res = xpath_eval($xpc, $path);
4654  if (count($res->nodeset) > 0) {
4655  $init_node = $res->nodeset[0];
4656  $childs = $init_node->child_nodes();
4657  for ($i = 0; $i < count($childs); $i++) {
4658  if ($childs[$i]->node_name() == "IntLink") {
4659  $il_node = $childs[$i];
4660  }
4661  }
4662  } else {
4663  $path = "//PageObject";
4664  $res = xpath_eval($xpc, $path);
4665  $page_node = $res->nodeset[0];
4666  $init_node = $this->dom->create_element("InitOpenedContent");
4667  $init_node = $page_node->append_child($init_node);
4668  $il_node = $this->dom->create_element("IntLink");
4669  $il_node = $init_node->append_child($il_node);
4670  }
4671  $il_node->set_attribute("Target", $a_id);
4672  $il_node->set_attribute("Type", $link_type);
4673  $il_node->set_attribute("TargetFrame", $a_target);
4674  }
4675 
4676  $this->update();
4677  }
4678 
4679 
4685  public function getInitialOpenedContent()
4686  {
4687  $this->buildDom();
4688 
4689  $xpc = xpath_new_context($this->dom);
4690  $path = "//PageObject/InitOpenedContent";
4691  $res = xpath_eval($xpc, $path);
4692  $il_node = null;
4693  if (count($res->nodeset) > 0) {
4694  $init_node = $res->nodeset[0];
4695  $childs = $init_node->child_nodes();
4696  for ($i = 0; $i < count($childs); $i++) {
4697  if ($childs[$i]->node_name() == "IntLink") {
4698  $il_node = $childs[$i];
4699  }
4700  }
4701  }
4702  if (!is_null($il_node)) {
4703  $id = $il_node->get_attribute("Target");
4704  $link_type = $il_node->get_attribute("Type");
4705  $target = $il_node->get_attribute("TargetFrame");
4706 
4707  switch ($link_type) {
4708  case "MediaObject":
4709  $type = "media";
4710  break;
4711 
4712  case "PageObject":
4713  $type = "page";
4714  break;
4715 
4716  case "GlossaryItem":
4717  $type = "term";
4718  break;
4719  }
4720  include_once("./Services/Link/classes/class.ilInternalLink.php");
4722  return array("id" => $id, "type" => $type, "target" => $target);
4723  }
4724 
4725  return array();
4726  }
4727  // @todo end
4728 
4739  public function beforePageContentUpdate($a_page_content)
4740  {
4741  }
4742 
4750  public function copy($a_id, $a_parent_type = "", $a_parent_id = 0, $a_clone_mobs = false)
4751  {
4752  if ($a_parent_type == "") {
4753  $a_parent_type = $this->getParentType();
4754  if ($a_parent_id == 0) {
4755  $a_parent_id = $this->getParentId();
4756  }
4757  }
4758 
4759  include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4760  foreach (self::lookupTranslations($this->getParentType(), $this->getId()) as $l) {
4761  $existed = false;
4762  $orig_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), 0, $l);
4763  if (ilPageObject::_exists($a_parent_type, $a_id, $l)) {
4764  $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, $a_id, 0, $l);
4765  $existed = true;
4766  } else {
4767  $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, 0, 0, $l);
4768  $new_page_object->setParentId($a_parent_id);
4769  $new_page_object->setId($a_id);
4770  }
4771  $new_page_object->setXMLContent($orig_page->copyXMLContent($a_clone_mobs));
4772  $new_page_object->setActive($orig_page->getActive());
4773  $new_page_object->setActivationStart($orig_page->getActivationStart());
4774  $new_page_object->setActivationEnd($orig_page->getActivationEnd());
4775  if ($existed) {
4776  $new_page_object->buildDom();
4777  $new_page_object->update();
4778  } else {
4779  $new_page_object->create();
4780  }
4781  }
4782  }
4783 
4791  public static function lookupTranslations($a_parent_type, $a_id)
4792  {
4793  global $DIC;
4794 
4795  $db = $DIC->database();
4796 
4797  $set = $db->query(
4798  "SELECT lang FROM page_object " .
4799  " WHERE page_id = " . $db->quote($a_id, "integer") .
4800  " AND parent_type = " . $db->quote($a_parent_type, "text")
4801  );
4802  $langs = array();
4803  while ($rec = $db->fetchAssoc($set)) {
4804  $langs[] = $rec["lang"];
4805  }
4806  return $langs;
4807  }
4808 
4809 
4815  public function copyPageToTranslation($a_target_lang)
4816  {
4817  $transl_page = ilPageObjectFactory::getInstance(
4818  $this->getParentType(),
4819  0,
4820  0,
4821  $a_target_lang
4822  );
4823  $transl_page->setId($this->getId());
4824  $transl_page->setParentId($this->getParentId());
4825  $transl_page->setXMLContent($this->copyXMLContent());
4826  $transl_page->setActive($this->getActive());
4827  $transl_page->setActivationStart($this->getActivationStart());
4828  $transl_page->setActivationEnd($this->getActivationEnd());
4829  $transl_page->create();
4830  }
4831 
4835 
4839  public function getEditLock()
4840  {
4841  $db = $this->db;
4842  $user = $this->user;
4843 
4844  $min = (int) $this->getEffectiveEditLockTime();
4845  if ($min > 0) {
4846  // try to set the lock for the user
4847  $ts = time();
4848  $db->manipulate(
4849  "UPDATE page_object SET " .
4850  " edit_lock_user = " . $db->quote($user->getId(), "integer") . "," .
4851  " edit_lock_ts = " . $db->quote($ts, "integer") .
4852  " WHERE (edit_lock_user = " . $db->quote($user->getId(), "integer") . " OR " .
4853  " edit_lock_ts < " . $db->quote(time() - ($min * 60), "integer") . ") " .
4854  " AND page_id = " . $db->quote($this->getId(), "integer") .
4855  " AND parent_type = " . $db->quote($this->getParentType(), "text")
4856  );
4857 
4858  $set = $db->query(
4859  "SELECT edit_lock_user FROM page_object " .
4860  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4861  " AND parent_type = " . $db->quote($this->getParentType(), "text")
4862  );
4863  $rec = $db->fetchAssoc($set);
4864  if ($rec["edit_lock_user"] != $user->getId()) {
4865  return false;
4866  }
4867  }
4868 
4869  return true;
4870  }
4871 
4875  public function releasePageLock()
4876  {
4877  $db = $this->db;
4878  $user = $this->user;
4879  $aset = new ilSetting("adve");
4880 
4881  $min = (int) $aset->get("block_mode_minutes") ;
4882  if ($min > 0) {
4883  // try to set the lock for the user
4884  $ts = time();
4885  $db->manipulate(
4886  "UPDATE page_object SET " .
4887  " edit_lock_user = " . $db->quote($user->getId(), "integer") . "," .
4888  " edit_lock_ts = 0" .
4889  " WHERE edit_lock_user = " . $db->quote($user->getId(), "integer") .
4890  " AND page_id = " . $db->quote($this->getId(), "integer") .
4891  " AND parent_type = " . $db->quote($this->getParentType(), "text")
4892  );
4893 
4894  $set = $db->query(
4895  "SELECT edit_lock_user FROM page_object " .
4896  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4897  " AND parent_type = " . $db->quote($this->getParentType(), "text")
4898  );
4899  $rec = $db->fetchAssoc($set);
4900  if ($rec["edit_lock_user"] != $user->getId()) {
4901  return false;
4902  }
4903  }
4904 
4905  return true;
4906  }
4907 
4913  public function getEditLockInfo()
4914  {
4915  $db = $this->db;
4916 
4917  $aset = new ilSetting("adve");
4918  $min = (int) $aset->get("block_mode_minutes");
4919 
4920  $set = $db->query(
4921  "SELECT edit_lock_user, edit_lock_ts FROM page_object " .
4922  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
4923  " AND parent_type = " . $db->quote($this->getParentType(), "text")
4924  );
4925  $rec = $db->fetchAssoc($set);
4926  $rec["edit_lock_until"] = $rec["edit_lock_ts"] + $min * 60;
4927 
4928  return $rec;
4929  }
4930 
4943  public static function truncateHTML($a_text, $a_length = 100, $a_ending = '...', $a_exact = false, $a_consider_html = true)
4944  {
4945  include_once "Services/Utilities/classes/class.ilStr.php";
4946 
4947  if ($a_consider_html) {
4948  // if the plain text is shorter than the maximum length, return the whole text
4949  if (strlen(preg_replace('/<.*?>/', '', $a_text)) <= $a_length) {
4950  return $a_text;
4951  }
4952 
4953  // splits all html-tags to scanable lines
4954  $total_length = strlen($a_ending);
4955  $open_tags = array();
4956  $truncate = '';
4957  preg_match_all('/(<.+?>)?([^<>]*)/s', $a_text, $lines, PREG_SET_ORDER);
4958  foreach ($lines as $line_matchings) {
4959  // if there is any html-tag in this line, handle it and add it (uncounted) to the output
4960  if (!empty($line_matchings[1])) {
4961  // if it's an "empty element" with or without xhtml-conform closing slash
4962  if (preg_match('/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is', $line_matchings[1])) {
4963  // do nothing
4964  }
4965  // if tag is a closing tag
4966  elseif (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line_matchings[1], $tag_matchings)) {
4967  // delete tag from $open_tags list
4968  $pos = array_search($tag_matchings[1], $open_tags);
4969  if ($pos !== false) {
4970  unset($open_tags[$pos]);
4971  }
4972  }
4973  // if tag is an opening tag
4974  elseif (preg_match('/^<\s*([^\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings)) {
4975  // add tag to the beginning of $open_tags list
4976  array_unshift($open_tags, strtolower($tag_matchings[1]));
4977  }
4978  // add html-tag to $truncate'd text
4979  $truncate .= $line_matchings[1];
4980  }
4981 
4982  // calculate the length of the plain text part of the line; handle entities as one character
4983  $content_length = strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
4984  if ($total_length + $content_length > $a_length) {
4985  // the number of characters which are left
4986  $left = $a_length - $total_length;
4987  $entities_length = 0;
4988  // search for html entities
4989  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)) {
4990  // calculate the real length of all entities in the legal range
4991  foreach ($entities[0] as $entity) {
4992  if ($entity[1] + 1 - $entities_length <= $left) {
4993  $left--;
4994  $entities_length += strlen($entity[0]);
4995  } else {
4996  // no more characters left
4997  break;
4998  }
4999  }
5000  }
5001 
5002  // $truncate .= substr($line_matchings[2], 0, $left+$entities_length);
5003  $truncate .= ilStr::shortenText($line_matchings[2], 0, $left + $entities_length);
5004 
5005  // maximum lenght is reached, so get off the loop
5006  break;
5007  } else {
5008  $truncate .= $line_matchings[2];
5009  $total_length += $content_length;
5010  }
5011 
5012  // if the maximum length is reached, get off the loop
5013  if ($total_length >= $a_length) {
5014  break;
5015  }
5016  }
5017  } else {
5018  if (strlen($a_text) <= $a_length) {
5019  return $a_text;
5020  } else {
5021  // $truncate = substr($a_text, 0, $a_length - strlen($a_ending));
5022  $truncate = ilStr::shortenText($a_text, 0, $a_length - strlen($a_ending));
5023  }
5024  }
5025 
5026  // THIS IS BUGGY AS IT MIGHT BREAK AN OPEN TAG AT THE END
5027  if (!sizeof($open_tags)) {
5028  // if the words shouldn't be cut in the middle...
5029  if (!$a_exact) {
5030  // ...search the last occurance of a space...
5031  $spacepos = strrpos($truncate, ' ');
5032  if ($spacepos !== false) {
5033  // ...and cut the text in this position
5034  // $truncate = substr($truncate, 0, $spacepos);
5035  $truncate = ilStr::shortenText($truncate, 0, $spacepos);
5036  }
5037  }
5038  }
5039 
5040  // add the defined ending to the text
5041  $truncate .= $a_ending;
5042 
5043  if ($a_consider_html) {
5044  // close all unclosed html-tags
5045  foreach ($open_tags as $tag) {
5046  $truncate .= '</' . $tag . '>';
5047  }
5048  }
5049 
5050  return $truncate;
5051  }
5052 
5058  public function getContentTemplates()
5059  {
5060  return array();
5061  }
5062 
5070  public static function getLastChangeByParent($a_parent_type, $a_parent_id, $a_lang = "")
5071  {
5072  global $DIC;
5073 
5074  $db = $DIC->database();
5075 
5076  $and_lang = "";
5077  if ($a_lang != "") {
5078  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
5079  }
5080 
5081  $db->setLimit(1);
5082  $q = "SELECT last_change FROM page_object " .
5083  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
5084  " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang .
5085  " ORDER BY last_change DESC";
5086 
5087  $set = $db->query($q);
5088  $rec = $db->fetchAssoc($set);
5089 
5090  return $rec["last_change"];
5091  }
5092 
5093  public function getEffectiveEditLockTime()
5094  {
5095  if ($this->getPageConfig()->getEditLockSupport() == false) {
5096  return 0;
5097  }
5098 
5099  $aset = new ilSetting("adve");
5100  $min = (int) $aset->get("block_mode_minutes") ;
5101 
5102  return $min;
5103  }
5104 
5110  public function getAllFileObjIds()
5111  {
5112  $file_obj_ids = array();
5113 
5114  // insert inst id file item identifier entries
5115  $xpc = xpath_new_context($this->dom);
5116  $path = "//FileItem/Identifier";
5117  $res = xpath_eval($xpc, $path);
5118  for ($i = 0; $i < count($res->nodeset); $i++) {
5119  $file_obj_ids[] = $res->nodeset[$i]->get_attribute("Entry");
5120  }
5121  unset($xpc);
5122  return $file_obj_ids;
5123  }
5124 
5129  public function resolveResources($ref_mapping)
5130  {
5131  include_once("./Services/COPage/classes/class.ilPCResources.php");
5132  ilPCResources::resolveResources($this, $ref_mapping);
5133  }
5134 
5139  public function getRepoObjId()
5140  {
5141  return $this->getParentId();
5142  }
5143 
5144 }
static _exists($a_parent_type, $a_id, $a_lang="", $a_no_cache=false)
Checks whether page exists.
getLastUpdateOfIncludedElements()
Get last update of included elements (media objects and files).
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
static _lookupName($a_user_id)
lookup user name
xslt_create()
buildDom($a_force=false)
performAutomaticModifications()
Perform automatic modifications (may be overwritten by sub classes)
removeQuestions(&$temp_dom)
Remove questions from document.
appendXMLContent($a_xml)
append xml content to page setXMLContent must be called before and the same encoding must be used ...
stripHierIDs()
strip all hierarchical id attributes out of the dom tree
static shortenText($a_string, $a_start_pos, $a_num_bytes, $a_encoding='UTF-8')
Shorten text to the given number of bytes.
checkPCIds()
Check, whether (all) page content hashes are set.
increaseViewCnt()
Increase view cnt.
getAllPCIds()
Get all pc ids.
generatePcId($a_pc_ids=false)
Generate new pc id.
$target_arr
Definition: goto.php:47
static deliverData($a_data, $a_filename, $mime="application/octet-stream", $charset="")
deliver data for download via browser.
static incEdId($ed_id)
Increases an hierarchical editing id at lowest level (last number)
static _getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
static _existsAndNotEmpty($a_parent_type, $a_id, $a_lang="-")
Checks whether page exists and is not empty (may return true on some empty pages) ...
updateFromXML()
Updates page object with current xml content.
$path
Definition: aliased.php:25
__beforeDelete()
Before deletion handler (internal).
releasePageLock()
Release page lock.
addFileSizes()
add file sizes
static getPCDefinitionByName($a_pc_name)
Get PC definition by name.
lookforhier($a_hier_id)
getInternalLinks($a_cnt_multiple=false)
get all internal links that are used within the page
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) ...
$size
Definition: RandomTest.php:84
static _getMapAreasIntLinks($a_mob_id)
get all internal links of map areas of a mob
static _lookupType($a_obj_id, $a_lm_id=0)
Lookup type.
copyPageToTranslation($a_target_lang)
Copy page to translation.
$files
Definition: metarefresh.php:49
const IL_CAL_DATETIME
getFO()
get fo page content
getLanguage()
Get language.
static _deleteAllUsages($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
static
needsImportParsing($a_parse="")
const ILIAS_VERSION_NUMERIC
__afterUpdate($a_domdoc, $a_xml, $a_creation=false, $a_empty=false)
After update event handler (internal).
setImportMode($a_val)
Set import mode.
$template
deleteContentFromHierId($a_hid, $a_update=true)
delete content object with hierarchical id >= $a_hid
xpath_new_context($dom_document)
Class ilPCTable.
$type
global $DIC
Definition: saml.php:7
setActive($a_active)
set activation
static _exists($a_id, $a_reference=false, $a_type=null)
checks if an object exists in object_data
existsPCId($a_pc_id)
existsPCId
static sortHierIds($a_array)
Sort an array of Hier IDS in ascending order.
$_GET["client_id"]
$h
resolveIIMMediaAliases($a_mapping)
Resolve iim media aliases (in ilContObjParse)
getFirstColumnIds()
get ids of all first table columns
handleCopiedContent($a_dom, $a_self_ass=true, $a_clone_mobs=false)
Handle copied content.
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.
xslt_free(&$proc)
getMediaAliasElement($a_mob_id, $a_nr=1)
get complete media object (alias) element
create()
create new page (with current xml data)
static getPagesWithLinks($a_parent_type, $a_parent_id, $a_lang="-")
Get all pages for parent object that contain internal links.
setParagraphContent($a_hier_id, $a_content)
Set content of paragraph.
deleteContents($a_hids, $a_update=true, $a_self_ass=false)
Delete multiple content objects.
domxml_open_mem($str, $mode=0, &$error=null)
setActivationEnd($a_activationend)
Set Activation End.
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.
setActivationStart($a_activationstart)
Set Activation Start.
copyXmlContent($a_clone_mobs=false)
Copy content of page; replace page components with copies where necessary (e.g.
xpath_eval($xpath_context, $eval_str, $contextnode=null)
newIIMCopies($temp_dom)
Replaces media objects in interactive images with copies of the interactive images.
static getPCDefinitions()
Get PC definitions.
static getAllPages($a_parent_type, $a_parent_id, $a_lang="-")
Get all pages for parent object.
static getPageContributors($a_parent_type, $a_page_id, $a_lang="-")
Get all contributors for parent object.
send_paragraph($par_id, $filename)
static _resolveMapAreaLinks($a_mob_id)
resolve internal links of all media items of a media object
pasteContents($a_hier_id, $a_self_ass=false)
Paste contents from pc clipboard.
setShowActivationInfo($a_val)
Set show page activation info.
Class ilPCParagraph.
resolveIntLinks($a_link_map=null)
Resolves all internal link targets of the page, if targets are available (after import) ...
read()
Read page data.
getQuestionIds()
Get question ids.
$s
Definition: pwgen.php:45
getHistoryEntries()
Get History Entries.
static getLastChangeByParent($a_parent_type, $a_parent_id, $a_lang="")
Get all pages for parent object.
getDomDoc()
Get dom doc (php5 dom document)
Class ilMediaAliasItem.
static requirePCClassByName($a_name)
Get instance.
moveContentAfter($a_source, $a_target, $a_spcid="", $a_tpcid="")
move content object from position $a_source before position $a_target (both hierarchical content ids)...
checkForTag($a_content_tag, $a_hier_id, $a_pc_id="")
Get content node from dom.
registerOfflineHandler($handler)
const IL_CAL_UNIX
static _moveContentAfterHierId(&$a_source_page, &$a_target_page, $a_hid)
move content of hierarchical id >= $a_hid to other page
static now()
Return current timestamp in Y-m-d H:i:s format.
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date public.
static xml2output($a_text, $a_wysiwyg=false, $a_replace_lists=true, $unmask=true)
Converts xml from DB to output in edit textarea.
getPageContentsHashes()
Get page contents hashes.
user()
Definition: user.php:4
__afterHistoryEntry($a_old_domdoc, $a_old_content, $a_old_nr)
Before deletion handler (internal).
getContentObject($a_hier_id, $a_pc_id="")
Get a content object of the page.
handleRepositoryLinksOnCopy($a_mapping, $a_source_ref_id)
Handle repository links on copy process.
getFileItemIds()
get ids of all file items
$start
Definition: bench.php:8
getRenderMd5()
Get Render MD5.
static getConfigInstance($a_parent_type)
Get page config instance.
static lookupParentId($a_id, $a_type)
Lookup parent id.
$time
Definition: cron.php:21
newMobCopies($temp_dom)
Replaces media objects with copies.
$a_type
Definition: workflow.php:92
moveIntLinks($a_from_to)
Move internal links from one destination to another.
setRenderedContent($a_renderedcontent)
Set Rendered Content.
compareVersion($a_left, $a_right)
Compares to revisions of the page.
addUpdateListener(&$a_object, $a_method, $a_parameters="")
collectMediaObjects($a_inline_only=true)
get all media objects, that are referenced and used within the page
__construct($a_id=0, $a_old_nr=0, $a_lang="-")
Constructor public.
moveContentBefore($a_source, $a_target, $a_spcid="", $a_tpcid="")
move content object from position $a_source before position $a_target (both hierarchical content ids)...
foreach($_POST as $key=> $value) $res
$mobs
static _existsAndNotEmpty($a_parent_type, $a_id, $a_lang="-")
checks whether page exists and is not empty (may return true on some empty pages) ...
getXMLContent($a_incl_head=false)
get xml content of page
static _lookupActive($a_id, $a_parent_type, $a_check_scheduled_activation=false, $a_lang="-")
lookup activation status
$a_content
Definition: workflow.php:93
static _writeParentId($a_parent_type, $a_pg_id, $a_par_id)
Write parent id.
beforePageContentUpdate($a_page_content)
Before page content update.
deleteInternalLinks()
Delete internal links.
static _writeActive($a_id, $a_parent_type, $a_active, $a_reset_scheduled_activation=true, $a_lang="-")
write activation status
getActive($a_check_scheduled_activation=false)
get activation
getLastChange()
Get Last Change.
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
getListItemIds()
get ids of all list items
getInitialOpenedContent()
Get initial opened content.
resolveFileItems($a_mapping)
Resolve file items (after import)
static _lookupObjId($a_id)
Class ilPageObject.
$text
Definition: errorreport.php:18
resolveQuestionReferences($a_mapping)
Resolve all quesion references (after import)
containsIntLink()
returns true, if page was marked as containing an intern link (via setContainsIntLink) (this method s...
createFromXML()
Create new page object with current xml content.
setRenderedTime($a_renderedtime)
Set Rendered Time.
getRenderedContent()
Get Rendered Content.
static getParentObjectContributors($a_parent_type, $a_parent_id, $a_lang="-")
Get all contributors for parent object.
getImportMode()
Get import mode.
getActivationStart()
Get Activation Start.
Date and time handling
catch(Exception $e) if(isset($_POST['cancel'])) if(isset($_POST['continue'])) $cfg
setPageConfig($a_val)
Set page config object.
appendLangVarXML(&$xml, $var)
static getRecentChanges($a_parent_type, $a_parent_id, $a_period=30, $a_lang="")
Get recent pages changes for parent object.
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
Class ilObjMediaObject.
Unknown page content type exception.
$query
static _handleImportRepositoryLinks($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
Change targest of repository links.
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:
getOfflineHandler()
Get offline handler.
getShowActivationInfo()
Get show page activation info.
setId($a_id)
set id
const IL_INSERT_AFTER
static _lookupImportId($a_obj_id)
static _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_usage_lang="-")
get all files of an object
update($a_validate=true, $a_no_history=false)
update complete page content in db (dom xml content is used)
static _lookupType($a_id, $a_reference=false)
lookup object type
setRenderMd5($a_rendermd5)
Set Render MD5.
static _lookupContainsDeactivatedElements($a_id, $a_parent_type, $a_lang="-")
lookup whether page contains deactivated elements
static _isScheduledActivation($a_id, $a_parent_type, $a_lang="-")
Check whether page is activated by time schedule.
containsIntLinks($a_content)
Check whether content contains internal links.
static _instantiateQuestion($question_id)
deleteContentBeforeHierId($a_hid, $a_update=true)
delete content object with hierarchical id < $a_hid
$filename
Definition: buildRTE.php:89
getContentTemplates()
Get content templates.
insertPCIds()
Insert Page Content IDs.
getFirstRowIds()
get ids of all first table rows
getLanguageVariablesXML()
Get language variables as XML.
$row
addHierIDs()
Add hierarchical ID (e.g.
getLastChangeUser()
Get last change user.
insertInstIntoIDs($a_inst, $a_res_ref_to_obj_id=true)
inserts installation id into ids (e.g.
static truncateHTML($a_text, $a_length=100, $a_ending='...', $a_exact=false, $a_consider_html=true)
Truncate (html) string.
saveInitialOpenedContent($a_type, $a_id, $a_target)
Save initial opened content.
saveStyleUsage($a_domdoc, $a_old_nr=0)
Save all style class/template usages.
setContainsQuestion($a_val)
Set contains question.
handleImportRepositoryLink($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
afterConstructor()
After constructor.
exit
Definition: backend.php:16
static _lookupFileSize($a_id)
Lookups the file size of the file in bytes.
static _lookupActivationData($a_id, $a_parent_type, $a_lang="-")
Lookup activation data.
static getInstance($a_parent_type, $a_id=0, $a_old_nr=0, $a_lang="-")
Get page object instance.
static _getLastUpdateOfObjects($a_objs)
Get last update for a set of media objects.
getDom()
Deprecated php4DomDocument.
$errors
Definition: index.php:6
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.
setLastChange($a_lastchange)
Set Last Change.
getHistoryEntry($a_old_nr)
Get History Entry.
getEditLockInfo()
Get edit lock info.
bbCode2XML(&$a_content)
transforms bbCode to corresponding xml
setLanguage($a_val)
Set language.
$lm_set
global $l
Definition: afr.php:30
setXMLContent($a_xml, $a_encoding="UTF-8")
set xml content of page, start with <PageObject...>, end with </PageObject>, comply with ILIAS DTD...
newQuestionCopies(&$temp_dom)
Replaces existing question content elements with new copies.
setLastChangeUser($a_val)
Set last change user.
writeRenderedContent($a_content, $a_md5)
Write rendered content.
initPageConfig()
Init page config.
getPageConfig()
Get page config object.
static lookupTranslations($a_parent_type, $a_id)
Lookup translations.
const DOMXML_LOAD_PARSING
getMultimediaXML()
get a xml string that contains all media object elements, that are referenced by any media alias in t...
static preloadActivationDataByParentId($a_parent_id)
Preload activation data by Parent Id.
containsDeactivatedElements($a_content)
Check whether content contains deactivated elements.
resolveMediaAliases($a_mapping, $a_reuse_existing_by_import=false)
Resolve media aliases (after import)
getEditLock()
Get page lock.
$ret
Definition: parser.php:6
setContainsIntLink($a_contains_link)
lm parser set this flag to true, if the page contains intern links (this method should only be called...
switchEnableMultiple($a_hids, $a_update=true, $a_self_ass=false)
(De-)activate elements
$i
Definition: disco.tpl.php:19
copyContents($a_hids)
Copy contents to clipboard.
$def
Definition: croninfo.php:21
getHistoryInfo($a_nr)
Get information about a history entry, its predecessor and its successor.
const IL_MODE_OUTPUT
countPageContents()
Remove questions from document.
static getLogger($a_component_id)
Get component logger.
$url
getHierIds()
get all hierarchical ids
$links
Class ilPCMediaObject.
saveInternalLinks($a_domdoc)
save internal links of page
$source
Definition: linkback.php:22
afterUpdate()
After update.
getRenderedTime()
Get Rendered Time.
& getContentNode($a_hier_id, $a_pc_id="")
Get content node from dom.
getActivationEnd()
Get Activation End.
getRepoObjId()
Get object id of repository object that contains this page, return 0 if page does not belong to a rep...
static setAction($a_action)
$target
Definition: test.php:19
$handler
resolveResources($ref_mapping)
Resolve resources.
$key
Definition: croninfo.php:18
static getNewPages($a_parent_type, $a_parent_id, $a_lang="-")
Get new pages.
getHierIdsForPCIds($a_pc_ids)
Get hier ids for a set of pc ids.
$_POST["username"]
copy($a_id, $a_parent_type="", $a_parent_id=0, $a_clone_mobs=false)
Copy page.
static resolveResources(ilPageObject $page, $ref_mappings)
Resolve resources.
if(function_exists('posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
Definition: cron.php:35
Extension of ilPageObject for learning modules.
getContainsQuestion()
Get contains question.
getAllFileObjIds()
Get all file object ids.
getParentType()
Get parent type.
deleteStyleUsages($a_old_nr=0)
Delete style usages.
const IL_INSERT_CHILD
validateDom()
Validate the page content agains page DTD.
const IL_INSERT_BEFORE
cutContents($a_hids)
Copy contents to clipboard and cut them from the page.
deleteContent($a_hid, $a_update=true, $a_pcid="")
delete content object with hierarchical id $a_hid
Class ilPCDataTable.
addChangeDivClasses($a_hashes)