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