Skip to content

Conversation

@shohag121
Copy link
Member

@shohag121 shohag121 commented Nov 7, 2025

All Submissions:

  • My code follow the WordPress' coding standards
  • My code satisfies feature requirements
  • My code is tested
  • My code passes the PHPCS tests
  • My code has proper inline documentation
  • I've included related pull request(s) (optional)
  • I've included developer documentation (optional)
  • I've added proper labels to this pull request

Changes proposed in this Pull Request:

Related Pull Request(s)

Closes

  • Closes #

How to test the changes in this Pull Request:

  • Steps or issue link

Changelog entry

- **update:** Cloudflare Turnstile added as a Captcha provider. 

Before Changes

Describe the issue before changes with screenshots(s).

After Changes

Screenshot 2025-11-07 at 11 18 27 am

Feature Video (optional)

Link of detailed video if this PR is for a feature.

PR Self Review Checklist:

  • Code is not following code style guidelines
  • Bad naming: make sure you would understand your code if you read it a few months from now.
  • KISS: Keep it simple, Sweetie (not stupid!).
  • DRY: Don't Repeat Yourself.
  • Code that is not readable: too many nested 'if's are a bad sign.
  • Performance issues
  • Complicated constructions that need refactoring or comments: code should almost always be self-explanatory.
  • Grammar errors.

FOR PR REVIEWER ONLY:

As a reviewer, your feedback should be focused on the idea, not the person. Seek to understand, be respectful, and focus on constructive dialog.

As a contributor, your responsibility is to learn from suggestions and iterate your pull request should it be needed based on feedback. Seek to collaborate and produce the best possible contribution to the greater whole.

  • Correct — Does the change do what it’s supposed to? ie: code 100% fulfilling the requirements?
  • Secure — Would a nefarious party find some way to exploit this change? ie: everything is sanitized/escaped appropriately for any SQL or XSS injection possibilities?
  • Readable — Will your future self be able to understand this change months down the road?
  • Elegant — Does the change fit aesthetically within the overall style and architecture?

Summary by CodeRabbit

Release Notes

  • New Features

    • Migrated CAPTCHA system to support multiple providers: Google reCAPTCHA v3 and Cloudflare Turnstile
    • Store owners can now select and switch between different CAPTCHA providers in admin settings for improved flexibility
  • Documentation

    • Added comprehensive guide for configuring and migrating to the new CAPTCHA provider system
  • Chores

    • Marked legacy reCAPTCHA functions as deprecated; the new provider-based system is recommended

…upport**

- Added a provider-based architecture for captcha management, supporting multiple providers (Google reCAPTCHA v3 and Cloudflare Turnstile).
- Introduced `CaptchaServiceProvider`, `Manager`, and provider-specific classes for streamlined captcha handling.
- Deprecated legacy captcha helper functions in favor of DI container-resolved manager.
- Updated contact form and asset handling to dynamically adapt based on the selected captcha provider.
- Added comprehensive provider configuration options in the admin settings.
- Included migration documentation (`captcha.md`) outlining integration steps and best practices for transitioning to the new system.
…d compatibility

- Updated token handling to target generic form elements instead of a specific form ID.
- Added a hidden input field for storing the captcha token, ensuring compatibility with various forms.
@shohag121 shohag121 requested a review from mrabbani November 7, 2025 05:12
@shohag121 shohag121 self-assigned this Nov 7, 2025
@shohag121 shohag121 added Needs: Testing This requires further testing Needs: Dev Review It requires a developer review and approval labels Nov 7, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 7, 2025

Walkthrough

This pull request replaces Dokan's hardcoded Google reCAPTCHA v3 integration with a pluggable, provider-based CAPTCHA architecture. The refactor introduces a ProviderInterface contract, an AbstractProvider base class, a Manager registry facade, and two concrete implementations: GoogleRecaptchaV3Provider and CloudflareTurnstileProvider. Legacy reCAPTCHA settings are removed, validation flows are updated to use the new provider system, and functions are marked deprecated.

Changes

Cohort / File(s) Summary
Documentation
docs/captcha.md
New guide describing the provider-based CAPTCHA migration, architecture, admin settings, frontend integration, validation, and migration steps.
Provider Architecture
includes/Captcha/ProviderInterface.php, includes/Captcha/AbstractProvider.php
Introduced public interface defining contract for CAPTCHA providers (slug, label, readiness, asset registration, rendering, validation, admin settings). Added abstract base class implementing common functionality (caching readiness, option retrieval, hook registration, enlistment, boolean normalization).
Provider Implementations
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php, includes/Captcha/Providers/CloudflareTurnstileProvider.php
Added two concrete provider implementations with slug/label, readiness checks, asset registration, field rendering, server-side validation via respective APIs, and admin settings fields.
Provider Management & Registry
includes/Captcha/Manager.php
Introduced central registry and facade managing provider discovery, activation, enablement, asset delegation, validation, field rendering, admin settings integration, and backward-compatible defaults.
Dependency Injection
includes/DependencyManagement/Providers/CaptchaServiceProvider.php, includes/DependencyManagement/Providers/ServiceProvider.php
Added CaptchaServiceProvider registering Manager and provider implementations into DI container; integrated into main ServiceProvider boot sequence.
Core Integration Updates
includes/Admin/Settings.php
Removed legacy Google reCAPTCHA v3 validation settings block (site key, secret key, and related flags) from Dokan appearance settings.
Validation Flow Migration
includes/Ajax.php
Replaced direct reCAPTCHA validation with provider-agnostic flow using Manager from DI container; checks active provider before validating token.
Asset Management
includes/Assets.php
Removed legacy dokan-google-recaptcha script entry; replaced manual reCAPTCHA enqueuing with manager-driven asset registration via DI container.
Backward Compatibility
includes/functions.php
Added deprecation annotations to dokan_get_vendor_store_banner_height, dokan_get_recaptcha_site_and_secret_keys, and dokan_handle_recaptcha_validation without changing signatures.
Template Updates
templates/widgets/store-contact-form.php
Removed hardcoded recaptcha token hidden input field from store contact form.

Sequence Diagram(s)

sequenceDiagram
    participant User as Frontend
    participant Ajax as Ajax Handler
    participant Manager as Captcha Manager
    participant Provider as Active Provider
    participant External as External API

    User->>Ajax: Submit form with captcha token
    Ajax->>Manager: validate(context, token)
    
    rect rgb(200, 230, 255)
        note over Manager: Check if enabled & provider ready
        Manager->>Manager: is_enabled()?
        Manager->>Manager: get_active_provider()
    end
    
    alt Provider enabled and ready
        Manager->>Provider: validate(context, token)
        rect rgb(200, 255, 220)
            note over Provider: Server-side verification
            Provider->>External: POST siteverify (token, secret)
            External-->>Provider: Success/failure response
        end
        Provider-->>Manager: bool (valid/invalid)
    else Provider not available
        Manager-->>Ajax: false (invalid)
    end
    
    Manager-->>Ajax: bool result
    
    alt Token valid
        Ajax->>User: Process form submission
    else Token invalid
        Ajax->>User: Validation error
    end
Loading
sequenceDiagram
    participant Admin as Admin User
    participant Settings as Settings Panel
    participant Manager as Captcha Manager
    participant Providers as Registered Providers

    Admin->>Settings: Open appearance settings
    Settings->>Manager: filter_settings_fields()
    
    rect rgb(200, 230, 255)
        note over Manager: Build provider registry
        Manager->>Manager: register_providers_from_filter()
        Manager->>Providers: Discover from dokan_captcha_providers filter
        Providers-->>Manager: Provider instances
    end
    
    Manager->>Manager: Get active provider settings
    Manager->>Providers: get_admin_settings_fields()
    Providers-->>Manager: Provider-specific fields
    
    Manager-->>Settings: Global enable + provider select + provider fields
    Settings->>Admin: Rendered form with all captcha options
    
    Admin->>Admin: Select provider & configure
    Admin->>Settings: Save settings
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Areas requiring extra attention:
    • includes/Captcha/Manager.php — Central registry with multiple responsibilities (provider discovery, activation, settings filtering); verify filter hook integration and backward-compatibility logic
    • includes/Ajax.php — Validation flow replacement; ensure error handling parity with legacy flow and DI container integration correctness
    • includes/Captcha/AbstractProvider.php and concrete providers — Interface contract compliance, readiness caching logic, and API integration correctness (especially Cloudflare Turnstile and Google validation endpoints)
    • includes/Admin/Settings.php — Verify all legacy reCAPTCHA settings removal does not orphan related logic elsewhere
    • includes/Assets.php — DI container asset registration pathway; ensure lazy loading and script dependencies are correct

Possibly related PRs

Suggested labels

Dev Review Done, Upcoming Release

Suggested reviewers

  • mrabbani

Poem

🐰 Hop along, old CAPTCHA ways so worn,
The Provider system greets the dawn,
Turnstile and reCAPTCHA stand as one,
With pluggable magic, the battle's won!
Flexible, clean, and ready to play,
Dokan's captcha leaps into the fray! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning PR description lacks critical details about changes and testing procedures despite containing comprehensive structural sections. Add specific implementation details in 'Changes proposed' section, describe changes in 'Before Changes' section, complete testing steps, and mark completed checklist items.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Dokan Captcha service Provider' is directly related to the main change—introducing a new Captcha service provider architecture. However, it is somewhat generic and doesn't specify the key implementation details like the provider-based system or the removal of legacy reCAPTCHA v3 hardcoding.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch update/captcha-service-provider

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (10)
docs/captcha.md (2)

6-6: Replace DOKAN_SINCE placeholder with the actual version.

Readers need a concrete version (e.g., “≥ 4.0.8”).


74-75: Keep docs consistent with code: token/asset flow.

Note: GoogleRecaptchaV3Provider now enqueues the Google API directly; it’s no longer pre‑registered in Assets::get_scripts(). Please adjust the note accordingly.

includes/functions.php (2)

4021-4044: Mark usage at runtime for deprecated helper.

Add wc_deprecated_function() so developers get runtime notices when calling this.

 function dokan_get_recaptcha_site_and_secret_keys( $boolean = false ) {
+    wc_deprecated_function( __FUNCTION__, 'DOKAN 4.0.8', '\WeDevs\Dokan\Captcha\Manager + providers' );

4050-4088: Ditto: deprecate with runtime notice.

Emit a deprecation notice on entry.

 function dokan_handle_recaptcha_validation( $action, $token, $secretkey ) {
+    wc_deprecated_function( __FUNCTION__, 'DOKAN 4.0.8', '\WeDevs\Dokan\Captcha\Manager::validate()' );
includes/DependencyManagement/Providers/ServiceProvider.php (1)

71-72: Ensure CAPTCHA hooks are registered during boot.

After registering CaptchaServiceProvider, proactively call Manager->register_hooks() so provider fields/settings are injected even if no global Hookable bootstrap runs.

-        $this->getContainer()->addServiceProvider( new CaptchaServiceProvider() );
+        $this->getContainer()->addServiceProvider( new CaptchaServiceProvider() );
+        // Ensure Captcha hooks are registered early.
+        $this->getContainer()->get( \WeDevs\Dokan\Captcha\Manager::class )->register_hooks();

If hooks are already auto-booted for all Hookable services elsewhere, ignore this and confirm where that happens.

includes/Ajax.php (1)

347-356: Fail closed when CAPTCHA is enabled, and tighten condition/message.

  • If captcha is enabled but no active provider is ready, the form currently bypasses validation. Prefer failing closed in that case.
  • Use a strict boolean check and generic message (works for Turnstile too).
-        // Validate captcha using the selected provider if available
-        $captcha_manager = dokan_get_container()->get( \WeDevs\Dokan\Captcha\Manager::class );
-        if ( $captcha_manager && $captcha_manager->get_active_provider() ) {
-            $is_valid = $captcha_manager->validate( 'dokan_contact_seller_recaptcha', $recaptcha_token );
-
-            if ( empty( $is_valid ) ) {
-                $message = sprintf( $error_template, __( 'reCAPTCHA verification failed!', 'dokan-lite' ) );
-                wp_send_json_error( $message );
-            }
-        }
+        // Validate captcha using the selected provider
+        $captcha_manager = dokan_get_container()->get( \WeDevs\Dokan\Captcha\Manager::class );
+        if ( $captcha_manager && $captcha_manager->is_enabled() ) {
+            $provider = $captcha_manager->get_active_provider();
+            if ( ! $provider ) {
+                $message = sprintf( $error_template, __( 'Captcha is not configured. Please try again later.', 'dokan-lite' ) );
+                wp_send_json_error( $message );
+            }
+            $is_valid = $captcha_manager->validate( 'dokan_contact_seller_recaptcha', $recaptcha_token );
+            if ( ! $is_valid ) {
+                $message = sprintf( $error_template, __( 'Captcha verification failed!', 'dokan-lite' ) );
+                wp_send_json_error( $message );
+            }
+        }

Confirm UX: if you prefer soft‑fail when disabled, this only enforces when the global “Enable Captcha Service” is on.

includes/DependencyManagement/Providers/CaptchaServiceProvider.php (1)

15-33: Register hooks in a boot phase to guarantee provider readiness.

Consider making this provider bootable and invoking register_hooks() for Manager and providers. This avoids relying on a separate global Hookable bootstrap.

-namespace WeDevs\Dokan\DependencyManagement\Providers;
+namespace WeDevs\Dokan\DependencyManagement\Providers;
@@
-use WeDevs\Dokan\DependencyManagement\BaseServiceProvider;
+use WeDevs\Dokan\DependencyManagement\BootableServiceProvider;
@@
-class CaptchaServiceProvider extends BaseServiceProvider {
+class CaptchaServiceProvider extends BootableServiceProvider {
@@
     public function register(): void {
         foreach ( $this->services as $service ) {
             $definition = $this->share_with_implements_tags( $service );
             $this->add_tags( $definition, $this->tags );
         }
     }
+
+    public function boot(): void {
+        // Ensure hooks are registered once services are in the container.
+        $this->getContainer()->get( \WeDevs\Dokan\Captcha\Manager::class )->register_hooks();
+        foreach ( [ \WeDevs\Dokan\Captcha\Providers\GoogleRecaptchaV3Provider::class, \WeDevs\Dokan\Captcha\Providers\CloudflareTurnstileProvider::class ] as $cls ) {
+            $this->getContainer()->get( $cls )->register_hooks();
+        }
+    }

If there is already a global boot mechanism that calls register_hooks() for all Hookable services, please confirm and feel free to skip this change.

includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (1)

52-64: Update comment and avoid implying pre-registration.

The handle isn’t pre-registered in Assets anymore. Tweak the comment to avoid confusion, or wrap with wp_script_is to avoid duplicate enqueue.

-        // The handle is already registered in Assets::get_scripts() as 'dokan-google-recaptcha'.
+        // Enqueue Google reCAPTCHA v3 with the site key; helper code consumes dokan_google_recaptcha.recaptcha_sitekey.
+        // Guard against duplicate enqueue if needed.
+        if ( wp_script_is( 'dokan-google-recaptcha', 'enqueued' ) ) {
+            return;
+        }
includes/Captcha/Providers/CloudflareTurnstileProvider.php (2)

56-66: Reuse the site key and bail out defensively.

$site is fetched but unused, tripping PHPMD. Using it to short-circuit keeps the code tidy and protects against stale readiness cache if the key is removed mid-request.

-        $site = $this->get_option( 'turnstile_site_key', '' );
-        // Register & enqueue Turnstile API
+        $site = $this->get_option( 'turnstile_site_key', '' );
+        if ( empty( $site ) ) {
+            return;
+        }
+
+        // Register & enqueue Turnstile API

60-61: Version the registered script to avoid stale caches.

WordPress coding standards flag unversioned script registration because browsers may cache an out-of-date asset. Pass your plugin version (or another stable version) so cache busting works predictably.

-            wp_register_script( $handle, 'https://challenges.cloudflare.com/turnstile/v0/api.js', [], null, true );
+            wp_register_script( $handle, 'https://challenges.cloudflare.com/turnstile/v0/api.js', [], DOKAN_PLUGIN_VERSION, true );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c8a580 and 5612b16.

⛔ Files ignored due to path filters (1)
  • assets/images/cloudflare.png is excluded by !**/*.png
📒 Files selected for processing (13)
  • docs/captcha.md (1 hunks)
  • includes/Admin/Settings.php (0 hunks)
  • includes/Ajax.php (1 hunks)
  • includes/Assets.php (1 hunks)
  • includes/Captcha/AbstractProvider.php (1 hunks)
  • includes/Captcha/Manager.php (1 hunks)
  • includes/Captcha/ProviderInterface.php (1 hunks)
  • includes/Captcha/Providers/CloudflareTurnstileProvider.php (1 hunks)
  • includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (1 hunks)
  • includes/DependencyManagement/Providers/CaptchaServiceProvider.php (1 hunks)
  • includes/DependencyManagement/Providers/ServiceProvider.php (1 hunks)
  • includes/functions.php (2 hunks)
  • templates/widgets/store-contact-form.php (0 hunks)
💤 Files with no reviewable changes (2)
  • templates/widgets/store-contact-form.php
  • includes/Admin/Settings.php
🧰 Additional context used
🧬 Code graph analysis (9)
includes/Ajax.php (5)
dokan.php (1)
  • dokan_get_container (79-83)
includes/Captcha/Manager.php (3)
  • Manager (17-206)
  • get_active_provider (91-104)
  • validate (115-121)
includes/Captcha/Providers/CloudflareTurnstileProvider.php (1)
  • validate (96-115)
includes/Captcha/ProviderInterface.php (1)
  • validate (40-40)
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (1)
  • validate (89-110)
includes/DependencyManagement/Providers/ServiceProvider.php (1)
includes/DependencyManagement/Providers/CaptchaServiceProvider.php (1)
  • CaptchaServiceProvider (15-34)
includes/DependencyManagement/Providers/CaptchaServiceProvider.php (5)
includes/Captcha/Providers/CloudflareTurnstileProvider.php (1)
  • CloudflareTurnstileProvider (14-157)
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (1)
  • GoogleRecaptchaV3Provider (14-168)
includes/DependencyManagement/BaseServiceProvider.php (3)
  • BaseServiceProvider (21-103)
  • share_with_implements_tags (86-88)
  • add_tags (98-102)
includes/Captcha/Manager.php (1)
  • Manager (17-206)
includes/DependencyManagement/Providers/ServiceProvider.php (1)
  • register (93-97)
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (4)
includes/Captcha/AbstractProvider.php (5)
  • AbstractProvider (14-93)
  • compute_readiness (48-48)
  • get_option (19-21)
  • is_ready (31-37)
  • to_bool (84-92)
includes/Captcha/Providers/CloudflareTurnstileProvider.php (7)
  • get_slug (20-22)
  • get_label (29-31)
  • compute_readiness (38-45)
  • register_assets (52-67)
  • render_field_html (77-86)
  • validate (96-115)
  • get_admin_settings_fields (122-155)
includes/Captcha/ProviderInterface.php (7)
  • get_slug (9-9)
  • get_label (12-12)
  • register_assets (21-21)
  • is_ready (15-15)
  • render_field_html (30-30)
  • validate (40-40)
  • get_admin_settings_fields (48-48)
includes/Captcha/Manager.php (4)
  • register_assets (107-112)
  • render_field_html (124-130)
  • validate (115-121)
  • to_bool (198-205)
includes/Captcha/Manager.php (7)
includes/Admin/Settings.php (1)
  • Settings (18-1112)
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (8)
  • GoogleRecaptchaV3Provider (14-168)
  • get_slug (20-22)
  • to_bool (119-126)
  • register_assets (52-64)
  • validate (89-110)
  • render_field_html (77-79)
  • get_label (29-31)
  • get_admin_settings_fields (134-167)
includes/Captcha/AbstractProvider.php (3)
  • register_hooks (58-60)
  • to_bool (84-92)
  • is_ready (31-37)
includes/Captcha/Providers/CloudflareTurnstileProvider.php (6)
  • get_slug (20-22)
  • register_assets (52-67)
  • validate (96-115)
  • render_field_html (77-86)
  • get_label (29-31)
  • get_admin_settings_fields (122-155)
includes/Captcha/ProviderInterface.php (7)
  • get_slug (9-9)
  • is_ready (15-15)
  • register_assets (21-21)
  • validate (40-40)
  • render_field_html (30-30)
  • get_label (12-12)
  • get_admin_settings_fields (48-48)
includes/functions.php (1)
  • dokan_get_option (1014-1024)
dokan.php (1)
  • dokan_get_container (79-83)
includes/Captcha/Providers/CloudflareTurnstileProvider.php (4)
includes/Captcha/AbstractProvider.php (4)
  • AbstractProvider (14-93)
  • compute_readiness (48-48)
  • get_option (19-21)
  • is_ready (31-37)
includes/Captcha/ProviderInterface.php (7)
  • get_slug (9-9)
  • get_label (12-12)
  • register_assets (21-21)
  • is_ready (15-15)
  • render_field_html (30-30)
  • validate (40-40)
  • get_admin_settings_fields (48-48)
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (7)
  • get_slug (20-22)
  • get_label (29-31)
  • compute_readiness (38-45)
  • register_assets (52-64)
  • render_field_html (77-79)
  • validate (89-110)
  • get_admin_settings_fields (134-167)
includes/Captcha/Manager.php (3)
  • register_assets (107-112)
  • render_field_html (124-130)
  • validate (115-121)
includes/Captcha/ProviderInterface.php (4)
includes/Captcha/Providers/CloudflareTurnstileProvider.php (6)
  • get_slug (20-22)
  • get_label (29-31)
  • register_assets (52-67)
  • render_field_html (77-86)
  • validate (96-115)
  • get_admin_settings_fields (122-155)
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (6)
  • get_slug (20-22)
  • get_label (29-31)
  • register_assets (52-64)
  • render_field_html (77-79)
  • validate (89-110)
  • get_admin_settings_fields (134-167)
includes/Captcha/AbstractProvider.php (1)
  • is_ready (31-37)
includes/Captcha/Manager.php (3)
  • register_assets (107-112)
  • render_field_html (124-130)
  • validate (115-121)
includes/Captcha/AbstractProvider.php (5)
includes/functions.php (1)
  • dokan_get_option (1014-1024)
includes/Captcha/ProviderInterface.php (1)
  • is_ready (15-15)
includes/Captcha/Providers/CloudflareTurnstileProvider.php (1)
  • compute_readiness (38-45)
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (1)
  • compute_readiness (38-45)
includes/Captcha/Manager.php (1)
  • register_hooks (27-34)
includes/Assets.php (5)
dokan.php (1)
  • dokan_get_container (79-83)
includes/Captcha/Manager.php (2)
  • Manager (17-206)
  • register_assets (107-112)
includes/Captcha/Providers/CloudflareTurnstileProvider.php (1)
  • register_assets (52-67)
includes/Captcha/ProviderInterface.php (1)
  • register_assets (21-21)
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php (1)
  • register_assets (52-64)
🪛 GitHub Check: Run PHPCS inspection
includes/Captcha/Providers/CloudflareTurnstileProvider.php

[failure] 157-157:
The closing brace for the class must go on the next line after the body


[warning] 60-60:
Resource version not set in call to wp_register_script(). This means new versions of the script may not always be loaded due to browser caching.

includes/Captcha/AbstractProvider.php

[warning] 19-19:
It is recommended not to use reserved keyword "default" as function parameter name. Found: $default

🪛 LanguageTool
docs/captcha.md

[uncategorized] ~31-~31: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...via the dokan_captcha_providers filter so third parties can add providers - Deleg...

(COMMA_COMPOUND_SENTENCE_2)

🪛 PHPMD (2.15.0)
includes/Captcha/Providers/GoogleRecaptchaV3Provider.php

77-77: Avoid unused parameters such as '$context'. (undefined)

(UnusedFormalParameter)


77-77: Avoid unused parameters such as '$args'. (undefined)

(UnusedFormalParameter)

includes/Captcha/Manager.php

145-145: Avoid unused parameters such as '$settings_instance'. (undefined)

(UnusedFormalParameter)

includes/Captcha/Providers/CloudflareTurnstileProvider.php

56-56: Avoid unused local variables such as '$site'. (undefined)

(UnusedLocalVariable)


77-77: Avoid unused parameters such as '$context'. (undefined)

(UnusedFormalParameter)


77-77: Avoid unused parameters such as '$args'. (undefined)

(UnusedFormalParameter)


96-96: Avoid unused parameters such as '$context'. (undefined)

(UnusedFormalParameter)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: e2e tests (1, 3)
  • GitHub Check: e2e tests (3, 3)
  • GitHub Check: e2e tests (2, 3)
  • GitHub Check: api tests (1, 1)
🔇 Additional comments (2)
includes/Assets.php (1)

853-856: Review comment is incorrect - Manager::register_hooks() and Provider register_hooks() are properly invoked.

The bootstrap mechanism in dokan-class.php (lines 273-276) retrieves all services implementing the Hookable interface from the container and explicitly calls register_hooks() on each one during the init action. Since both Manager and AbstractProvider implement Hookable, their register_hooks() methods are automatically invoked as part of the normal plugin initialization sequence, ensuring CAPTCHA hooks and fields are properly registered.

Likely an incorrect or invalid review comment.

includes/Captcha/Manager.php (1)

149-192: Good job wiring provider-specific settings gating.

The combined show_if conditions keep provider fields hidden unless captcha is enabled and the matching provider is selected, which will save merchants a lot of confusion.

Comment on lines +96 to +114
public function validate( string $context, string $token ): bool {
$secret = $this->get_option( 'turnstile_secret_key', '' );
if ( empty( $token ) || empty( $secret ) ) {
return false;
}
$response = wp_remote_post(
'https://challenges.cloudflare.com/turnstile/v0/siteverify', [
'body' => [
'secret' => $secret,
'response' => $token,
],
]
);
if ( is_wp_error( $response ) ) {
return false;
}
$response_body = wp_remote_retrieve_body( $response );
$data = json_decode( $response_body, true );
return ! empty( $data['success'] );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Prevent fatal when Cloudflare returns non-JSON payloads.

json_decode() can return null (e.g., HTML error page or empty body). Accessing $data['success'] on a non-array throws a PHP 8 fatal (“Cannot use array offset on value of type null”), breaking captcha validation and the request path. Guard the decode result before reading offsets.

-        $data = json_decode( $response_body, true );
-        return ! empty( $data['success'] );
+        $data = json_decode( $response_body, true );
+        if ( ! is_array( $data ) ) {
+            return false;
+        }
+
+        return ! empty( $data['success'] );
🧰 Tools
🪛 PHPMD (2.15.0)

96-96: Avoid unused parameters such as '$context'. (undefined)

(UnusedFormalParameter)

🤖 Prompt for AI Agents
In includes/Captcha/Providers/CloudflareTurnstileProvider.php around lines 96 to
114, json_decode() can return null for non-JSON responses which makes
$data['success'] access fatal; after decoding, ensure the result is an array and
that the 'success' key exists before accessing it—if json_decode() does not
return an array (or the 'success' key is absent), return false; implement this
guard by checking is_array($data) and using isset/array_key_exists on 'success'
(or default to false) before returning the boolean.

Comment on lines +155 to +157
}

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Fix class-closing brace indentation.

PHPCS is failing because the class closing brace is indented. WordPress standards expect it flush-left.

-}
+}

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Check: Run PHPCS inspection

[failure] 157-157:
The closing brace for the class must go on the next line after the body

🤖 Prompt for AI Agents
In includes/Captcha/Providers/CloudflareTurnstileProvider.php around lines 155
to 157, the class closing brace is indented; adjust the file so the final "}" of
the class is flush-left (no leading spaces or tabs) to match WordPress PHPCS
standards. Ensure there is a single newline after the closing brace if file ends
there and that indentation inside the class remains unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs: Dev Review It requires a developer review and approval Needs: Testing This requires further testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants