Skip to content

fix: store cache transient-version markers with an expiration#3266

Open
MdAsifHossainNadim wants to merge 5 commits into
developfrom
feature/clear-dokan-cache
Open

fix: store cache transient-version markers with an expiration#3266
MdAsifHossainNadim wants to merge 5 commits into
developfrom
feature/clear-dokan-cache

Conversation

@MdAsifHossainNadim

@MdAsifHossainNadim MdAsifHossainNadim commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Cache group transient-version markers are written via set_transient() with no expiration, so WordPress stores them with autoload = yes and never clears them. On sites without a persistent object cache this bloats the autoloaded options (a client reported 5,000+ autoloaded rows, mostly _transient_dokan_cache_*-transient-version).

This adds a filterable expiration to the marker so WordPress stores it autoload = no (with a _transient_timeout_ companion) and garbage-collects it like any transient.

Related PR: https://github.com/getdokan/dokan-pro/pull/5765
Closes: https://github.com/getdokan/plugin-internal-tasks/issues/1965

Change

includes/Traits/TransientCache.phpget_transient_version() now sets the marker with:

apply_filters( 'dokan_cache_transient_version_expiration', MONTH_IN_SECONDS, $group )

The default TTL (1 month) comfortably outlives the longest-lived data transient (≤ 1 week), so cache groups are not invalidated prematurely.

How to test

  1. On a site without a persistent object cache, trigger any Dokan caching (load the vendor dashboard / a report).
  2. Inspect a marker row:
    SELECT option_name, autoload FROM wp_options
    WHERE option_name LIKE '_transient_dokan_cache_%-transient-version' LIMIT 5;
    • Before: autoload = yes, no _transient_timeout_ companion.
    • After: autoload = no (or off) with a matching _transient_timeout_… row ~30 days out.
  3. Confirm cached features (reports, product counts) still work.

Verified

Local site, forcing the DB transient path: marker stored autoload = off with a ~2592000s (30-day) timeout; cache read-back unaffected.


Ref: getdokan/plugin-internal-tasks#1965 · Companion Pro PR adds a Clear Dokan Caches admin tool.

🤖 Generated with Claude Code

Summary by CodeRabbit

Summary

  • New Features
    • Added a new Dashboard Tools page with built-in actions to regenerate required Dokan pages and clear Dokan caches.
    • Allows additional Tools sections to be injected into the page for extended functionality.
  • Chores / Improvements
    • Cache version markers now expire automatically (with configurable lifetime) to reduce stale-cache risk and improve cleanup.
  • UI Compatibility
    • Kept the legacy Tools submenu entry available alongside the new Tools page.

Cache group version markers were written via set_transient() without an
expiration, so WordPress stores them with autoload=yes and never clears
them — bloating autoloaded options on sites without a persistent object
cache (5,000+ rows reported).

Pass a filterable expiration (dokan_cache_transient_version_expiration,
default MONTH_IN_SECONDS) so WordPress stores the marker autoload=no with a
timeout and garbage-collects it. The default TTL outlives the longest-lived
data transient to avoid premature group invalidation.

Ref: getdokan/plugin-internal-tasks#1965

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a configurable expiration for transient cache version markers and adds a new Admin Tools dashboard page with functionality to manage default Dokan pages and clear caches. The Tools page is available in both React (new) and Vue (legacy) with extensible sections for Pro features. Backend logic is centralized in a ToolsActions service exposed via AJAX and REST endpoints, with permission gating and proper error handling.

Changes

Transient cache optimization

Layer / File(s) Summary
Configurable transient version expiration
includes/Traits/TransientCache.php
The get_transient_version() method adds a dokan_cache_transient_version_expiration filter (defaulting to MONTH_IN_SECONDS) and passes the resulting TTL to set_transient() so WordPress can garbage-collect the marker rather than storing it indefinitely.

Admin Tools feature

