From 728e26b6c8604d14ac1291f7772056d2ca7d0926 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois?= <f.mably@gmail.com>
Date: Thu, 13 Feb 2025 08:47:11 +0100
Subject: [PATCH] Issue #3506366 by mably: Get rid of appendXml

---
 src/Service/TermGlossaryManager.php | 41 +++++++++++------------------
 1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/src/Service/TermGlossaryManager.php b/src/Service/TermGlossaryManager.php
index bbebb26..ed9a3eb 100644
--- a/src/Service/TermGlossaryManager.php
+++ b/src/Service/TermGlossaryManager.php
@@ -178,7 +178,8 @@ class TermGlossaryManager implements TermGlossaryManagerInterface {
         }
       }
 
-      $total_tags = 0;
+      $ctx->tags = [];
+      $ctx->tagIndex = 0;
 
       $html_dom = Html::load($input);
       $xpath = new \DOMXPath($html_dom);
@@ -199,8 +200,7 @@ class TermGlossaryManager implements TermGlossaryManagerInterface {
 
         $ctx->currentText = $current_node_text;
 
-        $ctx->tags = [];
-        $ctx->tagIndex = 0;
+        $last_tag_index = $ctx->tagIndex;
 
         foreach ($term_list as $ctx->termId => $ctx->termArray) {
           if ($ctx->isSingleMatch && $this->isTermAlreadySeen($ctx)) {
@@ -214,36 +214,27 @@ class TermGlossaryManager implements TermGlossaryManagerInterface {
         }
 
         // Perform replacements only if one or more matches are found.
-        if ($ctx->tagIndex > 0) {
+        if ($ctx->tagIndex > $last_tag_index) {
           // $originalNode->nodeValue have unescaped HTML entities,
           // the following line escapes them back.
-          $escaped_text = Html::escape($ctx->currentText);
-
-          $text_with_tags = preg_replace_callback(
-            '/\{\{(\d+)}}/',
-            function ($matches) use (&$ctx) {
-              $index = (int) $matches[1];
-              return $ctx->tags[$index] ?? '{{' . $index . '}}';
-            },
-            $escaped_text,
-          );
-
-          $replacement_node = $html_dom->createDocumentFragment();
-          $replacement_node->appendXML($text_with_tags);
-
-          $current_text_node->parentNode->replaceChild(
-            $replacement_node, $current_text_node);
-
-          $total_tags += $ctx->tagIndex;
+          $current_text_node->nodeValue = Html::escape($ctx->currentText);
         }
       }
 
-      if ($total_tags === 0) {
-        // No replacement has occurred, no need to serialize.
+      if ($ctx->tagIndex === 0) {
+        // No replacement has occurred, nothing to do.
         return $input;
       }
       else {
-        return Html::serialize($html_dom);
+        // Replace all placeholders by their corresponding tags.
+        return preg_replace_callback(
+          '/\{\{(\d+)}}/',
+          function ($matches) use (&$ctx) {
+            $index = (int) $matches[1];
+            return $ctx->tags[$index] ?? '{{' . $index . '}}';
+          },
+          Html::serialize($html_dom),
+        );
       }
     }
   }
-- 
GitLab