| @@ -6,8 +6,9 @@ | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | namespace SureDonation\Inc; |
| 9 | 9 | |
| 10 | +use SureDonation\Inc\API\Settings_API; | |
| 10 | 11 | use SureDonation\Inc\Database\Tables\Donations; |
| 11 | 12 | use SureDonation\Inc\Emails\Email_Handler; |
| 12 | 13 | use SureDonation\Inc\Payments\Payment_Helper; |
| 13 | 14 | |
| @@ -91,8 +92,70 @@ | ||
| 91 | 92 | return update_option( self::OPTION_NAME, $options ); |
| 92 | 93 | } |
| 93 | 94 | |
| 94 | 95 | /** |
| 96 | + * Whether honeypot spam protection is enabled in the global settings. | |
| 97 | + * | |
| 98 | + * @return bool True when the honeypot is enabled. | |
| 99 | + * @since 1.1.0 | |
| 100 | + */ | |
| 101 | + public static function is_honeypot_enabled() { | |
| 102 | + $spam_settings = self::get_suredonation_option( Settings_API::SPAM_OPTION_KEY, [] ); | |
| 103 | + | |
| 104 | + return is_array( $spam_settings ) && ! empty( $spam_settings['honeypot'] ); | |
| 105 | + } | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * Output the hidden honeypot field when spam protection is enabled. | |
| 109 | + * | |
| 110 | + * Genuine visitors never see or fill this hidden field, so it is submitted | |
| 111 | + * with an empty value. A filled value (a bot that auto-fills every input) or | |
| 112 | + * a missing field (a bot that strips unknown inputs) is flagged as spam at | |
| 113 | + * submission time. | |
| 114 | + * | |
| 115 | + * @return void | |
| 116 | + * @see Helper::is_honeypot_spam() | |
| 117 | + * @since 1.1.0 | |
| 118 | + */ | |
| 119 | + public static function render_honeypot_field() { | |
| 120 | + if ( ! self::is_honeypot_enabled() ) { | |
| 121 | + return; | |
| 122 | + } | |
| 123 | + | |
| 124 | + echo '<input type="hidden" name="suredonation_honeypot" value="" />'; | |
| 125 | + } | |
| 126 | + | |
| 127 | + /** | |
| 128 | + * Determine whether the current submission tripped the honeypot. | |
| 129 | + * | |
| 130 | + * Returns false when honeypot protection is disabled. When enabled, a real | |
| 131 | + * submission always carries the hidden field with an empty value; a missing | |
| 132 | + * field or any non-empty value is treated as spam. | |
| 133 | + * | |
| 134 | + * The honeypot field holds no sensitive data and is only inspected for | |
| 135 | + * emptiness. Nonce/referer verification is performed by the calling | |
| 136 | + * submission handler before this method runs. | |
| 137 | + * | |
| 138 | + * @return bool True when the submission should be rejected as spam. | |
| 139 | + * @since 1.1.0 | |
| 140 | + */ | |
| 141 | + public static function is_honeypot_spam() { | |
| 142 | + if ( ! self::is_honeypot_enabled() ) { | |
| 143 | + return false; | |
| 144 | + } | |
| 145 | + | |
| 146 | + // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by the calling submission handler; value only checked for emptiness. | |
| 147 | + if ( ! isset( $_POST['suredonation_honeypot'] ) ) { | |
| 148 | + return true; | |
| 149 | + } | |
| 150 | + | |
| 151 | + // phpcs:ignore WordPress.Security.NonceVerification.Missing -- See note above. | |
| 152 | + $value = sanitize_text_field( wp_unslash( $_POST['suredonation_honeypot'] ) ); | |
| 153 | + | |
| 154 | + return '' !== $value; | |
| 155 | + } | |
| 156 | + | |
| 157 | + /** | |
| 95 | 158 | * Get all campaign meta as an array. |
| 96 | 159 | * |
| 97 | 160 | * @param int $campaign_id Campaign post ID. |
| 98 | 161 | * @return array<string, mixed> Campaign meta values. |
| @@ -408,9 +471,9 @@ | ||
| 408 | 471 | * @param string $action Unique action identifier namespacing the bucket. |
| 409 | 472 | * @param int $max Maximum attempts permitted within the window. |
| 410 | 473 | * @param int $window Window length in seconds. |
| 411 | 474 | * @return bool True if the request is within limits; false if the limit is exceeded. |
| 412 | - * @since x.x.x | |
| 475 | + * @since 1.1.0 | |
| 413 | 476 | */ |
| 414 | 477 | public static function check_rate_limit( $action, $max = 15, $window = MINUTE_IN_SECONDS ) { |
| 415 | 478 | $ip = self::get_client_ip(); |
| 416 | 479 | if ( '' === $ip ) { |