Layer / File(s) Summary
ToolsActions service and core logic
includes/Admin/Tools/ToolsActions.php
Core ToolsActions class provides create_default_pages() (creates missing Dokan pages, adopts existing ones by slug, sets rewrite rules), check_all_dokan_pages_exists() (returns flag from option), and clear_dokan_caches() (deletes transients, flushes object cache, fires action).
AJAX and REST endpoint handlers
includes/Ajax.php, includes/REST/ToolsController.php, includes/REST/Manager.php
AJAX handlers in Ajax and REST routes in ToolsController expose the three ToolsActions methods with manage_woocommerce capability checks. REST Manager registers the controller so routes are auto-loaded.
Admin dashboard page and menu integration
includes/Admin/Dashboard/Pages/Tools.php, includes/Admin/Menu.php, includes/DependencyManagement/Providers/AdminDashboardServiceProvider.php
New Tools dashboard page class with localized metadata and menu position 98, registered via DI provider. Legacy Vue tools submenu entry added to Menu alongside the new React tools item.
Asset and routing configuration
includes/Assets.php, src/admin/router/index.js, src/admin/dashboard/components/Dashboard.tsx
Vue and React admin routes registered: Vue /tools route points to Tools.vue, React /tools route renders <Tools /> in Dashboard.
Reusable ToolsSection UI component
src/components/ToolsSection.tsx, src/components/index.tsx
New ToolsSection React component renders card-row UI with optional progress bar, configurable button state (loading/disabled), and title/description; exported from components barrel for reuse.
React Tools page and section types
src/admin/dashboard/components/Tools/types.ts, src/admin/dashboard/components/Tools/HeaderImage.tsx, src/admin/dashboard/components/Tools/Tools.tsx
TypeScript types for Tools props and tool descriptors; HeaderImage component renders static SVG; Tools container defines base sections (InstallationGuide, ClearDokanCaches), applies extension filter, and renders card layout with toaster.
React Tools section implementations
src/admin/dashboard/components/Tools/sections/InstallationGuide.tsx, src/admin/dashboard/components/Tools/sections/ClearDokanCaches.tsx
InstallationGuide calls /dokan/v1/admin/tools/create-pages on click, pre-checks page existence to disable button when done; ClearDokanCaches calls /dokan/v1/admin/tools/clear-caches with loading/error toast feedback.
Vue Tools page implementation
src/admin/pages/Tools.vue
Vue component renders sections from computed list (free + filtered injected), supports built-in actions (create_pages, clear_dokan_caches) via AJAX with progress/loading UI, and forwards unknown actions to dokan_admin_tools_do_action hook.

Sequence Diagram

sequenceDiagram
  participant Admin as Admin User
  participant UI as React/Vue UI
  participant REST as REST/AJAX
  participant ToolsActions as ToolsActions Service
  participant DB as WordPress DB
  participant Cache as WP Object Cache

  Admin->>UI: Click "Create Pages" or "Clear Caches"
  UI->>REST: POST /dokan/v1/admin/tools/create-pages or clear-caches
  REST->>ToolsActions: call create_default_pages() or clear_dokan_caches()
  
  alt Create Default Pages
    ToolsActions->>DB: Query wp_posts by page slug
    DB-->>ToolsActions: Return existing pages
    ToolsActions->>DB: Insert missing pages
    ToolsActions->>DB: Update dokan_pages option
    ToolsActions->>DB: Flush rewrite rules
    DB-->>ToolsActions: Success
  else Clear Caches
    ToolsActions->>DB: DELETE FROM wp_options WHERE option_name LIKE '_transient_dokan_%'
    ToolsActions->>Cache: wp_cache_flush()
    Cache-->>ToolsActions: Cache cleared
    ToolsActions->>REST: Fire dokan_caches_cleared action
  end

  ToolsActions-->>REST: Return { success, message }
  REST-->>UI: JSON response
  UI->>Admin: Show success/error toast, update button state
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • getdokan/dokan#3251: Adds Playwright E2E coverage for the new Admin Tools page, including REST endpoint interactions for create-pages and clear-caches features introduced in this PR.

Suggested labels

Needs: Dev Review

Suggested reviewers

  • mrabbani

Poem

🐰 A toolkit appears in the admin's domain,
With pages to birth and caches to drain—
React and Vue dance, Pro can extend,
Transients now expire, and bloat finds its end! 🎉

🚥 Pre-merge checks | ✅ 1 | ❌ 4

❌ Failed checks (2 warnings, 2 inconclusive)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title describes only a small transient-cache fix, but the changeset includes extensive admin tooling infrastructure (Tools page, REST controller, components, Vue integration) unrelated to the cache marker expiration. Update title to reflect the full scope, e.g., 'feat: add admin Tools page with cache management and page creation actions' or split into multiple focused PRs.
Out of Scope Changes check ⚠️ Warning The changeset includes substantial out-of-scope additions beyond issue #1965: a complete admin Tools page infrastructure (React/TSX components, Vue components, menu entries, service classes) and page creation/management actions unrelated to the transient-marker fix or cache clearing. Clarify whether admin Tools page and page-creation infrastructure are part of issue #1965 scope; if not, extract into separate PRs or update the issue to document these as explicit requirements.
Description check ❓ Inconclusive The description focuses on the transient-version marker fix and references a companion Pro PR for 'Clear Dokan Caches', but does not document the extensive React/Vue components, REST controller, admin menu changes, or new admin Tools page infrastructure also present in this changeset. Clarify whether the admin tooling is final Lite functionality or placeholder scaffolding; expand description to document all substantial changes including the new admin Tools page, components, and REST endpoints.
Linked Issues check ❓ Inconclusive The PR implements objectives 1, 3, and 4 from issue #1965 (transient-version expiration, Tools page, REST endpoints, admin UI), but does not explicitly document or complete objective 2 (cleanup/migration commands like WP CLI or SQL), and scope extends beyond the stated objectives into Lite admin tooling. Clarify whether cleanup commands are deferred to a follow-up PR; confirm that new admin tooling (Tools page, page creation actions) aligns with issue scope or belongs in a separate issue.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/clear-dokan-cache

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.

