Skip to content

[Documents] Do not send link editables as internal without an element… - #4087

Open
codingioanniskrikos wants to merge 5 commits into
pimcore:2026.2from
codingioanniskrikos:fix/link-editable-internal-without-id
Open

[Documents] Do not send link editables as internal without an element…#4087
codingioanniskrikos wants to merge 5 commits into
pimcore:2026.2from
codingioanniskrikos:fix/link-editable-internal-without-id

Conversation

@codingioanniskrikos

@codingioanniskrikos codingioanniskrikos commented Sep 8, 2026

Copy link
Copy Markdown

Resolves pimcore/platform-version#459

A link editable was sent to the backend as internal: true even when no element was behind it, and internalType was sent as undefined, which JSON.stringify drops. This happens with a link whose target document was deleted: it still has linktype: 'internal', but no id and no type left.

The backend then trusts that flag and reads internalType / internalId without checking them, which breaks rendering and saving of the whole document.

Now internal is only claimed when an id is present. Otherwise the value is sent as a direct link, and internalType is sent as null instead of undefined.

Copilot AI balanced review requested due to automatic review settings September 8, 2026 12:14
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

Copilot AI left a comment

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.

🟡 Changes recommended

Internal links can still be emitted without the required internal type.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates document-link serialization to safely downgrade stale internal links to direct links.

Changes:

  • Requires an internal ID before serializing links as internal.
  • Emits explicit null values and preserves the stale path.
  • Changes malformed internal links to linktype: 'direct'.

Review assessment:

  • Root cause is only partially addressed: internalType remains unchecked at line 93.
  • Serialization is handled at the correct boundary with compatible type widening.
  • The centralized API transformation covers known callers.
  • No focused regression test was added; documentation changes are unnecessary.
File summaries
File Description
assets/js/src/core/modules/element/dynamic-types/definitions/document/editable/types/dynamic-type-document-editable-link.tsx Adjusts document-link API serialization for stale internal targets.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@codingioanniskrikos

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@codingioanniskrikos
codingioanniskrikos marked this pull request as ready for review September 8, 2026 12:33
@ValeriaMaltseva
ValeriaMaltseva self-requested a review September 8, 2026 12:51
@ValeriaMaltseva ValeriaMaltseva self-assigned this Sep 8, 2026
@ValeriaMaltseva
ValeriaMaltseva requested a balanced review from Copilot September 9, 2026 09:59

Copilot AI left a comment

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.

🟡 Changes recommended

The behavioral fix lacks a regression test covering the reported failure.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Balanced

@ValeriaMaltseva ValeriaMaltseva left a comment

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.

@codingioanniskrikos
Hi! Thanks for this - the diagnosis is spot on, and the guard sits in the right place. It
matches the invariant the rest of the feature already assumes: use-link-data-type.ts:57
gates openLink on exactly the same two fields, and link-value-converter.ts:53-54 always
sets internal and internalType together. Sending internalType: null instead of
undefined is the load-bearing part — with the key present-but-null,
Link.php:306 (setDataFromEditmode) short-circuits cleanly and the backend's own
normalisation runs instead of reading a missing key.

Three things before this can go in:

  1. Base branch. The linked issue reports Affected Version 2026.2, but this targets
    2026.x. Bugfixes land on the active release line and forward-merge up, so please
    retarget to 2026.2 — otherwise 2026.2 users don't get the fix.

  2. Regression test. transformValueForApi is a pure function and there are jest tests
    throughout this tree already (e.g.
    document/editable/components/renderlet-editable/renderlet-content.test.tsx), so this is
    cheap. Four cases: valid internal stays internal; internal + id but no internalType
    direct; internal + internalType but no id → direct; direct unchanged. Please also
    assert 'internalType' in result — the undefined key being dropped by JSON.stringify
    is the exact mechanism of this bug, and a plain deep-equal won't catch a regression.

  3. Changelog. DocumentLinkEditableValue is re-exported through the public SDK
    (js/src/sdk/modules/element/index.ts:169), so widening internalType to string | null
    is a public type change — external bundles assigning it to string | undefined will now
    fail to compile. The widening is the right call (narrowing it is what caused the bug), it
    just shouldn't land silently.

Thanks in advance! :)

codingioanniskrikos and others added 4 commits September 9, 2026 14:54
transformValueForApi is pure, so the four relevant shapes are cheap to pin
down: a fully resolved internal link stays internal, an internal link missing
either the id or the type is downgraded to a direct one, and a direct link is
left alone.

Each downgrade case asserts 'internalType' in result rather than comparing the
object as a whole. An undefined internalType is dropped by JSON.stringify and
never reaches the backend, which is the mechanism of the bug being fixed here;
a deep-equal assertion would not catch a regression back to it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ation

DocumentLinkEditableValue is re-exported through the public SDK entry point
(js/src/sdk/modules/element/index.ts), so widening internalType from
string | undefined to string | null | undefined is a public type change.
External bundles that assign the property to a string | undefined variable
will no longer compile against it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codingioanniskrikos
codingioanniskrikos force-pushed the fix/link-editable-internal-without-id branch from fc6eb8a to f42ff12 Compare September 9, 2026 13:10
@codingioanniskrikos
codingioanniskrikos changed the base branch from 2026.x to 2026.2 September 9, 2026 13:11
The two existing downgrade cases each drop only one of the two fields, so
neither reproduces the shape reported in pimcore#459: a link whose target document
was deleted keeps linktype: 'internal' but has lost both the id and the type.

Assert that shape directly - internal false, internalId and internalType null,
linktype 'direct', and the path it used to resolve to preserved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Sep 9, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Link editable is sent as internal without an element behind it, breaking document rendering and saving

3 participants