PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.4.2
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.4.2
1.4.2 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 All 36 releases
← All changes | includes/modules/ObjectCache/ObjectCacheModule.php +68 -13 1.3.7 → 1.4.2 View file →
@@ -19,8 +19,9 @@
19 19 defined( 'ABSPATH' ) || exit;
20 20
21 21 use XSpeed\Module;
22 22 use XSpeed\Object_Cache;
23 +use XSpeed\Object_Cache_Takeover;
23 24
24 25 final class ObjectCacheModule extends Module {
25 26
26 27 public const SLUG = 'object-cache';
@@ -62,14 +63,27 @@
62 63 'label' => __( 'Cache server', 'xspeed' ),
63 64 'description' => __( 'The cache server your host provides. Ask your host if you are not sure.', 'xspeed' ),
64 65 ),
65 66 'redis_host' => array(
66 - 'type' => 'string',
67 - 'default' => '127.0.0.1',
68 - 'constants' => array( 'XSPEED_OC_HOST', 'WP_REDIS_HOST' ),
69 - 'label' => __( 'Redis host', 'xspeed' ),
70 - 'description' => __( 'Address of the Redis server. Use 127.0.0.1 when Redis runs on the same server as your site.', 'xspeed' ),
71 - 'dependsOn' => array( 'field' => 'backend', 'value' => 'redis' ),
67 + 'type' => 'string',
68 + 'default' => '127.0.0.1',
69 + // WP_REDIS_PATH is Redis Object Cache's name for a unix socket,
70 + // and it only means one when WP_REDIS_SCHEME says `unix` -- the
71 + // same pair that plugin reads. It ranks above WP_REDIS_HOST
72 + // because that plugin ignores the host once the scheme is unix,
73 + // and hosts that write the pair often leave a stale host
74 + // beside it. (#566)
75 + 'constants' => array( 'XSPEED_OC_HOST', 'WP_REDIS_PATH', 'WP_REDIS_HOST' ),
76 + 'constants_when' => array(
77 + 'WP_REDIS_PATH' => array(
78 + 'constant' => 'WP_REDIS_SCHEME',
79 + 'is' => 'unix',
80 + 'case_insensitive' => true,
81 + ),
82 + ),
83 + 'label' => __( 'Redis host', 'xspeed' ),
84 + 'description' => __( 'Address of the Redis server, or the path to its socket file if your host gave you one (for example /run/redis/redis.sock). Use 127.0.0.1 when Redis runs on the same server as your site.', 'xspeed' ),
85 + 'dependsOn' => array( 'field' => 'backend', 'value' => 'redis' ),
72 86 ),
73 87 'redis_port' => array(
74 88 'type' => 'int',
75 89 'default' => 6379,
@@ -76,9 +90,9 @@
76 90 'min' => 1,
77 91 'max' => 65535,
78 92 'constants' => array( 'XSPEED_OC_PORT', 'WP_REDIS_PORT' ),
79 93 'label' => __( 'Redis port', 'xspeed' ),
80 - 'description' => __( 'The default Redis port is 6379.', 'xspeed' ),
94 + 'description' => __( 'The default Redis port is 6379. Not used when the host is a socket path.', 'xspeed' ),
81 95 'advanced' => true,
82 96 'dependsOn' => array( 'field' => 'backend', 'value' => 'redis' ),
83 97 ),
84 98 'redis_user' => array(
@@ -87,9 +101,11 @@
87 101 // WP_REDIS_PASSWORD trails the dedicated names because in its
88 102 // array form -- how xCloud and Cloudways hand out ACL
89 103 // credentials -- it carries the username too. It is pair-only:
90 104 // as a plain string it is a password, never a username.
91 - 'constants' => array( 'XSPEED_OC_USER', 'WP_REDIS_USER', 'WP_REDIS_PASSWORD' ),
105 + // WP_REDIS_USERNAME is Redis Object Cache's name for the same
106 + // thing, and that plugin lets it win over the array form. (#566)
107 + 'constants' => array( 'XSPEED_OC_USER', 'WP_REDIS_USERNAME', 'WP_REDIS_USER', 'WP_REDIS_PASSWORD' ),
92 108 'constants_pair_only' => array( 'WP_REDIS_PASSWORD' ),
93 109 'constant_pair' => 'user',
94 110 'label' => __( 'Redis username', 'xspeed' ),
95 111 'description' => __( 'Only needed if your host gave you a Redis username along with the password. Leave blank otherwise.', 'xspeed' ),
@@ -659,9 +675,9 @@
659 675 * probe recorded on save knows; until this it had no reader outside
660 676 * WP-CLI, so the panel kept saying "Redis ready" over a cache that
661 677 * stored nothing. (#398)
662 678 */
663 - $detect = Object_Cache::detect();
679 + $detect = Object_Cache::detect( true );
664 680 $failure = self::live_write_failure();
665 681 if ( null !== $failure ) {
666 682 $detect['write_probe'] = $failure;
667 683 }
@@ -748,12 +764,22 @@
748 764
749 765 public function rest_enable( \WP_REST_Request $request ) {
750 766 // Persist any settings sent with the enable call first, then act on them.
751 767 $body = $request->get_json_params();
768 + // `takeover` is an action, not a setting: take it out before the body
769 + // is saved as the settings row. Sent in the body rather than the query
770 + // string because on plain permalinks the REST base already carries
771 + // `?rest_route=`. (#686)
772 + $takeover = is_array( $body ) && ! empty( $body['takeover'] )
773 + ? rest_sanitize_boolean( $body['takeover'] )
774 + : rest_sanitize_boolean( $request->get_param( 'takeover' ) );
775 + if ( is_array( $body ) ) {
776 + unset( $body['takeover'] );
777 + }
752 778 if ( is_array( $body ) && ! empty( $body ) ) {
753 779 \XSpeed\Settings_Manager::update( self::SLUG, $body );
754 780 }
755 - $result = Object_Cache::enable( $this->get_settings() );
781 + $result = Object_Cache::enable( $this->get_settings(), array( 'takeover' => $takeover ) );
756 782
757 783 if ( $result['ok'] && class_exists( '\\XSpeed\\Activity_Log' ) ) {
758 784 \XSpeed\Activity_Log::record(
759 785 'object_cache_enabled',
@@ -764,9 +790,11 @@
764 790 return rest_ensure_response( $result );
765 791 }
766 792
767 793 public function rest_disable( \WP_REST_Request $request ) {
768 - $result = Object_Cache::disable();
794 + $result = Object_Cache::disable(
795 + array( 'restore' => rest_sanitize_boolean( $request->get_param( 'restore' ) ) )
796 + );
769 797 if ( $result['ok'] && class_exists( '\\XSpeed\\Activity_Log' ) ) {
770 798 \XSpeed\Activity_Log::record(
771 799 'object_cache_disabled',
772 800 'Object cache disabled.',
@@ -799,8 +827,20 @@
799 827 'type' => 'positional',
800 828 'name' => 'value',
801 829 'optional' => true,
802 830 ),
831 + array(
832 + 'type' => 'flag',
833 + 'name' => 'takeover',
834 + 'description' => 'With enable: switch from the plugin that owns object-cache.php (backs it up, turns that plugin off, installs xSpeed, undoes everything on failure).',
835 + 'optional' => true,
836 + ),
837 + array(
838 + 'type' => 'flag',
839 + 'name' => 'restore',
840 + 'description' => 'With disable: put back the plugin xSpeed switched from.',
841 + 'optional' => true,
842 + ),
803 843 ),
804 844 ),
805 845 );
806 846 }
@@ -956,13 +996,28 @@
956 996 $t = Object_Cache::test_connection( $this->get_settings() );
957 997 $t['ok'] ? \WP_CLI::success( $t['message'] ) : \WP_CLI::error( $t['message'] );
958 998 return;
959 999 case 'enable':
960 - $r = Object_Cache::enable( $this->get_settings() );
1000 + $r = Object_Cache::enable(
1001 + $this->get_settings(),
1002 + array( 'takeover' => ! empty( $assoc['takeover'] ) )
1003 + );
1004 + if ( ! $r['ok'] && ! empty( $r['needs_takeover'] ) && Object_Cache_Takeover::STRATEGY_REFUSE !== ( $r['owner']['strategy'] ?? '' ) ) {
1005 + // This handler also answers MCP (through Cli_Bridge), where
1006 + // the switch is an argument, not a flag.
1007 + \WP_CLI::error( $r['message'] . ' To switch, run again with --takeover (MCP: takeover: true).' );
1008 + }
961 1009 $r['ok'] ? \WP_CLI::success( $r['message'] ) : \WP_CLI::error( $r['message'] );
962 1010 return;
963 1011 case 'disable':
964 - $r = Object_Cache::disable();
1012 + $r = Object_Cache::disable( array( 'restore' => ! empty( $assoc['restore'] ) ) );
1013 + // Disabling worked; a restore that could not complete is a
1014 + // warning, not a failed command.
1015 + if ( $r['ok'] && false === ( $r['restored'] ?? null ) ) {
1016 + \WP_CLI::warning( $r['message'] );
1017 + \WP_CLI::success( 'Object cache disabled.' );
1018 + return;
1019 + }
965 1020 $r['ok'] ? \WP_CLI::success( $r['message'] ) : \WP_CLI::error( $r['message'] );
966 1021 return;
967 1022 default:
968 1023 \WP_CLI::error( "Unknown action: $action" );