@MdAsifHossainNadim MdAsifHossainNadim marked this pull request as ready for review June 11, 2026 12:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@includes/Traits/TransientCache.php`:
- Line 51: Replace the placeholder docblock tag "`@since` DOKAN_SINCE" in the
TransientCache trait with the concrete release version string (e.g., "`@since`
3.4.0" or the appropriate current release) so the method/hook documentation is
accurate; locate the docblock inside the includes/Traits/TransientCache.php file
and update the `@since` annotation accordingly for the associated method/hook.
- Around line 56-58: The filtered expiration value from
apply_filters('dokan_cache_transient_version_expiration', MONTH_IN_SECONDS,
$group) must be validated before calling set_transient to avoid non-expiring
markers; update the TransientCache logic to coerce and guard $expiration (ensure
it is a positive integer greater than zero, e.g. (int)$expiration and if <= 0
fallback to MONTH_IN_SECONDS) and then pass the validated value into
set_transient($transient_name, $transient_value, $expiration).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d2a46952-3382-4c10-b5ad-f512f99ed9f4

📥 Commits

Reviewing files that changed from the base of the PR and between 782cd09 and c282683.

📒 Files selected for processing (1)
  • includes/Traits/TransientCache.php

Comment thread includes/Traits/TransientCache.php
Comment thread includes/Traits/TransientCache.php

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@includes/Admin/Tools/ToolsActions.php`:
- Around line 97-99: The `update_option( 'dokan_pages_created', 1 )` call is
executed unconditionally regardless of whether the page creation operations
succeeded or failed. Add conditional logic to only set `dokan_pages_created` to
1 after verifying that all required pages were actually created successfully.
Check the return values or results from the preceding page creation operations
(before the `update_option( 'dokan_pages', $dokan_pages )` call) and only
proceed with marking `dokan_pages_created` as complete if all operations were
successful, otherwise leave the flag unset or set it to 0 to indicate incomplete
setup.
- Around line 142-154: Replace the global wp_cache_flush() call in the
ToolsActions.php file with targeted cache deletion that only removes
Dokan-specific cache keys. Instead of clearing all WordPress caches, use
wp_cache_delete() to selectively clear only the Dokan-related cache entries that
need to be invalidated. This prevents clearing unrelated site caches from other
plugins and services. Identify all critical Dokan cache keys (such as those for
products, settings, vendor data, etc.) and call wp_cache_delete() for each of
them individually.
- Around line 113-116: The method check_all_dokan_pages_exists() is returning
string values '1' and '0' instead of proper booleans, which causes the frontend
contract to break because in JavaScript '0' is truthy. Additionally, the method
only checks a stale dokan_pages_created option rather than verifying actual page
state. Modify the method to return real boolean values (true and false) instead
of strings, and update the logic to verify the actual existence of dokan pages
by querying current page records instead of only relying on the potentially
outdated get_option call.

In `@includes/Ajax.php`:
- Around line 73-80: The create_pages() method is missing nonce verification
which is required to prevent CSRF attacks. Even though the method has a
capability check with current_user_can(), nonce validation is necessary for
state-changing operations. Add nonce verification at the beginning of the
create_pages() method using wp_verify_nonce() to check for a nonce parameter in
the request, and return an error response if verification fails. Follow the
pattern used in the clear_caches() method (referenced at Lines 108-110) which
already implements nonce validation correctly.

In `@src/admin/dashboard/components/Tools/HeaderImage.tsx`:
- Line 1: The HeaderImage function parameter has implicit typing which violates
strict TypeScript mode. Define an explicit props interface or type for the
function parameters. Create a type that specifies the structure of the props
object, explicitly declaring that className is a string type with a default
value of an empty string. Apply this type annotation to the destructured
parameter in the HeaderImage function signature to ensure all component props
are strictly typed.

In `@src/admin/dashboard/components/Tools/sections/InstallationGuide.tsx`:
- Around line 45-54: The useEffect hook that calls apiFetch for the
'/dokan/v1/admin/tools/check-all-dokan-pages-exists' endpoint has a .then
handler but is missing a .catch handler, which can cause unhandled promise
rejections if the request fails. Add a .catch block after the .then to handle
rejection cases appropriately, such as logging any errors that occur during the
API call and optionally setting a fallback state to ensure the component behaves
predictably regardless of whether the request succeeds or fails.

In `@src/admin/pages/Tools.vue`:
- Around line 103-137: The `createPages()` and `checkAllPages()` methods send
AJAX requests without CSRF nonce protection, making them vulnerable to CSRF
attacks. Additionally, `createPages()` only clears the loading flag on success,
which locks the UI if the request fails. Fix this by adding nonce parameters to
both jQuery.post calls (the nonce should be available from the dokan object) and
ensure the loading flag in `createPages()` is cleared in both success and error
scenarios by using error handlers or wrapping the callback logic to guarantee
cleanup on all outcomes.

In `@src/components/ToolsSection.tsx`:
- Line 62: The className string in ToolsSection.tsx contains Tailwind CSS
important modifiers using the legacy prefix syntax (exclamation mark before the
utility class). Update all important modifiers in the className from prefix
placement (like !h-[28px]) to the Tailwind v4 recommended suffix placement
(h-[28px]!) by moving the exclamation mark to the end of each utility class.
This affects all four utility classes in the style definition: h-[28px],
font-[500], text-[12px], and leading-[16px].
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a44b1dea-fc10-4c7d-a3a0-d475e30bafd5

📥 Commits

Reviewing files that changed from the base of the PR and between c282683 and 5be325b.

📒 Files selected for processing (18)
  • includes/Admin/Dashboard/Pages/Tools.php
  • includes/Admin/Menu.php
  • includes/Admin/Tools/ToolsActions.php
  • includes/Ajax.php
  • includes/Assets.php
  • includes/DependencyManagement/Providers/AdminDashboardServiceProvider.php
  • includes/REST/Manager.php
  • includes/REST/ToolsController.php
  • src/admin/dashboard/components/Dashboard.tsx
  • src/admin/dashboard/components/Tools/HeaderImage.tsx
  • src/admin/dashboard/components/Tools/Tools.tsx
  • src/admin/dashboard/components/Tools/sections/ClearDokanCaches.tsx
  • src/admin/dashboard/components/Tools/sections/InstallationGuide.tsx
  • src/admin/dashboard/components/Tools/types.ts
  • src/admin/pages/Tools.vue
  • src/admin/router/index.js
  • src/components/ToolsSection.tsx
  • src/components/index.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/components/index.tsx

Comment thread includes/Admin/Tools/ToolsActions.php
Comment thread includes/Admin/Tools/ToolsActions.php
Comment on lines +142 to +154
wp_cache_flush();

/**
* Fires after all Dokan caches have been cleared from the admin Tools page.
*
* @since DOKAN_SINCE
*/
do_action( 'dokan_caches_cleared' );

return [
'process' => 'success',
'message' => __( 'Dokan caches have been cleared successfully.', 'dokan-lite' ),
];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Avoid full object-cache flush for a Dokan-scoped action.

At Line 142, wp_cache_flush() clears all groups, not just Dokan keys. This can evict unrelated site caches and cause broad performance degradation after a single Tools click.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@includes/Admin/Tools/ToolsActions.php` around lines 142 - 154, Replace the
global wp_cache_flush() call in the ToolsActions.php file with targeted cache
deletion that only removes Dokan-specific cache keys. Instead of clearing all
WordPress caches, use wp_cache_delete() to selectively clear only the
Dokan-related cache entries that need to be invalidated. This prevents clearing
unrelated site caches from other plugins and services. Identify all critical
Dokan cache keys (such as those for products, settings, vendor data, etc.) and
call wp_cache_delete() for each of them individually.

Comment thread includes/Ajax.php
Comment thread src/admin/dashboard/components/Tools/HeaderImage.tsx
Comment thread src/admin/dashboard/components/Tools/sections/InstallationGuide.tsx
Comment thread src/admin/pages/Tools.vue
Comment thread src/components/ToolsSection.tsx
@MdAsifHossainNadim MdAsifHossainNadim self-assigned this Jun 18, 2026
@MdAsifHossainNadim MdAsifHossainNadim added Needs: Testing This requires further testing Needs: Dev Review It requires a developer review and approval labels Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Dependency With Pro Needs: Dev Review It requires a developer review and approval Needs: Testing This requires further testing QA In Progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants