ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
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_4_5.dtd";
66  var $language = "-";
67  static protected $activation_data = array();
68  protected $import_mode = false;
69 
74  final public function ilPageObject($a_id = 0, $a_old_nr = 0, $a_lang = "-")
75  {
76  global $ilias;
77 
78  // @todo: move this elsewhere
79  require_once("./Services/COPage/syntax_highlight/php/Beautifier/Init.php");
80  require_once("./Services/COPage/syntax_highlight/php/Output/Output_css.php");
81 
82  $this->parent_type = $this->getParentType();
83  $this->id = $a_id;
84  $this->ilias =& $ilias;
85  $this->setLanguage($a_lang);
86 
87  $this->contains_int_link = false;
88  $this->needs_parsing = false;
89  $this->update_listeners = array();
90  $this->update_listener_cnt = 0;
91  $this->dom_builded = false;
92  $this->page_not_found = false;
93  $this->old_nr = $a_old_nr;
94  $this->encoding = "UTF-8";
95  $this->id_elements =
96  array("PageContent", "TableRow", "TableData", "ListItem", "FileItem",
97  "Section", "Tab", "ContentPopup");
98  $this->setActive(true);
99 
100  if($a_id != 0)
101  {
102  $this->read();
103  }
104 
105  $this->initPageConfig();
106 
107  $this->afterConstructor();
108  }
109 
116  function afterConstructor()
117  {
118 
119  }
120 
121 
127  abstract function getParentType();
128 
134  final function initPageConfig()
135  {
136  include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
138  $this->setPageConfig($cfg);
139  }
140 
146  function setLanguage($a_val)
147  {
148  $this->language = $a_val;
149  }
150 
156  function getLanguage()
157  {
158  return $this->language;
159  }
160 
166  function setPageConfig($a_val)
167  {
168  $this->page_config = $a_val;
169  }
170 
176  function getPageConfig()
177  {
178  return $this->page_config;
179  }
180 
186  function setRenderMd5($a_rendermd5)
187  {
188  $this->rendermd5 = $a_rendermd5;
189  }
190 
196  function getRenderMd5()
197  {
198  return $this->rendermd5;
199  }
200 
206  function setRenderedContent($a_renderedcontent)
207  {
208  $this->renderedcontent = $a_renderedcontent;
209  }
210 
217  {
218  return $this->renderedcontent;
219  }
220 
226  function setRenderedTime($a_renderedtime)
227  {
228  $this->renderedtime = $a_renderedtime;
229  }
230 
236  function getRenderedTime()
237  {
238  return $this->renderedtime;
239  }
240 
246  function setLastChange($a_lastchange)
247  {
248  $this->lastchange = $a_lastchange;
249  }
250 
256  function getLastChange()
257  {
258  return $this->lastchange;
259  }
260 
266  public function setLastChangeUser($a_val)
267  {
268  $this->last_change_user = $a_val;
269  }
270 
276  public function getLastChangeUser()
277  {
278  return $this->last_change_user;
279  }
280 
286  function setShowActivationInfo($a_val)
287  {
288  $this->show_page_act_info = $a_val;
289  }
290 
297  {
298  return $this->show_page_act_info;
299  }
300 
304  function read()
305  {
306  global $ilDB;
307 
308  $this->setActive(true);
309  if ($this->old_nr == 0)
310  {
311  $query = "SELECT * FROM page_object".
312  " WHERE page_id = ".$ilDB->quote($this->id, "integer").
313  " AND parent_type=".$ilDB->quote($this->getParentType(), "text").
314  " AND lang = ".$ilDB->quote($this->getLanguage(), "text");
315  $pg_set = $this->ilias->db->query($query);
316  $this->page_record = $ilDB->fetchAssoc($pg_set);
317  $this->setActive($this->page_record["active"]);
318  $this->setActivationStart($this->page_record["activation_start"]);
319  $this->setActivationEnd($this->page_record["activation_end"]);
320  $this->setShowActivationInfo($this->page_record["show_activation_info"]);
321  }
322  else
323  {
324  $query = "SELECT * FROM page_history".
325  " WHERE page_id = ".$ilDB->quote($this->id, "integer").
326  " AND parent_type=".$ilDB->quote($this->getParentType(), "text").
327  " AND nr = ".$ilDB->quote((int) $this->old_nr, "integer").
328  " AND lang = ".$ilDB->quote($this->getLanguage(), "text");
329  $pg_set = $ilDB->query($query);
330  $this->page_record = $ilDB->fetchAssoc($pg_set);
331  }
332  if (!$this->page_record)
333  {
334  include_once("./Services/COPage/exceptions/class.ilCOPageNotFoundException.php");
335  throw new ilCOPageNotFoundException("Error: Page ".$this->id." is not in database".
336  " (parent type ".$this->getParentType().").");
337  }
338 
339  $this->xml = $this->page_record["content"];
340  $this->setParentId($this->page_record["parent_id"]);
341  $this->last_change_user = $this->page_record["last_change_user"];
342  $this->create_user = $this->page_record["create_user"];
343  $this->setRenderedContent($this->page_record["rendered_content"]);
344  $this->setRenderMd5($this->page_record["render_md5"]);
345  $this->setRenderedTime($this->page_record["rendered_time"]);
346  $this->setLastChange($this->page_record["last_change"]);
347 
348  }
349 
357  static function _exists($a_parent_type, $a_id, $a_lang = "")
358  {
359  global $ilDB;
360  if (isset(self::$exists[$a_parent_type.":".$a_id.":".$a_lang]))
361  {
362  return self::$exists[$a_parent_type.":".$a_id.":".$a_lang];
363  }
364 
365  $and_lang = "";
366  if ($a_lang != "")
367  {
368  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
369  }
370 
371  $query = "SELECT page_id FROM page_object WHERE page_id = ".$ilDB->quote($a_id, "integer")." ".
372  "AND parent_type = ".$ilDB->quote($a_parent_type, "text").$and_lang;
373  $set = $ilDB->query($query);
374  if ($row = $ilDB->fetchAssoc($set))
375  {
376  self::$exists[$a_parent_type.":".$a_id.":".$a_lang] = true;
377  return true;
378  }
379  else
380  {
381  self::$exists[$a_parent_type.":".$a_id.":".$a_lang] = false;
382  return false;
383  }
384  }
385 
393  static function _existsAndNotEmpty($a_parent_type, $a_id, $a_lang = "-")
394  {
395  global $ilDB;
396 
397  include_once("./Services/COPage/classes/class.ilPageUtil.php");
398 
399  return ilPageUtil::_existsAndNotEmpty($a_parent_type, $a_id, $a_lang);
400  }
401 
402  function buildDom($a_force = false)
403  {
404  if ($this->dom_builded && !$a_force)
405  {
406  return;
407  }
408 
409 //echo "\n<br>buildDomWith:".$this->getId().":xml:".$this->getXMLContent(true).":<br>";
410 
411  $this->dom = @domxml_open_mem($this->getXMLContent(true), DOMXML_LOAD_VALIDATING, $error);
412 
413  $xpc = xpath_new_context($this->dom);
414  $path = "//PageObject";
415  $res =& xpath_eval($xpc, $path);
416  if (count($res->nodeset) == 1)
417  {
418  $this->node =& $res->nodeset[0];
419  }
420 
421  if (empty($error))
422  {
423  $this->dom_builded = true;
424  return true;
425  }
426  else
427  {
428  return $error;
429  }
430  }
431 
432  function freeDom()
433  {
434  //$this->dom->free();
435  unset($this->dom);
436  }
437 
441  function getDom()
442  {
443  return $this->dom;
444  }
445 
452  function getDomDoc()
453  {
454  if ($this->dom instanceof php4DOMDocument)
455  {
456  return $this->dom->myDOMDocument;
457  }
458 
459  return $this->dom;
460  }
461 
462 
466  function setId($a_id)
467  {
468  $this->id = $a_id;
469  }
470 
471  function getId()
472  {
473  return $this->id;
474  }
475 
476  function setParentId($a_id)
477  {
478  $this->parent_id = $a_id;
479  }
480 
481  function getParentId()
482  {
483  return $this->parent_id;
484  }
485 
486  function addUpdateListener(&$a_object, $a_method, $a_parameters = "")
487  {
489  $this->update_listeners[$cnt]["object"] =& $a_object;
490  $this->update_listeners[$cnt]["method"] = $a_method;
491  $this->update_listeners[$cnt]["parameters"] = $a_parameters;
492  $this->update_listener_cnt++;
493  }
494 
496  {
497  for($i=0; $i<$this->update_listener_cnt; $i++)
498  {
499  $object =& $this->update_listeners[$i]["object"];
500  $method = $this->update_listeners[$i]["method"];
501  $parameters = $this->update_listeners[$i]["parameters"];
502  $object->$method($parameters);
503  }
504  }
505 
511  function setActive($a_active)
512  {
513  $this->active = $a_active;
514  }
515 
521  function getActive($a_check_scheduled_activation = false)
522  {
523  if ($a_check_scheduled_activation && !$this->active)
524  {
525  include_once("./Services/Calendar/classes/class.ilDateTime.php");
526  $start = new ilDateTime($this->getActivationStart(), IL_CAL_DATETIME);
527  $end = new ilDateTime($this->getActivationEnd(), IL_CAL_DATETIME);
528  $now = new ilDateTime(time(), IL_CAL_UNIX);
529  if (!ilDateTime::_before($now, $start) && !ilDateTime::_after($now, $end))
530  {
531  return true;
532  }
533  }
534  return $this->active;
535  }
536 
542  static function preloadActivationDataByParentId($a_parent_id)
543  {
544  global $ilDB;
545 
546  $set = $ilDB->query("SELECT page_id, parent_type, lang, active, activation_start, activation_end, show_activation_info FROM page_object ".
547  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer")
548  );
549  while ($rec = $ilDB->fetchAssoc($set))
550  {
551  self::$activation_data[$rec["page_id"].":".$rec["parent_type"].":".$rec["lang"]] = $rec;
552  }
553  }
554 
555 
559  static function _lookupActive($a_id, $a_parent_type, $a_check_scheduled_activation = false, $a_lang = "-")
560  {
561  global $ilDB;
562 
563  // language must be set at least to "-"
564  if ($a_lang == "")
565  {
566  $a_lang = "-";
567  }
568 
569  if (isset(self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang]))
570  {
571  $rec = self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang];
572  }
573  else
574  {
575  $set = $ilDB->queryF("SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s".
576  " AND parent_type = %s AND lang = %s",
577  array("integer", "text", "text"),
578  array($a_id, $a_parent_type, $a_lang));
579  $rec = $ilDB->fetchAssoc($set);
580  }
581 
582 
583  $rec["n"] = ilUtil::now();
584 
585  if (!$rec["active"] && $a_check_scheduled_activation)
586  {
587  if ($rec["n"] >= $rec["activation_start"] &&
588  $rec["n"] <= $rec["activation_end"])
589  {
590  return true;
591  }
592  }
593 
594  return $rec["active"];
595  }
596 
600  static function _isScheduledActivation($a_id, $a_parent_type, $a_lang = "-")
601  {
602  global $ilDB;
603 
604  // language must be set at least to "-"
605  if ($a_lang == "")
606  {
607  $a_lang = "-";
608  }
609 
610 //echo "<br>";
611 //var_dump(self::$activation_data); exit;
612  if (isset(self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang]))
613  {
614  $rec = self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang];
615  }
616  else
617  {
618  $set = $ilDB->queryF("SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s".
619  " AND parent_type = %s AND lang = %s", array("integer", "text", "text"),
620  array($a_id, $a_parent_type, $a_lang));
621  $rec = $ilDB->fetchAssoc($set);
622  }
623 
624  if (!$rec["active"] && $rec["activation_start"] != "")
625  {
626  return true;
627  }
628 
629  return false;
630  }
631 
635  function _writeActive($a_id, $a_parent_type, $a_active, $a_reset_scheduled_activation = true, $a_lang = "-")
636  {
637  global $ilDB;
638 
639  // language must be set at least to "-"
640  if ($a_lang == "")
641  {
642  $a_lang = "-";
643  }
644 
645  if ($a_reset_scheduled_activation)
646  {
647  $st = $ilDB->manipulateF("UPDATE page_object SET active = %s, activation_start = %s, ".
648  " activation_end = %s WHERE page_id = %s".
649  " AND parent_type = %s AND lang = %s", array("boolean", "timestamp", "timestamp", "integer", "text", "text"),
650  array($a_active, null, null, $a_id, $a_parent_type, $a_lang));
651  }
652  else
653  {
654  $st = $ilDB->prepareManip("UPDATE page_object SET active = %s WHERE page_id = %s".
655  " AND parent_type = %s AND lang = %s", array("boolean", "integer", "text", "text"),
656  array($a_active, $a_id, $a_parent_type, $a_lang));
657  }
658  }
659 
663  function _lookupActivationData($a_id, $a_parent_type, $a_lang = "-")
664  {
665  global $ilDB;
666 
667  // language must be set at least to "-"
668  if ($a_lang == "")
669  {
670  $a_lang = "-";
671  }
672 
673  if (isset(self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang]))
674  {
675  $rec = self::$activation_data[$a_id.":".$a_parent_type.":".$a_lang];
676  }
677  else
678  {
679  $set = $ilDB->queryF("SELECT active, activation_start, activation_end, show_activation_info FROM page_object WHERE page_id = %s".
680  " AND parent_type = %s AND lang = %s",
681  array("integer", "text", "text"),
682  array($a_id, $a_parent_type, $a_lang));
683  $rec = $ilDB->fetchAssoc($set);
684  }
685 
686  return $rec;
687  }
688 
689 
693  static function lookupParentId($a_id, $a_type)
694  {
695  global $ilDB;
696 
697  $res = $ilDB->query("SELECT parent_id FROM page_object WHERE page_id = ".$ilDB->quote($a_id, "integer")." ".
698  "AND parent_type=".$ilDB->quote($a_type, "text"));
699  $rec = $ilDB->fetchAssoc($res);
700  return $rec["parent_id"];
701  }
702 
706  function _writeParentId($a_parent_type, $a_pg_id, $a_par_id)
707  {
708  global $ilDB;
709 
710  $st = $ilDB->manipulateF("UPDATE page_object SET parent_id = %s WHERE page_id = %s".
711  " AND parent_type = %s", array("integer", "integer", "text"),
712  array($a_par_id, $a_pg_id, $a_parent_type));
713  }
714 
720  function setActivationStart($a_activationstart)
721  {
722  $this->activationstart = $a_activationstart;
723  }
724 
731  {
732  return $this->activationstart;
733  }
734 
740  function setActivationEnd($a_activationend)
741  {
742  $this->activationend = $a_activationend;
743  }
744 
750  function getActivationEnd()
751  {
752  return $this->activationend;
753  }
754 
763  function getContentObject($a_hier_id, $a_pc_id = "")
764  {
765  $cont_node = $this->getContentNode($a_hier_id, $a_pc_id);
766  if (!is_object($cont_node))
767  {
768  return false;
769  }
770  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
771  $node_name = $cont_node->node_name();
772  if ($node_name == "PageObject")
773  {
774  return null;
775  }
776  if ($node_name == "PageContent")
777  {
778  $child_node = $cont_node->first_child();
779  $node_name = $child_node->node_name();
780  }
781 
782  // table extra handling (@todo: get rid of it)
783  if ($node_name == "Table")
784  {
785  if ($child_node->get_attribute("DataTable") == "y")
786  {
787  require_once("./Services/COPage/classes/class.ilPCDataTable.php");
788  $tab = new ilPCDataTable($this);
789  $tab->setNode($cont_node);
790  $tab->setHierId($a_hier_id);
791  }
792  else
793  {
794  require_once("./Services/COPage/classes/class.ilPCTable.php");
795  $tab = new ilPCTable($this);
796  $tab->setNode($cont_node);
797  $tab->setHierId($a_hier_id);
798  }
799  $tab->setPcId($a_pc_id);
800  return $tab;
801  }
802 
803  // media extra handling (@todo: get rid of it)
804  if ($node_name == "MediaObject")
805  {
806  if ($_GET["pgEdMediaMode"] != "") {echo "ilPageObject::error media"; exit;}
807 
808  //require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
809  require_once("./Services/COPage/classes/class.ilPCMediaObject.php");
810 
811  $mal_node =& $child_node->first_child();
812 //echo "ilPageObject::getContentObject:nodename:".$mal_node->node_name().":<br>";
813  $id_arr = explode("_", $mal_node->get_attribute("OriginId"));
814  $mob_id = $id_arr[count($id_arr) - 1];
815 
816  // allow deletion of non-existing media objects
817  if (!ilObject::_exists($mob_id) && in_array("delete", $_POST))
818  {
819  $mob_id = 0;
820  }
821 
822  //$mob =& new ilObjMediaObject($mob_id);
823  $mob = new ilPCMediaObject($this);
824  $mob->readMediaObject($mob_id);
825 
826  //$mob->setDom($this->dom);
827  $mob->setNode($cont_node);
828  $mob->setHierId($a_hier_id);
829  $mob->setPcId($a_pc_id);
830  return $mob;
831  }
832 
833  //
834  // generic procedure
835  //
836 
837  $pc_def = ilCOPagePCDef::getPCDefinitionByName($node_name);
838 
839  // check if pc definition has been found
840  if (!is_array($pc_def))
841  {
842  include_once("./Services/COPage/exceptions/class.ilCOPageUnknownPCTypeException.php");
843  throw new ilCOPageUnknownPCTypeException('Unknown PC Name "'.$node_name.'".');
844  }
845  $pc_class = "ilPC".$pc_def["name"];
846  $pc_path = "./".$pc_def["component"]."/".$pc_def["directory"]."/class.".$pc_class.".php";
847  require_once($pc_path);
848  $pc = new $pc_class($this);
849  $pc->setNode($cont_node);
850  $pc->setHierId($a_hier_id);
851  $pc->setPcId($a_pc_id);
852  return $pc;
853  }
854 
861  function &getContentNode($a_hier_id, $a_pc_id = "")
862  {
863  $xpc = xpath_new_context($this->dom);
864  if($a_hier_id == "pg")
865  {
866  return $this->node;
867  }
868  else
869  {
870  // get per pc id
871  if ($a_pc_id != "")
872  {
873  $path = "//*[@PCID = '$a_pc_id']";
874  $res =& xpath_eval($xpc, $path);
875  if (count($res->nodeset) == 1)
876  {
877  $cont_node =& $res->nodeset[0];
878  return $cont_node;
879  }
880  }
881 
882  // fall back to hier id
883  $path = "//*[@HierId = '$a_hier_id']";
884  $res =& xpath_eval($xpc, $path);
885  if (count($res->nodeset) == 1)
886  {
887  $cont_node =& $res->nodeset[0];
888  return $cont_node;
889  }
890  }
891  }
892 
899  function checkForTag($a_content_tag, $a_hier_id, $a_pc_id = "")
900  {
901  $xpc = xpath_new_context($this->dom);
902  // get per pc id
903  if ($a_pc_id != "")
904  {
905  $path = "//*[@PCID = '$a_pc_id']//".$a_content_tag;
906  $res = xpath_eval($xpc, $path);
907  if (count($res->nodeset) > 0)
908  {
909  return true;
910  }
911  }
912 
913  // fall back to hier id
914  $path = "//*[@HierId = '$a_hier_id']//".$a_content_tag;
915  $res =& xpath_eval($xpc, $path);
916  if (count($res->nodeset) > 0)
917  {
918  return true;
919  }
920  return false;
921  }
922 
923  // only for test purposes
924  function lookforhier($a_hier_id)
925  {
926  $xpc = xpath_new_context($this->dom);
927  $path = "//*[@HierId = '$a_hier_id']";
928  $res =& xpath_eval($xpc, $path);
929  if (count($res->nodeset) == 1)
930  return "YES";
931  else
932  return "NO";
933  }
934 
935 
936  function &getNode()
937  {
938  return $this->node;
939  }
940 
941 
950  function setXMLContent($a_xml, $a_encoding = "UTF-8")
951  {
952  $this->encoding = $a_encoding;
953  $this->xml = $a_xml;
954  }
955 
962  function appendXMLContent($a_xml)
963  {
964  $this->xml.= $a_xml;
965  }
966 
967 
971  function getXMLContent($a_incl_head = false)
972  {
973  // build full http path for XML DOCTYPE header.
974  // Under windows a relative path doesn't work :-(
975  if($a_incl_head)
976  {
977 //echo "+".$this->encoding."+";
978  $enc_str = (!empty($this->encoding))
979  ? "encoding=\"".$this->encoding."\""
980  : "";
981  return "<?xml version=\"1.0\" $enc_str ?>".
982  "<!DOCTYPE PageObject SYSTEM \"".ILIAS_ABSOLUTE_PATH."/xml/".$this->cur_dtd."\">".
983  $this->xml;
984  }
985  else
986  {
987  return $this->xml;
988  }
989  }
990 
995  function copyXmlContent($a_clone_mobs = false)
996  {
997  $xml = $this->getXmlContent();
998  $temp_dom = domxml_open_mem('<?xml version="1.0" encoding="UTF-8"?>'.$xml,
999  DOMXML_LOAD_PARSING, $error);
1000  if(empty($error))
1001  {
1002  $this->handleCopiedContent($temp_dom, true, $a_clone_mobs);
1003  }
1004  $xml = $temp_dom->dump_mem(0, $this->encoding);
1005  $xml = eregi_replace("<\?xml[^>]*>","",$xml);
1006  $xml = eregi_replace("<!DOCTYPE[^>]*>","",$xml);
1007 
1008  return $xml;
1009  }
1010 
1011 // @todo 1: begin: generalize, remove concrete dependencies
1012 
1022  function handleCopiedContent($a_dom, $a_self_ass = true, $a_clone_mobs = false)
1023  {
1024  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1026 
1027  // handle question elements
1028  if ($a_self_ass)
1029  {
1030  $this->newQuestionCopies($a_dom);
1031  }
1032  else
1033  {
1034  $this->removeQuestions($a_dom);
1035  }
1036 
1037  // handle interactive images
1038  $this->newIIMCopies($a_dom);
1039 
1040  // handle media objects
1041  if ($a_clone_mobs)
1042  {
1043  $this->newMobCopies($a_dom);
1044  }
1045 
1046 // @todo 1: move all functions from above to the new domdoc
1047  if ($a_dom instanceof php4DOMDocument)
1048  {
1049  $a_dom = $a_dom->myDOMDocument;
1050  }
1051  foreach ($defs as $def)
1052  {
1054  $cl = $def["pc_class"];
1055  $cl::handleCopiedContent($a_dom, $a_self_ass, $a_clone_mobs);
1056  }
1057 
1058  }
1059 
1064  function newIIMCopies($temp_dom)
1065  {
1066  // Get question IDs
1067  $path = "//InteractiveImage/MediaAlias";
1068  $xpc = xpath_new_context($temp_dom);
1069  $res = & xpath_eval($xpc, $path);
1070 
1071  $q_ids = array();
1072  include_once("./Services/Link/classes/class.ilInternalLink.php");
1073  for ($i = 0; $i < count ($res->nodeset); $i++)
1074  {
1075  $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1076 
1077  $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1078  $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1079 
1080  if (!($inst_id > 0))
1081  {
1082  if ($mob_id > 0)
1083  {
1084  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1085  $media_object = new ilObjMediaObject($mob_id);
1086 
1087  // now copy this question and change reference to
1088  // new question id
1089  $new_mob = $media_object->duplicate();
1090 
1091  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_".$new_mob->getId());
1092  }
1093  }
1094  }
1095  }
1096 
1100  function newMobCopies($temp_dom)
1101  {
1102  // Get question IDs
1103  $path = "//MediaObject/MediaAlias";
1104  $xpc = xpath_new_context($temp_dom);
1105  $res = & xpath_eval($xpc, $path);
1106 
1107  $q_ids = array();
1108  include_once("./Services/Link/classes/class.ilInternalLink.php");
1109  for ($i = 0; $i < count ($res->nodeset); $i++)
1110  {
1111  $or_id = $res->nodeset[$i]->get_attribute("OriginId");
1112 
1113  $inst_id = ilInternalLink::_extractInstOfTarget($or_id);
1114  $mob_id = ilInternalLink::_extractObjIdOfTarget($or_id);
1115 
1116  if (!($inst_id > 0))
1117  {
1118  if ($mob_id > 0)
1119  {
1120  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1121  $media_object = new ilObjMediaObject($mob_id);
1122 
1123  // now copy this question and change reference to
1124  // new question id
1125  $new_mob = $media_object->duplicate();
1126 
1127  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_".$new_mob->getId());
1128  }
1129  }
1130  }
1131  }
1132 
1137  function newQuestionCopies(&$temp_dom)
1138  {
1139  // Get question IDs
1140  $path = "//Question";
1141  $xpc = xpath_new_context($temp_dom);
1142  $res = & xpath_eval($xpc, $path);
1143 
1144  $q_ids = array();
1145  include_once("./Services/Link/classes/class.ilInternalLink.php");
1146  for ($i = 0; $i < count ($res->nodeset); $i++)
1147  {
1148  $qref = $res->nodeset[$i]->get_attribute("QRef");
1149 
1150  $inst_id = ilInternalLink::_extractInstOfTarget($qref);
1152 
1153  if (!($inst_id > 0))
1154  {
1155  if ($q_id > 0)
1156  {
1157  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1158  $question = assQuestion::_instantiateQuestion($q_id);
1159  // check due to #16557
1160  if (is_object($question))
1161  {
1162  // check if page for question exists
1163  // due to a bug in early 4.2.x version this is possible
1164  if (!ilPageObject::_exists("qpl", $q_id))
1165  {
1166  $question->createPageObject();
1167  }
1168 
1169  // now copy this question and change reference to
1170  // new question id
1171  $duplicate_id = $question->duplicate(false);
1172  $res->nodeset[$i]->set_attribute("QRef", "il__qst_".$duplicate_id);
1173  }
1174  }
1175  }
1176  }
1177  }
1178 
1185  function removeQuestions(&$temp_dom)
1186  {
1187  // Get question IDs
1188  $path = "//Question";
1189  $xpc = xpath_new_context($temp_dom);
1190  $res = & xpath_eval($xpc, $path);
1191  for ($i = 0; $i < count ($res->nodeset); $i++)
1192  {
1193  $parent_node = $res->nodeset[$i]->parent_node();
1194  $parent_node->unlink_node($parent_node);
1195  }
1196  }
1197 
1198 // @todo: end
1199 
1207  {
1208  // Get question IDs
1209  $this->buildDom();
1210  $path = "//PageContent";
1211  $xpc = xpath_new_context($this->dom);
1212  $res = & xpath_eval($xpc, $path);
1213  return count ($res->nodeset);
1214  }
1215 
1220  function getXMLFromDom($a_incl_head = false, $a_append_mobs = false, $a_append_bib = false,
1221  $a_append_str = "", $a_omit_pageobject_tag = false)
1222  {
1223  if ($a_incl_head)
1224  {
1225 //echo "\n<br>#".$this->encoding."#";
1226  return $this->dom->dump_mem(0, $this->encoding);
1227  }
1228  else
1229  {
1230  // append multimedia object elements
1231  if ($a_append_mobs || $a_append_bib || $a_append_link_info)
1232  {
1233  $mobs = "";
1234  $bibs = "";
1235  if ($a_append_mobs)
1236  {
1237  $mobs =& $this->getMultimediaXML();
1238  }
1239  if ($a_append_bib)
1240  {
1241 // deprecated
1242 // $bibs =& $this->getBibliographyXML();
1243  }
1244  $trans =& $this->getLanguageVariablesXML();
1245  return "<dummy>".$this->dom->dump_node($this->node).$mobs.$bibs.$trans.$a_append_str."</dummy>";
1246  }
1247  else
1248  {
1249  if (is_object($this->dom))
1250  {
1251  if ($a_omit_pageobject_tag)
1252  {
1253  $xml = "";
1254  $childs =& $this->node->child_nodes();
1255  for($i = 0; $i < count($childs); $i++)
1256  {
1257  $xml.= $this->dom->dump_node($childs[$i]);
1258  }
1259  return $xml;
1260  }
1261  else
1262  {
1263  $xml = $this->dom->dump_mem(0, $this->encoding);
1264  $xml = eregi_replace("<\?xml[^>]*>","",$xml);
1265  $xml = eregi_replace("<!DOCTYPE[^>]*>","",$xml);
1266 
1267  return $xml;
1268 
1269  // don't use dump_node. This gives always entities.
1270  //return $this->dom->dump_node($this->node);
1271  }
1272  }
1273  else
1274  {
1275  return "";
1276  }
1277  }
1278  }
1279  }
1280 
1285  {
1286  global $lng;
1287 
1288  $xml = "<LVs>";
1289  $lang_vars = array(
1290  "ed_paste_clip", "ed_edit", "ed_edit_prop", "ed_delete", "ed_moveafter",
1291  "ed_movebefore", "ed_go", "ed_class", "ed_width", "ed_align_left",
1292  "ed_align_right", "ed_align_center", "ed_align_left_float",
1293  "ed_align_right_float", "ed_delete_item", "ed_new_item_before",
1294  "ed_new_item_after", "ed_copy_clip", "please_select", "ed_split_page",
1295  "ed_item_up", "ed_item_down", "ed_split_page_next","ed_enable",
1296  "de_activate", "ed_paste", "ed_edit_multiple", "ed_cut", "ed_copy", "ed_insert_templ",
1297  "ed_click_to_add_pg", "download");
1298 
1299  // collect lang vars from pc elements
1300  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
1302  foreach ($defs as $def)
1303  {
1304  $lang_vars[] = "pc_".$def["pc_type"];
1305  $lang_vars[] = "ed_insert_".$def["pc_type"];
1306 
1308  $cl = $def["pc_class"];
1309  $lvs = call_user_func($def["pc_class"].'::getLangVars');
1310  foreach ($lvs as $lv)
1311  {
1312  $lang_vars[] = $lv;
1313  }
1314  }
1315 
1316  foreach ($lang_vars as $lang_var)
1317  {
1318  $this->appendLangVarXML($xml, $lang_var);
1319  }
1320 
1321  $xml.= "</LVs>";
1322 
1323  return $xml;
1324  }
1325 
1326  function appendLangVarXML(&$xml, $var)
1327  {
1328  global $lng;
1329 
1330  $xml.= "<LV name=\"$var\" value=\"".$lng->txt("cont_".$var)."\"/>";
1331  }
1332 
1333 // @todo begin: move this to paragraph class
1334 
1336  {
1337  if($this->dom)
1338  {
1339  require_once("./Services/COPage/classes/class.ilPCParagraph.php");
1340  $xpc = xpath_new_context($this->dom);
1341  $path = "//Paragraph[1]";
1342  $res =& xpath_eval($xpc, $path);
1343  if (count($res->nodeset) > 0)
1344  {
1345  $cont_node =& $res->nodeset[0]->parent_node();
1346  $par =& new ilPCParagraph($this);
1347  $par->setNode($cont_node);
1348  return $par->getText();
1349  }
1350  }
1351  return "";
1352  }
1353 
1360  function setParagraphContent($a_hier_id, $a_content)
1361  {
1362  $node = $this->getContentNode($a_hier_id);
1363  if (is_object($node))
1364  {
1365  $node->set_content($a_content);
1366  }
1367  }
1368 
1369 // @todo end
1370 
1371 
1380  // @todo: can we do this better
1381  function setContainsIntLink($a_contains_link)
1382  {
1383  $this->contains_int_link = $a_contains_link;
1384  }
1385 
1390  // @todo: can we do this better
1391  function containsIntLink()
1392  {
1393  return $this->contains_int_link;
1394  }
1395 
1401  function setImportMode($a_val)
1402  {
1403  $this->import_mode = $a_val;
1404  }
1405 
1411  function getImportMode()
1412  {
1413  return $this->import_mode;
1414  }
1415 
1416  function needsImportParsing($a_parse = "")
1417  {
1418 
1419  if ($a_parse === true)
1420  {
1421  $this->needs_parsing = true;
1422  }
1423  if ($a_parse === false)
1424  {
1425  $this->needs_parsing = false;
1426  }
1427  return $this->needs_parsing;
1428  }
1429 
1435  // @todo: can we do this better
1436  public function setContainsQuestion($a_val)
1437  {
1438  $this->contains_question = $a_val;
1439  }
1440 
1446  public function getContainsQuestion()
1447  {
1448  return $this->contains_question;
1449  }
1450 
1451 
1456  // @todo: move to media class
1457  function collectMediaObjects($a_inline_only = true)
1458  {
1459 //echo htmlentities($this->getXMLFromDom());
1460  // determine all media aliases of the page
1461  $xpc = xpath_new_context($this->dom);
1462  $path = "//MediaObject/MediaAlias";
1463  $res =& xpath_eval($xpc, $path);
1464  $mob_ids = array();
1465  for($i = 0; $i < count($res->nodeset); $i++)
1466  {
1467  $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1468  $mob_id = $id_arr[count($id_arr) - 1];
1469  $mob_ids[$mob_id] = $mob_id;
1470  }
1471 
1472  // determine all media aliases of interactive images
1473  $xpc = xpath_new_context($this->dom);
1474  $path = "//InteractiveImage/MediaAlias";
1475  $res =& xpath_eval($xpc, $path);
1476  for($i = 0; $i < count($res->nodeset); $i++)
1477  {
1478  $id_arr = explode("_", $res->nodeset[$i]->get_attribute("OriginId"));
1479  $mob_id = $id_arr[count($id_arr) - 1];
1480  $mob_ids[$mob_id] = $mob_id;
1481  }
1482 
1483  // determine all inline internal media links
1484  $xpc = xpath_new_context($this->dom);
1485  $path = "//IntLink[@Type = 'MediaObject']";
1486  $res =& xpath_eval($xpc, $path);
1487 
1488  for($i = 0; $i < count($res->nodeset); $i++)
1489  {
1490  if (($res->nodeset[$i]->get_attribute("TargetFrame") == "") ||
1491  (!$a_inline_only))
1492  {
1493  $target = $res->nodeset[$i]->get_attribute("Target");
1494  $id_arr = explode("_", $target);
1495  if (($id_arr[1] == IL_INST_ID) ||
1496  (substr($target, 0, 4) == "il__"))
1497  {
1498  $mob_id = $id_arr[count($id_arr) - 1];
1499  if (ilObject::_exists($mob_id))
1500  {
1501  $mob_ids[$mob_id] = $mob_id;
1502  }
1503  }
1504  }
1505  }
1506 
1507  return $mob_ids;
1508  }
1509 
1510 
1514  // @todo: can we do this better?
1515  function getInternalLinks($a_cnt_multiple = false)
1516  {
1517  // get all internal links of the page
1518  $xpc = xpath_new_context($this->dom);
1519  $path = "//IntLink";
1520  $res = xpath_eval($xpc, $path);
1521 
1522  $links = array();
1523  $cnt_multiple = 1;
1524  for($i = 0; $i < count($res->nodeset); $i++)
1525  {
1526  $add = "";
1527  if ($a_cnt_multiple)
1528  {
1529  $add = ":".$cnt_multiple;
1530  }
1531  $target = $res->nodeset[$i]->get_attribute("Target");
1532  $type = $res->nodeset[$i]->get_attribute("Type");
1533  $targetframe = $res->nodeset[$i]->get_attribute("TargetFrame");
1534  $anchor = $res->nodeset[$i]->get_attribute("Anchor");
1535  $links[$target.":".$type.":".$targetframe.":".$anchor.$add] =
1536  array("Target" => $target, "Type" => $type,
1537  "TargetFrame" => $targetframe, "Anchor" => $anchor);
1538 
1539  // get links (image map areas) for inline media objects
1540  if ($type == "MediaObject" && $targetframe == "")
1541  {
1542  if (substr($target, 0, 4) =="il__")
1543  {
1544  $id_arr = explode("_", $target);
1545  $id = $id_arr[count($id_arr) - 1];
1546 
1547  $med_links = ilMediaItem::_getMapAreasIntLinks($id);
1548  foreach($med_links as $key => $med_link)
1549  {
1550  $links[$key] = $med_link;
1551  }
1552  }
1553 
1554  }
1555 //echo "<br>-:".$target.":".$type.":".$targetframe.":-";
1556  $cnt_multiple++;
1557  }
1558  unset($xpc);
1559 
1560  // get all media aliases
1561  $xpc = xpath_new_context($this->dom);
1562  $path = "//MediaAlias";
1563  $res =& xpath_eval($xpc, $path);
1564 
1565  require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
1566  for($i = 0; $i < count($res->nodeset); $i++)
1567  {
1568  $oid = $res->nodeset[$i]->get_attribute("OriginId");
1569  if (substr($oid, 0, 4) =="il__")
1570  {
1571  $id_arr = explode("_", $oid);
1572  $id = $id_arr[count($id_arr) - 1];
1573 
1574  $med_links = ilMediaItem::_getMapAreasIntLinks($id);
1575  foreach($med_links as $key => $med_link)
1576  {
1577  $links[$key] = $med_link;
1578  }
1579  }
1580  }
1581  unset($xpc);
1582 
1583  return $links;
1584  }
1585 
1590  // @todo: move to media class
1591  function getMultimediaXML()
1592  {
1593  $mob_ids = $this->collectMediaObjects();
1594 
1595  // get xml of corresponding media objects
1596  $mobs_xml = "";
1597  require_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1598  foreach($mob_ids as $mob_id => $dummy)
1599  {
1600  if (ilObject::_lookupType($mob_id) == "mob")
1601  {
1602  $mob_obj =& new ilObjMediaObject($mob_id);
1603  $mobs_xml .= $mob_obj->getXML(IL_MODE_OUTPUT);
1604  }
1605  }
1606 //var_dump($mobs_xml);
1607  return $mobs_xml;
1608  }
1609 
1613  // @todo: move to media class
1614  function getMediaAliasElement($a_mob_id, $a_nr = 1)
1615  {
1616  $xpc = xpath_new_context($this->dom);
1617  $path = "//MediaObject/MediaAlias[@OriginId='il__mob_$a_mob_id']";
1618  $res =& xpath_eval($xpc, $path);
1619  $mal_node =& $res->nodeset[$a_nr - 1];
1620  $mob_node =& $mal_node->parent_node();
1621 
1622  return $this->dom->dump_node($mob_node);
1623  }
1624 
1630  function validateDom()
1631  {
1632  $this->stripHierIDs();
1633 
1634  // possible fix for #14820
1635  libxml_disable_entity_loader(false);
1636 
1637  @$this->dom->validate($error);
1638 
1639  return $error;
1640  }
1641 
1657  // @todo: can we do this better? remove dependencies?
1658  function addHierIDs()
1659  {
1660  $this->hier_ids = array();
1661  $this->first_row_ids = array();
1662  $this->first_col_ids = array();
1663  $this->list_item_ids = array();
1664  $this->file_item_ids = array();
1665 
1666  // set hierarchical ids for Paragraphs, Tables, TableRows and TableData elements
1667  $xpc = xpath_new_context($this->dom);
1668  //$path = "//Paragraph | //Table | //TableRow | //TableData";
1669 
1670  $sep = $path = "";
1671  foreach ($this->id_elements as $el)
1672  {
1673  $path.= $sep."//".$el;
1674  $sep = " | ";
1675  }
1676 
1677  $res =& xpath_eval($xpc, $path);
1678  for($i = 0; $i < count($res->nodeset); $i++)
1679  {
1680  $cnode = $res->nodeset[$i];
1681  $ctag = $cnode->node_name();
1682 
1683  // get hierarchical id of previous sibling
1684  $sib_hier_id = "";
1685  while($cnode =& $cnode->previous_sibling())
1686  {
1687  if (($cnode->node_type() == XML_ELEMENT_NODE)
1688  && $cnode->has_attribute("HierId"))
1689  {
1690  $sib_hier_id = $cnode->get_attribute("HierId");
1691  //$sib_hier_id = $id_attr->value();
1692  break;
1693  }
1694  }
1695 
1696  if ($sib_hier_id != "") // set id to sibling id "+ 1"
1697  {
1698  require_once("./Services/COPage/classes/class.ilPageContent.php");
1699  $node_hier_id = ilPageContent::incEdId($sib_hier_id);
1700  $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1701  $this->hier_ids[] = $node_hier_id;
1702  if ($ctag == "TableData")
1703  {
1704  if (substr($par_hier_id,strlen($par_hier_id)-2) == "_1")
1705  {
1706  $this->first_row_ids[] = $node_hier_id;
1707  }
1708  }
1709  if ($ctag == "ListItem")
1710  {
1711  $this->list_item_ids[] = $node_hier_id;
1712  }
1713  if ($ctag == "FileItem")
1714  {
1715  $this->file_item_ids[] = $node_hier_id;
1716  }
1717  }
1718  else // no sibling -> node is first child
1719  {
1720  // get hierarchical id of next parent
1721  $cnode = $res->nodeset[$i];
1722  $par_hier_id = "";
1723  while($cnode =& $cnode->parent_node())
1724  {
1725  if (($cnode->node_type() == XML_ELEMENT_NODE)
1726  && $cnode->has_attribute("HierId"))
1727  {
1728  $par_hier_id = $cnode->get_attribute("HierId");
1729  //$par_hier_id = $id_attr->value();
1730  break;
1731  }
1732  }
1733 //echo "<br>par:".$par_hier_id." ($ctag)";
1734  if (($par_hier_id != "") && ($par_hier_id != "pg")) // set id to parent_id."_1"
1735  {
1736  $node_hier_id = $par_hier_id."_1";
1737  $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1738  $this->hier_ids[] = $node_hier_id;
1739  if ($ctag == "TableData")
1740  {
1741  $this->first_col_ids[] = $node_hier_id;
1742  if (substr($par_hier_id,strlen($par_hier_id)-2) == "_1")
1743  {
1744  $this->first_row_ids[] = $node_hier_id;
1745  }
1746  }
1747  if ($ctag == "ListItem")
1748  {
1749  $this->list_item_ids[] = $node_hier_id;
1750  }
1751  if ($ctag == "FileItem")
1752  {
1753  $this->file_item_ids[] = $node_hier_id;
1754  }
1755 
1756  }
1757  else // no sibling, no parent -> first node
1758  {
1759  $node_hier_id = "1";
1760  $res->nodeset[$i]->set_attribute("HierId", $node_hier_id);
1761  $this->hier_ids[] = $node_hier_id;
1762  }
1763  }
1764  }
1765 
1766  // set special hierarchical id "pg" for pageobject
1767  $xpc = xpath_new_context($this->dom);
1768  $path = "//PageObject";
1769  $res =& xpath_eval($xpc, $path);
1770  for($i = 0; $i < count($res->nodeset); $i++) // should only be 1
1771  {
1772  $res->nodeset[$i]->set_attribute("HierId", "pg");
1773  $this->hier_ids[] = "pg";
1774  }
1775  unset($xpc);
1776  }
1777 
1781  function getHierIds()
1782  {
1783  return $this->hier_ids;
1784  }
1785 
1789  // @todo: move to table classes
1790  function getFirstRowIds()
1791  {
1792  return $this->first_row_ids;
1793  }
1794 
1798  // @todo: move to table classes
1800  {
1801  return $this->first_col_ids;
1802  }
1803 
1807  // @todo: move to list class
1808  function getListItemIds()
1809  {
1810  return $this->list_item_ids;
1811  }
1812 
1816  // @todo: move to file item class
1817  function getFileItemIds()
1818  {
1819  return $this->file_item_ids;
1820  }
1821 
1825  function stripHierIDs()
1826  {
1827  if(is_object($this->dom))
1828  {
1829  $xpc = xpath_new_context($this->dom);
1830  $path = "//*[@HierId]";
1831  $res =& xpath_eval($xpc, $path);
1832  for($i = 0; $i < count($res->nodeset); $i++) // should only be 1
1833  {
1834  if ($res->nodeset[$i]->has_attribute("HierId"))
1835  {
1836  $res->nodeset[$i]->remove_attribute("HierId");
1837  }
1838  }
1839  unset($xpc);
1840  }
1841  }
1842 
1846  function getHierIdsForPCIds($a_pc_ids)
1847  {
1848  if (!is_array($a_pc_ids) || count($a_pc_ids) == 0)
1849  {
1850  return array();
1851  }
1852  $ret = array();
1853 
1854  if(is_object($this->dom))
1855  {
1856  $xpc = xpath_new_context($this->dom);
1857  $path = "//*[@PCID]";
1858  $res =& xpath_eval($xpc, $path);
1859  for($i = 0; $i < count($res->nodeset); $i++) // should only be 1
1860  {
1861  $pc_id = $res->nodeset[$i]->get_attribute("PCID");
1862  if (in_array($pc_id, $a_pc_ids))
1863  {
1864  $ret[$pc_id] = $res->nodeset[$i]->get_attribute("HierId");
1865  }
1866  }
1867  unset($xpc);
1868  }
1869 //var_dump($ret);
1870  return $ret;
1871  }
1872 
1876  // @todo: move to file item class
1877  function addFileSizes()
1878  {
1879  $xpc = xpath_new_context($this->dom);
1880  $path = "//FileItem";
1881  $res =& xpath_eval($xpc, $path);
1882  for($i = 0; $i < count($res->nodeset); $i++)
1883  {
1884  $cnode =& $res->nodeset[$i];
1885  $size_node =& $this->dom->create_element("Size");
1886  $size_node =& $cnode->append_child($size_node);
1887 
1888  $childs =& $cnode->child_nodes();
1889  $size = "";
1890  for($j = 0; $j < count($childs); $j++)
1891  {
1892  if ($childs[$j]->node_name() == "Identifier")
1893  {
1894  if ($childs[$j]->has_attribute("Entry"))
1895  {
1896  $entry = $childs[$j]->get_attribute("Entry");
1897  $entry_arr = explode("_", $entry);
1898  $id = $entry_arr[count($entry_arr) - 1];
1899  require_once("./Modules/File/classes/class.ilObjFile.php");
1901  }
1902  }
1903  }
1904  $size_node->set_content($size);
1905  }
1906 
1907  unset($xpc);
1908  }
1909 
1914  // @todo: possible to improve this?
1915  function resolveIntLinks()
1916  {
1917  // resolve normal internal links
1918  $xpc = xpath_new_context($this->dom);
1919  $path = "//IntLink";
1920  $res =& xpath_eval($xpc, $path);
1921  for($i = 0; $i < count($res->nodeset); $i++)
1922  {
1923  $target = $res->nodeset[$i]->get_attribute("Target");
1924  $type = $res->nodeset[$i]->get_attribute("Type");
1925 
1926  $new_target = ilInternalLink::_getIdForImportId($type, $target);
1927  if ($new_target !== false)
1928  {
1929  $res->nodeset[$i]->set_attribute("Target", $new_target);
1930  }
1931  else // check wether link target is same installation
1932  {
1933  if (ilInternalLink::_extractInstOfTarget($target) == IL_INST_ID &&
1934  IL_INST_ID > 0 && $type != "RepositoryItem")
1935  {
1936  $new_target = ilInternalLink::_removeInstFromTarget($target);
1937  if (ilInternalLink::_exists($type, $new_target))
1938  {
1939  $res->nodeset[$i]->set_attribute("Target", $new_target);
1940  }
1941  }
1942  }
1943 
1944  }
1945  unset($xpc);
1946 
1947  // resolve internal links in map areas
1948  $xpc = xpath_new_context($this->dom);
1949  $path = "//MediaAlias";
1950  $res =& xpath_eval($xpc, $path);
1951 //echo "<br><b>page::resolve</b><br>";
1952 //echo "Content:".htmlentities($this->getXMLFromDOM()).":<br>";
1953  for($i = 0; $i < count($res->nodeset); $i++)
1954  {
1955  $orig_id = $res->nodeset[$i]->get_attribute("OriginId");
1956  $id_arr = explode("_", $orig_id);
1957  $mob_id = $id_arr[count($id_arr) - 1];
1959  }
1960  }
1961 
1968  // @todo: move to media classes?
1969  function resolveMediaAliases($a_mapping)
1970  {
1971  // resolve normal internal links
1972  $xpc = xpath_new_context($this->dom);
1973  $path = "//MediaAlias";
1974  $res =& xpath_eval($xpc, $path);
1975  $changed = false;
1976  for($i = 0; $i < count($res->nodeset); $i++)
1977  {
1978  $old_id = $res->nodeset[$i]->get_attribute("OriginId");
1979  $old_id = explode("_", $old_id);
1980  $old_id = $old_id[count($old_id) - 1];
1981  if ($a_mapping[$old_id] > 0)
1982  {
1983  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_".$a_mapping[$old_id]);
1984  $changed = true;
1985  }
1986  }
1987  unset($xpc);
1988 
1989  return $changed;
1990  }
1991 
1998  // @todo: move to iim classes?
1999  function resolveIIMMediaAliases($a_mapping)
2000  {
2001  // resolve normal internal links
2002  $xpc = xpath_new_context($this->dom);
2003  $path = "//InteractiveImage/MediaAlias";
2004  $res =& xpath_eval($xpc, $path);
2005  $changed = false;
2006  for($i = 0; $i < count($res->nodeset); $i++)
2007  {
2008  $old_id = $res->nodeset[$i]->get_attribute("OriginId");
2009  if ($a_mapping[$old_id] > 0)
2010  {
2011  $res->nodeset[$i]->set_attribute("OriginId", "il__mob_".$a_mapping[$old_id]);
2012  $changed = true;
2013  }
2014  }
2015  unset($xpc);
2016 
2017  return $changed;
2018  }
2019 
2026  // @todo: move to file classes?
2027  function resolveFileItems($a_mapping)
2028  {
2029  // resolve normal internal links
2030  $xpc = xpath_new_context($this->dom);
2031  $path = "//FileItem/Identifier";
2032  $res =& xpath_eval($xpc, $path);
2033  $changed = false;
2034  for($i = 0; $i < count($res->nodeset); $i++)
2035  {
2036  $old_id = $res->nodeset[$i]->get_attribute("Entry");
2037  $old_id = explode("_", $old_id);
2038  $old_id = $old_id[count($old_id) - 1];
2039  if ($a_mapping[$old_id] > 0)
2040  {
2041  $res->nodeset[$i]->set_attribute("Entry", "il__file_".$a_mapping[$old_id]);
2042  $changed = true;
2043  }
2044  }
2045  unset($xpc);
2046 
2047  return $changed;
2048  }
2049 
2054  // @todo: move to question classes
2055  function resolveQuestionReferences($a_mapping)
2056  {
2057  // resolve normal internal links
2058  $xpc = xpath_new_context($this->dom);
2059  $path = "//Question";
2060  $res =& xpath_eval($xpc, $path);
2061  for($i = 0; $i < count($res->nodeset); $i++)
2062  {
2063  $qref = $res->nodeset[$i]->get_attribute("QRef");
2064 
2065  if (isset($a_mapping[$qref]))
2066  {
2067  $res->nodeset[$i]->set_attribute("QRef", "il__qst_".$a_mapping[$qref]["pool"]);
2068  }
2069  }
2070  unset($xpc);
2071  }
2072 
2073 
2080  // @todo: generalize, internal links usage info
2081  function moveIntLinks($a_from_to)
2082  {
2083  $this->buildDom();
2084 
2085  $changed = false;
2086 
2087  // resolve normal internal links
2088  $xpc = xpath_new_context($this->dom);
2089  $path = "//IntLink";
2090  $res =& xpath_eval($xpc, $path);
2091  for($i = 0; $i < count($res->nodeset); $i++)
2092  {
2093  $target = $res->nodeset[$i]->get_attribute("Target");
2094  $type = $res->nodeset[$i]->get_attribute("Type");
2095  $obj_id = ilInternalLink::_extractObjIdOfTarget($target);
2096  if ($a_from_to[$obj_id] > 0 && is_int(strpos($target, "__")))
2097  {
2098  if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg")
2099  {
2100  $res->nodeset[$i]->set_attribute("Target", "il__pg_".$a_from_to[$obj_id]);
2101  $changed = true;
2102  }
2103  if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st")
2104  {
2105  $res->nodeset[$i]->set_attribute("Target", "il__st_".$a_from_to[$obj_id]);
2106  $changed = true;
2107  }
2108  }
2109  }
2110  unset($xpc);
2111 
2112  // map areas
2113  $this->addHierIDs();
2114  $xpc = xpath_new_context($this->dom);
2115  $path = "//MediaAlias";
2116  $res =& xpath_eval($xpc, $path);
2117 
2118  require_once("Services/MediaObjects/classes/class.ilMediaItem.php");
2119  require_once("Services/COPage/classes/class.ilMediaAliasItem.php");
2120 
2121  for($i = 0; $i < count($res->nodeset); $i++)
2122  {
2123  $media_object_node = $res->nodeset[$i]->parent_node();
2124  $page_content_node = $media_object_node->parent_node();
2125  $c_hier_id = $page_content_node->get_attribute("HierId");
2126 
2127  // first check, wheter we got instance map areas -> take these
2128  $std_alias_item = new ilMediaAliasItem($this->dom,
2129  $c_hier_id, "Standard");
2130  $areas = $std_alias_item->getMapAreas();
2131  $correction_needed = false;
2132  if (count($areas) > 0)
2133  {
2134  // check if correction needed
2135  foreach($areas as $area)
2136  {
2137  if ($area["Type"] == "PageObject" ||
2138  $area["Type"] == "StructureObject")
2139  {
2140  $t = $area["Target"];
2141  $tid = _extractObjIdOfTarget($t);
2142  if ($a_from_to[$tid] > 0)
2143  {
2144  $correction_needed = true;
2145  }
2146  }
2147  }
2148  }
2149  else
2150  {
2151  $areas = array();
2152 
2153  // get object map areas and check whether at least one must
2154  // be corrected
2155  $oid = $res->nodeset[$i]->get_attribute("OriginId");
2156  if (substr($oid, 0, 4) =="il__")
2157  {
2158  $id_arr = explode("_", $oid);
2159  $id = $id_arr[count($id_arr) - 1];
2160 
2161  $mob = new ilObjMediaObject($id);
2162  $med_item = $mob->getMediaItem("Standard");
2163  $med_areas = $med_item->getMapAreas();
2164 
2165  foreach($med_areas as $area)
2166  {
2167  $link_type = ($area->getLinkType() == "int")
2168  ? "IntLink"
2169  : "ExtLink";
2170 
2171  $areas[] = array(
2172  "Nr" => $area->getNr(),
2173  "Shape" => $area->getShape(),
2174  "Coords" => $area->getCoords(),
2175  "Link" => array(
2176  "LinkType" => $link_type,
2177  "Href" => $area->getHref(),
2178  "Title" => $area->getTitle(),
2179  "Target" => $area->getTarget(),
2180  "Type" => $area->getType(),
2181  "TargetFrame" => $area->getTargetFrame()
2182  )
2183  );
2184 
2185  if ($area->getType() == "PageObject" ||
2186  $area->getType() == "StructureObject")
2187  {
2188  $t = $area->getTarget();
2190  if ($a_from_to[$tid] > 0)
2191  {
2192  $correction_needed = true;
2193  }
2194 //var_dump($a_from_to);
2195  }
2196  }
2197  }
2198  }
2199 
2200  // correct map area links
2201  if ($correction_needed)
2202  {
2203  $changed = true;
2204  $std_alias_item->deleteAllMapAreas();
2205  foreach($areas as $area)
2206  {
2207  if ($area["Link"]["LinkType"] == "IntLink")
2208  {
2209  $target = $area["Link"]["Target"];
2210  $type = $area["Link"]["Type"];
2211  $obj_id = ilInternalLink::_extractObjIdOfTarget($target);
2212  if ($a_from_to[$obj_id] > 0)
2213  {
2214  if ($type == "PageObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "pg")
2215  {
2216  $area["Link"]["Target"] = "il__pg_".$a_from_to[$obj_id];
2217  }
2218  if ($type == "StructureObject" && ilLMObject::_lookupType($a_from_to[$obj_id]) == "st")
2219  {
2220  $area["Link"]["Target"] = "il__st_".$a_from_to[$obj_id];
2221  }
2222  }
2223  }
2224 
2225  $std_alias_item->addMapArea($area["Shape"], $area["Coords"],
2226  $area["Link"]["Title"],
2227  array( "Type" => $area["Link"]["Type"],
2228  "TargetFrame" => $area["Link"]["TargetFrame"],
2229  "Target" => $area["Link"]["Target"],
2230  "Href" => $area["Link"]["Href"],
2231  "LinkType" => $area["Link"]["LinkType"],
2232  ));
2233  }
2234  }
2235  }
2236  unset($xpc);
2237 
2238  return $changed;
2239  }
2240 
2246  // @todo: generalize, internal links usage info
2247  static function _handleImportRepositoryLinks($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2248  {
2249  include_once("./Services/Link/classes/class.ilInternalLink.php");
2250 
2251 //echo "-".$a_rep_import_id."-".$a_rep_ref_id."-";
2252  $sources = ilInternalLink::_getSourcesOfTarget("obj",
2253  ilInternalLink::_extractObjIdOfTarget($a_rep_import_id),
2254  ilInternalLink::_extractInstOfTarget($a_rep_import_id));
2255 //var_dump($sources);
2256  foreach($sources as $source)
2257  {
2258 //echo "A";
2259  if ($source["type"] == "lm:pg")
2260  {
2261 //echo "B";
2262  include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
2263  if (self::_exists("lm", $source["id"], $source["lang"]))
2264  {
2265  $page_obj = new ilLMPage($source["id"], 0, $source["lang"]);
2266  if (!$page_obj->page_not_found)
2267  {
2268  //echo "C";
2269  $page_obj->handleImportRepositoryLink($a_rep_import_id,
2270  $a_rep_type, $a_rep_ref_id);
2271  }
2272  $page_obj->update();
2273  }
2274  }
2275  }
2276  }
2277 
2278  // @todo: generalize, internal links usage info
2279  function handleImportRepositoryLink($a_rep_import_id, $a_rep_type, $a_rep_ref_id)
2280  {
2281  $this->buildDom();
2282 
2283  // resolve normal internal links
2284  $xpc = xpath_new_context($this->dom);
2285  $path = "//IntLink";
2286  $res =& xpath_eval($xpc, $path);
2287 //echo "1";
2288  for($i = 0; $i < count($res->nodeset); $i++)
2289  {
2290 //echo "2";
2291  $target = $res->nodeset[$i]->get_attribute("Target");
2292  $type = $res->nodeset[$i]->get_attribute("Type");
2293  if ($target == $a_rep_import_id && $type == "RepositoryItem")
2294  {
2295 //echo "setting:"."il__".$a_rep_type."_".$a_rep_ref_id;
2296  $res->nodeset[$i]->set_attribute("Target",
2297  "il__".$a_rep_type."_".$a_rep_ref_id);
2298  }
2299  }
2300  unset($xpc);
2301  }
2302 
2306  function createFromXML()
2307  {
2308  global $lng, $ilDB, $ilUser;
2309 
2310 //echo "<br>PageObject::createFromXML[".$this->getId()."]";
2311 
2312  $empty = false;
2313  if($this->getXMLContent() == "")
2314  {
2315  $this->setXMLContent("<PageObject></PageObject>");
2316  $empty = true;
2317  }
2318 
2319  $content = $this->getXMLContent();
2320  $this->buildDom(true);
2321  $dom_doc = $this->getDomDoc();
2322 
2323  $iel = $this->containsDeactivatedElements($content);
2324  $inl = $this->containsIntLinks($content);
2325 
2326  // create object
2327  $ilDB->insert("page_object", array(
2328  "page_id" => array("integer", $this->getId()),
2329  "parent_id" => array("integer", $this->getParentId()),
2330  "lang" => array("text", $this->getLanguage()),
2331  "content" => array("clob", $content),
2332  "parent_type" => array("text", $this->getParentType()),
2333  "create_user" => array("integer", $ilUser->getId()),
2334  "last_change_user" => array("integer", $ilUser->getId()),
2335  "active" => array("integer", $this->getActive()),
2336  "inactive_elements" => array("integer", $iel),
2337  "int_links" => array("integer", $inl),
2338  "created" => array("timestamp", ilUtil::now()),
2339  "last_change" => array("timestamp", ilUtil::now())
2340  ));
2341 
2342  // after update event
2343  $this->__afterUpdate($dom_doc, $content, true, $empty);
2344 
2345  }
2346 
2347 
2356  function updateFromXML()
2357  {
2358  global $lng, $ilDB, $ilUser;
2359 
2360 //echo "<br>PageObject::updateFromXML[".$this->getId()."]";
2361 //echo "update:".ilUtil::prepareDBString(($this->getXMLContent())).":<br>";
2362 //echo "update:".htmlentities($this->getXMLContent()).":<br>";
2363 
2364  $content = $this->getXMLContent();
2365  $this->buildDom(true);
2366  $dom_doc = $this->getDomDoc();
2367 
2368  $iel = $this->containsDeactivatedElements($content);
2369  $inl = $this->containsIntLinks($content);
2370 
2371  $ilDB->update("page_object", array(
2372  "content" => array("clob", $content),
2373  "parent_id" => array("integer", $this->getParentId()),
2374  "last_change_user" => array("integer", $ilUser->getId()),
2375  "last_change" => array("timestamp", ilUtil::now()),
2376  "active" => array("integer", $this->getActive()),
2377  "activation_start" => array("timestamp", $this->getActivationStart()),
2378  "activation_end" => array("timestamp", $this->getActivationEnd()),
2379  "inactive_elements" => array("integer", $iel),
2380  "int_links" => array("integer", $inl),
2381  ), array(
2382  "page_id" => array("integer", $this->getId()),
2383  "parent_type" => array("text", $this->getParentType()),
2384  "lang" => array("text", $this->getLanguage())
2385  ));
2386 
2387  // after update event
2388  $this->__afterUpdate($dom_doc, $content);
2389 
2390  return true;
2391  }
2392 
2399  protected final function __afterUpdate($a_domdoc, $a_xml, $a_creation = false, $a_empty = false)
2400  {
2401  // we do not need this if we are creating an empty page
2402  if (!$a_creation || !$a_empty)
2403  {
2404  // save internal link information
2405  // the page object is responsible to do this, since it "offers" the
2406  // internal link feature pc and page classes
2407  $this->saveInternalLinks($a_domdoc);
2408 
2409  // save style usage
2410  $this->saveStyleUsage($a_domdoc);
2411 
2412  // pc classes hook
2413  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2415  foreach ($defs as $def)
2416  {
2418  $cl = $def["pc_class"];
2419  call_user_func($def["pc_class"].'::afterPageUpdate', $this, $a_domdoc, $a_xml, $a_creation);
2420  }
2421  }
2422 
2423  // call page hook
2424  $this->afterUpdate($a_domdoc, $a_xml);
2425 
2426  // call update listeners
2427  $this->callUpdateListeners();
2428  }
2429 
2436  function afterUpdate()
2437  {
2438  }
2439 
2440 
2445  function update($a_validate = true, $a_no_history = false)
2446  {
2447  global $lng, $ilDB, $ilUser, $ilLog, $ilCtrl;
2448 
2449  $lm_set = new ilSetting("lm");
2450 
2451 //echo "<br>**".$this->getId()."**";
2452 //echo "<br>PageObject::update[".$this->getId()."],validate($a_validate)";
2453 //echo "\n<br>dump_all2:".$this->dom->dump_mem(0, "UTF-8").":";
2454 //echo "\n<br>PageObject::update:".$this->getXMLFromDom().":";
2455 //debug_print_backtrace();
2456 //echo "<br>PageObject::update:".htmlentities($this->getXMLFromDom()); exit;
2457 
2458  // add missing pc ids
2459  if (!$this->checkPCIds())
2460  {
2461  $this->insertPCIds();
2462  }
2463 
2464  // test validating
2465  if($a_validate)
2466  {
2467  $errors = $this->validateDom();
2468  }
2469 //var_dump($errors); exit;
2470  if (empty($errors) && !$this->getEditLock())
2471  {
2472  include_once("./Services/User/classes/class.ilUserUtil.php");
2473  $lock = $this->getEditLockInfo();
2474  $errors[0] = array(0 => 0,
2475  1 => "nocontent#".$lng->txt("cont_not_saved_edit_lock_expired")."<br />".
2476  $lng->txt("obj_usr").": ".
2477  ilUserUtil::getNamePresentation($lock["edit_lock_user"])."<br />".
2478  $lng->txt("content_until").": ".
2479  ilDatePresentation::formatDate(new ilDateTime($lock["edit_lock_until"],IL_CAL_UNIX))
2480  );
2481  }
2482 
2483 //echo "-".htmlentities($this->getXMLFromDom())."-"; exit;
2484  if(empty($errors))
2485  {
2486  // @todo 1: is this page type or pc content type
2487  // related -> plugins should be able to hook in!?
2489 
2490  // get xml content
2491  $content = $this->getXMLFromDom();
2492  $dom_doc = $this->getDomDoc();
2493 
2494  // this needs to be locked
2495 
2496  // write history entry
2497  $old_set = $ilDB->query("SELECT * FROM page_object WHERE ".
2498  "page_id = ".$ilDB->quote($this->getId(), "integer")." AND ".
2499  "parent_type = ".$ilDB->quote($this->getParentType(), "text")." AND ".
2500  "lang = ".$ilDB->quote($this->getLanguage(), "text"));
2501  $last_nr_set = $ilDB->query("SELECT max(nr) as mnr FROM page_history WHERE ".
2502  "page_id = ".$ilDB->quote($this->getId(), "integer")." AND ".
2503  "parent_type = ".$ilDB->quote($this->getParentType(), "text")." AND ".
2504  "lang = ".$ilDB->quote($this->getLanguage(), "text"));
2505  $last_nr = $ilDB->fetchAssoc($last_nr_set);
2506  if ($old_rec = $ilDB->fetchAssoc($old_set))
2507  {
2508  // only save, if something has changed
2509  // added user id to the check for ilias 5.0, 7.10.2014
2510  if (($content != $old_rec["content"] || $ilUser->getId() != $old_rec["last_change_user"]) &&
2511  !$a_no_history && !$this->history_saved && $lm_set->get("page_history", 1))
2512  {
2513  if ($old_rec["content"] != "<PageObject></PageObject>")
2514  {
2515  $ilDB->manipulateF("DELETE FROM page_history WHERE ".
2516  "page_id = %s AND parent_type = %s AND hdate = %s AND lang = %s",
2517  array("integer", "text", "timestamp", "text"),
2518  array($old_rec["page_id"], $old_rec["parent_type"], $old_rec["last_change"], $old_rec["lang"]));
2519 
2520  // the following lines are a workaround for
2521  // bug 6741
2522  $last_c = $old_rec["last_change"];
2523  if ($last_c == "")
2524  {
2525  $last_c = ilUtil::now();
2526  }
2527 
2528  $ilDB->insert("page_history", array(
2529  "page_id" => array("integer", $old_rec["page_id"]),
2530  "parent_type" => array("text", $old_rec["parent_type"]),
2531  "lang" => array("text", $old_rec["lang"]),
2532  "hdate" => array("timestamp", $last_c),
2533  "parent_id" => array("integer", $old_rec["parent_id"]),
2534  "content" => array("clob", $old_rec["content"]),
2535  "user_id" => array("integer", $old_rec["last_change_user"]),
2536  "ilias_version" => array("text", ILIAS_VERSION_NUMERIC),
2537  "nr" => array("integer", (int) $last_nr["mnr"] + 1)
2538  ));
2539 
2540  $old_content = $old_rec["content"];
2541  $old_domdoc = new DOMDocument();
2542  $old_nr = $last_nr["mnr"] + 1;
2543  $old_domdoc->loadXML('<?xml version="1.0" encoding="UTF-8"?>'.$old_content);
2544 
2545  // after history entry creation event
2546  $this->__afterHistoryEntry($old_domdoc, $old_content, $old_nr);
2547 
2548  $this->history_saved = true; // only save one time
2549  }
2550  else
2551  {
2552  $this->history_saved = true; // do not save on first change
2553  }
2554  }
2555  }
2556 //echo htmlentities($content);
2557  $em = (trim($content) == "<PageObject/>")
2558  ? 1
2559  : 0;
2560 
2561  // @todo: pass dom instead?
2562  $iel = $this->containsDeactivatedElements($content);
2563  $inl = $this->containsIntLinks($content);
2564 
2565  $ilDB->update("page_object", array(
2566  "content" => array("clob", $content),
2567  "parent_id" => array("integer", $this->getParentId()),
2568  "last_change_user" => array("integer", $ilUser->getId()),
2569  "last_change" => array("timestamp", ilUtil::now()),
2570  "is_empty" => array("integer", $em),
2571  "active" => array("integer", $this->getActive()),
2572  "activation_start" => array("timestamp", $this->getActivationStart()),
2573  "activation_end" => array("timestamp", $this->getActivationEnd()),
2574  "show_activation_info" => array("integer", $this->getShowActivationInfo()),
2575  "inactive_elements" => array("integer", $iel),
2576  "int_links" => array("integer", $inl),
2577  ), array(
2578  "page_id" => array("integer", $this->getId()),
2579  "parent_type" => array("text", $this->getParentType()),
2580  "lang" => array("text", $this->getLanguage())
2581  ));
2582 
2583  // after update event
2584  $this->__afterUpdate($dom_doc, $content);
2585 
2586 //echo "<br>PageObject::update:".htmlentities($this->getXMLContent()).":";
2587  return true;
2588  }
2589  else
2590  {
2591  return $errors;
2592  }
2593  }
2594 
2595 
2596 
2600  function delete()
2601  {
2602  global $ilDB;
2603 
2604  $mobs = array();
2605  $files = array();
2606 
2607  if (!$this->page_not_found)
2608  {
2609  $this->buildDom();
2610  $mobs = $this->collectMediaObjects(false);
2611  }
2612  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2613  $mobs2 = ilObjMediaObject::_getMobsOfObject($this->getParentType().":pg", $this->getId(), false);
2614  foreach ($mobs2 as $m)
2615  {
2616  if (!in_array($m, $mobs))
2617  {
2618  $mobs[] = $m;
2619  }
2620  }
2621 
2622  $this->__beforeDelete();
2623 
2624  // delete style usages
2625  $this->deleteStyleUsages(false);
2626 
2627  // delete internal links
2628  $this->deleteInternalLinks();
2629 
2630  // delete all mob usages
2631  ilObjMediaObject::_deleteAllUsages($this->getParentType().":pg", $this->getId());
2632 
2633  // delete news
2634  include_once("./Services/News/classes/class.ilNewsItem.php");
2636  $this->getParentType(), $this->getId(), "pg");
2637 
2638  // delete page_object entry
2639  $ilDB->manipulate("DELETE FROM page_object ".
2640  "WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
2641  " AND parent_type= ".$ilDB->quote($this->getParentType(), "text"));
2642  //$this->ilias->db->query($query);
2643 
2644  // delete media objects
2645  foreach ($mobs as $mob_id)
2646  {
2647  if(ilObject::_lookupType($mob_id) != 'mob')
2648  {
2649  $GLOBALS['ilLog']->write(__METHOD__.': Type mismatch. Ignoring mob with id: '.$mob_id);
2650  continue;
2651  }
2652 
2653  if (ilObject::_exists($mob_id))
2654  {
2655  $mob_obj =& new ilObjMediaObject($mob_id);
2656  $mob_obj->delete();
2657  }
2658  }
2659 
2660 
2661  /* delete public and private notes (see PageObjectGUI->getNotesHTML())
2662  as they can be seen as personal data we are keeping them for now
2663  include_once("Services/Notes/classes/class.ilNote.php");
2664  foreach(array(IL_NOTE_PRIVATE, IL_NOTE_PUBLIC) as $note_type)
2665  {
2666  foreach(ilNote::_getNotesOfObject($this->getParentId(), $this->getId(),
2667  $this->getParentType(), $note_type) as $note)
2668  {
2669  $note->delete();
2670  }
2671  }
2672  */
2673  }
2674 
2680  protected final function __beforeDelete()
2681  {
2682  // pc classes hook
2683  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2685  foreach ($defs as $def)
2686  {
2688  $cl = $def["pc_class"];
2689  call_user_func($def["pc_class"].'::beforePageDelete', $this);
2690  }
2691  }
2692 
2698  protected final function __afterHistoryEntry($a_old_domdoc, $a_old_content, $a_old_nr)
2699  {
2700  // save style usage
2701  $this->saveStyleUsage($a_old_domdoc, $a_old_nr);
2702 
2703  // pc classes hook
2704  include_once("./Services/COPage/classes/class.ilCOPagePCDef.php");
2706  foreach ($defs as $def)
2707  {
2709  $cl = $def["pc_class"];
2710  call_user_func($def["pc_class"].'::afterPageHistoryEntry', $this, $a_old_domdoc, $a_old_content, $a_old_nr);
2711  }
2712  }
2713 
2719  function saveStyleUsage($a_domdoc, $a_old_nr = 0)
2720  {
2721  global $ilDB;
2722 
2723  // media aliases
2724  $xpath = new DOMXPath($a_domdoc);
2725  $path = "//Paragraph | //Section | //MediaAlias | //FileItem".
2726  " | //Table | //TableData | //Tabs | //List";
2727  $nodes = $xpath->query($path);
2728  $usages = array();
2729  foreach($nodes as $node)
2730  {
2731  switch ($node->localName)
2732  {
2733  case "Paragraph":
2734  $sname = $node->getAttribute("Characteristic");
2735  $stype = "text_block";
2736  $template = 0;
2737  break;
2738 
2739  case "Section":
2740  $sname = $node->getAttribute("Characteristic");
2741  $stype = "section";
2742  $template = 0;
2743  break;
2744 
2745  case "MediaAlias":
2746  $sname = $node->getAttribute("Class");
2747  $stype = "media_cont";
2748  $template = 0;
2749  break;
2750 
2751  case "FileItem":
2752  $sname = $node->getAttribute("Class");
2753  $stype = "flist_li";
2754  $template = 0;
2755  break;
2756 
2757  case "Table":
2758  $sname = $node->getAttribute("Template");
2759  if ($sname == "")
2760  {
2761  $sname = $node->getAttribute("Class");
2762  $stype = "table";
2763  $template = 0;
2764  }
2765  else
2766  {
2767  $stype = "table";
2768  $template = 1;
2769  }
2770  break;
2771 
2772  case "TableData":
2773  $sname = $node->getAttribute("Class");
2774  $stype = "table_cell";
2775  $template = 0;
2776  break;
2777 
2778  case "Tabs":
2779  $sname = $node->getAttribute("Template");
2780  if ($sname != "")
2781  {
2782  if ($node->getAttribute("Type") == "HorizontalAccordion")
2783  {
2784  $stype = "haccordion";
2785  }
2786  if ($node->getAttribute("Type") == "VerticalAccordion")
2787  {
2788  $stype = "vaccordion";
2789  }
2790  }
2791  $template = 1;
2792  break;
2793 
2794  case "List":
2795  $sname = $node->getAttribute("Class");
2796  if ($node->getAttribute("Type") == "Ordered")
2797  {
2798  $stype = "list_o";
2799  }
2800  else
2801  {
2802  $stype = "list_u";
2803  }
2804  $template = 0;
2805  break;
2806  }
2807  if ($sname != "" && $stype != "")
2808  {
2809  $usages[$sname.":".$stype.":".$template] = array("sname" => $sname,
2810  "stype" => $stype, "template" => $template);
2811  }
2812  }
2813 
2814 
2815  $this->deleteStyleUsages($a_old_nr);
2816 
2817  foreach ($usages as $u)
2818  {
2819  $ilDB->manipulate("INSERT INTO page_style_usage ".
2820  "(page_id, page_type, page_lang, page_nr, template, stype, sname) VALUES (".
2821  $ilDB->quote($this->getId(), "integer").",".
2822  $ilDB->quote($this->getParentType(), "text").",".
2823  $ilDB->quote($this->getLanguage(), "text").",".
2824  $ilDB->quote($a_old_nr, "integer").",".
2825  $ilDB->quote($u["template"], "integer").",".
2826  $ilDB->quote($u["stype"], "text").",".
2827  $ilDB->quote($u["sname"], "text").
2828  ")");
2829  }
2830  }
2831 
2838  function deleteStyleUsages($a_old_nr = 0)
2839  {
2840  global $ilDB;
2841 
2842  if ($a_old_nr !== false)
2843  {
2844  $and_old_nr = " AND page_nr = ".$ilDB->quote($a_old_nr, "integer");
2845  }
2846 
2847  $ilDB->manipulate("DELETE FROM page_style_usage WHERE ".
2848  " page_id = ".$ilDB->quote($this->getId(), "integer").
2849  " AND page_type = ".$ilDB->quote($this->getParentType(), "text").
2850  " AND page_lang = ".$ilDB->quote($this->getLanguage(), "text").
2851  $and_old_nr
2852  );
2853  }
2854 
2855 
2860  // @todo: move to content include class
2862  {
2863  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2864  include_once("./Modules/File/classes/class.ilObjFile.php");
2866  $this->getId());
2867  $files = ilObjFile::_getFilesOfObject($this->getParentType().":pg",
2868  $this->getId());
2869  $objs = array_merge($mobs, $files);
2870  return ilObject::_getLastUpdateOfObjects($objs);
2871  }
2872 
2880  {
2881  include_once("./Services/Link/classes/class.ilInternalLink.php");
2883  $this->getLanguage());
2884  }
2885 
2886 
2892  // @todo: move to specific classes, internal link use info
2893  function saveInternalLinks($a_domdoc)
2894  {
2895  global $ilDB;
2896 
2897  $this->deleteInternalLinks();
2898 
2899  // query IntLink elements
2900  $xpath = new DOMXPath($a_domdoc);
2901  $nodes = $xpath->query('//IntLink');
2902  foreach($nodes as $node)
2903  {
2904  $link_type = $node->getAttribute("Type");
2905 
2906  switch ($link_type)
2907  {
2908  case "StructureObject":
2909  $t_type = "st";
2910  break;
2911 
2912  case "PageObject":
2913  $t_type = "pg";
2914  break;
2915 
2916  case "GlossaryItem":
2917  $t_type = "git";
2918  break;
2919 
2920  case "MediaObject":
2921  $t_type = "mob";
2922  break;
2923 
2924  case "RepositoryItem":
2925  $t_type = "obj";
2926  break;
2927 
2928  case "File":
2929  $t_type = "file";
2930  break;
2931 
2932  case "WikiPage":
2933  $t_type = "wpage";
2934  break;
2935  }
2936 
2937  $target = $node->getAttribute("Target");
2938  $target_arr = explode("_", $target);
2939  $t_id = $target_arr[count($target_arr) - 1];
2940 
2941  // link to other internal object
2942  if (is_int(strpos($target, "__")))
2943  {
2944  $t_inst = 0;
2945  }
2946  else // link to unresolved object in other installation
2947  {
2948  $t_inst = $target_arr[1];
2949  }
2950 
2951  if ($t_id > 0)
2952  {
2953  ilInternalLink::_saveLink($this->getParentType().":pg", $this->getId(), $t_type,
2954  $t_id, $t_inst, $this->getLanguage());
2955  }
2956  }
2957  }
2958 
2962  function create()
2963  {
2964  $this->createFromXML();
2965  }
2966 
2974  function deleteContent($a_hid, $a_update = true, $a_pcid = "")
2975  {
2976  $curr_node =& $this->getContentNode($a_hid, $a_pcid);
2977  $curr_node->unlink_node($curr_node);
2978  if ($a_update)
2979  {
2980  return $this->update();
2981  }
2982  }
2983 
2984 
2992  function deleteContents($a_hids, $a_update = true, $a_self_ass = false)
2993  {
2994  if (!is_array($a_hids))
2995  {
2996  return;
2997  }
2998  foreach($a_hids as $a_hid)
2999  {
3000  $a_hid = explode(":", $a_hid);
3001 //echo "-".$a_hid[0]."-".$a_hid[1]."-";
3002 
3003 // @todo 1: hook
3004  // do not delete question nodes in assessment pages
3005  if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass)
3006  {
3007  $curr_node =& $this->getContentNode($a_hid[0], $a_hid[1]);
3008  if (is_object($curr_node))
3009  {
3010  $parent_node = $curr_node->parent_node();
3011  if ($parent_node->node_name() != "TableRow")
3012  {
3013  $curr_node->unlink_node($curr_node);
3014  }
3015  }
3016  }
3017  }
3018  if ($a_update)
3019  {
3020  return $this->update();
3021  }
3022  }
3023 
3029  function cutContents($a_hids)
3030  {
3031  $this->copyContents($a_hids);
3032  return $this->deleteContents($a_hids, true, $this->getPageConfig()->getEnableSelfAssessment());
3033  }
3034 
3040  function copyContents($a_hids)
3041  {
3042  global $ilUser;
3043 //var_dump($a_hids);
3044  if (!is_array($a_hids))
3045  {
3046  return;
3047  }
3048 
3049  $time = date("Y-m-d H:i:s", time());
3050 
3051  $hier_ids = array();
3052  $skip = array();
3053  foreach($a_hids as $a_hid)
3054  {
3055  if ($a_hid == "")
3056  {
3057  continue;
3058  }
3059  $a_hid = explode(":", $a_hid);
3060 
3061  // check, whether new hid is child of existing one or vice versa
3062  reset($hier_ids);
3063  foreach($hier_ids as $h)
3064  {
3065  if($h."_" == substr($a_hid[0], 0, strlen($h) + 1))
3066  {
3067  $skip[] = $a_hid[0];
3068  }
3069  if($a_hid[0]."_" == substr($h, 0, strlen($a_hid[0]) + 1))
3070  {
3071  $skip[] = $h;
3072  }
3073  }
3074  $pc_id[$a_hid[0]] = $a_hid[1];
3075  if ($a_hid[0] != "")
3076  {
3077  $hier_ids[$a_hid[0]] = $a_hid[0];
3078  }
3079  }
3080  foreach ($skip as $s)
3081  {
3082  unset($hier_ids[$s]);
3083  }
3084  include_once("./Services/COPage/classes/class.ilPageContent.php");
3085  $hier_ids = ilPageContent::sortHierIds($hier_ids);
3086  $nr = 1;
3087  foreach($hier_ids as $hid)
3088  {
3089  $curr_node = $this->getContentNode($hid, $pc_id[$hid]);
3090  if (is_object($curr_node))
3091  {
3092  if ($curr_node->node_name() == "PageContent")
3093  {
3094  $content = $this->dom->dump_node($curr_node);
3095  // remove pc and hier ids
3096  $content = eregi_replace("PCID=\"[a-z0-9]*\"","",$content);
3097  $content = eregi_replace("HierId=\"[a-z0-9_]*\"","",$content);
3098 
3099  $ilUser->addToPCClipboard($content, $time, $nr);
3100  $nr++;
3101  }
3102  }
3103  }
3104  include_once("./Modules/LearningModule/classes/class.ilEditClipboard.php");
3106  }
3107 
3111  function pasteContents($a_hier_id, $a_self_ass = false)
3112  {
3113  global $ilUser;
3114 
3115  $a_hid = explode(":", $a_hier_id);
3116  $content = $ilUser->getPCClipboardContent();
3117 
3118  // we insert from last to first, because we insert all at the
3119  // same hier_id
3120  for ($i = count($content) - 1; $i >= 0; $i--)
3121  {
3122 
3123  $c = $content[$i];
3124  $temp_dom = domxml_open_mem('<?xml version="1.0" encoding="UTF-8"?>'.$c,
3125  DOMXML_LOAD_PARSING, $error);
3126  if(empty($error))
3127  {
3128  $this->handleCopiedContent($temp_dom, $a_self_ass);
3129  $xpc = xpath_new_context($temp_dom);
3130  $path = "//PageContent";
3131  $res = xpath_eval($xpc, $path);
3132  if (count($res->nodeset) > 0)
3133  {
3134  $new_pc_node = $res->nodeset[0];
3135  $cloned_pc_node = $new_pc_node->clone_node (true);
3136  $cloned_pc_node->unlink_node ($cloned_pc_node);
3137  $this->insertContentNode ($cloned_pc_node, $a_hid[0],
3138  IL_INSERT_AFTER, $a_hid[1]);
3139  }
3140  }
3141  else
3142  {
3143 //var_dump($error);
3144  }
3145  }
3146  $e = $this->update();
3147 //var_dump($e);
3148  }
3149 
3153  function switchEnableMultiple($a_hids, $a_update = true, $a_self_ass = false)
3154  {
3155  if (!is_array($a_hids))
3156  {
3157  return;
3158  }
3159  $obj = & $this->content_obj;
3160 
3161  foreach($a_hids as $a_hid)
3162  {
3163  $a_hid = explode(":", $a_hid);
3164  $curr_node =& $this->getContentNode($a_hid[0], $a_hid[1]);
3165  if (is_object($curr_node))
3166  {
3167  if ($curr_node->node_name() == "PageContent")
3168  {
3169  $cont_obj =& $this->getContentObject($a_hid[0], $a_hid[1]);
3170  if ($cont_obj->isEnabled ())
3171  {
3172  // do not deactivate question nodes in assessment pages
3173  if (!$this->checkForTag("Question", $a_hid[0], $a_hid[1]) || $a_self_ass)
3174  {
3175  $cont_obj->disable();
3176  }
3177  }
3178  else
3179  {
3180  $cont_obj->enable();
3181  }
3182  }
3183  }
3184  }
3185 
3186  if ($a_update)
3187  {
3188  return $this->update();
3189  }
3190  }
3191 
3192 
3200  function deleteContentFromHierId($a_hid, $a_update = true)
3201  {
3202  $hier_ids = $this->getHierIds();
3203 
3204  // iterate all hierarchical ids
3205  foreach ($hier_ids as $hier_id)
3206  {
3207  // delete top level nodes only
3208  if (!is_int(strpos($hier_id, "_")))
3209  {
3210  if ($hier_id != "pg" && $hier_id >= $a_hid)
3211  {
3212  $curr_node =& $this->getContentNode($hier_id);
3213  $curr_node->unlink_node($curr_node);
3214  }
3215  }
3216  }
3217  if ($a_update)
3218  {
3219  return $this->update();
3220  }
3221  }
3222 
3230  function deleteContentBeforeHierId($a_hid, $a_update = true)
3231  {
3232  $hier_ids = $this->getHierIds();
3233 
3234  // iterate all hierarchical ids
3235  foreach ($hier_ids as $hier_id)
3236  {
3237  // delete top level nodes only
3238  if (!is_int(strpos($hier_id, "_")))
3239  {
3240  if ($hier_id != "pg" && $hier_id < $a_hid)
3241  {
3242  $curr_node =& $this->getContentNode($hier_id);
3243  $curr_node->unlink_node($curr_node);
3244  }
3245  }
3246  }
3247  if ($a_update)
3248  {
3249  return $this->update();
3250  }
3251  }
3252 
3253 
3261  function _moveContentAfterHierId(&$a_source_page, &$a_target_page, $a_hid)
3262  {
3263  $hier_ids = $a_source_page->getHierIds();
3264 
3265  $copy_ids = array();
3266 
3267  // iterate all hierarchical ids
3268  foreach ($hier_ids as $hier_id)
3269  {
3270  // move top level nodes only
3271  if (!is_int(strpos($hier_id, "_")))
3272  {
3273  if ($hier_id != "pg" && $hier_id >= $a_hid)
3274  {
3275  $copy_ids[] = $hier_id;
3276  }
3277  }
3278  }
3279  asort($copy_ids);
3280 
3281  $parent_node =& $a_target_page->getContentNode("pg");
3282  $target_dom =& $a_target_page->getDom();
3283  $parent_childs =& $parent_node->child_nodes();
3284  $cnt_parent_childs = count($parent_childs);
3285 //echo "-$cnt_parent_childs-";
3286  $first_child =& $parent_childs[0];
3287  foreach($copy_ids as $copy_id)
3288  {
3289  $source_node =& $a_source_page->getContentNode($copy_id);
3290 
3291  $new_node =& $source_node->clone_node(true);
3292  $new_node->unlink_node($new_node);
3293 
3294  $source_node->unlink_node($source_node);
3295 
3296  if($cnt_parent_childs == 0)
3297  {
3298  $new_node =& $parent_node->append_child($new_node);
3299  }
3300  else
3301  {
3302  //$target_dom->import_node($new_node);
3303  $new_node =& $first_child->insert_before($new_node, $first_child);
3304  }
3305  $parent_childs =& $parent_node->child_nodes();
3306 
3307  //$cnt_parent_childs++;
3308  }
3309 
3310  $a_target_page->update();
3311  $a_source_page->update();
3312 
3313  }
3314 
3318  function insertContent(&$a_cont_obj, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "")
3319  {
3320 //echo "-".$a_pos."-".$a_pcid."-";
3321  // move mode into container elements is always INSERT_CHILD
3322  $curr_node = $this->getContentNode($a_pos, $a_pcid);
3323  $curr_name = $curr_node->node_name();
3324 
3325  // @todo: try to generalize this
3326  if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3327  ($curr_name == "ListItem") || ($curr_name == "Section")
3328  || ($curr_name == "Tab") || ($curr_name == "ContentPopup"))
3329  {
3330  $a_mode = IL_INSERT_CHILD;
3331  }
3332 
3333  $hid = $curr_node->get_attribute("HierId");
3334  if ($hid != "")
3335  {
3336 //echo "-".$a_pos."-".$hid."-";
3337  $a_pos = $hid;
3338  }
3339 
3340  if($a_mode != IL_INSERT_CHILD) // determine parent hierarchical id
3341  { // of sibling at $a_pos
3342  $pos = explode("_", $a_pos);
3343  $target_pos = array_pop($pos);
3344  $parent_pos = implode($pos, "_");
3345  }
3346  else // if we should insert a child, $a_pos is alreade the hierarchical id
3347  { // of the parent node
3348  $parent_pos = $a_pos;
3349  }
3350 
3351  // get the parent node
3352  if($parent_pos != "")
3353  {
3354  $parent_node =& $this->getContentNode($parent_pos);
3355  }
3356  else
3357  {
3358  $parent_node =& $this->getNode();
3359  }
3360 
3361  // count the parent children
3362  $parent_childs =& $parent_node->child_nodes();
3363  $cnt_parent_childs = count($parent_childs);
3364 //echo "ZZ$a_mode";
3365  switch ($a_mode)
3366  {
3367  // insert new node after sibling at $a_pos
3368  case IL_INSERT_AFTER:
3369  $new_node =& $a_cont_obj->getNode();
3370  //$a_pos = ilPageContent::incEdId($a_pos);
3371  //$curr_node =& $this->getContentNode($a_pos);
3372 //echo "behind $a_pos:";
3373  if($succ_node =& $curr_node->next_sibling())
3374  {
3375  $new_node =& $succ_node->insert_before($new_node, $succ_node);
3376  }
3377  else
3378  {
3379 //echo "movin doin append_child";
3380  $new_node =& $parent_node->append_child($new_node);
3381  }
3382  $a_cont_obj->setNode($new_node);
3383  break;
3384 
3385  case IL_INSERT_BEFORE:
3386 //echo "INSERT_BEF";
3387  $new_node =& $a_cont_obj->getNode();
3388  $succ_node =& $this->getContentNode($a_pos);
3389  $new_node =& $succ_node->insert_before($new_node, $succ_node);
3390  $a_cont_obj->setNode($new_node);
3391  break;
3392 
3393  // insert new node as first child of parent $a_pos (= $a_parent)
3394  case IL_INSERT_CHILD:
3395 //echo "insert as child:parent_childs:$cnt_parent_childs:<br>";
3396  $new_node =& $a_cont_obj->getNode();
3397  if($cnt_parent_childs == 0)
3398  {
3399  $new_node =& $parent_node->append_child($new_node);
3400  }
3401  else
3402  {
3403  $new_node =& $parent_childs[0]->insert_before($new_node, $parent_childs[0]);
3404  }
3405  $a_cont_obj->setNode($new_node);
3406 //echo "PP";
3407  break;
3408  }
3409 
3410  //check for PlaceHolder to remove in EditMode-keep in Layout Mode
3411  if (!$this->getPageConfig()->getEnablePCType("PlaceHolder")) {
3412  $sub_nodes = $curr_node->child_nodes() ;
3413  foreach ( $sub_nodes as $sub_node ) {
3414  if ($sub_node->node_name() == "PlaceHolder") {
3415  $curr_node->unlink_node();
3416  }
3417  }
3418  }
3419  }
3420 
3424  function insertContentNode(&$a_cont_node, $a_pos, $a_mode = IL_INSERT_AFTER, $a_pcid = "")
3425  {
3426  // move mode into container elements is always INSERT_CHILD
3427  $curr_node = $this->getContentNode($a_pos, $a_pcid);
3428  $curr_name = $curr_node->node_name();
3429 
3430  // @todo: try to generalize
3431  if (($curr_name == "TableData") || ($curr_name == "PageObject") ||
3432  ($curr_name == "ListItem") || ($curr_name == "Section")
3433  || ($curr_name == "Tab") || ($curr_name == "ContentPopup"))
3434  {
3435  $a_mode = IL_INSERT_CHILD;
3436  }
3437 
3438  $hid = $curr_node->get_attribute("HierId");
3439  if ($hid != "")
3440  {
3441  $a_pos = $hid;
3442  }
3443 
3444  if($a_mode != IL_INSERT_CHILD) // determine parent hierarchical id
3445  { // of sibling at $a_pos
3446  $pos = explode("_", $a_pos);
3447  $target_pos = array_pop($pos);
3448  $parent_pos = implode($pos, "_");
3449  }
3450  else // if we should insert a child, $a_pos is alreade the hierarchical id
3451  { // of the parent node
3452  $parent_pos = $a_pos;
3453  }
3454 
3455  // get the parent node
3456  if($parent_pos != "")
3457  {
3458  $parent_node =& $this->getContentNode($parent_pos);
3459  }
3460  else
3461  {
3462  $parent_node =& $this->getNode();
3463  }
3464 
3465  // count the parent children
3466  $parent_childs =& $parent_node->child_nodes();
3467  $cnt_parent_childs = count($parent_childs);
3468 
3469  switch ($a_mode)
3470  {
3471  // insert new node after sibling at $a_pos
3472  case IL_INSERT_AFTER:
3473  //$new_node =& $a_cont_obj->getNode();
3474  if($succ_node = $curr_node->next_sibling())
3475  {
3476  $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3477  }
3478  else
3479  {
3480  $a_cont_node = $parent_node->append_child($a_cont_node);
3481  }
3482  //$a_cont_obj->setNode($new_node);
3483  break;
3484 
3485  case IL_INSERT_BEFORE:
3486  //$new_node =& $a_cont_obj->getNode();
3487  $succ_node = $this->getContentNode($a_pos);
3488  $a_cont_node = $succ_node->insert_before($a_cont_node, $succ_node);
3489  //$a_cont_obj->setNode($new_node);
3490  break;
3491 
3492  // insert new node as first child of parent $a_pos (= $a_parent)
3493  case IL_INSERT_CHILD:
3494  //$new_node =& $a_cont_obj->getNode();
3495  if($cnt_parent_childs == 0)
3496  {
3497  $a_cont_node = $parent_node->append_child($a_cont_node);
3498  }
3499  else
3500  {
3501  $a_cont_node = $parent_childs[0]->insert_before($a_cont_node, $parent_childs[0]);
3502  }
3503  //$a_cont_obj->setNode($new_node);
3504  break;
3505  }
3506  }
3507 
3512  function moveContentBefore($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3513  {
3514  if($a_source == $a_target)
3515  {
3516  return;
3517  }
3518 
3519  // clone the node
3520  $content =& $this->getContentObject($a_source, $a_spcid);
3521  $source_node =& $content->getNode();
3522  $clone_node =& $source_node->clone_node(true);
3523 
3524  // delete source node
3525  $this->deleteContent($a_source, false, $a_spcid);
3526 
3527  // insert cloned node at target
3528  $content->setNode($clone_node);
3529  $this->insertContent($content, $a_target, IL_INSERT_BEFORE, $a_tpcid);
3530  return $this->update();
3531 
3532  }
3533 
3538  function moveContentAfter($a_source, $a_target, $a_spcid = "", $a_tpcid = "")
3539  {
3540  if($a_source == $a_target)
3541  {
3542  return;
3543  }
3544 
3545  // clone the node
3546  $content =& $this->getContentObject($a_source, $a_spcid);
3547  $source_node =& $content->getNode();
3548  $clone_node =& $source_node->clone_node(true);
3549 
3550  // delete source node
3551  $this->deleteContent($a_source, false, $a_spcid);
3552 
3553  // insert cloned node at target
3554  $content->setNode($clone_node);
3555  $this->insertContent($content, $a_target, IL_INSERT_AFTER, $a_tpcid);
3556  return $this->update();
3557  }
3558 
3562  // @todo: move to paragraph
3563  function bbCode2XML(&$a_content)
3564  {
3565  $a_content = eregi_replace("\[com\]","<Comment>",$a_content);
3566  $a_content = eregi_replace("\[\/com\]","</Comment>",$a_content);
3567  $a_content = eregi_replace("\[emp]","<Emph>",$a_content);
3568  $a_content = eregi_replace("\[\/emp\]","</Emph>",$a_content);
3569  $a_content = eregi_replace("\[str]","<Strong>",$a_content);
3570  $a_content = eregi_replace("\[\/str\]","</Strong>",$a_content);
3571  }
3572 
3577  function insertInstIntoIDs($a_inst, $a_res_ref_to_obj_id = true)
3578  {
3579  // insert inst id into internal links
3580  $xpc = xpath_new_context($this->dom);
3581  $path = "//IntLink";
3582  $res =& xpath_eval($xpc, $path);
3583  for($i = 0; $i < count($res->nodeset); $i++)
3584  {
3585  $target = $res->nodeset[$i]->get_attribute("Target");
3586  $type = $res->nodeset[$i]->get_attribute("Type");
3587 
3588  if (substr($target, 0, 4) == "il__")
3589  {
3590  $id = substr($target, 4, strlen($target) - 4);
3591 
3592  // convert repository links obj_<ref_id> to <type>_<obj_id>
3593  // this leads to bug 6685.
3594  if ($a_res_ref_to_obj_id && $type == "RepositoryItem")
3595  {
3596  $id_arr = explode("_", $id);
3597 
3598  // changed due to bug 6685
3599  $ref_id = $id_arr[1];
3600  $obj_id = ilObject::_lookupObjId($id_arr[1]);
3601 
3602  $otype = ilObject::_lookupType($obj_id);
3603  if ($obj_id > 0)
3604  {
3605  // changed due to bug 6685
3606  // the ref_id should be used, if the content is
3607  // imported on the same installation
3608  // the obj_id should be used, if a different
3609  // installation imports, but has an import_id for
3610  // the object id.
3611  $id = $otype."_".$obj_id."_".$ref_id;
3612  //$id = $otype."_".$ref_id;
3613  }
3614  }
3615  $new_target = "il_".$a_inst."_".$id;
3616  $res->nodeset[$i]->set_attribute("Target", $new_target);
3617  }
3618  }
3619  unset($xpc);
3620 
3621  // @todo: move to media/fileitems/questions, ...
3622 
3623  // insert inst id into media aliases
3624  $xpc = xpath_new_context($this->dom);
3625  $path = "//MediaAlias";
3626  $res =& xpath_eval($xpc, $path);
3627  for($i = 0; $i < count($res->nodeset); $i++)
3628  {
3629  $origin_id = $res->nodeset[$i]->get_attribute("OriginId");
3630  if (substr($origin_id, 0, 4) == "il__")
3631  {
3632  $new_id = "il_".$a_inst."_".substr($origin_id, 4, strlen($origin_id) - 4);
3633  $res->nodeset[$i]->set_attribute("OriginId", $new_id);
3634  }
3635  }
3636  unset($xpc);
3637 
3638  // insert inst id file item identifier entries
3639  $xpc = xpath_new_context($this->dom);
3640  $path = "//FileItem/Identifier";
3641  $res =& xpath_eval($xpc, $path);
3642  for($i = 0; $i < count($res->nodeset); $i++)
3643  {
3644  $origin_id = $res->nodeset[$i]->get_attribute("Entry");
3645  if (substr($origin_id, 0, 4) == "il__")
3646  {
3647  $new_id = "il_".$a_inst."_".substr($origin_id, 4, strlen($origin_id) - 4);
3648  $res->nodeset[$i]->set_attribute("Entry", $new_id);
3649  }
3650  }
3651  unset($xpc);
3652 
3653  // insert inst id into question references
3654  $xpc = xpath_new_context($this->dom);
3655  $path = "//Question";
3656  $res =& xpath_eval($xpc, $path);
3657  for($i = 0; $i < count($res->nodeset); $i++)
3658  {
3659  $qref = $res->nodeset[$i]->get_attribute("QRef");
3660 //echo "<br>setted:".$qref;
3661  if (substr($qref, 0, 4) == "il__")
3662  {
3663  $new_id = "il_".$a_inst."_".substr($qref, 4, strlen($qref) - 4);
3664 //echo "<br>setting:".$new_id;
3665  $res->nodeset[$i]->set_attribute("QRef", $new_id);
3666  }
3667  }
3668  unset($xpc);
3669 
3670  }
3671 
3675  function checkPCIds()
3676  {
3677  $this->builddom();
3678  $mydom = $this->dom;
3679 
3680  $sep = $path = "";
3681  foreach ($this->id_elements as $el)
3682  {
3683  $path.= $sep."//".$el."[not(@PCID)]";
3684  $sep = " | ";
3685  $path.= $sep."//".$el."[@PCID='']";
3686  }
3687 
3688  $xpc = xpath_new_context($mydom);
3689  $res = & xpath_eval($xpc, $path);
3690 
3691  if (count ($res->nodeset) > 0)
3692  {
3693  return false;
3694  }
3695  return true;
3696  }
3697 
3704  function getAllPCIds()
3705  {
3706  $this->builddom();
3707  $mydom = $this->dom;
3708 
3709  $pcids = array();
3710 
3711  $sep = $path = "";
3712  foreach ($this->id_elements as $el)
3713  {
3714  $path.= $sep."//".$el."[@PCID]";
3715  $sep = " | ";
3716  }
3717 
3718  // get existing ids
3719  $xpc = xpath_new_context($mydom);
3720  $res = & xpath_eval($xpc, $path);
3721 
3722  for ($i = 0; $i < count ($res->nodeset); $i++)
3723  {
3724  $node = $res->nodeset[$i];
3725  $pcids[] = $node->get_attribute("PCID");
3726  }
3727  return $pcids;
3728  }
3729 
3736  function existsPCId($a_pc_id)
3737  {
3738  $this->builddom();
3739  $mydom = $this->dom;
3740 
3741  $pcids = array();
3742 
3743  $sep = $path = "";
3744  foreach ($this->id_elements as $el)
3745  {
3746  $path.= $sep."//".$el."[@PCID='".$a_pc_id."']";
3747  $sep = " | ";
3748  }
3749 
3750  // get existing ids
3751  $xpc = xpath_new_context($mydom);
3752  $res = & xpath_eval($xpc, $path);
3753  return (count($res->nodeset) > 0);
3754  }
3755 
3762  function generatePcId($a_pc_ids = false)
3763  {
3764  if ($a_pc_ids === false)
3765  {
3766  $a_pc_ids = $this->getAllPCIds();
3767  }
3768  $id = ilUtil::randomHash(10, $a_pc_ids);
3769  return $id;
3770  }
3771 
3772 
3776  function insertPCIds()
3777  {
3778  $this->builddom();
3779  $mydom = $this->dom;
3780 
3781  $pcids = $this->getAllPCIds();
3782 
3783  // add missing ones
3784  $sep = $path = "";
3785  foreach ($this->id_elements as $el)
3786  {
3787  $path.= $sep."//".$el."[not(@PCID)]";
3788  $sep = " | ";
3789  $path.= $sep."//".$el."[@PCID='']";
3790  $sep = " | ";
3791  }
3792  $xpc = xpath_new_context($mydom);
3793  $res = & xpath_eval($xpc, $path);
3794 
3795  for ($i = 0; $i < count ($res->nodeset); $i++)
3796  {
3797  $node = $res->nodeset[$i];
3798  $id = ilUtil::randomHash(10, $pcids);
3799  $pcids[] = $id;
3800 //echo "setting-".$id."-";
3801  $res->nodeset[$i]->set_attribute("PCID", $id);
3802  }
3803  }
3804 
3809  {
3810  $this->builddom();
3811  $this->addHierIds();
3812  $mydom = $this->dom;
3813 
3814  // get existing ids
3815  $path = "//PageContent";
3816  $xpc = xpath_new_context($mydom);
3817  $res = & xpath_eval($xpc, $path);
3818 
3819  $hashes = array();
3820  require_once("./Services/COPage/classes/class.ilPCParagraph.php");
3821  for ($i = 0; $i < count ($res->nodeset); $i++)
3822  {
3823  $hier_id = $res->nodeset[$i]->get_attribute("HierId");
3824  $pc_id = $res->nodeset[$i]->get_attribute("PCID");
3825  $dump = $mydom->dump_node($res->nodeset[$i]);
3826  if (($hpos = strpos($dump, ' HierId="'.$hier_id.'"')) > 0)
3827  {
3828  $dump = substr($dump, 0, $hpos).
3829  substr($dump, $hpos + strlen(' HierId="'.$hier_id.'"'));
3830  }
3831 
3832  $childs = $res->nodeset[$i]->child_nodes();
3833  $content = "";
3834  if ($childs[0] && $childs[0]->node_name() == "Paragraph")
3835  {
3836  $content = $mydom->dump_node($childs[0]);
3837  $content = substr($content, strpos($content, ">") + 1,
3838  strrpos($content, "<") - (strpos($content, ">") + 1));
3839 //var_dump($content);
3840  $content = ilPCParagraph::xml2output($content);
3841 //var_dump($content);
3842  }
3843  //$hashes[$hier_id] =
3844  // array("PCID" => $pc_id, "hash" => md5($dump));
3845  $hashes[$pc_id] =
3846  array("hier_id" => $hier_id, "hash" => md5($dump), "content" => $content);
3847  }
3848 
3849  return $hashes;
3850  }
3851 
3855 // @todo: move to questions
3856  function getQuestionIds()
3857  {
3858  $this->builddom();
3859  $mydom = $this->dom;
3860 
3861  // Get question IDs
3862  $path = "//Question";
3863  $xpc = xpath_new_context($mydom);
3864  $res = & xpath_eval($xpc, $path);
3865 
3866  $q_ids = array();
3867  include_once("./Services/Link/classes/class.ilInternalLink.php");
3868  for ($i = 0; $i < count ($res->nodeset); $i++)
3869  {
3870  $qref = $res->nodeset[$i]->get_attribute("QRef");
3871 
3872  $inst_id = ilInternalLink::_extractInstOfTarget($qref);
3873  $obj_id = ilInternalLink::_extractObjIdOfTarget($qref);
3874 
3875  if (!($inst_id > 0))
3876  {
3877  if ($obj_id > 0)
3878  {
3879  $q_ids[] = $obj_id;
3880  }
3881  }
3882  }
3883  return $q_ids;
3884  }
3885 
3886 // @todo: move to paragraph
3887  function send_paragraph ($par_id, $filename)
3888  {
3889  $this->builddom();
3890 
3891  $mydom = $this->dom;
3892 
3893  $xpc = xpath_new_context($mydom);
3894 
3895  //$path = "//PageContent[position () = $par_id]/Paragraph";
3896  //$path = "//Paragraph[$par_id]";
3897  $path = "/descendant::Paragraph[position() = $par_id]";
3898 
3899  $res = & xpath_eval($xpc, $path);
3900 
3901  if (count ($res->nodeset) != 1)
3902  die ("Should not happen");
3903 
3904  $context_node = $res->nodeset[0];
3905 
3906  // get plain text
3907 
3908  $childs = $context_node->child_nodes();
3909 
3910  for($j=0; $j<count($childs); $j++)
3911  {
3912  $content .= $mydom->dump_node($childs[$j]);
3913  }
3914 
3915  $content = str_replace("<br />", "\n", $content);
3916  $content = str_replace("<br/>", "\n", $content);
3917 
3918  $plain_content = html_entity_decode($content);
3919 
3920  ilUtil::deliverData($plain_content, $filename);
3921  /*
3922  $file_type = "application/octet-stream";
3923  header("Content-type: ".$file_type);
3924  header("Content-disposition: attachment; filename=\"$filename\"");
3925  echo $plain_content;*/
3926  exit();
3927  }
3928 
3932 // @todo: deprecated?
3933  function getFO()
3934  {
3935  $xml = $this->getXMLFromDom(false, true, true);
3936  $xsl = file_get_contents("./Services/COPage/xsl/page_fo.xsl");
3937  $args = array( '/_xml' => $xml, '/_xsl' => $xsl );
3938  $xh = xslt_create();
3939 
3940  $params = array ();
3941 
3942 
3943  $fo = xslt_process($xh,"arg:/_xml","arg:/_xsl",NULL,$args, $params);
3944  var_dump($fo);
3945  // do some replacements
3946  $fo = str_replace("\n", "", $fo);
3947  $fo = str_replace("<br/>", "<br>", $fo);
3948  $fo = str_replace("<br>", "\n", $fo);
3949 
3950  xslt_free($xh);
3951 
3952  //
3953  $fo = substr($fo, strpos($fo,">") + 1);
3954 //echo "<br><b>fo:</b><br>".htmlentities($fo); flush();
3955  return $fo;
3956  }
3957 
3958  function registerOfflineHandler ($handler) {
3959  $this->offline_handler = $handler;
3960  }
3961 
3969  {
3970  return $this->offline_handler;
3971  }
3972 
3973 
3977  static function _lookupContainsDeactivatedElements($a_id, $a_parent_type, $a_lang = "-")
3978  {
3979  global $ilDB;
3980 
3981  if ($a_lang == "")
3982  {
3983  $a_lang = "-";
3984  }
3985 
3986  $query = "SELECT * FROM page_object WHERE page_id = ".
3987  $ilDB->quote($a_id, "integer")." AND ".
3988  " parent_type = ".$ilDB->quote($a_parent_type, "text")." AND ".
3989  " lang = ".$ilDB->quote($a_lang, "text")." AND ".
3990  " inactive_elements = ".$ilDB->quote(1, "integer");
3991  $obj_set = $ilDB->query($query);
3992 
3993  if ($obj_rec = $obj_set->fetchRow(DB_FETCHMODE_ASSOC))
3994  {
3995  return true;
3996  }
3997 
3998  return false;
3999  }
4000 
4007  function containsDeactivatedElements($a_content)
4008  {
4009  if (strpos($a_content, " Enabled=\"False\""))
4010  {
4011  return true;
4012  }
4013  return false;
4014  }
4015 
4020  {
4021  global $ilDB;
4022 
4023  $h_query = "SELECT * FROM page_history ".
4024  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4025  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4026  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4027  " ORDER BY hdate DESC";
4028 
4029  $hset = $ilDB->query($h_query);
4030  $hentries = array();
4031 
4032  while ($hrec = $ilDB->fetchAssoc($hset))
4033  {
4034  $hrec["sortkey"] = (int) $hrec["nr"];
4035  $hrec["user"] = (int) $hrec["user_id"];
4036  $hentries[] = $hrec;
4037  }
4038 //var_dump($hentries);
4039  return $hentries;
4040  }
4041 
4045  function getHistoryEntry($a_old_nr)
4046  {
4047  global $ilDB;
4048 
4049  $res = $ilDB->queryF("SELECT * FROM page_history ".
4050  " WHERE page_id = %s ".
4051  " AND parent_type = %s ".
4052  " AND nr = %s".
4053  " AND lang = %s",
4054  array("integer", "text", "integer", "text"),
4055  array($this->getId(), $this->getParentType(), $a_old_nr, $this->getLanguage()));
4056  if ($hrec = $ilDB->fetchAssoc($res))
4057  {
4058  return $hrec;
4059  }
4060 
4061  return false;
4062  }
4063 
4064 
4071  function getHistoryInfo($a_nr)
4072  {
4073  global $ilDB;
4074 
4075  // determine previous entry
4076  $and_nr = ($a_nr > 0)
4077  ? " AND nr < ".$ilDB->quote((int) $a_nr, "integer")
4078  : "";
4079  $res = $ilDB->query("SELECT MAX(nr) mnr FROM page_history ".
4080  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4081  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4082  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4083  $and_nr);
4084  $row = $ilDB->fetchAssoc($res);
4085  if ($row["mnr"] > 0)
4086  {
4087  $res = $ilDB->query("SELECT * FROM page_history ".
4088  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4089  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4090  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4091  " AND nr = ".$ilDB->quote((int) $row["mnr"], "integer"));
4092  $row = $ilDB->fetchAssoc($res);
4093  $ret["previous"] = $row;
4094  }
4095 
4096  // determine next entry
4097  $res = $ilDB->query("SELECT MIN(nr) mnr FROM page_history ".
4098  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4099  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4100  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4101  " AND nr > ".$ilDB->quote((int) $a_nr, "integer"));
4102  $row = $ilDB->fetchAssoc($res);
4103  if ($row["mnr"] > 0)
4104  {
4105  $res = $ilDB->query("SELECT * FROM page_history ".
4106  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4107  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4108  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4109  " AND nr = ".$ilDB->quote((int) $row["mnr"], "integer"));
4110  $row = $ilDB->fetchAssoc($res);
4111  $ret["next"] = $row;
4112  }
4113 
4114  // current
4115  if ($a_nr > 0)
4116  {
4117  $res = $ilDB->query("SELECT * FROM page_history ".
4118  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4119  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4120  " AND lang = ".$ilDB->quote($this->getLanguage(), "text").
4121  " AND nr = ".$ilDB->quote((int) $a_nr, "integer"));
4122  $row = $ilDB->fetchAssoc($res);
4123  }
4124  else
4125  {
4126  $res = $ilDB->query("SELECT page_id, last_change hdate, parent_type, parent_id, last_change_user user_id, content, lang FROM page_object ".
4127  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4128  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text").
4129  " AND lang = ".$ilDB->quote($this->getLanguage(), "text"));
4130  $row = $ilDB->fetchAssoc($res);
4131  }
4132  $ret["current"] = $row;
4133 
4134  return $ret;
4135  }
4136 
4137  function addChangeDivClasses($a_hashes)
4138  {
4139  $xpc = xpath_new_context($this->dom);
4140  $path = "/*[1]";
4141  $res = xpath_eval($xpc, $path);
4142  $rnode = $res->nodeset[0];
4143 
4144 //echo "A";
4145  foreach($a_hashes as $pc_id => $h)
4146  {
4147 //echo "B";
4148  if ($h["change"] != "")
4149  {
4150  $dc_node = $this->dom->create_element("DivClass");
4151  $dc_node->set_attribute("HierId", $h["hier_id"]);
4152  $dc_node->set_attribute("Class", "ilEdit".$h["change"]);
4153  $dc_node = $rnode->append_child($dc_node);
4154  }
4155  }
4156 //echo "<br><br><br><br><br><br>".htmlentities($this->getXMLFromDom());
4157  }
4158 
4165  function compareVersion($a_left, $a_right)
4166  {
4167  // get page objects
4168  include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4169  $l_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_left);
4170  $r_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), $a_right);
4171 
4172  $l_hashes = $l_page->getPageContentsHashes();
4173  $r_hashes = $r_page->getPageContentsHashes();
4174  // determine all deleted and changed page elements
4175  foreach ($l_hashes as $pc_id => $h)
4176  {
4177  if (!isset($r_hashes[$pc_id]))
4178  {
4179  $l_hashes[$pc_id]["change"] = "Deleted";
4180  }
4181  else
4182  {
4183  if ($l_hashes[$pc_id]["hash"] != $r_hashes[$pc_id]["hash"])
4184  {
4185  $l_hashes[$pc_id]["change"] = "Modified";
4186  $r_hashes[$pc_id]["change"] = "Modified";
4187 
4188  include_once("./Services/COPage/mediawikidiff/class.WordLevelDiff.php");
4189  // if modified element is a paragraph, highlight changes
4190  if ($l_hashes[$pc_id]["content"] != "" &&
4191  $r_hashes[$pc_id]["content"] != "")
4192  {
4193  $new_left = str_replace("\n", "<br />", $l_hashes[$pc_id]["content"]);
4194  $new_right = str_replace("\n", "<br />", $r_hashes[$pc_id]["content"]);
4195  $wldiff = new WordLevelDiff(array($new_left),
4196  array($new_right));
4197  $new_left = $wldiff->orig();
4198  $new_right = $wldiff->closing();
4199  $l_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_left[0]);
4200  $r_page->setParagraphContent($l_hashes[$pc_id]["hier_id"], $new_right[0]);
4201  }
4202  }
4203  }
4204  }
4205 
4206  // determine all new paragraphs
4207  foreach ($r_hashes as $pc_id => $h)
4208  {
4209  if (!isset($l_hashes[$pc_id]))
4210  {
4211  $r_hashes[$pc_id]["change"] = "New";
4212  }
4213  }
4214  $l_page->addChangeDivClasses($l_hashes);
4215  $r_page->addChangeDivClasses($r_hashes);
4216 
4217  return array("l_page" => $l_page, "r_page" => $r_page,
4218  "l_changes" => $l_hashes, "r_changes" => $r_hashes);
4219  }
4220 
4224  function increaseViewCnt()
4225  {
4226  global $ilDB;
4227 
4228  $ilDB->manipulate("UPDATE page_object ".
4229  " SET view_cnt = view_cnt + 1 ".
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  }
4234 
4242  static function getRecentChanges($a_parent_type, $a_parent_id, $a_period = 30, $a_lang = "")
4243  {
4244  global $ilDB;
4245 
4246  $and_lang = "";
4247  if ($a_lang != "")
4248  {
4249  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4250  }
4251 
4252  $page_changes = array();
4253  $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4254  $q = "SELECT * FROM page_object ".
4255  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4256  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").
4257  " AND last_change >= ".$ilDB->quote($limit_ts, "timestamp").$and_lang;
4258  // " AND (TO_DAYS(now()) - TO_DAYS(last_change)) <= ".((int)$a_period);
4259  $set = $ilDB->query($q);
4260  while($page = $ilDB->fetchAssoc($set))
4261  {
4262  $page_changes[] = array(
4263  "date" => $page["last_change"],
4264  "id" => $page["page_id"],
4265  "lang" => $page["lang"],
4266  "type" => "page",
4267  "user" => $page["last_change_user"]);
4268  }
4269 
4270  $and_str = "";
4271  if ($a_period > 0)
4272  {
4273  $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
4274  $and_str = " AND hdate >= ".$ilDB->quote($limit_ts, "timestamp")." ";
4275  }
4276 
4277  $q = "SELECT * FROM page_history ".
4278  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4279  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").
4280  $and_str.$and_lang;
4281  $set = $ilDB->query($q);
4282  while ($page = $ilDB->fetchAssoc($set))
4283  {
4284  $page_changes[] = array(
4285  "date" => $page["hdate"],
4286  "id" => $page["page_id"],
4287  "lang" => $page["lang"],
4288  "type" => "hist",
4289  "nr" => $page["nr"],
4290  "user" => $page["user_id"]);
4291  }
4292 
4293  $page_changes = ilUtil::sortArray($page_changes, "date", "desc");
4294 
4295  return $page_changes;
4296  }
4297 
4305  static function getAllPages($a_parent_type, $a_parent_id, $a_lang = "-")
4306  {
4307  global $ilDB;
4308 
4309  $and_lang = "";
4310  if ($a_lang != "")
4311  {
4312  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4313  }
4314 
4315  $page_changes = array();
4316 
4317  $q = "SELECT * FROM page_object ".
4318  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4319  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").$and_lang;
4320  $set = $ilDB->query($q);
4321  $pages = array();
4322  while ($page = $ilDB->fetchAssoc($set))
4323  {
4324  $key_add = ($a_lang == "")
4325  ? ":".$page["lang"]
4326  : "";
4327  $pages[$page["page_id"].$key_add] = array(
4328  "date" => $page["last_change"],
4329  "id" => $page["page_id"],
4330  "lang" => $page["lang"],
4331  "user" => $page["last_change_user"]);
4332  }
4333 
4334  return $pages;
4335  }
4336 
4343  static function getNewPages($a_parent_type, $a_parent_id, $a_lang = "-")
4344  {
4345  global $ilDB;
4346 
4347  $and_lang = "";
4348  if ($a_lang != "")
4349  {
4350  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4351  }
4352 
4353  $pages = array();
4354 
4355  $q = "SELECT * FROM page_object ".
4356  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4357  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").$and_lang.
4358  " ORDER BY created DESC";
4359  $set = $ilDB->query($q);
4360  while($page = $ilDB->fetchAssoc($set))
4361  {
4362  if ($page["created"] != "")
4363  {
4364  $pages[] = array(
4365  "created" => $page["created"],
4366  "id" => $page["page_id"],
4367  "lang" => $page["lang"],
4368  "user" => $page["create_user"],
4369  );
4370  }
4371  }
4372 
4373  return $pages;
4374  }
4375 
4382  static function getParentObjectContributors($a_parent_type, $a_parent_id, $a_lang = "-")
4383  {
4384  global $ilDB;
4385 
4386  $and_lang = "";
4387  if ($a_lang != "")
4388  {
4389  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4390  }
4391 
4392  $contributors = array();
4393  $set = $ilDB->queryF("SELECT last_change_user, lang, page_id FROM page_object ".
4394  " WHERE parent_id = %s AND parent_type = %s ".
4395  " AND last_change_user != %s".$and_lang,
4396  array("integer", "text", "integer"),
4397  array($a_parent_id, $a_parent_type, 0));
4398 
4399  while ($page = $ilDB->fetchAssoc($set))
4400  {
4401  if ($a_lang == "")
4402  {
4403  $contributors[$page["last_change_user"]][$page["page_id"]][$page["lang"]] = 1;
4404  }
4405  else
4406  {
4407  $contributors[$page["last_change_user"]][$page["page_id"]] = 1;
4408  }
4409  }
4410 
4411  $set = $ilDB->queryF("SELECT count(DISTINCT page_id, parent_type, hdate, lang) as cnt, lang, page_id, user_id FROM page_history ".
4412  " WHERE parent_id = %s AND parent_type = %s AND user_id != %s ".$and_lang.
4413  " GROUP BY page_id, user_id, lang ",
4414  array("integer", "text", "integer"),
4415  array($a_parent_id, $a_parent_type, 0));
4416  while ($hpage = $ilDB->fetchAssoc($set))
4417  {
4418  if ($a_lang == "")
4419  {
4420  $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] =
4421  $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] + $hpage["cnt"];
4422  }
4423  else
4424  {
4425  $contributors[$hpage["user_id"]][$hpage["page_id"]] =
4426  $contributors[$hpage["user_id"]][$hpage["page_id"]] + $hpage["cnt"];
4427  }
4428  }
4429 
4430  $c = array();
4431  foreach ($contributors as $k => $co)
4432  {
4433  if (ilObject::_lookupType($k) == "usr")
4434  {
4435  $name = ilObjUser::_lookupName($k);
4436  $c[] = array("user_id" => $k, "pages" => $co,
4437  "lastname" => $name["lastname"], "firstname" => $name["firstname"]);
4438  }
4439  }
4440 
4441  return $c;
4442  }
4443 
4450  static function getPageContributors($a_parent_type, $a_page_id, $a_lang = "-")
4451  {
4452  global $ilDB;
4453 
4454  $and_lang = "";
4455  if ($a_lang != "")
4456  {
4457  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4458  }
4459 
4460  $contributors = array();
4461  $set = $ilDB->queryF("SELECT last_change_user, lang FROM page_object ".
4462  " WHERE page_id = %s AND parent_type = %s ".
4463  " AND last_change_user != %s".$and_lang,
4464  array("integer", "text", "integer"),
4465  array($a_page_id, $a_parent_type, 0));
4466 
4467  while ($page = $ilDB->fetchAssoc($set))
4468  {
4469  if ($a_lang == "")
4470  {
4471  $contributors[$page["last_change_user"]][$page["lang"]] = 1;
4472  }
4473  else
4474  {
4475  $contributors[$page["last_change_user"]] = 1;
4476  }
4477  }
4478 
4479  $set = $ilDB->queryF("SELECT count(DISTINCT page_id, parent_type, hdate, lang) as cnt, lang, page_id, user_id FROM page_history ".
4480  " WHERE page_id = %s AND parent_type = %s AND user_id != %s ".$and_lang.
4481  " GROUP BY user_id, page_id, lang ",
4482  array("integer", "text", "integer"),
4483  array($a_page_id, $a_parent_type, 0));
4484  while ($hpage = $ilDB->fetchAssoc($set))
4485  {
4486  if ($a_lang == "")
4487  {
4488  $contributors[$hpage["user_id"]][$page["lang"]] =
4489  $contributors[$hpage["user_id"]][$page["lang"]] + $hpage["cnt"];
4490  }
4491  else
4492  {
4493  $contributors[$hpage["user_id"]] =
4494  $contributors[$hpage["user_id"]] + $hpage["cnt"];
4495  }
4496  }
4497 
4498  $c = array();
4499  foreach ($contributors as $k => $co)
4500  {
4501  $name = ilObjUser::_lookupName($k);
4502  $c[] = array("user_id" => $k, "pages" => $co,
4503  "lastname" => $name["lastname"], "firstname" => $name["firstname"]);
4504  }
4505 
4506  return $c;
4507  }
4508 
4512  function writeRenderedContent($a_content, $a_md5)
4513  {
4514  global $ilDB;
4515 
4516  $ilDB->update("page_object", array(
4517  "rendered_content" => array("clob", $a_content),
4518  "render_md5" => array("text", $a_md5),
4519  "rendered_time" => array("timestamp", ilUtil::now())
4520  ), array(
4521  "page_id" => array("integer", $this->getId()),
4522  "lang" => array("text", $this->getLanguage()),
4523  "parent_type" => array("text", $this->getParentType())
4524  ));
4525  }
4526 
4534  static function getPagesWithLinks($a_parent_type, $a_parent_id, $a_lang = "-")
4535  {
4536  global $ilDB;
4537 
4538  $page_changes = array();
4539 
4540  $and_lang = "";
4541  if ($a_lang != "")
4542  {
4543  $and_lang = " AND lang = ".$ilDB->quote($a_lang, "text");
4544  }
4545 
4546  $q = "SELECT * FROM page_object ".
4547  " WHERE parent_id = ".$ilDB->quote($a_parent_id, "integer").
4548  " AND parent_type = ".$ilDB->quote($a_parent_type, "text").
4549  " AND int_links = ".$ilDB->quote(1, "integer").$and_lang;
4550  $set = $ilDB->query($q);
4551  $pages = array();
4552  while ($page = $ilDB->fetchAssoc($set))
4553  {
4554  $key_add = ($a_lang == "")
4555  ? ":".$page["lang"]
4556  : "";
4557  $pages[$page["page_id"].$key_add] = array(
4558  "date" => $page["last_change"],
4559  "id" => $page["page_id"],
4560  "lang" => $page["lang"],
4561  "user" => $page["last_change_user"]);
4562  }
4563 
4564  return $pages;
4565  }
4566 
4573  function containsIntLinks($a_content)
4574  {
4575  if (strpos($a_content, "IntLink"))
4576  {
4577  return true;
4578  }
4579  return false;
4580  }
4581 
4586  {
4587  }
4588 
4594 // @todo begin: generalize
4595  function saveInitialOpenedContent($a_type, $a_id, $a_target)
4596  {
4597  $this->buildDom();
4598 
4599  switch($a_type)
4600  {
4601  case "media":
4602  $link_type = "MediaObject";
4603  $a_id = "il__mob_".$a_id;
4604  break;
4605 
4606  case "page":
4607  $link_type = "PageObject";
4608  $a_id = "il__pg_".$a_id;
4609  break;
4610 
4611  case "term":
4612  $link_type = "GlossaryItem";
4613  $a_id = "il__git_".$a_id;
4614  $a_target = "Glossary";
4615  break;
4616  }
4617 
4618  // if type or id missing -> delete InitOpenedContent, if existing
4619  if ($link_type == "" || $a_id == "")
4620  {
4621  $xpc = xpath_new_context($this->dom);
4622  $path = "//PageObject/InitOpenedContent";
4623  $res = xpath_eval($xpc, $path);
4624  if (count($res->nodeset) > 0)
4625  {
4626  $res->nodeset[0]->unlink_node($res->nodeset[0]);
4627  }
4628  }
4629  else
4630  {
4631  $xpc = xpath_new_context($this->dom);
4632  $path = "//PageObject/InitOpenedContent";
4633  $res = xpath_eval($xpc, $path);
4634  if (count($res->nodeset) > 0)
4635  {
4636  $init_node = $res->nodeset[0];
4637  $childs = $init_node->child_nodes();
4638  for($i = 0; $i < count($childs); $i++)
4639  {
4640  if ($childs[$i]->node_name() == "IntLink")
4641  {
4642  $il_node = $childs[$i];
4643  }
4644  }
4645  }
4646  else
4647  {
4648  $path = "//PageObject";
4649  $res = xpath_eval($xpc, $path);
4650  $page_node = $res->nodeset[0];
4651  $init_node = $this->dom->create_element("InitOpenedContent");
4652  $init_node = $page_node->append_child($init_node);
4653  $il_node = $this->dom->create_element("IntLink");
4654  $il_node = $init_node->append_child($il_node);
4655  }
4656  $il_node->set_attribute("Target", $a_id);
4657  $il_node->set_attribute("Type", $link_type);
4658  $il_node->set_attribute("TargetFrame", $a_target);
4659  }
4660 
4661  $ret = $this->update();
4662  }
4663 
4664 
4671  {
4672  $this->buildDom();
4673 
4674  $xpc = xpath_new_context($this->dom);
4675  $path = "//PageObject/InitOpenedContent";
4676  $res = xpath_eval($xpc, $path);
4677  $il_node = null;
4678  if (count($res->nodeset) > 0)
4679  {
4680  $init_node = $res->nodeset[0];
4681  $childs = $init_node->child_nodes();
4682  for($i = 0; $i < count($childs); $i++)
4683  {
4684  if ($childs[$i]->node_name() == "IntLink")
4685  {
4686  $il_node = $childs[$i];
4687  }
4688  }
4689  }
4690  if (!is_null($il_node))
4691  {
4692  $id = $il_node->get_attribute("Target");
4693  $link_type = $il_node->get_attribute("Type");
4694  $target = $il_node->get_attribute("TargetFrame");
4695 
4696  switch($link_type)
4697  {
4698  case "MediaObject":
4699  $type = "media";
4700  break;
4701 
4702  case "PageObject":
4703  $type = "page";
4704  break;
4705 
4706  case "GlossaryItem":
4707  $type = "term";
4708  break;
4709  }
4710  include_once("./Services/Link/classes/class.ilInternalLink.php");
4712  return array("id" => $id, "type" => $type, "target" => $target);
4713  }
4714 
4715  return array();
4716  }
4717 // @todo end
4718 
4729  function beforePageContentUpdate($a_page_content)
4730  {
4731 
4732  }
4733 
4741  function copy($a_id, $a_parent_type = "", $a_parent_id = 0, $a_clone_mobs = false)
4742  {
4743  if ($a_parent_type == "")
4744  {
4745  $a_parent_type = $this->getParentType();
4746  if ($a_parent_id == 0)
4747  {
4748  $a_parent_id = $this->getParentId();
4749  }
4750  }
4751 
4752  include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
4753  foreach (self::lookupTranslations($this->getParentType(), $this->getId()) as $l)
4754  {
4755  $existed = false;
4756  $orig_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), 0, $l);
4757  if (ilPageObject::_exists($a_parent_type, $a_id, $l))
4758  {
4759  $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, $a_id, 0, $l);
4760  $existed = true;
4761  }
4762  else
4763  {
4764  $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, 0, 0, $l);
4765  $new_page_object->setParentId($a_parent_id);
4766  $new_page_object->setId($a_id);
4767  }
4768  $new_page_object->setXMLContent($orig_page->copyXMLContent($a_clone_mobs));
4769  $new_page_object->setActive($orig_page->getActive());
4770  $new_page_object->setActivationStart($orig_page->getActivationStart());
4771  $new_page_object->setActivationEnd($orig_page->getActivationEnd());
4772  if ($existed)
4773  {
4774  $new_page_object->buildDom();
4775  $new_page_object->update();
4776  }
4777  else
4778  {
4779  $new_page_object->create();
4780  }
4781  }
4782 
4783  }
4784 
4792  static function lookupTranslations($a_parent_type, $a_id)
4793  {
4794  global $ilDB;
4795 
4796  $set = $ilDB->query("SELECT lang FROM page_object ".
4797  " WHERE page_id = ".$ilDB->quote($a_id, "integer").
4798  " AND parent_type = ".$ilDB->quote($a_parent_type, "text")
4799  );
4800  $langs = array();
4801  while ($rec = $ilDB->fetchAssoc($set))
4802  {
4803  $langs[] = $rec["lang"];
4804  }
4805  return $langs;
4806  }
4807 
4808 
4814  function copyPageToTranslation($a_target_lang)
4815  {
4816  $transl_page = ilPageObjectFactory::getInstance($this->getParentType(),
4817  0, 0, $a_target_lang);
4818  $transl_page->setId($this->getId());
4819  $transl_page->setParentId($this->getParentId());
4820  $transl_page->setXMLContent($this->copyXMLContent());
4821  $transl_page->setActive($this->getActive());
4822  $transl_page->setActivationStart($this->getActivationStart());
4823  $transl_page->setActivationEnd($this->getActivationEnd());
4824  $transl_page->create();
4825  }
4826 
4830 
4834  function getEditLock()
4835  {
4836  global $ilUser, $ilDB;
4837 
4838  $aset = new ilSetting("adve");
4839 
4840  $min = (int) $aset->get("block_mode_minutes") ;
4841  if ($min > 0)
4842  {
4843  // try to set the lock for the user
4844  $ts = time();
4845  $ilDB->manipulate("UPDATE page_object SET ".
4846  " edit_lock_user = ".$ilDB->quote($ilUser->getId(), "integer").",".
4847  " edit_lock_ts = ".$ilDB->quote($ts, "integer").
4848  " WHERE (edit_lock_user = ".$ilDB->quote($ilUser->getId(), "integer")." OR ".
4849  " edit_lock_ts < ".$ilDB->quote(time() - ($min * 60), "integer").") ".
4850  " AND page_id = ".$ilDB->quote($this->getId(), "integer").
4851  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
4852  );
4853 
4854  $set = $ilDB->query("SELECT edit_lock_user FROM page_object ".
4855  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4856  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
4857  );
4858  $rec = $ilDB->fetchAssoc($set);
4859  if ($rec["edit_lock_user"] != $ilUser->getId())
4860  {
4861  return false;
4862  }
4863  }
4864 
4865  return true;
4866  }
4867 
4871  function releasePageLock()
4872  {
4873  global $ilUser, $ilDB;
4874 
4875  $aset = new ilSetting("adve");
4876 
4877  $min = (int) $aset->get("block_mode_minutes") ;
4878  if ($min > 0)
4879  {
4880  // try to set the lock for the user
4881  $ts = time();
4882  $ilDB->manipulate("UPDATE page_object SET ".
4883  " edit_lock_user = ".$ilDB->quote($ilUser->getId(), "integer").",".
4884  " edit_lock_ts = 0".
4885  " WHERE edit_lock_user = ".$ilDB->quote($ilUser->getId(), "integer").
4886  " AND page_id = ".$ilDB->quote($this->getId(), "integer").
4887  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
4888  );
4889 
4890  $set = $ilDB->query("SELECT edit_lock_user FROM page_object ".
4891  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4892  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
4893  );
4894  $rec = $ilDB->fetchAssoc($set);
4895  if ($rec["edit_lock_user"] != $ilUser->getId())
4896  {
4897  return false;
4898  }
4899  }
4900 
4901  return true;
4902  }
4903 
4909  function getEditLockInfo()
4910  {
4911  global $ilDB;
4912 
4913  $aset = new ilSetting("adve");
4914  $min = (int) $aset->get("block_mode_minutes");
4915 
4916  $set = $ilDB->query("SELECT edit_lock_user, edit_lock_ts FROM page_object ".
4917  " WHERE page_id = ".$ilDB->quote($this->getId(), "integer").
4918  " AND parent_type = ".$ilDB->quote($this->getParentType(), "text")
4919  );
4920  $rec = $ilDB->fetchAssoc($set);
4921  $rec["edit_lock_until"] = $rec["edit_lock_ts"] + $min * 60;
4922 
4923  return $rec;
4924  }
4925 
4938  public static function truncateHTML($a_text, $a_length = 100, $a_ending = '...', $a_exact = false, $a_consider_html = true)
4939  {
4940  include_once "Services/Utilities/classes/class.ilStr.php";
4941 
4942  if ($a_consider_html)
4943  {
4944  // if the plain text is shorter than the maximum length, return the whole text
4945  if(strlen(preg_replace('/<.*?>/', '', $a_text)) <= $a_length)
4946  {
4947  return $a_text;
4948  }
4949 
4950  // splits all html-tags to scanable lines
4951  $total_length = strlen($a_ending);
4952  $open_tags = array();
4953  $truncate = '';
4954  preg_match_all('/(<.+?>)?([^<>]*)/s', $a_text, $lines, PREG_SET_ORDER);
4955  foreach($lines as $line_matchings)
4956  {
4957  // if there is any html-tag in this line, handle it and add it (uncounted) to the output
4958  if(!empty($line_matchings[1]))
4959  {
4960  // if it's an "empty element" with or without xhtml-conform closing slash
4961  if(preg_match('/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is', $line_matchings[1]))
4962  {
4963  // do nothing
4964  }
4965  // if tag is a closing tag
4966  else if(preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line_matchings[1], $tag_matchings))
4967  {
4968  // delete tag from $open_tags list
4969  $pos = array_search($tag_matchings[1], $open_tags);
4970  if ($pos !== false)
4971  {
4972  unset($open_tags[$pos]);
4973  }
4974  }
4975  // if tag is an opening tag
4976  else if (preg_match('/^<\s*([^\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings))
4977  {
4978  // add tag to the beginning of $open_tags list
4979  array_unshift($open_tags, strtolower($tag_matchings[1]));
4980  }
4981  // add html-tag to $truncate'd text
4982  $truncate .= $line_matchings[1];
4983  }
4984 
4985  // calculate the length of the plain text part of the line; handle entities as one character
4986  $content_length = strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
4987  if($total_length+$content_length > $a_length)
4988  {
4989  // the number of characters which are left
4990  $left = $a_length - $total_length;
4991  $entities_length = 0;
4992  // search for html entities
4993  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))
4994  {
4995  // calculate the real length of all entities in the legal range
4996  foreach($entities[0] as $entity)
4997  {
4998  if($entity[1]+1-$entities_length <= $left)
4999  {
5000  $left--;
5001  $entities_length += strlen($entity[0]);
5002  }
5003  else
5004  {
5005  // no more characters left
5006  break;
5007  }
5008  }
5009  }
5010 
5011  // $truncate .= substr($line_matchings[2], 0, $left+$entities_length);
5012  $truncate .= ilStr::shortenText($line_matchings[2], 0, $left+$entities_length);
5013 
5014  // maximum lenght is reached, so get off the loop
5015  break;
5016  }
5017  else
5018  {
5019  $truncate .= $line_matchings[2];
5020  $total_length += $content_length;
5021  }
5022 
5023  // if the maximum length is reached, get off the loop
5024  if($total_length >= $a_length)
5025  {
5026  break;
5027  }
5028  }
5029  }
5030  else
5031  {
5032  if(strlen($a_text) <= $a_length)
5033  {
5034  return $a_text;
5035  }
5036  else
5037  {
5038  // $truncate = substr($a_text, 0, $a_length - strlen($a_ending));
5039  $truncate = ilStr::shortenText($a_text, 0, $a_length - strlen($a_ending));
5040  }
5041  }
5042 
5043  // THIS IS BUGGY AS IT MIGHT BREAK AN OPEN TAG AT THE END
5044  if(!sizeof($open_tags))
5045  {
5046  // if the words shouldn't be cut in the middle...
5047  if (!$a_exact)
5048  {
5049  // ...search the last occurance of a space...
5050  $spacepos = strrpos($truncate, ' ');
5051  if($spacepos !== false)
5052  {
5053  // ...and cut the text in this position
5054  // $truncate = substr($truncate, 0, $spacepos);
5055  $truncate = ilStr::shortenText($truncate, 0, $spacepos);
5056  }
5057  }
5058  }
5059 
5060  // add the defined ending to the text
5061  $truncate .= $a_ending;
5062 
5063  if($a_consider_html)
5064  {
5065  // close all unclosed html-tags
5066  foreach($open_tags as $tag)
5067  {
5068  $truncate .= '</'.$tag.'>';
5069  }
5070  }
5071 
5072  return $truncate;
5073  }
5074 
5081  {
5082  return array();
5083  }
5084 }
5085 ?>