PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.3.6
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.3.6
1.3.6 1.3.5 1.3.4 1.3.3 1.3.2 1.3.1 1.3.0 1.2.4 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 All 32 releases
← All changes | includes/class-rest-api.php +49 -12 1.1.3 → 1.3.6 View file →
@@ -425,8 +425,13 @@
425 425 'nginx_snippet' => Gzip::nginx_snippet(),
426 426 ),
427 427 'rewrite_probe' => $rewrite_probe,
428 428 'nginx_server_block' => Cache::full_nginx_server_block(),
429 + // What enabling the page cache would do to
430 + // wp-content/advanced-cache.php. The dashboard discloses the
431 + // replacement BEFORE the write when a leftover drop-in is
432 + // already there; see Page_Cache_Detector::dropin_disclosure().
433 + 'dropin' => Page_Cache_Detector::dropin_disclosure(),
429 434 // Separate Mobile Cache visibility (FBS-83145). `blocking` is
430 435 // true when mobile_separate is what's keeping the device-blind
431 436 // static fast path from installing on a rewrite-capable server;
432 437 // `needs_review` is true when a migration turned it on for us and
@@ -433,9 +438,16 @@
433 438 // the user hasn't confirmed they actually need it. The dashboard
434 439 // renders a callout (+ "Check now" equality probe) from these.
435 440 'mobile_separate' => array(
436 441 'enabled' => ! empty( Settings::get()['cache_enabled'] ) ? (bool) ( Settings_Manager::get( 'cache' )['mobile_separate'] ?? false ) : false,
437 - 'blocking' => $rewrite_capable && 'mobile_separate' === Cache::static_rewrite_block_reason(),
442 + // Gated to servers that HAVE a static fast path — see the
443 + // matching comment in Admin::bootstrap_payload(): on IIS /
444 + // unknown, block_reason still falls through to
445 + // mobile_separate and reporting it as "blocking" would nag
446 + // about a rewrite that does not exist there (#108).
447 + // LiteSpeed joined the capable set with the opt-in (#509).
448 + 'blocking' => ( $rewrite_capable || Server::LITESPEED === $server_type )
449 + && 'mobile_separate' === Cache::static_rewrite_block_reason(),
438 450 'needs_review' => Cache::mobile_separate_needs_review(),
439 451 ),
440 452 )
441 453 );
@@ -459,10 +471,19 @@
459 471 return rest_ensure_response( $updated );
460 472 }
461 473
462 474 public function purge() {
463 - Cache::purge_all( __( 'dashboard', 'xspeed' ) );
464 - return rest_ensure_response( array( 'stats' => Cache::get_stats() ) );
475 + // The same core function `wp xspeed purge` runs, so the dashboard
476 + // button and the CLI cannot clear different sets of stores — and the
477 + // per-store report is available here for the UI to surface a store
478 + // that was skipped or refused rather than flashing "cache cleared".
479 + $report = Purge_Runner::run( array( 'all' ), __( 'dashboard', 'xspeed' ) );
480 + return rest_ensure_response(
481 + array(
482 + 'stats' => Cache::get_stats(),
483 + 'report' => $report,
484 + )
485 + );
465 486 }
466 487
467 488 /**
468 489 * The "Cached Pages" drill-down: which pages are cached and how old they
@@ -504,17 +525,27 @@
504 525 * Returns the same shape the dashboard bootstrap uses, so the caller can
505 526 * swap it straight into state without a second round trip. (FBS-84012)
506 527 */
507 528 public function recheck_rewrite() {
508 - $probe = Cache::recheck_static_rewrite();
529 + $raw = Cache::recheck_static_rewrite();
509 530 $server_type = Server::detect();
510 531
532 + // Qualify the raw probe against known config refusals. The probe
533 + // fetches its own file from the static tree, which succeeds even when
534 + // no real page is served that way — so an unqualified `active` told
535 + // clients the static path was engaged on sites where it demonstrably
536 + // wasn't. `block_reason` is exposed so a client can act on the
537 + // specific cause rather than re-deriving it. See
538 + // Cache::qualify_rewrite_probe().
539 + $probe = Cache::qualify_rewrite_probe( $raw );
540 +
511 541 return rest_ensure_response(
512 542 array(
513 - 'active' => (bool) ( $probe['active'] ?? false ),
514 - 'pending' => (bool) ( $probe['pending'] ?? false ),
515 - 'inconclusive' => (bool) ( $probe['inconclusive'] ?? false ),
516 - 'reason' => (string) ( $probe['reason'] ?? '' ),
543 + 'active' => $probe['active'],
544 + 'pending' => (bool) ( $raw['pending'] ?? false ),
545 + 'inconclusive' => $probe['inconclusive'],
546 + 'reason' => $probe['reason'],
547 + 'block_reason' => $probe['block_reason'],
517 548 'server_type' => $server_type,
518 549 'snippet' => Cache::nginx_snippet(),
519 550 'topology' => Server::rewrite_topology(),
520 551 'behind_proxy' => Server::is_behind_proxy(),
@@ -530,9 +561,9 @@
530 561 // permission_callback above already enforced current_user_can(
531 562 // 'manage_options' ); the REST nonce is verified by core via the
532 563 // X-WP-Nonce header.
533 564 $state = Cache::toggle( $enabled );
534 - $updated = Settings::update( array( 'cache_enabled' => $state['enabled'] ) );
565 + $updated = Settings::get();
535 566
536 567 // Recompute the unified nginx block AFTER cache_enabled is persisted.
537 568 // Cache::toggle() computes it inline, but cache_enabled isn't written
538 569 // until the Settings::update() above — so the block inside $state
@@ -542,11 +573,17 @@
542 573 $state['nginx_server_block'] = Cache::full_nginx_server_block();
543 574
544 575 return rest_ensure_response(
545 576 array(
546 - 'enabled' => $updated['cache_enabled'],
547 - 'stats' => Cache::get_stats(),
548 - 'install_state' => $state,
577 + 'enabled' => $updated['cache_enabled'],
578 + // Surfaced at the top level so the dashboard can explain a
579 + // refusal rather than silently snapping the toggle back:
580 + // Cache::toggle() writes nothing when another plugin owns the
581 + // drop-in or WP_CACHE is in a shape we must not rewrite.
582 + 'blocked' => ! empty( $state['blocked'] ),
583 + 'blocked_reason' => $state['blocked_reason'] ?? null,
584 + 'stats' => Cache::get_stats(),
585 + 'install_state' => $state,
549 586 )
550 587 );
551 588 }
552 589 }