Skip to:
Content

BuddyPress.org

Ticket #8544: 8544.patch

File 8544.patch, 2.7 KB (added by petersmithrestless, 2 years ago)

Patch to ensure thread_id is generated in a single db transaction while inserting a new message

  • src/bp-messages/classes/class-bp-messages-message.php

    diff --git src/bp-messages/classes/class-bp-messages-message.php src/bp-messages/classes/class-bp-messages-message.php
    index 63f6d2dfd..c5785e129 100644
    class BP_Messages_Message { 
    129129                        return false;
    130130                }
    131131
    132                 $new_thread = false;
    133 
    134                 // If we have no thread_id then this is the first message of a new thread.
    135                 if ( empty( $this->thread_id ) ) {
    136                         $this->thread_id = (int) $wpdb->get_var( "SELECT MAX(thread_id) FROM {$bp->messages->table_name_messages}" ) + 1;
    137                         $new_thread      = true;
    138                 }
    139 
    140                 // First insert the message into the messages table.
    141                 if ( ! $wpdb->query( $wpdb->prepare( "INSERT INTO {$bp->messages->table_name_messages} ( thread_id, sender_id, subject, message, date_sent ) VALUES ( %d, %d, %s, %s, %s )", $this->thread_id, $this->sender_id, $this->subject, $this->message, $this->date_sent ) ) ) {
    142                         return false;
    143                 }
    144 
    145                 $this->id = $wpdb->insert_id;
     132        // If we have no thread_id then this is the first message of a new thread.
     133        // Generate a new thread_id in the same transaction as the insert to avoid a race condition which could allow multiple threads to be assigned the same thread_id
     134        if ( empty( $this->thread_id ) ) {
     135            $new_thread = true;
     136            $insert_message_query = $wpdb->prepare(
     137                "INSERT INTO {$bp->messages->table_name_messages} "
     138                . "( thread_id, sender_id, subject, message, date_sent ) "
     139                . "VALUES ( "
     140                . "( SELECT MAX(thread_id) FROM {$bp->messages->table_name_messages} m ) + 1, "
     141                . "%d, %s, %s, %s )",
     142                $this->sender_id, $this->subject, $this->message, $this->date_sent );
     143        }
     144        // Add a new message to an existing thread
     145        else {
     146            $new_thread = false;
     147            $insert_message_query = $wpdb->prepare(
     148                "INSERT INTO {$bp->messages->table_name_messages} "
     149                . "( thread_id, sender_id, subject, message, date_sent ) "
     150                . "VALUES ( %d, %d, %s, %s, %s )",
     151                $this->thread_id, $this->sender_id, $this->subject, $this->message, $this->date_sent );
     152        }
     153
     154        // First insert the message into the messages table.
     155        if ( ! $wpdb->query( $insert_message_query ) ){
     156            return false;
     157        }
     158
     159        $this->id = $wpdb->insert_id;
     160
     161        // For new threads fetch the thread_id that was generated during the insert query
     162        if ($new_thread) {
     163            $this->thread_id = (int) $wpdb->get_var( $wpdb->prepare("SELECT thread_id FROM {$bp->messages->table_name_messages} WHERE id=%d", $this->id ) );
     164        }
    146165
    147166                $recipient_ids = array();
    148167