ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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 {
48  static $exists = array();
49 
50  var $id;
51  var $ilias;
52  var $dom;
53  var $xml;
54  var $encoding;
55  var $node;
56  var $cur_dtd = "ilias_pg_5_1.dtd";
66  var $language = "-";
67  static protected $activation_data = array();
68  protected $import_mode = false;
69 
73  protected $log;
74 
79  final public function ilPageObject($a_id = 0, $a_old_nr = 0, $a_lang = "-")
80  {
81  global $ilias;
82 
83  $this->log = ilLoggerFactory::getLogger('copg');
84 
85  // @todo: move this elsewhere
86  require_once("./Services/COPage/syntax_highlight/php/Beautifier/Init.php");
87  require_once("./Services/COPage/syntax_highlight/php/Output/Output_css.php");
88 
89  $this->parent_type = $this->getParentType();
90  $this->id = $a_id;
91  $this->ilias =& $ilias;
92  $this->setLanguage($a_lang);
93 
94  $this->contains_int_link = false;
95  $this->needs_parsing = false;
96  $this->update_listeners = array();
97  $this->update_listener_cnt = 0;
98  $this->dom_builded = false;
99  $this->page_not_found = false;
100  $this->old_nr = $a_old_nr;
101  $this->encoding = "UTF-8";
102  $this->id_elements =
103  array("PageContent", "TableRow", "TableData", "ListItem", "FileItem",
104  "Section", "Tab", "ContentPopup");
105  $this->setActive(true);
106  $this->show_page_act_info = false;
107 
108  if($a_id != 0)
109  {
110  $this->read();
111  }
112 
113  $this->initPageConfig();
114 
115  $this->afterConstructor();
116  }
117 
124  function afterConstructor()
125  {
126 
127  }
128 
129 
135  abstract function getParentType();
136 
142  final function initPageConfig()
143  {
144  include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
146  $this->setPageConfig($cfg);
147  }
148 
154  function setLanguage($a_val)
155  {
156  $this->language = $a_val;
157  }
158 
164  function getLanguage()
165  {
166  return $this->language;
167  }
168 
174  function setPageConfig($a_val)
175  {
176  $this->page_config = $a_val;
177  }
178 
184  function getPageConfig()
185  {
186  return $this->page_config;
187  }
188 
194  function setRenderMd5($a_rendermd5)
195  {
196  $this->rendermd5 = $a_rendermd5;
197  }
198 
204  function getRenderMd5()
205  {
206  return $this->rendermd5;
207  }
208 
214  function setRenderedContent($a_renderedcontent)
215  {
216  $this->renderedcontent = $a_renderedcontent;
217  }
218 
225  {
226  return $this->renderedcontent;
227  }
228 
234  function setRenderedTime($a_renderedtime)
235  {
236  $this->renderedtime = $a_renderedtime;
237  }
238 
244  function getRenderedTime()
245  {
246  return $this->renderedtime;
247  }
248 
254  function setLastChange($a_lastchange)
255  {
256  $this->lastchange = $a_lastchange;
257  }
258 
264  function getLastChange()
265  {
266  return $this->lastchange;
267  }
268 
274  public function setLastChangeUser($a_val)
275  {
276  $this->last_change_user = $a_val;
277  }
278 
284  public function getLastChangeUser()
285  {
286  return $this->last_change_user;
287  }
288 
294  function setShowActivationInfo($a_val)
295  {
296  $this->show_page_act_info = $a_val;
297  }
298 
305  {
306  return $this->show_page_act_info;
307  }
308 
312  function read()
313  {
314  global $ilDB;
315 
316  $this->setActive(true);
317  if ($this->old_nr == 0)
318  {
319  $query = "SELECT * FROM page_object".
320  " WHERE page_id = ".$ilDB->quote($this->id, "integer").
321  " AND parent_type=".$ilDB->quote($this->getParentType(), "text").
322  " AND lang = ".$ilDB->quote($this->getLanguage(), "text");
323  $pg_set = $this->ilias->db->query($query);
324  $this->page_record = $ilDB->fetchAssoc($pg_set);
325  $this->setActive($this->page_record["active"]);
326  $this->setActivationStart($this->page_record["activation_start"]);
327  $this->setActivationEnd($this->page_record["activation_end"]);
328  $this->setShowActivationInfo($this->page_record["show_activation_info"]);
329  }
330  else
331  {
332  $query = "SELECT * FROM page_history".
333  " WHERE page_id = ".$ilDB->quote($this->id, "integer").
334  " AND parent_type=".$ilDB->quote($this->getParentType(), "text").
335  " AND nr = ".$ilDB->quote((int) $this->old_nr, "integer").
336  " AND lang = ".$ilDB->quote($this->getLanguage(), "text");
337  $pg_set = $ilDB->query($query);
338  $this->page_record = $ilDB->fetchAssoc($pg_set);
339  }
340  if (!$this->page_record)
341  {
342  include_once("./Services/COPage/exceptions/class.ilCOPageNotFoundException.php");
343  throw new ilCOPageNotFoundException("Error: Page ".$this->id." is not in database".
344  " (parent type ".$this->getParentType().").");
345  }
346 
347  $this->xml = $this->page_record["content"];
348  $this->setParentId($this->page_record["parent_id"]);
349  $this->last_change_user = $this->page_record["last_change_user"];
350  $this->create_user = $this->page_record["create_user"];
351  $this->setRenderedContent($this->page_record["rendered_content"]);
352  $this->setRenderMd5($this->page_record["render_md5"]);
353  $this->setRenderedTime($this->page_record["rendered_time"]);
354  $this->setLastChange($this->page_record["last_change"]);
355 
356  }
357 
365  static function _exists($a_parent_type, $a_id, $a_lang = "", $a_no_cache = false)
366  {
367  global $ilDB;
368  if (!$a_no_cache && isset(self::$exists[$a_parent_type.":".$a_id.":".$a_lang]))
369  {
370  return self::$exists[$a_parent_type.":".$a_id.":".$a_lang];
371  }
372 
373  $and_lang = "";
374  if ($a_lang != "")
375  {
376  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
377  }
378 
379  $query = "SELECT page_id FROM page_object WHERE page_id = ".$ilDB->quote($a_id, "integer")." ".
380  "AND parent_type = ".$ilDB->quote($a_parent_type, "text").$and_lang;
381  $set = $ilDB->query($query);
382  if ($row = $ilDB->fetchAssoc($set))
383  {
384  self::$exists[$a_parent_type.":".$a_id.":".$a_lang] = true;
385  return true;
386  }
387  else
388  {
389  self::$exists[$a_parent_type.":".$a_id.":".$a_lang] = false;
390  return false;
391  }
392  }
393 
401  static function _existsAndNotEmpty($a_parent_type, $a_id, $a_lang = "-")
402  {
403  global $ilDB;
404 
405  include_once("./Services/COPage/classes/class.ilPageUtil.php");
406 
407  return ilPageUtil::_existsAndNotEmpty($a_parent_type, $a_id, $a_lang);
408  }
409 
410  function buildDom($a_force = false)
411  {
412  if ($this->dom_builded && !$a_force)
413  {
414  return;
415  }
416 
417 //echo "\n<br>buildDomWith:".$this->getId().":xml:".$this->getXMLContent(true).":<br>";
418 
419  $this->dom = @domxml_open_mem($this->getXMLContent(true), DOMXML_LOAD_VALIDATING, $error);
420 
421  $xpc = xpath_new_context($this->dom);
422  $path = "//PageObject";
423  $res =& xpath_eval($xpc, $path);
424  if (count($res->nodeset) == 1)
425  {
426  $this->node =& $res->nodeset[0];
427  }
428 
429  if (empty($error))
430  {
431  $this->dom_builded = true;
432  return true;
433  }
434  else
435  {
436  return $error;
437  }
438  }
439 
440  function freeDom()
441  {
442  //$this->dom->free();
443  unset($this->dom);
444  }
445 
449  function getDom()
450  {
451  return $this->dom;
452  }
453 
460  function getDomDoc()
461  {
462  if ($this->dom instanceof php4DOMDocument)
463  {
464  return $this->dom->myDOMDocument;
465  }
466 
467  return $this->dom;
468  }
469 
470 
474  function setId($a_id)
475  {
476  $this->id = $a_id;
477  }
478 
479  function getId()
480  {
481  return $this->id;
482  }
483 
484  function setParentId($a_id)
485  {
486  $this->parent_id = $a_id;
487  }
488 
489  function getParentId()
490  {
491  return $this->parent_id;
492  }
493 
494  function addUpdateListener(&$a_object, $a_method, $a_parameters = "")
495  {
497  $this->update_listeners[$cnt]["object"] =& $a_object;
498  $this->update_listeners[$cnt]["method"] = $a_method;
499  $this->update_listeners[$cnt]["parameters"] = $a_parameters;
500  $this->update_listener_cnt++;
501  }
502 
504  {
505  for($i=0; $i<$this->update_listener_cnt; $i++)
506  {
507  $object =& $this->update_listeners[$i]["object"];
508  $method = $this->update_listeners[$i]["method"];
509  $parameters = $this->update_listeners[$i]["parameters"];
510  $object->$method($parameters);
511  }
512  }
513 
519  function setActive($a_active)
520  {
521  $this->active = $a_active;
522  }
523 
529  function getActive($a_check_scheduled_activation = false)
530  {
531  if ($a_check_scheduled_activation && !$this->active)
532  {
533  include_once("./Services/Calendar/classes/class.ilDateTime.php");
534  $start = new ilDateTime($this->getActivationStart(), IL_CAL_DATETIME);
535  $end = new ilDateTime($this->getActivationEnd(), IL_CAL_DATETIME);
536  $now = new ilDateTime(time(), IL_CAL_UNIX);
537  if (!ilDateTime::_before($now, $start) && !ilDateTime::_after($now, $end))
538  {
539  return true;
540  }
541  }
542  return $this->active;
543  }
544 
550  static function preloadActivationDataByParentId($a_parent_id)
551  {
552  global $ilDB;
553 
554  $set = $ilDB->query("SELECT page_id, parent_type, lang, active, activation_start, activation_end, show_activation_info FROM page_object ".
555  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer")
556  );
557  while ($rec = $ilDB->fetchAssoc($set))
558  {
559  self::$activation_data[$rec["page_id"].":".$rec["parent_type"].":".$rec["lang"]] = $rec;
560  }
561  }
562 
563 
567  static function _lookupActive($a_id, $a_parent_type, $a_check_scheduled_activation = false, $a_lang = "-")
568  {
569  global $ilDB;
570 
571  // language must be set at least to "-"
572  if ($a_lang == "")
573  {
574  $a_lang = "-";
575  }
576 
577  if (isset(self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang]))
578  {
579  $rec = self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang];
580  }
581  else
582  {
583  $set = $ilDB->queryF("SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s".
584  " AND parent_type = %s AND lang = %s",
585  array("integer", "text", "text"),
586  array($a_id, $a_parent_type, $a_lang));
587  $rec = $ilDB->fetchAssoc($set);
588  }
589 
590 
591  $rec["n"] = ilUtil::now();
592 
593  if (!$rec["active"] && $a_check_scheduled_activation)
594  {
595  if ($rec["n"] >= $rec["activation_start"] &&
596  $rec["n"] <= $rec["activation_end"])
597  {
598  return true;
599  }
600  }
601 
602  return $rec["active"];
603  }
604 
608  static function _isScheduledActivation($a_id, $a_parent_type, $a_lang = "-")
609  {
610  global $ilDB;
611 
612  // language must be set at least to "-"
613  if ($a_lang == "")
614  {
615  $a_lang = "-";
616  }
617 
618 //echo "<br>";
619 //var_dump(self::$activation_data); exit;
620  if (isset(self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang]))
621  {
622  $rec = self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang];
623  }
624  else
625  {
626  $set = $ilDB->queryF("SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s".
627  " AND parent_type = %s AND lang = %s", array("integer", "text", "text"),
628  array($a_id, $a_parent_type, $a_lang));
629  $rec = $ilDB->fetchAssoc($set);
630  }
631 
632  if (!$rec["active"] && $rec["activation_start"] != "")
633  {
634  return true;
635  }
636 
637  return false;
638  }
639 
643  function _writeActive($a_id, $a_parent_type, $a_active, $a_reset_scheduled_activation = true, $a_lang = "-")
644  {
645  global $ilDB;
646 
647  // language must be set at least to "-"
648  if ($a_lang == "")
649  {
650  $a_lang = "-";
651  }
652 
653  if ($a_reset_scheduled_activation)
654  {
655  $st = $ilDB->manipulateF("UPDATE page_object SET active = %s, activation_start = %s, ".
656  " activation_end = %s WHERE page_id = %s".
657  " AND parent_type = %s AND lang = %s", array("boolean", "timestamp", "timestamp", "integer", "text", "text"),
658  array($a_active, null, null, $a_id, $a_parent_type, $a_lang));
659  }
660  else
661  {
662  $st = $ilDB->prepareManip("UPDATE page_object SET active = %s WHERE page_id = %s".
663  " AND parent_type = %s AND lang = %s", array("boolean", "integer", "text", "text"),
664  array($a_active, $a_id, $a_parent_type, $a_lang));
665  }
666  }
667 
671  function _lookupActivationData($a_id, $a_parent_type, $a_lang = "-")
672  {
673  global $ilDB;
674 
675  // language must be set at least to "-"
676  if ($a_lang == "")
677  {
678  $a_lang = "-";
679  }
680 
681  if (isset(self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang]))
682  {
683  $rec = self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang];
684  }
685  else
686  {
687  $set = $ilDB->queryF("SELECT active, activation_start, activation_end, show_activation_info FROM page_object WHERE page_id = %s".
688  " AND parent_type = %s AND lang = %s",
689  array("integer", "text", "text"),
690  array($a_id, $a_parent_type, $a_lang));
691  $rec = $ilDB->fetchAssoc($set);
692  }
693 
694  return $rec;
695  }
696 
697 
701  static function lookupParentId($a_id, $a_type)
702  {
703  global $ilDB;
704 
705  $res = $ilDB->query("SELECT parent_id FROM page_object WHERE page_id = ".$ilDB->quote($a_id, "integer")." ".
706  "AND parent_type=".$ilDB->quote($a_type, "text"));
707  $rec = $ilDB->fetchAssoc($res);
708  return $rec["parent_id"];
709  }
710 
714  function _writeParentId($a_parent_type, $a_pg_id, $a_par_id)
715  {
716  global $ilDB;
717 
718  $st = $ilDB->manipulateF("UPDATE page_object SET parent_id = %s WHERE page_id = %s".
719  " AND parent_type = %s", array("integer", "integer", "text"),
720  array($a_par_id, $a_pg_id, $a_parent_type));
721  }
722 
728  function setActivationStart($a_activationstart)
729  {
730  if ($a_activationstart == "")
731  {
732  $a_activationstart = null;
733  }
734  $this->activationstart = $a_activationstart;
735  }
736 
743  {
744  return $this->activationstart;
745  }
746 
752  function setActivationEnd($a_activationend)
753  {
754  if ($a_activationend == "")
755  {
756  $a_activationend = null;
757  }
758  $this->activationend = $a_activationend;
759  }
760 
766  function getActivationEnd()
767  {
768  return $this->activationend;
769  }
770 
779  function getContentObject($a_hier_id, $a_pc_id = "")
780  {
781  $cont_node = $this->getContentNode($a_hier_id, $a_pc_id);
782  if (!is_object($cont_node))
783  {
784  return false;
785  }
786  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
787  $node_name = $cont_node->node_name();
788  if ($node_name == "PageObject")
789  {
790  return null;
791  }
792  if ($node_name == "PageContent")
793  {
794  $child_node = $cont_node->first_child();
795  $node_name = $child_node->node_name();
796  }
797 
798  // table extra handling (@todo: get rid of it)
799  if ($node_name == "Table")
800  {
801  if ($child_node->get_attribute("DataTable") == "y")
802  {
803  require_once("./Services/COPage/classes/class.ilPCDataTable.php");
804  $tab = new ilPCDataTable($this);
805  $tab->setNode($cont_node);
806  $tab->setHierId($a_hier_id);
807  }
808  else
809  {
810  require_once("./Services/COPage/classes/class.ilPCTable.php");
811  $tab = new ilPCTable($this);
812  $tab->setNode($cont_node);
813  $tab->setHierId($a_hier_id);
814  }
815  $tab->setPcId($a_pc_id);
816  return $tab;
817  }
818 
819  // media extra handling (@todo: get rid of it)
820  if ($node_name == "MediaObject")
821  {
822  if ($_GET["pgEdMediaMode"] != "") {echo "ilPageObject::error media"; exit;}
823 
824  //require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
825  require_once("./Services/COPage/classes/class.ilPCMediaObject.php");
826 
827  $mal_node =& $child_node->first_child();
828 //echo "ilPageObject::getContentObject:nodename:".$mal_node->node_name().":<br>";
829  $id_arr = explode("_", $mal_node->get_attribute("OriginId"));
830  $mob_id = $id_arr[count($id_arr) - 1];
831 
832  // allow deletion of non-existing media objects
833  if (!ilObject::_exists($mob_id) && in_array("delete", $_POST))
834  {
835  $mob_id = 0;
836  }
837 
838  //$mob =& new ilObjMediaObject($mob_id);
839  $mob = new ilPCMediaObject($this);
840  $mob->readMediaObject($mob_id);
841 
842  //$mob->setDom($this->dom);
843  $mob->setNode($cont_node);
844  $mob->setHierId($a_hier_id);
845  $mob->setPcId($a_pc_id);
846  return $mob;
847  }
848 
849  //
850  // generic procedure
851  //
852 
853  $pc_def = ilCOPagePCDef::getPCDefinitionByName($node_name);
854 
855  // check if pc definition has been found
856  if (!is_array($pc_def))
857  {
858  include_once("./Services/COPage/exceptions/class.ilCOPageUnknownPCTypeException.php");
859  throw new ilCOPageUnknownPCTypeException('Unknown PC Name "'.$node_name.'".');
860  }
861  $pc_class = "ilPC".$pc_def["name"];
862  $pc_path = "./".$pc_def["component"]."/".$pc_def["directory"]."/class.".$pc_class.".php";
863  require_once($pc_path);
864  $pc = new $pc_class($this);
865  $pc->setNode($cont_node);
866  $pc->setHierId($a_hier_id);
867  $pc->setPcId($a_pc_id);
868  return $pc;
869  }
870 
877  function &getContentNode($a_hier_id, $a_pc_id = "")
878  {
879  $xpc = xpath_new_context($this->dom);
880  if($a_hier_id == "pg")
881  {
882  return $this->node;
883  }
884  else
885  {
886  // get per pc id
887  if ($a_pc_id != "")
888  {
889  $path = "//*[@PCID = '$a_pc_id']";
890  $res =& xpath_eval($xpc, $path);
891  if (count($res->nodeset) == 1)
892  {
893  $cont_node =& $res->nodeset[0];
894  return $cont_node;
895  }
896  }
897 
898  // fall back to hier id
899  $path = "//*[@HierId = '$a_hier_id']";
900  $res =& xpath_eval($xpc, $path);
901  if (count($res->nodeset) == 1)
902  {
903  $cont_node =& $res->nodeset[0];
904  return $cont_node;
905  }
906  }
907  }
908 
915  function checkForTag($a_content_tag, $a_hier_id, $a_pc_id = "")
916  {
917  $xpc = xpath_new_context($this->dom);
918  // get per pc id
919  if ($a_pc_id != "")
920  {
921  $path = "//*[@PCID = '$a_pc_id']//".$a_content_tag;
922  $res = xpath_eval($xpc, $path);
923  if (count($res->nodeset) > 0)
924  {
925  return true;
926  }
927  }
928 
929  // fall back to hier id
930  $path = "//*[@HierId = '$a_hier_id']//".$a_content_tag;
931  $res =& xpath_eval($xpc, $path);
932  if (count($res->nodeset) > 0)
933  {
934  return true;
935  }
936  return false;
937  }
938 
939  // only for test purposes
940  function lookforhier($a_hier_id)
941  {
942  $xpc = xpath_new_context($this->dom);
943  $path = "//*[@HierId = '$a_hier_id']";
944  $res =& xpath_eval($xpc, $path);
945  if (count($res->nodeset) == 1)
946  return "YES";
947  else
948  return "NO";
949  }
950 
951 
952  function &getNode()
953  {
954  return $this->node;
955  }
956 
957 
966  function setXMLContent($a_xml, $a_encoding = "UTF-8")
967  {
968  $this->encoding = $a_encoding;
969  $this->xml = $a_xml;
970  }
971 
978  function appendXMLContent($a_xml)
979  {
980  $this->xml.= $a_xml;
981  }
982 
983 
987  function getXMLContent($a_incl_head = false)
988  {
989  // build full http path for XML DOCTYPE header.
990  // Under windows a relative path doesn't work :-(
991  if($a_incl_head)
992  {
993 //echo "+".$this->encoding."+";
994  $enc_str = (!empty($this->encoding))
995  ? "encoding=\"".$this->encoding."\""
996  : "";
997  return "<?xml version=\"1.0\" $enc_str ?>".
998  "<!DOCTYPE PageObject SYSTEM \"".ILIAS_ABSOLUTE_PATH."/xml/".$this->cur_dtd."\">".
999  $this->xml;
1000  }
1001  else
1002  {
1003  return $this->xml;
1004  }
1005  }
1006 
1011  function copyXmlContent($a_clone_mobs = false)
1012  {
1013  $xml = $this->getXmlContent();
1014  $temp_dom = domxml_open_mem('<?xml version="1.0" encoding="UTF-8"?>'.$xml,
1015  DOMXML_LOAD_PARSING, $error);
1016  if(empty($error))
1017  {
1018  $this->handleCopiedContent($temp_dom, true, $a_clone_mobs);
1019  }
1020  $xml = $temp_dom->dump_mem(0, $this->encoding);
1021  $xml = eregi_replace("<\?xml[^>]*>","",$xml);
1022  $xml = eregi_replace("<!DOCTYPE[^>]*>","",$xml);
1023 
1024  return $xml;
1025  }
1026 
1027 // @todo 1: begin: generalize, remove concrete dependencies
1028 
1038  function handleCopiedContent($a_dom, $a_self_ass = true, $a_clone_mobs = false)
1039  {
1040  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1042 
1043  // handle question elements
1044  if ($a_self_ass)
1045  {
1046  $this->newQuestionCopies($a_dom);
1047  }
1048  else
1049  {
1050  $this->removeQuestions($a_dom);
1051  }
1052 
1053  // handle interactive images
1054  $this->newIIMCopies($a_dom);
1055 
1056  // handle media objects
1057  if ($a_clone_mobs)
1058  {
1059  $this->newMobCopies($a_dom);
1060  }
1061 
1062 // @todo 1: move all functions from above to the new domdoc
1063  if ($a_dom instanceof php4DOMDocument)
1064  {
1065  $a_dom = $a_dom->myDOMDocument;
1066  }
1067  foreach ($defs as $def)
1068  {
1070  $cl = $def["pc_class"];
1071  $cl::handleCopiedContent($a_dom, $a_self_ass, $a_clone_mobs);
1072  }
1073 
1074  }
1075 
1080  function newIIMCopies($temp_dom)
1081  {
1082  // Get question IDs
1083  $path = "//InteractiveImage/MediaAlias";
1084  $xpc = xpath_new_context($temp_dom);
1085  $res = & xpath_eval($xpc, $path);
1086 
1087  $q_ids = array();
1088  include_once("./Services/Link/classes/class.ilInternalLink.php");
1089  for ($i = 0; $i < count ($res->nodeset); $i++)
1090  {
1091  $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1092 
1093  $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1094  $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1095 
1096  if (!($inst_id > 0))
1097  {
1098  if ($mob_id > 0)
1099  {
1100  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1101  $media_object = new ilObjMediaObject($mob_id);
1102 
1103  // now copy this question and change reference to
1104  // new question id
1105  $new_mob = $media_object->duplicate();
1106 
1107  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_".$new_mob->getId());
1108  }
1109  }
1110  }
1111  }
1112 
1116  function newMobCopies($temp_dom)
1117  {
1118  // Get question IDs
1119  $path = "//MediaObject/MediaAlias";
1120  $xpc = xpath_new_context($temp_dom);
1121  $res = & xpath_eval($xpc, $path);
1122 
1123  $q_ids = array();
1124  include_once("./Services/Link/classes/class.ilInternalLink.php");
1125  for ($i = 0; $i < count ($res->nodeset); $i++)
1126  {
1127  $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1128 
1129  $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1130  $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1131 
1132  if (!($inst_id > 0))
1133  {
1134  if ($mob_id > 0)
1135  {
1136  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1137  $media_object = new ilObjMediaObject($mob_id);
1138 
1139  // now copy this question and change reference to
1140  // new question id
1141  $new_mob = $media_object->duplicate();
1142 
1143  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_".$new_mob->getId());
1144  }
1145  }
1146  }
1147  }
1148 
1153  function newQuestionCopies(&$temp_dom)
1154  {
1155  // Get question IDs
1156  $path = "//Question";
1157  $xpc = xpath_new_context($temp_dom);
1158  $res = & xpath_eval($xpc, $path);
1159 
1160  $q_ids = array();
1161  include_once("./Services/Link/classes/class.ilInternalLink.php");
1162  for ($i = 0; $i < count ($res->nodeset); $i++)
1163  {
1164  $qref = $res->nodeset[$i]->get_attribute("QRef");
1165 
1166  $inst_id = ilInternalLink::_extractInstOfTarget($qref);
1168 
1169  if (!($inst_id > 0))
1170  {
1171  if ($q_id > 0)
1172  {
1173  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1174  $question = assQuestion::_instantiateQuestion($q_id);
1175  // check due to #16557
1176  if (is_object($question) && $question->isComplete())
1177  {
1178  // check if page for question exists
1179  // due to a bug in early 4.2.x version this is possible
1180  if (!ilPageObject::_exists("qpl", $q_id))
1181  {
1182  $question->createPageObject();
1183  }
1184 
1185  // now copy this question and change reference to
1186  // new question id
1187  $duplicate_id = $question->duplicate(false);
1188  $res->nodeset[$i]->set_attribute("QRef", "il__qst_".$duplicate_id);
1189  }
1190  }
1191  }
1192  }
1193  }
1194 
1201  function removeQuestions(&$temp_dom)
1202  {
1203  // Get question IDs
1204  $path = "//Question";
1205  $xpc = xpath_new_context($temp_dom);
1206  $res = & xpath_eval($xpc, $path);
1207  for ($i = 0; $i < count ($res->nodeset); $i++)
1208  {
1209  $parent_node = $res->nodeset[$i]->parent_node();
1210  $parent_node->unlink_node($parent_node);
1211  }
1212  }
1213 
1214 // @todo: end
1215 
1223  {
1224  // Get question IDs
1225  $this->buildDom();
1226  $path = "//PageContent";
1227  $xpc = xpath_new_context($this->dom);
1228  $res = & xpath_eval($xpc, $path);
1229  return count ($res->nodeset);
1230  }
1231 
1236  function getXMLFromDom($a_incl_head = false, $a_append_mobs = false, $a_append_bib = false,
1237  $a_append_str = "", $a_omit_pageobject_tag = false)
1238  {
1239  if ($a_incl_head)
1240  {
1241 //echo "\n<br>#".$this->encoding."#";
1242  return $this->dom->dump_mem(0, $this->encoding);
1243  }
1244  else
1245  {
1246  // append multimedia object elements
1247  if ($a_append_mobs || $a_append_bib || $a_append_link_info)
1248  {
1249  $mobs = "";
1250  $bibs = "";
1251  if ($a_append_mobs)
1252  {
1253  $mobs =& $this->getMultimediaXML();
1254  }
1255  if ($a_append_bib)
1256  {
1257 // deprecated
1258 // $bibs =& $this->getBibliographyXML();
1259  }
1260  $trans =& $this->getLanguageVariablesXML();
1261  return "<dummy>".$this->dom->dump_node($this->node).$mobs.$bibs.$trans.$a_append_str."</dummy>";
1262  }
1263  else
1264  {
1265  if (is_object($this->dom))
1266  {
1267  if ($a_omit_pageobject_tag)
1268  {
1269  $xml = "";
1270  $childs =& $this->node->child_nodes();
1271  for($i = 0; $i < count($childs); $i++)
1272  {
1273  $xml.= $this->dom->dump_node($childs[$i]);
1274  }
1275  return $xml;
1276  }
1277  else
1278  {
1279  $xml = $this->dom->dump_mem(0, $this->encoding);
1280  $xml = eregi_replace("<\?xml[^>]*>","",$xml);
1281  $xml = eregi_replace("<!DOCTYPE[^>]*>","",$xml);
1282 
1283  return $xml;
1284 
1285  // don't use dump_node. This gives always entities.
1286  //return $this->dom->dump_node($this->node);
1287  }
1288  }
1289  else
1290  {
1291  return "";
1292  }
1293  }
1294  }
1295  }
1296 
1301  {
1302  global $lng;
1303 
1304  $xml = "<LVs>";
1305  $lang_vars = array(
1306  "ed_paste_clip", "ed_edit", "ed_edit_prop", "ed_delete", "ed_moveafter",
1307  "ed_movebefore", "ed_go", "ed_class", "ed_width", "ed_align_left",
1308  "ed_align_right", "ed_align_center", "ed_align_left_float",
1309  "ed_align_right_float", "ed_delete_item", "ed_new_item_before",
1310  "ed_new_item_after", "ed_copy_clip", "please_select", "ed_split_page",
1311  "ed_item_up", "ed_item_down", "ed_split_page_next","ed_enable",
1312  "de_activate", "ed_paste", "ed_edit_multiple", "ed_cut", "ed_copy", "ed_insert_templ",
1313  "ed_click_to_add_pg", "download");
1314 
1315  // collect lang vars from pc elements
1316  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1318  foreach ($defs as $def)
1319  {
1320  $lang_vars[] = "pc_".$def["pc_type"];
1321  $lang_vars[] = "ed_insert_".$def["pc_type"];
1322 
1324  $cl = $def["pc_class"];
1325  $lvs = call_user_func($def["pc_class"].'::getLangVars');
1326  foreach ($lvs as $lv)
1327  {
1328  $lang_vars[] = $lv;
1329  }
1330  }
1331 
1332  foreach ($lang_vars as $lang_var)
1333  {
1334  $this->appendLangVarXML($xml, $lang_var);
1335  }
1336 
1337  $xml.= "</LVs>";
1338 
1339  return $xml;
1340  }
1341 
1342  function appendLangVarXML(&$xml, $var)
1343  {
1344  global $lng;
1345 
1346  $xml.= "<LV name=\"$var\" value=\"".$lng->txt("cont_".$var)."\"/>";
1347  }
1348 
1349 // @todo begin: move this to paragraph class
1350 
1352  {
1353  if($this->dom)
1354  {
1355  require_once("./Services/COPage/classes/class.ilPCParagraph.php");
1356  $xpc = xpath_new_context($this->dom);
1357  $path = "//Paragraph[1]";
1358  $res =& xpath_eval($xpc, $path);
1359  if (count($res->nodeset) > 0)
1360  {
1361  $cont_node =& $res->nodeset[0]->parent_node();
1362  $par =& new ilPCParagraph($this);
1363  $par->setNode($cont_node);
1364  return $par->getText();
1365  }
1366  }
1367  return "";
1368  }
1369 
1376  function setParagraphContent($a_hier_id, $a_content)
1377  {
1378  $node = $this->getContentNode($a_hier_id);
1379  if (is_object($node))
1380  {
1381  $node->set_content($a_content);
1382  }
1383  }
1384 
1385 // @todo end
1386 
1387 
1396  // @todo: can we do this better
1397  function setContainsIntLink($a_contains_link)
1398  {
1399  $this->contains_int_link = $a_contains_link;
1400  }
1401 
1406  // @todo: can we do this better
1407  function containsIntLink()
1408  {
1409  return $this->contains_int_link;
1410  }
1411 
1417  function setImportMode($a_val)
1418  {
1419  $this->import_mode = $a_val;
1420  }
1421 
1427  function getImportMode()
1428  {
1429  return $this->import_mode;
1430  }
1431 
1432  function needsImportParsing($a_parse = "")
1433  {
1434 
1435  if ($a_parse === true)
1436  {
1437  $this->needs_parsing = true;
1438  }
1439  if ($a_parse === false)
1440  {
1441  $this->needs_parsing = false;
1442  }
1443  return $this->needs_parsing;
1444  }
1445 
1451  // @todo: can we do this better
1452  public function setContainsQuestion($a_val)
1453  {
1454  $this->contains_question = $a_val;
1455  }
1456 
1462  public function getContainsQuestion()
1463  {
1464  return $this->contains_question;
1465  }
1466 
1467 
1472  // @todo: move to media class
1473  function collectMediaObjects($a_inline_only = true)
1474  {
1475 //echo htmlentities($this->getXMLFromDom());
1476  // determine all media aliases of the page
1477  $xpc = xpath_new_context($this->dom);
1478  $path = "//MediaObject/MediaAlias";
1479  $res =& xpath_eval($xpc, $path);
1480  $mob_ids = array();
1481  for($i = 0; $i < count($res->nodeset); $i++)
1482  {
1483  $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1484  $mob_id = $id_arr[count($id_arr) - 1];
1485  $mob_ids[$mob_id] = $mob_id;
1486  }
1487 
1488  // determine all media aliases of interactive images
1489  $xpc = xpath_new_context($this->dom);
1490  $path = "//InteractiveImage/MediaAlias";
1491  $res =& xpath_eval($xpc, $path);
1492  for($i = 0; $i < count($res->nodeset); $i++)
1493  {
1494  $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1495  $mob_id = $id_arr[count($id_arr) - 1];
1496  $mob_ids[$mob_id] = $mob_id;
1497  }
1498 
1499  // determine all inline internal media links
1500  $xpc = xpath_new_context($this->dom);
1501  $path = "//IntLink[@Type = 'MediaObject']";
1502  $res =& xpath_eval($xpc, $path);
1503 
1504  for($i = 0; $i < count($res->nodeset); $i++)
1505  {
1506  if (($res->nodeset[$i]->get_attribute("TargetFrame") == "") ||
1507  (!$a_inline_only))
1508  {
1509  $target = $res->nodeset[$i]->get_attribute("Target");
1510  $id_arr = explode("_", $target);
1511  if (($id_arr[1] == IL_INST_ID) ||
1512  (substr($target, 0, 4) == "il__"))
1513  {
1514  $mob_id = $id_arr[count($id_arr) - 1];
1515  if (ilObject::_exists($mob_id))
1516  {
1517  $mob_ids[$mob_id] = $mob_id;
1518  }
1519  }
1520  }
1521  }
1522 
1523  return $mob_ids;
1524  }
1525 
1526 
1530  // @todo: can we do this better?
1531  function getInternalLinks($a_cnt_multiple = false)
1532  {
1533  // get all internal links of the page
1534  $xpc = xpath_new_context($this->dom);
1535  $path = "//IntLink";
1536  $res = xpath_eval($xpc, $path);
1537 
1538  $links = array();
1539  $cnt_multiple = 1;
1540  for($i = 0; $i < count($res->nodeset); $i++)
1541  {
1542  $add = "";
1543  if ($a_cnt_multiple)
1544  {
1545  $add = ":".$cnt_multiple;
1546  }
1547  $target = $res->nodeset[$i]->get_attribute("Target");
1548  $type = $res->nodeset[$i]->get_attribute("Type");
1549  $targetframe = $res->nodeset[$i]->get_attribute("TargetFrame");
1550  $anchor = $res->nodeset[$i]->get_attribute("Anchor");
1551  $links[$target.":".$type.":".$targetframe.":".$anchor.$add] =
1552  array("Target" => $target, "Type" => $type,
1553  "TargetFrame" => $targetframe, "Anchor" => $anchor);
1554 
1555  // get links (image map areas) for inline media objects
1556  if ($type == "MediaObject" && $targetframe == "")
1557  {
1558  if (substr($target, 0, 4) =="il__")
1559  {
1560  $id_arr = explode("_", $target);
1561  $id = $id_arr[count($id_arr) - 1];
1562 
1563  $med_links = ilMediaItem::_getMapAreasIntLinks($id);
1564  foreach($med_links as $key => $med_link)
1565  {
1566  $links[$key] = $med_link;
1567  }
1568  }
1569 
1570  }
1571 //echo "<br>-:".$target.":".$type.":".$targetframe.":-";
1572  $cnt_multiple++;
1573  }
1574  unset($xpc);
1575 
1576  // get all media aliases
1577  $xpc = xpath_new_context($this->dom);
1578  $path = "//MediaAlias";
1579  $res =& xpath_eval($xpc, $path);
1580 
1581  require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
1582  for($i = 0; $i < count($res->nodeset); $i++)
1583  {
1584  $oid = $res->nodeset[$i]->get_attribute("OriginId");
1585  if (substr($oid, 0, 4) =="il__")
1586  {
1587  $id_arr = explode("_", $oid);
1588  $id = $id_arr[count($id_arr) - 1];
1589 
1590  $med_links = ilMediaItem::_getMapAreasIntLinks($id);
1591  foreach($med_links as $key => $med_link)
1592  {
1593  $links[$key] = $med_link;
1594  }
1595  }
1596  }
1597  unset($xpc);
1598 
1599  return $links;
1600  }
1601 
1606  // @todo: move to media class
1607  function getMultimediaXML()
1608  {
1609  $mob_ids = $this->collectMediaObjects();
1610 
1611  // get xml of corresponding media objects
1612  $mobs_xml = "";
1613  require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1614  foreach($mob_ids as $mob_id => $dummy)
1615  {
1616  if (ilObject::_lookupType($mob_id) == "mob")
1617  {
1618  $mob_obj =& new ilObjMediaObject($mob_id);
1619  $mobs_xml .= $mob_obj->getXML(IL_MODE_OUTPUT);
1620  }
1621  }
1622 //var_dump($mobs_xml);
1623  return $mobs_xml;
1624  }
1625 
1629  // @todo: move to media class
1630  function getMediaAliasElement($a_mob_id, $a_nr = 1)
1631  {
1632  $xpc = xpath_new_context($this->dom);
1633  $path = "//MediaObject/MediaAlias[@OriginId='il__mob_$a_mob_id']";
1634  $res =& xpath_eval($xpc, $path);
1635  $mal_node =& $res->nodeset[$a_nr - 1];
1636  $mob_node =& $mal_node->parent_node();
1637 
1638  return $this->dom->dump_node($mob_node);
1639  }
1640 
1646  function validateDom()
1647  {
1648  $this->stripHierIDs();
1649 
1650  // possible fix for #14820
1651  libxml_disable_entity_loader(false);
1652 
1653  @$this->dom->validate($error);
1654 
1655  return $error;
1656  }
1657 
1673  // @todo: can we do this better? remove dependencies?
1674  function addHierIDs()
1675  {
1676  $this->hier_ids = array();
1677  $this->first_row_ids = array();
1678  $this->first_col_ids = array();
1679  $this->list_item_ids = array();
1680  $this->file_item_ids = array();
1681 
1682  // set hierarchical ids for Paragraphs, Tables, TableRows and TableData elements
1683  $xpc = xpath_new_context($this->dom);
1684  //$path = "//Paragraph | //Table | //TableRow | //TableData";
1685 
1686  $sep = $path = "";
1687  foreach ($this->id_elements as $el)
1688  {
1689  $path.= $sep."//".$el;
1690  $sep = " | ";
1691  }
1692 
1693  $res =& xpath_eval($xpc, $path);
1694  for($i = 0; $i < count($res->nodeset); $i++)
1695  {
1696  $cnode = $res->nodeset[$i];
1697  $ctag = $cnode->node_name();
1698 
1699  // get hierarchical id of previous sibling
1700  $sib_hier_id = "";
1701  while($cnode =& $cnode->previous_sibling())
1702  {
1703  if (($cnode->node_type() == XML_ELEMENT_NODE)
1704  && $cnode->has_attribute("HierId"))
1705  {
1706  $sib_hier_id = $cnode->get_attribute("HierId");
1707  //$sib_hier_id = $id_attr->value();
1708  break;
1709  }
1710  }
1711 
1712  if ($sib_hier_id != "") // set id to sibling id "+ 1"
1713  {
1714  require_once("./Services/COPage/classes/class.ilPageContent.php");
1715  $node_hier_id = ilPageContent::incEdId($sib_hier_id);
1716  $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1717  $this->hier_ids[] = $node_hier_id;
1718  if ($ctag == "TableData")
1719  {
1720  if (substr($par_hier_id,strlen($par_hier_id)-2) == "_1")
1721  {
1722  $this->first_row_ids[] = $node_hier_id;
1723  }
1724  }
1725  if ($ctag == "ListItem")
1726  {
1727  $this->list_item_ids[] = $node_hier_id;
1728  }
1729  if ($ctag == "FileItem")
1730  {
1731  $this->file_item_ids[] = $node_hier_id;
1732  }
1733  }
1734  else // no sibling -> node is first child
1735  {
1736  // get hierarchical id of next parent
1737  $cnode = $res->nodeset[$i];
1738  $par_hier_id = "";
1739  while($cnode =& $cnode->parent_node())
1740  {
1741  if (($cnode->node_type() == XML_ELEMENT_NODE)
1742  && $cnode->has_attribute("HierId"))
1743  {
1744  $par_hier_id = $cnode->get_attribute("HierId");
1745  //$par_hier_id = $id_attr->value();
1746  break;
1747  }
1748  }
1749 //echo "<br>par:".$par_hier_id." ($ctag)";
1750  if (($par_hier_id != "") && ($par_hier_id != "pg")) // set id to parent_id."_1"
1751  {
1752  $node_hier_id = $par_hier_id."_1";
1753  $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1754  $this->hier_ids[] = $node_hier_id;
1755  if ($ctag == "TableData")
1756  {
1757  $this->first_col_ids[] = $node_hier_id;
1758  if (substr($par_hier_id,strlen($par_hier_id)-2) == "_1")
1759  {
1760  $this->first_row_ids[] = $node_hier_id;
1761  }
1762  }
1763  if ($ctag == "ListItem")
1764  {
1765  $this->list_item_ids[] = $node_hier_id;
1766  }
1767  if ($ctag == "FileItem")
1768  {
1769  $this->file_item_ids[] = $node_hier_id;
1770  }
1771 
1772  }
1773  else // no sibling, no parent -> first node
1774  {
1775  $node_hier_id = "1";
1776  $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1777  $this->hier_ids[] = $node_hier_id;
1778  }
1779  }
1780  }
1781 
1782  // set special hierarchical id "pg" for pageobject
1783  $xpc = xpath_new_context($this->dom);
1784  $path = "//PageObject";
1785  $res =& xpath_eval($xpc, $path);
1786  for($i = 0; $i < count($res->nodeset); $i++) // should only be 1
1787  {
1788  $res->nodeset[$i]->set_attribute("HierId", "pg");
1789  $this->hier_ids[] = "pg";
1790  }
1791  unset($xpc);
1792  }
1793 
1797  function getHierIds()
1798  {
1799  return $this->hier_ids;
1800  }
1801 
1805  // @todo: move to table classes
1806  function getFirstRowIds()
1807  {
1808  return $this->first_row_ids;
1809  }
1810 
1814  // @todo: move to table classes
1816  {
1817  return $this->first_col_ids;
1818  }
1819 
1823  // @todo: move to list class
1824  function getListItemIds()
1825  {
1826  return $this->list_item_ids;
1827  }
1828 
1832  // @todo: move to file item class
1833  function getFileItemIds()
1834  {
1835  return $this->file_item_ids;
1836  }
1837 
1841  function stripHierIDs()
1842  {
1843  if(is_object($this->dom))
1844  {
1845  $xpc = xpath_new_context($this->dom);
1846  $path = "//*[@HierId]";
1847  $res =& xpath_eval($xpc, $path);
1848  for($i = 0; $i < count($res->nodeset); $i++) // should only be 1
1849  {
1850  if ($res->nodeset[$i]->has_attribute("HierId"))
1851  {
1852  $res->nodeset[$i]->remove_attribute("HierId");
1853  }
1854  }
1855  unset($xpc);
1856  }
1857  }
1858 
1862  function getHierIdsForPCIds($a_pc_ids)
1863  {
1864  if (!is_array($a_pc_ids) || count($a_pc_ids) == 0)
1865  {
1866  return array();
1867  }
1868  $ret = array();
1869 
1870  if(is_object($this->dom))
1871  {
1872  $xpc = xpath_new_context($this->dom);
1873  $path = "//*[@PCID]";
1874  $res =& xpath_eval($xpc, $path);
1875  for($i = 0; $i < count($res->nodeset); $i++) // should only be 1
1876  {
1877  $pc_id = $res->nodeset[$i]->get_attribute("PCID");
1878  if (in_array($pc_id, $a_pc_ids))
1879  {
1880  $ret[$pc_id] = $res->nodeset[$i]->get_attribute("HierId");
1881  }
1882  }
1883  unset($xpc);
1884  }
1885 //var_dump($ret);
1886  return $ret;
1887  }
1888 
1892  // @todo: move to file item class
1893  function addFileSizes()
1894  {
1895  $xpc = xpath_new_context($this->dom);
1896  $path = "//FileItem";
1897  $res =& xpath_eval($xpc, $path);
1898  for($i = 0; $i < count($res->nodeset); $i++)
1899  {
1900  $cnode =& $res->nodeset[$i];
1901  $size_node =& $this->dom->create_element("Size");
1902  $size_node =& $cnode->append_child($size_node);
1903 
1904  $childs =& $cnode->child_nodes();
1905  $size = "";
1906  for($j = 0; $j < count($childs); $j++)
1907  {
1908  if ($childs[$j]->node_name() == "Identifier")
1909  {
1910  if ($childs[$j]->has_attribute("Entry"))
1911  {
1912  $entry = $childs[$j]->get_attribute("Entry");
1913  $entry_arr = explode("_", $entry);
1914  $id = $entry_arr[count($entry_arr) - 1];
1915  require_once("./Modules/File/classes/class.ilObjFile.php");
1917  }
1918  }
1919  }
1920  $size_node->set_content($size);
1921  }
1922 
1923  unset($xpc);
1924  }
1925 
1930  // @todo: possible to improve this?
1931  function resolveIntLinks($a_link_map = null)
1932  {
1933  $changed = false;
1934 
1935  $this->log->debug("start");
1936 
1937  // resolve normal internal links
1938  $xpc = xpath_new_context($this->dom);
1939  $path = "//IntLink";
1940  $res =& xpath_eval($xpc, $path);
1941  for($i = 0; $i < count($res->nodeset); $i++)
1942  {
1943  $target = $res->nodeset[$i]->get_attribute("Target");
1944  $type = $res->nodeset[$i]->get_attribute("Type");
1945 
1946  if ($a_link_map == null)
1947  {
1948  $new_target = ilInternalLink::_getIdForImportId($type, $target);
1949  $this->log->debug("no map, type: ".$type.", target: ".$target.", new target: ".$new_target);
1950 // echo "-".$new_target."-".$type."-".$target."-"; exit;
1951  }
1952  else
1953  {
1954  $nt = explode("_", $a_link_map[$target]);
1955  $new_target = false;
1956  if ($nt[1] == IL_INST_ID)
1957  {
1958  $new_target = "il__".$nt[2]."_".$nt[3];
1959  }
1960  $this->log->debug("map, type: ".$type.", target: ".$target.", new target: ".$new_target);
1961  }
1962  if ($new_target !== false)
1963  {
1964  $res->nodeset[$i]->set_attribute("Target", $new_target);
1965  $changed = true;
1966  }
1967  else // check wether link target is same installation
1968  {
1969  if (ilInternalLink::_extractInstOfTarget($target) == IL_INST_ID &&
1970  IL_INST_ID > 0 && $type != "RepositoryItem")
1971  {
1972  $new_target = ilInternalLink::_removeInstFromTarget($target);
1973  if (ilInternalLink::_exists($type, $new_target))
1974  {
1975  $res->nodeset[$i]->set_attribute("Target", $new_target);
1976  $changed = true;
1977  }
1978  }
1979  }
1980 
1981  }
1982  unset($xpc);
1983 
1984  // resolve internal links in map areas
1985  $xpc = xpath_new_context($this->dom);
1986  $path = "//MediaAlias";
1987  $res =& xpath_eval($xpc, $path);
1988 //echo "<br><b>page::resolve</b><br>";
1989 //echo "Content:".htmlentities($this->getXMLFromDOM()).":<br>";
1990  for($i = 0; $i < count($res->nodeset); $i++)
1991  {
1992  $orig_id = $res->nodeset[$i]->get_attribute("OriginId");
1993  $id_arr = explode("_", $orig_id);
1994  $mob_id = $id_arr[count($id_arr) - 1];
1996  }
1997  return $changed;
1998  }
1999 
2006  // @todo: move to media classes?
2007  function resolveMediaAliases($a_mapping, $a_reuse_existing_by_import = false)
2008  {
2009  // resolve normal internal links
2010  $xpc = xpath_new_context($this->dom);
2011  $path = "//MediaAlias";
2012  $res =& xpath_eval($xpc, $path);
2013  $changed = false;
2014  for($i = 0; $i < count($res->nodeset); $i++)
2015  {
2016  // get the ID of the import file from the xml
2017  $old_id = $res->nodeset[$i]->get_attribute("OriginId");
2018  $old_id = explode("_", $old_id);
2019  $old_id = $old_id[count($old_id) - 1];
2020  // get the new id from the current mapping
2021  if ($a_mapping[$old_id] > 0)
2022  {
2023  $new_id = $a_mapping[$old_id];
2024  if ($a_reuse_existing_by_import)
2025  {
2026  // this should work, if the lm has been imported in a translation installation and re-exported
2027  $import_id = ilObject::_lookupImportId($new_id);
2028  $imp = explode("_", $import_id);
2029  if ($imp[1] == IL_INST_ID && $imp[2] == "mob" && ilObject::_lookupType($imp[3]) == "mob")
2030  {
2031  $new_id = $imp[3];
2032  }
2033 
2034  // now check, if the translation has been done just by changing text in the exported
2035  // translation file
2036  if ($import_id == "")
2037  {
2038  // if the old_id is also referred by the page content of the default language
2039  // we assume that this media object is unchanged
2040  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2041  $med_of_def_lang = ilObjMediaObject::_getMobsOfObject("lm:pg", $this->getId(), 0, "-");
2042  if (in_array($old_id, $med_of_def_lang))
2043  {
2044  $new_id = $old_id;
2045  }
2046  }
2047  }
2048 
2049  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_".$new_id);
2050  $changed = true;
2051  }
2052  }
2053  unset($xpc);
2054 
2055  return $changed;
2056  }
2057 
2064  // @todo: move to iim classes?
2065  function resolveIIMMediaAliases($a_mapping)
2066  {
2067  // resolve normal internal links
2068  $xpc = xpath_new_context($this->dom);
2069  $path = "//InteractiveImage/MediaAlias";
2070  $res =& xpath_eval($xpc, $path);
2071  $changed = false;
2072  for($i = 0; $i < count($res->nodeset); $i++)
2073  {
2074  $old_id = $res->nodeset[$i]->get_attribute("OriginId");
2075  if ($a_mapping[$old_id] > 0)
2076  {
2077  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_".$a_mapping[$old_id]);
2078  $changed = true;
2079  }
2080  }
2081  unset($xpc);
2082 
2083  return $changed;
2084  }
2085 
2092  // @todo: move to file classes?
2093  function resolveFileItems($a_mapping)
2094  {
2095  // resolve normal internal links
2096  $xpc = xpath_new_context($this->dom);
2097  $path = "//FileItem/Identifier";
2098  $res =& xpath_eval($xpc, $path);
2099  $changed = false;
2100  for($i = 0; $i < count($res->nodeset); $i++)
2101  {
2102  $old_id = $res->nodeset[$i]->get_attribute("Entry");
2103  $old_id = explode("_", $old_id);
2104  $old_id = $old_id[count($old_id) - 1];
2105  if ($a_mapping[$old_id] > 0)
2106  {
2107  $res->nodeset[$i]->set_attribute("Entry", "il__file_".$a_mapping[$old_id]);
2108  $changed = true;
2109  }
2110  }
2111  unset($xpc);
2112 
2113  return $changed;
2114  }
2115 
2120  // @todo: move to question classes
2121  function resolveQuestionReferences($a_mapping)
2122  {
2123  // resolve normal internal links
2124  $xpc = xpath_new_context($this->dom);
2125  $path = "//Question";
2126  $res =& xpath_eval($xpc, $path);
2127  $updated = false;
2128  for($i = 0; $i < count($res->nodeset); $i++)
2129  {
2130  $qref = $res->nodeset[$i]->get_attribute("QRef");
2131 
2132  if (isset($a_mapping[$qref]))
2133  {
2134  $res->nodeset[$i]->set_attribute("QRef", "il__qst_".$a_mapping[$qref]["pool"]);
2135  $updated = true;
2136  }
2137  }
2138  unset($xpc);
2139 
2140  return $updated;
2141  }
2142 
2143 
2150  // @todo: generalize, internal links usage info
2151  function moveIntLinks($a_from_to)
2152  {
2153  $this->buildDom();
2154 
2155  $changed = false;
2156 
2157  // resolve normal internal links
2158  $xpc = xpath_new_context($this->dom);
2159  $path = "//IntLink";
2160  $res =& xpath_eval($xpc, $path);
2161  for($i = 0; $i < count($res->nodeset); $i++)
2162  {
2163  $target = $res->nodeset[$i]->get_attribute("Target");
2164  $type = $res->nodeset[$i]->get_attribute("Type");
2165  $obj_id = ilInternalLink::_extractObjIdOfTarget($target);
2166  if ($a_from_to[$obj_id] > 0 && is_int(strpos($target, "__")))
2167  {
2168  if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg")
2169  {
2170  $res->nodeset[$i]->set_attribute("Target", "il__pg_".$a_from_to[$obj_id]);
2171  $changed = true;
2172  }
2173  if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st")
2174  {
2175  $res->nodeset[$i]->set_attribute("Target", "il__st_".$a_from_to[$obj_id]);
2176  $changed = true;
2177  }
2178  }
2179  }
2180  unset($xpc);
2181 
2182  // map areas
2183  $this->addHierIDs();
2184  $xpc = xpath_new_context($this->dom);
2185  $path = "//MediaAlias";
2186  $res =& xpath_eval($xpc, $path);
2187 
2188  require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
2189  require_once("Services/COPage/classes/class.ilMediaAliasItem.php");
2190 
2191  for($i = 0; $i < count($res->nodeset); $i++)
2192  {
2193  $media_object_node = $res->nodeset[$i]->parent_node();
2194  $page_content_node = $media_object_node->parent_node();
2195  $c_hier_id = $page_content_node->get_attribute("HierId");
2196 
2197  // first check, wheter we got instance map areas -> take these
2198  $std_alias_item = new ilMediaAliasItem($this->dom,
2199  $c_hier_id, "Standard");
2200  $areas = $std_alias_item->getMapAreas();
2201  $correction_needed = false;
2202  if (count($areas) > 0)
2203  {
2204  // check if correction needed
2205  foreach($areas as $area)
2206  {
2207  if ($area["Type"] == "PageObject" ||
2208  $area["Type"] == "StructureObject")
2209  {
2210  $t = $area["Target"];
2211  $tid = _extractObjIdOfTarget($t);
2212  if ($a_from_to[$tid] > 0)
2213  {
2214  $correction_needed = true;
2215  }
2216  }
2217  }
2218  }
2219  else
2220  {
2221  $areas = array();
2222 
2223  // get object map areas and check whether at least one must
2224  // be corrected
2225  $oid = $res->nodeset[$i]->get_attribute("OriginId");
2226  if (substr($oid, 0, 4) =="il__")
2227  {
2228  $id_arr = explode("_", $oid);
2229  $id = $id_arr[count($id_arr) - 1];
2230 
2231  $mob = new ilObjMediaObject($id);
2232  $med_item = $mob->getMediaItem("Standard");
2233  $med_areas = $med_item->getMapAreas();
2234 
2235  foreach($med_areas as $area)
2236  {
2237  $link_type = ($area->getLinkType() == "int")
2238  ? "IntLink"
2239  : "ExtLink";
2240 
2241  $areas[] = array(
2242  "Nr" => $area->getNr(),
2243  "Shape" => $area->getShape(),
2244  "Coords" => $area->getCoords(),
2245  "Link" => array(
2246  "LinkType" => $link_type,
2247  "Href" => $area->getHref(),
2248  "Title" => $area->getTitle(),
2249  "Target" => $area->getTarget(),
2250  "Type" => $area->getType(),
2251  "TargetFrame" => $area->getTargetFrame()
2252  )
2253  );
2254 
2255  if ($area->getType() == "PageObject" ||
2256  $area->getType() == "StructureObject")
2257  {
2258  $t = $area->getTarget();
2260  if ($a_from_to[$tid] > 0)
2261  {
2262  $correction_needed = true;
2263  }
2264 //var_dump($a_from_to);
2265  }
2266  }
2267  }
2268  }
2269 
2270  // correct map area links
2271  if ($correction_needed)
2272  {
2273  $changed = true;
2274  $std_alias_item->deleteAllMapAreas();
2275  foreach($areas as $area)
2276  {
2277  if ($area["Link"]["LinkType"] == "IntLink")
2278  {
2279  $target = $area["Link"]["Target"];
2280  $type = $area["Link"]["Type"];
2281  $obj_id = ilInternalLink::_extractObjIdOfTarget($target);
2282  if ($a_from_to[$obj_id] > 0)
2283  {
2284  if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg")
2285  {
2286  $area["Link"]["Target"] = "il__pg_".$a_from_to[$obj_id];
2287  }
2288  if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st")
2289  {
2290  $area["Link"]["Target"] = "il__st_".$a_from_to[$obj_id];
2291  }
2292  }
2293  }
2294 
2295  $std_alias_item->addMapArea($area["Shape"], $area["Coords"],
2296  $area["Link"]["Title"],
2297  array( "Type" => $area["Link"]["Type"],
2298  "TargetFrame" => $area["Link"]["TargetFrame"],
2299  "Target" => $area["Link"]["Target"],
2300  "Href" => $area["Link"]["Href"],
2301  "LinkType" => $area["Link"]["LinkType"],
2302  ));
2303  }
2304  }
2305  }
2306  unset($xpc);
2307 
2308  return $changed;
2309  }
2310 
2316  // @todo: generalize, internal links usage info
2317  static function _handleImportRepositoryLinks($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2318  {
2319  include_once("./Services/Link/classes/class.ilInternalLink.php");
2320 
2321 //echo "-".$a_rep_import_id."-".$a_rep_ref_id."-";
2322  $sources = ilInternalLink::_getSourcesOfTarget("obj",
2323  ilInternalLink::_extractObjIdOfTarget($a_rep_import_id),
2324  ilInternalLink::_extractInstOfTarget($a_rep_import_id));
2325 //var_dump($sources);
2326  foreach($sources as $source)
2327  {
2328 //echo "A";
2329  if ($source["type"] == "lm:pg")
2330  {
2331 //echo "B";
2332  include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
2333  if (self::_exists("lm", $source["id"], $source["lang"]))
2334  {
2335  $page_obj = new ilLMPage($source["id"], 0, $source["lang"]);
2336  if (!$page_obj->page_not_found)
2337  {
2338  //echo "C";
2339  $page_obj->handleImportRepositoryLink($a_rep_import_id,
2340  $a_rep_type, $a_rep_ref_id);
2341  }
2342  $page_obj->update();
2343  }
2344  }
2345  }
2346  }
2347 
2348  // @todo: generalize, internal links usage info
2349  function handleImportRepositoryLink($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2350  {
2351  $this->buildDom();
2352 
2353  // resolve normal internal links
2354  $xpc = xpath_new_context($this->dom);
2355  $path = "//IntLink";
2356  $res =& xpath_eval($xpc, $path);
2357 //echo "1";
2358  for($i = 0; $i < count($res->nodeset); $i++)
2359  {
2360 //echo "2";
2361  $target = $res->nodeset[$i]->get_attribute("Target");
2362  $type = $res->nodeset[$i]->get_attribute("Type");
2363  if ($target == $a_rep_import_id && $type == "RepositoryItem")
2364  {
2365 //echo "setting:"."il__".$a_rep_type."_".$a_rep_ref_id;
2366  $res->nodeset[$i]->set_attribute("Target",
2367  "il__".$a_rep_type."_".$a_rep_ref_id);
2368  }
2369  }
2370  unset($xpc);
2371  }
2372 
2376  function createFromXML()
2377  {
2378  global $lng, $ilDB, $ilUser;
2379 
2380 //echo "<br>PageObject::createFromXML[".$this->getId()."]";
2381 
2382  $empty = false;
2383  if($this->getXMLContent() == "")
2384  {
2385  $this->setXMLContent("<PageObject></PageObject>");
2386  $empty = true;
2387  }
2388 
2389  $content = $this->getXMLContent();
2390  $this->buildDom(true);
2391  $dom_doc = $this->getDomDoc();
2392 
2393  $iel = $this->containsDeactivatedElements($content);
2394  $inl = $this->containsIntLinks($content);
2395 
2396  // create object
2397  $ilDB->insert("page_object", array(
2398  "page_id" => array("integer", $this->getId()),
2399  "parent_id" => array("integer", $this->getParentId()),
2400  "lang" => array("text", $this->getLanguage()),
2401  "content" => array("clob", $content),
2402  "parent_type" => array("text", $this->getParentType()),
2403  "create_user" => array("integer", $ilUser->getId()),
2404  "last_change_user" => array("integer", $ilUser->getId()),
2405  "active" => array("integer", (int) $this->getActive()),
2406  "activation_start" => array("timestamp", $this->getActivationStart()),
2407  "activation_end" => array("timestamp", $this->getActivationEnd()),
2408  "show_activation_info" => array("integer", (int) $this->getShowActivationInfo()),
2409  "inactive_elements" => array("integer", $iel),
2410  "int_links" => array("integer", $inl),
2411  "created" => array("timestamp", ilUtil::now()),
2412  "last_change" => array("timestamp", ilUtil::now())
2413  ));
2414 
2415  // after update event
2416  $this->__afterUpdate($dom_doc, $content, true, $empty);
2417 
2418  }
2419 
2420 
2429  function updateFromXML()
2430  {
2431  global $lng, $ilDB, $ilUser;
2432 
2433  $this->log->debug("ilPageObject, updateFromXML(): start, id: ".$this->getId());
2434 
2435 //echo "<br>PageObject::updateFromXML[".$this->getId()."]";
2436 //echo "update:".ilUtil::prepareDBString(($this->getXMLContent())).":<br>";
2437 //echo "update:".htmlentities($this->getXMLContent()).":<br>";
2438 
2439  $content = $this->getXMLContent();
2440 
2441  $this->log->debug("ilPageObject, updateFromXML(): content: ".substr($content, 0, 100));
2442 
2443  $this->buildDom(true);
2444  $dom_doc = $this->getDomDoc();
2445 
2446  $iel = $this->containsDeactivatedElements($content);
2447  $inl = $this->containsIntLinks($content);
2448 
2449  $ilDB->update("page_object", array(
2450  "content" => array("clob", $content),
2451  "parent_id" => array("integer", $this->getParentId()),
2452  "last_change_user" => array("integer", $ilUser->getId()),
2453  "last_change" => array("timestamp", ilUtil::now()),
2454  "active" => array("integer", $this->getActive()),
2455  "activation_start" => array("timestamp", $this->getActivationStart()),
2456  "activation_end" => array("timestamp", $this->getActivationEnd()),
2457  "inactive_elements" => array("integer", $iel),
2458  "int_links" => array("integer", $inl),
2459  ), array(
2460  "page_id" => array("integer", $this->getId()),
2461  "parent_type" => array("text", $this->getParentType()),
2462  "lang" => array("text", $this->getLanguage())
2463  ));
2464 
2465  // after update event
2466  $this->__afterUpdate($dom_doc, $content);
2467 
2468  $this->log->debug("ilPageObject, updateFromXML(): end");
2469 
2470  return true;
2471  }
2472 
2479  protected final function __afterUpdate($a_domdoc, $a_xml, $a_creation = false, $a_empty = false)
2480  {
2481  // we do not need this if we are creating an empty page
2482  if (!$a_creation || !$a_empty)
2483  {
2484  // save internal link information
2485  // the page object is responsible to do this, since it "offers" the
2486  // internal link feature pc and page classes
2487  $this->saveInternalLinks($a_domdoc);
2488 
2489  // save style usage
2490  $this->saveStyleUsage($a_domdoc);
2491 
2492  // pc classes hook
2493  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2495  foreach ($defs as $def)
2496  {
2498  $cl = $def["pc_class"];
2499  call_user_func($def["pc_class"].'::afterPageUpdate', $this, $a_domdoc, $a_xml, $a_creation);
2500  }
2501  }
2502 
2503  // call page hook
2504  $this->afterUpdate($a_domdoc, $a_xml);
2505 
2506  // call update listeners
2507  $this->callUpdateListeners();
2508  }
2509 
2516  function afterUpdate()
2517  {
2518  }
2519 
2520 
2525  function update($a_validate = true, $a_no_history = false)
2526  {
2527  global $lng, $ilDB, $ilUser, $ilLog, $ilCtrl;
2528 
2529  $this->log->debug("ilPageObject, update(): start, id: ".$this->getId());
2530 
2531  $lm_set = new ilSetting("lm");
2532 
2533 //echo "<br>**".$this->getId()."**";
2534 //echo "<br>PageObject::update[".$this->getId()."],validate($a_validate)";
2535 //echo "\n<br>dump_all2:".$this->dom->dump_mem(0, "UTF-8").":";
2536 //echo "\n<br>PageObject::update:".$this->getXMLFromDom().":";
2537 //debug_print_backtrace();
2538 //echo "<br>PageObject::update:".htmlentities($this->getXMLFromDom()); exit;
2539 
2540  // add missing pc ids
2541  if (!$this->checkPCIds())
2542  {
2543  $this->insertPCIds();
2544  }
2545 
2546  // test validating
2547  if($a_validate)
2548  {
2549  $errors = $this->validateDom();
2550  }
2551 //var_dump($errors); exit;
2552  if (empty($errors) && !$this->getEditLock())
2553  {
2554  include_once("./Services/User/classes/class.ilUserUtil.php");
2555  $lock = $this->getEditLockInfo();
2556  $errors[0] = array(0 => 0,
2557  1 => "nocontent#".$lng->txt("cont_not_saved_edit_lock_expired")."<br />".
2558  $lng->txt("obj_usr").": ".
2559  ilUserUtil::getNamePresentation($lock["edit_lock_user"])."<br />".
2560  $lng->txt("content_until").": ".
2561  ilDatePresentation::formatDate(new ilDateTime($lock["edit_lock_until"],IL_CAL_UNIX))
2562  );
2563  }
2564 
2565  if (!empty($errors))
2566  {
2567  $this->log->debug("ilPageObject, update(): errors: ".print_r($errors, true));
2568  }
2569 
2570 //echo "-".htmlentities($this->getXMLFromDom())."-"; exit;
2571  if(empty($errors))
2572  {
2573  // @todo 1: is this page type or pc content type
2574  // related -> plugins should be able to hook in!?
2576 
2577  // get xml content
2578  $content = $this->getXMLFromDom();
2579  $dom_doc = $this->getDomDoc();
2580 
2581  // this needs to be locked
2582 
2583  // write history entry
2584  $old_set = $ilDB->query("SELECT * FROM page_object WHERE ".
2585  "page_id = ".$ilDB->quote($this->getId(), "integer")." AND ".
2586  "parent_type = ".$ilDB->quote($this->getParentType(), "text")." AND ".
2587  "lang = ".$ilDB->quote($this->getLanguage(), "text"));
2588  $last_nr_set = $ilDB->query("SELECT max(nr) as mnr FROM page_history WHERE ".
2589  "page_id = ".$ilDB->quote($this->getId(), "integer")." AND ".
2590  "parent_type = ".$ilDB->quote($this->getParentType(), "text")." AND ".
2591  "lang = ".$ilDB->quote($this->getLanguage(), "text"));
2592  $last_nr = $ilDB->fetchAssoc($last_nr_set);
2593  if ($old_rec = $ilDB->fetchAssoc($old_set))
2594  {
2595  // only save, if something has changed
2596  // added user id to the check for ilias 5.0, 7.10.2014
2597  if (($content != $old_rec["content"] || $ilUser->getId() != $old_rec["last_change_user"]) &&
2598  !$a_no_history && !$this->history_saved && $lm_set->get("page_history", 1))
2599  {
2600  if ($old_rec["content"] != "<PageObject></PageObject>")
2601  {
2602  $ilDB->manipulateF("DELETE FROM page_history WHERE ".
2603  "page_id = %s AND parent_type = %s AND hdate = %s AND lang = %s",
2604  array("integer", "text", "timestamp", "text"),
2605  array($old_rec["page_id"], $old_rec["parent_type"], $old_rec["last_change"], $old_rec["lang"]));
2606 
2607  // the following lines are a workaround for
2608  // bug 6741
2609  $last_c = $old_rec["last_change"];
2610  if ($last_c == "")
2611  {
2612  $last_c = ilUtil::now();
2613  }
2614 
2615  $ilDB->insert("page_history", array(
2616  "page_id" => array("integer", $old_rec["page_id"]),
2617  "parent_type" => array("text", $old_rec["parent_type"]),
2618  "lang" => array("text", $old_rec["lang"]),
2619  "hdate" => array("timestamp", $last_c),
2620  "parent_id" => array("integer", $old_rec["parent_id"]),
2621  "content" => array("clob", $old_rec["content"]),
2622  "user_id" => array("integer", $old_rec["last_change_user"]),
2623  "ilias_version" => array("text", ILIAS_VERSION_NUMERIC),
2624  "nr" => array("integer", (int) $last_nr["mnr"] + 1)
2625  ));
2626 
2627  $old_content = $old_rec["content"];
2628  $old_domdoc = new DOMDocument();
2629  $old_nr = $last_nr["mnr"] + 1;
2630  $old_domdoc->loadXML('<?xml version="1.0" encoding="UTF-8"?>'.$old_content);
2631 
2632  // after history entry creation event
2633  $this->__afterHistoryEntry($old_domdoc, $old_content, $old_nr);
2634 
2635  $this->history_saved = true; // only save one time
2636  }
2637  else
2638  {
2639  $this->history_saved = true; // do not save on first change
2640  }
2641  }
2642  }
2643 //echo htmlentities($content);
2644  $em = (trim($content) == "<PageObject/>")
2645  ? 1
2646  : 0;
2647 
2648  // @todo: pass dom instead?
2649  $iel = $this->containsDeactivatedElements($content);
2650  $inl = $this->containsIntLinks($content);
2651 
2652  $ilDB->update("page_object", array(
2653  "content" => array("clob", $content),
2654  "parent_id" => array("integer", $this->getParentId()),
2655  "last_change_user" => array("integer", $ilUser->getId()),
2656  "last_change" => array("timestamp", ilUtil::now()),
2657  "is_empty" => array("integer", $em),
2658  "active" => array("integer", $this->getActive()),
2659  "activation_start" => array("timestamp", $this->getActivationStart()),
2660  "activation_end" => array("timestamp", $this->getActivationEnd()),
2661  "show_activation_info" => array("integer", $this->getShowActivationInfo()),
2662  "inactive_elements" => array("integer", $iel),
2663  "int_links" => array("integer", $inl),
2664  ), array(
2665  "page_id" => array("integer", $this->getId()),
2666  "parent_type" => array("text", $this->getParentType()),
2667  "lang" => array("text", $this->getLanguage())
2668  ));
2669 
2670  // after update event
2671  $this->__afterUpdate($dom_doc, $content);
2672 
2673  $this->log->debug("ilPageObject, update(): updated and returning true, content: ".substr($this->getXMLContent(), 0, 100));
2674 
2675 //echo "<br>PageObject::update:".htmlentities($this->getXMLContent()).":";
2676  return true;
2677  }
2678  else
2679  {
2680  return $errors;
2681  }
2682  }
2683 
2684 
2685 
2689  function delete()
2690  {
2691  global $ilDB;
2692 
2693  $copg_logger = ilLoggerFactory::getLogger('copg');
2694  $copg_logger->debug("ilPageObject: Delete called for ID '".$this->getId()."',".
2695  " parent type: '".$this->getParentType()."', ".
2696  " hist nr: '".$this->old_nr."', ".
2697  " lang: '".$this->getLanguage()."', "
2698  );
2699 
2700  $mobs = array();
2701  $files = array();
2702 
2703  if (!$this->page_not_found)
2704  {
2705  $this->buildDom();
2706  $mobs = $this->collectMediaObjects(false);
2707  }
2708  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2709  $mobs2 = ilObjMediaObject::_getMobsOfObject($this->getParentType().":pg", $this->getId(), false);
2710  foreach ($mobs2 as $m)
2711  {
2712  if (!in_array($m, $mobs))
2713  {
2714  $mobs[] = $m;
2715  }
2716  }
2717 
2718  $copg_logger->debug("ilPageObject: ... found ".count($mobs)." media objects.");
2719 
2720  $this->__beforeDelete();
2721 
2722  // delete style usages
2723  $this->deleteStyleUsages(false);
2724 
2725  // delete internal links
2726  $this->deleteInternalLinks();
2727 
2728  // delete all mob usages
2729  ilObjMediaObject::_deleteAllUsages($this->getParentType().":pg", $this->getId());
2730 
2731  // delete news
2732  include_once("./Services/News/classes/class.ilNewsItem.php");
2734  $this->getParentType(), $this->getId(), "pg");
2735 
2736  // delete page_object entry
2737  $ilDB->manipulate("DELETE FROM page_object ".
2738  "WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
2739  " AND parent_type= ".$ilDB->quote($this->getParentType(), "text"));
2740  //$this->ilias->db->query($query);
2741 
2742  // delete media objects
2743  foreach ($mobs as $mob_id)
2744  {
2745  $copg_logger->debug("ilPageObject: ... processing mob ".$mob_id.".");
2746 
2747  if(ilObject::_lookupType($mob_id) != 'mob')
2748  {
2749  $copg_logger->debug("ilPageObject: ... type mismatch. Ignoring mob ".$mob_id.".");
2750  continue;
2751  }
2752 
2753  if (ilObject::_exists($mob_id))
2754  {
2755  $copg_logger->debug("ilPageObject: ... delete mob ".$mob_id.".");
2756 
2757  $mob_obj =& new ilObjMediaObject($mob_id);
2758  $mob_obj->delete();
2759  }
2760  else
2761  {
2762  $copg_logger->debug("ilPageObject: ... missing mob ".$mob_id.".");
2763  }
2764  }
2765 
2766 
2767  /* delete public and private notes (see PageObjectGUI->getNotesHTML())
2768  as they can be seen as personal data we are keeping them for now
2769  include_once("Services/Notes/classes/class.ilNote.php");
2770  foreach(array(IL_NOTE_PRIVATE, IL_NOTE_PUBLIC) as $note_type)
2771  {
2772  foreach(ilNote::_getNotesOfObject($this->getParentId(), $this->getId(),
2773  $this->getParentType(), $note_type) as $note)
2774  {
2775  $note->delete();
2776  }
2777  }
2778  */
2779  }
2780 
2786  protected final function __beforeDelete()
2787  {
2788  // pc classes hook
2789  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2791  foreach ($defs as $def)
2792  {
2794  $cl = $def["pc_class"];
2795  call_user_func($def["pc_class"].'::beforePageDelete', $this);
2796  }
2797  }
2798 
2804  protected final function __afterHistoryEntry($a_old_domdoc, $a_old_content, $a_old_nr)
2805  {
2806  // save style usage
2807  $this->saveStyleUsage($a_old_domdoc, $a_old_nr);
2808 
2809  // pc classes hook
2810  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2812  foreach ($defs as $def)
2813  {
2815  $cl = $def["pc_class"];
2816  call_user_func($def["pc_class"].'::afterPageHistoryEntry', $this, $a_old_domdoc, $a_old_content, $a_old_nr);
2817  }
2818  }
2819 
2825  function saveStyleUsage($a_domdoc, $a_old_nr = 0)
2826  {
2827  global $ilDB;
2828 
2829  // media aliases
2830  $xpath = new DOMXPath($a_domdoc);
2831  $path = "//Paragraph | //Section | //MediaAlias | //FileItem".
2832  " | //Table | //TableData | //Tabs | //List";
2833  $nodes = $xpath->query($path);
2834  $usages = array();
2835  foreach($nodes as $node)
2836  {
2837  switch ($node->localName)
2838  {
2839  case "Paragraph":
2840  $sname = $node->getAttribute("Characteristic");
2841  $stype = "text_block";
2842  $template = 0;
2843  break;
2844 
2845  case "Section":
2846  $sname = $node->getAttribute("Characteristic");
2847  $stype = "section";
2848  $template = 0;
2849  break;
2850 
2851  case "MediaAlias":
2852  $sname = $node->getAttribute("Class");
2853  $stype = "media_cont";
2854  $template = 0;
2855  break;
2856 
2857  case "FileItem":
2858  $sname = $node->getAttribute("Class");
2859  $stype = "flist_li";
2860  $template = 0;
2861  break;
2862 
2863  case "Table":
2864  $sname = $node->getAttribute("Template");
2865  if ($sname == "")
2866  {
2867  $sname = $node->getAttribute("Class");
2868  $stype = "table";
2869  $template = 0;
2870  }
2871  else
2872  {
2873  $stype = "table";
2874  $template = 1;
2875  }
2876  break;
2877 
2878  case "TableData":
2879  $sname = $node->getAttribute("Class");
2880  $stype = "table_cell";
2881  $template = 0;
2882  break;
2883 
2884  case "Tabs":
2885  $sname = $node->getAttribute("Template");
2886  if ($sname != "")
2887  {
2888  if ($node->getAttribute("Type") == "HorizontalAccordion")
2889  {
2890  $stype = "haccordion";
2891  }
2892  if ($node->getAttribute("Type") == "VerticalAccordion")
2893  {
2894  $stype = "vaccordion";
2895  }
2896  }
2897  $template = 1;
2898  break;
2899 
2900  case "List":
2901  $sname = $node->getAttribute("Class");
2902  if ($node->getAttribute("Type") == "Ordered")
2903  {
2904  $stype = "list_o";
2905  }
2906  else
2907  {
2908  $stype = "list_u";
2909  }
2910  $template = 0;
2911  break;
2912  }
2913  if ($sname != "" && $stype != "")
2914  {
2915  $usages[$sname.":".$stype.":".$template] = array("sname" => $sname,
2916  "stype" => $stype, "template" => $template);
2917  }
2918  }
2919 
2920 
2921  $this->deleteStyleUsages($a_old_nr);
2922 
2923  foreach ($usages as $u)
2924  {
2925  $ilDB->manipulate("INSERT INTO page_style_usage ".
2926  "(page_id, page_type, page_lang, page_nr, template, stype, sname) VALUES (".
2927  $ilDB->quote($this->getId(), "integer").",".
2928  $ilDB->quote($this->getParentType(), "text").",".
2929  $ilDB->quote($this->getLanguage(), "text").",".
2930  $ilDB->quote($a_old_nr, "integer").",".
2931  $ilDB->quote($u["template"], "integer").",".
2932  $ilDB->quote($u["stype"], "text").",".
2933  $ilDB->quote($u["sname"], "text").
2934  ")");
2935  }
2936  }
2937 
2944  function deleteStyleUsages($a_old_nr = 0)
2945  {
2946  global $ilDB;
2947 
2948  if ($a_old_nr !== false)
2949  {
2950  $and_old_nr = " AND page_nr = ".$ilDB->quote($a_old_nr, "integer");
2951  }
2952 
2953  $ilDB->manipulate("DELETE FROM page_style_usage WHERE ".
2954  " page_id = ".$ilDB->quote($this->getId(), "integer").
2955  " AND page_type = ".$ilDB->quote($this->getParentType(), "text").
2956  " AND page_lang = ".$ilDB->quote($this->getLanguage(), "text").
2957  $and_old_nr
2958  );
2959  }
2960 
2961 
2966  // @todo: move to content include class
2968  {
2969  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2970  include_once("./Modules/File/classes/class.ilObjFile.php");
2972  $this->getId());
2973  $files = ilObjFile::_getFilesOfObject($this->getParentType().":pg",
2974  $this->getId());
2975  $objs = array_merge($mobs, $files);
2976  return ilObject::_getLastUpdateOfObjects($objs);
2977  }
2978 
2986  {
2987  include_once("./Services/Link/classes/class.ilInternalLink.php");
2989  $this->getLanguage());
2990  }
2991 
2992 
2998  // @todo: move to specific classes, internal link use info
2999  function saveInternalLinks($a_domdoc)
3000  {
3001  global $ilDB;
3002 
3003  $this->deleteInternalLinks();
3004 
3005  // query IntLink elements
3006  $xpath = new DOMXPath($a_domdoc);
3007  $nodes = $xpath->query('//IntLink');
3008  foreach($nodes as $node)
3009  {
3010  $link_type = $node->getAttribute("Type");
3011 
3012  switch ($link_type)
3013  {
3014  case "StructureObject":
3015  $t_type = "st";
3016  break;
3017 
3018  case "PageObject":
3019  $t_type = "pg";
3020  break;
3021 
3022  case "GlossaryItem":
3023  $t_type = "git";
3024  break;
3025 
3026  case "MediaObject":
3027  $t_type = "mob";
3028  break;
3029 
3030  case "RepositoryItem":
3031  $t_type = "obj";
3032  break;
3033 
3034  case "File":
3035  $t_type = "file";
3036  break;
3037 
3038  case "WikiPage":
3039  $t_type = "wpage";
3040  break;
3041 
3042  case "User":
3043  $t_type = "user";
3044  break;
3045  }
3046 
3047  $target = $node->getAttribute("Target");
3048  $target_arr = explode("_", $target);
3049  $t_id = $target_arr[count($target_arr) - 1];
3050 
3051  // link to other internal object
3052  if (is_int(strpos($target, "__")))
3053  {
3054  $t_inst = 0;
3055  }
3056  else // link to unresolved object in other installation
3057  {
3058  $t_inst = $target_arr[1];
3059  }
3060 
3061  if ($t_id > 0)
3062  {
3063  ilInternalLink::_saveLink($this->getParentType().":pg", $this->getId(), $t_type,
3064  $t_id, $t_inst, $this->getLanguage());
3065  }
3066  }
3067  }
3068 
3072  function create()
3073  {
3074  $this->createFromXML();
3075  }
3076 
3084  function deleteContent($a_hid, $a_update = true, $a_pcid = "")
3085  {
3086  $curr_node =& $this->getContentNode($a_hid, $a_pcid);
3087  $curr_node->unlink_node($curr_node);
3088  if ($a_update)
3089  {
3090  return $this->update();
3091  }
3092  }
3093 
3094 
3102  function deleteContents($a_hids, $a_update = true, $a_self_ass = false)
3103  {
3104  if (!is_array($a_hids))
3105  {
3106  return;
3107  }
3108  foreach($a_hids as $a_hid)
3109  {
3110  $a_hid = explode(":", $a_hid);
3111 //echo "-".$a_hid[0]."-".$a_hid[1]."-";
3112 
3113 // @todo 1: hook
3114  // do not delete question nodes in assessment pages
3115  if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass)
3116  {
3117  $curr_node =& $this->getContentNode($a_hid[0], $a_hid[1]);
3118  if (is_object($curr_node))
3119  {
3120  $parent_node = $curr_node->parent_node();
3121  if ($parent_node->node_name() != "TableRow")
3122  {
3123  $curr_node->unlink_node($curr_node);
3124  }
3125  }
3126  }
3127  }
3128  if ($a_update)
3129  {
3130  return $this->update();
3131  }
3132  }
3133 
3139  function cutContents($a_hids)
3140  {
3141  $this->copyContents($a_hids);
3142  return $this->deleteContents($a_hids, true, $this->getPageConfig()->getEnableSelfAssessment());
3143  }
3144 
3150  function copyContents($a_hids)
3151  {
3152  global $ilUser;
3153 //var_dump($a_hids);
3154  if (!is_array($a_hids))
3155  {
3156  return;
3157  }
3158 
3159  $time = date("Y-m-d H:i:s", time());
3160 
3161  $hier_ids = array();
3162  $skip = array();
3163  foreach($a_hids as $a_hid)
3164  {
3165  if ($a_hid == "")
3166  {
3167  continue;
3168  }
3169  $a_hid = explode(":", $a_hid);
3170 
3171  // check, whether new hid is child of existing one or vice versa
3172  reset($hier_ids);
3173  foreach($hier_ids as $h)
3174  {
3175  if($h."_" == substr($a_hid[0], 0, strlen($h) + 1))
3176  {
3177  $skip[] = $a_hid[0];
3178  }
3179  if($a_hid[0]."_" == substr($h, 0, strlen($a_hid[0]) + 1))
3180  {
3181  $skip[] = $h;
3182  }
3183  }
3184  $pc_id[$a_hid[0]] = $a_hid[1];
3185  if ($a_hid[0] != "")
3186  {
3187  $hier_ids[$a_hid[0]] = $a_hid[0];
3188  }
3189  }
3190  foreach ($skip as $s)
3191  {
3192  unset($hier_ids[$s]);
3193  }
3194  include_once("./Services/COPage/classes/class.ilPageContent.php");
3195  $hier_ids = ilPageContent::sortHierIds($hier_ids);
3196  $nr = 1;
3197  foreach($hier_ids as $hid)
3198  {
3199  $curr_node = $this->getContentNode($hid, $pc_id[$hid]);
3200  if (is_object($curr_node))
3201  {
3202  if ($curr_node->node_name() == "PageContent")
3203  {
3204  $content = $this->dom->dump_node($curr_node);
3205  // remove pc and hier ids
3206  $content = eregi_replace("PCID=\"[a-z0-9]*\"","",$content);
3207  $content = eregi_replace("HierId=\"[a-z0-9_]*\"","",$content);
3208 
3209  $ilUser->addToPCClipboard($content, $time, $nr);
3210  $nr++;
3211  }
3212  }
3213  }
3214  include_once("./Modules/LearningModule/classes/class.ilEditClipboard.php");
3216  }
3217 
3221  function pasteContents($a_hier_id, $a_self_ass = false)
3222  {
3223  global $ilUser;
3224 
3225  $a_hid = explode(":", $a_hier_id);
3226  $content = $ilUser->getPCClipboardContent();
3227 
3228  // we insert from last to first, because we insert all at the
3229  // same hier_id
3230  for ($i = count($content) - 1; $i >= 0; $i--)
3231  {
3232 
3233  $c = $content[$i];
3234  $temp_dom = domxml_open_mem('<?xml version="1.0" encoding="UTF-8"?>'.$c,
3235  DOMXML_LOAD_PARSING, $error);
3236  if(empty($error))
3237  {
3238  $this->handleCopiedContent($temp_dom, $a_self_ass);
3239  $xpc = xpath_new_context($temp_dom);
3240  $path = "//PageContent";
3241  $res = xpath_eval($xpc, $path);
3242  if (count($res->nodeset) > 0)
3243  {
3244  $new_pc_node = $res->nodeset[0];
3245  $cloned_pc_node = $new_pc_node->clone_node (true);
3246  $cloned_pc_node->unlink_node ($cloned_pc_node);
3247  $this->insertContentNode ($cloned_pc_node, $a_hid[0],
3248  IL_INSERT_AFTER, $a_hid[1]);
3249  }
3250  }
3251  else
3252  {
3253 //var_dump($error);
3254  }
3255  }
3256  $e = $this->update();
3257 //var_dump($e);
3258  }
3259 
3263  function switchEnableMultiple($a_hids, $a_update = true, $a_self_ass = false)
3264  {
3265  if (!is_array($a_hids))
3266  {
3267  return;
3268  }
3269  $obj = & $this->content_obj;
3270 
3271  foreach($a_hids as $a_hid)
3272  {
3273  $a_hid = explode(":", $a_hid);
3274  $curr_node =& $this->getContentNode($a_hid[0], $a_hid[1]);
3275  if (is_object($curr_node))
3276  {
3277  if ($curr_node->node_name() == "PageContent")
3278  {
3279  $cont_obj =& $this->getContentObject($a_hid[0], $a_hid[1]);
3280  if ($cont_obj->isEnabled ())
3281  {
3282  // do not deactivate question nodes in assessment pages
3283  if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass)
3284  {
3285  $cont_obj->disable();
3286  }
3287  }
3288  else
3289  {
3290  $cont_obj->enable();
3291  }
3292  }
3293  }
3294  }
3295 
3296  if ($a_update)
3297  {
3298  return $this->update();
3299  }
3300  }
3301 
3302 
3310  function deleteContentFromHierId($a_hid, $a_update = true)
3311  {
3312  $hier_ids = $this->getHierIds();
3313 
3314  // iterate all hierarchical ids
3315  foreach ($hier_ids as $hier_id)
3316  {
3317  // delete top level nodes only
3318  if (!is_int(strpos($hier_id, "_")))
3319  {
3320  if ($hier_id != "pg" && $hier_id >= $a_hid)
3321  {
3322  $curr_node =& $this->getContentNode($hier_id);
3323  $curr_node->unlink_node($curr_node);
3324  }
3325  }
3326  }
3327  if ($a_update)
3328  {
3329  return $this->update();
3330  }
3331  }
3332 
3340  function deleteContentBeforeHierId($a_hid, $a_update = true)
3341  {
3342  $hier_ids = $this->getHierIds();
3343 
3344  // iterate all hierarchical ids
3345  foreach ($hier_ids as $hier_id)
3346  {
3347  // delete top level nodes only
3348  if (!is_int(strpos($hier_id, "_")))
3349  {
3350  if ($hier_id != "pg" && $hier_id < $a_hid)
3351  {
3352  $curr_node =& $this->getContentNode($hier_id);
3353  $curr_node->unlink_node($curr_node);
3354  }
3355  }
3356  }
3357  if ($a_update)
3358  {
3359  return $this->update();
3360  }
3361  }
3362 
3363 
3371  function _moveContentAfterHierId(&$a_source_page, &$a_target_page, $a_hid)
3372  {
3373  $hier_ids = $a_source_page->getHierIds();
3374 
3375  $copy_ids = array();
3376 
3377  // iterate all hierarchical ids
3378  foreach ($hier_ids as $hier_id)
3379  {
3380  // move top level nodes only
3381  if (!is_int(strpos($hier_id, "_")))
3382  {
3383  if ($hier_id != "pg" && $hier_id >= $a_hid)
3384  {
3385  $copy_ids[] = $hier_id;
3386  }
3387  }
3388  }
3389  asort($copy_ids);
3390 
3391  $parent_node =& $a_target_page->getContentNode("pg");
3392  $target_dom =& $a_target_page->getDom();
3393  $parent_childs =& $parent_node->child_nodes();
3394  $cnt_parent_childs = count($parent_childs);
3395 //echo "-$cnt_parent_childs-";
3396  $first_child =& $parent_childs[0];
3397  foreach($copy_ids as $copy_id)
3398  {
3399  $source_node =& $a_source_page->getContentNode($copy_id);
3400 
3401  $new_node =& $source_node->clone_node(true);
3402  $new_node->unlink_node($new_node);
3403 
3404  $source_node->unlink_node($source_node);
3405 
3406  if($cnt_parent_childs == 0)
3407  {
3408  $new_node =& $parent_node->append_child($new_node);
3409  }
3410  else
3411  {
3412  //$target_dom->import_node($new_node);
3413  $new_node =& $first_child->insert_before($new_node, $first_child);
3414  }
3415  $parent_childs =& $parent_node->child_nodes();
3416 
3417  //$cnt_parent_childs++;
3418  }
3419 
3420  $a_target_page->update();
3421  $a_source_page->update();
3422 
3423  }
3424 
3428  function insertContent(&$a_cont_obj, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "")
3429  {
3430 //echo "-".$a_pos."-".$a_pcid."-";
3431  // move mode into container elements is always INSERT_CHILD
3432  $curr_node = $this->getContentNode($a_pos, $a_pcid);
3433  $curr_name = $curr_node->node_name();
3434 
3435  // @todo: try to generalize this
3436  if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3437  ($curr_name == "ListItem") || ($curr_name == "Section")
3438  || ($curr_name == "Tab") || ($curr_name == "ContentPopup"))
3439  {
3440  $a_mode = IL_INSERT_CHILD;
3441  }
3442 
3443  $hid = $curr_node->get_attribute("HierId");
3444  if ($hid != "")
3445  {
3446 //echo "-".$a_pos."-".$hid."-";
3447  $a_pos = $hid;
3448  }
3449 
3450  if($a_mode != IL_INSERT_CHILD) // determine parent hierarchical id
3451  { // of sibling at $a_pos
3452  $pos = explode("_", $a_pos);
3453  $target_pos = array_pop($pos);
3454  $parent_pos = implode($pos, "_");
3455  }
3456  else // if we should insert a child, $a_pos is alreade the hierarchical id
3457  { // of the parent node
3458  $parent_pos = $a_pos;
3459  }
3460 
3461  // get the parent node
3462  if($parent_pos != "")
3463  {
3464  $parent_node =& $this->getContentNode($parent_pos);
3465  }
3466  else
3467  {
3468  $parent_node =& $this->getNode();
3469  }
3470 
3471  // count the parent children
3472  $parent_childs =& $parent_node->child_nodes();
3473  $cnt_parent_childs = count($parent_childs);
3474 //echo "ZZ$a_mode";
3475  switch ($a_mode)
3476  {
3477  // insert new node after sibling at $a_pos
3478  case IL_INSERT_AFTER:
3479  $new_node =& $a_cont_obj->getNode();
3480  //$a_pos = ilPageContent::incEdId($a_pos);
3481  //$curr_node =& $this->getContentNode($a_pos);
3482 //echo "behind $a_pos:";
3483  if($succ_node =& $curr_node->next_sibling())
3484  {
3485  $new_node =& $succ_node->insert_before($new_node, $succ_node);
3486  }
3487  else
3488  {
3489 //echo "movin doin append_child";
3490  $new_node =& $parent_node->append_child($new_node);
3491  }
3492  $a_cont_obj->setNode($new_node);
3493  break;
3494 
3495  case IL_INSERT_BEFORE:
3496 //echo "INSERT_BEF";
3497  $new_node =& $a_cont_obj->getNode();
3498  $succ_node =& $this->getContentNode($a_pos);
3499  $new_node =& $succ_node->insert_before($new_node, $succ_node);
3500  $a_cont_obj->setNode($new_node);
3501  break;
3502 
3503  // insert new node as first child of parent $a_pos (= $a_parent)
3504  case IL_INSERT_CHILD:
3505 //echo "insert as child:parent_childs:$cnt_parent_childs:<br>";
3506  $new_node =& $a_cont_obj->getNode();
3507  if($cnt_parent_childs == 0)
3508  {
3509  $new_node =& $parent_node->append_child($new_node);
3510  }
3511  else
3512  {
3513  $new_node =& $parent_childs[0]->insert_before($new_node, $parent_childs[0]);
3514  }
3515  $a_cont_obj->setNode($new_node);
3516 //echo "PP";
3517  break;
3518  }
3519 
3520  //check for PlaceHolder to remove in EditMode-keep in Layout Mode
3521  if (!$this->getPageConfig()->getEnablePCType("PlaceHolder")) {
3522  $sub_nodes = $curr_node->child_nodes() ;
3523  foreach ( $sub_nodes as $sub_node ) {
3524  if ($sub_node->node_name() == "PlaceHolder") {
3525  $curr_node->unlink_node();
3526  }
3527  }
3528  }
3529  }
3530 
3534  function insertContentNode(&$a_cont_node, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "")
3535  {
3536  // move mode into container elements is always INSERT_CHILD
3537  $curr_node = $this->getContentNode($a_pos, $a_pcid);
3538  $curr_name = $curr_node->node_name();
3539 
3540  // @todo: try to generalize
3541  if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3542  ($curr_name == "ListItem") || ($curr_name == "Section")
3543  || ($curr_name == "Tab") || ($curr_name == "ContentPopup"))
3544  {
3545  $a_mode = IL_INSERT_CHILD;
3546  }
3547 
3548  $hid = $curr_node->get_attribute("HierId");
3549  if ($hid != "")
3550  {
3551  $a_pos = $hid;
3552  }
3553 
3554  if($a_mode != IL_INSERT_CHILD) // determine parent hierarchical id
3555  { // of sibling at $a_pos
3556  $pos = explode("_", $a_pos);
3557  $target_pos = array_pop($pos);
3558  $parent_pos = implode($pos, "_");
3559  }
3560  else // if we should insert a child, $a_pos is alreade the hierarchical id
3561  { // of the parent node
3562  $parent_pos = $a_pos;
3563  }
3564 
3565  // get the parent node
3566  if($parent_pos != "")
3567  {
3568  $parent_node =& $this->getContentNode($parent_pos);
3569  }
3570  else
3571  {
3572  $parent_node =& $this->getNode();
3573  }
3574 
3575  // count the parent children
3576  $parent_childs =& $parent_node->child_nodes();
3577  $cnt_parent_childs = count($parent_childs);
3578 
3579  switch ($a_mode)
3580  {
3581  // insert new node after sibling at $a_pos
3582  case IL_INSERT_AFTER:
3583  //$new_node =& $a_cont_obj->getNode();
3584  if($succ_node = $curr_node->next_sibling())
3585  {
3586  $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3587  }
3588  else
3589  {
3590  $a_cont_node = $parent_node->append_child($a_cont_node);
3591  }
3592  //$a_cont_obj->setNode($new_node);
3593  break;
3594 
3595  case IL_INSERT_BEFORE:
3596  //$new_node =& $a_cont_obj->getNode();
3597  $succ_node = $this->getContentNode($a_pos);
3598  $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3599  //$a_cont_obj->setNode($new_node);
3600  break;
3601 
3602  // insert new node as first child of parent $a_pos (= $a_parent)
3603  case IL_INSERT_CHILD:
3604  //$new_node =& $a_cont_obj->getNode();
3605  if($cnt_parent_childs == 0)
3606  {
3607  $a_cont_node = $parent_node->append_child($a_cont_node);
3608  }
3609  else
3610  {
3611  $a_cont_node = $parent_childs[0]->insert_before($a_cont_node, $parent_childs[0]);
3612  }
3613  //$a_cont_obj->setNode($new_node);
3614  break;
3615  }
3616  }
3617 
3622  function moveContentBefore($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3623  {
3624  if($a_source == $a_target)
3625  {
3626  return;
3627  }
3628 
3629  // clone the node
3630  $content =& $this->getContentObject($a_source, $a_spcid);
3631  $source_node =& $content->getNode();
3632  $clone_node =& $source_node->clone_node(true);
3633 
3634  // delete source node
3635  $this->deleteContent($a_source, false, $a_spcid);
3636 
3637  // insert cloned node at target
3638  $content->setNode($clone_node);
3639  $this->insertContent($content, $a_target, IL_INSERT_BEFORE, $a_tpcid);
3640  return $this->update();
3641 
3642  }
3643 
3648  function moveContentAfter($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3649  {
3650  if($a_source == $a_target)
3651  {
3652  return;
3653  }
3654 
3655  // clone the node
3656  $content =& $this->getContentObject($a_source, $a_spcid);
3657  $source_node =& $content->getNode();
3658  $clone_node =& $source_node->clone_node(true);
3659 
3660  // delete source node
3661  $this->deleteContent($a_source, false, $a_spcid);
3662 
3663  // insert cloned node at target
3664  $content->setNode($clone_node);
3665  $this->insertContent($content, $a_target, IL_INSERT_AFTER, $a_tpcid);
3666  return $this->update();
3667  }
3668 
3672  // @todo: move to paragraph
3673  function bbCode2XML(&$a_content)
3674  {
3675  $a_content = eregi_replace("\[com\]","<Comment>",$a_content);
3676  $a_content = eregi_replace("\[\/com\]","</Comment>",$a_content);
3677  $a_content = eregi_replace("\[emp]","<Emph>",$a_content);
3678  $a_content = eregi_replace("\[\/emp\]","</Emph>",$a_content);
3679  $a_content = eregi_replace("\[str]","<Strong>",$a_content);
3680  $a_content = eregi_replace("\[\/str\]","</Strong>",$a_content);
3681  }
3682 
3687  function insertInstIntoIDs($a_inst, $a_res_ref_to_obj_id = true)
3688  {
3689  // insert inst id into internal links
3690  $xpc = xpath_new_context($this->dom);
3691  $path = "//IntLink";
3692  $res =& xpath_eval($xpc, $path);
3693  for($i = 0; $i < count($res->nodeset); $i++)
3694  {
3695  $target = $res->nodeset[$i]->get_attribute("Target");
3696  $type = $res->nodeset[$i]->get_attribute("Type");
3697 
3698  if (substr($target, 0, 4) == "il__")
3699  {
3700  $id = substr($target, 4, strlen($target) - 4);
3701 
3702  // convert repository links obj_<ref_id> to <type>_<obj_id>
3703  // this leads to bug 6685.
3704  if ($a_res_ref_to_obj_id && $type == "RepositoryItem")
3705  {
3706  $id_arr = explode("_", $id);
3707 
3708  // changed due to bug 6685
3709  $ref_id = $id_arr[1];
3710  $obj_id = ilObject::_lookupObjId($id_arr[1]);
3711 
3712  $otype = ilObject::_lookupType($obj_id);
3713  if ($obj_id > 0)
3714  {
3715  // changed due to bug 6685
3716  // the ref_id should be used, if the content is
3717  // imported on the same installation
3718  // the obj_id should be used, if a different
3719  // installation imports, but has an import_id for
3720  // the object id.
3721  $id = $otype."_".$obj_id."_".$ref_id;
3722  //$id = $otype."_".$ref_id;
3723  }
3724  }
3725  $new_target = "il_".$a_inst."_".$id;
3726  $res->nodeset[$i]->set_attribute("Target", $new_target);
3727  }
3728  }
3729  unset($xpc);
3730 
3731  // @todo: move to media/fileitems/questions, ...
3732 
3733  // insert inst id into media aliases
3734  $xpc = xpath_new_context($this->dom);
3735  $path = "//MediaAlias";
3736  $res =& xpath_eval($xpc, $path);
3737  for($i = 0; $i < count($res->nodeset); $i++)
3738  {
3739  $origin_id = $res->nodeset[$i]->get_attribute("OriginId");
3740  if (substr($origin_id, 0, 4) == "il__")
3741  {
3742  $new_id = "il_".$a_inst."_".substr($origin_id, 4, strlen($origin_id) - 4);
3743  $res->nodeset[$i]->set_attribute("OriginId", $new_id);
3744  }
3745  }
3746  unset($xpc);
3747 
3748  // insert inst id file item identifier entries
3749  $xpc = xpath_new_context($this->dom);
3750  $path = "//FileItem/Identifier";
3751  $res =& xpath_eval($xpc, $path);
3752  for($i = 0; $i < count($res->nodeset); $i++)
3753  {
3754  $origin_id = $res->nodeset[$i]->get_attribute("Entry");
3755  if (substr($origin_id, 0, 4) == "il__")
3756  {
3757  $new_id = "il_".$a_inst."_".substr($origin_id, 4, strlen($origin_id) - 4);
3758  $res->nodeset[$i]->set_attribute("Entry", $new_id);
3759  }
3760  }
3761  unset($xpc);
3762 
3763  // insert inst id into question references
3764  $xpc = xpath_new_context($this->dom);
3765  $path = "//Question";
3766  $res =& xpath_eval($xpc, $path);
3767  for($i = 0; $i < count($res->nodeset); $i++)
3768  {
3769  $qref = $res->nodeset[$i]->get_attribute("QRef");
3770 //echo "<br>setted:".$qref;
3771  if (substr($qref, 0, 4) == "il__")
3772  {
3773  $new_id = "il_".$a_inst."_".substr($qref, 4, strlen($qref) - 4);
3774 //echo "<br>setting:".$new_id;
3775  $res->nodeset[$i]->set_attribute("QRef", $new_id);
3776  }
3777  }
3778  unset($xpc);
3779 
3780  // insert inst id into content snippets
3781  $xpc = xpath_new_context($this->dom);
3782  $path = "//ContentInclude";
3783  $res =& xpath_eval($xpc, $path);
3784  for($i = 0; $i < count($res->nodeset); $i++)
3785  {
3786  $ci = $res->nodeset[$i]->get_attribute("InstId");
3787  if ($ci == "")
3788  {
3789  $res->nodeset[$i]->set_attribute("InstId", $a_inst);
3790  }
3791  }
3792  unset($xpc);
3793 
3794  }
3795 
3799  function checkPCIds()
3800  {
3801  $this->builddom();
3802  $mydom = $this->dom;
3803 
3804  $sep = $path = "";
3805  foreach ($this->id_elements as $el)
3806  {
3807  $path.= $sep."//".$el."[not(@PCID)]";
3808  $sep = " | ";
3809  $path.= $sep."//".$el."[@PCID='']";
3810  }
3811 
3812  $xpc = xpath_new_context($mydom);
3813  $res = & xpath_eval($xpc, $path);
3814 
3815  if (count ($res->nodeset) > 0)
3816  {
3817  return false;
3818  }
3819  return true;
3820  }
3821 
3828  function getAllPCIds()
3829  {
3830  $this->builddom();
3831  $mydom = $this->dom;
3832 
3833  $pcids = array();
3834 
3835  $sep = $path = "";
3836  foreach ($this->id_elements as $el)
3837  {
3838  $path.= $sep."//".$el."[@PCID]";
3839  $sep = " | ";
3840  }
3841 
3842  // get existing ids
3843  $xpc = xpath_new_context($mydom);
3844  $res = & xpath_eval($xpc, $path);
3845 
3846  for ($i = 0; $i < count ($res->nodeset); $i++)
3847  {
3848  $node = $res->nodeset[$i];
3849  $pcids[] = $node->get_attribute("PCID");
3850  }
3851  return $pcids;
3852  }
3853 
3860  function existsPCId($a_pc_id)
3861  {
3862  $this->builddom();
3863  $mydom = $this->dom;
3864 
3865  $pcids = array();
3866 
3867  $sep = $path = "";
3868  foreach ($this->id_elements as $el)
3869  {
3870  $path.= $sep."//".$el."[@PCID='".$a_pc_id."']";
3871  $sep = " | ";
3872  }
3873 
3874  // get existing ids
3875  $xpc = xpath_new_context($mydom);
3876  $res = & xpath_eval($xpc, $path);
3877  return (count($res->nodeset) > 0);
3878  }
3879 
3886  function generatePcId($a_pc_ids = false)
3887  {
3888  if ($a_pc_ids === false)
3889  {
3890  $a_pc_ids = $this->getAllPCIds();
3891  }
3892  $id = ilUtil::randomHash(10, $a_pc_ids);
3893  return $id;
3894  }
3895 
3896 
3900  function insertPCIds()
3901  {
3902  $this->builddom();
3903  $mydom = $this->dom;
3904 
3905  $pcids = $this->getAllPCIds();
3906 
3907  // add missing ones
3908  $sep = $path = "";
3909  foreach ($this->id_elements as $el)
3910  {
3911  $path.= $sep."//".$el."[not(@PCID)]";
3912  $sep = " | ";
3913  $path.= $sep."//".$el."[@PCID='']";
3914  $sep = " | ";
3915  }
3916  $xpc = xpath_new_context($mydom);
3917  $res = & xpath_eval($xpc, $path);
3918 
3919  for ($i = 0; $i < count ($res->nodeset); $i++)
3920  {
3921  $node = $res->nodeset[$i];
3922  $id = ilUtil::randomHash(10, $pcids);
3923  $pcids[] = $id;
3924 //echo "setting-".$id."-";
3925  $res->nodeset[$i]->set_attribute("PCID", $id);
3926  }
3927  }
3928 
3933  {
3934  $this->builddom();
3935  $this->addHierIds();
3936  $mydom = $this->dom;
3937 
3938  // get existing ids
3939  $path = "//PageContent";
3940  $xpc = xpath_new_context($mydom);
3941  $res = & xpath_eval($xpc, $path);
3942 
3943  $hashes = array();
3944  require_once("./Services/COPage/classes/class.ilPCParagraph.php");
3945  for ($i = 0; $i < count ($res->nodeset); $i++)
3946  {
3947  $hier_id = $res->nodeset[$i]->get_attribute("HierId");
3948  $pc_id = $res->nodeset[$i]->get_attribute("PCID");
3949  $dump = $mydom->dump_node($res->nodeset[$i]);
3950  if (($hpos = strpos($dump, ' HierId="'.$hier_id.'"')) > 0)
3951  {
3952  $dump = substr($dump, 0, $hpos).
3953  substr($dump, $hpos + strlen(' HierId="'.$hier_id.'"'));
3954  }
3955 
3956  $childs = $res->nodeset[$i]->child_nodes();
3957  $content = "";
3958  if ($childs[0] && $childs[0]->node_name() == "Paragraph")
3959  {
3960  $content = $mydom->dump_node($childs[0]);
3961  $content = substr($content, strpos($content, ">") + 1,
3962  strrpos($content, "<") - (strpos($content, ">") + 1));
3963 //var_dump($content);
3964  $content = ilPCParagraph::xml2output($content);
3965 //var_dump($content);
3966  }
3967  //$hashes[$hier_id] =
3968  // array("PCID" => $pc_id, "hash" => md5($dump));
3969  $hashes[$pc_id] =
3970  array("hier_id" => $hier_id, "hash" => md5($dump), "content" => $content);
3971  }
3972 
3973  return $hashes;
3974  }
3975 
3979 // @todo: move to questions
3980  function getQuestionIds()
3981  {
3982  $this->builddom();
3983  $mydom = $this->dom;
3984 
3985  // Get question IDs
3986  $path = "//Question";
3987  $xpc = xpath_new_context($mydom);
3988  $res = & xpath_eval($xpc, $path);
3989 
3990  $q_ids = array();
3991  include_once("./Services/Link/classes/class.ilInternalLink.php");
3992  for ($i = 0; $i < count ($res->nodeset); $i++)
3993  {
3994  $qref = $res->nodeset[$i]->get_attribute("QRef");
3995 
3996  $inst_id = ilInternalLink::_extractInstOfTarget($qref);
3997  $obj_id = ilInternalLink::_extractObjIdOfTarget($qref);
3998 
3999  if (!($inst_id > 0))
4000  {
4001  if ($obj_id > 0)
4002  {
4003  $q_ids[] = $obj_id;
4004  }
4005  }
4006  }
4007  return $q_ids;
4008  }
4009 
4010 // @todo: move to paragraph
4011  function send_paragraph ($par_id, $filename)
4012  {
4013  $this->builddom();
4014 
4015  $mydom = $this->dom;
4016 
4017  $xpc = xpath_new_context($mydom);
4018 
4019  //$path = "//PageContent[position () = $par_id]/Paragraph";
4020  //$path = "//Paragraph[$par_id]";
4021  $path = "/descendant::Paragraph[position() = $par_id]";
4022 
4023  $res = & xpath_eval($xpc, $path);
4024 
4025  if (count ($res->nodeset) != 1)
4026  die ("Should not happen");
4027 
4028  $context_node = $res->nodeset[0];
4029 
4030  // get plain text
4031 
4032  $childs = $context_node->child_nodes();
4033 
4034  for($j=0; $j<count($childs); $j++)
4035  {
4036  $content .= $mydom->dump_node($childs[$j]);
4037  }
4038 
4039  $content = str_replace("<br />", "\n", $content);
4040  $content = str_replace("<br/>", "\n", $content);
4041 
4042  $plain_content = html_entity_decode($content);
4043 
4044  ilUtil::deliverData($plain_content, $filename);
4045  /*
4046  $file_type = "application/octet-stream";
4047  header("Content-type: ".$file_type);
4048  header("Content-disposition: attachment; filename=\"$filename\"");
4049  echo $plain_content;*/
4050  exit();
4051  }
4052 
4056 // @todo: deprecated?
4057  function getFO()
4058  {
4059  $xml = $this->getXMLFromDom(false, true, true);
4060  $xsl = file_get_contents("./Services/COPage/xsl/page_fo.xsl");
4061  $args = array( '/_xml' => $xml, '/_xsl' => $xsl );
4062  $xh = xslt_create();
4063 
4064  $params = array ();
4065 
4066 
4067  $fo = xslt_process($xh,"arg:/_xml","arg:/_xsl",NULL,$args, $params);
4068  var_dump($fo);
4069  // do some replacements
4070  $fo = str_replace("\n", "", $fo);
4071  $fo = str_replace("<br/>", "<br>", $fo);
4072  $fo = str_replace("<br>", "\n", $fo);
4073 
4074  xslt_free($xh);
4075 
4076  //
4077  $fo = substr($fo, strpos($fo,">") + 1);
4078 //echo "<br><b>fo:</b><br>".htmlentities($fo); flush();
4079  return $fo;
4080  }
4081 
4082  function registerOfflineHandler ($handler) {
4083  $this->offline_handler = $handler;
4084  }
4085 
4093  {
4094  return $this->offline_handler;
4095  }
4096 
4097 
4101  static function _lookupContainsDeactivatedElements($a_id, $a_parent_type, $a_lang = "-")
4102  {
4103  global $ilDB;
4104 
4105  if ($a_lang == "")
4106  {
4107  $a_lang = "-";
4108  }
4109 
4110  $query = "SELECT * FROM page_object WHERE page_id = ".
4111  $ilDB->quote($a_id, "integer")." AND ".
4112  " parent_type = ".$ilDB->quote($a_parent_type, "text")." AND ".
4113  " lang = ".$ilDB->quote($a_lang, "text")." AND ".
4114  " inactive_elements = ".$ilDB->quote(1, "integer");
4115  $obj_set = $ilDB->query($query);
4116 
4117  if ($obj_rec = $obj_set->fetchRow(DB_FETCHMODE_ASSOC))
4118  {
4119  return true;
4120  }
4121 
4122  return false;
4123  }
4124 
4131  function containsDeactivatedElements($a_content)
4132  {
4133  if (strpos($a_content, " Enabled=\"False\""))
4134  {
4135  return true;
4136  }
4137  return false;
4138  }
4139 
4144  {
4145  global $ilDB;
4146 
4147  $h_query = "SELECT * FROM page_history ".
4148  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4149  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4150  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4151  " ORDER BY hdate DESC";
4152 
4153  $hset = $ilDB->query($h_query);
4154  $hentries = array();
4155 
4156  while ($hrec = $ilDB->fetchAssoc($hset))
4157  {
4158  $hrec["sortkey"] = (int) $hrec["nr"];
4159  $hrec["user"] = (int) $hrec["user_id"];
4160  $hentries[] = $hrec;
4161  }
4162 //var_dump($hentries);
4163  return $hentries;
4164  }
4165 
4169  function getHistoryEntry($a_old_nr)
4170  {
4171  global $ilDB;
4172 
4173  $res = $ilDB->queryF("SELECT * FROM page_history ".
4174  " WHERE page_id = %s ".
4175  " AND parent_type = %s ".
4176  " AND nr = %s".
4177  " AND lang = %s",
4178  array("integer", "text", "integer", "text"),
4179  array($this->getId(), $this->getParentType(), $a_old_nr, $this->getLanguage()));
4180  if ($hrec = $ilDB->fetchAssoc($res))
4181  {
4182  return $hrec;
4183  }
4184 
4185  return false;
4186  }
4187 
4188 
4195  function getHistoryInfo($a_nr)
4196  {
4197  global $ilDB;
4198 
4199  // determine previous entry
4200  $and_nr = ($a_nr > 0)
4201  ? " AND nr < ".$ilDB->quote((int) $a_nr, "integer")
4202  : "";
4203  $res = $ilDB->query("SELECT MAX(nr) mnr FROM page_history ".
4204  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4205  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4206  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4207  $and_nr);
4208  $row = $ilDB->fetchAssoc($res);
4209  if ($row["mnr"] > 0)
4210  {
4211  $res = $ilDB->query("SELECT * FROM page_history ".
4212  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4213  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4214  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4215  " AND nr = ".$ilDB->quote((int) $row["mnr"], "integer"));
4216  $row = $ilDB->fetchAssoc($res);
4217  $ret["previous"] = $row;
4218  }
4219 
4220  // determine next entry
4221  $res = $ilDB->query("SELECT MIN(nr) mnr FROM page_history ".
4222  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4223  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4224  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4225  " AND nr > ".$ilDB->quote((int) $a_nr, "integer"));
4226  $row = $ilDB->fetchAssoc($res);
4227  if ($row["mnr"] > 0)
4228  {
4229  $res = $ilDB->query("SELECT * FROM page_history ".
4230  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4231  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4232  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4233  " AND nr = ".$ilDB->quote((int) $row["mnr"], "integer"));
4234  $row = $ilDB->fetchAssoc($res);
4235  $ret["next"] = $row;
4236  }
4237 
4238  // current
4239  if ($a_nr > 0)
4240  {
4241  $res = $ilDB->query("SELECT * FROM page_history ".
4242  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4243  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4244  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4245  " AND nr = ".$ilDB->quote((int) $a_nr, "integer"));
4246  $row = $ilDB->fetchAssoc($res);
4247  }
4248  else
4249  {
4250  $res = $ilDB->query("SELECT page_id, last_change hdate, parent_type, parent_id, last_change_user user_id, content, lang FROM page_object ".
4251  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4252  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4253  " AND lang = ".$ilDB->quote($this->getLanguage(), "text"));
4254  $row = $ilDB->fetchAssoc($res);
4255  }
4256  $ret["current"] = $row;
4257 
4258  return $ret;
4259  }
4260 
4261  function addChangeDivClasses($a_hashes)
4262  {
4263  $xpc = xpath_new_context($this->dom);
4264  $path = "/*[1]";
4265  $res = xpath_eval($xpc, $path);
4266  $rnode = $res->nodeset[0];
4267 
4268 //echo "A";
4269  foreach($a_hashes as $pc_id => $h)
4270  {
4271 //echo "B";
4272  if ($h["change"] != "")
4273  {
4274  $dc_node = $this->dom->create_element("DivClass");
4275  $dc_node->set_attribute("HierId", $h["hier_id"]);
4276  $dc_node->set_attribute("Class", "ilEdit".$h["change"]);
4277  $dc_node = $rnode->append_child($dc_node);
4278  }
4279  }
4280 //echo "<br><br><br><br><br><br>".htmlentities($this->getXMLFromDom());
4281  }
4282 
4289  function compareVersion($a_left, $a_right)
4290  {
4291  // get page objects
4292  include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4293  $l_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_left);
4294  $r_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_right);
4295 
4296  $l_hashes = $l_page->getPageContentsHashes();
4297  $r_hashes = $r_page->getPageContentsHashes();
4298  // determine all deleted and changed page elements
4299  foreach ($l_hashes as $pc_id => $h)
4300  {
4301  if (!isset($r_hashes[$pc_id]))
4302  {
4303  $l_hashes[$pc_id]["change"] = "Deleted";
4304  }
4305  else
4306  {
4307  if ($l_hashes[$pc_id]["hash"] != $r_hashes[$pc_id]["hash"])
4308  {
4309  $l_hashes[$pc_id]["change"] = "Modified";
4310  $r_hashes[$pc_id]["change"] = "Modified";
4311 
4312  include_once("./Services/COPage/mediawikidiff/class.WordLevelDiff.php");
4313  // if modified element is a paragraph, highlight changes
4314  if ($l_hashes[$pc_id]["content"] != "" &&
4315  $r_hashes[$pc_id]["content"] != "")
4316  {
4317  $new_left = str_replace("\n", "<br />", $l_hashes[$pc_id]["content"]);
4318  $new_right = str_replace("\n", "<br />", $r_hashes[$pc_id]["content"]);
4319  $wldiff = new WordLevelDiff(array($new_left),
4320  array($new_right));
4321  $new_left = $wldiff->orig();
4322  $new_right = $wldiff->closing();
4323  $l_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_left[0]);
4324  $r_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_right[0]);
4325  }
4326  }
4327  }
4328  }
4329 
4330  // determine all new paragraphs
4331  foreach ($r_hashes as $pc_id => $h)
4332  {
4333  if (!isset($l_hashes[$pc_id]))
4334  {
4335  $r_hashes[$pc_id]["change"] = "New";
4336  }
4337  }
4338  $l_page->addChangeDivClasses($l_hashes);
4339  $r_page->addChangeDivClasses($r_hashes);
4340 
4341  return array("l_page" => $l_page, "r_page" => $r_page,
4342  "l_changes" => $l_hashes, "r_changes" => $r_hashes);
4343  }
4344 
4348  function increaseViewCnt()
4349  {
4350  global $ilDB;
4351 
4352  $ilDB->manipulate("UPDATE page_object ".
4353  " SET view_cnt = view_cnt + 1 ".
4354  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4355  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4356  " AND lang = ".$ilDB->quote($this->getLanguage(), "text"));
4357  }
4358 
4366  static function getRecentChanges($a_parent_type, $a_parent_id, $a_period = 30, $a_lang = "")
4367  {
4368  global $ilDB;
4369 
4370  $and_lang = "";
4371  if ($a_lang != "")
4372  {
4373  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4374  }
4375 
4376  $page_changes = array();
4377  $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4378  $q = "SELECT * FROM page_object ".
4379  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4380  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").
4381  " AND last_change >= ".$ilDB->quote($limit_ts, "timestamp").$and_lang;
4382  // " AND (TO_DAYS(now()) - TO_DAYS(last_change)) <= ".((int)$a_period);
4383  $set = $ilDB->query($q);
4384  while($page = $ilDB->fetchAssoc($set))
4385  {
4386  $page_changes[] = array(
4387  "date" => $page["last_change"],
4388  "id" => $page["page_id"],
4389  "lang" => $page["lang"],
4390  "type" => "page",
4391  "user" => $page["last_change_user"]);
4392  }
4393 
4394  $and_str = "";
4395  if ($a_period > 0)
4396  {
4397  $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4398  $and_str = " AND hdate >= ".$ilDB->quote($limit_ts, "timestamp")." ";
4399  }
4400 
4401  $q = "SELECT * FROM page_history ".
4402  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4403  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").
4404  $and_str.$and_lang;
4405  $set = $ilDB->query($q);
4406  while ($page = $ilDB->fetchAssoc($set))
4407  {
4408  $page_changes[] = array(
4409  "date" => $page["hdate"],
4410  "id" => $page["page_id"],
4411  "lang" => $page["lang"],
4412  "type" => "hist",
4413  "nr" => $page["nr"],
4414  "user" => $page["user_id"]);
4415  }
4416 
4417  $page_changes = ilUtil::sortArray($page_changes, "date", "desc");
4418 
4419  return $page_changes;
4420  }
4421 
4429  static function getAllPages($a_parent_type, $a_parent_id, $a_lang = "-")
4430  {
4431  global $ilDB;
4432 
4433  $and_lang = "";
4434  if ($a_lang != "")
4435  {
4436  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4437  }
4438 
4439  $page_changes = array();
4440 
4441  $q = "SELECT * FROM page_object ".
4442  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4443  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").$and_lang;
4444  $set = $ilDB->query($q);
4445  $pages = array();
4446  while ($page = $ilDB->fetchAssoc($set))
4447  {
4448  $key_add = ($a_lang == "")
4449  ? ":".$page["lang"]
4450  : "";
4451  $pages[$page["page_id"].$key_add] = array(
4452  "date" => $page["last_change"],
4453  "id" => $page["page_id"],
4454  "lang" => $page["lang"],
4455  "user" => $page["last_change_user"]);
4456  }
4457 
4458  return $pages;
4459  }
4460 
4467  static function getNewPages($a_parent_type, $a_parent_id, $a_lang = "-")
4468  {
4469  global $ilDB;
4470 
4471  $and_lang = "";
4472  if ($a_lang != "")
4473  {
4474  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4475  }
4476 
4477  $pages = array();
4478 
4479  $q = "SELECT * FROM page_object ".
4480  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4481  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").$and_lang.
4482  " ORDER BY created DESC";
4483  $set = $ilDB->query($q);
4484  while($page = $ilDB->fetchAssoc($set))
4485  {
4486  if ($page["created"] != "")
4487  {
4488  $pages[] = array(
4489  "created" => $page["created"],
4490  "id" => $page["page_id"],
4491  "lang" => $page["lang"],
4492  "user" => $page["create_user"],
4493  );
4494  }
4495  }
4496 
4497  return $pages;
4498  }
4499 
4506  static function getParentObjectContributors($a_parent_type, $a_parent_id, $a_lang = "-")
4507  {
4508  global $ilDB;
4509 
4510  $and_lang = "";
4511  if ($a_lang != "")
4512  {
4513  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4514  }
4515 
4516  $contributors = array();
4517  $set = $ilDB->queryF("SELECT last_change_user, lang, page_id FROM page_object ".
4518  " WHERE parent_id = %s AND parent_type = %s ".
4519  " AND last_change_user != %s".$and_lang,
4520  array("integer", "text", "integer"),
4521  array($a_parent_id, $a_parent_type, 0));
4522 
4523  while ($page = $ilDB->fetchAssoc($set))
4524  {
4525  if ($a_lang == "")
4526  {
4527  $contributors[$page["last_change_user"]][$page["page_id"]][$page["lang"]] = 1;
4528  }
4529  else
4530  {
4531  $contributors[$page["last_change_user"]][$page["page_id"]] = 1;
4532  }
4533  }
4534 
4535  $set = $ilDB->queryF("SELECT count(DISTINCT page_id, parent_type, hdate, lang) as cnt, lang, page_id, user_id FROM page_history ".
4536  " WHERE parent_id = %s AND parent_type = %s AND user_id != %s ".$and_lang.
4537  " GROUP BY page_id, user_id, lang ",
4538  array("integer", "text", "integer"),
4539  array($a_parent_id, $a_parent_type, 0));
4540  while ($hpage = $ilDB->fetchAssoc($set))
4541  {
4542  if ($a_lang == "")
4543  {
4544  $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] =
4545  $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] + $hpage["cnt"];
4546  }
4547  else
4548  {
4549  $contributors[$hpage["user_id"]][$hpage["page_id"]] =
4550  $contributors[$hpage["user_id"]][$hpage["page_id"]] + $hpage["cnt"];
4551  }
4552  }
4553 
4554  $c = array();
4555  foreach ($contributors as $k => $co)
4556  {
4557  if (ilObject::_lookupType($k) == "usr")
4558  {
4559  $name = ilObjUser::_lookupName($k);
4560  $c[] = array("user_id" => $k, "pages" => $co,
4561  "lastname" => $name["lastname"], "firstname" => $name["firstname"]);
4562  }
4563  }
4564 
4565  return $c;
4566  }
4567 
4574  static function getPageContributors($a_parent_type, $a_page_id, $a_lang = "-")
4575  {
4576  global $ilDB;
4577 
4578  $and_lang = "";
4579  if ($a_lang != "")
4580  {
4581  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4582  }
4583 
4584  $contributors = array();
4585  $set = $ilDB->queryF("SELECT last_change_user, lang FROM page_object ".
4586  " WHERE page_id = %s AND parent_type = %s ".
4587  " AND last_change_user != %s".$and_lang,
4588  array("integer", "text", "integer"),
4589  array($a_page_id, $a_parent_type, 0));
4590 
4591  while ($page = $ilDB->fetchAssoc($set))
4592  {
4593  if ($a_lang == "")
4594  {
4595  $contributors[$page["last_change_user"]][$page["lang"]] = 1;
4596  }
4597  else
4598  {
4599  $contributors[$page["last_change_user"]] = 1;
4600  }
4601  }
4602 
4603  $set = $ilDB->queryF("SELECT count(DISTINCT page_id, parent_type, hdate, lang) as cnt, lang, page_id, user_id FROM page_history ".
4604  " WHERE page_id = %s AND parent_type = %s AND user_id != %s ".$and_lang.
4605  " GROUP BY user_id, page_id, lang ",
4606  array("integer", "text", "integer"),
4607  array($a_page_id, $a_parent_type, 0));
4608  while ($hpage = $ilDB->fetchAssoc($set))
4609  {
4610  if ($a_lang == "")
4611  {
4612  $contributors[$hpage["user_id"]][$page["lang"]] =
4613  $contributors[$hpage["user_id"]][$page["lang"]] + $hpage["cnt"];
4614  }
4615  else
4616  {
4617  $contributors[$hpage["user_id"]] =
4618  $contributors[$hpage["user_id"]] + $hpage["cnt"];
4619  }
4620  }
4621 
4622  $c = array();
4623  foreach ($contributors as $k => $co)
4624  {
4625  include_once "Services/User/classes/class.ilObjUser.php";
4626  $name = ilObjUser::_lookupName($k);
4627  $c[] = array("user_id" => $k, "pages" => $co,
4628  "lastname" => $name["lastname"], "firstname" => $name["firstname"]);
4629  }
4630 
4631  return $c;
4632  }
4633 
4637  function writeRenderedContent($a_content, $a_md5)
4638  {
4639  global $ilDB;
4640 
4641  $ilDB->update("page_object", array(
4642  "rendered_content" => array("clob", $a_content),
4643  "render_md5" => array("text", $a_md5),
4644  "rendered_time" => array("timestamp", ilUtil::now())
4645  ), array(
4646  "page_id" => array("integer", $this->getId()),
4647  "lang" => array("text", $this->getLanguage()),
4648  "parent_type" => array("text", $this->getParentType())
4649  ));
4650  }
4651 
4659  static function getPagesWithLinks($a_parent_type, $a_parent_id, $a_lang = "-")
4660  {
4661  global $ilDB;
4662 
4663  $page_changes = array();
4664 
4665  $and_lang = "";
4666  if ($a_lang != "")
4667  {
4668  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4669  }
4670 
4671  $q = "SELECT * FROM page_object ".
4672  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4673  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").
4674  " AND int_links = ".$ilDB->quote(1, "integer").$and_lang;
4675  $set = $ilDB->query($q);
4676  $pages = array();
4677  while ($page = $ilDB->fetchAssoc($set))
4678  {
4679  $key_add = ($a_lang == "")
4680  ? ":".$page["lang"]
4681  : "";
4682  $pages[$page["page_id"].$key_add] = array(
4683  "date" => $page["last_change"],
4684  "id" => $page["page_id"],
4685  "lang" => $page["lang"],
4686  "user" => $page["last_change_user"]);
4687  }
4688 
4689  return $pages;
4690  }
4691 
4698  function containsIntLinks($a_content)
4699  {
4700  if (strpos($a_content, "IntLink"))
4701  {
4702  return true;
4703  }
4704  return false;
4705  }
4706 
4711  {
4712  }
4713 
4719 // @todo begin: generalize
4720  function saveInitialOpenedContent($a_type, $a_id, $a_target)
4721  {
4722  $this->buildDom();
4723 
4724  switch($a_type)
4725  {
4726  case "media":
4727  $link_type = "MediaObject";
4728  $a_id = "il__mob_".$a_id;
4729  break;
4730 
4731  case "page":
4732  $link_type = "PageObject";
4733  $a_id = "il__pg_".$a_id;
4734  break;
4735 
4736  case "term":
4737  $link_type = "GlossaryItem";
4738  $a_id = "il__git_".$a_id;
4739  $a_target = "Glossary";
4740  break;
4741  }
4742 
4743  // if type or id missing -> delete InitOpenedContent, if existing
4744  if ($link_type == "" || $a_id == "")
4745  {
4746  $xpc = xpath_new_context($this->dom);
4747  $path = "//PageObject/InitOpenedContent";
4748  $res = xpath_eval($xpc, $path);
4749  if (count($res->nodeset) > 0)
4750  {
4751  $res->nodeset[0]->unlink_node($res->nodeset[0]);
4752  }
4753  }
4754  else
4755  {
4756  $xpc = xpath_new_context($this->dom);
4757  $path = "//PageObject/InitOpenedContent";
4758  $res = xpath_eval($xpc, $path);
4759  if (count($res->nodeset) > 0)
4760  {
4761  $init_node = $res->nodeset[0];
4762  $childs = $init_node->child_nodes();
4763  for($i = 0; $i < count($childs); $i++)
4764  {
4765  if ($childs[$i]->node_name() == "IntLink")
4766  {
4767  $il_node = $childs[$i];
4768  }
4769  }
4770  }
4771  else
4772  {
4773  $path = "//PageObject";
4774  $res = xpath_eval($xpc, $path);
4775  $page_node = $res->nodeset[0];
4776  $init_node = $this->dom->create_element("InitOpenedContent");
4777  $init_node = $page_node->append_child($init_node);
4778  $il_node = $this->dom->create_element("IntLink");
4779  $il_node = $init_node->append_child($il_node);
4780  }
4781  $il_node->set_attribute("Target", $a_id);
4782  $il_node->set_attribute("Type", $link_type);
4783  $il_node->set_attribute("TargetFrame", $a_target);
4784  }
4785 
4786  $ret = $this->update();
4787  }
4788 
4789 
4796  {
4797  $this->buildDom();
4798 
4799  $xpc = xpath_new_context($this->dom);
4800  $path = "//PageObject/InitOpenedContent";
4801  $res = xpath_eval($xpc, $path);
4802  $il_node = null;
4803  if (count($res->nodeset) > 0)
4804  {
4805  $init_node = $res->nodeset[0];
4806  $childs = $init_node->child_nodes();
4807  for($i = 0; $i < count($childs); $i++)
4808  {
4809  if ($childs[$i]->node_name() == "IntLink")
4810  {
4811  $il_node = $childs[$i];
4812  }
4813  }
4814  }
4815  if (!is_null($il_node))
4816  {
4817  $id = $il_node->get_attribute("Target");
4818  $link_type = $il_node->get_attribute("Type");
4819  $target = $il_node->get_attribute("TargetFrame");
4820 
4821  switch($link_type)
4822  {
4823  case "MediaObject":
4824  $type = "media";
4825  break;
4826 
4827  case "PageObject":
4828  $type = "page";
4829  break;
4830 
4831  case "GlossaryItem":
4832  $type = "term";
4833  break;
4834  }
4835  include_once("./Services/Link/classes/class.ilInternalLink.php");
4837  return array("id" => $id, "type" => $type, "target" => $target);
4838  }
4839 
4840  return array();
4841  }
4842 // @todo end
4843 
4854  function beforePageContentUpdate($a_page_content)
4855  {
4856 
4857  }
4858 
4866  function copy($a_id, $a_parent_type = "", $a_parent_id = 0, $a_clone_mobs = false)
4867  {
4868  if ($a_parent_type == "")
4869  {
4870  $a_parent_type = $this->getParentType();
4871  if ($a_parent_id == 0)
4872  {
4873  $a_parent_id = $this->getParentId();
4874  }
4875  }
4876 
4877  include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4878  foreach (self::lookupTranslations($this->getParentType(), $this->getId()) as $l)
4879  {
4880  $existed = false;
4881  $orig_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), 0, $l);
4882  if (ilPageObject::_exists($a_parent_type, $a_id, $l))
4883  {
4884  $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, $a_id, 0, $l);
4885  $existed = true;
4886  }
4887  else
4888  {
4889  $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, 0, 0, $l);
4890  $new_page_object->setParentId($a_parent_id);
4891  $new_page_object->setId($a_id);
4892  }
4893  $new_page_object->setXMLContent($orig_page->copyXMLContent($a_clone_mobs));
4894  $new_page_object->setActive($orig_page->getActive());
4895  $new_page_object->setActivationStart($orig_page->getActivationStart());
4896  $new_page_object->setActivationEnd($orig_page->getActivationEnd());
4897  if ($existed)
4898  {
4899  $new_page_object->buildDom();
4900  $new_page_object->update();
4901  }
4902  else
4903  {
4904  $new_page_object->create();
4905  }
4906  }
4907 
4908  }
4909 
4917  static function lookupTranslations($a_parent_type, $a_id)
4918  {
4919  global $ilDB;
4920 
4921  $set = $ilDB->query("SELECT lang FROM page_object ".
4922  " WHERE page_id = ".$ilDB->quote($a_id, "integer").
4923  " AND parent_type = ".$ilDB->quote($a_parent_type, "text")
4924  );
4925  $langs = array();
4926  while ($rec = $ilDB->fetchAssoc($set))
4927  {
4928  $langs[] = $rec["lang"];
4929  }
4930  return $langs;
4931  }
4932 
4933 
4939  function copyPageToTranslation($a_target_lang)
4940  {
4941  $transl_page = ilPageObjectFactory::getInstance($this->getParentType(),
4942  0, 0, $a_target_lang);
4943  $transl_page->setId($this->getId());
4944  $transl_page->setParentId($this->getParentId());
4945  $transl_page->setXMLContent($this->copyXMLContent());
4946  $transl_page->setActive($this->getActive());
4947  $transl_page->setActivationStart($this->getActivationStart());
4948  $transl_page->setActivationEnd($this->getActivationEnd());
4949  $transl_page->create();
4950  }
4951 
4955 
4959  function getEditLock()
4960  {
4961  global $ilUser, $ilDB;
4962  //return false;
4963  $aset = new ilSetting("adve");
4964 
4965  $min = (int) $aset->get("block_mode_minutes") ;
4966  if ($min > 0)
4967  {
4968  // try to set the lock for the user
4969  $ts = time();
4970  $ilDB->manipulate("UPDATE page_object SET ".
4971  " edit_lock_user = ".$ilDB->quote($ilUser->getId(), "integer").",".
4972  " edit_lock_ts = ".$ilDB->quote($ts, "integer").
4973  " WHERE (edit_lock_user = ".$ilDB->quote($ilUser->getId(), "integer")." OR ".
4974  " edit_lock_ts < ".$ilDB->quote(time() - ($min * 60), "integer").") ".
4975  " AND page_id = ".$ilDB->quote($this->getId(), "integer").
4976  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
4977  );
4978 
4979  $set = $ilDB->query("SELECT edit_lock_user FROM page_object ".
4980  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4981  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
4982  );
4983  $rec = $ilDB->fetchAssoc($set);
4984  if ($rec["edit_lock_user"] != $ilUser->getId())
4985  {
4986  return false;
4987  }
4988  }
4989 
4990  return true;
4991  }
4992 
4996  function releasePageLock()
4997  {
4998  global $ilUser, $ilDB;
4999 
5000  $aset = new ilSetting("adve");
5001 
5002  $min = (int) $aset->get("block_mode_minutes") ;
5003  if ($min > 0)
5004  {
5005  // try to set the lock for the user
5006  $ts = time();
5007  $ilDB->manipulate("UPDATE page_object SET ".
5008  " edit_lock_user = ".$ilDB->quote($ilUser->getId(), "integer").",".
5009  " edit_lock_ts = 0".
5010  " WHERE edit_lock_user = ".$ilDB->quote($ilUser->getId(), "integer").
5011  " AND page_id = ".$ilDB->quote($this->getId(), "integer").
5012  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
5013  );
5014 
5015  $set = $ilDB->query("SELECT edit_lock_user FROM page_object ".
5016  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
5017  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
5018  );
5019  $rec = $ilDB->fetchAssoc($set);
5020  if ($rec["edit_lock_user"] != $ilUser->getId())
5021  {
5022  return false;
5023  }
5024  }
5025 
5026  return true;
5027  }
5028 
5034  function getEditLockInfo()
5035  {
5036  global $ilDB;
5037 
5038  $aset = new ilSetting("adve");
5039  $min = (int) $aset->get("block_mode_minutes");
5040 
5041  $set = $ilDB->query("SELECT edit_lock_user, edit_lock_ts FROM page_object ".
5042  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
5043  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
5044  );
5045  $rec = $ilDB->fetchAssoc($set);
5046  $rec["edit_lock_until"] = $rec["edit_lock_ts"] + $min * 60;
5047 
5048  return $rec;
5049  }
5050 
5063  public static function truncateHTML($a_text, $a_length = 100, $a_ending = '...', $a_exact = false, $a_consider_html = true)
5064  {
5065  include_once "Services/Utilities/classes/class.ilStr.php";
5066 
5067  if ($a_consider_html)
5068  {
5069  // if the plain text is shorter than the maximum length, return the whole text
5070  if(strlen(preg_replace('/<.*?>/', '', $a_text)) <= $a_length)
5071  {
5072  return $a_text;
5073  }
5074 
5075  // splits all html-tags to scanable lines
5076  $total_length = strlen($a_ending);
5077  $open_tags = array();
5078  $truncate = '';
5079  preg_match_all('/(<.+?>)?([^<>]*)/s', $a_text, $lines, PREG_SET_ORDER);
5080  foreach($lines as $line_matchings)
5081  {
5082  // if there is any html-tag in this line, handle it and add it (uncounted) to the output
5083  if(!empty($line_matchings[1]))
5084  {
5085  // if it's an "empty element" with or without xhtml-conform closing slash
5086  if(preg_match('/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is', $line_matchings[1]))
5087  {
5088  // do nothing
5089  }
5090  // if tag is a closing tag
5091  else if(preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line_matchings[1], $tag_matchings))
5092  {
5093  // delete tag from $open_tags list
5094  $pos = array_search($tag_matchings[1], $open_tags);
5095  if ($pos !== false)
5096  {
5097  unset($open_tags[$pos]);
5098  }
5099  }
5100  // if tag is an opening tag
5101  else if (preg_match('/^<\s*([^\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings))
5102  {
5103  // add tag to the beginning of $open_tags list
5104  array_unshift($open_tags, strtolower($tag_matchings[1]));
5105  }
5106  // add html-tag to $truncate'd text
5107  $truncate .= $line_matchings[1];
5108  }
5109 
5110  // calculate the length of the plain text part of the line; handle entities as one character
5111  $content_length = strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
5112  if($total_length+$content_length > $a_length)
5113  {
5114  // the number of characters which are left
5115  $left = $a_length - $total_length;
5116  $entities_length = 0;
5117  // search for html entities
5118  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))
5119  {
5120  // calculate the real length of all entities in the legal range
5121  foreach($entities[0] as $entity)
5122  {
5123  if($entity[1]+1-$entities_length <= $left)
5124  {
5125  $left--;
5126  $entities_length += strlen($entity[0]);
5127  }
5128  else
5129  {
5130  // no more characters left
5131  break;
5132  }
5133  }
5134  }
5135 
5136  // $truncate .= substr($line_matchings[2], 0, $left+$entities_length);
5137  $truncate .= ilStr::shortenText($line_matchings[2], 0, $left+$entities_length);
5138 
5139  // maximum lenght is reached, so get off the loop
5140  break;
5141  }
5142  else
5143  {
5144  $truncate .= $line_matchings[2];
5145  $total_length += $content_length;
5146  }
5147 
5148  // if the maximum length is reached, get off the loop
5149  if($total_length >= $a_length)
5150  {
5151  break;
5152  }
5153  }
5154  }
5155  else
5156  {
5157  if(strlen($a_text) <= $a_length)
5158  {
5159  return $a_text;
5160  }
5161  else
5162  {
5163  // $truncate = substr($a_text, 0, $a_length - strlen($a_ending));
5164  $truncate = ilStr::shortenText($a_text, 0, $a_length - strlen($a_ending));
5165  }
5166  }
5167 
5168  // THIS IS BUGGY AS IT MIGHT BREAK AN OPEN TAG AT THE END
5169  if(!sizeof($open_tags))
5170  {
5171  // if the words shouldn't be cut in the middle...
5172  if (!$a_exact)
5173  {
5174  // ...search the last occurance of a space...
5175  $spacepos = strrpos($truncate, ' ');
5176  if($spacepos !== false)
5177  {
5178  // ...and cut the text in this position
5179  // $truncate = substr($truncate, 0, $spacepos);
5180  $truncate = ilStr::shortenText($truncate, 0, $spacepos);
5181  }
5182  }
5183  }
5184 
5185  // add the defined ending to the text
5186  $truncate .= $a_ending;
5187 
5188  if($a_consider_html)
5189  {
5190  // close all unclosed html-tags
5191  foreach($open_tags as $tag)
5192  {
5193  $truncate .= '</'.$tag.'>';
5194  }
5195  }
5196 
5197  return $truncate;
5198  }
5199 
5206  {
5207  return array();
5208  }
5209 
5217  static function getLastChangeByParent($a_parent_type, $a_parent_id, $a_lang = "")
5218  {
5219  global $ilDB;
5220 
5221  $and_lang = "";
5222  if ($a_lang != "")
5223  {
5224  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
5225  }
5226 
5227  $ilDB->setLimit(1);
5228  $q = "SELECT last_change FROM page_object ".
5229  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
5230  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").$and_lang.
5231  " ORDER BY last_change DESC";
5232 
5233  $set = $ilDB->query($q);
5234  $rec = $ilDB->fetchAssoc($set);
5235 
5236  return $rec["last_change"];
5237  }
5238 
5244  function getAllFileObjIds()
5245  {
5246  $file_obj_ids = array();
5247 
5248  // insert inst id file item identifier entries
5249  $xpc = xpath_new_context($this->dom);
5250  $path = "//FileItem/Identifier";
5251  $res = xpath_eval($xpc, $path);
5252  for($i = 0; $i < count($res->nodeset); $i++)
5253  {
5254  $file_obj_ids[] = $res->nodeset[$i]->get_attribute("Entry");
5255  }
5256  unset($xpc);
5257  return $file_obj_ids;
5258  }
5259 
5260 
5261 
5262 
5263 }
5264 ?>
const DOMXML_LOAD_PARSING
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 _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 ...
getPCDefinitions()
Get PC definitions.
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:86
ILIAS Setting Class.
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 _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
lookforhier($a_hier_id)
getInternalLinks($a_cnt_multiple=false)
get all internal links that are used within the page
$size
Definition: RandomTest.php:79
exit
Definition: login.php:54
static _lookupType($a_obj_id, $a_lm_id=0)
Lookup type.
domxml_open_mem($str, $mode=DOMXML_LOAD_PARSING, &$error=NULL)
$_POST['username']
Definition: cron.php:12
copyPageToTranslation($a_target_lang)
Copy page to translation.
const IL_CAL_DATETIME
getFO()
get fo page content
getLanguage()
Get language.
_resolveMapAreaLinks($a_mob_id)
resolve internal links of all media items of a media object
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.
_writeParentId($a_parent_type, $a_pg_id, $a_par_id)
Write parent id.
deleteContentFromHierId($a_hid, $a_update=true)
delete content object with hierarchical id >= $a_hid
xpath_new_context($dom_document)
Class ilPCTable.
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.
setActivationEnd($a_activationend)
Set Activation End.
static _before(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.
setActivationStart($a_activationstart)
Set Activation Start.
copyXmlContent($a_clone_mobs=false)
Copy content of page; replace page components with copies where necessary (e.g.
xpath_eval($xpath_context, $eval_str, $contextnode=null)
newIIMCopies($temp_dom)
Replaces media objects in interactive images with copies of the interactive images.
static 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)
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.
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 sortArray($array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
static now()
Return current timestamp in Y-m-d H:i:s format.
getPageContentsHashes()
Get page contents hashes.
_lookupActivationData($a_id, $a_parent_type, $a_lang="-")
Lookup activation data.
__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.
_moveContentAfterHierId(&$a_source_page, &$a_target_page, $a_hid)
move content of hierarchical id >= $a_hid to other page
getFileItemIds()
get ids of all file items
global $ilCtrl
Definition: ilias.php:18
getRenderMd5()
Get Render MD5.
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) ...
static getConfigInstance($a_parent_type)
Get page config instance.
static lookupParentId($a_id, $a_type)
Lookup parent id.
newMobCopies($temp_dom)
Replaces media objects with copies.
moveIntLinks($a_from_to)
Move internal links from one destination to another.
_existsAndNotEmpty($a_parent_type, $a_id, $a_lang="-")
checks whether page exists and is not empty (may return true on some empty pages) ...
setRenderedContent($a_renderedcontent)
Set Rendered Content.
compareVersion($a_left, $a_right)
Compares to revisions of the page.
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)
Default behaviour is:
addUpdateListener(&$a_object, $a_method, $a_parameters="")
const DOMXML_LOAD_VALIDATING
collectMediaObjects($a_inline_only=true)
get all media objects, that are referenced and used within the page
static xml2output($a_text, $a_wysiwyg=false, $a_replace_lists=true)
Converts xml from DB to output in edit textarea.
moveContentBefore($a_source, $a_target, $a_spcid="", $a_tpcid="")
move content object from position $a_source before position $a_target (both hierarchical content ids)...
$mobs
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
beforePageContentUpdate($a_page_content)
Before page content update.
deleteInternalLinks()
Delete internal links.
_writeActive($a_id, $a_parent_type, $a_active, $a_reset_scheduled_activation=true, $a_lang="-")
write activation status
getActive($a_check_scheduled_activation=false)
get activation
getLastChange()
Get Last Change.
insertContentNode(&$a_cont_node, $a_pos, $a_mode=IL_INSERT_AFTER, $a_pcid="")
insert a content node before/after a sibling or as first child of a parent
getListItemIds()
get ids of all list items
getInitialOpenedContent()
Get initial opened content.
resolveFileItems($a_mapping)
Resolve file items (after import)
static _lookupObjId($a_id)
Class ilPageObject.
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...
static formatDate(ilDateTime $date)
Format a date public.
createFromXML()
Create new page object with current xml content.
_deleteAllUsages($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
static
setRenderedTime($a_renderedtime)
Set Rendered Time.
getRenderedContent()
Get Rendered Content.
getPCDefinitionByName($a_pc_name)
Get PC definition by name.
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
redirection script todo: (a better solution should control the processing via a xml file) ...
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.
const DB_FETCHMODE_ASSOC
Definition: class.ilDB.php:10
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.
static _handleImportRepositoryLinks($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
Change targest of repository links.
getOfflineHandler()
Get offline handler.
getShowActivationInfo()
Get show page activation info.
setId($a_id)
set id
_getMapAreasIntLinks($a_mob_id)
get all internal links of map areas of a mob
const IL_INSERT_AFTER
static _lookupImportId($a_obj_id)
static _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_usage_lang="-")
get all files of an object
update($a_validate=true, $a_no_history=false)
update complete page content in db (dom xml content is used)
static _lookupType($a_id, $a_reference=false)
lookup object type
setRenderMd5($a_rendermd5)
Set Render MD5.
static _lookupContainsDeactivatedElements($a_id, $a_parent_type, $a_lang="-")
lookup whether page contains deactivated elements
static _isScheduledActivation($a_id, $a_parent_type, $a_lang="-")
Check whether page is activated by time schedule.
containsIntLinks($a_content)
Check whether content contains internal links.
static _instantiateQuestion($question_id)
deleteContentBeforeHierId($a_hid, $a_update=true)
delete content object with hierarchical id < $a_hid
$filename
Definition: buildRTE.php:89
getContentTemplates()
Get content templates.
insertPCIds()
Insert Page Content IDs.
_getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
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 getInstance($a_parent_type, $a_id=0, $a_old_nr=0, $a_lang="-")
Get page object instance.
$errors
getDom()
Deprecated php4DomDocument.
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 $ilUser
Definition: imgupload.php:15
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...
$ref_id
Definition: sahs_server.php:39
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.
global $lng
Definition: privfeed.php:40
$path
Definition: index.php:22
static lookupTranslations($a_parent_type, $a_id)
Lookup translations.
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.
global $ilDB
resolveMediaAliases($a_mapping, $a_reuse_existing_by_import=false)
Resolve media aliases (after import)
getEditLock()
Get page lock.
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
copyContents($a_hids)
Copy contents to clipboard.
getHistoryInfo($a_nr)
Get information about a history entry, its predecessor and its successor.
ilPageObject($a_id=0, $a_old_nr=0, $a_lang="-")
Constructor public.
const IL_MODE_OUTPUT
countPageContents()
Remove questions from document.
static getLogger($a_component_id)
Get component logger.
getHierIds()
get all hierarchical ids
Class ilPCMediaObject.
saveInternalLinks($a_domdoc)
save internal links of page
afterUpdate()
After update.
getRenderedTime()
Get Rendered Time.
_getLastUpdateOfObjects($a_objs)
Get last update for a set of media objects.
& getContentNode($a_hier_id, $a_pc_id="")
Get content node from dom.
getActivationEnd()
Get Activation End.
static getNewPages($a_parent_type, $a_parent_id, $a_lang="-")
Get new pages.
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.
getHierIdsForPCIds($a_pc_ids)
Get hier ids for a set of pc ids.
$params
Definition: example_049.php:96
copy($a_id, $a_parent_type="", $a_parent_id=0, $a_clone_mobs=false)
Copy page.
Extension of ilPageObject for learning modules.
getContainsQuestion()
Get contains question.
getAllFileObjIds()
Get all file object ids.
getParentType()
Get parent type.
deleteStyleUsages($a_old_nr=0)
Delete style usages.
const IL_INSERT_CHILD
validateDom()
Validate the page content agains page DTD.
const IL_INSERT_BEFORE
cutContents($a_hids)
Copy contents to clipboard and cut them from the page.
deleteContent($a_hid, $a_update=true, $a_pcid="")
delete content object with hierarchical id $a_hid
Class ilPCDataTable.
addChangeDivClasses($a_hashes)