diff --git a/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload-handler.php b/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload-handler.php index fa947907a4..34d8782672 100644 --- a/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload-handler.php +++ b/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload-handler.php @@ -24,6 +24,13 @@ */ class Upload_Handler { + /** + * How the reply confirming an author's upload starts, in the review conversation. + * + * @var string + */ + const UPLOAD_CONFIRMATION = 'This is an automated message to confirm that we have received your updated plugin file.'; + /** * Path to temporary plugin folder. * @@ -1017,7 +1024,7 @@ public static function update_review_email( $post, $attachment ) { return false; } - $text = "This is an automated message to confirm that we have received your updated plugin file.\n\n"; + $text = self::UPLOAD_CONFIRMATION . "\n\n"; $text .= sprintf( "File updated by %s, version %s.\n", wp_get_current_user()->user_login, diff --git a/wordpress.org/public_html/wp-content/plugins/wporg-abilities/plugins/plugin-directory/tools/class-get-plugin-status.php b/wordpress.org/public_html/wp-content/plugins/wporg-abilities/plugins/plugin-directory/tools/class-get-plugin-status.php index 91d6bc86e0..31af7dbe80 100644 --- a/wordpress.org/public_html/wp-content/plugins/wporg-abilities/plugins/plugin-directory/tools/class-get-plugin-status.php +++ b/wordpress.org/public_html/wp-content/plugins/wporg-abilities/plugins/plugin-directory/tools/class-get-plugin-status.php @@ -13,6 +13,7 @@ use WordPressdotorg\Plugin_Directory\Clients\FreeScout as FreeScout_Client; use WordPressdotorg\Plugin_Directory\Clients\HelpScout as HelpScout_Client; use WordPressdotorg\Plugin_Directory\Plugin_Directory; +use WordPressdotorg\Plugin_Directory\Shortcodes\Upload_Handler; use WordPressdotorg\Plugin_Directory\Template; use WordPressdotorg\Plugin_Directory\Tools\Helpscout; @@ -275,7 +276,7 @@ private static function get_feedback( \WP_Post $post, bool $full_history = false // When only the latest reviewer message is needed, find it directly. if ( ! $full_history ) { foreach ( $threads as $thread ) { - if ( in_array( $thread->type ?? '', array( 'reply', 'message' ), true ) ) { + if ( 'reviewer' === self::get_sender( $thread ) ) { $body = $thread->body ?? ''; if ( $body ) { $body = self::html_to_text( $body ); @@ -301,7 +302,8 @@ private static function get_feedback( \WP_Post $post, bool $full_history = false // Full history: process all threads. foreach ( $threads as $thread ) { // Skip internal notes and system events — only include customer and agent messages. - if ( ! in_array( $thread->type ?? '', array( 'customer', 'reply', 'message' ), true ) ) { + $from = self::get_sender( $thread ); + if ( ! $from ) { continue; } @@ -313,7 +315,7 @@ private static function get_feedback( \WP_Post $post, bool $full_history = false } $feedback[] = array( - 'from' => 'customer' === $thread->type ? 'author' : 'reviewer', + 'from' => $from, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- HelpScout API property. 'date' => $thread->createdAt ?? '', 'body' => $body, @@ -325,6 +327,32 @@ private static function get_feedback( \WP_Post $post, bool $full_history = false return array_reverse( $feedback ); } + /** + * Who a thread is from. + * + * The plugin directory confirms an author's upload with a reply of its own, in either helpdesk, which is the + * author's doing rather than the reviewer's feedback. + * + * @param object $thread A thread, shaped like HelpScout's. + * @return string `author` or `reviewer`; empty for notes and system events. + */ + private static function get_sender( object $thread ): string { + $type = $thread->type ?? ''; + + if ( 'customer' === $type ) { + return 'author'; + } + + if ( ! in_array( $type, array( 'reply', 'message' ), true ) ) { + return ''; + } + + // At the start only, so a reviewer quoting it is still the reviewer. + $text = trim( wp_strip_all_tags( (string) ( $thread->body ?? '' ) ) ); + + return str_starts_with( $text, Upload_Handler::UPLOAD_CONFIRMATION ) ? 'author' : 'reviewer'; + } + /** * Strip boilerplate from review feedback, keeping only the issues sections. *