Use textnode instant of span element
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / html / upcast / node / HtmlUpcastNodeWoltlabMetacode.class.php
1 <?php
2
3 namespace wcf\system\html\upcast\node;
4
5 use wcf\data\bbcode\BBCodeCache;
6 use wcf\system\html\metacode\upcast\IMetacodeUpcast;
7 use wcf\system\html\node\AbstractHtmlNodeProcessor;
8 use wcf\util\DOMUtil;
9
10 /**
11 * Processes bbcodes represented by `<woltlab-metacode>`.
12 *
13 * @author Olaf Braun
14 * @copyright 2001-2024 WoltLab GmbH
15 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
16 * @since 6.1
17 */
18 final class HtmlUpcastNodeWoltlabMetacode extends AbstractHtmlUpcastNode
19 {
20 /**
21 * @inheritDoc
22 */
23 protected $tagName = 'woltlab-metacode';
24
25 #[\Override]
26 public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor)
27 {
28 /** @var IMetacodeUpcast[] $upcasters */
29 $upcasters = [];
30 $nodes = [];
31
32 /** @var \DOMElement $element */
33 foreach ($elements as $element) {
34 if (DOMUtil::isRemoved($element) || $element->parentNode === null) {
35 // ignore elements that existed, but have been removed
36 // from the DOM due to action taken by an upcaster
37 continue;
38 }
39
40 $name = $element->getAttribute('data-name');
41 if ($name === 'abstract') {
42 continue;
43 }
44
45 $attributes = $htmlNodeProcessor->parseAttributes($element->getAttribute('data-attributes'));
46 if ($attributes === []) {
47 $element->removeAttribute('data-attributes');
48 }
49
50 // check for upcast
51 $upcast = $upcasters[$name] ?? null;
52 if ($upcast === null) {
53 $className = 'wcf\\system\\html\\metacode\\upcast\\' . \ucfirst($name) . 'MetacodeUpcast';
54 if (\class_exists($className)) {
55 $upcast = new $className();
56
57 $upcasters[$name] = $upcast;
58 }
59 }
60 if ($upcast === null) {
61 continue;
62 }
63
64 $upcast->cacheObject($attributes);
65 $nodes[] = [$element, $name, $upcast, $attributes];
66 }
67
68 foreach ($nodes as [$element, $name, $upcast, $attributes]) {
69 if ($upcast->hasValidAttributes($attributes)) {
70 $upcast->upcast($element, $attributes);
71 } else {
72 // Replace this with a text node
73 /** @see HtmlBBCodeParser::buildBBCodeTag() */
74 $attributes = \array_filter($attributes, fn($value) => $value !== null);
75
76 if (!empty($attributes)) {
77 foreach ($attributes as &$attribute) {
78 $attribute = "'" . \addcslashes($attribute, "'") . "'";
79 }
80 unset($attribute);
81
82 $attributes = '=' . \implode(",", $attributes);
83 } else {
84 $attributes = '';
85 }
86 $text = \sprintf('[%s%s][/%s]', $name, $attributes, $name);
87 $bbcode = BBCodeCache::getInstance()->getBBCodeByTag($name);
88
89 if ($bbcode === null || $bbcode->isBlockElement) {
90 $newElement = $element->ownerDocument->createElement('p');
91 $newElement->textContent = $text;
92 DOMUtil::replaceElement($element, $newElement);
93 } else {
94 $element->parentNode->insertBefore($element->ownerDocument->createTextNode($text), $element);
95 $element->parentNode->removeChild($element);
96 }
97 }
98 }
99 }
100
101 #[\Override]
102 public function replaceTag(array $data)
103 {
104 return $data['parsedTag'];
105 }
106 }