Skip to content

IBX-12106: Fixed handling of invalid xml:id values in RichText - #343

Merged
konradoboza merged 5 commits into
4.6from
ibx-12106-sanitize-invalid-xml-id
Sep 11, 2026
Merged

IBX-12106: Fixed handling of invalid xml:id values in RichText#343
konradoboza merged 5 commits into
4.6from
ibx-12106-sanitize-invalid-xml-id

Conversation

@tbialcz

@tbialcz tbialcz commented Aug 24, 2026

Copy link
Copy Markdown
Contributor
🎫 Issue IBX-12106

Description:

Pasting external HTML into a RichText field can bring ids which are not valid XML xml:id values (e.g. id="227", id="foo bar"). Since EZP-31574 draft saves skip validation, so such ids get stored in DocBook. Every later loadXML() of that content emits a libxml warning, which Symfony's error handler turns into an exception — the content can no longer be rendered or deleted.

Two fixes:

  1. New XmlId input converter (priority 60, right after the XSLT) fixes invalid xml:id values on save: invalid characters become _, ids starting with a digit get a _ prefix, collisions get a _1 suffix. Internal anchor links (xlink:href="#...") are updated to match, so they keep working.
  2. New DOMDocumentLoaderInterface service (DOMDocumentLoader) loads already stored XML without emitting libxml warnings — errors are logged instead (Monolog channel ibexa.richtext), with content/version/field ID where available. It is injected into Type::fromPersistenceValue(), RichTextStorage, SearchField and REST RichTextProcessor, so content broken before this fix renders again and can be edited or deleted. Re-saving it fixes the stored ids.

Passing a string to Value::__construct() is now deprecated (since 4.6.33, only \DOMDocument in 6.0) — load the document with the new service instead.

For QA:

  1. Create content with a RichText field, paste HTML containing <p id="227">text</p> and <a href="#227">link</a>, save/publish — no error, and the stored DocBook contains xml:id="_227" and xlink:href="#_227".
  2. Content stored with a broken id before this fix (or injected via SQL: xml:id="227") — its page, draft edit page, restore from trash and send to trash all work without a 500.
  3. Re-save such broken content — the stored id gets fixed to _227.
  4. Content with valid ids/anchors is stored unchanged.
  5. Loading broken content (step 2) logs a warning RichText XML document loaded with libxml errors with contentId/versionNo/fieldId in the context, on the ibexa.richtext channel (ibexa.richtext.WARNING in var/log/dev.log).

Documentation:

  • New Ibexa\Contracts\FieldTypeRichText\RichText\DOMDocumentLoaderInterface service for loading stored RichText XML.
  • New Monolog channel ibexa.richtext used by DOMDocumentLoader and RichTextStorage.
  • Deprecation: new Value(string $xml) — pass \DOMDocument instead; the string argument will be removed in 6.0.

@tbialcz
tbialcz force-pushed the ibx-12106-sanitize-invalid-xml-id branch from b4e6e8b to f3ee157 Compare August 24, 2026 07:45
@tbialcz tbialcz added Bug Something isn't working Ready for review labels Aug 24, 2026
@tbialcz
tbialcz requested a review from a team August 24, 2026 07:46
Comment thread src/lib/RichText/DOMDocumentLoader.php
@tbialcz
tbialcz requested a review from bnowak August 24, 2026 08:26
Comment thread src/lib/RichText/DOMDocumentLoader.php Outdated
Comment thread src/lib/RichText/DOMDocumentLoader.php
Comment thread src/lib/FieldType/RichText/Value.php Outdated
@tbialcz
tbialcz requested a review from alongosz August 27, 2026 08:04
*/
declare(strict_types=1);

namespace Ibexa\Contracts\FieldTypeRichText\RichText;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a Contract - external packages should not be able to use it. Afaik you only add this interface because you need it for tests. It can live alongside the implementation.

@tbialcz tbialcz Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s not only for tests. The deprecation points developers to this service, so I thought it belongs in Contracts.

@tbialcz
tbialcz force-pushed the ibx-12106-sanitize-invalid-xml-id branch from a8d95a7 to 1ee97f7 Compare August 27, 2026 08:13
@tbialcz
tbialcz requested a review from Steveb-p August 27, 2026 08:15
Comment thread src/bundle/Resources/config/settings/fieldtype_external_storages.yaml Outdated
Comment thread src/lib/FieldType/RichText/Value.php Outdated
@tbialcz
tbialcz force-pushed the ibx-12106-sanitize-invalid-xml-id branch 2 times, most recently from 3bf2e45 to 60810e7 Compare August 28, 2026 05:15
@tbialcz tbialcz added the Doc needed The changes require some documentation label Aug 28, 2026
Comment thread src/lib/FieldType/RichText/Value.php Outdated
@tbialcz
tbialcz force-pushed the ibx-12106-sanitize-invalid-xml-id branch from 60810e7 to f393e87 Compare August 31, 2026 13:20
@tbialcz
tbialcz requested a review from Steveb-p August 31, 2026 13:20
Comment thread src/bundle/Resources/config/settings/fieldtype_external_storages.yaml Outdated
Comment thread src/lib/FieldType/RichText/Value.php Outdated
Comment thread tests/lib/FieldType/RichTextTest.php Outdated
Comment thread tests/lib/FieldType/RichTextTest.php Outdated
Comment thread tests/lib/RichText/Converter/XmlIdTest.php Outdated
Comment thread tests/lib/RichText/Converter/XmlIdTest.php Outdated
Comment thread tests/lib/RichText/Converter/XmlIdTest.php Outdated
@tbialcz
tbialcz requested a review from alongosz September 3, 2026 07:50

@alongosz alongosz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, given my last remark is about the pre-existing code in a different form, that just would be nice to have fixed here.

Comment thread src/bundle/Resources/config/settings/fieldtype_external_storages.yaml Outdated
@KamilSznajdrowicz
KamilSznajdrowicz force-pushed the ibx-12106-sanitize-invalid-xml-id branch from 71faf1f to 7189cdb Compare September 10, 2026 12:04
@sonarqubecloud

Copy link
Copy Markdown

@KamilSznajdrowicz KamilSznajdrowicz left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA Approved
PR tested on 4.6.x-dev, patch applied and successfully tested on v4.6.32

@konradoboza
konradoboza merged commit 105ab17 into 4.6 Sep 11, 2026
21 checks passed
@konradoboza
konradoboza deleted the ibx-12106-sanitize-invalid-xml-id branch September 11, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something isn't working Doc needed The changes require some documentation QA approved

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants