| @@ -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'; |
| @@ -659,9 +660,9 @@ | ||
| 659 | 660 | * probe recorded on save knows; until this it had no reader outside |
| 660 | 661 | * WP-CLI, so the panel kept saying "Redis ready" over a cache that |
| 661 | 662 | * stored nothing. (#398) |
| 662 | 663 | */ |
| 663 | - $detect = Object_Cache::detect(); | |
| 664 | + $detect = Object_Cache::detect( true ); | |
| 664 | 665 | $failure = self::live_write_failure(); |
| 665 | 666 | if ( null !== $failure ) { |
| 666 | 667 | $detect['write_probe'] = $failure; |
| 667 | 668 | } |
| @@ -748,12 +749,22 @@ | ||
| 748 | 749 | |
| 749 | 750 | public function rest_enable( \WP_REST_Request $request ) { |
| 750 | 751 | // Persist any settings sent with the enable call first, then act on them. |
| 751 | 752 | $body = $request->get_json_params(); |
| 753 | + // `takeover` is an action, not a setting: take it out before the body | |
| 754 | + // is saved as the settings row. Sent in the body rather than the query | |
| 755 | + // string because on plain permalinks the REST base already carries | |
| 756 | + // `?rest_route=`. (#686) | |
| 757 | + $takeover = is_array( $body ) && ! empty( $body['takeover'] ) | |
| 758 | + ? rest_sanitize_boolean( $body['takeover'] ) | |
| 759 | + : rest_sanitize_boolean( $request->get_param( 'takeover' ) ); | |
| 760 | + if ( is_array( $body ) ) { | |
| 761 | + unset( $body['takeover'] ); | |
| 762 | + } | |
| 752 | 763 | if ( is_array( $body ) && ! empty( $body ) ) { |
| 753 | 764 | \XSpeed\Settings_Manager::update( self::SLUG, $body ); |
| 754 | 765 | } |
| 755 | - $result = Object_Cache::enable( $this->get_settings() ); | |
| 766 | + $result = Object_Cache::enable( $this->get_settings(), array( 'takeover' => $takeover ) ); | |
| 756 | 767 | |
| 757 | 768 | if ( $result['ok'] && class_exists( '\\XSpeed\\Activity_Log' ) ) { |
| 758 | 769 | \XSpeed\Activity_Log::record( |
| 759 | 770 | 'object_cache_enabled', |
| @@ -764,9 +775,11 @@ | ||
| 764 | 775 | return rest_ensure_response( $result ); |
| 765 | 776 | } |
| 766 | 777 | |
| 767 | 778 | public function rest_disable( \WP_REST_Request $request ) { |
| 768 | - $result = Object_Cache::disable(); | |
| 779 | + $result = Object_Cache::disable( | |
| 780 | + array( 'restore' => rest_sanitize_boolean( $request->get_param( 'restore' ) ) ) | |
| 781 | + ); | |
| 769 | 782 | if ( $result['ok'] && class_exists( '\\XSpeed\\Activity_Log' ) ) { |
| 770 | 783 | \XSpeed\Activity_Log::record( |
| 771 | 784 | 'object_cache_disabled', |
| 772 | 785 | 'Object cache disabled.', |
| @@ -799,8 +812,20 @@ | ||
| 799 | 812 | 'type' => 'positional', |
| 800 | 813 | 'name' => 'value', |
| 801 | 814 | 'optional' => true, |
| 802 | 815 | ), |
| 816 | + array( | |
| 817 | + 'type' => 'flag', | |
| 818 | + 'name' => 'takeover', | |
| 819 | + '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).', | |
| 820 | + 'optional' => true, | |
| 821 | + ), | |
| 822 | + array( | |
| 823 | + 'type' => 'flag', | |
| 824 | + 'name' => 'restore', | |
| 825 | + 'description' => 'With disable: put back the plugin xSpeed switched from.', | |
| 826 | + 'optional' => true, | |
| 827 | + ), | |
| 803 | 828 | ), |
| 804 | 829 | ), |
| 805 | 830 | ); |
| 806 | 831 | } |
| @@ -956,13 +981,28 @@ | ||
| 956 | 981 | $t = Object_Cache::test_connection( $this->get_settings() ); |
| 957 | 982 | $t['ok'] ? \WP_CLI::success( $t['message'] ) : \WP_CLI::error( $t['message'] ); |
| 958 | 983 | return; |
| 959 | 984 | case 'enable': |
| 960 | - $r = Object_Cache::enable( $this->get_settings() ); | |
| 985 | + $r = Object_Cache::enable( | |
| 986 | + $this->get_settings(), | |
| 987 | + array( 'takeover' => ! empty( $assoc['takeover'] ) ) | |
| 988 | + ); | |
| 989 | + if ( ! $r['ok'] && ! empty( $r['needs_takeover'] ) && Object_Cache_Takeover::STRATEGY_REFUSE !== ( $r['owner']['strategy'] ?? '' ) ) { | |
| 990 | + // This handler also answers MCP (through Cli_Bridge), where | |
| 991 | + // the switch is an argument, not a flag. | |
| 992 | + \WP_CLI::error( $r['message'] . ' To switch, run again with --takeover (MCP: takeover: true).' ); | |
| 993 | + } | |
| 961 | 994 | $r['ok'] ? \WP_CLI::success( $r['message'] ) : \WP_CLI::error( $r['message'] ); |
| 962 | 995 | return; |
| 963 | 996 | case 'disable': |
| 964 | - $r = Object_Cache::disable(); | |
| 997 | + $r = Object_Cache::disable( array( 'restore' => ! empty( $assoc['restore'] ) ) ); | |
| 998 | + // Disabling worked; a restore that could not complete is a | |
| 999 | + // warning, not a failed command. | |
| 1000 | + if ( $r['ok'] && false === ( $r['restored'] ?? null ) ) { | |
| 1001 | + \WP_CLI::warning( $r['message'] ); | |
| 1002 | + \WP_CLI::success( 'Object cache disabled.' ); | |
| 1003 | + return; | |
| 1004 | + } | |
| 965 | 1005 | $r['ok'] ? \WP_CLI::success( $r['message'] ) : \WP_CLI::error( $r['message'] ); |
| 966 | 1006 | return; |
| 967 | 1007 | default: |
| 968 | 1008 | \WP_CLI::error( "Unknown action: $action" ); |