Skip to content

Conversation

@rakib1904107
Copy link

@rakib1904107 rakib1904107 commented Dec 19, 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:

Added a caching layer to avoid redundant database queries. The query now executes only once, with subsequent calls fetching the cached result instead of hitting the database.

Related Pull Request(s)

  • Full PR Link

Closes

How to test the changes in this Pull Request:

  • Go to the Vendor Dashboard.
  • Open Query Monitor and check the "Duplicate Queries" section.
  • Look for the method WPML_Multilingual_Options_Utils->get_option_without_filtering().

Changelog entry

*Title: Bug/Problem - Duplicate Queries Detected on Vendor Dashboard When Dokan WPML Is Enabled

Before Changes

When Dokan WPML is active, Query Monitor reports duplicate database queries on the vendor dashboard. The duplicate calls originate from the method WPML_Multilingual_Options_Utils->get_option_without_filtering().

After Changes

The vendor dashboard avoid unnecessary duplicate option queries, especially those triggered through WPML, to ensure optimal performance.

Feature Video (optional)

Video reference: https://d.pr/v/Gaa2R9

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

  • Performance Improvements

    • Implemented option caching to speed repeated settings lookups and reduce load.
    • Cached values are reused across requests to improve responsiveness.
  • Reliability / Bug Fixes

    • Added automatic cache invalidation when related settings change so updates appear immediately.
    • Ensures users see the latest configuration without stale values.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 19, 2025

📝 Walkthrough

Walkthrough

Adds an in-memory option cache to Dokan_WPML: a private static cache, hooks registered to clear specific cached options on option changes, a public cache-clearing method, and get_raw_option updated to return cached values and populate the cache on misses.

Changes

Cohort / File(s) Summary
Option caching & hooks
dokan-wpml.php
Introduced private static $cached_options; constructor registers updated_option, added_option, and deleted_option hooks to call cache invalidation.
Cache invalidation API
dokan-wpml.php
Added public function clear_option_cache( $option ) to remove the specific option entry from the in-memory cache.
Cached option retrieval
dokan-wpml.php
get_raw_option($option, $section, $default='') now returns self::$cached_options[$section][$option] when present; on miss, calls WPML_Multilingual_Options_Utils->get_option_without_filtering(), stores the result in the cache, and returns it.

Sequence Diagram(s)

sequenceDiagram
  participant Caller as Dokan_WPML::get_raw_option
  participant Cache as In-memory Cache (self::$cached_options)
  participant WPML as WPML_Multilingual_Options_Utils
  participant WP as WordPress Options

  rect rgb(230, 247, 255)
    Caller->>Cache: check [section][option]
    alt cache hit
      Cache-->>Caller: return cached value
    else cache miss
      Caller->>WPML: get_option_without_filtering(option, section, default)
      WPML->>WP: read option from DB (or WP option API)
      WP-->>WPML: option value
      WPML-->>Caller: raw option value
      Caller->>Cache: store value at [section][option]
      Cache-->>Caller: return stored value
    end
  end

  note over WP,Cache: Hooks (updated_option/added_option/deleted_option)\ncall Dokan_WPML::clear_option_cache(option) to remove cached entry
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

"I nibble bits of code with care,
Caching crumbs saved from repeated fare.
A hop, a tuck, options now fast —
No duplicate queries stuck in the past. 🐇"

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix/duplicate-queries-vendor-dashboard-dokan-wpml' directly addresses the primary objective of eliminating duplicate database queries on the vendor dashboard when Dokan WPML is active.
Linked Issues check ✅ Passed The PR successfully implements caching for WPML options to eliminate duplicate queries from WPML_Multilingual_Options_Utils->get_option_without_filtering(), directly satisfying the core requirement in issue #5258.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing option caching in the Dokan_WPML class to prevent duplicate queries; no unrelated modifications were introduced.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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 fix/duplicate-queries-vendor-dashboard-dokan-wpml

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4667338 and a00af31.

📒 Files selected for processing (1)
  • dokan-wpml.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • dokan-wpml.php

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

@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: 0

🧹 Nitpick comments (1)
dokan-wpml.php (1)

52-57: Minor: Use PHPDoc format for the docblock.

The comment uses /* instead of /**, which means IDEs and documentation generators won't recognize it as a proper PHPDoc block.

Suggested fix
-    /*
+    /**
      * Cached options
      *
      * @var array
      */
     private $cached_options = [];
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 04340bd and b4ab57d.

📒 Files selected for processing (1)
  • dokan-wpml.php (2 hunks)
🔇 Additional comments (1)
dokan-wpml.php (1)

1013-1033: Caching implementation looks good.

The per-request cache correctly prevents duplicate database queries to WPML_Multilingual_Options_Utils->get_option_without_filtering(). Since the class uses a singleton pattern, the cache persists across all calls within the same request.

One minor note: if WPML_Multilingual_Options_Utils class is not loaded (line 1020-1022), the fallback path doesn't cache its result. This is acceptable since WPML is a required dependency, but worth being aware of if debugging caching behavior in edge cases.

Copy link

@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: 0

🧹 Nitpick comments (1)
dokan-wpml.php (1)

221-235: Cache invalidation works correctly for the current use case.

The unused parameter warnings from PHPMD are false positives—$param2 and $param3 are required because WordPress hooks pass different numbers of arguments (updated_option passes 3, added_option passes 2, deleted_option passes 1), and this method must be compatible with all three.

However, the invalidation logic assumes only the dokan_pages option is cached. While this matches current usage (lines 590, 785, 813), the get_raw_option method signature is generic and could cache other sections. If the method is used for other sections in the future, those cached values won't be invalidated properly.

🔎 Optional: More defensive cache invalidation

If you want to future-proof the cache invalidation for any section, consider checking if the updated option matches any cached section:

 public function clear_option_cache( $option, $param2 = null, $param3 = null ) {
-    // Clear only if dokan_pages option is affected
-    if ( $option === 'dokan_pages' ) {
-       $this->cached_options = [];
+    // Clear cache entries for the affected option/section
+    if ( empty( $this->cached_options ) ) {
+        return;
     }
+    
+    foreach ( array_keys( $this->cached_options ) as $cache_key ) {
+        // Cache keys are formatted as: {section}_{option}
+        // If the section matches the updated option name, clear it
+        if ( strpos( $cache_key, $option . '_' ) === 0 ) {
+            unset( $this->cached_options[ $cache_key ] );
+        }
+    }
 }

This approach clears only the cache entries for the affected section rather than the entire cache, making it safer if the method is used for caching other WordPress options in the future.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b4ab57d and 82767f1.

📒 Files selected for processing (1)
  • dokan-wpml.php
🧰 Additional context used
🪛 PHPMD (2.15.0)
dokan-wpml.php

230-230: Avoid unused parameters such as '$param2'. (undefined)

(UnusedFormalParameter)


230-230: Avoid unused parameters such as '$param3'. (undefined)

(UnusedFormalParameter)

🔇 Additional comments (3)
dokan-wpml.php (3)

52-57: LGTM!

Clean addition of the cache storage property to hold option values in memory.


92-96: Cache invalidation hooks correctly registered.

The three hooks properly cover all option lifecycle events (add, update, delete) to ensure cache coherency.


1033-1053: Caching implementation correctly eliminates duplicate queries.

The cache-check-before-fetch pattern is correctly implemented and directly addresses the PR objective to eliminate duplicate calls to WPML_Multilingual_Options_Utils->get_option_without_filtering().

The cache key construction ({section}_{option}) is straightforward and appropriate for the use case. While theoretically there could be key collisions with specially crafted section/option names (e.g., section="foo_bar" + option="baz" producing the same key as section="foo" + option="bar_baz"), this is extremely unlikely given the controlled nature of WordPress option names.

Copy link

@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

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 82767f1 and 21cb62a.

📒 Files selected for processing (1)
  • dokan-wpml.php
🔇 Additional comments (3)
dokan-wpml.php (3)

52-57: LGTM! Cache property is appropriately scoped.

The static property is correctly used for in-memory caching across multiple method calls during a single request.


93-96: LGTM! Hook registration correctly uses only the needed parameter.

The cache clearing hooks are properly registered and only accept the $option parameter, which is all that's needed for cache invalidation.


1038-1056: LGTM! Caching implementation is well-structured.

The cache-check-compute-store pattern is correctly implemented, and the use of the null coalesce operator addresses previous feedback.

@rakib1904107
Copy link
Author

All problems are fixed. Please check.

@dev-shahed
Copy link
Member

Tested and found good, waiting for dev review done

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants