Skip to content

[6.x] Fix infinite recursion when evaluating cyclic link fields - #15386

Closed
duncanmcclean wants to merge 1 commit into
6.xfrom
shallow-evaluated-links
Closed

duncanmcclean wants to merge 1 commit into
6.xfrom
shallow-evaluated-links

Conversation

@duncanmcclean

Copy link
Copy Markdown
Member

This pull request fixes an issue where entries whose link fields point at each other (A → B → C → A) would cause infinite recursion when the entry was converted to an array or JSON, eg. via Entry::toArray(), json_encode($entry) or {{ collection:pages as="menu" }}{{ menu | to_json }}.

This was happening because AugmentedCollection::toArray(), when evaluating, eagerly walks whatever ArrayableLink::toArray() returns. That's the full augmented array of the linked entry, which contains its own link field, and so on until the stack overflows. Even without a cycle, this expanded the whole link graph into the array.

This PR fixes it by representing links shallowly in evaluated arrays, matching how they're already represented in JSON since #11375. ArrayableLink gains a toShallowArray() method, which jsonSerialize() now uses too. Deep {{ link:field }} / $link['field'] access in templates is unchanged.

Fixes #9105

`AugmentedCollection::toArray()` with evaluation eagerly walked whatever `ArrayableLink::toArray()` returned, so entries whose `link` fields point at each other recursed until the stack overflowed. JSON already represents links shallowly, so evaluated arrays now do the same via `ArrayableLink::toShallowArray()`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TeNvgwke5qBF5vWGVWyXce
@duncanmcclean

Copy link
Copy Markdown
Member Author

Closing this one. On reflection, it's breaking: for links that don't form a cycle, Entry::toArray(), json_encode($entry) and {{ entries | to_json }} would go from returning the linked entry's full data to only id, title, url, permalink and api_url. Anyone reading a custom field out of that JSON would lose it in a minor release.

A different approach is needed. The nested evaluation happens inside the AugmentedCollection::toArray() closure, so a cycle guard can live there: track the link targets being expanded and only fall back to the shallow array when a target repeats. That keeps today's output for everyone without cycles and fixes #9105 for those with them.

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.

ArrayableLink in Statamic >4.32 causes infinite loop due to array augmentation

1 participant