ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilPageObject.php
Go to the documentation of this file.
1 <?php
2 
19 define("IL_INSERT_BEFORE", 0);
20 define("IL_INSERT_AFTER", 1);
21 define("IL_INSERT_CHILD", 2);
22 
23 /*
24 
25  - move dom related code to PageDom class/interface
26  - move ilDB dependency to ar object
27  - move internal links related code to extra class
28  - make factory available through DIC, opt allow decentralized factory parts
29  - PC types
30  -- internal links used/implemented?
31  -- styles used/implemented?
32  - application classes need
33  -- page object
34  --- page object should return php5 domdoc (getDom() vs getDomDoc()?)
35  esp. plugins should use this
36  -- remove content element hook, if content is not allowed
37  - PC types could move to components (e.g. blog, login)
38  - How to modularize xsl?
39  -- read from db?
40  -- xml entries say that xslt code is used -> read file and include in
41  main xslt file
42 
43 */
44 
46 
52 abstract class ilPageObject
53 {
54  protected \ILIAS\COPage\Dom\DomUtil $dom_util;
55  protected \ILIAS\COPage\Link\LinkManager $link;
56  protected \ILIAS\COPage\PC\PCDefinition $pc_definition;
57  protected int $create_user = 0;
61  protected array $id_elements;
62  public int $old_nr;
63  protected bool $page_not_found = false;
64  protected bool $show_page_act_info = false;
66  public static array $exists = array();
67  protected ilDBInterface $db;
68  protected ilObjUser $user;
69  protected ilLanguage $lng;
70  protected ilTree $tree;
72  protected int $id;
73  public ?DOMDocument $dom = null;
74  public string $xml = "";
75  public string $encoding = "";
76  public DomNode $node;
77  public string $cur_dtd = "ilias_pg_9.dtd";
78  public bool $contains_int_link = false;
79  public bool $needs_parsing = false;
80  public string $parent_type = "";
81  public int $parent_id = 0;
82  public array $update_listeners = [];
83  public int $update_listener_cnt = 0;
84  public ?object $offline_handler = null; // see LMPresentation handleCodeParagraph
85  public bool $dom_builded = false;
86  public bool $history_saved = false;
87  protected string $language = "-";
88  protected static array $activation_data = array();
89  protected bool $import_mode = false;
90  protected ilLogger $log;
91  protected ?array $page_record = array();
92  protected bool $active = false;
94  protected string $rendermd5 = "";
95  protected string $renderedcontent = "";
96  protected string $renderedtime = "";
97  protected string $lastchange = "";
98  public int $last_change_user = 0;
99  protected bool $contains_question = false;
100  protected array $hier_ids = [];
101  protected ?string $activationstart = null; // IL_CAL_DATETIME format
102  protected ?string $activationend = null; // IL_CAL_DATETIME format
103  protected \ILIAS\COPage\ReadingTime\ReadingTimeManager $reading_time_manager;
104  protected $concrete_lang = "";
105  protected \ILIAS\COPage\ID\ContentIdManager $content_id_manager;
106  protected \ILIAS\COPage\Page\PageManager $page_manager;
107  protected \ILIAS\COPage\Style\StyleManager $style_manager;
108  protected \ILIAS\COPage\PC\DomainService $pc_service;
109 
110  final public function __construct(
111  int $a_id = 0,
112  int $a_old_nr = 0,
113  string $a_lang = "-"
114  ) {
115  global $DIC;
116  $this->obj_definition = $DIC["objDefinition"];
117  $this->db = $DIC->database();
118  $this->user = $DIC->user();
119  $this->lng = $DIC->language();
120  $this->tree = $DIC->repositoryTree();
121  $this->log = ilLoggerFactory::getLogger('copg');
122  $this->lom_services = $DIC->learningObjectMetadata();
123 
124  $this->reading_time_manager = new ILIAS\COPage\ReadingTime\ReadingTimeManager();
125 
126  $this->parent_type = $this->getParentType();
127  $this->id = $a_id;
128  $this->setLanguage($a_lang);
129 
130  $this->contains_int_link = false;
131  $this->needs_parsing = false;
132  $this->update_listeners = array();
133  $this->update_listener_cnt = 0;
134  $this->dom_builded = false;
135  $this->page_not_found = false;
136  $this->old_nr = $a_old_nr;
137  $this->encoding = "UTF-8";
138  $this->id_elements =
139  array("PageContent",
140  "TableRow",
141  "TableData",
142  "ListItem",
143  "FileItem",
144  "Section",
145  "Tab",
146  "ContentPopup",
147  "GridCell"
148  );
149  $this->setActive(true);
150  $this->show_page_act_info = false;
151 
152  if ($a_id != 0) {
153  $this->read();
154  }
155 
156  $this->initPageConfig();
157  $this->afterConstructor();
158  $domain = $DIC->copage()
159  ->internal()
160  ->domain();
161  $this->content_id_manager = $domain
162  ->contentIds($this);
163  $this->page_manager = $domain->page();
164  $this->pc_service = $domain->pc();
165  $this->pc_definition = $domain->pc()->definition();
166  $this->link = $domain->link();
167  $this->style_manager = $domain->style();
168  $this->dom_util = $domain->domUtil();
169  }
170 
171  public function setContentIdManager(
172  \ILIAS\COPage\ID\ContentIdManager $content_id_manager
173  ): void {
174  $this->content_id_manager = $content_id_manager;
175  }
176 
177  public function afterConstructor(): void
178  {
179  }
180 
181  abstract public function getParentType(): string;
182 
183  public function initPageConfig(): void
184  {
186  $this->setPageConfig($cfg);
187  }
188 
193  public function setLanguage(string $a_val): void
194  {
195  $this->language = $a_val;
196  }
197 
198  public function getLanguage(): string
199  {
200  return $this->language;
201  }
202 
203  public function setPageConfig(ilPageConfig $a_val): void
204  {
205  $this->page_config = $a_val;
206  }
207 
208  public function setConcreteLang(string $a_val)
209  {
210  $this->concrete_lang = $a_val;
211  }
212 
213  public function getConcreteLang(): string
214  {
215  return $this->concrete_lang;
216  }
217 
218  public function getPageConfig(): ilPageConfig
219  {
220  return $this->page_config;
221  }
222 
223  public function setRenderMd5(string $a_rendermd5): void
224  {
225  $this->rendermd5 = $a_rendermd5;
226  }
227 
228  public function getRenderMd5(): string
229  {
230  return $this->rendermd5;
231  }
232 
233  public function setRenderedContent(string $a_renderedcontent): void
234  {
235  $this->renderedcontent = $a_renderedcontent;
236  }
237 
238  public function getRenderedContent(): string
239  {
240  return $this->renderedcontent;
241  }
242 
243  public function setRenderedTime(string $a_renderedtime): void
244  {
245  $this->renderedtime = $a_renderedtime;
246  }
247 
248  public function getRenderedTime(): string
249  {
250  return $this->renderedtime;
251  }
252 
253  public function setLastChange(string $a_lastchange): void
254  {
255  $this->lastchange = $a_lastchange;
256  }
257 
258  public function getLastChange(): string
259  {
260  return $this->lastchange;
261  }
262 
263  public function setLastChangeUser(int $a_val): void
264  {
265  $this->last_change_user = $a_val;
266  }
267 
268  public function getLastChangeUser(): int
269  {
271  }
272 
273  public function setShowActivationInfo(bool $a_val): void
274  {
275  $this->show_page_act_info = $a_val;
276  }
277 
278  public function getShowActivationInfo(): bool
279  {
281  }
282 
283  public function getCreationUserId(): int
284  {
285  return $this->create_user;
286  }
287 
291  public function read(): void
292  {
293  $this->setActive(true);
294  if ($this->old_nr == 0) {
295  $query = "SELECT * FROM page_object" .
296  " WHERE page_id = " . $this->db->quote($this->id, "integer") .
297  " AND parent_type=" . $this->db->quote($this->getParentType(), "text") .
298  " AND lang = " . $this->db->quote($this->getLanguage(), "text");
299  $pg_set = $this->db->query($query);
300  if (!$this->page_record = $this->db->fetchAssoc($pg_set)) {
301  throw new ilCOPageNotFoundException("Error: Page " . $this->id . " is not in database" .
302  " (parent type " . $this->getParentType() . ", lang: " . $this->getLanguage() . ").");
303  }
304  $this->setActive($this->page_record["active"]);
305  $this->setActivationStart($this->page_record["activation_start"]);
306  $this->setActivationEnd($this->page_record["activation_end"]);
307  $this->setShowActivationInfo($this->page_record["show_activation_info"]);
308  } else {
309  $query = "SELECT * FROM page_history" .
310  " WHERE page_id = " . $this->db->quote($this->id, "integer") .
311  " AND parent_type=" . $this->db->quote($this->getParentType(), "text") .
312  " AND nr = " . $this->db->quote($this->old_nr, "integer") .
313  " AND lang = " . $this->db->quote($this->getLanguage(), "text");
314  $pg_set = $this->db->query($query);
315  $this->page_record = $this->db->fetchAssoc($pg_set);
316  }
317  if (!$this->page_record) {
318  throw new ilCOPageNotFoundException("Error: Page " . $this->id . " is not in database" .
319  " (parent type " . $this->getParentType() . ", lang: " . $this->getLanguage() . ").");
320  }
321  $this->xml = $this->page_record["content"];
322  $this->setParentId((int) $this->page_record["parent_id"]);
323  $this->last_change_user = (int) ($this->page_record["last_change_user"] ?? 0);
324  $this->create_user = (int) ($this->page_record["create_user"] ?? 0);
325  $this->setRenderedContent((string) ($this->page_record["rendered_content"] ?? ""));
326  $this->setRenderMd5((string) ($this->page_record["render_md5"] ?? ""));
327  $this->setRenderedTime((string) ($this->page_record["rendered_time"] ?? ""));
328  $this->setLastChange((string) ($this->page_record["last_change"] ?? ""));
329  }
330 
335  public static function _exists(
336  string $a_parent_type,
337  int $a_id,
338  string $a_lang = "",
339  bool $a_no_cache = false
340  ): bool {
341  global $DIC;
342 
343  $db = $DIC->database();
344 
345  if (!$a_no_cache && isset(self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang])) {
346  return self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang];
347  }
348 
349  $and_lang = "";
350  if ($a_lang != "") {
351  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
352  }
353 
354  $query = "SELECT page_id FROM page_object WHERE page_id = " . $db->quote($a_id, "integer") . " " .
355  "AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang;
356  $set = $db->query($query);
357  if ($row = $db->fetchAssoc($set)) {
358  self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang] = true;
359  return true;
360  } else {
361  self::$exists[$a_parent_type . ":" . $a_id . ":" . $a_lang] = false;
362  return false;
363  }
364  }
365 
369  public static function _existsAndNotEmpty(
370  string $a_parent_type,
371  int $a_id,
372  string $a_lang = "-"
373  ): bool {
374  return ilPageUtil::_existsAndNotEmpty($a_parent_type, $a_id, $a_lang);
375  }
376 
380  public function buildDom(bool $a_force = false)
381  {
382  if ($this->dom_builded && !$a_force) {
383  return true;
384  }
385  $error = null;
386  if ($this->getXMLContent() === "") {
387  $this->setXMLContent("<PageObject></PageObject>");
388  }
389  $this->dom = $this->dom_util->docFromString($this->getXMLContent(true), $error);
390  $path = "//PageObject";
391  if (is_null($this->dom)) {
392  throw new ilCOPageException("Invalid page xml (" .
393  $this->getId() . "," . $this->getLanguage() . "): " . $this->getXMLContent(true));
394  }
395  $nodes = $this->dom_util->path($this->dom, $path);
396  if (count($nodes) == 1) {
397  $this->node = $nodes->item(0);
398  } else {
399  throw new ilCOPageException("Invalid page xml (" .
400  $this->getId() . "," . $this->getLanguage() . "): " . $this->getXMLContent(true));
401  }
402 
403  if (empty($error)) {
404  $this->dom_builded = true;
405  return true;
406  } else {
407  return $error;
408  }
409  }
410 
411  public function freeDom(): void
412  {
413  unset($this->dom);
414  }
415 
419  public function getDomDoc(): DOMDocument
420  {
421  return $this->dom;
422  }
423 
424  public function setId(int $a_id): void
425  {
426  $this->id = $a_id;
427  }
428 
429  public function getId(): int
430  {
431  return $this->id;
432  }
433 
434  public function setParentId(int $a_id): void
435  {
436  $this->parent_id = $a_id;
437  }
438 
439  public function getParentId(): int
440  {
441  return $this->parent_id;
442  }
443 
447  public function addUpdateListener(
448  object $a_object,
449  string $a_method,
450  $a_parameters = ""
451  ): void {
453  $this->update_listeners[$cnt]["object"] = $a_object;
454  $this->update_listeners[$cnt]["method"] = $a_method;
455  $this->update_listeners[$cnt]["parameters"] = $a_parameters;
456  $this->update_listener_cnt++;
457  }
458 
459  public function callUpdateListeners(): void
460  {
461  for ($i = 0; $i < $this->update_listener_cnt; $i++) {
462  $object = $this->update_listeners[$i]["object"];
463  $method = $this->update_listeners[$i]["method"];
464  $parameters = $this->update_listeners[$i]["parameters"];
465  $object->$method($parameters);
466  }
467  }
468 
469  public function setActive(bool $a_active): void
470  {
471  $this->active = $a_active;
472  }
473 
474  public function getActive(
475  bool $a_check_scheduled_activation = false
476  ): bool {
477  if ($a_check_scheduled_activation && !$this->active) {
478  $start = new ilDateTime($this->getActivationStart(), IL_CAL_DATETIME);
479  $end = new ilDateTime($this->getActivationEnd(), IL_CAL_DATETIME);
480  $now = new ilDateTime(time(), IL_CAL_UNIX);
481  if (!ilDateTime::_before($now, $start) && !ilDateTime::_after($now, $end)) {
482  return true;
483  }
484  }
485  return $this->active;
486  }
487 
491  public static function preloadActivationDataByParentId(int $a_parent_id): void
492  {
493  global $DIC;
494 
495  $db = $DIC->database();
496  $set = $db->query(
497  "SELECT page_id, parent_type, lang, active, activation_start, activation_end, show_activation_info FROM page_object " .
498  " WHERE parent_id = " . $db->quote($a_parent_id, "integer")
499  );
500  while ($rec = $db->fetchAssoc($set)) {
501  self::$activation_data[$rec["page_id"] . ":" . $rec["parent_type"] . ":" . $rec["lang"]] = $rec;
502  }
503  }
504 
508  public static function _lookupActive(
509  int $a_id,
510  string $a_parent_type,
511  bool $a_check_scheduled_activation = false,
512  string $a_lang = "-"
513  ): bool {
514  global $DIC;
515 
516  $db = $DIC->database();
517 
518  // language must be set at least to "-"
519  if ($a_lang == "") {
520  $a_lang = "-";
521  }
522 
523  if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
524  $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
525  } else {
526  $set = $db->queryF(
527  "SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s" .
528  " AND parent_type = %s AND lang = %s",
529  array("integer", "text", "text"),
530  array($a_id, $a_parent_type, $a_lang)
531  );
532  $rec = $db->fetchAssoc($set);
533  if (!$rec) {
534  return true;
535  }
536  }
537 
538  $rec["n"] = ilUtil::now();
539  if (!$rec["active"] && $a_check_scheduled_activation) {
540  if ($rec["n"] >= $rec["activation_start"] &&
541  $rec["n"] <= $rec["activation_end"]) {
542  return true;
543  }
544  }
545 
546  return (bool) $rec["active"];
547  }
548 
552  public static function _isScheduledActivation(
553  int $a_id,
554  string $a_parent_type,
555  string $a_lang = "-"
556  ): bool {
557  global $DIC;
558 
559  $db = $DIC->database();
560 
561  // language must be set at least to "-"
562  if ($a_lang == "") {
563  $a_lang = "-";
564  }
565 
566  //echo "<br>";
567  //var_dump(self::$activation_data); exit;
568  if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
569  $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
570  } else {
571  $set = $db->queryF(
572  "SELECT active, activation_start, activation_end FROM page_object WHERE page_id = %s" .
573  " AND parent_type = %s AND lang = %s",
574  array("integer", "text", "text"),
575  array($a_id, $a_parent_type, $a_lang)
576  );
577  $rec = $db->fetchAssoc($set);
578  }
579 
580  if (!$rec["active"] && $rec["activation_start"] != "") {
581  return true;
582  }
583 
584  return false;
585  }
586 
590  public static function _writeActive(
591  int $a_id,
592  string $a_parent_type,
593  bool $a_active
594  ): void {
595  global $DIC;
596 
597  $db = $DIC->database();
598 
599  // language must be set at least to "-"
600  $a_lang = "-";
601 
602  $db->manipulateF(
603  "UPDATE page_object SET active = %s, activation_start = %s, " .
604  " activation_end = %s WHERE page_id = %s" .
605  " AND parent_type = %s AND lang = %s",
606  array("int", "timestamp", "timestamp", "integer", "text", "text"),
607  array((int) $a_active, null, null, $a_id, $a_parent_type, $a_lang)
608  );
609  }
610 
614  public static function _lookupActivationData(
615  int $a_id,
616  string $a_parent_type,
617  string $a_lang = "-"
618  ): array {
619  global $DIC;
620 
621  $db = $DIC->database();
622 
623  // language must be set at least to "-"
624  if ($a_lang == "") {
625  $a_lang = "-";
626  }
627 
628  if (isset(self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang])) {
629  $rec = self::$activation_data[$a_id . ":" . $a_parent_type . ":" . $a_lang];
630  } else {
631  $set = $db->queryF(
632  "SELECT active, activation_start, activation_end, show_activation_info FROM page_object WHERE page_id = %s" .
633  " AND parent_type = %s AND lang = %s",
634  array("integer", "text", "text"),
635  array($a_id, $a_parent_type, $a_lang)
636  );
637  $rec = $db->fetchAssoc($set);
638  if (!$rec) {
639  return [
640  "active" => 1,
641  "activation_start" => null,
642  "activation_end" => null,
643  "show_activation_info" => 0
644  ];
645  }
646  }
647 
648  return $rec;
649  }
650 
651  public static function lookupParentId(int $a_id, string $a_type): int
652  {
653  global $DIC;
654 
655  $db = $DIC->database();
656 
657  $res = $db->query("SELECT parent_id FROM page_object WHERE page_id = " . $db->quote($a_id, "integer") . " " .
658  "AND parent_type=" . $db->quote($a_type, "text"));
659  $rec = $db->fetchAssoc($res);
660  return (int) ($rec["parent_id"] ?? 0);
661  }
662 
663  public static function _writeParentId(string $a_parent_type, int $a_pg_id, int $a_par_id): void
664  {
665  global $DIC;
666 
667  $db = $DIC->database();
668  $db->manipulateF(
669  "UPDATE page_object SET parent_id = %s WHERE page_id = %s" .
670  " AND parent_type = %s",
671  array("integer", "integer", "text"),
672  array($a_par_id, $a_pg_id, $a_parent_type)
673  );
674  }
675 
679  public function setActivationStart(?string $a_activationstart): void
680  {
681  if ($a_activationstart == "") {
682  $a_activationstart = null;
683  }
684  $this->activationstart = $a_activationstart;
685  }
686 
687  public function getActivationStart(): ?string
688  {
689  return $this->activationstart;
690  }
691 
696  public function setActivationEnd(?string $a_activationend): void
697  {
698  if ($a_activationend == "") {
699  $a_activationend = null;
700  }
701  $this->activationend = $a_activationend;
702  }
703 
704  public function getActivationEnd(): ?string
705  {
706  return $this->activationend;
707  }
708 
712  public function getContentObject(
713  string $a_hier_id,
714  string $a_pc_id = ""
715  ): ?ilPageContent {
716  $node = $this->page_manager->content($this->getDomDoc())->getContentDomNode(
717  $a_hier_id,
718  $a_pc_id
719  );
720  $this->log->debug("getContentObject: " . " $a_hier_id, $a_pc_id, " . $node->nodeName);
721  return $this->pc_service->getByNode($node, $this);
722  }
723 
727  public function getContentObjectForPcId(string $pcid): ?ilPageContent
728  {
729  $hier_ids = $this->getHierIdsForPCIds([$pcid]);
730  return $this->getContentObject($hier_ids[$pcid], $pcid);
731  }
732 
736  public function getParentContentObjectForPcId(string $pcid): ?ilPageContent
737  {
738  $content_object = $this->getContentObjectForPcId($pcid);
739  $node = $content_object->getDomNode();
740  $node = $node->parentNode;
741  while ($node) {
742  if ($node->nodeName == "PageContent") {
743  $pcid = $node->getAttribute("PCID");
744  if ($pcid != "") {
745  return $this->getContentObjectForPcId($pcid);
746  }
747  }
748  $node = $node->parentNode;
749  }
750  return null;
751  }
752 
753  public function getContentDomNode(string $a_hier_id, string $a_pc_id = ""): ?DOMNode
754  {
755  $cm = $this->page_manager->content($this->getDomDoc());
756  return $cm->getContentDomNode($a_hier_id, $a_pc_id);
757  }
758 
759  public function getDomNodeForPCId(string $pc_id): ?DOMNode
760  {
761  return $this->getContentDomNode("", $pc_id);
762  }
763 
770  public function setXMLContent(string $a_xml, string $a_encoding = "UTF-8"): void
771  {
772  $this->encoding = $a_encoding;
773  $this->xml = $a_xml;
774  }
775 
780  public function appendXMLContent(string $a_xml): void
781  {
782  $this->xml .= $a_xml;
783  }
784 
788  public function getXMLContent(bool $a_incl_head = false): string
789  {
790  // build full http path for XML DOCTYPE header.
791  // Under windows a relative path doesn't work :-(
792  if ($a_incl_head) {
793  //echo "+".$this->encoding."+";
794  $enc_str = (!empty($this->encoding))
795  ? "encoding=\"" . $this->encoding . "\""
796  : "";
797  return "<?xml version=\"1.0\" $enc_str ?>" .
798  "<!DOCTYPE PageObject SYSTEM \"" . $this->getIliasAbsolutePath() . "/components/ILIAS/Export/xml/" . $this->cur_dtd . "\">" .
799  $this->xml;
800  } else {
801  return $this->xml;
802  }
803  }
804 
805  protected function getIliasAbsolutePath(): string
806  {
807  return ILIAS_ABSOLUTE_PATH;
808  }
809 
815  public function copyXmlContent(
816  bool $a_clone_mobs = false,
817  int $a_new_parent_id = 0,
818  int $obj_copy_id = 0,
819  bool $self_ass = true
820  ): string {
821  $cm = $this->page_manager->contentFromXml($this->getXMLContent());
822  return $cm->copyXmlContent(
823  $this,
824  $a_clone_mobs,
825  $a_new_parent_id,
826  $obj_copy_id,
827  $self_ass
828  );
829  }
830 
831  // @todo 1: begin: generalize, remove concrete dependencies
832 
833 
840  public function handleDeleteContent(?DOMNode $a_node = null, $move_operation = false): void
841  {
842  $pm = $this->page_manager->content($this->getDomDoc());
843  $pm->handleDeleteContent($this, $a_node, $move_operation);
844  }
845 
850  public function getXMLFromDom(
851  bool $a_incl_head = false,
852  bool $a_append_mobs = false,
853  bool $a_append_bib = false,
854  string $a_append_str = "",
855  bool $a_omit_pageobject_tag = false,
856  int $style_id = 0,
857  bool $offline = false
858  ): string {
859  if ($a_incl_head) {
860  //echo "\n<br>#".$this->encoding."#";
861  return $this->dom_util->dump($this->node);
862  } else {
863  // append multimedia object elements
864  if ($a_append_mobs || $a_append_bib) {
865  $mobs = "";
866  $bibs = "";
867  if ($a_append_mobs) {
868  $mobs = $this->getMultimediaXML($offline);
869  }
870  if ($a_append_bib) {
871  // deprecated
872  // $bibs = $this->getBibliographyXML();
873  }
874  $trans = $this->getLanguageVariablesXML($style_id);
875  //echo htmlentities($this->dom->dump_node($this->node)); exit;
876  return "<dummy>" . $this->dom_util->dump($this->node) . $mobs . $bibs . $trans . $a_append_str . "</dummy>";
877  } else {
878  if (is_object($this->dom)) {
879  if ($a_omit_pageobject_tag) {
880  $xml = "";
881  foreach ($this->node->childNodes as $child) {
882  $xml .= $this->dom_util->dump($child);
883  }
884  } else {
885  $xml = $this->dom_util->dump($this->node);
886  $xml = preg_replace('/<\?xml[^>]*>/i', "", $xml);
887  $xml = preg_replace('/<!DOCTYPE[^>]*>/i', "", $xml);
888 
889  // don't use dump_node. This gives always entities.
890  //return $this->dom->dump_node($this->node);
891  }
892  return $xml;
893  } else {
894  return "";
895  }
896  }
897  }
898  }
899 
903  public function getLanguageVariablesXML(int $style_id = 0): string
904  {
905  $xml = "<LVs>";
906  $lang_vars = array(
907  "ed_paste_clip",
908  "ed_edit",
909  "ed_edit_prop",
910  "ed_delete",
911  "ed_moveafter",
912  "ed_movebefore",
913  "ed_go",
914  "ed_class",
915  "ed_width",
916  "ed_align_left",
917  "ed_align_right",
918  "ed_align_center",
919  "ed_align_left_float",
920  "ed_align_right_float",
921  "ed_delete_item",
922  "ed_new_item_before",
923  "ed_new_item_after",
924  "ed_copy_clip",
925  "please_select",
926  "ed_split_page",
927  "ed_item_up",
928  "ed_item_down",
929  "ed_split_page_next",
930  "ed_enable",
931  "de_activate",
932  "ed_paste",
933  "ed_edit_multiple",
934  "ed_cut",
935  "ed_copy",
936  "ed_insert_templ",
937  "ed_click_to_add_pg",
938  "download"
939  );
940 
941  // collect lang vars from pc elements
942  $defs = $this->pc_definition->getPCDefinitions();
943  foreach ($defs as $def) {
944  $lang_vars[] = "pc_" . $def["pc_type"];
945  $lang_vars[] = "ed_insert_" . $def["pc_type"];
946 
947  $cl = $def["pc_class"];
948  $lvs = call_user_func($def["pc_class"] . '::getLangVars');
949  foreach ($lvs as $lv) {
950  $lang_vars[] = $lv;
951  }
952  }
953 
954  // workaround for #30561, should go to characteristic manager
955  $dummy_pc = new ilPCSectionGUI($this, null, "");
956  $dummy_pc->setStyleId($style_id);
957  foreach (["section", "table", "flist_li", "list_u", "list_o",
958  "table", "table_cell"] as $type) {
959  $dummy_pc->getCharacteristicsOfCurrentStyle([$type]);
960  foreach ($dummy_pc->getCharacteristics() as $char => $txt) {
961  $xml .= "<LV name=\"char_" . $type . "_" . $char . "\" value=\"" . $txt . "\"/>";
962  }
963  }
964  $type = "media_cont";
965  $dummy_pc = new ilPCMediaObjectGUI($this, null, "");
966  $dummy_pc->setStyleId($style_id);
967  $dummy_pc->getCharacteristicsOfCurrentStyle([$type]);
968  foreach ($dummy_pc->getCharacteristics() as $char => $txt) {
969  $xml .= "<LV name=\"char_" . $type . "_" . $char . "\" value=\"" . $txt . "\"/>";
970  }
971  foreach (["text_block", "heading1", "heading2", "heading3"] as $type) {
972  $dummy_pc = new ilPCParagraphGUI($this, null, "");
973  $dummy_pc->setStyleId($style_id);
974  $dummy_pc->getCharacteristicsOfCurrentStyle([$type]);
975  foreach ($dummy_pc->getCharacteristics() as $char => $txt) {
976  $xml .= "<LV name=\"char_" . $type . "_" . $char . "\" value=\"" . $txt . "\"/>";
977  }
978  }
979  foreach ($lang_vars as $lang_var) {
980  $xml .= $this->getLangVarXML($lang_var);
981  }
982  $xml .= "</LVs>";
983  return $xml;
984  }
985 
986  protected function getLangVarXML(string $var): string
987  {
988  $val = $this->lng->txt("cont_" . $var);
989  $val = str_replace('"', "&quot;", $val);
990  return "<LV name=\"$var\" value=\"" . $val . "\"/>";
991  }
992 
993  public function getFirstParagraphText(): string
994  {
995  return $this->pc_service->paragraph()->getFirstParagraphText($this);
996  }
997 
998  public function getParagraphForPCID(string $pcid): ?ilPCParagraph
999  {
1000  return $this->pc_service->paragraph()->getParagraphForPCID($this, $pcid);
1001  }
1002 
1003 
1010  // @todo: can we do this better
1011  public function setContainsIntLink(bool $a_contains_link): void
1012  {
1013  $this->contains_int_link = $a_contains_link;
1014  }
1015 
1020  // @todo: can we do this better
1021  public function containsIntLink(): bool
1022  {
1023  return $this->contains_int_link;
1024  }
1025 
1026  public function setImportMode(bool $a_val): void
1027  {
1028  $this->import_mode = $a_val;
1029  }
1030 
1031  public function getImportMode(): bool
1032  {
1033  return $this->import_mode;
1034  }
1035 
1036  public function needsImportParsing(?bool $a_parse = null): bool
1037  {
1038  if ($a_parse === true) {
1039  $this->needs_parsing = true;
1040  }
1041  if ($a_parse === false) {
1042  $this->needs_parsing = false;
1043  }
1044  return $this->needs_parsing;
1045  }
1046 
1047  // @todo: can we do this better
1048  public function setContainsQuestion(bool $a_val): void
1049  {
1050  $this->contains_question = $a_val;
1051  }
1052 
1053  public function getContainsQuestion(): bool
1054  {
1055  return $this->contains_question;
1056  }
1057 
1058 
1063  public function collectMediaObjects(bool $a_inline_only = true): array
1064  {
1065  $mob_manager = $this->pc_service->mediaObject();
1066  return $mob_manager->collectMediaObjects($this->getDomDoc(), $a_inline_only);
1067  }
1068 
1072  public function getInternalLinks(): array
1073  {
1074  return $this->link->getInternalLinks($this->getDomDoc());
1075  }
1076 
1081  public function getMultimediaXML(
1082  bool $offline = false
1083  ): string
1084  {
1085  $mob_manager = $this->pc_service->mediaObject();
1086  return $mob_manager->getMultimediaXML($this->getDomDoc(), $offline);
1087  }
1088 
1092  public function getMediaAliasElement(int $a_mob_id, int $a_nr = 1): string
1093  {
1094  $mob_manager = $this->pc_service->mediaObject();
1095  return $mob_manager->getMediaAliasElement(
1096  $this->getDomDoc(),
1097  $a_mob_id,
1098  $a_nr
1099  );
1100  }
1101 
1105  public function validateDom(bool $throw = false): ?array
1106  {
1107  $this->stripHierIDs();
1108 
1109  // possible fix for #14820
1110  //libxml_disable_entity_loader(false);
1111 
1112  $error = null;
1113  $this->dom_util->validate($this->dom, $error, $throw);
1114  return $error;
1115  }
1116 
1120  public function addHierIDs(): void
1121  {
1122  $this->content_id_manager->addHierIDsToDom();
1123  }
1124 
1125  public function getHierIds(): array
1126  {
1127  return $this->content_id_manager->getHierIds();
1128  }
1129 
1130  public function stripHierIDs(): void
1131  {
1132  $this->content_id_manager->stripHierIDsFromDom();
1133  }
1134 
1135  public function stripPCIDs(): void
1136  {
1137  $this->content_id_manager->stripPCIDs();
1138  }
1139 
1143  public function getHierIdsForPCIds(array $a_pc_ids): array
1144  {
1145  return $this->content_id_manager->getHierIdsForPCIds($a_pc_ids);
1146  }
1147 
1148  public function getHierIdForPcId(string $pcid): string
1149  {
1150  return $this->content_id_manager->getHierIdForPcId($pcid);
1151  }
1152 
1156  public function getPCIdsForHierIds(array $hier_ids): array
1157  {
1158  return $this->content_id_manager->getPCIdsForHierIds($hier_ids);
1159  }
1160 
1161  public function getPCIdForHierId(string $hier_id): string
1162  {
1163  return $this->content_id_manager->getPCIdForHierId($hier_id);
1164  }
1165 
1169  public function addFileSizes(): void
1170  {
1171  $this->pc_service->fileList()->addFileSizes($this->getDomDoc());
1172  }
1173 
1178  public function resolveIntLinks(array $a_link_map = null): bool
1179  {
1180  return $this->link->resolveIntLinks($this->getDomDoc(), $a_link_map);
1181  }
1182 
1187  public function resolveMediaAliases(
1188  array $a_mapping,
1189  bool $a_reuse_existing_by_import = false
1190  ): bool {
1191  return $this->pc_service->mediaObject()->resolveMediaAliases(
1192  $this,
1193  $a_mapping,
1194  $a_reuse_existing_by_import
1195  );
1196  }
1197 
1202  public function resolveIIMMediaAliases(array $a_mapping): bool
1203  {
1204  return $this->pc_service->interactiveImage()->resolveIIMMediaAliases(
1205  $this->getDomDoc(),
1206  $a_mapping
1207  );
1208  }
1209 
1214  public function resolveFileItems(array $a_mapping): bool
1215  {
1216  return $this->pc_service->fileList()->resolveFileItems(
1217  $this->getDomDoc(),
1218  $a_mapping
1219  );
1220  }
1221 
1226  public function resolveQuestionReferences(array $a_mapping): bool
1227  {
1228  $qm = $this->pc_service->question();
1229  return $qm->resolveQuestionReferences(
1230  $this->getDomDoc(),
1231  $a_mapping
1232  );
1233  }
1234 
1235 
1240  public function moveIntLinks(array $a_from_to): bool
1241  {
1242  $this->buildDom();
1243  $this->addHierIDs();
1244  return $this->link->moveIntLinks(
1245  $this->getDomDoc(),
1246  $a_from_to
1247  );
1248  }
1249 
1250 
1255  array $a_mapping,
1256  int $a_source_ref_id
1257  ): void {
1258  $this->buildDom();
1259 
1260  $tree = $this->tree;
1261  $this->log->debug("Handle repository links...");
1262 
1263  $defs = $this->pc_definition->getPCDefinitions();
1264  foreach ($defs as $def) {
1265  if (method_exists($def["pc_class"], 'afterRepositoryCopy')) {
1266  call_user_func($def["pc_class"] . '::afterRepositoryCopy', $this, $a_mapping, $a_source_ref_id);
1267  }
1268  }
1269 
1270  $this->link->handleRepositoryLinksOnCopy($this->getDomDoc(), $a_mapping, $a_source_ref_id, $tree);
1271  }
1272 
1273  public function setEmptyPageXml(): void
1274  {
1275  $this->setXMLContent("<PageObject></PageObject>");
1276  }
1277 
1281  public function createFromXML(): void
1282  {
1283  $empty = false;
1284  if ($this->getXMLContent() === "") {
1285  $this->setEmptyPageXml();
1286  $empty = true;
1287  }
1288  $content = $this->getXMLContent();
1289  $this->buildDom(true);
1290  $dom_doc = $this->getDomDoc();
1291 
1292  $errors = $this->validateDom(true);
1293 
1294  $iel = $this->containsDeactivatedElements($content);
1295  $inl = $this->containsIntLinks($content);
1296  // create object
1297  $this->db->insert("page_object", array(
1298  "page_id" => array("integer", $this->getId()),
1299  "parent_id" => array("integer", $this->getParentId()),
1300  "lang" => array("text", $this->getLanguage()),
1301  "content" => array("clob", $content),
1302  "parent_type" => array("text", $this->getParentType()),
1303  "create_user" => array("integer", $this->user->getId()),
1304  "last_change_user" => array("integer", $this->user->getId()),
1305  "active" => array("integer", (int) $this->getActive()),
1306  "activation_start" => array("timestamp", $this->getActivationStart()),
1307  "activation_end" => array("timestamp", $this->getActivationEnd()),
1308  "show_activation_info" => array("integer", (int) $this->getShowActivationInfo()),
1309  "inactive_elements" => array("integer", $iel),
1310  "int_links" => array("integer", $inl),
1311  "created" => array("timestamp", ilUtil::now()),
1312  "last_change" => array("timestamp", ilUtil::now()),
1313  "is_empty" => array("integer", $empty)
1314  ));
1315  // after update event
1316  $this->__afterUpdate($dom_doc, $content, true, $empty);
1317  }
1318 
1326  public function updateFromXML(): bool
1327  {
1328  $this->log->debug("ilPageObject, updateFromXML(): start, id: " . $this->getId());
1329 
1330  $content = $this->getXMLContent();
1331 
1332  $this->log->debug("ilPageObject, updateFromXML(): content: " . substr($content, 0, 100));
1333 
1334  $this->buildDom(true);
1335  $dom_doc = $this->getDomDoc();
1336 
1337  $errors = $this->validateDom(true);
1338 
1339  $iel = $this->containsDeactivatedElements($content);
1340  $inl = $this->containsIntLinks($content);
1341 
1342  $this->db->update("page_object", array(
1343  "content" => array("clob", $content),
1344  "parent_id" => array("integer", $this->getParentId()),
1345  "last_change_user" => array("integer", $this->user->getId()),
1346  "last_change" => array("timestamp", ilUtil::now()),
1347  "active" => array("integer", $this->getActive()),
1348  "activation_start" => array("timestamp", $this->getActivationStart()),
1349  "activation_end" => array("timestamp", $this->getActivationEnd()),
1350  "inactive_elements" => array("integer", $iel),
1351  "int_links" => array("integer", $inl),
1352  ), array(
1353  "page_id" => array("integer", $this->getId()),
1354  "parent_type" => array("text", $this->getParentType()),
1355  "lang" => array("text", $this->getLanguage())
1356  ));
1357 
1358  // after update event
1359  $this->__afterUpdate($dom_doc, $content);
1360 
1361  $this->log->debug("ilPageObject, updateFromXML(): end");
1362 
1363  return true;
1364  }
1365 
1370  final protected function __afterUpdate(
1371  DOMDocument $a_domdoc,
1372  string $a_xml,
1373  bool $a_creation = false,
1374  bool $a_empty = false
1375  ): void {
1376  // we do not need this if we are creating an empty page
1377  if (!$a_creation || !$a_empty) {
1378  // save internal link information
1379  // the page object is responsible to do this, since it "offers" the
1380  // internal link feature pc and page classes
1381  $this->saveInternalLinks($a_domdoc);
1382 
1383  // save style usage
1384  $this->saveStyleUsage($a_domdoc);
1385 
1386  // save estimated reading time
1387  $this->reading_time_manager->saveTime($this);
1388 
1389  // pc classes hook
1390  $defs = $this->pc_definition->getPCDefinitions();
1391  foreach ($defs as $def) {
1392  $cl = $def["pc_class"];
1393  call_user_func($def["pc_class"] . '::afterPageUpdate', $this, $a_domdoc, $a_xml, $a_creation);
1394  }
1395  }
1396 
1397  // call page hook
1398  $this->afterUpdate($a_domdoc, $a_xml);
1399 
1400  // call update listeners
1401  $this->callUpdateListeners();
1402  }
1403 
1407  public function afterUpdate(DOMDocument $domdoc, string $xml): void
1408  {
1409  }
1410 
1417  public function update(bool $a_validate = true, bool $a_no_history = false)
1418  {
1419  $this->log->debug("start..., id: " . $this->getId());
1420  $lm_set = new ilSetting("lm");
1421 
1422  // add missing pc ids
1423  if (!$this->checkPCIds()) {
1424  $this->insertPCIds();
1425  }
1426 
1427  // test validating
1428  if ($a_validate) {
1429  $this->log->debug($this->dom_util->dump($this->getDomDoc()->documentElement));
1430  $errors = $this->validateDom();
1431  }
1432  //var_dump($errors); exit;
1433  if (empty($errors) && !$this->getEditLock()) {
1434  $lock = $this->getEditLockInfo();
1435  $errors[0] = array(0 => 0,
1436  1 => $this->lng->txt("cont_not_saved_edit_lock_expired") . "<br />" .
1437  $this->lng->txt("obj_usr") . ": " .
1438  ilUserUtil::getNamePresentation($lock["edit_lock_user"]) . "<br />" .
1439  $this->lng->txt("content_until") . ": " .
1440  ilDatePresentation::formatDate(new ilDateTime($lock["edit_lock_until"], IL_CAL_UNIX))
1441  );
1442  }
1443 
1444  // check for duplicate pc ids
1445  $this->log->debug("checking duplicate ids");
1446  if ($this->hasDuplicatePCIds()) {
1447  $errors[0] = $this->lng->txt("cont_could_not_save_duplicate_pc_ids") .
1448  " (" . implode(", ", $this->getDuplicatePCIds()) . ")";
1449  }
1450 
1451  if (!empty($errors)) {
1452  $this->log->debug("ilPageObject, update(): errors: " . print_r($errors, true));
1453  }
1454 
1455  //echo "-".htmlentities($this->getXMLFromDom())."-"; exit;
1456  if (empty($errors)) {
1457  // @todo 1: is this page type or pc content type
1458  // related -> plugins should be able to hook in!?
1459 
1460  $this->log->debug("perform automatic modifications");
1462 
1463  // get xml content
1464  $content = $this->getXMLFromDom();
1465  $dom_doc = $this->getDomDoc();
1466 
1467  // this needs to be locked
1468 
1469  // write history entry
1470  $old_set = $this->db->query("SELECT * FROM page_object WHERE " .
1471  "page_id = " . $this->db->quote($this->getId(), "integer") . " AND " .
1472  "parent_type = " . $this->db->quote($this->getParentType(), "text") . " AND " .
1473  "lang = " . $this->db->quote($this->getLanguage(), "text"));
1474  $last_nr_set = $this->db->query("SELECT max(nr) as mnr FROM page_history WHERE " .
1475  "page_id = " . $this->db->quote($this->getId(), "integer") . " AND " .
1476  "parent_type = " . $this->db->quote($this->getParentType(), "text") . " AND " .
1477  "lang = " . $this->db->quote($this->getLanguage(), "text"));
1478  $last_nr = $this->db->fetchAssoc($last_nr_set);
1479  if ($old_rec = $this->db->fetchAssoc($old_set)) {
1480  // only save, if something has changed
1481  // added user id to the check for ilias 5.0, 7.10.2014
1482  if (($content != $old_rec["content"] || $this->user->getId() != $old_rec["last_change_user"]) &&
1483  !$a_no_history && !$this->history_saved && $lm_set->get("page_history", 1)) {
1484  if ($old_rec["content"] != "<PageObject></PageObject>") {
1485  $this->db->manipulateF(
1486  "DELETE FROM page_history WHERE " .
1487  "page_id = %s AND parent_type = %s AND hdate = %s AND lang = %s",
1488  array("integer", "text", "timestamp", "text"),
1489  array($old_rec["page_id"],
1490  $old_rec["parent_type"],
1491  $old_rec["last_change"],
1492  $old_rec["lang"]
1493  )
1494  );
1495 
1496  // the following lines are a workaround for
1497  // bug 6741
1498  $last_c = $old_rec["last_change"];
1499  if ($last_c == "") {
1500  $last_c = ilUtil::now();
1501  }
1502 
1503  $this->db->insert("page_history", array(
1504  "page_id" => array("integer", $old_rec["page_id"]),
1505  "parent_type" => array("text", $old_rec["parent_type"]),
1506  "lang" => array("text", $old_rec["lang"]),
1507  "hdate" => array("timestamp", $last_c),
1508  "parent_id" => array("integer", $old_rec["parent_id"]),
1509  "content" => array("clob", $old_rec["content"]),
1510  "user_id" => array("integer", $old_rec["last_change_user"]),
1511  "ilias_version" => array("text", ILIAS_VERSION_NUMERIC),
1512  "nr" => array("integer", (int) $last_nr["mnr"] + 1)
1513  ));
1514 
1515  $old_content = $old_rec["content"];
1516  $old_domdoc = new DOMDocument();
1517  $old_nr = $last_nr["mnr"] + 1;
1518  $old_domdoc->loadXML('<?xml version="1.0" encoding="UTF-8"?>' . $old_content);
1519 
1520  // after history entry creation event
1521  $this->log->debug("calling __afterHistoryEntry");
1522  $this->__afterHistoryEntry($old_domdoc, $old_content, $old_nr);
1523 
1524  // only save one time
1525  }
1526  $this->history_saved = true;
1527  }
1528  }
1529  //echo htmlentities($content);
1530  $em = (trim($content) == "<PageObject/>")
1531  ? 1
1532  : 0;
1533 
1534  // @todo: pass dom instead?
1535  $this->log->debug("checking deactivated elements");
1536  $iel = $this->containsDeactivatedElements($content);
1537  $this->log->debug("checking internal links");
1538  $inl = $this->containsIntLinks($content);
1539 
1540  $now = ilUtil::now();
1541  $this->lastchange = $now;
1542  $this->db->update("page_object", array(
1543  "content" => array("clob", $content),
1544  "parent_id" => array("integer", $this->getParentId()),
1545  "last_change_user" => array("integer", $this->user->getId()),
1546  "last_change" => array("timestamp", $now),
1547  "is_empty" => array("integer", $em),
1548  "active" => array("integer", $this->getActive()),
1549  "activation_start" => array("timestamp", $this->getActivationStart()),
1550  "activation_end" => array("timestamp", $this->getActivationEnd()),
1551  "show_activation_info" => array("integer", $this->getShowActivationInfo()),
1552  "inactive_elements" => array("integer", $iel),
1553  "int_links" => array("integer", $inl),
1554  ), array(
1555  "page_id" => array("integer", $this->getId()),
1556  "parent_type" => array("text", $this->getParentType()),
1557  "lang" => array("text", $this->getLanguage())
1558  ));
1559 
1560  // after update event
1561  $this->log->debug("calling __afterUpdate()");
1562  $this->__afterUpdate($dom_doc, $content);
1563 
1564  $this->log->debug(
1565  "...ending, updated and returning true, content: " . substr(
1566  $this->getXMLContent(),
1567  0,
1568  1000
1569  )
1570  );
1571 
1572  //echo "<br>PageObject::update:".htmlentities($this->getXMLContent()).":";
1573  return true;
1574  } else {
1575  return $errors;
1576  }
1577  }
1578 
1579  public function delete(): void
1580  {
1581  $copg_logger = ilLoggerFactory::getLogger('copg');
1582  $copg_logger->debug(
1583  "ilPageObject: Delete called for ID '" . $this->getId() . "'," .
1584  " parent type: '" . $this->getParentType() . "', " .
1585  " hist nr: '" . $this->old_nr . "', " .
1586  " lang: '" . $this->getLanguage() . "', "
1587  );
1588 
1589  $mobs = array();
1590  if (!$this->page_not_found) {
1591  $this->buildDom();
1592  $mobs = $this->collectMediaObjects(false);
1593  }
1595  $this->getParentType() . ":pg",
1596  $this->getId(),
1597  false,
1598  $this->getLanguage()
1599  );
1600 
1601  foreach ($mobs2 as $m) {
1602  if (!in_array($m, $mobs)) {
1603  $mobs[] = $m;
1604  }
1605  }
1606 
1607  $copg_logger->debug("ilPageObject: ... found " . count($mobs) . " media objects.");
1608 
1609  $this->__beforeDelete();
1610 
1611  // treat plugged content
1612  $this->handleDeleteContent();
1613 
1614  // delete style usages
1615  $this->deleteStyleUsages(false);
1616 
1617  // delete internal links
1618  $this->deleteInternalLinks();
1619 
1620  // delete all mob usages
1621  ilObjMediaObject::_deleteAllUsages($this->getParentType() . ":pg", $this->getId());
1622 
1623  // delete news
1624  if (!$this->isTranslationPage()) {
1626  $this->getParentId(),
1627  $this->getParentType(),
1628  $this->getId(),
1629  "pg"
1630  );
1631  }
1632 
1633  // delete page_object entry
1634  $and = $this->isTranslationPage()
1635  ? " AND lang = " . $this->db->quote($this->getLanguage(), "text")
1636  : "";
1637  $this->db->manipulate("DELETE FROM page_object " .
1638  "WHERE page_id = " . $this->db->quote($this->getId(), "integer") .
1639  " AND parent_type= " . $this->db->quote($this->getParentType(), "text") . $and);
1640 
1641  // delete media objects
1642  foreach ($mobs as $mob_id) {
1643  $copg_logger->debug("ilPageObject: ... processing mob " . $mob_id . ".");
1644 
1645  if (ilObject::_lookupType($mob_id) != 'mob') {
1646  $copg_logger->debug("ilPageObject: ... type mismatch. Ignoring mob " . $mob_id . ".");
1647  continue;
1648  }
1649 
1650  if (ilObject::_exists($mob_id)) {
1651  $copg_logger->debug("ilPageObject: ... delete mob " . $mob_id . ".");
1652 
1653  $mob_obj = new ilObjMediaObject($mob_id);
1654  $mob_obj->delete();
1655  } else {
1656  $copg_logger->debug("ilPageObject: ... missing mob " . $mob_id . ".");
1657  }
1658  }
1659 
1660  $this->__afterDelete();
1661  }
1662 
1663  protected function isTranslationPage(): bool
1664  {
1665  return !in_array($this->getLanguage(), ["", "-"]);
1666  }
1667 
1671  final protected function __beforeDelete(): void
1672  {
1673  // pc classes hook
1674  $defs = $this->pc_definition->getPCDefinitions();
1675  foreach ($defs as $def) {
1676  $cl = $def["pc_class"];
1677  call_user_func($def["pc_class"] . '::beforePageDelete', $this);
1678  }
1679  }
1680 
1681  final protected function __afterDelete(): void
1682  {
1683  $this->afterDelete();
1684  }
1685 
1686  protected function afterDelete(): void
1687  {
1688  }
1689 
1690  final protected function __afterHistoryEntry(
1691  DOMDocument $a_old_domdoc,
1692  string $a_old_content,
1693  int $a_old_nr
1694  ): void {
1695  // save style usage
1696  $this->saveStyleUsage($a_old_domdoc, $a_old_nr);
1697 
1698  // pc classes hook
1699  $defs = $this->pc_definition->getPCDefinitions();
1700  foreach ($defs as $def) {
1701  $cl = $def["pc_class"];
1702  call_user_func(
1703  $def["pc_class"] . '::afterPageHistoryEntry',
1704  $this,
1705  $a_old_domdoc,
1706  $a_old_content,
1707  $a_old_nr
1708  );
1709  }
1710  }
1711 
1715  public function saveStyleUsage(
1716  DOMDocument $a_domdoc,
1717  int $a_old_nr = 0
1718  ): void {
1719  $this->style_manager->saveStyleUsage(
1720  $this,
1721  $a_domdoc,
1722  $a_old_nr
1723  );
1724  }
1725 
1729  public function deleteStyleUsages(int $a_old_nr = 0): void
1730  {
1731  $this->style_manager->deleteStyleUsages($this, $a_old_nr);
1732  }
1733 
1739  public function getLastUpdateOfIncludedElements(): string
1740  {
1742  $this->getParentType() . ":pg",
1743  $this->getId()
1744  );
1745  $files = ilObjFile::_getFilesOfObject(
1746  $this->getParentType() . ":pg",
1747  $this->getId()
1748  );
1749  $objs = array_merge($mobs, $files);
1750  return ilObject::_getLastUpdateOfObjects($objs);
1751  }
1752 
1756  public function deleteInternalLinks(): void
1757  {
1758  $this->link->deleteInternalLinks($this);
1759  }
1760 
1761 
1766  public function saveInternalLinks(DOMDocument $a_domdoc): void
1767  {
1768  $this->link->saveInternalLinks(
1769  $this,
1770  $a_domdoc
1771  );
1772  }
1773 
1777  public function create(bool $a_import = false): void
1778  {
1779  $this->createFromXML();
1780  }
1781 
1788  public function deleteContent(
1789  string $a_hid,
1790  bool $a_update = true,
1791  string $a_pcid = "",
1792  bool $move_operation = false
1793  ) {
1794  $pm = $this->page_manager->content($this->getDomDoc());
1795  $pm->deleteContent($this, $a_hid, $a_pcid, $move_operation);
1796  if ($a_update) {
1797  return $this->update();
1798  }
1799  return true;
1800  }
1801 
1809  public function deleteContents(
1810  array $a_hids,
1811  bool $a_update = true,
1812  bool $a_self_ass = false,
1813  bool $move_operation = false
1814  ) {
1815  $pm = $this->page_manager->content($this->getDomDoc());
1816  $pm->deleteContents($this, $a_hids, $a_self_ass, $move_operation);
1817  if ($a_update) {
1818  return $this->update();
1819  }
1820  return true;
1821  }
1822 
1828  public function cutContents(array $a_hids)
1829  {
1830  $this->copyContents($a_hids);
1831  return $this->deleteContents(
1832  $a_hids,
1833  true,
1834  $this->getPageConfig()->getEnableSelfAssessment(),
1835  true
1836  );
1837  }
1838 
1842  public function copyContents(array $a_hids): void
1843  {
1844  $cm = $this->page_manager->content($this->getDomDoc());
1845  $cm->copyContents($a_hids, $this->user);
1846  }
1847 
1853  public function pasteContents(
1854  string $a_hier_id,
1855  bool $a_self_ass = false
1856  ) {
1857  $user = $this->user;
1858  $cm = $this->page_manager->content($this->getDomDoc());
1859  $cm->pasteContents(
1860  $user,
1861  $a_hier_id,
1862  $this,
1863  $a_self_ass
1864  );
1865  return $this->update();
1866  }
1867 
1875  public function switchEnableMultiple(
1876  array $a_hids,
1877  bool $a_update = true,
1878  bool $a_self_ass = false
1879  ) {
1880  $cm = $this->page_manager->content($this->getDomDoc());
1881  $cm->switchEnableMultiple($this, $a_hids, $a_self_ass);
1882  if ($a_update) {
1883  return $this->update();
1884  }
1885  return true;
1886  }
1887 
1891  public function insertContent(
1892  ilPageContent $a_cont_obj,
1893  string $a_pos,
1894  int $a_mode = IL_INSERT_AFTER,
1895  string $a_pcid = "",
1896  bool $remove_placeholder = true
1897  ): void {
1898  $cm = $this->page_manager->content($this->getDomDoc());
1899  $cm->insertContent(
1900  $a_cont_obj,
1901  $a_pos,
1902  $a_mode,
1903  $a_pcid,
1904  $remove_placeholder,
1905  $this->getPageConfig()->getEnablePCType("PlaceHolder")
1906  );
1907  }
1908 
1912  public function insertContentNode(
1913  DOMNode $a_cont_node,
1914  string $a_pos,
1915  int $a_mode = IL_INSERT_AFTER,
1916  string $a_pcid = ""
1917  ): void {
1918  $cm = $this->page_manager->content($this->getDomDoc());
1919  $cm->insertContentNode(
1920  $a_cont_node,
1921  $a_pos,
1922  $a_mode,
1923  $a_pcid
1924  );
1925  }
1926 
1927 
1940  public function moveContentAfter(
1941  string $a_source,
1942  string $a_target,
1943  string $a_spcid = "",
1944  string $a_tpcid = ""
1945  ) {
1946  $cm = $this->page_manager->content($this->getDomDoc());
1947  $cm->moveContentAfter(
1948  $this,
1949  $a_source,
1950  $a_target,
1951  $a_spcid,
1952  $a_tpcid
1953  );
1954  return $this->update();
1955  }
1956 
1963  public function insertInstIntoIDs(
1964  string $a_inst,
1965  bool $a_res_ref_to_obj_id = true
1966  ): void {
1967  $cm = $this->page_manager->content($this->getDomDoc());
1968  $cm->insertInstIntoIDs($a_inst, $a_res_ref_to_obj_id);
1969  }
1970 
1974  public function checkPCIds(): bool
1975  {
1976  return $this->content_id_manager->checkPCIds();
1977  }
1978 
1982  public function getAllPCIds(): array
1983  {
1984  return $this->content_id_manager->getAllPCIds();
1985  }
1986 
1987  public function hasDuplicatePCIds(): bool
1988  {
1989  return $this->content_id_manager->hasDuplicatePCIds();
1990  }
1991 
1996  public function getDuplicatePCIds(): array
1997  {
1998  return $this->content_id_manager->getDuplicatePCIds();
1999  }
2000 
2001  public function generatePCId(): string
2002  {
2003  return $this->content_id_manager->generatePCId();
2004  }
2005 
2009  public function insertPCIds(): void
2010  {
2011  $this->content_id_manager->insertPCIds();
2012  }
2013 
2014  public function sendParagraph(
2015  string $par_id,
2016  string $filename
2017  ): void {
2018  $this->pc_service->paragraph()->send(
2019  $this->getDomDoc(),
2020  $par_id,
2021  $filename
2022  );
2023  }
2024 
2025  public function registerOfflineHandler(object $handler): void
2026  {
2027  $this->offline_handler = $handler;
2028  }
2029 
2030  public function getOfflineHandler(): ?object
2031  {
2032  return $this->offline_handler;
2033  }
2034 
2038  public static function _lookupContainsDeactivatedElements(
2039  int $a_id,
2040  string $a_parent_type,
2041  string $a_lang = "-"
2042  ): bool {
2043  global $DIC;
2044 
2045  $db = $DIC->database();
2046 
2047  if ($a_lang == "") {
2048  $a_lang = "-";
2049  }
2050 
2051  $query = "SELECT * FROM page_object WHERE page_id = " .
2052  $db->quote($a_id, "integer") . " AND " .
2053  " parent_type = " . $db->quote($a_parent_type, "text") . " AND " .
2054  " lang = " . $db->quote($a_lang, "text") . " AND " .
2055  " inactive_elements = " . $db->quote(1, "integer");
2056  $obj_set = $db->query($query);
2057 
2058  if ($obj_rec = $obj_set->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
2059  return true;
2060  }
2061 
2062  return false;
2063  }
2064 
2068  public function containsDeactivatedElements(string $a_content): bool
2069  {
2070  if (strpos($a_content, " Enabled=\"False\"")) {
2071  return true;
2072  }
2073  return false;
2074  }
2075 
2079  public function getHistoryEntries(): array
2080  {
2081  $db = $this->db;
2082 
2083  $h_query = "SELECT * FROM page_history " .
2084  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2085  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
2086  " AND lang = " . $db->quote($this->getLanguage(), "text") .
2087  " ORDER BY hdate DESC";
2088 
2089  $hset = $db->query($h_query);
2090  $hentries = array();
2091 
2092  while ($hrec = $db->fetchAssoc($hset)) {
2093  $hrec["sortkey"] = (int) $hrec["nr"];
2094  $hrec["user"] = (int) $hrec["user_id"];
2095  $hentries[] = $hrec;
2096  }
2097  //var_dump($hentries);
2098  return $hentries;
2099  }
2100 
2104  public function getHistoryEntry(int $a_old_nr): ?array
2105  {
2106  $db = $this->db;
2107 
2108  $res = $db->queryF(
2109  "SELECT * FROM page_history " .
2110  " WHERE page_id = %s " .
2111  " AND parent_type = %s " .
2112  " AND nr = %s" .
2113  " AND lang = %s",
2114  array("integer", "text", "integer", "text"),
2115  array($this->getId(), $this->getParentType(), $a_old_nr, $this->getLanguage())
2116  );
2117  if ($hrec = $db->fetchAssoc($res)) {
2118  return $hrec;
2119  }
2120 
2121  return null;
2122  }
2123 
2129  public function getHistoryInfo(int $a_nr): array
2130  {
2131  $db = $this->db;
2132 
2133  // determine previous entry
2134  $and_nr = ($a_nr > 0)
2135  ? " AND nr < " . $db->quote($a_nr, "integer")
2136  : "";
2137  $res = $db->query("SELECT MAX(nr) mnr FROM page_history " .
2138  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2139  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
2140  " AND lang = " . $db->quote($this->getLanguage(), "text") .
2141  $and_nr);
2142  $row = $db->fetchAssoc($res);
2143  if ($row["mnr"] > 0) {
2144  $res = $db->query("SELECT * FROM page_history " .
2145  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2146  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
2147  " AND lang = " . $db->quote($this->getLanguage(), "text") .
2148  " AND nr = " . $db->quote((int) $row["mnr"], "integer"));
2149  $row = $db->fetchAssoc($res);
2150  $ret["previous"] = $row;
2151  }
2152 
2153  // determine next entry
2154  $res = $db->query("SELECT MIN(nr) mnr FROM page_history " .
2155  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2156  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
2157  " AND lang = " . $db->quote($this->getLanguage(), "text") .
2158  " AND nr > " . $db->quote($a_nr, "integer"));
2159  $row = $db->fetchAssoc($res);
2160  if ($row["mnr"] > 0) {
2161  $res = $db->query("SELECT * FROM page_history " .
2162  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2163  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
2164  " AND lang = " . $db->quote($this->getLanguage(), "text") .
2165  " AND nr = " . $db->quote((int) $row["mnr"], "integer"));
2166  $row = $db->fetchAssoc($res);
2167  $ret["next"] = $row;
2168  }
2169 
2170  // current
2171  if ($a_nr > 0) {
2172  $res = $db->query("SELECT * FROM page_history " .
2173  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2174  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
2175  " AND lang = " . $db->quote($this->getLanguage(), "text") .
2176  " AND nr = " . $db->quote($a_nr, "integer"));
2177  } else {
2178  $res = $db->query("SELECT page_id, last_change hdate, parent_type, parent_id, last_change_user user_id, content, lang FROM page_object " .
2179  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2180  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
2181  " AND lang = " . $db->quote($this->getLanguage(), "text"));
2182  }
2183  $row = $db->fetchAssoc($res);
2184  $ret["current"] = $row;
2185 
2186  return $ret;
2187  }
2188 
2189  public function preparePageForCompare(ilPageObject $page): void
2190  {
2191  }
2192 
2196  public function increaseViewCnt(): void
2197  {
2198  $db = $this->db;
2199 
2200  $db->manipulate("UPDATE page_object " .
2201  " SET view_cnt = view_cnt + 1 " .
2202  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2203  " AND parent_type = " . $db->quote($this->getParentType(), "text") .
2204  " AND lang = " . $db->quote($this->getLanguage(), "text"));
2205  }
2206 
2213  public static function getRecentChanges(
2214  string $a_parent_type,
2215  int $a_parent_id,
2216  int $a_period = 30,
2217  string $a_lang = ""
2218  ): array {
2219  global $DIC;
2220 
2221  $db = $DIC->database();
2222 
2223  $and_lang = "";
2224  if ($a_lang != "") {
2225  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
2226  }
2227 
2228  $page_changes = array();
2229  $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
2230  $q = "SELECT * FROM page_object " .
2231  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
2232  " AND parent_type = " . $db->quote($a_parent_type, "text") .
2233  " AND last_change >= " . $db->quote($limit_ts, "timestamp") . $and_lang;
2234  // " AND (TO_DAYS(now()) - TO_DAYS(last_change)) <= ".((int)$a_period);
2235  $set = $db->query($q);
2236  while ($page = $db->fetchAssoc($set)) {
2237  $page_changes[] = array(
2238  "date" => $page["last_change"],
2239  "id" => $page["page_id"],
2240  "lang" => $page["lang"],
2241  "type" => "page",
2242  "user" => $page["last_change_user"]
2243  );
2244  }
2245 
2246  $and_str = "";
2247  if ($a_period > 0) {
2248  $limit_ts = date('Y-m-d H:i:s', time() - ($a_period * 24 * 60 * 60));
2249  $and_str = " AND hdate >= " . $db->quote($limit_ts, "timestamp") . " ";
2250  }
2251 
2252  $q = "SELECT * FROM page_history " .
2253  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
2254  " AND parent_type = " . $db->quote($a_parent_type, "text") .
2255  $and_str . $and_lang;
2256  $set = $db->query($q);
2257  while ($page = $db->fetchAssoc($set)) {
2258  $page_changes[] = array(
2259  "date" => $page["hdate"],
2260  "id" => $page["page_id"],
2261  "lang" => $page["lang"],
2262  "type" => "hist",
2263  "nr" => $page["nr"],
2264  "user" => $page["user_id"]
2265  );
2266  }
2267 
2268  $page_changes = ilArrayUtil::sortArray($page_changes, "date", "desc");
2269 
2270  return $page_changes;
2271  }
2272 
2276  public static function getAllPages(
2277  string $a_parent_type,
2278  int $a_parent_id,
2279  string $a_lang = "-"
2280  ): array {
2281  global $DIC;
2282 
2283  $db = $DIC->database();
2284 
2285  $and_lang = "";
2286  if ($a_lang != "") {
2287  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
2288  }
2289 
2290  $q = "SELECT * FROM page_object " .
2291  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
2292  " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang;
2293  $set = $db->query($q);
2294  $pages = array();
2295  while ($page = $db->fetchAssoc($set)) {
2296  $key_add = ($a_lang == "")
2297  ? ":" . $page["lang"]
2298  : "";
2299  $pages[$page["page_id"] . $key_add] = array(
2300  "date" => $page["last_change"],
2301  "id" => $page["page_id"],
2302  "lang" => $page["lang"],
2303  "user" => $page["last_change_user"]
2304  );
2305  }
2306 
2307  return $pages;
2308  }
2309 
2313  public static function getNewPages(
2314  string $a_parent_type,
2315  int $a_parent_id,
2316  string $a_lang = "-"
2317  ): array {
2318  global $DIC;
2319 
2320  $db = $DIC->database();
2321 
2322  $and_lang = "";
2323  if ($a_lang != "") {
2324  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
2325  }
2326 
2327  $pages = array();
2328 
2329  $q = "SELECT * FROM page_object " .
2330  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
2331  " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang .
2332  " ORDER BY created DESC";
2333  $set = $db->query($q);
2334  while ($page = $db->fetchAssoc($set)) {
2335  if ($page["created"] != "") {
2336  $pages[] = array(
2337  "created" => $page["created"],
2338  "id" => $page["page_id"],
2339  "lang" => $page["lang"],
2340  "user" => $page["create_user"],
2341  );
2342  }
2343  }
2344 
2345  return $pages;
2346  }
2347 
2353  public static function getParentObjectContributors(
2354  string $a_parent_type,
2355  int $a_parent_id,
2356  string $a_lang = "-"
2357  ): array {
2358  global $DIC;
2359 
2360  $db = $DIC->database();
2361 
2362  $and_lang = "";
2363  if ($a_lang != "") {
2364  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
2365  }
2366 
2367  $contributors = array();
2368  $set = $db->queryF(
2369  "SELECT last_change_user, lang, page_id FROM page_object " .
2370  " WHERE parent_id = %s AND parent_type = %s " .
2371  " AND last_change_user != %s" . $and_lang,
2372  array("integer", "text", "integer"),
2373  array($a_parent_id, $a_parent_type, 0)
2374  );
2375 
2376  while ($page = $db->fetchAssoc($set)) {
2377  if ($a_lang == "") {
2378  $contributors[$page["last_change_user"]][$page["page_id"]][$page["lang"]] = 1;
2379  } else {
2380  $contributors[$page["last_change_user"]][$page["page_id"]] = 1;
2381  }
2382  }
2383 
2384  $set = $db->queryF(
2385  "SELECT count(*) as cnt, lang, page_id, user_id FROM page_history " .
2386  " WHERE parent_id = %s AND parent_type = %s AND user_id != %s " . $and_lang .
2387  " GROUP BY page_id, user_id, lang ",
2388  array("integer", "text", "integer"),
2389  array($a_parent_id, $a_parent_type, 0)
2390  );
2391  while ($hpage = $db->fetchAssoc($set)) {
2392  if ($a_lang == "") {
2393  $contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] =
2394  ($contributors[$hpage["user_id"]][$hpage["page_id"]][$hpage["lang"]] ?? 0) + $hpage["cnt"];
2395  } else {
2396  $contributors[$hpage["user_id"]][$hpage["page_id"]] =
2397  ($contributors[$hpage["user_id"]][$hpage["page_id"]] ?? 0) + $hpage["cnt"];
2398  }
2399  }
2400 
2401  $c = array();
2402  foreach ($contributors as $k => $co) {
2403  if (ilObject::_lookupType($k) == "usr") {
2404  $name = ilObjUser::_lookupName($k);
2405  $c[] = array("user_id" => $k,
2406  "pages" => $co,
2407  "lastname" => $name["lastname"],
2408  "firstname" => $name["firstname"]
2409  );
2410  }
2411  }
2412 
2413  return $c;
2414  }
2415 
2419  public static function getPageContributors(
2420  string $a_parent_type,
2421  int $a_page_id,
2422  string $a_lang = "-"
2423  ): array {
2424  global $DIC;
2425 
2426  $db = $DIC->database();
2427 
2428  $and_lang = "";
2429  if ($a_lang != "") {
2430  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
2431  }
2432 
2433  $contributors = array();
2434  $set = $db->queryF(
2435  "SELECT last_change_user, lang FROM page_object " .
2436  " WHERE page_id = %s AND parent_type = %s " .
2437  " AND last_change_user != %s" . $and_lang,
2438  array("integer", "text", "integer"),
2439  array($a_page_id, $a_parent_type, 0)
2440  );
2441 
2442  while ($page = $db->fetchAssoc($set)) {
2443  if ($a_lang == "") {
2444  $contributors[$page["last_change_user"]][$page["lang"]] = 1;
2445  } else {
2446  $contributors[$page["last_change_user"]] = 1;
2447  }
2448  }
2449 
2450  $set = $db->queryF(
2451  "SELECT count(*) as cnt, lang, page_id, user_id FROM page_history " .
2452  " WHERE page_id = %s AND parent_type = %s AND user_id != %s " . $and_lang .
2453  " GROUP BY user_id, page_id, lang ",
2454  array("integer", "text", "integer"),
2455  array($a_page_id, $a_parent_type, 0)
2456  );
2457  while ($hpage = $db->fetchAssoc($set)) {
2458  if ($a_lang === "") {
2459  $contributors[$hpage["user_id"]][$page["lang"]] =
2460  ($contributors[$hpage["user_id"]][$page["lang"]] ?? 0) + $hpage["cnt"];
2461  } else {
2462  $contributors[$hpage["user_id"]] =
2463  ($contributors[$hpage["user_id"]] ?? 0) + $hpage["cnt"];
2464  }
2465  }
2466 
2467  $c = array();
2468  foreach ($contributors as $k => $co) {
2469  $name = ilObjUser::_lookupName($k);
2470  $c[] = array("user_id" => $k,
2471  "pages" => $co,
2472  "lastname" => $name["lastname"],
2473  "firstname" => $name["firstname"]
2474  );
2475  }
2476 
2477  return $c;
2478  }
2479 
2483  public function writeRenderedContent(
2484  string $a_content,
2485  string $a_md5
2486  ): void {
2487  global $DIC;
2488 
2489  $db = $DIC->database();
2490 
2491  $db->update("page_object", array(
2492  "rendered_content" => array("clob", $a_content),
2493  "render_md5" => array("text", $a_md5),
2494  "rendered_time" => array("timestamp", ilUtil::now())
2495  ), array(
2496  "page_id" => array("integer", $this->getId()),
2497  "lang" => array("text", $this->getLanguage()),
2498  "parent_type" => array("text", $this->getParentType())
2499  ));
2500  }
2501 
2505  public static function getPagesWithLinks(
2506  string $a_parent_type,
2507  int $a_parent_id,
2508  string $a_lang = "-"
2509  ): array {
2510  global $DIC;
2511 
2512  $db = $DIC->database();
2513 
2514  $and_lang = "";
2515  if ($a_lang != "") {
2516  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
2517  }
2518 
2519  $q = "SELECT * FROM page_object " .
2520  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
2521  " AND parent_type = " . $db->quote($a_parent_type, "text") .
2522  " AND int_links = " . $db->quote(1, "integer") . $and_lang;
2523  $set = $db->query($q);
2524  $pages = array();
2525  while ($page = $db->fetchAssoc($set)) {
2526  $key_add = ($a_lang == "")
2527  ? ":" . $page["lang"]
2528  : "";
2529  $pages[$page["page_id"] . $key_add] = array(
2530  "date" => $page["last_change"],
2531  "id" => $page["page_id"],
2532  "lang" => $page["lang"],
2533  "user" => $page["last_change_user"]
2534  );
2535  }
2536 
2537  return $pages;
2538  }
2539 
2543  public function containsIntLinks(string $a_content): bool
2544  {
2545  if (strpos($a_content, "IntLink")) {
2546  return true;
2547  }
2548  return false;
2549  }
2550 
2554  public function performAutomaticModifications(): void
2555  {
2556  }
2557 
2558  protected function getContentManager(): \ILIAS\COPage\Page\PageContentManager
2559  {
2560  $this->buildDom();
2561  return $this->page_manager->content($this->getDomDoc());
2562  }
2563 
2567  public function saveInitialOpenedContent(
2568  string $a_type,
2569  int $a_id,
2570  string $a_target
2571  ): void {
2572  $cm = $this->getContentManager();
2573  $cm->setInitialOpenedContent($a_type, $a_id, $a_target);
2574  $this->update();
2575  }
2576 
2580  public function getInitialOpenedContent(): array
2581  {
2582  $cm = $this->getContentManager();
2583  return $cm->getInitialOpenedContent();
2584  }
2585 
2592  public function beforePageContentUpdate(ilPageContent $a_page_content): void
2593  {
2594  }
2595 
2604  public function copy(
2605  int $a_id,
2606  string $a_parent_type = "",
2607  int $a_new_parent_id = 0,
2608  bool $a_clone_mobs = false,
2609  int $obj_copy_id = 0,
2610  bool $overwrite_existing = true
2611  ): void {
2612  if ($a_parent_type == "") {
2613  $a_parent_type = $this->getParentType();
2614  if ($a_new_parent_id == 0) {
2615  $a_new_parent_id = $this->getParentId();
2616  }
2617  }
2618 
2619  foreach (self::lookupTranslations($this->getParentType(), $this->getId()) as $l) {
2620  $existed = false;
2621  $orig_page = ilPageObjectFactory::getInstance($this->getParentType(), $this->getId(), 0, $l);
2622  if (ilPageObject::_exists($a_parent_type, $a_id, $l)) {
2623  if (!$overwrite_existing) {
2624  continue;
2625  }
2626  $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, $a_id, 0, $l);
2627  $existed = true;
2628  } else {
2629  $new_page_object = ilPageObjectFactory::getInstance($a_parent_type, 0, 0, $l);
2630  $new_page_object->setParentId($a_new_parent_id);
2631  $new_page_object->setId($a_id);
2632  }
2633  $new_page_object->setXMLContent($orig_page->copyXMLContent($a_clone_mobs, $a_new_parent_id, $obj_copy_id));
2634  $new_page_object->setActive($orig_page->getActive());
2635  $new_page_object->setActivationStart($orig_page->getActivationStart());
2636  $new_page_object->setActivationEnd($orig_page->getActivationEnd());
2637  $this->setCopyProperties($new_page_object);
2638  if ($existed) {
2639  $new_page_object->buildDom();
2640  $new_page_object->update();
2641  } else {
2642  $new_page_object->create(false);
2643  }
2644  }
2645  }
2646 
2647  protected function setCopyProperties(ilPageObject $new_page): void
2648  {
2649  }
2650 
2651 
2655  public static function lookupTranslations(
2656  string $a_parent_type,
2657  int $a_id
2658  ): array {
2659  global $DIC;
2660 
2661  $db = $DIC->database();
2662 
2663  $set = $db->query(
2664  "SELECT lang FROM page_object " .
2665  " WHERE page_id = " . $db->quote($a_id, "integer") .
2666  " AND parent_type = " . $db->quote($a_parent_type, "text")
2667  );
2668  $langs = array();
2669  while ($rec = $db->fetchAssoc($set)) {
2670  $langs[] = $rec["lang"];
2671  }
2672  return $langs;
2673  }
2674 
2678  public function copyPageToTranslation(
2679  string $a_target_lang
2680  ): void {
2681  $transl_page = ilPageObjectFactory::getInstance(
2682  $this->getParentType(),
2683  0,
2684  0,
2685  $a_target_lang
2686  );
2687  $this->setTranslationProperties($transl_page);
2688  $transl_page->create(false);
2689  }
2690 
2691  protected function setTranslationProperties(self $transl_page): void
2692  {
2693  $transl_page->setId($this->getId());
2694  $transl_page->setParentId($this->getParentId());
2695  $transl_page->setXMLContent($this->copyXmlContent());
2696  $transl_page->setActive($this->getActive());
2697  $transl_page->setActivationStart($this->getActivationStart());
2698  $transl_page->setActivationEnd($this->getActivationEnd());
2699  }
2700 
2701 
2705 
2709  public function getEditLock(): bool
2710  {
2711  $db = $this->db;
2712  $user = $this->user;
2713 
2714  $min = $this->getEffectiveEditLockTime();
2715  if ($min > 0) {
2716  // try to set the lock for the user
2717  $ts = time();
2718  $db->manipulate(
2719  "UPDATE page_object SET " .
2720  " edit_lock_user = " . $db->quote($user->getId(), "integer") . "," .
2721  " edit_lock_ts = " . $db->quote($ts, "integer") .
2722  " WHERE (edit_lock_user = " . $db->quote($user->getId(), "integer") . " OR " .
2723  " edit_lock_ts < " . $db->quote(time() - ($min * 60), "integer") . ") " .
2724  " AND page_id = " . $db->quote($this->getId(), "integer") .
2725  " AND parent_type = " . $db->quote($this->getParentType(), "text")
2726  );
2727 
2728  $set = $db->query(
2729  "SELECT edit_lock_user FROM page_object " .
2730  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2731  " AND parent_type = " . $db->quote($this->getParentType(), "text")
2732  );
2733  $rec = $db->fetchAssoc($set);
2734  if ($rec["edit_lock_user"] != $user->getId()) {
2735  return false;
2736  }
2737  }
2738 
2739  return true;
2740  }
2741 
2745  public function releasePageLock(): bool
2746  {
2747  $db = $this->db;
2748  $user = $this->user;
2749  $aset = new ilSetting("adve");
2750 
2751  $min = (int) $aset->get("block_mode_minutes");
2752  if ($min > 0) {
2753  // try to set the lock for the user
2754  $ts = time();
2755  $db->manipulate(
2756  "UPDATE page_object SET " .
2757  " edit_lock_user = " . $db->quote($user->getId(), "integer") . "," .
2758  " edit_lock_ts = 0" .
2759  " WHERE edit_lock_user = " . $db->quote($user->getId(), "integer") .
2760  " AND page_id = " . $db->quote($this->getId(), "integer") .
2761  " AND parent_type = " . $db->quote($this->getParentType(), "text")
2762  );
2763 
2764  $set = $db->query(
2765  "SELECT edit_lock_user FROM page_object " .
2766  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2767  " AND parent_type = " . $db->quote($this->getParentType(), "text")
2768  );
2769  $rec = $db->fetchAssoc($set);
2770  if ($rec["edit_lock_user"] != $user->getId()) {
2771  return false;
2772  }
2773  }
2774 
2775  return true;
2776  }
2777 
2781  public function getEditLockInfo(): array
2782  {
2783  $db = $this->db;
2784 
2785  $aset = new ilSetting("adve");
2786  $min = (int) $aset->get("block_mode_minutes");
2787 
2788  $set = $db->query(
2789  "SELECT edit_lock_user, edit_lock_ts FROM page_object " .
2790  " WHERE page_id = " . $db->quote($this->getId(), "integer") .
2791  " AND parent_type = " . $db->quote($this->getParentType(), "text")
2792  );
2793  $rec = $db->fetchAssoc($set);
2794  $rec["edit_lock_until"] = $rec["edit_lock_ts"] + $min * 60;
2795 
2796  return $rec;
2797  }
2798 
2803  public static function truncateHTML(
2804  string $a_text,
2805  int $a_length = 100,
2806  string $a_ending = '...',
2807  bool $a_exact = false,
2808  bool $a_consider_html = true
2809  ): string {
2810  $open_tags = [];
2811  if ($a_consider_html) {
2812  // if the plain text is shorter than the maximum length, return the whole text
2813  if (strlen(preg_replace('/<.*?>/', '', $a_text)) <= $a_length) {
2814  return $a_text;
2815  }
2816 
2817  // splits all html-tags to scanable lines
2818  $total_length = strlen($a_ending);
2819  $open_tags = array();
2820  $truncate = '';
2821  preg_match_all('/(<.+?>)?([^<>]*)/s', $a_text, $lines, PREG_SET_ORDER);
2822  foreach ($lines as $line_matchings) {
2823  // if there is any html-tag in this line, handle it and add it (uncounted) to the output
2824  if (!empty($line_matchings[1])) {
2825  // if it's an "empty element" with or without xhtml-conform closing slash
2826  if (preg_match(
2827  '/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is',
2828  $line_matchings[1]
2829  )) {
2830  // do nothing
2831  } // if tag is a closing tag
2832  elseif (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line_matchings[1], $tag_matchings)) {
2833  // delete tag from $open_tags list
2834  $pos = array_search($tag_matchings[1], $open_tags);
2835  if ($pos !== false) {
2836  unset($open_tags[$pos]);
2837  }
2838  } // if tag is an opening tag
2839  elseif (preg_match('/^<\s*([^\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings)) {
2840  // add tag to the beginning of $open_tags list
2841  array_unshift($open_tags, strtolower($tag_matchings[1]));
2842  }
2843  // add html-tag to $truncate'd text
2844  $truncate .= $line_matchings[1];
2845  }
2846 
2847  // calculate the length of the plain text part of the line; handle entities as one character
2848  $content_length = strlen(preg_replace(
2849  '/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i',
2850  ' ',
2851  $line_matchings[2]
2852  ));
2853  if ($total_length + $content_length > $a_length) {
2854  // the number of characters which are left
2855  $left = $a_length - $total_length;
2856  $entities_length = 0;
2857  // search for html entities
2858  if (preg_match_all(
2859  '/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i',
2860  $line_matchings[2],
2861  $entities,
2862  PREG_OFFSET_CAPTURE
2863  )) {
2864  // calculate the real length of all entities in the legal range
2865  foreach ($entities[0] as $entity) {
2866  if ($entity[1] + 1 - $entities_length <= $left) {
2867  $left--;
2868  $entities_length += strlen($entity[0]);
2869  } else {
2870  // no more characters left
2871  break;
2872  }
2873  }
2874  }
2875 
2876  // $truncate .= substr($line_matchings[2], 0, $left+$entities_length);
2877  $truncate .= ilStr::shortenText($line_matchings[2], 0, $left + $entities_length);
2878 
2879  // maximum lenght is reached, so get off the loop
2880  break;
2881  } else {
2882  $truncate .= $line_matchings[2];
2883  $total_length += $content_length;
2884  }
2885 
2886  // if the maximum length is reached, get off the loop
2887  if ($total_length >= $a_length) {
2888  break;
2889  }
2890  }
2891  } else {
2892  if (strlen($a_text) <= $a_length) {
2893  return $a_text;
2894  } else {
2895  // $truncate = substr($a_text, 0, $a_length - strlen($a_ending));
2896  $truncate = ilStr::shortenText($a_text, 0, $a_length - strlen($a_ending));
2897  }
2898  }
2899 
2900  // THIS IS BUGGY AS IT MIGHT BREAK AN OPEN TAG AT THE END
2901  if (!count($open_tags)) {
2902  // if the words shouldn't be cut in the middle...
2903  if (!$a_exact) {
2904  // ...search the last occurance of a space...
2905  $spacepos = strrpos($truncate, ' ');
2906  if ($spacepos !== false) {
2907  // ...and cut the text in this position
2908  // $truncate = substr($truncate, 0, $spacepos);
2909  $truncate = ilStr::shortenText($truncate, 0, $spacepos);
2910  }
2911  }
2912  }
2913 
2914  // add the defined ending to the text
2915  $truncate .= $a_ending;
2916 
2917  if ($a_consider_html) {
2918  // close all unclosed html-tags
2919  foreach ($open_tags as $tag) {
2920  $truncate .= '</' . $tag . '>';
2921  }
2922  }
2923 
2924  return $truncate;
2925  }
2926 
2931  public function getContentTemplates(): array
2932  {
2933  return array();
2934  }
2935 
2939  public static function getLastChangeByParent(
2940  string $a_parent_type,
2941  int $a_parent_id,
2942  string $a_lang = ""
2943  ): string {
2944  global $DIC;
2945 
2946  $db = $DIC->database();
2947 
2948  $and_lang = "";
2949  if ($a_lang != "") {
2950  $and_lang = " AND lang = " . $db->quote($a_lang, "text");
2951  }
2952 
2953  $db->setLimit(1, 0);
2954  $q = "SELECT last_change FROM page_object " .
2955  " WHERE parent_id = " . $db->quote($a_parent_id, "integer") .
2956  " AND parent_type = " . $db->quote($a_parent_type, "text") . $and_lang .
2957  " ORDER BY last_change DESC";
2958 
2959  $set = $db->query($q);
2960  $rec = $db->fetchAssoc($set);
2961 
2962  return $rec["last_change"];
2963  }
2964 
2965  public function getEffectiveEditLockTime(): int
2966  {
2967  if ($this->getPageConfig()->getEditLockSupport() == false) {
2968  return 0;
2969  }
2970 
2971  $aset = new ilSetting("adve");
2972  $min = (int) $aset->get("block_mode_minutes");
2973 
2974  return $min;
2975  }
2976 
2981  public function resolveResources(array $ref_mapping): bool
2982  {
2983  return ilPCResources::resolveResources($this, $ref_mapping);
2984  }
2985 
2989  public function getRepoObjId(): ?int
2990  {
2991  return $this->getParentId();
2992  }
2993 
2998  public function getPCModel(): array
2999  {
3000  $model = [];
3001  /*
3002  $this->log->debug("--- Get page model start");
3003  $model = [];
3004  foreach ($this->getAllPCIds() as $pc_id) {
3005  $co = $this->getContentObjectForPcId($pc_id);
3006  if ($co !== null) {
3007  $co_model = $co->getModel();
3008  if ($co_model !== null) {
3009  $model[$pc_id] = $co_model;
3010  }
3011  }
3012  }
3013  $this->log->debug("--- Get page model end");
3014  */
3015 
3016  $config = $this->getPageConfig();
3017  foreach ($this->pc_definition->getPCDefinitions() as $def) {
3018  $model_provider = $this->pc_definition->getPCModelProviderByName($def["name"]);
3019  if ($config->getEnablePCType($def["name"]) || $def["name"] === "PlaceHolder") {
3020  if (!is_null($model_provider)) {
3021  foreach ($model_provider->getModels(
3022  $this->dom_util,
3023  $this
3024  ) as $pc_id => $co_model) {
3025  $model[$pc_id] = $co_model;
3026  }
3027  }
3028  }
3029  }
3030  return $model;
3031  }
3032 
3040  public function assignCharacteristic(
3041  array $targets,
3042  string $char_par,
3043  string $char_sec,
3044  string $char_med
3045  ) {
3046  if (is_array($targets)) {
3047  foreach ($targets as $t) {
3048  $tarr = explode(":", $t);
3049  $cont_obj = $this->getContentObject($tarr[0], $tarr[1]);
3050  if (is_object($cont_obj) && $cont_obj->getType() == "par") {
3051  $cont_obj->setCharacteristic($char_par);
3052  }
3053  if (is_object($cont_obj) && $cont_obj->getType() == "sec") {
3054  $cont_obj->setCharacteristic($char_sec);
3055  }
3056  if (is_object($cont_obj) && $cont_obj->getType() == "media") {
3057  $cont_obj->setClass($char_med);
3058  }
3059  }
3060  return $this->update();
3061  }
3062  return true;
3063  }
3064 }
assignCharacteristic(array $targets, string $char_par, string $char_sec, string $char_med)
Assign characteristic.
getLastUpdateOfIncludedElements()
Get last update of included elements (media objects and files).
setRenderedContent(string $a_renderedcontent)
performAutomaticModifications()
Perform automatic modifications (may be overwritten by sub classes)
getActive(bool $a_check_scheduled_activation=false)
static _lookupActive(int $a_id, string $a_parent_type, bool $a_check_scheduled_activation=false, string $a_lang="-")
lookup activation status
checkPCIds()
Check, whether (all) page content hashes are set.
static resolveResources(ilPageObject $page, array $ref_mappings)
cutContents(array $a_hids)
Copy contents to clipboard and cut them from the page.
getContentDomNode(string $a_hier_id, string $a_pc_id="")
increaseViewCnt()
Increase view cnt.
copyPageToTranslation(string $a_target_lang)
Copy page to translation.
getAllPCIds()
Get all pc ids.
getLangVarXML(string $var)
$res
Definition: ltiservices.php:69
getPCModel()
Get page component model.
updateFromXML()
Updates page object with current xml content This function is currently (8 beta) called by: ...
getHistoryInfo(int $a_nr)
Get information about a history entry, its predecessor and its successor.
__beforeDelete()
Before deletion handler (internal).
releasePageLock()
Release page lock.
addFileSizes()
add file sizes
validateDom(bool $throw=false)
Validate the page content agains page DTD.
setContainsQuestion(bool $a_val)
resolveFileItems(array $a_mapping)
Resolve file items (after import)
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false, ilObjUser $user=null,)
setPageConfig(ilPageConfig $a_val)
setCopyProperties(ilPageObject $new_page)
ILIAS COPage ID ContentIdManager $content_id_manager
getDuplicatePCIds()
Get all duplicate PC Ids.
appendXMLContent(string $a_xml)
append xml content to page setXMLContent must be called before and the same encoding must be us...
buildDom(bool $a_force=false)
static getParentObjectContributors(string $a_parent_type, int $a_parent_id, string $a_lang="-")
Get all contributors for parent object.
create(bool $a_import=false)
create new page (with current xml data)
const IL_CAL_DATETIME
setTranslationProperties(self $transl_page)
manipulateF(string $query, array $types, array $values)
ILIAS COPage PC DomainService $pc_service
setImportMode(bool $a_val)
static deleteNewsOfContext(int $a_context_obj_id, string $a_context_obj_type, int $a_context_sub_obj_id=0, string $a_context_sub_obj_type="")
Delete all news of a context.
static getLogger(string $a_component_id)
Get component logger.
getHierIdForPcId(string $pcid)
setParentId(int $a_id)
static getPagesWithLinks(string $a_parent_type, int $a_parent_id, string $a_lang="-")
Get all pages for parent object that contain internal links.
static _isScheduledActivation(int $a_id, string $a_parent_type, string $a_lang="-")
Check whether page is activated by time schedule.
getDomNodeForPCId(string $pc_id)
ILIAS COPage ReadingTime ReadingTimeManager $reading_time_manager
fetchAssoc(ilDBStatement $statement)
static _before(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.
getMultimediaXML(bool $offline=false)
get a xml string that contains all media object elements, that are referenced by any media alias in t...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setContentIdManager(\ILIAS\COPage\ID\ContentIdManager $content_id_manager)
Interface Observer Contains several chained tasks and infos about them.
resolveIntLinks(array $a_link_map=null)
Resolves all internal link targets of the page, if targets are available (after import) ...
update(bool $a_validate=true, bool $a_no_history=false)
update complete page content in db (dom xml content is used)
update(string $table_name, array $values, array $where)
$where MUST contain existing columns only.
static array $activation_data
static _existsAndNotEmpty(string $a_parent_type, int $a_id, string $a_lang="-")
Checks whether page exists and is not empty (may return true on some empty pages) ...
static _writeParentId(string $a_parent_type, int $a_pg_id, int $a_par_id)
getPCIdForHierId(string $hier_id)
static _lookupName(int $a_user_id)
lookup user name
saveStyleUsage(DOMDocument $a_domdoc, int $a_old_nr=0)
Save all style class/template usages.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
read()
Read page data.
getContentObjectForPcId(string $pcid)
Get content object for pc id.
static getPageContributors(string $a_parent_type, int $a_page_id, string $a_lang="-")
Get all contributors for parent object.
static _lookupActivationData(int $a_id, string $a_parent_type, string $a_lang="-")
Lookup activation data.
getHistoryEntries()
Get History Entries.
quote($value, string $type)
getDomDoc()
Get dom doc (DOMDocument)
ilPageConfig $page_config
beforePageContentUpdate(ilPageContent $a_page_content)
Before page content update Note: This one is "work in progress", currently only text paragraphs call ...
preparePageForCompare(ilPageObject $page)
static lookupTranslations(string $a_parent_type, int $a_id)
Lookup translations.
resolveIIMMediaAliases(array $a_mapping)
Resolve iim media aliases (in ilContObjParse)
const IL_CAL_UNIX
$c
Definition: deliver.php:9
static now()
Return current timestamp in Y-m-d H:i:s format.
setLimit(int $limit, int $offset=0)
Content object of ilPageObject (see ILIAS DTD).
handleRepositoryLinksOnCopy(array $a_mapping, int $a_source_ref_id)
Handle repository links on copy process.
$path
Definition: ltiservices.php:30
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
deleteContent(string $a_hid, bool $a_update=true, string $a_pcid="", bool $move_operation=false)
delete content object with hierarchical id $a_hid
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setXMLContent(string $a_xml, string $a_encoding="UTF-8")
set xml content of page, start with <PageObject...>, end with </PageObject>, comply with ILIAS DTD...
deleteStyleUsages(int $a_old_nr=0)
Delete style usages.
static _lookupContainsDeactivatedElements(int $a_id, string $a_parent_type, string $a_lang="-")
lookup whether page contains deactivated elements
static shortenText(string $a_string, int $a_start_pos, int $a_num_bytes, string $a_encoding='UTF-8')
Shorten text to the given number of bytes.
insertContentNode(DOMNode $a_cont_node, string $a_pos, int $a_mode=IL_INSERT_AFTER, string $a_pcid="")
insert a content node before/after a sibling or as first child of a parent
resolveResources(array $ref_mapping)
Resolve resources.
getHierIdsForPCIds(array $a_pc_ids)
Get hier ids for a set of pc ids.
ILIAS COPage Link LinkManager $link
saveInternalLinks(DOMDocument $a_domdoc)
save internal links of page
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static truncateHTML(string $a_text, int $a_length=100, string $a_ending='...', bool $a_exact=false, bool $a_consider_html=true)
Truncate (html) string.
const ILIAS_VERSION_NUMERIC
getInternalLinks()
get all internal links that are used within the page
getParentContentObjectForPcId(string $pcid)
Get parent content object for pc id.
static getNewPages(string $a_parent_type, int $a_parent_id, string $a_lang="-")
Get new pages.
static _existsAndNotEmpty(string $a_parent_type, int $a_id, string $a_lang="-")
checks whether page exists and is not empty (may return true on some empty pages) ...
copyXmlContent(bool $a_clone_mobs=false, int $a_new_parent_id=0, int $obj_copy_id=0, bool $self_ass=true)
Copy content of page; replace page components with copies where necessary (e.g.
containsIntLinks(string $a_content)
Check whether content contains internal links.
saveInitialOpenedContent(string $a_type, int $a_id, string $a_target)
Save initial opened content.
ILIAS COPage PC PCDefinition $pc_definition
static getNamePresentation( $a_user_id, bool $a_user_image=false, bool $a_profile_link=false, string $a_profile_back_link='', bool $a_force_first_lastname=false, bool $a_omit_login=false, bool $a_sortable=true, bool $a_return_data_array=false, $a_ctrl_path='ilpublicuserprofilegui')
Default behaviour is:
insertInstIntoIDs(string $a_inst, bool $a_res_ref_to_obj_id=true)
inserts installation id into ids (e.g.
DOMDocument $dom
setActivationStart(?string $a_activationstart)
static _after(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is after end This method does not consider tz offsets.
writeRenderedContent(string $a_content, string $a_md5)
Write rendered content.
deleteInternalLinks()
Delete internal links.
static getRecentChanges(string $a_parent_type, int $a_parent_id, int $a_period=30, string $a_lang="")
Get recent pages changes for parent object.
static _exists(string $a_parent_type, int $a_id, string $a_lang="", bool $a_no_cache=false)
Checks whether page exists.
insertContent(ilPageContent $a_cont_obj, string $a_pos, int $a_mode=IL_INSERT_AFTER, string $a_pcid="", bool $remove_placeholder=true)
insert a content node before/after a sibling or as first child of a parent
resolveMediaAliases(array $a_mapping, bool $a_reuse_existing_by_import=false)
Resolve media aliases (after import)
getInitialOpenedContent()
Get initial opened content.
setActivationEnd(?string $a_activationend)
Set Activation End.
Class ilPageObject Handles PageObjects of ILIAS Learning Modules (see ILIAS DTD)
moveContentAfter(string $a_source, string $a_target, string $a_spcid="", string $a_tpcid="")
move content object from position $a_source before position $a_target (both hierarchical content ids)...
getHistoryEntry(int $a_old_nr)
Get History Entry.
global $DIC
Definition: shib_login.php:25
deleteContents(array $a_hids, bool $a_update=true, bool $a_self_ass=false, bool $move_operation=false)
Delete multiple content objects.
containsIntLink()
returns true, if page was marked as containing an intern link (via setContainsIntLink) (this method s...
createFromXML()
Create new page object with current xml content.
ILIAS COPage Dom DomUtil $dom_util
query(string $query)
Run a (read-only) Query on the database.
setLanguage(string $a_val)
Set language.
ilObjectDefinition $obj_definition
switchEnableMultiple(array $a_hids, bool $a_update=true, bool $a_self_ass=false)
(De-)activate elements
const IL_INSERT_AFTER
$txt
Definition: error.php:30
static lookupParentId(int $a_id, string $a_type)
static _getMobsOfObject(string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
setConcreteLang(string $a_val)
getContentObject(string $a_hier_id, string $a_pc_id="")
Get a content object of the page.
static getLastChangeByParent(string $a_parent_type, int $a_parent_id, string $a_lang="")
Get all pages for parent object.
queryF(string $query, array $types, array $values)
$filename
Definition: buildRTE.php:78
getContentTemplates()
Get content templates.
insertPCIds()
Insert Page Content IDs.
static _writeActive(int $a_id, string $a_parent_type, bool $a_active)
write activation status
addHierIDs()
Add hierarchical ID (e.g.
afterUpdate(DOMDocument $domdoc, string $xml)
After update.
setContainsIntLink(bool $a_contains_link)
lm parser set this flag to true, if the page contains intern links (this method should only be called...
$handler
Definition: oai.php:14
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static preloadActivationDataByParentId(int $a_parent_id)
Preload activation data by Parent Id.
setLastChange(string $a_lastchange)
static _deleteAllUsages(string $a_type, int $a_id, ?int $a_usage_hist_nr=0, string $a_lang="-")
static array $exists
getEditLockInfo()
Get edit lock info.
moveIntLinks(array $a_from_to)
Move internal links from one destination to another.
$lm_set
sendParagraph(string $par_id, string $filename)
registerOfflineHandler(object $handler)
ilDBInterface $db
copyContents(array $a_hids)
Copy contents to clipboard.
LOMServices $lom_services
__afterUpdate(DOMDocument $a_domdoc, string $a_xml, bool $a_creation=false, bool $a_empty=false)
After update event handler (internal).
__afterHistoryEntry(DOMDocument $a_old_domdoc, string $a_old_content, int $a_old_nr)
addUpdateListener(object $a_object, string $a_method, $a_parameters="")
getLanguageVariablesXML(int $style_id=0)
Get language variables as XML.
static getConfigInstance(string $a_parent_type)
Get page config instance.
collectMediaObjects(bool $a_inline_only=true)
get all media objects, that are referenced and used within the page
getEditLock()
Get page lock.
$q
Definition: shib_logout.php:18
link(string $caption, string $href, bool $new_viewport=false)
needsImportParsing(?bool $a_parse=null)
containsDeactivatedElements(string $a_content)
Check whether content contains deactivated elements.
__construct(int $a_id=0, int $a_old_nr=0, string $a_lang="-")
getXMLContent(bool $a_incl_head=false)
get xml content of page
language()
description: > Example for rendring a language glyph.
Definition: language.php:25
copy(int $a_id, string $a_parent_type="", int $a_new_parent_id=0, bool $a_clone_mobs=false, int $obj_copy_id=0, bool $overwrite_existing=true)
Copy page.
getParagraphForPCID(string $pcid)
getPCIdsForHierIds(array $hier_ids)
Get hier ids for a set of pc ids.
manipulate(string $query)
Run a (write) Query on the database.
static _lookupType(int $id, bool $reference=false)
handleDeleteContent(?DOMNode $a_node=null, $move_operation=false)
Handle content before deletion This currently treats only plugged content If no node is given...
getXMLFromDom(bool $a_incl_head=false, bool $a_append_mobs=false, bool $a_append_bib=false, string $a_append_str="", bool $a_omit_pageobject_tag=false, int $style_id=0, bool $offline=false)
get xml content of page from dom (use this, if any changes are made to the document) ...
getRepoObjId()
Get object id of repository object that contains this page, return 0 if page does not belong to a rep...
ILIAS COPage Style StyleManager $style_manager
getMediaAliasElement(int $a_mob_id, int $a_nr=1)
get complete media object (alias) element
setActive(bool $a_active)
static _getLastUpdateOfObjects(array $obj_ids)
static getInstance(string $a_parent_type, int $a_id=0, int $a_old_nr=0, string $a_lang="-")
Get page object instance.
setRenderMd5(string $a_rendermd5)
ILIAS COPage Page PageManager $page_manager
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
pasteContents(string $a_hier_id, bool $a_self_ass=false)
Paste contents from pc clipboard.
setShowActivationInfo(bool $a_val)
setRenderedTime(string $a_renderedtime)
static getAllPages(string $a_parent_type, int $a_parent_id, string $a_lang="-")
Get all pages for parent object.
static sortArray(array $array, string $a_array_sortby_key, string $a_array_sortorder="asc", bool $a_numeric=false, bool $a_keep_keys=false)
Class ilPCParagraphGUI User Interface for Paragraph Editing.
setLastChangeUser(int $a_val)
resolveQuestionReferences(array $a_mapping)
Resolve all quesiont references (after import)