Issue #3586369: "Global context" checkbox description renders a literal <br> instead of a line break

Description

Fixes issue #3586369: the "Global context" checkbox on the AI Context item edit form rendered a literal <br> instead of a line break in its description.

Root cause 1

AiContextScopeGlobal::getItemFormDescription() The method cast its TranslatableMarkup return value to (string), discarding the object that implements MarkupInterface — the only thing that tells Twig's autoescape not to Html::escape() the string. Fixed by returning the TranslatableMarkup directly.

Note on scope vs. the original issue text: since #3586369 was filed, issue #3586361 (closed) renamed this method from getFormDescription() to getItemFormDescription() and promoted it from a protected, single-caller method to a public method declared on AiContextScopeInterface, now implemented by 4 plugins (AiContextScopeBase default, AiContextScopeTag, AiContextScopeTargetEntity, AiContextScopeSiteSection). So the fix's real surface is larger than the original issue's proposed patch:

  • AiContextScopeInterface::getItemFormDescription() — return type widened string → string|TranslatableMarkup; corrected a docblock that incorrectly claimed #description is filtered with Xss::filterAdmin() (it's actually plain Twig autoescape).
  • AiContextScopeBase::getItemFormDescription() (default fallback) — same return-type widening, required because PHP checks return-type covariance against the immediate parent class, not just the interface (caught by PHPStan).
  • AiContextScopeTagAiContextScopeTargetEntityAiContextScopeSiteSection — untouched; : string remains a valid covariant narrowing.

Root cause 2

AiContextItemForm.php (found during manual testing, not part of the original issue) buildForm() rebuilds the Global checkbox's #description to append a global-item-limit warning. It cast the (now-fixed) TranslatableMarkup to (string) and reinserted it via a :base placeholder in a new $this->t() call. Drupal's : placeholder always runs Html::escape(), even on MarkupInterface values — unlike @/%, which skip escaping when the value is MarkupInterface. That re-introduced the same literal-<br> bug through a second path. Fixed by keeping $base_description as the original TranslatableMarkup (no cast) and switching the placeholder from :base to @base in all three warning strings.

Test changes

  • AiContextScopeGlobalTest::testItemFormDescriptionKeepsSaveWarning() — added a (string) cast around the getItemFormDescription() call, since the file has declare(strict_types=1) and assertStringContainsString() requires a string argument, not a TranslatableMarkup object.

Testing instructions

  1. Install ai_context.
  2. Go to /admin/config/ai/context/items/add (or edit any existing item).
  3. Open the Context Scope section.
  4. The description under the Global context checkbox now renders both line breaks correctly instead of literal <br>.

Checklist

  • I have updated the MR title to use format: Issue #1234: My issue title.
  • I have updated the MR description to include: Closes #1234
  • I have performed a self-review of my own code
  • I have added or updated tests, or explained in the description why this change is not covered by tests
  • I have updated documentation for any new or changed functionality
  • I have written testing instructions and verified them locally
  • I have noted any required post-merge steps (config imports, cache rebuilds, manual changes)
  • This MR contains no breaking API or hook changes, or they are explicitly documented in the description

AI Compliance

Note

Check the one that best describes your usage, or leave all unchecked if AI was not significantly used.

  • AI Assisted Code
    Mainly written by a human; AI used for autocomplete or partial generation under full human supervision.
  • AI Generated Code
    Mainly generated by AI, reviewed and approved by a human before this MR was created.
  • Vibe Coded
    Generated by AI and only functionally reviewed before this MR was created.

Closes #3586369

Merge request reports

Loading