ILIAS  release_7 Revision v7.30-3-g800a261c036
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
4require_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"])) {
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]);
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"])) {
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 == "") {
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 {
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}
user()
Definition: user.php:4
$n
Definition: RandomTest.php:85
An exception for terminatinating execution or to throw for unit testing.
const IL_INSERT_AFTER
static addParent($node, $name)
Add parent.
static replaceByChilds($node)
Replace a node by its child.
static changeName($node, $name, $keep_attributes=true)
Change name of a node.
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 getLocalJsPaths()
Get paths of necessary js files.
static _lookupLogin($a_user_id)
lookup login
static _lookupId($a_user_str)
Lookup id by login.
static _getAllReferences($a_id)
get all reference ids of object
static _lookupType($a_id, $a_reference=false)
lookup object type
static xml2outputJS($s_text)
Prepare content for js output.
Class ilPCParagraph.
getText($a_short_mode=false)
Get (xml) content of paragraph.
handleNextBr($a_str)
Remove preceding
static getXMLTagMap()
Get tag to bb map.
static intLinks2xml($a_text)
internal links to xml
removeTrailingBr($a_str)
Remove trailing
static _saveAnchor($a_parent_type, $a_page_id, $a_page_lang, $a_anchor_name)
Save an anchor.
getLastSavedPCId($a_pg_obj, $a_as_ajax_str=false)
Get last inserted pc ids.
static _readAnchors($a_parent_type, $a_page_id, $a_page_lang="-")
Read anchors of a page.
getType()
Need to override getType from ilPageContent to distinguish between Pararagraph and Source.
static _input2xml($a_text, $a_lang, $a_wysiwyg=0, $a_handle_lists=true)
converts user input to xml
static autoLinkGlossariesPage($a_page, $a_terms)
Auto link glossary of whole page.
static xml2output($a_text, $a_wysiwyg=false, $a_replace_lists=true, $unmask=true)
Converts xml from DB to output in edit textarea.
static linkTermsInDom($a_dom, $a_terms, $a_par_node=null)
Link terms in a dom page object in bb style.
setNode($a_node)
Set Page Content Node.
getShowLineNumbers()
get attribute showlinenumbers
autoLinkGlossaries($a_glos)
Auto link glossaries.
saveJS( $a_pg_obj, $a_content, $a_char, $a_pc_id, $a_insert_at="", $from_placeholder=false)
Save input coming from ajax.
static saveAnchors($a_page, $a_domdoc)
Save anchors.
static handleAjaxContent($a_content)
Handle ajax content.
init()
Init page content component.
setSubCharacteristic($a_char)
set attribute subcharacteristic
createAtNode(&$node)
Create new page content (incl.
input2xml($a_text, $a_wysiwyg=0, $a_handle_lists=true)
createAfter($node)
Create paragraph node (incl.
static isValidTagContent(string $content)
static input2xmlReplaceLists($a_text)
Converts xml from DB to output in edit textarea.
static beforePageDelete($a_page)
Before page is being deleted.
setDownloadTitle($a_char)
set attribute download title
checkTextArray($text)
Check text array.
static xml2outputReplaceLists($a_text)
Replaces with *.
getAutoIndent()
Get AutoIndent (Code Paragraphs)
getDownloadTitle()
get attribute download title
static afterPageUpdate($a_page, DOMDocument $a_domdoc, $a_xml, $a_creation)
After page has been updated (or created)
setText($a_text, $a_auto_split=false)
Set (xml) content of text paragraph.
static replaceBBCode($a_text, $a_bb, $a_tag)
Replace bb code.
getOnloadCode($a_mode)
Get onload code.
static getBBMap()
Get bb to xml tag map.
setShowLineNumbers($a_char)
set attribute showlinenumbers
setLanguage($a_lang)
set language
static afterPageHistoryEntry($a_page, DOMDocument $a_old_domdoc, $a_old_xml, $a_old_nr)
After page history entry has been created.
setCharacteristic($a_char)
Set Characteristic of paragraph.
static handleAjaxContentPost($text)
Post input2xml handling of ajax content.
create(&$a_pg_obj, $a_hier_id, $a_pc_id="", $from_placeholder=false)
Create paragraph node (incl.
static replaceBBTagByMatching(string $start_tag, string $end_tag, string $xml_tag_name, string $text, array $attribs)
Transforms [iln...]...[\iln] to <IntLink...>...</IntLink>, if content is valid, otherwise it removes ...
static saveMetaKeywords($a_page, $a_domdoc)
save all keywords
static segmentString($a_haystack, $a_needles)
Segments a string into an array at each position of a substring.
getLanguage()
get language
createBeforeNode(&$node)
Create new page content (incl.
autoSplit($a_text)
This function splits a paragraph text that has been already processed with input2xml at each header p...
getParagraphSequenceContent($a_pg_obj)
Get paragraph sequenc of current paragraph.
updatePage($a_page)
Update page object (it would be better to have this centralized and to change the constructors and pa...
getSubCharacteristic()
get attribute subcharacteristic
static _deleteAnchors($a_parent_type, $a_page_id, $a_page_lang)
Delete anchors of a page.
getCharacteristic()
Get characteristic of paragraph.
getJavascriptFiles($a_mode)
Get Javascript files.
insert(\ilPageObject $page, $a_content, $a_char, $a_pc_id, $a_insert_at="", $a_new_pc_id="")
Save input coming from ajax.
static _getCommonBBButtons()
Get common bb buttons.
Class ilPageContent.
createPageContentNode($a_set_this_node=true)
Create page content node (always use this method first when adding a new element)
readHierId()
Read PC Id.
readPCId()
Read PC Id.
setType($a_type)
Set Type.
Class ilPageObject Handles PageObjects of ILIAS Learning Modules (see ILIAS DTD)
ILIAS Setting Class.
static strPos($a_haystack, $a_needle, $a_offset=null)
Definition: class.ilStr.php:30
static strrPos($a_haystack, $a_needle, $a_offset=null)
Definition: class.ilStr.php:39
static strIPos($a_haystack, $a_needle, $a_offset=null)
Definition: class.ilStr.php:48
static subStr($a_str, $a_start, $a_length=null)
Definition: class.ilStr.php:15
static strLen($a_string)
Definition: class.ilStr.php:78
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
static attribsToArray($a_str)
converts a string of format var1 = "val1" var2 = "val2" ... into an array
global $DIC
Definition: goto.php:24
$target_id
Definition: goto.php:51
$target_type
Definition: goto.php:50
$ilUser
Definition: imgupload.php:18
xpath_eval($xpath_context, $eval_str, $contextnode=null)
domxml_open_mem($str, $mode=0, &$error=null)
xpath_new_context($dom_document)
const DOMXML_LOAD_PARSING
exit
Definition: login.php:29
if($format !==null) $name
Definition: metadata.php:230
$i
Definition: metadata.php:24
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
$ret
Definition: parser.php:6
foreach($_POST as $key=> $value) $res
global $ilDB
success()
Definition: success.php:2
$lang
Definition: xapiexit.php:8
$rows
Definition: xhr_table.php:10