[1.x] fix(mentions): prevent deleted fallback for unsynced posts during formatting#4826
Merged
imorland merged 5 commits intoJul 23, 2026
Merged
Conversation
During the Saving event, the mentions pivot tables are not yet populated. When unparse() is called (e.g. by an extension reading $post->content), the fallback logic in updatePostMentionTags (and User/Tag variants) was attempting to execute a relationship query ($context->mentionsPosts()->find()). Because the pivot table is empty for a new post, this query fails, causing the unparser to incorrectly resolve the mention to the deleted_text fallback. This fix removes the pivot table constraint when the relationship is not eagerly loaded, directly querying the underlying model instead. This also resolves an N+1 query bottleneck when unparsing posts without eager loaded mentions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…matting When a post containing mentions is edited, Flarum generates a new `contentHtml` payload to send back in the immediate API response. During this save lifecycle, the mentions pivot tables (`post_mentions_users`, `post_mentions_posts`, etc.) are not fully synced for the current transaction. Previously, the formatters (`FormatPostMentions`, `FormatUserMentions`, etc.) contained a fallback check (`|| $context instanceof Post`) that forced a query against the pivot table if the relationship wasn't eager-loaded in memory. Because the pivot table is unsynced for edited posts, this query returned null, causing the formatter to mistakenly assume the mentioned entity was deleted. This resulted in the frontend UI temporarily displaying `[deleted]` mentions until the user manually refreshed the page. This fix removes the forced pivot table query. If the relation is not already loaded via `$context->getRelations()`, it falls back directly to the base model query (e.g., `Post::find()`), which accurately retrieves the display names for unsaved edits without hitting the empty pivot tables or triggering an N+1 lazy load. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The `editing_a_post_with_deleted_author_that_has_a_mention_works` tests were incorrectly submitting a `PATCH` payload with the exact same content as the unparsed original post text. Because the text was identical, Flarum correctly optimized away the `Revised` event, which meant the database pivot tables were never synced and the test failed on the database assertion. This fixes the test by actually mutating the content string during the edit, ensuring the `Revised` event is fired and the pivot tables are populated so they can be properly asserted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The `deleted_tag_mentions_relation_unparse_and_render_as_expected` test verified that a post mentioning a Tag (ID 3) would render as `[deleted]` if the relationship pivot row was missing, despite Tag 3 actually existing in the database fixtures. Before our format fixes, Flarum wrongly rendered this as deleted because it strictly trusted the empty pivot table. With our format logic fixed to correctly query the base table when the pivot is empty, Flarum rightfully discovered that Tag 3 still exists and refused to render it as deleted, causing the test to fail. This commit fix the test by changing the mention to target Tag ID 999 (which truly does not exist in the database fixtures), ensuring the deleted rendering logic is accurately tested against an actually missing tag. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: StyleCI Bot <bot@styleci.io>
imorland
approved these changes
Jul 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4823 & #3454
Backport fix from #4824 to 1.x
Changes proposed in this pull request:
This PR modifies all
Format*MentionsandUnparse*Mentionsclasses to:relationLoaded), executing 0 queries.Post::query()->find()) rather than querying the pivot table if the relation isn't loaded.This completely bypasses the pivot table requirement during text evaluation, allowing the formatters to accurately retrieve display names for edited posts.
This bug also caused false positives in the Flarum test suite:
editing_a_post_with_deleted_author_that_has_a_mention_works: The test edited a post by sending the exact same text that the post already had. Because the brokenunparse()method previously evaluated the old post content as[deleted], Flarum thought the content had changed and dispatched theRevisedevent. Withunparse()fixed, Flarum correctly recognizes the text did not change and skips theRevisedevent, causing the test's pivot table assertion to fail. This PR updates the test payloads to actually mutate the content so that theRevisedevent fires properly.deleted_tag_mentions_relation_unparse_and_render_as_expected: The test verified that a post mentioning a Tag would render as[deleted]if the pivot row was missing, despite the Tag actually existing in the database fixtures. Before our format fixes, Flarum wrongly rendered this as deleted because it strictly trusted the empty pivot table. With our format logic fixed, Flarum rightfully discovers the Tag still exists and refuses to render it as deleted, causing the test to fail. This PR updates the test to target a genuinely non-existent Tag ID (999) to accurately test the deleted fallback.Output of
$post->contentContent use to test:
Output:
This seems to fix issue related to email notification #3454 also:
Before:
After:
Necessity
Confirmed
composer test).Required changes: