verifier = $verifier; $this->init_hooks(); } /** * Initialize all form hooks. */ private function init_hooks() { // Enqueue script add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts')); add_action('login_enqueue_scripts', array($this, 'enqueue_scripts')); // 1. WordPress Login Form if ($this->verifier->is_enabled('enable_wp_login')) { add_action('login_form', array($this, 'render_widget')); add_filter('authenticate', array($this, 'verify_wp_login'), 30, 3); } // 2. WordPress Registration Form if ($this->verifier->is_enabled('enable_wp_register')) { add_action('register_form', array($this, 'render_widget')); add_filter('registration_errors', array($this, 'verify_wp_register'), 10, 3); } // 3. WordPress Comments Form if ($this->verifier->is_enabled('enable_wp_comments')) { add_action('comment_form_after_fields', array($this, 'render_widget')); add_action('comment_form_logged_in_after_fields', array($this, 'render_widget')); add_filter('preprocess_comment', array($this, 'verify_wp_comment')); } // 4. WordPress Lost Password Form if ($this->verifier->is_enabled('enable_wp_lostpassword')) { add_action('lostpassword_form', array($this, 'render_widget')); add_action('lostpassword_post', array($this, 'verify_wp_lostpassword'), 10, 1); } // 5. WooCommerce Login Form if ($this->verifier->is_enabled('enable_wc_login')) { add_action('woocommerce_login_form', array($this, 'render_widget')); add_filter('woocommerce_process_login_errors', array($this, 'verify_wc_login'), 10, 3); } // 6. WooCommerce Register Form if ($this->verifier->is_enabled('enable_wc_register')) { add_action('woocommerce_register_form', array($this, 'render_widget')); add_filter('woocommerce_process_registration_errors', array($this, 'verify_wc_register'), 10, 4); } // 7. WooCommerce Lost Password Form if ($this->verifier->is_enabled('enable_wc_lostpassword')) { add_action('woocommerce_lostpassword_form', array($this, 'render_widget')); add_action('woocommerce_lostpassword_post', array($this, 'verify_wc_lostpassword')); } // 8. WooCommerce Checkout Form if ($this->verifier->is_enabled('enable_wc_checkout')) { add_action('woocommerce_review_order_before_submit', array($this, 'render_widget')); add_action('woocommerce_checkout_process', array($this, 'verify_wc_checkout')); } // 9 & 10. WPForms (Lite & Pro) if ($this->verifier->is_enabled('enable_wpforms_lite') || $this->verifier->is_enabled('enable_wpforms_pro')) { add_action('wpforms_display_submit_before', array($this, 'render_widget_wpforms'), 10, 1); add_action('wpforms_process', array($this, 'verify_wpforms'), 10, 3); } } /** * Enqueue the Shielda widget script. */ public function enqueue_scripts() { if ($this->script_enqueued) { return; } $site_key = $this->verifier->get_site_key(); if (empty($site_key)) { return; } $script_url = SHIELDA_WIDGET_JS_URL; wp_enqueue_script( 'shielda-widget', $script_url, array(), SHIELDA_VERSION, array('strategy' => 'defer', 'in_footer' => false) ); // Add inline CSS for widget layout $custom_css = " .shielda-captcha-wrapper { margin: 14px 0; display: flex; flex-direction: column; align-items: flex-start; clear: both; } .shielda-captcha-wrapper .darban-captcha { min-height: 80px; width: 100%; max-width: 360px; } #loginform .shielda-captcha-wrapper, #registerform .shielda-captcha-wrapper, #lostpasswordform .shielda-captcha-wrapper { margin-bottom: 20px; } "; wp_add_inline_style('login', $custom_css); wp_register_style('shielda-inline-style', false); wp_enqueue_style('shielda-inline-style'); wp_add_inline_style('shielda-inline-style', $custom_css); $this->script_enqueued = true; } /** * Render the CAPTCHA widget DOM element. */ public function render_widget() { $site_key = $this->verifier->get_site_key(); if (empty($site_key)) { return; } $this->enqueue_scripts(); echo '
'; echo '
'; echo '
'; } /** * Render widget for WPForms. * * @param array $form_data */ public function render_widget_wpforms($form_data) { $this->render_widget(); } /* ── Verification Methods ──────────────────────────────────── */ /** * Verify WordPress Login. * * @param WP_User|WP_Error|null $user * @param string $username * @param string $password * @return WP_User|WP_Error */ public function verify_wp_login($user, $username, $password) { // Skip verification if already an error or if empty credentials (standard WP behavior) if (empty($username) || empty($password)) { return $user; } // Don't verify if already errored if (is_wp_error($user) && $user->get_error_code() !== '') { return $user; } $check = $this->verifier->verify(); if (!$check['success']) { return new WP_Error('shielda_captcha_error', '' . esc_html__('خطای امنیتی شیلدا:', 'shielda-captcha') . ' ' . esc_html($check['message'])); } return $user; } /** * Verify WordPress Registration. * * @param WP_Error $errors * @param string $sanitized_user_login * @param string $user_email * @return WP_Error */ public function verify_wp_register($errors, $sanitized_user_login, $user_email) { $check = $this->verifier->verify(); if (!$check['success']) { $errors->add('shielda_captcha_error', '' . esc_html__('خطای امنیتی شیلدا:', 'shielda-captcha') . ' ' . esc_html($check['message'])); } return $errors; } /** * Verify WordPress Comment. * * @param array $commentdata * @return array */ public function verify_wp_comment($commentdata) { // Allow pingbacks / trackbacks without captcha if (isset($commentdata['comment_type']) && in_array($commentdata['comment_type'], array('pingback', 'trackback'), true)) { return $commentdata; } $check = $this->verifier->verify(); if (!$check['success']) { wp_die( '' . esc_html__('خطای امنیتی شیلدا:', 'shielda-captcha') . ' ' . esc_html($check['message']), esc_html__('بررسی کپچا ناموفق بود', 'shielda-captcha'), array('back_link' => true) ); } return $commentdata; } /** * Verify WordPress Lost Password. * * @param WP_Error|null $errors */ public function verify_wp_lostpassword($errors) { $check = $this->verifier->verify(); if (!$check['success']) { if (is_wp_error($errors)) { $errors->add('shielda_captcha_error', '' . esc_html__('خطای امنیتی شیلدا:', 'shielda-captcha') . ' ' . esc_html($check['message'])); } else { wp_die( '' . esc_html__('خطای امنیتی شیلدا:', 'shielda-captcha') . ' ' . esc_html($check['message']), esc_html__('بررسی کپچا ناموفق بود', 'shielda-captcha'), array('back_link' => true) ); } } } /** * Verify WooCommerce Login. * * @param WP_Error $validation_error * @param string $username * @param string $password * @return WP_Error */ public function verify_wc_login($validation_error, $username, $password) { if (empty($username) || empty($password)) { return $validation_error; } $check = $this->verifier->verify(); if (!$check['success']) { $validation_error->add('shielda_captcha_error', '' . esc_html__('خطای امنیتی شیلدا:', 'shielda-captcha') . ' ' . esc_html($check['message'])); } return $validation_error; } /** * Verify WooCommerce Registration. * * @param WP_Error $errors * @param string $username * @param string $password * @param string $email * @return WP_Error */ public function verify_wc_register($errors, $username, $password, $email) { $check = $this->verifier->verify(); if (!$check['success']) { $errors->add('shielda_captcha_error', '' . esc_html__('خطای امنیتی شیلدا:', 'shielda-captcha') . ' ' . esc_html($check['message'])); } return $errors; } /** * Verify WooCommerce Lost Password. */ public function verify_wc_lostpassword() { $check = $this->verifier->verify(); if (!$check['success']) { if (function_exists('wc_add_notice')) { wc_add_notice('' . esc_html__('خطای امنیتی شیلدا:', 'shielda-captcha') . ' ' . esc_html($check['message']), 'error'); } } } /** * Verify WooCommerce Checkout. */ public function verify_wc_checkout() { $check = $this->verifier->verify(); if (!$check['success']) { if (function_exists('wc_add_notice')) { wc_add_notice('' . esc_html__('خطای امنیتی شیلدا:', 'shielda-captcha') . ' ' . esc_html($check['message']), 'error'); } } } /** * Verify WPForms submission. * * @param array $fields * @param array $entry * @param array $form_data */ public function verify_wpforms($fields, $entry, $form_data) { $check = $this->verifier->verify(); if (!$check['success']) { if (function_exists('wpforms')) { wpforms()->process->errors[$form_data['id']]['header'] = esc_html($check['message']); } } } }