ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilPCParagraph.php
Go to the documentation of this file.
1<?php
2
27{
28 protected string $inserted_pc_id;
29 protected ilObjUser $user;
30 protected ilLanguage $lng;
31
32 protected static array $bb_tags = array(
33 "com" => "Comment",
34 "emp" => "Emph",
35 "str" => "Strong",
36 "fn" => "Footnote",
37 "code" => "Code",
38 "acc" => "Accent",
39 "imp" => "Important",
40 "kw" => "Keyw",
41 "sub" => "Sub",
42 "sup" => "Sup",
43 "quot" => "Quotation",
44 );
45
55 public static function attribsToArray(string $a_str): array
56 {
57 $attribs = [];
58 while (is_int(strpos($a_str, "="))) {
59 $eq_pos = strpos($a_str, "=");
60 $qu1_pos = strpos($a_str, "\"");
61 $qu2_pos = strpos(substr($a_str, $qu1_pos + 1), "\"") + $qu1_pos + 1;
62 if (is_int($eq_pos) && is_int($qu1_pos) && is_int($qu2_pos)) {
63 $var = trim(substr($a_str, 0, $eq_pos));
64 $val = trim(substr($a_str, $qu1_pos + 1, ($qu2_pos - $qu1_pos) - 1));
65 $attribs[$var] = $val;
66 $a_str = substr($a_str, $qu2_pos + 1);
67 } else {
68 $a_str = "";
69 }
70 }
71 return $attribs;
72 }
73
74 public function init(): void
75 {
76 global $DIC;
77
78 $this->user = $DIC->user();
79 $this->lng = $DIC->language();
80 $this->setType("par");
81 }
82
86 protected static function getBBMap(): array
87 {
88 return self::$bb_tags;
89 }
90
94 protected static function getXMLTagMap(): array
95 {
96 return array_flip(self::$bb_tags);
97 }
98
103 protected function createAfter(DomNode $node): void
104 {
105 $node = $this->getNewPageContentNode();
106 if ($succ_node = $node->nextSibling) {
107 $node = $succ_node->parentNode->insertBefore($node, $succ_node);
108 } else {
109 $parent_node = $node->parentNode;
110 $node = $parent_node->appendChild($node);
111 }
112 $par_node = $this->dom_doc->createElement("Paragraph");
113 $par_node = $node->appendChild($par_node);
114 $par_node->setAttribute("Language", "");
115 $this->setDomNode($node);
116 }
117
122 public function create(
123 ilPageObject $a_pg_obj,
124 string $a_hier_id,
125 string $a_pc_id = "",
126 bool $from_placeholder = false
127 ): void {
128 //echo "-$a_pc_id-";
129 //echo "<br>-".htmlentities($a_pg_obj->getXMLFromDom())."-<br><br>"; mk();
130 $this->createPageContentNode();
131
132 // this next line kicks out placeholders, if something is inserted
133 $a_pg_obj->insertContent(
134 $this,
135 $a_hier_id,
137 $a_pc_id,
138 $from_placeholder
139 );
140
141 $par_node = $this->dom_doc->createElement("Paragraph");
142 $par_node = $this->getDomNode()->appendChild($par_node);
143 $par_node->setAttribute("Language", "");
144 }
145
152 public function setText(
153 string $a_text,
154 bool $a_auto_split = false
155 ) {
156 $text = $a_text;
157 if ($a_auto_split) {
158 $text = $this->autoSplit($a_text);
159 } else {
160 $text = [["level" => 0, "text" => $text]];
161 }
162 $error = $this->checkTextArray($text);
163
164 $orig_characteristic = "";
165 // remove all childs
166 if (empty($error)) {
167 $t = $text[0]["text"] ?? "";
168 $temp_dom = $this->dom_util->docFromString(
169 '<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $t . '</Paragraph>',
170 $error
171 );
172
173 // delete children of paragraph node
174 $this->dom_util->deleteAllChilds($this->getChildNode());
175
176 // copy new content children in paragraph node
177 $path = "//Paragraph";
178 $nodes = $this->dom_util->path(
179 $temp_dom,
180 $path
181 );
182 if (count($nodes) == 1) {
183 $new_par_node = $nodes->item(0);
184 $new_childs = $new_par_node->childNodes;
185
186 foreach ($new_childs as $new_child) {
187 $cloned_child = $new_child->cloneNode(true);
188 $cloned_child = $this->dom_doc->importNode($cloned_child, true);
189 $this->getChildNode()->appendChild($cloned_child);
190 }
191 $orig_characteristic = $this->getCharacteristic();
192
193 // if headlines are entered and current characteristic is a headline
194 // use no characteristic as standard
195 if ((count($text) > 1) && (substr($orig_characteristic, 0, 8) == "Headline")) {
196 $orig_characteristic = "";
197 }
198 if (isset($text[0]["level"]) && $text[0]["level"] > 0) {
199 $this->getChildNode()->setAttribute("Characteristic", 'Headline' . $text[0]["level"]);
200 }
201 }
202
203 $ok = true;
204
205 $c_node = $this->getDomNode();
206 // add other chunks afterwards
207 for ($i = 1, $iMax = count($text); $i < $iMax; $i++) {
208 if ($ok) {
209 $next_par = new ilPCParagraph($this->getPage());
210 $next_par->createAfter($c_node);
211 $next_par->setLanguage($this->getLanguage());
212 if ($text[$i]["level"] > 0) {
213 $next_par->setCharacteristic("Headline" . $text[$i]["level"]);
214 } else {
215 $next_par->setCharacteristic($orig_characteristic);
216 }
217 $ok = $next_par->setText($text[$i]["text"], false);
218 $c_node = $next_par->getDomNode();
219 }
220 }
221
222 return true;
223 } else {
224 // We want the correct number of \n here to have the real lines numbers
225 $check = array_reduce($text, function ($t, $i) {
226 return $t . $i["text"];
227 });
228 $text = str_replace("<br>", "\n", $check); // replace <br> with \n to get correct line
229 $text = str_replace("<br/>", "\n", $text);
230 $text = str_replace("<br />", "\n", $text);
231 $text = str_replace("</SimpleListItem>", "</SimpleListItem>\n", $text);
232 $text = str_replace("<SimpleBulletList>", "\n<SimpleBulletList>", $text);
233 $text = str_replace("<SimpleNumberedList>", "\n<SimpleNumberedList>", $text);
234 $text = str_replace("<Paragraph>\n", "<Paragraph>", $text);
235 $text = str_replace("</Paragraph>", "</Paragraph>\n", $text);
236 $doc = $this->dom_util->docFromString(
237 '<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $text . '</Paragraph>',
238 $error
239 );
240 $estr = (string) $error;
241 if (DEVMODE) {
242 $estr .= "<br />" . $text;
243 }
244
245 return $estr;
246 }
247 }
248
252 protected function checkTextArray(array $text): ?string
253 {
254 $check = "";
255 foreach ($text as $t) {
256 $check .= "<Paragraph>" . $t["text"] . "</Paragraph>";
257 }
258 $error = null;
259 $this->dom_util->docFromString(
260 '<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $check . '</Paragraph>',
261 $error
262 );
263 return $error;
264 }
265
269 public function getText(bool $a_short_mode = false): string
270 {
271 if (is_object($this->getChildNode())) {
272 $content = "";
273 foreach ($this->getChildNode()->childNodes as $c) {
274 $content .= $this->dom_util->dump($c);
275 }
276 return $content;
277 } else {
278 return "";
279 }
280 }
281
282 public function setCharacteristic(string $a_char): void
283 {
284 $this->dom_util->setAttribute($this->getChildNode(), "Characteristic", $a_char);
285 }
286
287 public function getCharacteristic(): string
288 {
289 return (string) $this->getChildNode()?->getAttribute("Characteristic");
290 }
291
292 public function setSubCharacteristic(string $a_char): void
293 {
294 $this->dom_util->setAttribute($this->getChildNode(), "SubCharacteristic", $a_char);
295 }
296
297 public function getAutoIndent(): string
298 {
299 return (string) $this->getChildNode()->getAttribute("AutoIndent");
300 }
301
302 public function setAutoIndent(string $ind): void
303 {
304 $this->dom_util->setAttribute($this->getChildNode(), "AutoIndent", $ind);
305 }
306
307 public function getSubCharacteristic(): string
308 {
309 return (string) $this->getChildNode()?->getAttribute("SubCharacteristic");
310 }
311
312 public function setDownloadTitle(string $title): void
313 {
314 $this->dom_util->setAttribute($this->getChildNode(), "DownloadTitle", $title);
315 }
316
317 public function getDownloadTitle(): string
318 {
319 return (string) $this->getChildNode()?->getAttribute("DownloadTitle");
320 }
321
322 public function setShowLineNumbers(string $a_char): void
323 {
324 $a_char = empty($a_char)
325 ? "n"
326 : $a_char;
327
328 $this->getChildNode()->setAttribute("ShowLineNumbers", $a_char);
329 }
330
331 public function getShowLineNumbers(): string
332 {
333 return (string) $this->getChildNode()?->getAttribute("ShowLineNumbers");
334 }
335
336 public function setLanguage(string $a_lang): void
337 {
338 $this->getChildNode()->setAttribute("Language", $a_lang);
339 }
340
341 public function getLanguage(): string
342 {
343 return $this->getChildNode()->getAttribute("Language");
344 }
345
346 public function input2xml(
347 string $a_text,
348 bool $a_wysiwyg = false,
349 bool $a_handle_lists = true
350 ): string {
351 return $this->_input2xml($a_text, $this->getLanguage(), $a_wysiwyg, $a_handle_lists);
352 }
353
354 protected static function replaceBBCode(
355 string $a_text,
356 string $a_bb,
357 string $a_tag
358 ): string {
359 $a_text = preg_replace('/\[' . $a_bb . '\]/i', "<" . $a_tag . ">", $a_text);
360 $a_text = preg_replace('/\[\/' . $a_bb . '\]/i', "</" . $a_tag . ">", $a_text);
361 return $a_text;
362 }
363
369 public static function _input2xml(
370 string $a_text,
371 string $a_lang,
372 bool $a_wysiwyg = false,
373 bool $a_handle_lists = true
374 ): string {
375 $log = null;
376 if (!defined('COPAGE_TEST')) {
378 $log->debug("_input2xml");
379 $log->debug("...start ");
380 $log->debug("...text: " . substr($a_text, 0, 1000));
381 $log->debug("...lang: " . $a_lang);
382 $log->debug("...wysiwyg: " . $a_wysiwyg);
383 $log->debug("...handle_lists: " . $a_handle_lists);
384 }
385
386 if (!$a_wysiwyg) {
387 $a_text = ilUtil::stripSlashes($a_text, false);
388 }
389
390 if ($a_wysiwyg) {
391 $a_text = str_replace("<br />", chr(10), $a_text);
392 }
393
394 // note: the order of the processing steps is crucial
395 // and should be the same as in xml2output() in REVERSE order!
396 $a_text = trim($a_text);
397
398 //echo "<br>between:".htmlentities($a_text);
399
400 // mask html
401 if (!$a_wysiwyg) {
402 $a_text = str_replace("&", "&amp;", $a_text);
403 }
404 $a_text = str_replace("<", "&lt;", $a_text);
405 $a_text = str_replace(">", "&gt;", $a_text);
406
407 // mask curly brackets
408 /*
409 echo htmlentities($a_text);
410 $a_text = str_replace("{", "&#123;", $a_text);
411 $a_text = str_replace("}", "&#125;", $a_text);
412 echo htmlentities($a_text);*/
413
414 // linefeed to br
415 $a_text = str_replace(chr(13) . chr(10), "<br />", $a_text);
416 $a_text = str_replace(chr(13), "<br />", $a_text);
417 $a_text = str_replace(chr(10), "<br />", $a_text);
418
419 if ($a_handle_lists) {
420 $a_text = ilPCParagraph::input2xmlReplaceLists($a_text);
421 }
422
423 foreach (self::getBBMap() as $bb => $tag) {
424 // remove empty tags
425 $a_text = str_replace("[" . $bb . "][/" . $bb . "]", "", $a_text);
426
427 // replace bb code by tag
428 $a_text = self::replaceBBCode($a_text, $bb, $tag);
429 }
430
431 $a_text = self::intLinks2xml($a_text);
432
433 // external link
434 $ws = "[ \t\r\f\v\n]*";
435 // remove empty external links
436 while (preg_match("~\[(xln$ws(url$ws=$ws\"([^\"])*\")$ws(target$ws=$ws(\"(Glossary|FAQ|Media)\"))?$ws)\]\[\/xln\]~i", $a_text, $found)) {
437 $a_text = str_replace($found[0], "", $a_text);
438 }
439 while (preg_match('~\[(xln$ws(url$ws=$ws(([^]])*)))$ws\]\[\/xln\]~i', $a_text, $found)) {
440 $a_text = str_replace($found[0], "", $a_text);
441 }
442 // external links
443 while (preg_match("~\[(xln$ws(url$ws=$ws\"([^\"])*\")$ws(target$ws=$ws(\"(Glossary|FAQ|Media)\"))?$ws)\]~i", $a_text, $found)) {
444 $old_text = $a_text;
445 $attribs = self::attribsToArray($found[2]);
446 if (isset($attribs["url"])) {
447 $a_text = self::replaceBBTagByMatching(
448 "[" . $found[1] . "]",
449 "[/xln]",
450 "ExtLink",
451 $a_text,
452 [
453 "Href" => $attribs["url"]
454 ]
455 );
456 }
457 if ($old_text === $a_text) {
458 $a_text = str_replace("[" . $found[1] . "]", "[error: " . $found[1] . "]", $a_text);
459 }
460 }
461
462 // ie/tinymce fix for links without "", see bug #8391
463 /* deprecated, should be removed soon, old IE not supported anymore
464 while (preg_match('~\[(xln$ws(url$ws=$ws(([^]])*)))$ws\]~i', $a_text, $found)) {
465 if ($found[3] != "") {
466 $a_text = str_replace("[" . $found[1] . "]", "<ExtLink Href=\"" . $found[3] . "\">", $a_text);
467 } else {
468 $a_text = str_replace("[" . $found[1] . "]", "[error: xln" . $found[1] . "]", $a_text);
469 }
470 }
471 $a_text = preg_replace('~\[\/xln\]~i', "</ExtLink>", $a_text);*/
472
473 // anchor
474 $ws = "[ \t\r\f\v\n]*";
475 while (preg_match("~\[(anc$ws(name$ws=$ws\"([^\"])*\")$ws)\]~i", $a_text, $found)) {
476 $attribs = self::attribsToArray($found[2]);
477 $a_text = self::replaceBBTagByMatching(
478 "[" . $found[1] . "]",
479 "[/anc]",
480 "Anchor",
481 $a_text,
482 [
483 "Name" => $attribs["name"]
484 ]
485 );
486 }
487
488 // marked text
489 while (preg_match("~\[(marked$ws(class$ws=$ws\"([^\"])*\")$ws)\]~i", $a_text, $found)) {
490 $attribs = self::attribsToArray($found[2]);
491 if (isset($attribs["class"])) {
492 $a_text = self::replaceBBTagByMatching(
493 "[" . $found[1] . "]",
494 "[/marked]",
495 "Marked",
496 $a_text,
497 [
498 "Class" => $attribs["class"]
499 ]
500 );
501 } else {
502 $a_text = str_replace("[" . $found[1] . "]", "[error:marked" . $found[1] . "]", $a_text);
503 }
504 }
505
506 if (!is_null($log)) {
507 $log->debug("...finish: " . substr($a_text, 0, 1000));
508 }
509
510 return $a_text;
511 }
512
513 protected static function isValidTagContent(string $content): bool
514 {
515 $use_internal_errors = libxml_use_internal_errors(true);
516 $sxe = simplexml_load_string("<?xml version='1.0'?><dummy>" . $content . "</dummy>");
517 libxml_use_internal_errors($use_internal_errors);
518 return ($sxe !== false);
519 }
520
526 protected static function replaceBBTagByMatching(
527 string $start_tag,
528 string $end_tag,
529 string $xml_tag_name,
530 string $text,
531 array $attribs
532 ): string {
533 $attrib_str = "";
534 foreach ($attribs as $key => $value) {
535 if ($value != "") {
536 $attrib_str .= ' ' . $key . '="' . $value . '"';
537 }
538 }
539
540 $ok = false;
541
542 $pos1 = strpos($text, $start_tag);
543
544 $pos2 = null;
545 if ($end_tag != "") {
546 $pos2 = strpos($text, $end_tag, $pos1 + strlen($start_tag));
547 if (is_int($pos1) && is_int($pos2)) {
548 $between = substr($text, $pos1 + strlen($start_tag), $pos2 - ($pos1 + strlen($start_tag)));
549 $ok = self::isValidTagContent($between);
550 }
551 } else { // no end tag
552 if (is_int($pos1)) {
553 $ok = true;
554 }
555 }
556 $short = ($end_tag == "")
557 ? "/"
558 : "";
559
560 $slash_chars = '/[]?()$*';
561
562 if ($ok) {
563 $replace_str = addcslashes($start_tag, $slash_chars);
564 $replace_str = str_replace("+", "\\+", $replace_str);
565 // replace start tag
566 $text = preg_replace(
567 '/' . $replace_str . '/i',
568 "<" . $xml_tag_name . $attrib_str . $short . ">",
569 $text,
570 1
571 );
572
573 // replace end tag
574 if ($end_tag != "") {
575 $text = preg_replace('~' . addcslashes($end_tag, $slash_chars) . '~i', "</" . $xml_tag_name . ">", $text, 1);
576 }
577 } else {
578 // remove start tag
579 if (is_int($pos1)) {
580 $text = preg_replace(
581 '/' . addcslashes($start_tag, $slash_chars) . '/i',
582 "",
583 $text,
584 1
585 );
586 }
587 // remove end tag
588 if (is_int($pos2)) {
589 $text = preg_replace(
590 '~' . addcslashes($end_tag, $slash_chars) . '~i',
591 "",
592 $text,
593 1
594 );
595 }
596 }
597 return $text;
598 }
599
603 public static function intLinks2xml(
604 string $a_text
605 ): string {
606 global $DIC;
607
608 $objDefinition = $DIC["objDefinition"];
609 $obj_id = 0;
610 $rtypes = $objDefinition->getAllRepositoryTypes();
611
612 // internal links
613 //$any = "[^\]]*"; // this doesn't work :-(
614 $ws = "[ \t\r\f\v\n]*";
615 $ltypes = "page|chap|term|media|obj|dfile|sess|wpage|ppage|" . implode("|", $rtypes);
616 // empty internal links
617 while (preg_match('~\[(iln' . $ws . '((inst' . $ws . '=' . $ws . '([\"0-9])*)?' . $ws .
618 "((" . $ltypes . ")$ws=$ws([\"0-9])*)$ws" .
619 "(target$ws=$ws(\"(New|FAQ|Media)\"))?$ws(anchor$ws=$ws(\"([^\"])*\"))?$ws))\]\[\/iln\]~i", $a_text, $found)) {
620 $a_text = str_replace($found[0], "", $a_text);
621 }
622 while (preg_match('~\[(iln' . $ws . '((inst' . $ws . '=' . $ws . '([\"0-9])*)?' . $ws .
623 "((" . $ltypes . ")$ws=$ws([\"0-9])*)$ws" .
624 "(target$ws=$ws(\"(New|FAQ|Media)\"))?$ws(anchor$ws=$ws(\"([^\"])*\"))?$ws))\]~i", $a_text, $found)) {
625 $attribs = self::attribsToArray($found[2]);
626 $inst_str = $attribs["inst"] ?? "";
627 // pages
628 if (isset($attribs["page"])) {
629 $a_text = self::replaceBBTagByMatching(
630 "[" . $found[1] . "]",
631 "[/iln]",
632 "IntLink",
633 $a_text,
634 [
635 "Target" => "il_" . $inst_str . "_pg_" . $attribs['page'],
636 "Type" => "PageObject",
637 "TargetFrame" => $found[10] ?? "",
638 "Anchor" => $attribs["anchor"] ?? ""
639 ]
640 );
641 }
642 // chapters
643 elseif (isset($attribs["chap"])) {
644 $a_text = self::replaceBBTagByMatching(
645 "[" . $found[1] . "]",
646 "[/iln]",
647 "IntLink",
648 $a_text,
649 [
650 "Target" => "il_" . $inst_str . "_st_" . $attribs['chap'],
651 "Type" => "StructureObject",
652 "TargetFrame" => $found[10] ?? ""
653 ]
654 );
655 }
656 // glossary terms
657 elseif (isset($attribs["term"])) {
658 $a_text = self::replaceBBTagByMatching(
659 "[" . $found[1] . "]",
660 "[/iln]",
661 "IntLink",
662 $a_text,
663 [
664 "Target" => "il_" . $inst_str . "_git_" . $attribs['term'],
665 "Type" => "GlossaryItem",
666 "TargetFrame" => (($found[10] ?? "") == "New")
667 ? "New"
668 : "Glossary"
669 ]
670 );
671 }
672 // wiki pages
673 elseif (isset($attribs["wpage"])) {
674 $a_text = self::replaceBBTagByMatching(
675 "[" . $found[1] . "]",
676 "[/iln]",
677 "IntLink",
678 $a_text,
679 [
680 "Target" => "il_" . $inst_str . "_wpage_" . $attribs['wpage'],
681 "Type" => "WikiPage",
682 "Anchor" => $attribs["anchor"] ?? ""
683 ]
684 );
685 }
686 // portfolio pages
687 elseif (isset($attribs["ppage"])) {
688 $a_text = self::replaceBBTagByMatching(
689 "[" . $found[1] . "]",
690 "[/iln]",
691 "IntLink",
692 $a_text,
693 [
694 "Target" => "il_" . $inst_str . "_ppage_" . $attribs['ppage'],
695 "Type" => "PortfolioPage"
696 ]
697 );
698 }
699 // media object
700 elseif (isset($attribs["media"])) {
701 $a_text = self::replaceBBTagByMatching(
702 "[" . $found[1] . "]",
703 "[/iln]",
704 "IntLink",
705 $a_text,
706 [
707 "Target" => "il_" . $inst_str . "_mob_" . $attribs['media'],
708 "Type" => "MediaObject",
709 "TargetFrame" => $found[10] ?? ""
710 ]
711 );
712 }
713 // direct download file (no repository object)
714 elseif (isset($attribs["dfile"])) {
715 $a_text = self::replaceBBTagByMatching(
716 "[" . $found[1] . "]",
717 "[/iln]",
718 "IntLink",
719 $a_text,
720 [
721 "Target" => "il_" . $inst_str . "_dfile_" . $attribs['dfile'],
722 "Type" => "File"
723 ]
724 );
725 }
726 // repository items (id is ref_id (will be used internally but will
727 // be replaced by object id for export purposes)
728 else {
729 foreach ($objDefinition->getAllRepositoryTypes() as $t) {
730 if (isset($attribs[$t])) {
731 $obj_id = $attribs[$t];
732 }
733 }
734 if (isset($attribs["obj"])) {
735 $obj_id = $attribs["obj"];
736 }
737
738 if ($obj_id > 0) {
739 if ($inst_str == "") {
740 $a_text = self::replaceBBTagByMatching(
741 "[" . $found[1] . "]",
742 "[/iln]",
743 "IntLink",
744 $a_text,
745 [
746 "Target" => "il_" . $inst_str . "_obj_" . $obj_id,
747 "Type" => "RepositoryItem"
748 ]
749 );
750 } else {
751 $a_text = self::replaceBBTagByMatching(
752 "[" . $found[1] . "]",
753 "[/iln]",
754 "IntLink",
755 $a_text,
756 [
757 "Target" => "il_" . $inst_str . "_" . $found[6] . "_" . $obj_id,
758 "Type" => "RepositoryItem"
759 ]
760 );
761 }
762 } else {
763 $a_text = preg_replace('/\[' . $found[1] . '\]/i', "[error: iln" . $found[1] . "]", $a_text);
764 }
765 }
766 }
767
768 while (preg_match("~\[(iln$ws((inst$ws=$ws([\"0-9])*)?" . $ws . "media$ws=$ws([\"0-9])*)$ws)/\]~i", $a_text, $found)) {
769 $attribs = self::attribsToArray($found[2]);
770 $inst_str = $attribs["inst"] ?? "";
771 $a_text = self::replaceBBTagByMatching(
772 "[" . $found[1] . "/]",
773 "",
774 "IntLink",
775 $a_text,
776 [
777 "Target" => "il_" . $inst_str . "_mob_" . $attribs['media'],
778 "Type" => "MediaObject"
779 ]
780 );
781 }
782
783 // user
784 while (preg_match("~\[(iln$ws((inst$ws=$ws([\"0-9])*)?" . $ws . "user$ws=$ws(\"([^\"])*)\")$ws)/\]~i", $a_text, $found)) {
785 $attribs = self::attribsToArray($found[2]);
786 $inst_str = $attribs["inst"] ?? "";
787 $user_id = ilObjUser::_lookupId($attribs['user']);
788 $a_text = self::replaceBBTagByMatching(
789 "[" . $found[1] . "/]",
790 "",
791 "IntLink",
792 $a_text,
793 [
794 "Target" => "il_" . $inst_str . "_user_" . $user_id,
795 "Type" => "User"
796 ]
797 );
798 }
799
800 return $a_text;
801 }
802
803
809 public static function input2xmlReplaceLists(
810 string $a_text
811 ): string {
812 $rows = explode("<br />", $a_text . "<br />");
813 //var_dump($a_text);
814
815 $old_level = 0;
816
817 $text = "";
818 $clist = [];
819
820 foreach ($rows as $row) {
821 $level = 0;
822 if (str_replace("#", "*", substr($row, 0, 3)) == "***") {
823 $level = 3;
824 } elseif (str_replace("#", "*", substr($row, 0, 2)) == "**") {
825 $level = 2;
826 } elseif (str_replace("#", "*", substr($row, 0, 1)) == "*") {
827 $level = 1;
828 }
829
830 // end previous line
831 if ($level < $old_level) {
832 for ($i = $old_level; $i > $level; $i--) {
833 $text .= "</SimpleListItem></" . $clist[$i] . ">";
834 }
835 if ($level > 0) {
836 $text .= "</SimpleListItem>";
837 }
838 } elseif ($old_level > 0 && $level > 0 && ($level == $old_level)) {
839 $text .= "</SimpleListItem>";
840 } elseif (($level == $old_level) && $text != "") {
841 $text .= "<br />";
842 }
843
844 // start next line
845 if ($level > $old_level) {
846 for ($i = $old_level + 1; $i <= $level; $i++) {
847 if (substr($row, $i - 1, 1) == "*") {
848 $clist[$i] = "SimpleBulletList";
849 } else {
850 $clist[$i] = "SimpleNumberedList";
851 }
852 $text .= "<" . $clist[$i] . "><SimpleListItem>";
853 }
854 } elseif ($old_level > 0 && $level > 0) {
855 $text .= "<SimpleListItem>";
856 }
857 $text .= substr($row, $level);
858
859 $old_level = $level;
860 }
861
862 // remove "<br />" at the end
863 if (substr($text, strlen($text) - 6) == "<br />") {
864 $text = substr($text, 0, strlen($text) - 6);
865 }
866
867 return $text;
868 }
869
875 public static function xml2outputReplaceLists(
876 string $a_text
877 ): string {
878 $list_start = false;
879 $li = false;
880
881 $segments = ilPCParagraph::segmentString($a_text, array("<SimpleBulletList>", "</SimpleBulletList>",
882 "</SimpleListItem>", "<SimpleListItem>", "<SimpleListItem/>", "<SimpleNumberedList>", "</SimpleNumberedList>"));
883
884 $current_list = array();
885 $text = "";
886 for ($i = 0, $iMax = count($segments); $i < $iMax; $i++) {
887 if ($segments[$i] == "<SimpleBulletList>") {
888 if (count($current_list) == 0) {
889 $list_start = true;
890 }
891 $current_list[] = "*";
892 $li = false;
893 } elseif ($segments[$i] == "<SimpleNumberedList>") {
894 if (count($current_list) == 0) {
895 $list_start = true;
896 }
897 $current_list[] = "#";
898 $li = false;
899 } elseif ($segments[$i] == "</SimpleBulletList>") {
900 array_pop($current_list);
901 $li = false;
902 } elseif ($segments[$i] == "</SimpleNumberedList>") {
903 array_pop($current_list);
904 $li = false;
905 } elseif ($segments[$i] == "<SimpleListItem>") {
906 $li = true;
907 } elseif ($segments[$i] == "</SimpleListItem>") {
908 $li = false;
909 } elseif ($segments[$i] == "<SimpleListItem/>") {
910 if ($list_start) {
911 $text .= "<br />";
912 $list_start = false;
913 }
914 foreach ($current_list as $list) {
915 $text .= $list;
916 }
917 $text .= "<br />";
918 $li = false;
919 } else {
920 if ($li) {
921 if ($list_start) {
922 $text .= "<br />";
923 $list_start = false;
924 }
925 foreach ($current_list as $list) {
926 $text .= $list;
927 }
928 }
929 $text .= $segments[$i];
930 if ($li) {
931 $text .= "<br />";
932 }
933 $li = false;
934 }
935 }
936
937 // remove trailing <br />, if text ends with list
938 if ((($segments[count($segments) - 1] ?? "") === "</SimpleBulletList>" ||
939 ($segments[count($segments) - 1] ?? "") === "</SimpleNumberedList>") &&
940 substr($text, strlen($text) - 6) === "<br />") {
941 $text = substr($text, 0, -6);
942 }
943
944 return $text;
945 }
946
950 public static function segmentString(
951 string $a_haystack,
952 array $a_needles
953 ): array {
954 $segments = array();
955 $found_needle = "";
956
957 $nothing_found = false;
958 while (!$nothing_found) {
959 $nothing_found = true;
960 $found = -1;
961 foreach ($a_needles as $needle) {
962 $pos = stripos($a_haystack, $needle);
963 if (is_int($pos) && ($pos < $found || $found == -1)) {
964 $found = $pos;
965 $found_needle = $needle;
966 $nothing_found = false;
967 }
968 }
969 if ($found > 0) {
970 $segments[] = substr($a_haystack, 0, $found);
971 $a_haystack = substr($a_haystack, $found);
972 }
973 if ($found > -1) {
974 $segments[] = substr($a_haystack, 0, strlen($found_needle));
975 $a_haystack = substr($a_haystack, strlen($found_needle));
976 }
977 }
978 if ($a_haystack != "") {
979 $segments[] = $a_haystack;
980 }
981
982 return $segments;
983 }
984
990 public static function xml2output(
991 string $a_text,
992 bool $a_wysiwyg = false,
993 bool $a_replace_lists = true,
994 bool $unmask = true
995 ): string {
996 // note: the order of the processing steps is crucial
997 // and should be the same as in input2xml() in REVERSE order!
998
999 // xml to bb code
1000 $any = "[^>]*";
1001 $tframestr = "";
1002
1003 foreach (self::getBBMap() as $bb => $tag) {
1004 $a_text = preg_replace('~<' . $tag . '[^>]*>~i', "[" . $bb . "]", $a_text);
1005 $a_text = preg_replace('~</' . $tag . '>~i', "[/" . $bb . "]", $a_text);
1006 $a_text = preg_replace('~<' . $tag . '/>~i', "[" . $bb . "][/" . $bb . "]", $a_text);
1007 }
1008
1009 // replace lists
1010 if ($a_replace_lists) {
1011 //echo "<br>".htmlentities($a_text);
1012 $a_text = ilPCParagraph::xml2outputReplaceLists($a_text);
1013 //echo "<br>".htmlentities($a_text);
1014 }
1015
1016 // internal links
1017 while (preg_match('~<IntLink(' . $any . ')>~i', $a_text, $found)) {
1018 $attribs = self::attribsToArray($found[1]);
1019 $target = explode("_", $attribs["Target"]);
1020 $target_id = $target[count($target) - 1];
1021 $inst_str = (!is_int(strpos($attribs["Target"], "__")))
1022 ? $inst_str = "inst=\"" . ($target[1] ?? '') . "\" "
1023 : $inst_str = "";
1024 switch ($attribs["Type"]) {
1025 case "PageObject":
1026 $tframestr = (!empty($attribs["TargetFrame"]))
1027 ? " target=\"" . $attribs["TargetFrame"] . "\""
1028 : "";
1029 $ancstr = (!empty($attribs["Anchor"]))
1030 ? ' anchor="' . $attribs["Anchor"] . '"'
1031 : "";
1032 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "page=\"" . $target_id . "\"$tframestr$ancstr]", $a_text);
1033 break;
1034
1035 case "StructureObject":
1036 $tframestr = (!empty($attribs["TargetFrame"]))
1037 ? " target=\"" . $attribs["TargetFrame"] . "\""
1038 : "";
1039 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "chap=\"" . $target_id . "\"$tframestr]", $a_text);
1040 break;
1041
1042 case "GlossaryItem":
1043 $tframestr = (empty($attribs["TargetFrame"]) || $attribs["TargetFrame"] == "Glossary")
1044 ? ""
1045 : " target=\"" . $attribs["TargetFrame"] . "\"";
1046 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "term=\"" . $target_id . "\"" . $tframestr . "]", $a_text);
1047 break;
1048
1049 case "WikiPage":
1050 $tframestr = "";
1051 $ancstr = (!empty($attribs["Anchor"]))
1052 ? ' anchor="' . $attribs["Anchor"] . '"'
1053 : "";
1054 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "wpage=\"" . $target_id . "\"" . $tframestr . $ancstr . "]", $a_text);
1055 break;
1056
1057 case "PortfolioPage":
1058 $tframestr = "";
1059 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "ppage=\"" . $target_id . "\"" . $tframestr . "]", $a_text);
1060 break;
1061
1062 case "MediaObject":
1063 if (empty($attribs["TargetFrame"])) {
1064 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "media=\"" . $target_id . "\"/]", $a_text);
1065 } else {
1066 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln media=\"" . $target_id . "\"" .
1067 " target=\"" . ($attribs["TargetFrame"] ?? "") . "\"]", $a_text);
1068 }
1069 break;
1070
1071 // Repository Item (using ref id)
1072 case "RepositoryItem":
1073 if ($inst_str == "") {
1074 $target_type = ilObject::_lookupType($target_id, true);
1075 } else {
1076 $rtype = ($target[count($target) - 2] ?? "");
1077 $target_type = $rtype;
1078 }
1079 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "$target_type=\"" . $target_id . "\"" . $tframestr . "]", $a_text);
1080 break;
1081
1082 // Download File (not in repository, Object ID)
1083 case "File":
1084 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "dfile=\"" . $target_id . "\"" . $tframestr . "]", $a_text);
1085 break;
1086
1087 // User
1088 case "User":
1089 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln " . $inst_str . "user=\"" . ilObjUser::_lookupLogin((int) $target_id) . "\"/]", $a_text);
1090 break;
1091
1092 default:
1093 $a_text = preg_replace('~<IntLink' . $found[1] . '>~i', "[iln]", $a_text);
1094 break;
1095 }
1096 }
1097 $a_text = str_replace("</IntLink>", "[/iln]", $a_text);
1098
1099 // external links
1100 while (preg_match('~<ExtLink(' . $any . ')>~i', $a_text, $found)) {
1101 $attribs = self::attribsToArray($found[1]);
1102 //$found[1] = str_replace("?", "\?", $found[1]);
1103 $tstr = "";
1104 if (in_array(($attribs["TargetFrame"] ?? ""), array("FAQ", "Glossary", "Media"))) {
1105 $tstr = ' target="' . ($attribs["TargetFrame"] ?? "") . '"';
1106 }
1107 $a_text = str_replace("<ExtLink" . $found[1] . ">", "[xln url=\"" . ($attribs["Href"] ?? "") . "\"$tstr]", $a_text);
1108 }
1109 $a_text = str_replace("</ExtLink>", "[/xln]", $a_text);
1110
1111 // anchor
1112 while (preg_match('~<Anchor(' . $any . '/)>~i', $a_text, $found)) {
1113 $attribs = self::attribsToArray($found[1]);
1114 $a_text = str_replace("<Anchor" . $found[1] . ">", "[anc name=\"" . ($attribs["Name"] ?? "") . "\"][/anc]", $a_text);
1115 }
1116 while (preg_match('~<Anchor(' . $any . ')>~i', $a_text, $found)) {
1117 $attribs = self::attribsToArray($found[1]);
1118 $a_text = str_replace("<Anchor" . $found[1] . ">", "[anc name=\"" . ($attribs["Name"] ?? "") . "\"]", $a_text);
1119 }
1120 $a_text = str_replace("</Anchor>", "[/anc]", $a_text);
1121
1122 // marked text
1123 while (preg_match('~<Marked(' . $any . ')>~i', $a_text, $found)) {
1124 $attribs = self::attribsToArray($found[1]);
1125 $a_text = str_replace("<Marked" . $found[1] . ">", "[marked class=\"" . ($attribs["Class"] ?? "") . "\"]", $a_text);
1126 }
1127 $a_text = str_replace("</Marked>", "[/marked]", $a_text);
1128
1129 // br to linefeed
1130 if (!$a_wysiwyg) {
1131 $a_text = str_replace("<br />", "\n", $a_text);
1132 $a_text = str_replace("<br/>", "\n", $a_text);
1133 }
1134
1135 if (!$a_wysiwyg) {
1136 // prevent curly brackets from being swallowed up by template engine
1137 $a_text = str_replace("{", "&#123;", $a_text);
1138 $a_text = str_replace("}", "&#125;", $a_text);
1139
1140 // unmask html
1141 if ($unmask) {
1142 $a_text = str_replace("&lt;", "<", $a_text);
1143 $a_text = str_replace("&gt;", ">", $a_text);
1144 }
1145
1146 // this is needed to allow html like <tag attribute="value">... in paragraphs
1147 $a_text = str_replace("&quot;", "\"", $a_text);
1148
1149 // make ampersands in (enabled) html attributes work
1150 // e.g. <a href="foo.php?n=4&t=5">hhh</a>
1151 $a_text = str_replace("&amp;", "&", $a_text);
1152
1153 // make &gt; and $lt; work to allow (disabled) html descriptions
1154 if ($unmask) {
1155 $a_text = str_replace("&lt;", "&amp;lt;", $a_text);
1156 $a_text = str_replace("&gt;", "&amp;gt;", $a_text);
1157 }
1158 }
1159 return $a_text;
1160 }
1161
1168 public function autoSplit(string $a_text): array
1169 {
1170 $a_text = str_replace("=<SimpleBulletList>", "=<br /><SimpleBulletList>", $a_text);
1171 $a_text = str_replace("=<SimpleNumberedList>", "=<br /><SimpleNumberedList>", $a_text);
1172 $a_text = str_replace("</SimpleBulletList>=", "</SimpleBulletList><br />=", $a_text);
1173 $a_text = str_replace("</SimpleNumberedList>=", "</SimpleNumberedList><br />=", $a_text);
1174 $a_text = "<br />" . $a_text . "<br />"; // add preceding and trailing br
1175
1176 $chunks = array();
1177 $c_text = $a_text;
1178 $head = "";
1179 while ($c_text != "") {
1180 //var_dump($c_text); flush();
1181 //echo "1";
1182 $s1 = strpos($c_text, "<br />=");
1183 if (is_int($s1)) {
1184 //echo "2";
1185 $s2 = strpos($c_text, "<br />==");
1186 if (is_int($s2) && $s2 <= $s1) {
1187 //echo "3";
1188 $s3 = strpos($c_text, "<br />===");
1189 if (is_int($s3) && $s3 <= $s2) { // possible level three header
1190 //echo "4";
1191 $n = strpos($c_text, "<br />", $s3 + 1);
1192 if ($n > ($s3 + 9) && substr($c_text, $n - 3, 9) == "===<br />") {
1193 //echo "5";
1194 // found level three header
1195 if ($s3 > 0 || $head != "") {
1196 //echo "6";
1197 $chunks[] = array("level" => 0,
1198 "text" => $this->removeTrailingBr($head . substr($c_text, 0, $s3)));
1199 $head = "";
1200 }
1201 $chunks[] = array("level" => 3,
1202 "text" => trim(substr($c_text, $s3 + 9, $n - $s3 - 12)));
1203 $c_text = $this->handleNextBr(substr($c_text, $n + 6));
1204 } else {
1205 //echo "7";
1206 $head .= substr($c_text, 0, $n);
1207 $c_text = substr($c_text, $n);
1208 }
1209 } else { // possible level two header
1210 //echo "8";
1211 $n = strpos($c_text, "<br />", $s2 + 1);
1212 if ($n > ($s2 + 8) && substr($c_text, $n - 2, 8) == "==<br />") {
1213 //echo "9";
1214 // found level two header
1215 if ($s2 > 0 || $head != "") {
1216 //echo "A";
1217 $chunks[] = array("level" => 0,
1218 "text" => $this->removeTrailingBr($head . substr($c_text, 0, $s2)));
1219 $head = "";
1220 }
1221 $chunks[] = array("level" => 2, "text" => trim(substr($c_text, $s2 + 8, $n - $s2 - 10)));
1222 $c_text = $this->handleNextBr(substr($c_text, $n + 6));
1223 } else {
1224 //echo "B";
1225 $head .= substr($c_text, 0, $n);
1226 $c_text = substr($c_text, $n);
1227 }
1228 }
1229 } else { // possible level one header
1230 $n = strpos($c_text, "<br />", $s1 + 1);
1231 if ($n > ($s1 + 7) && substr($c_text, $n - 1, 7) == "=<br />") {
1232 // found level one header
1233 if ($s1 > 0 || $head != "") {
1234 $chunks[] = array("level" => 0,
1235 "text" => $this->removeTrailingBr($head . substr($c_text, 0, $s1)));
1236 $head = "";
1237 }
1238 $chunks[] = array("level" => 1, "text" => trim(substr($c_text, $s1 + 7, $n - $s1 - 8)));
1239 $c_text = $this->handleNextBr(substr($c_text, $n + 6));
1240 //echo "<br>ctext:".htmlentities($c_text)."<br>";
1241 } else {
1242 $head .= substr($c_text, 0, $n);
1243 $c_text = substr($c_text, $n);
1244 //echo "<br>head:".$head."c_text:".$c_text."<br>";
1245 }
1246 }
1247 } else {
1248 //echo "G";
1249 $chunks[] = array("level" => 0, "text" => $head . $c_text);
1250 $head = "";
1251 $c_text = "";
1252 }
1253 }
1254 if (count($chunks) == 0) {
1255 $chunks[] = array("level" => 0, "text" => "");
1256 }
1257
1258
1259 // remove preceding br
1260 if (substr($chunks[0]["text"], 0, 6) == "<br />") {
1261 $chunks[0]["text"] = substr($chunks[0]["text"], 6);
1262 }
1263
1264 // remove trailing br
1265 if (substr(
1266 $chunks[count($chunks) - 1]["text"],
1267 strlen($chunks[count($chunks) - 1]["text"]) - 6,
1268 6
1269 ) == "<br />") {
1270 $chunks[count($chunks) - 1]["text"] =
1271 substr($chunks[count($chunks) - 1]["text"], 0, strlen($chunks[count($chunks) - 1]["text"]) - 6);
1272 if ($chunks[count($chunks) - 1]["text"] == "") {
1273 unset($chunks[count($chunks) - 1]);
1274 }
1275 }
1276 return $chunks;
1277 }
1278
1282 public function handleNextBr(string $a_str): string
1283 {
1284 // do not remove, if next line starts with a "=", otherwise two
1285 // headlines in a row will not be recognized
1286 if (substr($a_str, 0, 6) == "<br />" && substr($a_str, 6, 1) != "=") {
1287 $a_str = substr($a_str, 6);
1288 } else {
1289 // if next line starts with a "=" we need to reinsert the <br />
1290 // otherwise it will not be recognized
1291 if (substr($a_str, 0, 1) == "=") {
1292 $a_str = "<br />" . $a_str;
1293 }
1294 }
1295 return $a_str;
1296 }
1297
1301 public function removeTrailingBr(string $a_str): string
1302 {
1303 if (substr($a_str, strlen($a_str) - 6) == "<br />") {
1304 $a_str = substr($a_str, 0, strlen($a_str) - 6);
1305 }
1306 return $a_str;
1307 }
1308
1312 public function getType(): string
1313 {
1314 return ($this->getCharacteristic() == "Code")
1315 ? "src"
1316 : parent::getType();
1317 }
1318
1322
1329 public function saveJS(
1330 ilPageObject $a_pg_obj,
1331 string $a_content,
1332 string $a_char,
1333 string $a_pc_id,
1334 string $a_insert_at = "",
1335 bool $from_placeholder = false
1336 ) {
1337 $ilUser = $this->user;
1338
1339 $a_content = str_replace("<br>", "<br />", $a_content);
1340
1341 $this->log->debug("step 1: " . substr($a_content, 0, 1000));
1342 try {
1343 $t = self::handleAjaxContent($a_content);
1344 } catch (Exception $ex) {
1345 return $ex->getMessage() . ": " . htmlentities($a_content);
1346 }
1347 $this->log->debug("step 2: " . substr($t["text"], 0, 1000));
1348 if ($t === false) {
1349 return false;
1350 }
1351 $pc_id = explode(":", $a_pc_id);
1352 $insert_at = explode(":", $a_insert_at);
1353 $t_id = explode(":", $t["id"]);
1354
1355 // insert new paragraph
1356 if ($a_insert_at != "") {
1357 $par = new ilPCParagraph($this->getPage());
1358 $par->create($a_pg_obj, $insert_at[0], $insert_at[1], $from_placeholder);
1359 $par->writePCId($pc_id[1]);
1360 } else {
1361 $par = $a_pg_obj->getContentObject($pc_id[0], $pc_id[1]);
1362
1363 if (!$par) {
1364 return $this->lng->txt("copg_page_element_not_found") . " (saveJS): " . $pc_id[0] . ":" . $pc_id[1] . ".";
1365 }
1366 }
1367 /*
1368 if ($a_insert_at != "") {
1369 $pc_id = $a_pg_obj->generatePCId();
1370 $par->writePCId($pc_id);
1371 $this->inserted_pc_id = $pc_id;
1372 } else {
1373 $this->inserted_pc_id = $pc_id[1];
1374 }*/
1375 $lang = (string) $ilUser->getLanguage();
1376 if ($lang === "") {
1377 $lang = "de";
1378 }
1379 $par->setLanguage($lang);
1380 $par->setCharacteristic($t["class"]);
1381
1382 $t2 = $par->input2xml($t["text"], true, false);
1383 $this->log->debug("step 3: " . substr($t2, 0, 1000));
1384
1386 $this->log->debug("step 4: " . substr($t2, 0, 1000));
1387
1388 $updated = $par->setText($t2, true);
1389
1390 if ($updated !== true) {
1391 echo $updated;
1392 exit;
1393 }
1394 $updated = $par->updatePage($a_pg_obj);
1395 return $updated;
1396 }
1397
1401 public function getLastSavedPCId(
1402 ilPageObject $a_pg_obj,
1403 bool $a_as_ajax_str = false
1404 ): string {
1405 $sep = "";
1406
1407 if ($a_as_ajax_str) {
1408 $a_pg_obj->stripHierIDs();
1409 $a_pg_obj->addHierIDs();
1410 $ids = "###";
1411 $combined = $a_pg_obj->getHierIdsForPCIds(
1412 array($this->inserted_pc_id)
1413 );
1414 foreach ($combined as $pc_id => $hier_id) {
1415 //echo "1";
1416 $ids .= $sep . $hier_id . ":" . $pc_id;
1417 $sep = ";";
1418 }
1419 $ids .= "###";
1420 return $ids;
1421 }
1422
1423 return $this->inserted_pc_id;
1424 }
1425
1426
1430 public static function handleAjaxContent(
1431 string $a_content
1432 ): ?array {
1433 global $DIC;
1434
1435 $domutil = $DIC->copage()->internal()->domain()->domUtil();
1436
1437 $a_content = "<dummy>" . $a_content . "</dummy>";
1438
1439 $doc = new DOMDocument();
1440
1441 $content = ilUtil::stripSlashes($a_content, false);
1442
1443 // $content = str_replace("&lt;", "<", $content);
1444 // $content = str_replace("&gt;", ">", $content);
1445 //echo "\n\n".$content;
1446 $res = $doc->loadXML($content);
1447
1448 if (!$res) {
1449 return null;
1450 }
1451
1452 // convert tags
1453 $xpath = new DOMXpath($doc);
1454
1455 $tags = self::getXMLTagMap();
1456
1457 $elements = $xpath->query("//span");
1458 while (!is_null($elements) && !is_null($element = $elements->item(0))) {
1459 //$element = $elements->item(0);
1460 $class = $element->getAttribute("class");
1461 if (substr($class, 0, 16) == "ilc_text_inline_") {
1462 $class_arr = explode(" ", $class);
1463 $tag = substr($class_arr[0], 16);
1464 if (isset($tags[$tag])) { // known tag like strong
1465 $cnode = $domutil->changeName($element, "il" . substr($class_arr[0], 16), false);
1466 } else { // unknown tag -> marked text
1467 $cnode = $domutil->changeName($element, "ilMarked", false);
1468 $cnode->setAttribute("Class", substr($class_arr[0], 16));
1469 }
1470 for ($i = 1, $iMax = count($class_arr); $i < $iMax; $i++) {
1471 $tag = substr($class_arr[$i], 16);
1472 if (isset($tags[$tag])) { // known tag like strong
1473 $cnode = $domutil->addParent($cnode, "il" . substr($class_arr[$i], 16));
1474 } else { // unknown tag -> marked element
1475 $cnode = $domutil->addParent($cnode, "ilMarked");
1476 $cnode->setAttribute("Class", substr($class_arr[$i], 16));
1477 }
1478 }
1479 } else {
1480 $domutil->replaceByChilds($element);
1481 }
1482
1483 $elements = $xpath->query("//span");
1484 }
1485
1486 // convert tags
1487 $xpath = new DOMXpath($doc);
1488 $elements = $xpath->query("/dummy/div");
1489
1490 $ret = array();
1491 if (!is_null($elements)) {
1492 foreach ($elements as $element) {
1493 $id = $element->getAttribute("id");
1494 $class = $element->getAttribute("class");
1495 $class = substr($class, 15);
1496 if (trim($class) == "") {
1497 $class = "Standard";
1498 }
1499
1500 $text = $doc->saveXML($element);
1501 $text = str_replace("<br/>", "\n", $text);
1502
1503 // remove wrapping div
1504 $pos = strpos($text, ">");
1505 $text = substr($text, $pos + 1);
1506 $pos = strrpos($text, "<");
1507 $text = substr($text, 0, $pos);
1508
1509 // todo: remove empty spans <span ...> </span>
1510
1511 // replace tags by bbcode
1512 foreach (ilPageContentGUI::_getCommonBBButtons() as $bb => $cl) {
1513 if (!in_array($bb, array("code", "tex", "fn", "xln"))) {
1514 $text = str_replace(
1515 "<il" . $cl . ">",
1516 "[" . $bb . "]",
1517 $text
1518 );
1519 $text = str_replace(
1520 "</il" . $cl . ">",
1521 "[/" . $bb . "]",
1522 $text
1523 );
1524 $text = str_replace("<il" . $cl . "/>", "", $text);
1525 }
1526 }
1527 $text = str_replace(
1528 array("<code>", "</code>"),
1529 array("[code]", "[/code]"),
1530 $text
1531 );
1532 $text = str_replace(
1533 array('<sup class="ilc_sup_Sup">', '<sup>', "</sup>"),
1534 array("[sup]", "[sup]", "[/sup]"),
1535 $text
1536 );
1537 $text = str_replace(
1538 array('<sub class="ilc_sub_Sub">', '<sub>', "</sub>"),
1539 array("[sub]", "[sub]", "[/sub]"),
1540 $text
1541 );
1542
1543 $text = str_replace("<code/>", "", $text);
1544 $text = str_replace('<ul class="ilc_list_u_BulletedList"/>', "", $text);
1545 $text = str_replace('<ul class="ilc_list_o_NumberedList"/>', "", $text);
1546
1547 // replace marked text
1548 // external links
1549 $any = "[^>]*";
1550 while (preg_match('~<ilMarked(' . $any . ')>~i', $text, $found)) {
1551 $attribs = self::attribsToArray($found[1]);
1552 $text = str_replace("<ilMarked" . $found[1] . ">", "[marked class=\"" . $attribs["Class"] . "\"]", $text);
1553 }
1554 $text = str_replace("</ilMarked>", "[/marked]", $text);
1555
1556
1557 $ret[] = array("text" => $text, "id" => $id, "class" => $class);
1558 }
1559 }
1560
1561 // we should only have one here!
1562 return $ret[0];
1563 }
1564
1568 public static function handleAjaxContentPost(string $text): string
1569 {
1570 $text = str_replace(
1571 array("&lt;ul&gt;", "&lt;/ul&gt;"),
1572 array("<SimpleBulletList>", "</SimpleBulletList>"),
1573 $text
1574 );
1575 $text = str_replace(
1576 array("&lt;ol&gt;", "&lt;/ol&gt;"),
1577 array("<SimpleNumberedList>", "</SimpleNumberedList>"),
1578 $text
1579 );
1580 $text = str_replace(
1581 array("&lt;li&gt;", "&lt;/li&gt;"),
1582 array("<SimpleListItem>", "</SimpleListItem>"),
1583 $text
1584 );
1585 while (preg_match('~&lt;ul class=\"ilc_list_u_([^\"]*)\"&gt;~i', $text, $found)) {
1586 $class = $found[1];
1587 $text = str_replace('&lt;ul class="ilc_list_u_' . $class . '"&gt;', '<SimpleBulletList Class="' . $class . '">', $text);
1588 }
1589 while (preg_match('~&lt;ol class=\"ilc_list_o_([^\"]*)\"&gt;~i', $text, $found)) {
1590 $class = $found[1];
1591 $text = str_replace('&lt;ol class="ilc_list_o_' . $class . '"&gt;', '<SimpleNumberedList Class="' . $class . '">', $text);
1592 }
1593 while (preg_match('~&lt;li class=\"ilc_list_item_([^\"]*)\"&gt;~i', $text, $found)) {
1594 $class = $found[1];
1595 $text = str_replace('&lt;li class="ilc_list_item_' . $class . '"&gt;', '<SimpleListItem Class="' . $class . '">', $text);
1596 }
1597 while (preg_match('~&lt;li class=\"ilc_list_item_([^\"]*)\"\/&gt;~i', $text, $found)) {
1598 $class = $found[1];
1599 $text = str_replace('&lt;li class="ilc_list_item_' . $class . '"/&gt;', '<SimpleListItem Class="' . $class . '"></SimpleListItem>', $text);
1600 }
1601
1602 $text = str_replace("<SimpleBulletList><br />", "<SimpleBulletList>", $text);
1603 $text = str_replace("<SimpleNumberedList><br />", "<SimpleNumberedList>", $text);
1604 $text = str_replace("<br /><SimpleBulletList>", "<SimpleBulletList>", $text);
1605 $text = str_replace("<br /><SimpleNumberedList>", "<SimpleNumberedList>", $text);
1606 $text = str_replace("</SimpleBulletList><br />", "</SimpleBulletList>", $text);
1607 $text = str_replace("</SimpleNumberedList><br />", "</SimpleNumberedList>", $text);
1608 $text = str_replace("</SimpleListItem><br />", "</SimpleListItem>", $text);
1609
1610 return $text;
1611 }
1612
1620 public function updatePage(ilPageObject $a_page)
1621 {
1622 $a_page->beforePageContentUpdate($this);
1623 return $a_page->update();
1624 }
1625
1626 public function autoLinkGlossaries(
1627 array $a_glos
1628 ): void {
1629 if (is_array($a_glos) && count($a_glos) > 0) {
1630 // check which terms occur in the text (we may
1631 // get some false positives due to the strip_tags, but
1632 // we do not want to find strong or list or other stuff
1633 // within the tags
1634 $text = strip_tags($this->getText());
1635 $found_terms = array();
1636 foreach ($a_glos as $glo) {
1637 if (ilObject::_lookupType($glo) == "glo") {
1638 $ref_ids = ilObject::_getAllReferences($glo);
1639 $glo_ref_id = current($ref_ids);
1640 if ($glo_ref_id > 0) {
1641 $terms = ilGlossaryTerm::getTermList([$glo_ref_id]);
1642 foreach ($terms as $t) {
1643 if (is_int(stripos($text, $t["term"]))) {
1644 $found_terms[$t["id"]] = $t;
1645 }
1646 }
1647 }
1648 }
1649 }
1650 // did we find anything? -> modify content
1651 if (count($found_terms) > 0) {
1652 self::linkTermsInDom($this->dom_doc, $found_terms, $this->getChildNode());
1653 }
1654 }
1655 }
1656
1660 protected static function linkTermsInDom(
1661 DOMDocument $a_dom,
1662 array $a_terms,
1663 ?DOMNode $a_par_node = null
1664 ): void {
1665 global $DIC;
1666
1667 $domutil = $DIC->copage()->internal()->domain()->domUtil();
1668
1669 $par_node = null;
1670 // sort terms by their length (shortes first)
1671 // to prevent that nested tags are builded
1672 foreach ($a_terms as $k => $t) {
1673 $a_terms[$k]["termlength"] = strlen($t["term"]);
1674 }
1675 $a_terms = ilArrayUtil::sortArray($a_terms, "termlength", "asc", true);
1676
1677 $xpath = new DOMXPath($a_dom);
1678
1679 if ($par_node == null) {
1680 $parnodes = $xpath->query("//Paragraph[@Characteristic != 'Code']");
1681 } else {
1682 $parnodes = $xpath->query(".//Paragraph[@Characteristic != 'Code']", $par_node->parentNode);
1683 }
1684
1685 $strrPos = function (string $a_haystack, string $a_needle, ?int $a_offset = null): int {
1686 if (function_exists("mb_strpos")) {
1687 return mb_strrpos($a_haystack, $a_needle, (int) $a_offset, "UTF-8");
1688 } else {
1689 return strrpos($a_haystack, $a_needle, (int) $a_offset);
1690 }
1691 };
1692
1693 foreach ($parnodes as $parnode) {
1694 $textnodes = $xpath->query('.//text()', $parnode);
1695 foreach ($textnodes as $node) {
1696 $p = $node->getNodePath();
1697
1698 // we do not change text nodes inside of links
1699 if (!is_int(strpos($p, "/IntLink")) &&
1700 !is_int(strpos($p, "/ExtLink"))) {
1701 $node_val = $node->nodeValue;
1702
1703 // all terms
1704 foreach ($a_terms as $t) {
1705 $pos = ilStr::strIPos($node_val, $t["term"]);
1706
1707 // if term found
1708 while (is_int($pos)) {
1709 // check if we are in a tex tag, see #22261
1710 $tex_bpos = $strrPos(ilStr::subStr($node_val, 0, $pos), "[tex]");
1711 $tex_epos = ilStr::strPos($node_val, "[/tex]", $tex_bpos);
1712 if ($tex_bpos > 0 && $tex_epos > 0 && $tex_bpos < $pos && $tex_epos > $pos) {
1713 $pos += ilStr::strLen($t["term"]);
1714 } else {
1715 // check if the string is not included in another word
1716 // note that []
1717 $valid_limiters = array("", " ", "&nbsp;", ".", ",", ":", ";", "!", "?", "\"", "'", "(", ")");
1718 $b = ($pos > 0)
1719 ? ilStr::subStr($node_val, $pos - 1, 1)
1720 : "";
1721 $a = ilStr::subStr($node_val, $pos + ilStr::strLen($t["term"]), 1);
1722 if ((in_array($b, $valid_limiters) || htmlentities($b, null, 'utf-8') == "&nbsp;") && in_array($a, $valid_limiters)) {
1723 $mid = '[iln term="' . $t["id"] . '"]' .
1724 ilStr::subStr($node_val, $pos, ilStr::strLen($t["term"])) .
1725 "[/iln]";
1726
1727 $node_val = ilStr::subStr($node_val, 0, $pos) .
1728 $mid .
1729 ilStr::subStr($node_val, $pos + ilStr::strLen($t["term"]));
1730
1731 $pos += ilStr::strLen($mid);
1732 } else {
1733 $pos += ilStr::strLen($t["term"]);
1734 }
1735 }
1736 $pos = ilStr::strIPos($node_val, $t["term"], $pos);
1737 }
1738
1739 // insert [iln] tags
1740 }
1741
1742 $node->nodeValue = $node_val;
1743 }
1744
1745 // var_dump($p);
1746 // var_dump($node->nodeValue);
1747 }
1748
1749
1750 // dump paragraph node
1751 $text = $a_dom->saveXML($parnode);
1752 $text = substr($text, 0, strlen($text) - strlen("</Paragraph>"));
1753 $text = substr($text, strpos($text, ">") + 1);
1754
1755 // replace [iln] by tags with xml representation
1756 $text = self::intLinks2xml($text);
1757
1758 // "set text"
1759 $error = null;
1760 $temp_dom = $domutil->docFromString(
1761 '<?xml version="1.0" encoding="UTF-8"?><Paragraph>' . $text . '</Paragraph>',
1762 $error
1763 );
1764
1765 if (empty($error)) {
1766 // delete children of paragraph node
1767 $children = $parnode->childNodes;
1768 while ($parnode->hasChildNodes()) {
1769 $parnode->removeChild($parnode->firstChild);
1770 }
1771
1772 // copy new content children in paragraph node
1773 $xpath_temp = new DOMXPath($temp_dom);
1774 $temp_pars = $xpath_temp->query("//Paragraph");
1775
1776 foreach ($temp_pars as $new_par_node) {
1777 $new_childs = $new_par_node->childNodes;
1778
1779 foreach ($new_childs as $new_child) {
1780 //$cloned_child = $new_child->cloneNode(true);
1781 $cloned_child = $a_dom->importNode($new_child, true);
1782 $parnode->appendChild($cloned_child);
1783 }
1784 }
1785 }
1786 }
1787 // exit;
1788 }
1789
1790
1795 public static function autoLinkGlossariesPage(
1796 ilPageObject $a_page,
1797 array $a_terms
1798 ): void {
1799 $a_page->buildDom();
1800 self::linkTermsInDom($a_page->getDomDoc(), $a_terms);
1801 $a_page->update();
1802 }
1803
1807 public static function afterPageUpdate(
1808 ilPageObject $a_page,
1809 DOMDocument $a_domdoc,
1810 string $a_xml,
1811 bool $a_creation
1812 ): void {
1813 // pc paragraph
1814 self::saveMetaKeywords($a_page, $a_domdoc);
1815 self::saveAnchors($a_page, $a_domdoc);
1816 }
1817
1821 public static function beforePageDelete(
1822 ilPageObject $a_page
1823 ): void {
1824 // delete anchors
1825 self::_deleteAnchors($a_page->getParentType(), $a_page->getId(), $a_page->getLanguage());
1826 }
1827
1831 public static function afterPageHistoryEntry(
1832 ilPageObject $a_page,
1833 DOMDocument $a_old_domdoc,
1834 string $a_old_xml,
1835 int $a_old_nr
1836 ): void {
1837 }
1838
1842 public static function saveAnchors(
1843 ilPageObject $a_page,
1844 DOMDocument $a_domdoc
1845 ): void {
1846 self::_deleteAnchors($a_page->getParentType(), $a_page->getId(), $a_page->getLanguage());
1847
1848 // get all anchors
1849 $xpath = new DOMXPath($a_domdoc);
1850 $nodes = $xpath->query('//Anchor');
1851 $saved = array();
1852 foreach ($nodes as $node) {
1853 $name = $node->getAttribute("Name");
1854 if (trim($name) != "" && !in_array($name, $saved)) {
1855 self::_saveAnchor($a_page->getParentType(), $a_page->getId(), $a_page->getLanguage(), $name);
1856 $saved[] = $name;
1857 }
1858 }
1859 }
1860
1864 public static function _deleteAnchors(
1865 string $a_parent_type,
1866 int $a_page_id,
1867 string $a_page_lang
1868 ): void {
1869 global $DIC;
1870
1871 $ilDB = $DIC->database();
1872
1873 $ilDB->manipulate(
1874 "DELETE FROM page_anchor WHERE " .
1875 " page_parent_type = " . $ilDB->quote($a_parent_type, "text") .
1876 " AND page_id = " . $ilDB->quote($a_page_id, "integer") .
1877 " AND page_lang = " . $ilDB->quote($a_page_lang, "text")
1878 );
1879 }
1880
1884 public static function _saveAnchor(
1885 string $a_parent_type,
1886 int $a_page_id,
1887 string $a_page_lang,
1888 string $a_anchor_name
1889 ): void {
1890 global $DIC;
1891
1892 $ilDB = $DIC->database();
1893
1894 $ilDB->manipulate("INSERT INTO page_anchor " .
1895 "(page_parent_type, page_id, page_lang, anchor_name) VALUES (" .
1896 $ilDB->quote($a_parent_type, "text") . "," .
1897 $ilDB->quote($a_page_id, "integer") . "," .
1898 $ilDB->quote($a_page_lang, "text") . "," .
1899 $ilDB->quote($a_anchor_name, "text") .
1900 ")");
1901 }
1902
1906 public static function _readAnchors(
1907 string $a_parent_type,
1908 int $a_page_id,
1909 string $a_page_lang = "-"
1910 ): array {
1911 global $DIC;
1912
1913 $ilDB = $DIC->database();
1914
1915 $and_lang = ($a_page_lang != "")
1916 ? " AND page_lang = " . $ilDB->quote($a_page_lang, "text")
1917 : "";
1918
1919 $set = $ilDB->query(
1920 "SELECT * FROM page_anchor " .
1921 " WHERE page_parent_type = " . $ilDB->quote($a_parent_type, "text") .
1922 " AND page_id = " . $ilDB->quote($a_page_id, "integer") .
1923 $and_lang
1924 );
1925 $anchors = array();
1926 while ($rec = $ilDB->fetchAssoc($set)) {
1927 $anchors[] = $rec["anchor_name"];
1928 }
1929 return $anchors;
1930 }
1931
1935 public static function saveMetaKeywords(
1936 ilPageObject $a_page,
1937 DOMDocument $a_domdoc
1938 ): void {
1939 global $DIC;
1940
1941 $lom_services = $DIC->learningObjectMetadata();
1942
1943 // not nice, should be set by context per method
1944 if ($a_page->getParentType() == "term" ||
1945 $a_page->getParentType() == "lm") {
1946 // get existing keywords
1947 $keywords = array();
1948
1949 // find all Keyw tags
1950 $xpath = new DOMXPath($a_domdoc);
1951 $nodes = $xpath->query('//Keyw');
1952 foreach ($nodes as $node) {
1953 $k = trim(strip_tags($node->nodeValue));
1954 if (!in_array($k, $keywords)) {
1955 $keywords[] = $k;
1956 }
1957 }
1958
1959 $meta_type = ($a_page->getParentType() == "term")
1960 ? "term"
1961 : "pg";
1962 $meta_rep_id = $a_page->getParentId();
1963 $meta_id = $a_page->getId();
1964
1965 $lom_services->manipulate($meta_rep_id, $meta_id, $meta_type)
1966 ->prepareCreateOrUpdate($lom_services->paths()->keywords(), ...$keywords)
1967 ->execute();
1968 }
1969 }
1970
1971 public function getJavascriptFiles(string $a_mode): array
1972 {
1973 $adve_settings = new ilSetting("adve");
1974
1975 if ($a_mode != "edit" && $adve_settings->get("auto_url_linking")) {
1977 }
1978
1979 return array();
1980 }
1981
1982 public function getOnloadCode(string $a_mode): array
1983 {
1984 $adve_settings = new ilSetting("adve");
1985
1986 if ($a_mode != "edit" && $adve_settings->get("auto_url_linking")) {
1987 return array("il.ExtLink.autolink('.ilc_Paragraph, .ilc_page_fn_Footnote','ilc_link_ExtLink');");
1988 }
1989
1990 return array();
1991 }
1992
1993 public function getModel(): ?stdClass
1994 {
1995 $model = new \stdClass();
1996 $s_text = $this->getText();
1997 $s_text = static::xml2output($s_text, true, false);
1998 $s_text = ilPCParagraphGUI::xml2outputJS($s_text);
1999 $char = $this->getCharacteristic();
2000 if ($char == "") {
2001 $char = "Standard";
2002 }
2003 $model->characteristic = $char;
2004 $model->text = $s_text;
2005
2006 return $model;
2007 }
2008
2016 public function insert(
2017 \ilPageObject $page,
2018 string $a_content,
2019 string $a_char,
2020 string $a_pc_id,
2021 string $a_insert_at = "",
2022 string $a_new_pc_id = ""
2023 ) {
2024 throw new ilCOPagePCEditException("ilPCParagraph->insert is deprecated.");
2025 $ilUser = $this->user;
2026
2027 $this->log->debug("step 1: " . substr($a_content, 0, 1000));
2028
2029 try {
2030 $t = self::handleAjaxContent($a_content);
2031 } catch (Exception $ex) {
2032 return $ex->getMessage() . ": " . htmlentities($a_content);
2033 }
2034
2035 $this->log->debug("step 2: " . substr($t["text"], 0, 1000));
2036 if ($t === false) {
2037 return false;
2038 }
2039
2040 $pc_id = explode(":", $a_pc_id);
2041 $insert_at = explode(":", $a_insert_at);
2042 $t_id = explode(":", $t["id"]);
2043
2044 // insert new paragraph
2045 if ($a_insert_at != "") {
2046 $par = new ilPCParagraph($this->getPage());
2047 $par->create($page, $insert_at[0], $insert_at[1]);
2048 } else {
2049 $par = $page->getContentObject($pc_id[0], $pc_id[1]);
2050 }
2051
2052 if ($a_insert_at != "") {
2053 $pc_id = ($a_new_pc_id != "")
2054 ? $a_new_pc_id
2055 : $page->generatePcId();
2056 $par->writePCId($pc_id);
2057 $this->inserted_pc_id = $pc_id;
2058 } else {
2059 $this->inserted_pc_id = $pc_id[1];
2060 }
2061
2062 $par->setLanguage($ilUser->getLanguage());
2063 $par->setCharacteristic($t["class"]);
2064
2065 $t2 = $par->input2xml($t["text"], true, false);
2066 $this->log->debug("step 3: " . substr($t2, 0, 1000));
2067
2069 $this->log->debug("step 4: " . substr($t2, 0, 1000));
2070
2071 $updated = $par->setText($t2, true);
2072
2073 if ($updated !== true) {
2074 echo $updated;
2075 exit;
2076 }
2077 $updated = $par->updatePage($page);
2078 return $updated;
2079 }
2080}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$check
Definition: buildRTE.php:81
const IL_INSERT_AFTER
static sortArray(array $array, string $a_array_sortby_key, string $a_array_sortorder="asc", bool $a_numeric=false, bool $a_keep_keys=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getTermList(array $a_glo_ref_id, string $searchterm="", string $a_first_letter="", string $a_def="", int $a_tax_node=0, bool $a_add_amet_fields=false, ?array $a_amet_filter=null, bool $a_include_references=false)
Get all terms for given set of glossary ids.
language handling
static getLocalJsPaths()
Get paths of necessary js files.
static getLogger(string $a_component_id)
Get component logger.
User class.
static _lookupId(string|array $a_user_str)
static _lookupLogin(int $a_user_id)
static _lookupType(int $id, bool $reference=false)
static _getAllReferences(int $id)
get all reference ids for object ID
static xml2outputJS(string $s_text)
Prepare content for js output.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setDownloadTitle(string $title)
static replaceBBCode(string $a_text, string $a_bb, string $a_tag)
static autoLinkGlossariesPage(ilPageObject $a_page, array $a_terms)
Auto link glossary of whole page.
static getXMLTagMap()
Get tag to bb map.
static xml2output(string $a_text, bool $a_wysiwyg=false, bool $a_replace_lists=true, bool $unmask=true)
Converts xml from DB to output in edit textarea.
create(ilPageObject $a_pg_obj, string $a_hier_id, string $a_pc_id="", bool $from_placeholder=false)
Create paragraph node (incl.
checkTextArray(array $text)
Check text array.
static handleAjaxContentPost(string $text)
Post input2xml handling of ajax content.
static xml2outputReplaceLists(string $a_text)
Replaces with *.
getType()
Need to override getType from ilPageContent to distinguish between Pararagraph and Source.
static _readAnchors(string $a_parent_type, int $a_page_id, string $a_page_lang="-")
Read anchors of a page.
setLanguage(string $a_lang)
getModel()
Get model as needed for the front-end editor.
getLastSavedPCId(ilPageObject $a_pg_obj, bool $a_as_ajax_str=false)
Get last inserted pc ids.
static afterPageHistoryEntry(ilPageObject $a_page, DOMDocument $a_old_domdoc, string $a_old_xml, int $a_old_nr)
After page history entry has been created.
autoSplit(string $a_text)
This function splits a paragraph text that has been already processed with input2xml at each header p...
handleNextBr(string $a_str)
Remove preceding
init()
Init object.
getText(bool $a_short_mode=false)
Get (xml) content of paragraph.
static _deleteAnchors(string $a_parent_type, int $a_page_id, string $a_page_lang)
Delete anchors of a page.
saveJS(ilPageObject $a_pg_obj, string $a_content, string $a_char, string $a_pc_id, string $a_insert_at="", bool $from_placeholder=false)
Save input coming from ajax.
input2xml(string $a_text, bool $a_wysiwyg=false, bool $a_handle_lists=true)
static isValidTagContent(string $content)
setShowLineNumbers(string $a_char)
setAutoIndent(string $ind)
getJavascriptFiles(string $a_mode)
static saveMetaKeywords(ilPageObject $a_page, DOMDocument $a_domdoc)
save all keywords
setSubCharacteristic(string $a_char)
static _saveAnchor(string $a_parent_type, int $a_page_id, string $a_page_lang, string $a_anchor_name)
Save an anchor.
static getBBMap()
Get bb to xml tag map.
static _input2xml(string $a_text, string $a_lang, bool $a_wysiwyg=false, bool $a_handle_lists=true)
Converts user input to xml User input comes as bb code information, e.g.
getOnloadCode(string $a_mode)
static handleAjaxContent(string $a_content)
Handle ajax content.
static attribsToArray(string $a_str)
converts a string of format var1 = "val1" var2 = "val2" ... into an array
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 afterPageUpdate(ilPageObject $a_page, DOMDocument $a_domdoc, string $a_xml, bool $a_creation)
After page has been updated (or created)
createAfter(DomNode $node)
Create paragraph node (incl.
setText(string $a_text, bool $a_auto_split=false)
Set (xml) content of text paragraph.
static array $bb_tags
updatePage(ilPageObject $a_page)
Update page object (it would be better to have this centralized and to change the constructors and pa...
insert(\ilPageObject $page, string $a_content, string $a_char, string $a_pc_id, string $a_insert_at="", string $a_new_pc_id="")
Save input coming from ajax.
static segmentString(string $a_haystack, array $a_needles)
Segments a string into an array at each position of a substring.
autoLinkGlossaries(array $a_glos)
removeTrailingBr(string $a_str)
Remove trailing
static input2xmlReplaceLists(string $a_text)
Converts xml from DB to output in edit textarea.
static beforePageDelete(ilPageObject $a_page)
Before page is being deleted.
static intLinks2xml(string $a_text)
internal links to xml
static linkTermsInDom(DOMDocument $a_dom, array $a_terms, ?DOMNode $a_par_node=null)
Link terms in a dom page object in bb style.
setCharacteristic(string $a_char)
Content object of ilPageObject (see ILIAS DTD).
createPageContentNode(bool $a_set_this_node=true)
Create page content node (always use this method first when adding a new element)
setDomNode(DOMNode $node)
setType(string $a_type)
Set Type.
Class ilPageObject Handles PageObjects of ILIAS Learning Modules (see ILIAS DTD)
update(bool $a_validate=true, bool $a_no_history=false)
update complete page content in db (dom xml content is used)
getContentObject(string $a_hier_id, string $a_pc_id="")
Get a content object of the page.
setLanguage(string $a_val)
Set language.
getDomDoc()
Get dom doc (DOMDocument)
addHierIDs()
Add hierarchical ID (e.g.
insertContent(ilPageContent $a_cont_obj, string $a_pos, int $a_mode=IL_INSERT_AFTER, string $a_pcid="", bool $remove_placeholder=true)
insert a content node before/after a sibling or as first child of a parent
getHierIdsForPCIds(array $a_pc_ids)
Get hier ids for a set of pc ids.
beforePageContentUpdate(ilPageContent $a_page_content)
Before page content update Note: This one is "work in progress", currently only text paragraphs call ...
ILIAS Setting Class.
static strPos(string $a_haystack, string $a_needle, int $a_offset=0)
Definition: class.ilStr.php:39
static subStr(string $a_str, int $a_start, ?int $a_length=null)
Definition: class.ilStr.php:21
static strLen(string $a_string)
Definition: class.ilStr.php:60
static strIPos(string $a_haystack, string $a_needle, int $a_offset=0)
Definition: class.ilStr.php:51
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
$c
Definition: deliver.php:25
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
exit
$log
Definition: ltiresult.php:34
$path
Definition: ltiservices.php:30
$res
Definition: ltiservices.php:69
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26
getLanguage()
$lang
Definition: xapiexit.php:25