Fixed Moderated/deleted threads can be displayed as the last post/thread of a forum

PaulB

Well-known member
Affected version
2.2.7 Patch 1
  1. Alice creates a thread in forum 1. The discussion_state is visible, so the forum's last_post_* and last_thread_* fields are updated.
  2. Bob creates a thread in forum 1 after Alice, but during the same second. The discussion_state is moderated or deleted. The latter state should never happen during thread creation in vanilla XF, but the former is common.
  3. Bob's thread information is displayed as the most recent post/thread for that forum in the forum list even for members who can't view the thread.
The issue arises due to a logic issue in XF\Service\Thread\Creator#_save:
PHP:
if ($thread->last_post_date == $forum->last_post_date)
{
   $forum->fastUpdate([
      'last_post_id' => $post->post_id,
      'last_thread_id' => $post->thread_id
   ]);
}
When Bob's thread is created, that test will be true because Alice's thread has the same timestamp, but Bob's post isn't visible, so the fastUpdate shouldn't run.
 
Additionally, that should be > (or >=) not == as there is a race condition between when request A starts early than request B, but finishes after it.
 
When XF\Entity\Forum::rebuildLastPost is triggered (after bulk moderation actions mostly), It actually skips moderated posts. So there is an inconsistency here.

Actually Forum::threadAdded exists and is called, which updates these fields correctly. This code snippet can just get dropped.

:edit: Forum::threadAdded doesn't get reliably called with all the expected data due to a bug in the ordering of saves and _postSave functions being called.
 
Last edited:
Thank you for reporting this issue, it has now been resolved. We are aiming to include any changes that have been made in a future XF release (2.2.9).

Change log:
Improve cross-table data consistency when threads are created
There may be a delay before changes are rolled out to the XenForo Community.
 
The first post of a thread is a cascaded save, so the order of events is roughly:
  • The thread is saved
  • The post is saved
  • The post post-save functions are run
  • The thread post-save functions are run
I've made changes to write the first_post_id and last_post_id to the thread during the post post-save process, which makes them available in time to update the forum record during the thread post-save process, rendering the updates in the creator unnecessary. This also inherits the proper visibility checks and avoids other potential inconsistencies when two threads are created in the same forum at the same second.
 
Top Bottom