Reproduced on
A clean Flarum 2.0.0-rc.4 install with only flarum/tags and flarum/approval enabled (plus flarum/flags, an approval dependency), MariaDB 11. The control case below confirms the normal path is unaffected.
Description
When flarum/approval is active, content created pending approval is treated as is_private until approved. flarum/tags' UpdateTagMetadata correctly skips private content, so a pending discussion does not update tag metadata. But when the discussion is later approved, nothing recomputes the tag — so the tag's discussion_count and last_posted_discussion_id are left permanently unset/stale even though the discussion is now public.
Steps to reproduce
- Fresh Flarum 2.0.0-rc.4; enable Tags + Approval.
- Create a (non-restricted) tag. Grant the Members group
startDiscussion but not discussion.startWithoutApproval, so members' new discussions require approval.
- As a member, start a discussion with that tag. It is created pending:
is_approved = false, and approval marks it is_private = true.
- As an admin/mod, approve it:
PATCH /api/posts/{firstPostId} with { "data": { "attributes": { "isApproved": true } } }.
Expected
After approval, the tag's discussion_count and last_posted_discussion_id reflect the now-visible discussion.
Actual
The discussion becomes is_approved = true, is_private = false, fully visible — but the tag's discussion_count is still 0 and last_posted_discussion_id is still null. The /tags page shows a wrong count and no "latest discussion" for that tag. Replies gated by replyWithoutApproval are affected the same way.
Minimal reproduction output (core + tags + approval only):
A) member posts -> is_approved=false, is_private=true -> tag count=0, last_posted_discussion_id=NULL
admin approves -> is_approved=true, is_private=false -> tag count=0, last_posted_discussion_id=NULL <- bug
B) control: admin auto-approved post -> tag count=1, last_posted_discussion_id set (normal path works)
Root cause
Flarum\Approval\Listener\UnapproveNewContent::markUnapprovedContentAsPrivate() — unapproved content is treated as is_private.
Flarum\Tags\Listener\UpdateTagMetadata::updateTags() gates both the discussion_count change and setLastPostedDiscussion() behind ! $discussion->is_private, so pending content is (correctly) skipped on Started / Posted.
- On approval,
Flarum\Approval\Listener\UpdateDiscussionAfterPostApproval (handling PostWasApproved) refreshes the discussion's and author's counts, but never touches tag metadata — and UpdateTagMetadata does not subscribe to PostWasApproved / PostWasUnapproved.
So no code path updates tag metadata when content transitions from pending to approved.
Suggested fix
Have UpdateTagMetadata subscribe to PostWasApproved (and PostWasUnapproved) and recompute the affected tags' discussion_count + last_posted_discussion_id (e.g. refreshLastPostedDiscussion() plus a recount), with the matching decrement on unapprove/reject.
Related
Versions
- Flarum core / tags / approval: 2.0.0-rc.4
- PHP 8.x, MariaDB 11
Reproduced on
A clean Flarum 2.0.0-rc.4 install with only
flarum/tagsandflarum/approvalenabled (plusflarum/flags, an approval dependency), MariaDB 11. The control case below confirms the normal path is unaffected.Description
When
flarum/approvalis active, content created pending approval is treated asis_privateuntil approved.flarum/tags'UpdateTagMetadatacorrectly skips private content, so a pending discussion does not update tag metadata. But when the discussion is later approved, nothing recomputes the tag — so the tag'sdiscussion_countandlast_posted_discussion_idare left permanently unset/stale even though the discussion is now public.Steps to reproduce
startDiscussionbut notdiscussion.startWithoutApproval, so members' new discussions require approval.is_approved = false, and approval marks itis_private = true.PATCH /api/posts/{firstPostId}with{ "data": { "attributes": { "isApproved": true } } }.Expected
After approval, the tag's
discussion_countandlast_posted_discussion_idreflect the now-visible discussion.Actual
The discussion becomes
is_approved = true,is_private = false, fully visible — but the tag'sdiscussion_countis still0andlast_posted_discussion_idis stillnull. The/tagspage shows a wrong count and no "latest discussion" for that tag. Replies gated byreplyWithoutApprovalare affected the same way.Minimal reproduction output (core + tags + approval only):
Root cause
Flarum\Approval\Listener\UnapproveNewContent::markUnapprovedContentAsPrivate()— unapproved content is treated asis_private.Flarum\Tags\Listener\UpdateTagMetadata::updateTags()gates both thediscussion_countchange andsetLastPostedDiscussion()behind! $discussion->is_private, so pending content is (correctly) skipped onStarted/Posted.Flarum\Approval\Listener\UpdateDiscussionAfterPostApproval(handlingPostWasApproved) refreshes the discussion's and author's counts, but never touches tag metadata — andUpdateTagMetadatadoes not subscribe toPostWasApproved/PostWasUnapproved.So no code path updates tag metadata when content transitions from pending to approved.
Suggested fix
Have
UpdateTagMetadatasubscribe toPostWasApproved(andPostWasUnapproved) and recompute the affected tags'discussion_count+last_posted_discussion_id(e.g.refreshLastPostedDiscussion()plus a recount), with the matching decrement on unapprove/reject.Related
PostWasApprovedevent triggered incorrectly #3930 / fix(1.x,approval): correctPostWasApprovedevent trigger condition #3925 corrected whenPostWasApprovedfires, but not tag metadata.discussion_counton first/only-post deletion — a similar gap in the same listener.Versions