PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.4.1
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.4.1
1.4.1 1.4.0 1.3.7 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 All 35 releases
← All changes | includes/class-module.php +56 -0 1.3.4 → 1.4.1 View file →
@@ -309,8 +309,31 @@
309 309 array( 'status' => 403 )
310 310 );
311 311 }
312 312
313 + /*
314 + * A module another module has taken over from.
315 + *
316 + * Distinct from the licence gate above: that one says "you have not
317 + * paid for this", and this one says "something else on this site is
318 + * already doing it, and running both would be worse than running
319 + * either". The Cloudflare module behind the Cloudflare Enterprise
320 + * edge is the case it was written for — two proxy layers, each with
321 + * its own copy, and purges that reach one of them.
322 + *
323 + * Only a write that turns the module ON is refused. Turning it off,
324 + * or changing anything else, is exactly what somebody resolving the
325 + * conflict needs to be able to do.
326 + */
327 + $blocked = $this->blocked_by();
328 + if ( null !== $blocked && ! empty( $params['enabled'] ) ) {
329 + return new \WP_Error(
330 + 'xspeed_module_blocked',
331 + $blocked,
332 + array( 'status' => 409 )
333 + );
334 + }
335 +
313 336 // A field pinned by a wp-config.php constant cannot be written. Saying
314 337 // so beats a 200 over a write that silently did nothing -- and naming
315 338 // the constant tells the caller where to go and change it. (#398)
316 339 $locked = Settings_Manager::locked_in_input( static::SLUG, is_array( $params ) ? $params : array() );
@@ -336,8 +359,29 @@
336 359 return rest_ensure_response( $this->update_settings( $params ) );
337 360 }
338 361
339 362 /**
363 + * Why this module may not be switched on right now, or null.
364 + *
365 + * A seam for one module to stand another down. Free answers null for
366 + * everything and never blocks anything itself — it has no opinion about
367 + * which modules conflict, and an add-on that knows the answer says so.
368 + *
369 + * The reason is shown to the customer, so it says what to do rather than
370 + * naming an internal state.
371 + */
372 + final public function blocked_by(): ?string {
373 + /**
374 + * Filter: xspeed_module_blocked_by
375 + *
376 + * @param string|null $reason Why this module cannot be enabled.
377 + * @param string $slug The module being asked about.
378 + */
379 + $reason = apply_filters( 'xspeed_module_blocked_by', null, static::SLUG );
380 + return is_string( $reason ) && '' !== $reason ? $reason : null;
381 + }
382 +
383 + /**
340 384 * Is this a Pro module whose settings are locked for want of a licence?
341 385 *
342 386 * Shared by the REST handler and the write guard so the two can never
343 387 * disagree about what is locked.
@@ -500,8 +544,20 @@
500 544 return null;
501 545 }
502 546
503 547 return $this->bool_flag_reason();
548 + }
549 +
550 + /**
551 + * What the customer still needs before this module can work, when that is
552 + * something to buy or activate, in a few words ("Add-on needed").
553 + *
554 + * The dashboard shows it in the page header in place of the On/Off pill,
555 + * because "Off" on a module nobody can switch on yet reads as a setting
556 + * left off. Null, the default, keeps the pill.
557 + */
558 + public function status_label(): ?string {
559 + return null;
504 560 }
505 561
506 562 /**
507 563 * The reason text for a module whose "on" is "any of my flags is on".