ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilPCParagraph.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once("./Services/COPage/classes/class.ilPageContent.php");
5 
17 {
21  protected $user;
22 
23  public $dom;
24  public $par_node; // node of Paragraph element
25 
29  protected $lng;
30 
31  protected static $bb_tags = array(
32  "com" => "Comment",
33  "emp" => "Emph",
34  "str" => "Strong",
35  "fn" => "Footnote",
36  "code" => "Code",
37  "acc" => "Accent",
38  "imp" => "Important",
39  "kw" => "Keyw",
40  "sub" => "Sub",
41  "sup" => "Sup",
42  "quot" => "Quotation",
43  );
44 
48  public function init()
49  {
50  global $DIC;
51 
52  $this->user = $DIC->user();
53  $this->lng = $DIC->language();
54  $this->setType("par");
55  }
56 
62  protected static function getBBMap()
63  {
64  return self::$bb_tags;
65  }
66 
72  protected static function getXMLTagMap()
73  {
74  return array_flip(self::$bb_tags);
75  }
76 
77 
78 
84  public function setNode($a_node)
85  {
86  parent::setNode($a_node); // this is the PageContent node
87 
88  $childs = $a_node->child_nodes();
89  for ($i = 0; $i < count($childs); $i++) {
90  if ($childs[$i]->node_name() == "Paragraph") {
91  $this->par_node = $childs[$i]; //... and this the Paragraph node
92  }
93  }
94  }
95 
96 
102  public function createAtNode(&$node)
103  {
104  $this->node = $this->createPageContentNode();
105  $this->par_node = $this->dom->create_element("Paragraph");
106  $this->par_node = $this->node->append_child($this->par_node);
107  $this->par_node->set_attribute("Language", "");
108  $node->append_child($this->node);
109  }
110 
116  public function createBeforeNode(&$node)
117  {
118  $this->node = $this->createPageContentNode();
119  $this->par_node = $this->dom->create_element("Paragraph");
120  $this->par_node = $this->node->append_child($this->par_node);
121  $this->par_node->set_attribute("Language", "");
122  $node->insert_before($this->node, $node);
123  }
124 
131  public function createAfter($node)
132  {
133  $this->node = $this->createPageContentNode(false);
134  if ($succ_node = $node->next_sibling()) {
135  $this->node = $succ_node->insert_before($this->node, $succ_node);
136  } else {
137  $parent_node = $node->parent_node();
138  $this->node = $parent_node->append_child($this->node);
139  }
140  $this->par_node = $this->dom->create_element("Paragraph");
141  $this->par_node = $this->node->append_child($this->par_node);
142  $this->par_node->set_attribute("Language", "");
143  }
144 
152  public function create(&$a_pg_obj, $a_hier_id, $a_pc_id = "", $from_placeholder = false)
153  {
154  //echo "-$a_pc_id-";
155  //echo "<br>-".htmlentities($a_pg_obj->getXMLFromDom())."-<br><br>"; mk();
156  $this->node = $this->dom->create_element("PageContent");
157 
158  // this next line kicks out placeholders, if something is inserted
159  $a_pg_obj->insertContent(
160  $this,
161  $a_hier_id,
163  $a_pc_id,
164  $from_placeholder
165  );
166 
167  $this->par_node = $this->dom->create_element("Paragraph");
168  $this->par_node = $this->node->append_child($this->par_node);
169  $this->par_node->set_attribute("Language", "");
170  }
171 
178  public function setText($a_text, $a_auto_split = false)
179  {
180  if (!is_array($a_text)) {
181  $text = array(array("level" => 0, "text" => $a_text));
182  } else {
183  $text = $a_text;
184  }
185  if ($a_auto_split) {
186  $text = $this->autoSplit($a_text);
187  }
188 
189 
190  $error = $this->checkTextArray($text);
191 
192  /* we currently do no try to fix xml
193  if (!empty($error)) {
194  $text = $this->fixTextArray($text);
195  $error = $this->checkTextArray($text);
196  };*/
197 
198  // remove all childs
199  if (empty($error)) {
200  $temp_dom = domxml_open_mem(
201  '<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $text[0]["text"] . '</Paragraph>',
203  $error
204  );
205 
206  // delete children of paragraph node
207  $children = $this->par_node->child_nodes();
208  for ($i = 0; $i < count($children); $i++) {
209  $this->par_node->remove_child($children[$i]);
210  }
211 
212  // copy new content children in paragraph node
213  $xpc = xpath_new_context($temp_dom);
214  $path = "//Paragraph";
215  $res = xpath_eval($xpc, $path);
216  if (count($res->nodeset) == 1) {
217  $new_par_node = $res->nodeset[0];
218  $new_childs = $new_par_node->child_nodes();
219 
220  for ($i = 0; $i < count($new_childs); $i++) {
221  $cloned_child = $new_childs[$i]->clone_node(true);
222  $this->par_node->append_child($cloned_child);
223  }
224  $orig_characteristic = $this->getCharacteristic();
225 
226  // if headlines are entered and current characteristic is a headline
227  // use no characteristic as standard
228  if ((count($text) > 1) && (substr($orig_characteristic, 0, 8) == "Headline")) {
229  $orig_characteristic = "";
230  }
231  if ($text[0]["level"] > 0) {
232  $this->par_node->set_attribute("Characteristic", 'Headline' . $text[0]["level"]);
233  }
234  }
235 
236  $ok = true;
237 
238  $c_node = $this->node;
239  // add other chunks afterwards
240  for ($i = 1; $i < count($text); $i++) {
241  if ($ok) {
242  $next_par = new ilPCParagraph($this->getPage());
243  $next_par->createAfter($c_node);
244  $next_par->setLanguage($this->getLanguage());
245  if ($text[$i]["level"] > 0) {
246  $next_par->setCharacteristic("Headline" . $text[$i]["level"]);
247  } else {
248  $next_par->setCharacteristic($orig_characteristic);
249  }
250  $ok = $next_par->setText($text[$i]["text"], false);
251  $c_node = $next_par->node;
252  }
253  }
254 
255  return true;
256  } else {
257  // We want the correct number of \n here to have the real lines numbers
258  $check = array_reduce($text, function ($t, $i) {
259  return $t . $i["text"];
260  });
261  $text = str_replace("<br>", "\n", $check); // replace <br> with \n to get correct line
262  $text = str_replace("<br/>", "\n", $text);
263  $text = str_replace("<br />", "\n", $text);
264  $text = str_replace("</SimpleListItem>", "</SimpleListItem>\n", $text);
265  $text = str_replace("<SimpleBulletList>", "\n<SimpleBulletList>", $text);
266  $text = str_replace("<SimpleNumberedList>", "\n<SimpleNumberedList>", $text);
267  $text = str_replace("<Paragraph>\n", "<Paragraph>", $text);
268  $text = str_replace("</Paragraph>", "</Paragraph>\n", $text);
269  include_once("./Services/Dom/classes/class.ilDomDocument.php");
270  $doc = new ilDOMDocument();
271  $text = '<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $text . '</Paragraph>';
272  //echo htmlentities($text);
273  $this->success = $doc->loadXML($text);
274  $error = $doc->errors;
275  $estr = "";
276  foreach ($error as $e) {
277  $e = str_replace(" in Entity", "", $e);
278  $estr .= $e . "<br />";
279  }
280  if (DEVMODE) {
281  $estr .= "<br />" . $text;
282  }
283 
284  return $estr;
285  }
286  }
287 
293  protected function checkTextArray($text)
294  {
295  $check = "";
296  foreach ($text as $t) {
297  $check .= "<Paragraph>" . $t["text"] . "</Paragraph>";
298  }
299  $error = null;
300  //try {
301  $temp_dom = domxml_open_mem(
302  '<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $check . '</Paragraph>',
304  $error
305  );
306  //} catch (Exception $e) {
307 
308  //}
309  return $error;
310  }
311 
316  protected function fixTextArray($text)
317  {
318  $dom = new DOMDocument();
319  $dom->recover = true;
320  // try to fix
321  for ($i = 0; $i < count($text); $i++) {
322  $dom->loadXML(
323  '<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $text[$i]["text"] . '</Paragraph>',
324  LIBXML_NOWARNING | LIBXML_NOERROR
325  );
326  foreach ($dom->childNodes as $node) {
327  if ($node->nodeName == "Paragraph") {
328  $inner = "";
329  foreach ($node->childNodes as $child) {
330  $inner .= $dom->saveXML($child);
331  }
332  $text[$i]["text"] = $inner;
333  }
334  }
335  }
336  return $text;
337  }
338 
344  public function getText($a_short_mode = false)
345  {
346  if (is_object($this->par_node)) {
347  $content = "";
348  $childs = $this->par_node->child_nodes();
349  for ($i = 0; $i < count($childs); $i++) {
350  $content .= $this->dom->dump_node($childs[$i]);
351  }
352  return $content;
353  } else {
354  return "";
355  }
356  }
357 
361  public function getParagraphSequenceContent($a_pg_obj)
362  {
363  $childs = $this->par_node->parent_node()->parent_node()->child_nodes();
364  $seq = array();
365  $cur_seq = array();
366  $found = false;
367  $pc_id = $this->readPCId();
368  $hier_id = $this->readHierId();
369  for ($i = 0; $i < count($childs); $i++) {
370  $pchilds = $childs[$i]->child_nodes();
371  if ($pchilds[0]->node_name() == "Paragraph" &&
372  $pchilds[0]->get_attribute("Characteristic") != "Code") {
373  $cur_seq[] = $childs[$i];
374 
375  // check whether this is the sequence of the current paragraph
376  if ($childs[$i]->get_attribute("PCID") == $pc_id &&
377  $childs[$i]->get_attribute("HierId") == $hier_id) {
378  $found = true;
379  }
380 
381  // if this is the current sequenc, get it
382  if ($found) {
383  $seq = $cur_seq;
384  }
385  } else {
386  // non-paragraph element found -> init the current sequence
387  $cur_seq = array();
388  $found = false;
389  }
390  }
391 
392  $content = "";
393  $ids = "###";
394  $id_sep = "";
395  foreach ($seq as $p_node) {
396  $ids .= $id_sep . $p_node->get_attribute("HierId") . ":" . $p_node->get_attribute("PCID");
397  $po = $a_pg_obj->getContentObject(
398  $p_node->get_attribute("HierId"),
399  $p_node->get_attribute("PCID")
400  );
401  $s_text = $po->getText();
402  $s_text = $po->xml2output($s_text, true, false);
403  $char = $po->getCharacteristic();
404  if ($char == "") {
405  $char = "Standard";
406  }
407  $s_text = ilPCParagraphGUI::xml2outputJS($s_text, $char, $po->readPCId());
408  $content .= $s_text;
409  $id_sep = ";";
410  }
411  $ids .= "###";
412 
413  return $ids . $content;
414  }
415 
421  public function setCharacteristic($a_char)
422  {
423  if (!empty($a_char)) {
424  $this->par_node->set_attribute("Characteristic", $a_char);
425  } else {
426  if ($this->par_node->has_attribute("Characteristic")) {
427  $this->par_node->remove_attribute("Characteristic");
428  }
429  }
430  }
431 
437  public function getCharacteristic()
438  {
439  if (is_object($this->par_node)) {
440  return $this->par_node->get_attribute("Characteristic");
441  }
442  }
443 
444 
448  public function setSubCharacteristic($a_char)
449  {
450  if (!empty($a_char)) {
451  $this->par_node->set_attribute("SubCharacteristic", $a_char);
452  } else {
453  if ($this->par_node->has_attribute("SubCharacteristic")) {
454  $this->par_node->remove_attribute("SubCharacteristic");
455  }
456  }
457  }
458 
464  public function getAutoIndent()
465  {
466  return $this->par_node->get_attribute("AutoIndent");
467  }
468 
469  public function setAutoIndent($a_char)
470  {
471  if (!empty($a_char)) {
472  $this->par_node->set_attribute("AutoIndent", $a_char);
473  } else {
474  if ($this->par_node->has_attribute("AutoIndent")) {
475  $this->par_node->remove_attribute("AutoIndent");
476  }
477  }
478  }
479 
483  public function getSubCharacteristic()
484  {
485  return $this->par_node->get_attribute("SubCharacteristic");
486  }
487 
492  public function setDownloadTitle($a_char)
493  {
494  if (!empty($a_char)) {
495  $this->par_node->set_attribute("DownloadTitle", $a_char);
496  } else {
497  if ($this->par_node->has_attribute("DownloadTitle")) {
498  $this->par_node->remove_attribute("DownloadTitle");
499  }
500  }
501  }
502 
506  public function getDownloadTitle()
507  {
508  return $this->par_node->get_attribute("DownloadTitle");
509  }
510 
515  public function setShowLineNumbers($a_char)
516  {
517  $a_char = empty($a_char)?"n":$a_char;
518 
519  $this->par_node->set_attribute("ShowLineNumbers", $a_char);
520  }
521 
526  public function getShowLineNumbers()
527  {
528  return $this->par_node->get_attribute("ShowLineNumbers");
529  }
530 
534  public function setLanguage($a_lang)
535  {
536  $this->par_node->set_attribute("Language", $a_lang);
537  }
538 
542  public function getLanguage()
543  {
544  return $this->par_node->get_attribute("Language");
545  }
546 
547  public function input2xml($a_text, $a_wysiwyg = 0, $a_handle_lists = true)
548  {
549  return $this->_input2xml($a_text, $this->getLanguage(), $a_wysiwyg, $a_handle_lists);
550  }
551 
560  protected static function replaceBBCode($a_text, $a_bb, $a_tag)
561  {
562  $a_text = preg_replace('/\[' . $a_bb . '\]/i', "<" . $a_tag . ">", $a_text);
563  $a_text = preg_replace('/\[\/' . $a_bb . '\]/i', "</" . $a_tag . ">", $a_text);
564  return $a_text;
565  }
566 
567 
571  public static function _input2xml($a_text, $a_lang, $a_wysiwyg = 0, $a_handle_lists = true)
572  {
573  if (!$a_wysiwyg) {
574  $a_text = ilUtil::stripSlashes($a_text, false);
575  }
576 
577  if ($a_wysiwyg) {
578  $a_text = str_replace("<br />", chr(10), $a_text);
579  }
580 
581  // note: the order of the processing steps is crucial
582  // and should be the same as in xml2output() in REVERSE order!
583  $a_text = trim($a_text);
584 
585  //echo "<br>between:".htmlentities($a_text);
586 
587  // mask html
588  if (!$a_wysiwyg) {
589  $a_text = str_replace("&", "&amp;", $a_text);
590  }
591  $a_text = str_replace("<", "&lt;", $a_text);
592  $a_text = str_replace(">", "&gt;", $a_text);
593 
594  // Reconvert PageTurn and BibItemIdentifier
595  $a_text = preg_replace('/&lt;([\s\/]*?PageTurn.*?)&gt;/i', "<$1>", $a_text);
596  $a_text = preg_replace('/&lt;([\s\/]*?BibItemIdentifier.*?)&gt;/i', "<$1>", $a_text);
597 
598  //echo "<br>second:".htmlentities($a_text);
599 
600  // mask curly brackets
601  /*
602  echo htmlentities($a_text);
603  $a_text = str_replace("{", "&#123;", $a_text);
604  $a_text = str_replace("}", "&#125;", $a_text);
605  echo htmlentities($a_text);*/
606  // linefeed to br
607  $a_text = str_replace(chr(13) . chr(10), "<br />", $a_text);
608  $a_text = str_replace(chr(13), "<br />", $a_text);
609  $a_text = str_replace(chr(10), "<br />", $a_text);
610 
611  if ($a_handle_lists) {
612  $a_text = ilPCParagraph::input2xmlReplaceLists($a_text);
613  }
614 
615  foreach (self::getBBMap() as $bb => $tag) {
616  // remove empty tags
617  $a_text = str_replace("[" . $bb . "][/" . $bb . "]", "", $a_text);
618 
619  // replace bb code by tag
620  $a_text = self::replaceBBCode($a_text, $bb, $tag);
621  }
622 
623  $a_text = self::intLinks2xml($a_text);
624 
625  // external link
626  $ws = "[ \t\r\f\v\n]*";
627  // remove empty external links
628  while (preg_match("~\[(xln$ws(url$ws=$ws\"([^\"])*\")$ws(target$ws=$ws(\"(Glossary|FAQ|Media)\"))?$ws)\]\[\/xln\]~i", $a_text, $found)) {
629  $a_text = str_replace($found[0], "", $a_text);
630  }
631  while (preg_match('~\[(xln$ws(url$ws=$ws(([^]])*)))$ws\]\[\/xln\]~i', $a_text, $found)) {
632  $a_text = str_replace($found[0], "", $a_text);
633  }
634  // external links
635  while (preg_match("~\[(xln$ws(url$ws=$ws\"([^\"])*\")$ws(target$ws=$ws(\"(Glossary|FAQ|Media)\"))?$ws)\]~i", $a_text, $found)) {
636  $old_text = $a_text;
637  $attribs = ilUtil::attribsToArray($found[2]);
638  if (isset($attribs["url"])) {
639  $a_text = self::replaceBBTagByMatching(
640  "[" . $found[1] . "]",
641  "[/xln]",
642  "ExtLink",
643  $a_text,
644  [
645  "Href" => $attribs["url"]
646  ]
647  );
648  }
649  if ($old_text === $a_text) {
650  $a_text = str_replace("[" . $found[1] . "]", "[error: " . $found[1] . "]", $a_text);
651  }
652  }
653 
654  // ie/tinymce fix for links without "", see bug #8391
655  /* deprecated, should be removed soon, old IE not supported anymore
656  while (preg_match('~\[(xln$ws(url$ws=$ws(([^]])*)))$ws\]~i', $a_text, $found)) {
657  if ($found[3] != "") {
658  $a_text = str_replace("[" . $found[1] . "]", "<ExtLink Href=\"" . $found[3] . "\">", $a_text);
659  } else {
660  $a_text = str_replace("[" . $found[1] . "]", "[error: xln" . $found[1] . "]", $a_text);
661  }
662  }
663  $a_text = preg_replace('~\[\/xln\]~i', "</ExtLink>", $a_text);*/
664 
665  // anchor
666  $ws = "[ \t\r\f\v\n]*";
667  while (preg_match("~\[(anc$ws(name$ws=$ws\"([^\"])*\")$ws)\]~i", $a_text, $found)) {
668  $attribs = ilUtil::attribsToArray($found[2]);
669  $a_text = self::replaceBBTagByMatching(
670  "[" . $found[1] . "]",
671  "[/anc]",
672  "Anchor",
673  $a_text,
674  [
675  "Name" => $attribs["name"]
676  ]
677  );
678  }
679 
680  // marked text
681  while (preg_match("~\[(marked$ws(class$ws=$ws\"([^\"])*\")$ws)\]~i", $a_text, $found)) {
682  $attribs = ilUtil::attribsToArray($found[2]);
683  if (isset($attribs["class"])) {
684  $a_text = self::replaceBBTagByMatching(
685  "[" . $found[1] . "]",
686  "[/marked]",
687  "Marked",
688  $a_text,
689  [
690  "Class" => $attribs["class"]
691  ]
692  );
693  } else {
694  $a_text = str_replace("[" . $found[1] . "]", "[error:marked" . $found[1] . "]", $a_text);
695  }
696  }
697 
698 
699  //echo htmlentities($a_text); exit;
700  return $a_text;
701  }
702 
703  protected static function isValidTagContent(string $content) : bool
704  {
705  libxml_use_internal_errors(true);
706  $sxe = simplexml_load_string("<?xml version='1.0'?><dummy>" . $content . "</dummy>");
707  libxml_use_internal_errors(false);
708  return ($sxe !== false);
709  }
710 
716  protected static function replaceBBTagByMatching(
717  string $start_tag,
718  string $end_tag,
719  string $xml_tag_name,
720  string $text,
721  array $attribs
722  ) : string {
723  $attrib_str = "";
724  foreach ($attribs as $key => $value) {
725  if ($value != "") {
726  $attrib_str .= ' ' . $key . '="' . $value . '"';
727  }
728  }
729 
730  $ok = false;
731 
732  $pos1 = strpos($text, $start_tag);
733 
734  $pos2 = null;
735  if ($end_tag != "") {
736  $pos2 = strpos($text, $end_tag, $pos1 + strlen($start_tag));
737  if (is_int($pos1) && is_int($pos2)) {
738  $between = substr($text, $pos1 + strlen($start_tag), $pos2 - ($pos1 + strlen($start_tag)));
739  $ok = self::isValidTagContent($between);
740  }
741  } else { // no end tag
742  if (is_int($pos1)) {
743  $ok = true;
744  }
745  }
746  $short = ($end_tag == "")
747  ? "/"
748  : "";
749 
750  $slash_chars = '/[]?()$*';
751 
752  if ($ok) {
753  $replace_str = addcslashes($start_tag, $slash_chars);
754  $replace_str = str_replace("+", "\\+", $replace_str);
755  // replace start tag
756  $text = preg_replace(
757  '/' . $replace_str . '/i',
758  "<" . $xml_tag_name . $attrib_str . $short . ">",
759  $text,
760  1
761  );
762 
763  // replace end tag
764  if ($end_tag != "") {
765  $text = preg_replace('~' . addcslashes($end_tag, $slash_chars) . '~i', "</" . $xml_tag_name . ">", $text, 1);
766  }
767  } else {
768  // remove start tag
769  if (is_int($pos1)) {
770  $text = preg_replace(
771  '/' . addcslashes($start_tag, $slash_chars) . '/i',
772  "",
773  $text,
774  1
775  );
776  }
777  // remove end tag
778  if (is_int($pos2)) {
779  $text = preg_replace(
780  '~' . addcslashes($end_tag, $slash_chars) . '~i',
781  "",
782  $text,
783  1
784  );
785  }
786  }
787  return $text;
788  }
789 
796  public static function intLinks2xml($a_text)
797  {
798  global $DIC;
799 
800  $objDefinition = $DIC["objDefinition"];
801 
802  $rtypes = $objDefinition->getAllRepositoryTypes();
803 
804  // internal links
805  //$any = "[^\]]*"; // this doesn't work :-(
806  $ws = "[ \t\r\f\v\n]*";
807  $ltypes = "page|chap|term|media|obj|dfile|sess|wpage|ppage|" . implode("|", $rtypes);
808  // empty internal links
809  while (preg_match('~\[(iln' . $ws . '((inst' . $ws . '=' . $ws . '([\"0-9])*)?' . $ws .
810  "((" . $ltypes . ")$ws=$ws([\"0-9])*)$ws" .
811  "(target$ws=$ws(\"(New|FAQ|Media)\"))?$ws(anchor$ws=$ws(\"([^\"])*\"))?$ws))\]\[\/iln\]~i", $a_text, $found)) {
812  $a_text = str_replace($found[0], "", $a_text);
813  }
814  while (preg_match('~\[(iln' . $ws . '((inst' . $ws . '=' . $ws . '([\"0-9])*)?' . $ws .
815  "((" . $ltypes . ")$ws=$ws([\"0-9])*)$ws" .
816  "(target$ws=$ws(\"(New|FAQ|Media)\"))?$ws(anchor$ws=$ws(\"([^\"])*\"))?$ws))\]~i", $a_text, $found)) {
817  $attribs = ilUtil::attribsToArray($found[2]);
818  $inst_str = $attribs["inst"];
819  // pages
820  if (isset($attribs["page"])) {
821  $a_text = self::replaceBBTagByMatching(
822  "[" . $found[1] . "]",
823  "[/iln]",
824  "IntLink",
825  $a_text,
826  [
827  "Target" => "il_" . $inst_str . "_pg_" . $attribs['page'],
828  "Type" => "PageObject",
829  "TargetFrame" => $found[10] ?? "",
830  "Anchor" => $attribs["anchor"] ?? ""
831  ]
832  );
833  }
834  // chapters
835  elseif (isset($attribs["chap"])) {
836  $a_text = self::replaceBBTagByMatching(
837  "[" . $found[1] . "]",
838  "[/iln]",
839  "IntLink",
840  $a_text,
841  [
842  "Target" => "il_" . $inst_str . "_st_" . $attribs['chap'],
843  "Type" => "StructureObject",
844  "TargetFrame" => $found[10] ?? ""
845  ]
846  );
847  }
848  // glossary terms
849  elseif (isset($attribs["term"])) {
850  $a_text = self::replaceBBTagByMatching(
851  "[" . $found[1] . "]",
852  "[/iln]",
853  "IntLink",
854  $a_text,
855  [
856  "Target" => "il_" . $inst_str . "_git_" . $attribs['term'],
857  "Type" => "GlossaryItem",
858  "TargetFrame" => (($found[10] ?? "") == "New")
859  ? "New"
860  : "Glossary"
861  ]
862  );
863  }
864  // wiki pages
865  elseif (isset($attribs["wpage"])) {
866  $a_text = self::replaceBBTagByMatching(
867  "[" . $found[1] . "]",
868  "[/iln]",
869  "IntLink",
870  $a_text,
871  [
872  "Target" => "il_" . $inst_str . "_wpage_" . $attribs['wpage'],
873  "Type" => "WikiPage",
874  "Anchor" => $attribs["anchor"] ?? ""
875  ]
876  );
877  }
878  // portfolio pages
879  elseif (isset($attribs["ppage"])) {
880  $a_text = self::replaceBBTagByMatching(
881  "[" . $found[1] . "]",
882  "[/iln]",
883  "IntLink",
884  $a_text,
885  [
886  "Target" => "il_" . $inst_str . "_ppage_" . $attribs['ppage'],
887  "Type" => "PortfolioPage"
888  ]
889  );
890  }
891  // media object
892  elseif (isset($attribs["media"])) {
893  $a_text = self::replaceBBTagByMatching(
894  "[" . $found[1] . "]",
895  "[/iln]",
896  "IntLink",
897  $a_text,
898  [
899  "Target" => "il_" . $inst_str . "_mob_" . $attribs['media'],
900  "Type" => "MediaObject",
901  "TargetFrame" => $found[10] ?? ""
902  ]
903  );
904  }
905  // direct download file (no repository object)
906  elseif (isset($attribs["dfile"])) {
907  $a_text = self::replaceBBTagByMatching(
908  "[" . $found[1] . "]",
909  "[/iln]",
910  "IntLink",
911  $a_text,
912  [
913  "Target" => "il_" . $inst_str . "_dfile_" . $attribs['dfile'],
914  "Type" => "File"
915  ]
916  );
917  }
918  // repository items (id is ref_id (will be used internally but will
919  // be replaced by object id for export purposes)
920  else {
921  foreach ($objDefinition->getAllRepositoryTypes() as $t) {
922  if (isset($attribs[$t])) {
923  $obj_id = $attribs[$t];
924  }
925  }
926  if (isset($attribs["obj"])) {
927  $obj_id = $attribs["obj"];
928  }
929 
930  if ($obj_id > 0) {
931  if ($inst_str == "") {
932  $a_text = self::replaceBBTagByMatching(
933  "[" . $found[1] . "]",
934  "[/iln]",
935  "IntLink",
936  $a_text,
937  [
938  "Target" => "il_" . $inst_str . "_obj_" . $obj_id,
939  "Type" => "RepositoryItem"
940  ]
941  );
942  } else {
943  $a_text = self::replaceBBTagByMatching(
944  "[" . $found[1] . "]",
945  "[/iln]",
946  "IntLink",
947  $a_text,
948  [
949  "Target" => "il_" . $inst_str . "_" . $found[6] . "_" . $obj_id,
950  "Type" => "RepositoryItem"
951  ]
952  );
953  }
954  } else {
955  $a_text = preg_replace('/\[' . $found[1] . '\]/i', "[error: iln" . $found[1] . "]", $a_text);
956  }
957  }
958  }
959 
960  while (preg_match("~\[(iln$ws((inst$ws=$ws([\"0-9])*)?" . $ws . "media$ws=$ws([\"0-9])*)$ws)/\]~i", $a_text, $found)) {
961  $attribs = ilUtil::attribsToArray($found[2]);
962  $inst_str = $attribs["inst"] ?? "";
963  $a_text = self::replaceBBTagByMatching(
964  "[" . $found[1] . "/]",
965  "",
966  "IntLink",
967  $a_text,
968  [
969  "Target" => "il_" . $inst_str . "_mob_" . $attribs['media'],
970  "Type" => "MediaObject"
971  ]
972  );
973  }
974 
975  // user
976  while (preg_match("~\[(iln$ws((inst$ws=$ws([\"0-9])*)?" . $ws . "user$ws=$ws(\"([^\"])*)\")$ws)/\]~i", $a_text, $found)) {
977  $attribs = ilUtil::attribsToArray($found[2]);
978  $inst_str = $attribs["inst"];
979  include_once("./Services/User/classes/class.ilObjUser.php");
980  $user_id = ilObjUser::_lookupId($attribs['user']);
981  $a_text = self::replaceBBTagByMatching(
982  "[" . $found[1] . "/]",
983  "",
984  "IntLink",
985  $a_text,
986  [
987  "Target" => "il_" . $inst_str . "_user_" . $user_id,
988  "Type" => "User"
989  ]
990  );
991  }
992 
993  return $a_text;
994  }
995 
996 
1004  public static function input2xmlReplaceLists($a_text)
1005  {
1006  $rows = explode("<br />", $a_text . "<br />");
1007  //var_dump($a_text);
1008 
1009  $old_level = 0;
1010 
1011  $text = "";
1012 
1013  foreach ($rows as $row) {
1014  $level = 0;
1015  if (str_replace("#", "*", substr($row, 0, 3)) == "***") {
1016  $level = 3;
1017  } elseif (str_replace("#", "*", substr($row, 0, 2)) == "**") {
1018  $level = 2;
1019  } elseif (str_replace("#", "*", substr($row, 0, 1)) == "*") {
1020  $level = 1;
1021  }
1022 
1023  // end previous line
1024  if ($level < $old_level) {
1025  for ($i = $old_level; $i > $level; $i--) {
1026  $text .= "</SimpleListItem></" . $clist[$i] . ">";
1027  }
1028  if ($level > 0) {
1029  $text .= "</SimpleListItem>";
1030  }
1031  } elseif ($old_level > 0 && $level > 0 && ($level == $old_level)) {
1032  $text .= "</SimpleListItem>";
1033  } elseif (($level == $old_level) && $text != "") {
1034  $text .= "<br />";
1035  }
1036 
1037  // start next line
1038  if ($level > $old_level) {
1039  for ($i = $old_level + 1; $i <= $level; $i++) {
1040  if (substr($row, $i - 1, 1) == "*") {
1041  $clist[$i] = "SimpleBulletList";
1042  } else {
1043  $clist[$i] = "SimpleNumberedList";
1044  }
1045  $text .= "<" . $clist[$i] . "><SimpleListItem>";
1046  }
1047  } elseif ($old_level > 0 && $level > 0) {
1048  $text .= "<SimpleListItem>";
1049  }
1050  $text .= substr($row, $level);
1051 
1052  $old_level = $level;
1053  }
1054 
1055  // remove "<br />" at the end
1056  if (substr($text, strlen($text) - 6) == "<br />") {
1057  $text = substr($text, 0, strlen($text) - 6);
1058  }
1059 
1060  return $text;
1061  }
1062 
1070  public static function xml2outputReplaceLists($a_text)
1071  {
1072  $segments = ilPCParagraph::segmentString($a_text, array("<SimpleBulletList>", "</SimpleBulletList>",
1073  "</SimpleListItem>", "<SimpleListItem>", "<SimpleListItem/>", "<SimpleNumberedList>", "</SimpleNumberedList>"));
1074 
1075  $current_list = array();
1076  $text = "";
1077  for ($i = 0; $i <= count($segments); $i++) {
1078  if ($segments[$i] == "<SimpleBulletList>") {
1079  if (count($current_list) == 0) {
1080  $list_start = true;
1081  }
1082  array_push($current_list, "*");
1083  $li = false;
1084  } elseif ($segments[$i] == "<SimpleNumberedList>") {
1085  if (count($current_list) == 0) {
1086  $list_start = true;
1087  }
1088  array_push($current_list, "#");
1089  $li = false;
1090  } elseif ($segments[$i] == "</SimpleBulletList>") {
1091  array_pop($current_list);
1092  $li = false;
1093  } elseif ($segments[$i] == "</SimpleNumberedList>") {
1094  array_pop($current_list);
1095  $li = false;
1096  } elseif ($segments[$i] == "<SimpleListItem>") {
1097  $li = true;
1098  } elseif ($segments[$i] == "</SimpleListItem>") {
1099  $li = false;
1100  } elseif ($segments[$i] == "<SimpleListItem/>") {
1101  if ($list_start) {
1102  $text .= "<br />";
1103  $list_start = false;
1104  }
1105  foreach ($current_list as $list) {
1106  $text .= $list;
1107  }
1108  $text .= "<br />";
1109  $li = false;
1110  } else {
1111  if ($li) {
1112  if ($list_start) {
1113  $text .= "<br />";
1114  $list_start = false;
1115  }
1116  foreach ($current_list as $list) {
1117  $text .= $list;
1118  }
1119  }
1120  $text .= $segments[$i];
1121  if ($li) {
1122  $text .= "<br />";
1123  }
1124  $li = false;
1125  }
1126  }
1127 
1128  // remove trailing <br />, if text ends with list
1129  if ($segments[count($segments) - 1] == "</SimpleBulletList>" ||
1130  $segments[count($segments) - 1] == "</SimpleNumberedList>" &&
1131  substr($text, strlen($text) - 6) == "<br />") {
1132  $text = substr($text, 0, strlen($text) - 6);
1133  }
1134 
1135  return $text;
1136  }
1137 
1141  public static function segmentString($a_haystack, $a_needles)
1142  {
1143  $segments = array();
1144 
1145  $nothing_found = false;
1146  while (!$nothing_found) {
1147  $nothing_found = true;
1148  $found = -1;
1149  foreach ($a_needles as $needle) {
1150  $pos = stripos($a_haystack, $needle);
1151  if (is_int($pos) && ($pos < $found || $found == -1)) {
1152  $found = $pos;
1153  $found_needle = $needle;
1154  $nothing_found = false;
1155  }
1156  }
1157  if ($found > 0) {
1158  $segments[] = substr($a_haystack, 0, $found);
1159  $a_haystack = substr($a_haystack, $found);
1160  }
1161  if ($found > -1) {
1162  $segments[] = substr($a_haystack, 0, strlen($found_needle));
1163  $a_haystack = substr($a_haystack, strlen($found_needle));
1164  }
1165  }
1166  if ($a_haystack != "") {
1167  $segments[] = $a_haystack;
1168  }
1169 
1170  return $segments;
1171  }
1172 
1180  public static function xml2output($a_text, $a_wysiwyg = false, $a_replace_lists = true, $unmask = true)
1181  {
1182  // note: the order of the processing steps is crucial
1183  // and should be the same as in input2xml() in REVERSE order!
1184 
1185  // xml to bb code
1186  $any = "[^>]*";
1187 
1188  foreach (self::getBBMap() as $bb => $tag) {
1189  $a_text = preg_replace('~<' . $tag . '[^>]*>~i', "[" . $bb . "]", $a_text);
1190  $a_text = preg_replace('~</' . $tag . '>~i', "[/" . $bb . "]", $a_text);
1191  $a_text = preg_replace('~<' . $tag . '/>~i', "[" . $bb . "][/" . $bb . "]", $a_text);
1192  }
1193 
1194  // replace lists
1195  if ($a_replace_lists) {
1196  //echo "<br>".htmlentities($a_text);
1197  $a_text = ilPCParagraph::xml2outputReplaceLists($a_text);
1198  //echo "<br>".htmlentities($a_text);
1199  }
1200 
1201  // internal links
1202  while (preg_match('~<IntLink(' . $any . ')>~i', $a_text, $found)) {
1203  $found[0];
1204  $attribs = ilUtil::attribsToArray($found[1]);
1205  $target = explode("_", $attribs["Target"]);
1206  $target_id = $target[count($target) - 1];
1207  $inst_str = (!is_int(strpos($attribs["Target"], "__")))
1208  ? $inst_str = "inst=\"" . $target[1] . "\" "
1209  : $inst_str = "";
1210  switch ($attribs["Type"]) {
1211  case "PageObject":
1212  $tframestr = (!empty($attribs["TargetFrame"]))
1213  ? " target=\"" . $attribs["TargetFrame"] . "\""
1214  : "";
1215  $ancstr = (!empty($attribs["Anchor"]))
1216  ? ' anchor="' . $attribs["Anchor"] . '"'
1217  : "";
1218  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "page=\"" . $target_id . "\"$tframestr$ancstr]", $a_text);
1219  break;
1220 
1221  case "StructureObject":
1222  $tframestr = (!empty($attribs["TargetFrame"]))
1223  ? " target=\"" . $attribs["TargetFrame"] . "\""
1224  : "";
1225  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "chap=\"" . $target_id . "\"$tframestr]", $a_text);
1226  break;
1227 
1228  case "GlossaryItem":
1229  $tframestr = (empty($attribs["TargetFrame"]) || $attribs["TargetFrame"] == "Glossary")
1230  ? ""
1231  : " target=\"" . $attribs["TargetFrame"] . "\"";
1232  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "term=\"" . $target_id . "\"" . $tframestr . "]", $a_text);
1233  break;
1234 
1235  case "WikiPage":
1236  $tframestr = "";
1237  $ancstr = (!empty($attribs["Anchor"]))
1238  ? ' anchor="' . $attribs["Anchor"] . '"'
1239  : "";
1240  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "wpage=\"" . $target_id . "\"" . $tframestr . $ancstr . "]", $a_text);
1241  break;
1242 
1243  case "PortfolioPage":
1244  $tframestr = "";
1245  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "ppage=\"" . $target_id . "\"" . $tframestr . "]", $a_text);
1246  break;
1247 
1248  case "MediaObject":
1249  if (empty($attribs["TargetFrame"])) {
1250  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "media=\"" . $target_id . "\"/]", $a_text);
1251  } else {
1252  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln media=\"" . $target_id . "\"" .
1253  " target=\"" . $attribs["TargetFrame"] . "\"]", $a_text);
1254  }
1255  break;
1256 
1257  // Repository Item (using ref id)
1258  case "RepositoryItem":
1259  if ($inst_str == "") {
1260  $target_type = ilObject::_lookupType($target_id, true);
1261  } else {
1262  $rtype = $target[count($target) - 2];
1263  $target_type = $rtype;
1264  }
1265  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "$target_type=\"" . $target_id . "\"" . $tframestr . "]", $a_text);
1266  break;
1267 
1268  // Download File (not in repository, Object ID)
1269  case "File":
1270  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "dfile=\"" . $target_id . "\"" . $tframestr . "]", $a_text);
1271  break;
1272 
1273  // User
1274  case "User":
1275  include_once("./Services/User/classes/class.ilObjUser.php");
1276  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "user=\"" . ilObjUser::_lookupLogin($target_id) . "\"/]", $a_text);
1277  break;
1278 
1279  default:
1280  $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln]", $a_text);
1281  break;
1282  }
1283  }
1284  $a_text = str_replace("</IntLink>", "[/iln]", $a_text);
1285 
1286  // external links
1287  while (preg_match('~<ExtLink(' . $any . ')>~i', $a_text, $found)) {
1288  $found[0];
1289  $attribs = ilUtil::attribsToArray($found[1]);
1290  //$found[1] = str_replace("?", "\?", $found[1]);
1291  $tstr = "";
1292  if (in_array($attribs["TargetFrame"], array("FAQ", "Glossary", "Media"))) {
1293  $tstr = ' target="' . $attribs["TargetFrame"] . '"';
1294  }
1295  $a_text = str_replace("<ExtLink" . $found[1] . ">", "[xln url=\"" . $attribs["Href"] . "\"$tstr]", $a_text);
1296  }
1297  $a_text = str_replace("</ExtLink>", "[/xln]", $a_text);
1298 
1299  // anchor
1300  while (preg_match('~<Anchor(' . $any . '/)>~i', $a_text, $found)) {
1301  $found[0];
1302  $attribs = ilUtil::attribsToArray($found[1]);
1303  $a_text = str_replace("<Anchor" . $found[1] . ">", "[anc name=\"" . $attribs["Name"] . "\"][/anc]", $a_text);
1304  }
1305  while (preg_match('~<Anchor(' . $any . ')>~i', $a_text, $found)) {
1306  $found[0];
1307  $attribs = ilUtil::attribsToArray($found[1]);
1308  $a_text = str_replace("<Anchor" . $found[1] . ">", "[anc name=\"" . $attribs["Name"] . "\"]", $a_text);
1309  }
1310  $a_text = str_replace("</Anchor>", "[/anc]", $a_text);
1311 
1312  // marked text
1313  while (preg_match('~<Marked(' . $any . ')>~i', $a_text, $found)) {
1314  $found[0];
1315  $attribs = ilUtil::attribsToArray($found[1]);
1316  $a_text = str_replace("<Marked" . $found[1] . ">", "[marked class=\"" . $attribs["Class"] . "\"]", $a_text);
1317  }
1318  $a_text = str_replace("</Marked>", "[/marked]", $a_text);
1319 
1320  // br to linefeed
1321  if (!$a_wysiwyg) {
1322  $a_text = str_replace("<br />", "\n", $a_text);
1323  $a_text = str_replace("<br/>", "\n", $a_text);
1324  }
1325 
1326  if (!$a_wysiwyg) {
1327  // prevent curly brackets from being swallowed up by template engine
1328  $a_text = str_replace("{", "&#123;", $a_text);
1329  $a_text = str_replace("}", "&#125;", $a_text);
1330 
1331  // unmask html
1332  if ($unmask) {
1333  $a_text = str_replace("&lt;", "<", $a_text);
1334  $a_text = str_replace("&gt;", ">", $a_text);
1335  }
1336 
1337  // this is needed to allow html like <tag attribute="value">... in paragraphs
1338  $a_text = str_replace("&quot;", "\"", $a_text);
1339 
1340  // make ampersands in (enabled) html attributes work
1341  // e.g. <a href="foo.php?n=4&t=5">hhh</a>
1342  $a_text = str_replace("&amp;", "&", $a_text);
1343 
1344  // make &gt; and $lt; work to allow (disabled) html descriptions
1345  if ($unmask) {
1346  $a_text = str_replace("&lt;", "&amp;lt;", $a_text);
1347  $a_text = str_replace("&gt;", "&amp;gt;", $a_text);
1348  }
1349  }
1350  return $a_text;
1351  //return str_replace("<br />", chr(13).chr(10), $a_text);
1352  }
1353 
1360  public function autoSplit($a_text)
1361  {
1362  $a_text = str_replace("=<SimpleBulletList>", "=<br /><SimpleBulletList>", $a_text);
1363  $a_text = str_replace("=<SimpleNumberedList>", "=<br /><SimpleNumberedList>", $a_text);
1364  $a_text = str_replace("</SimpleBulletList>=", "</SimpleBulletList><br />=", $a_text);
1365  $a_text = str_replace("</SimpleNumberedList>=", "</SimpleNumberedList><br />=", $a_text);
1366  $a_text = "<br />" . $a_text . "<br />"; // add preceding and trailing br
1367 
1368  $chunks = array();
1369  $c_text = $a_text;
1370  //echo "0";
1371  while ($c_text != "") {
1372  //var_dump($c_text); flush();
1373  //echo "1";
1374  $s1 = strpos($c_text, "<br />=");
1375  if (is_int($s1)) {
1376  //echo "2";
1377  $s2 = strpos($c_text, "<br />==");
1378  if (is_int($s2) && $s2 <= $s1) {
1379  //echo "3";
1380  $s3 = strpos($c_text, "<br />===");
1381  if (is_int($s3) && $s3 <= $s2) { // possible level three header
1382  //echo "4";
1383  $n = strpos($c_text, "<br />", $s3 + 1);
1384  if ($n > ($s3 + 9) && substr($c_text, $n - 3, 9) == "===<br />") {
1385  //echo "5";
1386  // found level three header
1387  if ($s3 > 0 || $head != "") {
1388  //echo "6";
1389  $chunks[] = array("level" => 0,
1390  "text" => $this->removeTrailingBr($head . substr($c_text, 0, $s3)));
1391  $head = "";
1392  }
1393  $chunks[] = array("level" => 3,
1394  "text" => trim(substr($c_text, $s3 + 9, $n - $s3 - 12)));
1395  $c_text = $this->handleNextBr(substr($c_text, $n + 6));
1396  } else {
1397  //echo "7";
1398  $head .= substr($c_text, 0, $n);
1399  $c_text = substr($c_text, $n);
1400  }
1401  } else { // possible level two header
1402  //echo "8";
1403  $n = strpos($c_text, "<br />", $s2 + 1);
1404  if ($n > ($s2 + 8) && substr($c_text, $n - 2, 8) == "==<br />") {
1405  //echo "9";
1406  // found level two header
1407  if ($s2 > 0 || $head != "") {
1408  //echo "A";
1409  $chunks[] = array("level" => 0,
1410  "text" => $this->removeTrailingBr($head . substr($c_text, 0, $s2)));
1411  $head = "";
1412  }
1413  $chunks[] = array("level" => 2, "text" => trim(substr($c_text, $s2 + 8, $n - $s2 - 10)));
1414  $c_text = $this->handleNextBr(substr($c_text, $n + 6));
1415  } else {
1416  //echo "B";
1417  $head .= substr($c_text, 0, $n);
1418  $c_text = substr($c_text, $n);
1419  }
1420  }
1421  } else { // possible level one header
1422  //echo "C";
1423  $n = strpos($c_text, "<br />", $s1 + 1);
1424  if ($n > ($s1 + 7) && substr($c_text, $n - 1, 7) == "=<br />") {
1425  //echo "D";
1426  // found level one header
1427  if ($s1 > 0 || $head != "") {
1428  //echo "E";
1429  $chunks[] = array("level" => 0,
1430  "text" => $this->removeTrailingBr($head . substr($c_text, 0, $s1)));
1431  $head = "";
1432  }
1433  $chunks[] = array("level" => 1, "text" => trim(substr($c_text, $s1 + 7, $n - $s1 - 8)));
1434  $c_text = $this->handleNextBr(substr($c_text, $n + 6));
1435  //echo "<br>ctext:".htmlentities($c_text)."<br>";
1436  } else {
1437  $head .= substr($c_text, 0, $n);
1438  $c_text = substr($c_text, $n);
1439  //echo "<br>head:".$head."c_text:".$c_text."<br>";
1440  }
1441  }
1442  } else {
1443  //echo "G";
1444  $chunks[] = array("level" => 0, "text" => $head . $c_text);
1445  $head = "";
1446  $c_text = "";
1447  }
1448  }
1449  if (count($chunks) == 0) {
1450  $chunks[] = array("level" => 0, "text" => "");
1451  }
1452 
1453 
1454  // remove preceding br
1455  if (substr($chunks[0]["text"], 0, 6) == "<br />") {
1456  $chunks[0]["text"] = substr($chunks[0]["text"], 6);
1457  }
1458 
1459  // remove trailing br
1460  if (substr(
1461  $chunks[count($chunks) - 1]["text"],
1462  strlen($chunks[count($chunks) - 1]["text"]) - 6,
1463  6
1464  ) == "<br />") {
1465  $chunks[count($chunks) - 1]["text"] =
1466  substr($chunks[count($chunks) - 1]["text"], 0, strlen($chunks[count($chunks) - 1]["text"]) - 6);
1467  if ($chunks[count($chunks) - 1]["text"] == "") {
1468  unset($chunks[count($chunks) - 1]);
1469  }
1470  }
1471  return $chunks;
1472  }
1473 
1477  public function handleNextBr($a_str)
1478  {
1479  // do not remove, if next line starts with a "=", otherwise two
1480  // headlines in a row will not be recognized
1481  if (substr($a_str, 0, 6) == "<br />" && substr($a_str, 6, 1) != "=") {
1482  $a_str = substr($a_str, 6);
1483  } else {
1484  // if next line starts with a "=" we need to reinsert the <br />
1485  // otherwise it will not be recognized
1486  if (substr($a_str, 0, 1) == "=") {
1487  $a_str = "<br />" . $a_str;
1488  }
1489  }
1490  return $a_str;
1491  }
1492 
1496  public function removeTrailingBr($a_str)
1497  {
1498  if (substr($a_str, strlen($a_str) - 6) == "<br />") {
1499  $a_str = substr($a_str, 0, strlen($a_str) - 6);
1500  }
1501  return $a_str;
1502  }
1503 
1507  public function getType()
1508  {
1509  return ($this->getCharacteristic() == "Code")?"src":parent::getType();
1510  }
1511 
1515 
1522  public function saveJS(
1523  $a_pg_obj,
1524  $a_content,
1525  $a_char,
1526  $a_pc_id,
1527  $a_insert_at = "",
1528  $from_placeholder = false
1529  ) {
1530  $ilUser = $this->user;
1531 
1532  $a_content = str_replace("<br>", "<br />", $a_content);
1533 
1534  $this->log->debug("step 1: " . substr($a_content, 0, 1000));
1535  try {
1536  $t = self::handleAjaxContent($a_content);
1537  } catch (Exception $ex) {
1538  return $ex->getMessage() . ": " . htmlentities($a_content);
1539  }
1540  $this->log->debug("step 2: " . substr($t["text"], 0, 1000));
1541  if ($t === false) {
1542  return false;
1543  }
1544  $pc_id = explode(":", $a_pc_id);
1545  $insert_at = explode(":", $a_insert_at);
1546  $t_id = explode(":", $t["id"]);
1547 
1548  // insert new paragraph
1549  if ($a_insert_at != "") {
1550  $par = new ilPCParagraph($this->getPage());
1551  $par->create($a_pg_obj, $insert_at[0], $insert_at[1], $from_placeholder);
1552  $par->writePCId($pc_id[1]);
1553  } else {
1554  $par = $a_pg_obj->getContentObject($pc_id[0], $pc_id[1]);
1555 
1556  if (!$par) {
1557  return $this->lng->txt("copg_page_element_not_found") . " (saveJS): " . $pc_id[0] . ":" . $pc_id[1] . ".";
1558  }
1559  }
1560  /*
1561  if ($a_insert_at != "") {
1562  $pc_id = $a_pg_obj->generatePCId();
1563  $par->writePCId($pc_id);
1564  $this->inserted_pc_id = $pc_id;
1565  } else {
1566  $this->inserted_pc_id = $pc_id[1];
1567  }*/
1568 
1569  $par->setLanguage($ilUser->getLanguage());
1570  $par->setCharacteristic($t["class"]);
1571 
1572  $t2 = $par->input2xml($t["text"], true, false);
1573  $this->log->debug("step 3: " . substr($t2, 0, 1000));
1574 
1576  $this->log->debug("step 4: " . substr($t2, 0, 1000));
1577 
1578  $updated = $par->setText($t2, true);
1579 
1580  if ($updated !== true) {
1581  echo $updated;
1582  exit;
1583  return false;
1584  }
1585  $updated = $par->updatePage($a_pg_obj);
1586  //$updated = $a_pg_obj->update();
1587  return $updated;
1588  }
1589 
1596  public function getLastSavedPCId($a_pg_obj, $a_as_ajax_str = false)
1597  {
1598  if ($a_as_ajax_str) {
1599  $a_pg_obj->stripHierIDs();
1600  $a_pg_obj->addHierIds();
1601  $ids = "###";
1602  //var_dump($this->inserted_pc_ids);
1603  $combined = $a_pg_obj->getHierIdsForPCIds(
1604  array($this->inserted_pc_id)
1605  );
1606  foreach ($combined as $pc_id => $hier_id) {
1607  //echo "1";
1608  $ids .= $sep . $hier_id . ":" . $pc_id;
1609  $sep = ";";
1610  }
1611  $ids .= "###";
1612  return $ids;
1613  }
1614 
1615  return $this->inserted_pc_id;
1616  }
1617 
1618 
1622  public static function handleAjaxContent($a_content)
1623  {
1624  $a_content = "<dummy>" . $a_content . "</dummy>";
1625 
1626  $doc = new DOMDocument();
1627 
1628  $content = ilUtil::stripSlashes($a_content, false);
1629 
1630  // $content = str_replace("&lt;", "<", $content);
1631  // $content = str_replace("&gt;", ">", $content);
1632  //echo "\n\n".$content;
1633  $res = $doc->loadXML($content);
1634 
1635  if (!$res) {
1636  return false;
1637  }
1638 
1639  // convert tags
1640  $xpath = new DOMXpath($doc);
1641 
1642  $tags = self::getXMLTagMap();
1643 
1644  $elements = $xpath->query("//span");
1645  include_once("./Services/Utilities/classes/class.ilDOM2Util.php");
1646  while (!is_null($elements) && !is_null($element = $elements->item(0))) {
1647  //$element = $elements->item(0);
1648  $class = $element->getAttribute("class");
1649  if (substr($class, 0, 16) == "ilc_text_inline_") {
1650  $class_arr = explode(" ", $class);
1651  $tag = substr($class_arr[0], 16);
1652  if (isset($tags[$tag])) { // known tag like strong
1653  $cnode = ilDOM2Util::changeName($element, "il" . substr($class_arr[0], 16), false);
1654  } else { // unknown tag -> marked text
1655  $cnode = ilDOM2Util::changeName($element, "ilMarked", false);
1656  $cnode->setAttribute("Class", substr($class_arr[0], 16));
1657  }
1658  for ($i = 1; $i < count($class_arr); $i++) {
1659  $tag = substr($class_arr[$i], 16);
1660  if (isset($tags[$tag])) { // known tag like strong
1661  $cnode = ilDOM2Util::addParent($cnode, "il" . substr($class_arr[$i], 16));
1662  } else { // unknown tag -> marked element
1663  $cnode = ilDOM2Util::addParent($cnode, "ilMarked");
1664  $cnode->setAttribute("Class", substr($class_arr[$i], 16));
1665  }
1666  }
1667  } else {
1668  ilDOM2Util::replaceByChilds($element);
1669  }
1670 
1671  $elements = $xpath->query("//span");
1672  }
1673 
1674  // convert tags
1675  $xpath = new DOMXpath($doc);
1676  $elements = $xpath->query("/dummy/div");
1677 
1678  $ret = array();
1679  if (!is_null($elements)) {
1680  foreach ($elements as $element) {
1681  $id = $element->getAttribute("id");
1682  $class = $element->getAttribute("class");
1683  $class = substr($class, 15);
1684  if (trim($class) == "") {
1685  $class = "Standard";
1686  }
1687 
1688  $text = $doc->saveXML($element);
1689  $text = str_replace("<br/>", "\n", $text);
1690 
1691  // remove wrapping div
1692  $pos = strpos($text, ">");
1693  $text = substr($text, $pos + 1);
1694  $pos = strrpos($text, "<");
1695  $text = substr($text, 0, $pos);
1696 
1697  // todo: remove empty spans <span ...> </span>
1698 
1699  // replace tags by bbcode
1700  foreach (ilPageContentGUI::_getCommonBBButtons() as $bb => $cl) {
1701  if (!in_array($bb, array("code", "tex", "fn", "xln"))) {
1702  $text = str_replace(
1703  "<il" . $cl . ">",
1704  "[" . $bb . "]",
1705  $text
1706  );
1707  $text = str_replace(
1708  "</il" . $cl . ">",
1709  "[/" . $bb . "]",
1710  $text
1711  );
1712  $text = str_replace("<il" . $cl . "/>", "", $text);
1713  }
1714  }
1715  $text = str_replace(
1716  array("<code>", "</code>"),
1717  array("[code]", "[/code]"),
1718  $text
1719  );
1720  $text = str_replace(
1721  array('<sup class="ilc_sup_Sup">', '<sup>', "</sup>"),
1722  array("[sup]", "[sup]", "[/sup]"),
1723  $text
1724  );
1725  $text = str_replace(
1726  array('<sub class="ilc_sub_Sub">', '<sub>', "</sub>"),
1727  array("[sub]", "[sub]", "[/sub]"),
1728  $text
1729  );
1730 
1731  $text = str_replace("<code/>", "", $text);
1732  $text = str_replace('<ul class="ilc_list_u_BulletedList"/>', "", $text);
1733  $text = str_replace('<ul class="ilc_list_o_NumberedList"/>', "", $text);
1734 
1735  // replace marked text
1736  // external links
1737  $any = "[^>]*";
1738  while (preg_match('~<ilMarked(' . $any . ')>~i', $text, $found)) {
1739  $found[0];
1740  $attribs = ilUtil::attribsToArray($found[1]);
1741  $text = str_replace("<ilMarked" . $found[1] . ">", "[marked class=\"" . $attribs["Class"] . "\"]", $text);
1742  }
1743  $text = str_replace("</ilMarked>", "[/marked]", $text);
1744 
1745 
1746  $ret[] = array("text" => $text, "id" => $id, "class" => $class);
1747  }
1748  }
1749 
1750  // we should only have one here!
1751  return $ret[0];
1752  }
1753 
1757  public static function handleAjaxContentPost($text)
1758  {
1759  $text = str_replace(
1760  array("&lt;ul&gt;", "&lt;/ul&gt;"),
1761  array("<SimpleBulletList>", "</SimpleBulletList>"),
1762  $text
1763  );
1764  $text = str_replace(
1765  array("&lt;ul class='ilc_list_u_BulletedList'&gt;", "&lt;/ul&gt;"),
1766  array("<SimpleBulletList>", "</SimpleBulletList>"),
1767  $text
1768  );
1769  $text = str_replace(
1770  array("&lt;ul class=\"ilc_list_u_BulletedList\"&gt;", "&lt;/ul&gt;"),
1771  array("<SimpleBulletList>", "</SimpleBulletList>"),
1772  $text
1773  );
1774  $text = str_replace(
1775  array("&lt;ol&gt;", "&lt;/ol&gt;"),
1776  array("<SimpleNumberedList>", "</SimpleNumberedList>"),
1777  $text
1778  );
1779  $text = str_replace(
1780  array("&lt;ol class='ilc_list_o_NumberedList'&gt;", "&lt;/ol&gt;"),
1781  array("<SimpleNumberedList>", "</SimpleNumberedList>"),
1782  $text
1783  );
1784  $text = str_replace(
1785  array("&lt;ol class=\"ilc_list_o_NumberedList\"&gt;", "&lt;/ol&gt;"),
1786  array("<SimpleNumberedList>", "</SimpleNumberedList>"),
1787  $text
1788  );
1789  $text = str_replace(
1790  array("&lt;li&gt;", "&lt;/li&gt;"),
1791  array("<SimpleListItem>", "</SimpleListItem>"),
1792  $text
1793  );
1794  $text = str_replace(
1795  array("&lt;li class='ilc_list_item_StandardListItem'&gt;", "&lt;/li&gt;"),
1796  array("<SimpleListItem>", "</SimpleListItem>"),
1797  $text
1798  );
1799  $text = str_replace(
1800  array("&lt;li class=\"ilc_list_item_StandardListItem\"&gt;", "&lt;/li&gt;"),
1801  array("<SimpleListItem>", "</SimpleListItem>"),
1802  $text
1803  );
1804 
1805  $text = str_replace(
1806  array("&lt;li class=\"ilc_list_item_StandardListItem\"/&gt;"),
1807  array("<SimpleListItem></SimpleListItem>"),
1808  $text
1809  );
1810 
1811  $text = str_replace("<SimpleBulletList><br />", "<SimpleBulletList>", $text);
1812  $text = str_replace("<SimpleNumberedList><br />", "<SimpleNumberedList>", $text);
1813  $text = str_replace("<br /><SimpleBulletList>", "<SimpleBulletList>", $text);
1814  $text = str_replace("<br /><SimpleNumberedList>", "<SimpleNumberedList>", $text);
1815  $text = str_replace("</SimpleBulletList><br />", "</SimpleBulletList>", $text);
1816  $text = str_replace("</SimpleNumberedList><br />", "</SimpleNumberedList>", $text);
1817  $text = str_replace("</SimpleListItem><br />", "</SimpleListItem>", $text);
1818 
1819  return $text;
1820  }
1821 
1829  public function updatePage($a_page)
1830  {
1831  $a_page->beforePageContentUpdate($this);
1832 
1833  $ret = $a_page->update();
1834  return $ret;
1835  }
1836 
1843  public function autoLinkGlossaries($a_glos)
1844  {
1845  if (is_array($a_glos) && count($a_glos) > 0) {
1846  // check which terms occur in the text (we may
1847  // get some false positives due to the strip_tags, but
1848  // we do not want to find strong or list or other stuff
1849  // within the tags
1850  $text = strip_tags($this->getText());
1851  $found_terms = array();
1852  foreach ($a_glos as $glo) {
1853  if (ilObject::_lookupType($glo) == "glo") {
1854  $ref_ids = ilObject::_getAllReferences($glo);
1855  $glo_ref_id = current($ref_ids);
1856  if ($glo_ref_id > 0) {
1857  $terms = ilGlossaryTerm::getTermList($glo_ref_id);
1858  foreach ($terms as $t) {
1859  if (is_int(stripos($text, $t["term"]))) {
1860  $found_terms[$t["id"]] = $t;
1861  }
1862  }
1863  }
1864  }
1865  }
1866  // did we find anything? -> modify content
1867  if (count($found_terms) > 0) {
1868  self::linkTermsInDom($this->dom, $found_terms, $this->par_node);
1869  }
1870  }
1871  }
1872 
1879  protected static function linkTermsInDom($a_dom, $a_terms, $a_par_node = null)
1880  {
1881  // sort terms by their length (shortes first)
1882  // to prevent that nested tags are builded
1883  foreach ($a_terms as $k => $t) {
1884  $a_terms[$k]["termlength"] = strlen($t["term"]);
1885  }
1886  $a_terms = ilUtil::sortArray($a_terms, "termlength", "asc", true);
1887 
1888 
1889  if ($a_dom instanceof php4DOMDocument) {
1890  $a_dom = $a_dom->myDOMDocument;
1891  }
1892  if ($a_par_node instanceof php4DOMElement) {
1893  $a_par_node = $a_par_node->myDOMNode;
1894  }
1895 
1896  $xpath = new DOMXPath($a_dom);
1897 
1898  if ($a_par_node == null) {
1899  $parnodes = $xpath->query("//Paragraph[@Characteristic != 'Code']");
1900  } else {
1901  $parnodes = $xpath->query(".//Paragraph[@Characteristic != 'Code']", $a_par_node->parentNode);
1902  }
1903 
1904  include_once("./Services/Utilities/classes/class.ilStr.php");
1905 
1906  foreach ($parnodes as $parnode) {
1907  $textnodes = $xpath->query('.//text()', $parnode);
1908  foreach ($textnodes as $node) {
1909  $p = $node->getNodePath();
1910 
1911  // we do not change text nodes inside of links
1912  if (!is_int(strpos($p, "/IntLink")) &&
1913  !is_int(strpos($p, "/ExtLink"))) {
1914  $node_val = $node->nodeValue;
1915 
1916  // all terms
1917  foreach ($a_terms as $t) {
1918  $pos = ilStr::strIPos($node_val, $t["term"]);
1919 
1920  // if term found
1921  while (is_int($pos)) {
1922  // check if we are in a tex tag, see #22261
1923  $tex_bpos = ilStr::strrPos(ilStr::subStr($node_val, 0, $pos), "[tex]");
1924  $tex_epos = ilStr::strPos($node_val, "[/tex]", $tex_bpos);
1925  if ($tex_bpos > 0 && $tex_epos > 0 && $tex_bpos < $pos && $tex_epos > $pos) {
1926  $pos += ilStr::strLen($t["term"]);
1927  } else {
1928 
1929  // check if the string is not included in another word
1930  // note that []
1931  $valid_limiters = array("", " ", "&nbsp;", ".", ",", ":", ";", "!", "?", "\"", "'", "(", ")");
1932  $b = ($pos > 0)
1933  ? ilStr::subStr($node_val, $pos - 1, 1)
1934  : "";
1935  $a = ilStr::subStr($node_val, $pos + ilStr::strLen($t["term"]), 1);
1936  if ((in_array($b, $valid_limiters) || htmlentities($b, null, 'utf-8') == "&nbsp;") && in_array($a, $valid_limiters)) {
1937  $mid = '[iln term="' . $t["id"] . '"]' .
1938  ilStr::subStr($node_val, $pos, ilStr::strLen($t["term"])) .
1939  "[/iln]";
1940 
1941  $node_val = ilStr::subStr($node_val, 0, $pos) .
1942  $mid .
1943  ilStr::subStr($node_val, $pos + ilStr::strLen($t["term"]));
1944 
1945  $pos += ilStr::strLen($mid);
1946  } else {
1947  $pos += ilStr::strLen($t["term"]);
1948  }
1949  }
1950  $pos = ilStr::strIPos($node_val, $t["term"], $pos);
1951  }
1952 
1953  // insert [iln] tags
1954  }
1955 
1956  $node->nodeValue = $node_val;
1957  }
1958 
1959  // var_dump($p);
1960 // var_dump($node->nodeValue);
1961  }
1962 
1963 
1964  // dump paragraph node
1965  $text = $a_dom->saveXML($parnode);
1966  $text = substr($text, 0, strlen($text) - strlen("</Paragraph>"));
1967  $text = substr($text, strpos($text, ">") + 1);
1968 
1969  // replace [iln] by tags with xml representation
1970  $text = self::intLinks2xml($text);
1971 
1972  // "set text"
1973  $temp_dom = domxml_open_mem(
1974  '<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $text . '</Paragraph>',
1976  $error
1977  );
1978  $temp_dom = $temp_dom->myDOMDocument;
1979 
1980  if (empty($error)) {
1981  // delete children of paragraph node
1982  $children = $parnode->childNodes;
1983  while ($parnode->hasChildNodes()) {
1984  $parnode->removeChild($parnode->firstChild);
1985  }
1986 
1987  // copy new content children in paragraph node
1988  $xpath_temp = new DOMXPath($temp_dom);
1989  $temp_pars = $xpath_temp->query("//Paragraph");
1990 
1991  foreach ($temp_pars as $new_par_node) {
1992  $new_childs = $new_par_node->childNodes;
1993 
1994  foreach ($new_childs as $new_child) {
1995  //$cloned_child = $new_child->cloneNode(true);
1996  $cloned_child = $a_dom->importNode($new_child, true);
1997  $parnode->appendChild($cloned_child);
1998  }
1999  }
2000  }
2001  }
2002  // exit;
2003  }
2004 
2005 
2012  public static function autoLinkGlossariesPage($a_page, $a_terms)
2013  {
2014  $a_page->buildDom();
2015  $a_dom = $a_page->getDom();
2016 
2017  self::linkTermsInDom($a_dom, $a_terms);
2018 
2019  $a_page->update();
2020  }
2021 
2030  public static function afterPageUpdate($a_page, DOMDocument $a_domdoc, $a_xml, $a_creation)
2031  {
2032  // pc paragraph
2033  self::saveMetaKeywords($a_page, $a_domdoc);
2034  self::saveAnchors($a_page, $a_domdoc);
2035  }
2036 
2042  public static function beforePageDelete($a_page)
2043  {
2044  // delete anchors
2045  self::_deleteAnchors($a_page->getParentType(), $a_page->getId(), $a_page->getLanguage());
2046  }
2047 
2056  public static function afterPageHistoryEntry($a_page, DOMDocument $a_old_domdoc, $a_old_xml, $a_old_nr)
2057  {
2058  }
2059 
2065  public static function saveAnchors($a_page, $a_domdoc)
2066  {
2067  self::_deleteAnchors($a_page->getParentType(), $a_page->getId(), $a_page->getLanguage());
2068 
2069  // get all anchors
2070  $xpath = new DOMXPath($a_domdoc);
2071  $nodes = $xpath->query('//Anchor');
2072  $saved = array();
2073  foreach ($nodes as $node) {
2074  $name = $node->getAttribute("Name");
2075  if (trim($name) != "" && !in_array($name, $saved)) {
2076  self::_saveAnchor($a_page->getParentType(), $a_page->getId(), $a_page->getLanguage(), $name);
2077  $saved[] = $name;
2078  }
2079  }
2080  }
2081 
2085  public static function _deleteAnchors($a_parent_type, $a_page_id, $a_page_lang)
2086  {
2087  global $DIC;
2088 
2089  $ilDB = $DIC->database();
2090 
2091  $ilDB->manipulate(
2092  "DELETE FROM page_anchor WHERE " .
2093  " page_parent_type = " . $ilDB->quote($a_parent_type, "text") .
2094  " AND page_id = " . $ilDB->quote($a_page_id, "integer") .
2095  " AND page_lang = " . $ilDB->quote($a_page_lang, "text")
2096  );
2097  }
2098 
2102  public static function _saveAnchor($a_parent_type, $a_page_id, $a_page_lang, $a_anchor_name)
2103  {
2104  global $DIC;
2105 
2106  $ilDB = $DIC->database();
2107 
2108  $ilDB->manipulate("INSERT INTO page_anchor " .
2109  "(page_parent_type, page_id, page_lang, anchor_name) VALUES (" .
2110  $ilDB->quote($a_parent_type, "text") . "," .
2111  $ilDB->quote($a_page_id, "integer") . "," .
2112  $ilDB->quote($a_page_lang, "text") . "," .
2113  $ilDB->quote($a_anchor_name, "text") .
2114  ")");
2115  }
2116 
2120  public static function _readAnchors($a_parent_type, $a_page_id, $a_page_lang = "-")
2121  {
2122  global $DIC;
2123 
2124  $ilDB = $DIC->database();
2125 
2126  $and_lang = ($a_page_lang != "")
2127  ? " AND page_lang = " . $ilDB->quote($a_page_lang, "text")
2128  : "";
2129 
2130  $set = $ilDB->query(
2131  "SELECT * FROM page_anchor " .
2132  " WHERE page_parent_type = " . $ilDB->quote($a_parent_type, "text") .
2133  " AND page_id = " . $ilDB->quote($a_page_id, "integer") .
2134  $and_lang
2135  );
2136  $anchors = array();
2137  while ($rec = $ilDB->fetchAssoc($set)) {
2138  $anchors[] = $rec["anchor_name"];
2139  }
2140  return $anchors;
2141  }
2142 
2149  public static function saveMetaKeywords($a_page, $a_domdoc)
2150  {
2151  // not nice, should be set by context per method
2152  if ($a_page->getParentType() == "gdf" ||
2153  $a_page->getParentType() == "lm") {
2154  // get existing keywords
2155  $keywords = array();
2156 
2157  // find all Keyw tags
2158  $xpath = new DOMXPath($a_domdoc);
2159  $nodes = $xpath->query('//Keyw');
2160  foreach ($nodes as $node) {
2161  $k = trim(strip_tags($node->nodeValue));
2162  if (!in_array($k, $keywords)) {
2163  $keywords[] = $k;
2164  }
2165  }
2166 
2167  $meta_type = ($a_page->getParentType() == "gdf")
2168  ? "gdf"
2169  : "pg";
2170  $meta_rep_id = $a_page->getParentId();
2171  $meta_id = $a_page->getId();
2172 
2173  include_once("./Services/MetaData/classes/class.ilMD.php");
2174  $md_obj = new ilMD($meta_rep_id, $meta_id, $meta_type);
2175  $mkeywords = array();
2176  $lang = "";
2177  if (is_object($md_section = $md_obj->getGeneral())) {
2178  foreach ($ids = $md_section->getKeywordIds() as $id) {
2179  $md_key = $md_section->getKeyword($id);
2180  $mkeywords[] = strtolower($md_key->getKeyword());
2181  if ($lang == "") {
2182  $lang = $md_key->getKeywordLanguageCode();
2183  }
2184  }
2185  if ($lang == "") {
2186  foreach ($ids = $md_section->getLanguageIds() as $id) {
2187  $md_lang = $md_section->getLanguage($id);
2188  if ($lang == "") {
2189  $lang = $md_lang->getLanguageCode();
2190  }
2191  }
2192  }
2193  foreach ($keywords as $k) {
2194  if (!in_array(strtolower($k), $mkeywords)) {
2195  if (trim($k) != "" && $lang != "") {
2196  $md_key = $md_section->addKeyword();
2197  $md_key->setKeyword(ilUtil::stripSlashes($k));
2198  $md_key->setKeywordLanguage(new ilMDLanguageItem($lang));
2199  $md_key->save();
2200  }
2201  $mkeywords[] = strtolower($k);
2202  }
2203  }
2204  }
2205  }
2206  }
2207 
2211  public function getJavascriptFiles($a_mode)
2212  {
2213  $adve_settings = new ilSetting("adve");
2214 
2215  if ($a_mode != "edit" && $adve_settings->get("auto_url_linking")) {
2216  include_once("./Services/Link/classes/class.ilLinkifyUtil.php");
2218  }
2219 
2220  return array();
2221  }
2222 
2229  public function getOnloadCode($a_mode)
2230  {
2231  $adve_settings = new ilSetting("adve");
2232 
2233  if ($a_mode != "edit" && $adve_settings->get("auto_url_linking")) {
2234  return array("il.ExtLink.autolink('.ilc_Paragraph, .ilc_page_fn_Footnote','ilc_link_ExtLink');");
2235  }
2236 
2237  return array();
2238  }
2239 
2243  public function getModel()
2244  {
2245  $model = new \stdClass();
2246  $s_text = $this->getText();
2247  $s_text = $this->xml2output($s_text, true, false);
2248  $s_text = ilPCParagraphGUI::xml2outputJS($s_text);
2249  $char = $this->getCharacteristic();
2250  if ($char == "") {
2251  $char = "Standard";
2252  }
2253  $model->characteristic = $char;
2254  $model->text = $s_text;
2255 
2256  return $model;
2257  }
2258 
2265  public function insert(\ilPageObject $page, $a_content, $a_char, $a_pc_id, $a_insert_at = "", $a_new_pc_id = "")
2266  {
2267  $ilUser = $this->user;
2268 
2269  $this->log->debug("step 1: " . substr($a_content, 0, 1000));
2270 
2271  try {
2272  $t = self::handleAjaxContent($a_content);
2273  } catch (Exception $ex) {
2274  return $ex->getMessage() . ": " . htmlentities($a_content);
2275  }
2276 
2277  $this->log->debug("step 2: " . substr($t["text"], 0, 1000));
2278  if ($t === false) {
2279  return false;
2280  }
2281 
2282  $pc_id = explode(":", $a_pc_id);
2283  $insert_at = explode(":", $a_insert_at);
2284  $t_id = explode(":", $t["id"]);
2285 
2286  // insert new paragraph
2287  if ($a_insert_at != "") {
2288  $par = new ilPCParagraph($this->getPage());
2289  $par->create($page, $insert_at[0], $insert_at[1]);
2290  } else {
2291  $par = $a_pg_obj->getContentObject($pc_id[0], $pc_id[1]);
2292  }
2293 
2294  if ($a_insert_at != "") {
2295  $pc_id = ($a_new_pc_id != "")
2296  ? $a_new_pc_id
2297  : $a_pg_obj->generatePCId();
2298  $par->writePCId($pc_id);
2299  $this->inserted_pc_id = $pc_id;
2300  } else {
2301  $this->inserted_pc_id = $pc_id[1];
2302  }
2303 
2304  $par->setLanguage($ilUser->getLanguage());
2305  $par->setCharacteristic($t["class"]);
2306 
2307  $t2 = $par->input2xml($t["text"], true, false);
2308  $this->log->debug("step 3: " . substr($t2, 0, 1000));
2309 
2311  $this->log->debug("step 4: " . substr($t2, 0, 1000));
2312 
2313  $updated = $par->setText($t2, true);
2314 
2315  if ($updated !== true) {
2316  echo $updated;
2317  exit;
2318  return false;
2319  }
2320  $updated = $par->updatePage($a_pg_obj);
2321  //$updated = $a_pg_obj->update();
2322  return $updated;
2323  }
2324 }
static _lookupLogin($a_user_id)
lookup login
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
create(&$a_pg_obj, $a_hier_id, $a_pc_id="", $from_placeholder=false)
Create paragraph node (incl.
getLastSavedPCId($a_pg_obj, $a_as_ajax_str=false)
Get last inserted pc ids.
exit
Definition: login.php:29
createAfter($node)
Create paragraph node (incl.
static strLen($a_string)
Definition: class.ilStr.php:78
static attribsToArray($a_str)
converts a string of format var1 = "val1" var2 = "val2" ...
static getBBMap()
Get bb to xml tag map.
static strPos($a_haystack, $a_needle, $a_offset=null)
Definition: class.ilStr.php:30
static xml2outputReplaceLists($a_text)
Replaces with *.
$target_type
Definition: goto.php:50
getSubCharacteristic()
get attribute subcharacteristic
xpath_new_context($dom_document)
static beforePageDelete($a_page)
Before page is being deleted.
getDownloadTitle()
get attribute download title
setShowLineNumbers($a_char)
set attribute showlinenumbers
removeTrailingBr($a_str)
Remove trailing
static xml2outputJS($s_text)
Prepare content for js output.
static segmentString($a_haystack, $a_needles)
Segments a string into an array at each position of a substring.
success()
Definition: success.php:2
static handleAjaxContentPost($text)
Post input2xml handling of ajax content.
domxml_open_mem($str, $mode=0, &$error=null)
static getLocalJsPaths()
Get paths of necessary js files.
input2xml($a_text, $a_wysiwyg=0, $a_handle_lists=true)
xpath_eval($xpath_context, $eval_str, $contextnode=null)
setDownloadTitle($a_char)
set attribute download title
setText($a_text, $a_auto_split=false)
Set (xml) content of text paragraph.
static _lookupId($a_user_str)
Lookup id by login.
$target_id
Definition: goto.php:51
static replaceByChilds($node)
Replace a node by its child.
setNode($a_node)
Set Page Content Node.
Class ilPCParagraph.
setType($a_type)
Set Type.
static subStr($a_str, $a_start, $a_length=null)
Definition: class.ilStr.php:15
static getXMLTagMap()
Get tag to bb map.
getLanguage()
get language
getParagraphSequenceContent($a_pg_obj)
Get paragraph sequenc of current paragraph.
static xml2output($a_text, $a_wysiwyg=false, $a_replace_lists=true, $unmask=true)
Converts xml from DB to output in edit textarea.
user()
Definition: user.php:4
Class ilPageContent.
static _getAllReferences($a_id)
get all reference ids of object
setLanguage($a_lang)
set language
static replaceBBTagByMatching(string $start_tag, string $end_tag, string $xml_tag_name, string $text, array $attribs)
Transforms [iln...]...[] to <IntLink...>...</IntLink>, if content is valid, otherwise it removes the ...
getAutoIndent()
Get AutoIndent (Code Paragraphs)
init()
Init page content component.
if($format !==null) $name
Definition: metadata.php:230
static strIPos($a_haystack, $a_needle, $a_offset=null)
Definition: class.ilStr.php:48
static autoLinkGlossariesPage($a_page, $a_terms)
Auto link glossary of whole page.
readPCId()
Read PC Id.
getType()
Need to override getType from ilPageContent to distinguish between Pararagraph and Source...
setSubCharacteristic($a_char)
set attribute subcharacteristic
createBeforeNode(&$node)
Create new page content (incl.
static afterPageHistoryEntry($a_page, DOMDocument $a_old_domdoc, $a_old_xml, $a_old_nr)
After page history entry has been created.
php4DomElement
static input2xmlReplaceLists($a_text)
Converts xml from DB to output in edit textarea.
foreach($_POST as $key=> $value) $res
static handleAjaxContent($a_content)
Handle ajax content.
static linkTermsInDom($a_dom, $a_terms, $a_par_node=null)
Link terms in a dom page object in bb style.
insert(\ilPageObject $page, $a_content, $a_char, $a_pc_id, $a_insert_at="", $a_new_pc_id="")
Save input coming from ajax.
updatePage($a_page)
Update page object (it would be better to have this centralized and to change the constructors and pa...
static isValidTagContent(string $content)
createAtNode(&$node)
Create new page content (incl.
setCharacteristic($a_char)
Set Characteristic of paragraph.
static strrPos($a_haystack, $a_needle, $a_offset=null)
Definition: class.ilStr.php:39
getText($a_short_mode=false)
Get (xml) content of paragraph.
autoLinkGlossaries($a_glos)
Auto link glossaries.
Class ilPageObject Handles PageObjects of ILIAS Learning Modules (see ILIAS DTD)
global $DIC
Definition: goto.php:24
static changeName($node, $name, $keep_attributes=true)
Change name of a node.
getCharacteristic()
Get characteristic of paragraph.
static getTermList( $a_glo_ref_id, $searchterm="", $a_first_letter="", $a_def="", $a_tax_node=0, $a_add_amet_fields=false, array $a_amet_filter=null, $a_include_references=false)
Get all terms for given set of glossary ids.
static replaceBBCode($a_text, $a_bb, $a_tag)
Replace bb code.
static saveAnchors($a_page, $a_domdoc)
Save anchors.
$n
Definition: RandomTest.php:85
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
checkTextArray($text)
Check text array.
const IL_INSERT_AFTER
static _lookupType($a_id, $a_reference=false)
lookup object type
static _readAnchors($a_parent_type, $a_page_id, $a_page_lang="-")
Read anchors of a page.
autoSplit($a_text)
This function splits a paragraph text that has been already processed with input2xml at each header p...
static _saveAnchor($a_parent_type, $a_page_id, $a_page_lang, $a_anchor_name)
Save an anchor.
static _deleteAnchors($a_parent_type, $a_page_id, $a_page_lang)
Delete anchors of a page.
$rows
Definition: xhr_table.php:10
static addParent($node, $name)
Add parent.
$lang
Definition: xapiexit.php:8
static _input2xml($a_text, $a_lang, $a_wysiwyg=0, $a_handle_lists=true)
converts user input to xml
createPageContentNode($a_set_this_node=true)
Create page content node (always use this method first when adding a new element) ...
static _getCommonBBButtons()
Get common bb buttons.
const DOMXML_LOAD_PARSING
global $ilDB
$ret
Definition: parser.php:6
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
saveJS( $a_pg_obj, $a_content, $a_char, $a_pc_id, $a_insert_at="", $from_placeholder=false)
Save input coming from ajax.
static afterPageUpdate($a_page, DOMDocument $a_domdoc, $a_xml, $a_creation)
After page has been updated (or created)
$ilUser
Definition: imgupload.php:18
getOnloadCode($a_mode)
Get onload code.
handleNextBr($a_str)
Remove preceding
static saveMetaKeywords($a_page, $a_domdoc)
save all keywords
getJavascriptFiles($a_mode)
Get Javascript files.
readHierId()
Read PC Id.
static intLinks2xml($a_text)
internal links to xml
$i
Definition: metadata.php:24
getShowLineNumbers()
get attribute showlinenumbers