From 883e240ec91161a2efe32791a075ef7aedf1c671 Mon Sep 17 00:00:00 2001
From: Lee Rowlands <lee.rowlands@previousnext.com.au>
Date: Mon, 22 Jul 2024 09:33:18 +1000
Subject: [PATCH] Issue #3454196 by james.williams, longwave: Filter
 placeholders without arguments are not replaced when HTML corrector filter
 applied afterwards

(cherry picked from commit dc89b84c89aa716de2915effffc6082ed15804b9)
---
 .../filter/src/FilterProcessResult.php        |  6 ++++-
 .../Plugin/Filter/FilterTestPlaceholders.php  | 24 +++++++++++++++----
 .../filter/tests/src/Kernel/FilterAPITest.php |  2 +-
 .../Rest/EntityTestTextItemNormalizerTest.php |  2 +-
 4 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/core/modules/filter/src/FilterProcessResult.php b/core/modules/filter/src/FilterProcessResult.php
index e9c8d44719c8..acf79795953e 100644
--- a/core/modules/filter/src/FilterProcessResult.php
+++ b/core/modules/filter/src/FilterProcessResult.php
@@ -136,7 +136,11 @@ public function createPlaceholder($callback, array $args) {
     // @see \Drupal\Core\Render\PlaceholderGenerator::createPlaceholder()
     $arguments = UrlHelper::buildQuery($args);
     $token = Crypt::hashBase64(serialize([$callback, $args]));
-    $placeholder_markup = '<drupal-filter-placeholder callback="' . Html::escape($callback) . '" arguments="' . Html::escape($arguments) . '" token="' . Html::escape($token) . '"></drupal-filter-placeholder>';
+    $placeholder_markup = '<drupal-filter-placeholder callback="' . Html::escape($callback) . '"';
+    if ($arguments !== '') {
+      $placeholder_markup .= ' arguments="' . Html::escape($arguments) . '"';
+    }
+    $placeholder_markup .= ' token="' . Html::escape($token) . '"></drupal-filter-placeholder>';
 
     // Add the placeholder attachment.
     $this->addAttachments([
diff --git a/core/modules/filter/tests/filter_test/src/Plugin/Filter/FilterTestPlaceholders.php b/core/modules/filter/tests/filter_test/src/Plugin/Filter/FilterTestPlaceholders.php
index 618c1d85d88a..5ca88503d3e0 100644
--- a/core/modules/filter/tests/filter_test/src/Plugin/Filter/FilterTestPlaceholders.php
+++ b/core/modules/filter/tests/filter_test/src/Plugin/Filter/FilterTestPlaceholders.php
@@ -16,7 +16,7 @@
 #[Filter(
   id: "filter_test_placeholders",
   title: new TranslatableMarkup("Testing filter"),
-  description: new TranslatableMarkup("Appends a placeholder to the content; associates #lazy_builder callback."),
+  description: new TranslatableMarkup("Appends placeholders to the content; associates #lazy_builder callbacks."),
   type: FilterInterface::TYPE_TRANSFORM_REVERSIBLE
 )]
 class FilterTestPlaceholders extends FilterBase implements TrustedCallbackInterface {
@@ -26,8 +26,9 @@ class FilterTestPlaceholders extends FilterBase implements TrustedCallbackInterf
    */
   public function process($text, $langcode) {
     $result = new FilterProcessResult($text);
-    $placeholder = $result->createPlaceholder('\Drupal\filter_test\Plugin\Filter\FilterTestPlaceholders::renderDynamicThing', ['llama']);
-    $result->setProcessedText($text . '<p>' . $placeholder . '</p>');
+    $placeholder_with_argument = $result->createPlaceholder('\Drupal\filter_test\Plugin\Filter\FilterTestPlaceholders::renderDynamicThing', ['llama']);
+    $placeholder_without_arguments = $result->createPlaceholder('\Drupal\filter_test\Plugin\Filter\FilterTestPlaceholders::renderStaticThing', []);
+    $result->setProcessedText($text . '<p>' . $placeholder_with_argument . '</p>' . '<p>' . $placeholder_without_arguments . '</p>');
     return $result;
   }
 
@@ -46,11 +47,26 @@ public static function renderDynamicThing($thing) {
     ];
   }
 
+  /**
+   * #lazy_builder callback; builds a render array.
+   *
+   * @return array
+   *   A renderable array.
+   */
+  public static function renderStaticThing(): array {
+    return [
+      '#markup' => 'This is a static llama.',
+    ];
+  }
+
   /**
    * {@inheritdoc}
    */
   public static function trustedCallbacks() {
-    return ['renderDynamicThing'];
+    return [
+      'renderDynamicThing',
+      'renderStaticThing',
+    ];
   }
 
 }
diff --git a/core/modules/filter/tests/src/Kernel/FilterAPITest.php b/core/modules/filter/tests/src/Kernel/FilterAPITest.php
index 6dde2022fd93..4d50562b08f1 100644
--- a/core/modules/filter/tests/src/Kernel/FilterAPITest.php
+++ b/core/modules/filter/tests/src/Kernel/FilterAPITest.php
@@ -318,7 +318,7 @@ public function testProcessedTextElement(): void {
       'user.permissions',
     ];
     $this->assertEqualsCanonicalizing($expected_cache_contexts, $build['#cache']['contexts'], 'Expected cache contexts present.');
-    $expected_markup = '<p>Hello, world!</p><p>This is a dynamic llama.</p>';
+    $expected_markup = '<p>Hello, world!</p><p>This is a dynamic llama.</p><p>This is a static llama.</p>';
     $this->assertSame($expected_markup, (string) $build['#markup'], 'Expected #lazy_builder callback has been applied.');
   }
 
diff --git a/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php
index 49f48c009b1f..73b27a5526d5 100644
--- a/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php
+++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php
@@ -58,7 +58,7 @@ protected function getExpectedNormalizedEntity() {
       [
         'value' => 'Cádiz is the oldest continuously inhabited city in Spain and a nice place to spend a Sunday with friends.',
         'format' => 'my_text_format',
-        'processed' => '<p>Cádiz is the oldest continuously inhabited city in Spain and a nice place to spend a Sunday with friends.</p>' . "\n" . '<p>This is a dynamic llama.</p>',
+        'processed' => '<p>Cádiz is the oldest continuously inhabited city in Spain and a nice place to spend a Sunday with friends.</p>' . "\n" . '<p>This is a dynamic llama.</p><p>This is a static llama.</p>',
       ],
     ];
     return $expected;
-- 
GitLab