Add an empty upcast converter that handles custom bb-codes (#5851)
authorOlaf Braun <olaf_schmitz_1@t-online.de>
Tue, 19 Mar 2024 17:48:07 +0000 (18:48 +0100)
committerGitHub <noreply@github.com>
Tue, 19 Mar 2024 17:48:07 +0000 (18:48 +0100)
* Add an empty upcast converter that handles custom bb-codes

* Update wcfsetup/install/files/lib/system/html/metacode/upcast/EmptyMetacodeUpcast.class.php

Co-authored-by: Alexander Ebert <ebert@woltlab.com>
---------

Co-authored-by: Alexander Ebert <ebert@woltlab.com>
wcfsetup/install/files/lib/system/html/metacode/upcast/EmptyMetacodeUpcast.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/html/upcast/node/HtmlUpcastNodeWoltlabMetacode.class.php

diff --git a/wcfsetup/install/files/lib/system/html/metacode/upcast/EmptyMetacodeUpcast.class.php b/wcfsetup/install/files/lib/system/html/metacode/upcast/EmptyMetacodeUpcast.class.php
new file mode 100644 (file)
index 0000000..5daab36
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+namespace wcf\system\html\metacode\upcast;
+
+/**
+ * Always forces the passed BBCode to be converted into its plain text representation.
+ *
+ * @author      Olaf Braun
+ * @copyright   2001-2024 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since       6.1
+ */
+final class EmptyMetacodeUpcast implements IMetacodeUpcast
+{
+    #[\Override]
+    public function upcast(\DOMElement $element, array $attributes): void
+    {
+        // do nothing
+    }
+
+    #[\Override]
+    public function hasValidAttributes(array $attributes): bool
+    {
+        return false;
+    }
+
+    #[\Override]
+    public function cacheObject(array $attributes): void
+    {
+        // do nothing
+    }
+}
index d459297d66c72fb6d2857949647836c5514c5a25..48c0e1290e0f9e1a4730c147ff1502d404f3fd07 100644 (file)
@@ -3,6 +3,7 @@
 namespace wcf\system\html\upcast\node;
 
 use wcf\data\bbcode\BBCodeCache;
+use wcf\system\html\metacode\upcast\EmptyMetacodeUpcast;
 use wcf\system\html\metacode\upcast\IMetacodeUpcast;
 use wcf\system\html\node\AbstractHtmlNodeProcessor;
 use wcf\util\DOMUtil;
@@ -28,6 +29,7 @@ final class HtmlUpcastNodeWoltlabMetacode extends AbstractHtmlUpcastNode
         /** @var IMetacodeUpcast[] $upcasters */
         $upcasters = [];
         $nodes = [];
+        $emptyMetacodeUpcast = new EmptyMetacodeUpcast();
 
         /** @var \DOMElement $element */
         foreach ($elements as $element) {
@@ -46,6 +48,11 @@ final class HtmlUpcastNodeWoltlabMetacode extends AbstractHtmlUpcastNode
             if ($attributes === []) {
                 $element->removeAttribute('data-attributes');
             }
+            $bbcode = BBCodeCache::getInstance()->getBBCodeByTag($name);
+            if (!$bbcode->originIsSystem) {
+                $nodes[] = [$element, $name, $emptyMetacodeUpcast, $attributes];
+                continue;
+            }
 
             // check for upcast
             $upcast = $upcasters[$name] ?? null;
@@ -71,7 +78,7 @@ final class HtmlUpcastNodeWoltlabMetacode extends AbstractHtmlUpcastNode
             } else {
                 // Replace this with a text node
                 /** @see HtmlBBCodeParser::buildBBCodeTag() */
-                $attributes = \array_filter($attributes, fn($value) => $value !== null);
+                $attributes = \array_filter($attributes, static fn($value) => $value !== null);
 
                 if (!empty($attributes)) {
                     foreach ($attributes as &$attribute) {
@@ -83,16 +90,36 @@ final class HtmlUpcastNodeWoltlabMetacode extends AbstractHtmlUpcastNode
                 } else {
                     $attributes = '';
                 }
-                $text = \sprintf('[%s%s][/%s]', $name, $attributes, $name);
                 $bbcode = BBCodeCache::getInstance()->getBBCodeByTag($name);
 
                 if ($bbcode === null || $bbcode->isBlockElement) {
                     $newElement = $element->ownerDocument->createElement('p');
-                    $newElement->textContent = $text;
-                    DOMUtil::replaceElement($element, $newElement);
+                    $newElement->appendChild($element->ownerDocument->createTextNode("[{$name}{$attributes}]"));
+                    if ($bbcode->isSourceCode) {
+                        $newElement->appendChild(
+                            $element->ownerDocument->createTextNode($element->textContent)
+                        );
+                        DomUtil::replaceElement($element, $newElement, false);
+                    } else {
+                        DomUtil::replaceElement($element, $newElement);
+                    }
+                    $newElement->appendChild($element->ownerDocument->createTextNode("[/{$name}]"));
                 } else {
-                    $element->parentNode->insertBefore($element->ownerDocument->createTextNode($text), $element);
-                    $element->parentNode->removeChild($element);
+                    $insertNode = $element->parentNode->insertBefore(
+                        $element->ownerDocument->createTextNode("[{$name}{$attributes}]"),
+                        $element
+                    );
+                    if ($bbcode->isSourceCode) {
+                        $insertNode->parentNode->appendChild(
+                            $element->ownerDocument->createTextNode($element->textContent)
+                        );
+                        DOMUtil::removeNode($element);
+                    } else {
+                        DOMUtil::removeNode($element, true);
+                    }
+                    $insertNode->parentNode->appendChild(
+                        $element->ownerDocument->createTextNode("[/{$name}]")
+                    );
                 }
             }
         }