From 13ca0d90098ea1cbb5a0475ec9144a15855b31ed Mon Sep 17 00:00:00 2001 From: alexandergull Date: Mon, 5 Jan 2026 16:01:41 +0500 Subject: [PATCH 1/2] Fix. TRP. Correctly save TRP hashes. Do not set hashes only if license is inactive or manual moderation is force enabled in WP settings. --- inc/cleantalk-public.php | 14 ----- .../CleantalkPreprocessComment.php | 35 +++++++----- lib/Cleantalk/ApbctWP/CleantalkRealPerson.php | 57 +++++++++++++++---- 3 files changed, 69 insertions(+), 37 deletions(-) diff --git a/inc/cleantalk-public.php b/inc/cleantalk-public.php index b007516aa..d23f8087c 100644 --- a/inc/cleantalk-public.php +++ b/inc/cleantalk-public.php @@ -1009,20 +1009,6 @@ function ct_set_approved($approved, $_comment) return 1; } -/** - * Public action 'comment_post' - Store cleantalk hash in comment meta - * - * @psalm-suppress UnusedParam - * @return void - */ -function ct_set_real_user_badge_automod_hash($comment_id) -{ - $hash1 = ct_hash(); - if ( ! empty($hash1) ) { - update_comment_meta($comment_id, 'ct_real_user_badge_automod_hash', ct_hash()); - } -} - /** * Public filter 'pre_comment_approved' - Mark comment unapproved always * @return string diff --git a/lib/Cleantalk/Antispam/Integrations/CleantalkPreprocessComment.php b/lib/Cleantalk/Antispam/Integrations/CleantalkPreprocessComment.php index 6784e2414..6ac778882 100644 --- a/lib/Cleantalk/Antispam/Integrations/CleantalkPreprocessComment.php +++ b/lib/Cleantalk/Antispam/Integrations/CleantalkPreprocessComment.php @@ -2,6 +2,7 @@ namespace Cleantalk\Antispam\Integrations; +use Cleantalk\ApbctWP\CleantalkRealPerson; use Cleantalk\ApbctWP\Sanitize; use Cleantalk\ApbctWP\Variables\AltSessions; use Cleantalk\ApbctWP\Variables\Cookie; @@ -259,6 +260,7 @@ public function allow() } else { $this->setCommentPreStatusAndModifyEmail('not_approved'); } + $this->addActionSetTRPHash(); return; } @@ -271,6 +273,7 @@ public function allow() !$is_allowed_because_of_inactive_license ) { $this->setCommentPreStatusAndModifyEmail('approved'); + $this->addActionSetTRPHash(); } else { // moderation disabled - standard WP check if ( @@ -280,6 +283,7 @@ public function allow() } else { $this->setCommentPreStatusAndModifyEmail('not_approved'); } + // thi is the only case when we do not set TRP hash! } } else { //not new author - standard WP check @@ -290,9 +294,18 @@ public function allow() } else { $this->setCommentPreStatusAndModifyEmail('not_approved'); } + $this->addActionSetTRPHash(); } } + /** + * TRP hash should be set anyway if Cleantalk processed. + */ + private function addActionSetTRPHash() + { + add_action('comment_post', array(CleantalkRealPerson::class, 'setTRPHash'), 999, 2); + } + public function doBlock($message) { $ct_result = $this->base_call_result['ct_result']; @@ -536,24 +549,20 @@ private function rerunWPcheckCommentFunction() return $check_result; } + /** + * @param $status + * + * @return void + */ private function setCommentPreStatusAndModifyEmail($status) { if ($status !== 'approved' && $status !== 'not_approved') { return; } - if ( $status === 'approved' ) { - add_filter('pre_comment_approved', 'ct_set_approved', 999, 2); - - // Always set hash for auto-moderated (approved) comments if cleantalk_allowed_moderation is enabled - if ( - !empty($this->apbct->settings['cleantalk_allowed_moderation']) && - $this->apbct->settings['cleantalk_allowed_moderation'] == '1' - ) { - add_action('comment_post', 'ct_set_real_user_badge_automod_hash', 999, 2); - } - } else { - add_filter('pre_comment_approved', 'ct_set_not_approved', 999, 2); - } + $pre_comment_approved_callback_function = $status === 'approved' + ? 'ct_set_approved' + : 'ct_set_not_approved'; + add_filter('pre_comment_approved', $pre_comment_approved_callback_function, 999, 2); // Modify the email notification add_filter( diff --git a/lib/Cleantalk/ApbctWP/CleantalkRealPerson.php b/lib/Cleantalk/ApbctWP/CleantalkRealPerson.php index d51e6fe66..21f40c920 100644 --- a/lib/Cleantalk/ApbctWP/CleantalkRealPerson.php +++ b/lib/Cleantalk/ApbctWP/CleantalkRealPerson.php @@ -4,6 +4,8 @@ class CleantalkRealPerson { + public static $meta_hash_name__old = 'ct_real_user_badge_hash'; + public static $meta_hash_name__automod = 'ct_real_user_badge_automod_hash'; public static function getLocalizingData() { /** @psalm-suppress PossiblyUndefinedVariable */ @@ -43,21 +45,56 @@ public function publicCommentAddTrpClass($classes, $_css_class, $comment_id, $co // Logic for show TRP badge $show_trp = false; $the_real_person = !empty($apbct->settings['comments__the_real_person']) && $apbct->settings['comments__the_real_person'] == '1'; - $allowed_moderation = !empty($apbct->settings['cleantalk_allowed_moderation']) && $apbct->settings['cleantalk_allowed_moderation'] == '1'; + $show_trp = $the_real_person && self::isTRPHashExist($comment_id) && $comment->comment_author; - if ($the_real_person && $allowed_moderation) { + if ($show_trp || $show_trp_on_roles) { + $classes[] = 'apbct-trp'; + } + return $classes; + } + + /** + * @return bool + */ + private static function isAutomodEnabled() + { + global $apbct; + return !empty($apbct->settings['cleantalk_allowed_moderation']) && $apbct->settings['cleantalk_allowed_moderation'] == '1'; + } + + /** + * Check if TRP hash is saved for comment ID. Autodetect if cleantalk_allowed_moderation is enabled. + * @param int|string $comment_id + * @return bool + */ + public static function isTRPHashExist($comment_id) + { + if (self::isAutomodEnabled()) { // Only for auto-moderated - $automod_hash = get_comment_meta((int)$comment_id, 'ct_real_user_badge_automod_hash', true); - $show_trp = $automod_hash && $comment->comment_author; - } elseif ($the_real_person && !$allowed_moderation) { + $trp_hash = get_comment_meta((int)$comment_id, self::$meta_hash_name__automod, true); + } else { // Only for old - $old_hash = get_comment_meta((int)$comment_id, 'ct_real_user_badge_hash', true); - $show_trp = $old_hash && $comment->comment_author; + $trp_hash = get_comment_meta((int)$comment_id, self::$meta_hash_name__old, true); } - if ($show_trp || $show_trp_on_roles) { - $classes[] = 'apbct-trp'; + return !empty($trp_hash); + } + + /** + * Save TRP hash for comment ID. Autodetect if cleantalk_allowed_moderation is enabled. + * @param int|string $comment_id + * + * @return void + */ + public static function setTRPHash($comment_id) + { + $hash = ct_hash(); + if ( ! empty($hash) ) { + if (self::isAutomodEnabled()) { + update_comment_meta((int)$comment_id, self::$meta_hash_name__automod, $hash); + } else { + update_comment_meta((int)$comment_id, self::$meta_hash_name__old, $hash); + } } - return $classes; } } From 0cd650f28959ecd793a95602a62b8eb634dce097 Mon Sep 17 00:00:00 2001 From: alexandergull Date: Tue, 6 Jan 2026 11:10:09 +0500 Subject: [PATCH 2/2] Fix. TRP. Cleantalk allowed moderation discussion state. --- inc/cleantalk-settings.php | 8 +++++++- .../Integrations/CleantalkPreprocessComment.php | 13 +++++++++++-- lib/Cleantalk/ApbctWP/CleantalkRealPerson.php | 15 ++++----------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/inc/cleantalk-settings.php b/inc/cleantalk-settings.php index 5887e28b6..2ac035549 100644 --- a/inc/cleantalk-settings.php +++ b/inc/cleantalk-settings.php @@ -63,6 +63,7 @@ function apbct_settings_add_page() global $apbct; $filtered = ($value === '1' || $value === 1) ? '1' : '0'; + //sync discussion and plugin settings if ($old_value !== $filtered) { $apbct->settings['cleantalk_allowed_moderation'] = $filtered; $apbct->saveSettings(); @@ -2101,7 +2102,7 @@ function apbct_discussion_settings__field__moderation() name="cleantalk_allowed_moderation" id="cleantalk_allowed_moderation" value="1" ' . - checked('1', $apbct->settings['cleantalk_allowed_moderation'], false) . + checked('1', TT::toString($apbct->settings['cleantalk_allowed_moderation'], '0'), false) . '/> '; $output .= esc_html__('Skip manual approving for the very first comment if a comment has been allowed by CleanTalk Anti-Spam protection.', 'cleantalk-spam-protect'); $output .= ''; @@ -2575,6 +2576,11 @@ function apbct_settings__validate($incoming_settings) $incoming_settings['data__email_decoder_obfuscation_custom_text'] = ContactsEncoder::getDefaultReplacingText(); } + //sync discussion and plugin settings + if (isset($incoming_settings['cleantalk_allowed_moderation'])) { + update_option('cleantalk_allowed_moderation', TT::toString($incoming_settings['cleantalk_allowed_moderation'], '0')); + } + /** * Triggered before returning the settings */ diff --git a/lib/Cleantalk/Antispam/Integrations/CleantalkPreprocessComment.php b/lib/Cleantalk/Antispam/Integrations/CleantalkPreprocessComment.php index 6ac778882..f2b1b8ef2 100644 --- a/lib/Cleantalk/Antispam/Integrations/CleantalkPreprocessComment.php +++ b/lib/Cleantalk/Antispam/Integrations/CleantalkPreprocessComment.php @@ -218,7 +218,7 @@ public function allow() { $wp_comment_moderation_enabled = get_option('comment_moderation') === '1'; $wp_auto_approve_for_user_who_has_approved_comment = get_option('comment_previously_approved') === '1'; - $clentalk_option_skip_moderation_for_first_comment = get_option('cleantalk_allowed_moderation', 1) == 1; + $cleantalk_option_skip_moderation_for_first_comment = self::firstCommentAutoModEnabled(); $is_allowed_because_of_inactive_license = false; $args = array( @@ -251,7 +251,7 @@ public function allow() // if anu of options is disabled - standard WP recheck and exit if ( !$wp_auto_approve_for_user_who_has_approved_comment || - !$clentalk_option_skip_moderation_for_first_comment + !$cleantalk_option_skip_moderation_for_first_comment ) { if ( $this->rerunWPcheckCommentFunction() @@ -572,4 +572,13 @@ private function setCommentPreStatusAndModifyEmail($status) 2 ); // Add two blacklist links: by email and IP } + + /** + * @return bool + */ + public static function firstCommentAutoModEnabled() + { + global $apbct; + return !empty($apbct->settings['cleantalk_allowed_moderation']) && $apbct->settings['cleantalk_allowed_moderation'] == '1'; + } } diff --git a/lib/Cleantalk/ApbctWP/CleantalkRealPerson.php b/lib/Cleantalk/ApbctWP/CleantalkRealPerson.php index 28742ea16..b0d82f2d2 100644 --- a/lib/Cleantalk/ApbctWP/CleantalkRealPerson.php +++ b/lib/Cleantalk/ApbctWP/CleantalkRealPerson.php @@ -2,6 +2,8 @@ namespace Cleantalk\ApbctWP; +use Cleantalk\Antispam\Integrations\CleantalkPreprocessComment; + class CleantalkRealPerson { public static $meta_hash_name__old = 'ct_real_user_badge_hash'; @@ -52,15 +54,6 @@ public function publicCommentAddTrpClass($classes, $_css_class, $comment_id, $co return $classes; } - /** - * @return bool - */ - private static function isAutomodEnabled() - { - global $apbct; - return !empty($apbct->settings['cleantalk_allowed_moderation']) && $apbct->settings['cleantalk_allowed_moderation'] == '1'; - } - /** * Check if TRP hash is saved for comment ID. Autodetect if cleantalk_allowed_moderation is enabled. * @param int|string $comment_id @@ -68,7 +61,7 @@ private static function isAutomodEnabled() */ public static function isTRPHashExist($comment_id) { - if (self::isAutomodEnabled()) { + if (CleantalkPreprocessComment::firstCommentAutoModEnabled()) { // Only for auto-moderated $trp_hash = get_comment_meta((int)$comment_id, self::$meta_hash_name__automod, true); } else { @@ -89,7 +82,7 @@ public static function setTRPHash($comment_id) { $hash = ct_hash(); if ( ! empty($hash) ) { - if (self::isAutomodEnabled()) { + if (CleantalkPreprocessComment::firstCommentAutoModEnabled()) { update_comment_meta((int)$comment_id, self::$meta_hash_name__automod, $hash); } else { update_comment_meta((int)$comment_id, self::$meta_hash_name__old, $hash);