Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
56.52% covered (warning)
56.52%
52 / 92
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
CacheController
56.52% covered (warning)
56.52%
52 / 92
25.00% covered (danger)
25.00%
1 / 4
44.63
0.00% covered (danger)
0.00%
0 / 1
 register_routes
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
1
 get_settings
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 update_settings
53.45% covered (warning)
53.45%
31 / 58
0.00% covered (danger)
0.00%
0 / 1
37.70
 purge_all
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace NewfoldLabs\WP\Module\Performance\RestApi;
4
5use NewfoldLabs\WP\Module\Performance\Permissions;
6use NewfoldLabs\WP\Module\Performance\Cache\CacheExclusion;
7use NewfoldLabs\WP\Module\Performance\Cache\CacheManager;
8use NewfoldLabs\WP\Module\Performance\Cache\CachePurgingService;
9use NewfoldLabs\WP\Module\Performance\Cache\Types\ObjectCache;
10
11use function NewfoldLabs\WP\ModuleLoader\container;
12use function NewfoldLabs\WP\Module\Performance\get_cache_level;
13use function NewfoldLabs\WP\Module\Performance\get_cache_exclusion;
14
15/**
16 * Class CacheExclusionController
17 */
18class CacheController {
19    /**
20     * REST namespace
21     *
22     * @var string
23     */
24    protected $namespace = 'newfold-performance/v1';
25
26    /**
27     * REST base
28     *
29     * @var string
30     */
31    protected $rest_base = '/cache';
32
33    /**
34     * Registers rest routes for PluginsController class.
35     *
36     * @return void
37     */
38    public function register_routes() {
39
40        \register_rest_route(
41            $this->namespace,
42            $this->rest_base . '/settings',
43            array(
44                array(
45                    'methods'             => \WP_REST_Server::READABLE,
46                    'callback'            => array( $this, 'get_settings' ),
47                    'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
48                ),
49                array(
50                    'methods'             => \WP_REST_Server::CREATABLE,
51                    'callback'            => array( $this, 'update_settings' ),
52                    'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
53                ),
54                array(
55                    'methods'             => \WP_REST_Server::DELETABLE,
56                    'callback'            => array( $this, 'purge_all' ),
57                    'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
58                ),
59            )
60        );
61    }
62
63    /**
64     * Get the settings
65     *
66     * @return \WP_REST_Response
67     */
68    public function get_settings() {
69        // If user preference is "on" but the drop-in is missing, restore it so the UI shows enabled.
70        ObjectCache::maybe_restore_dropin();
71        $response = array(
72            'cacheExclusion' => get_cache_exclusion(),
73            'cacheLevel'     => get_cache_level(),
74            'objectCache'    => ObjectCache::get_state(),
75        );
76        return new \WP_REST_Response( $response, 200 );
77    }
78
79    /**
80     * Update the settings
81     *
82     * @param \WP_REST_Request $request the request.
83     * @return \WP_REST_Response
84     */
85    public function update_settings( \WP_REST_Request $request ) {
86
87        if ( $request->has_param( 'cacheExclusion' ) ) {
88            $cache_exclusion = $request->get_param( 'cacheExclusion' );
89            $normalized      = CacheExclusion::normalize( $cache_exclusion );
90            if ( ! preg_match( CacheExclusion::CACHE_EXCLUSION_VALIDATE_REGEX, $normalized ) ) {
91                return new \WP_REST_Response(
92                    array(
93                        'result'  => false,
94                        'message' => __( 'Invalid cache exclusion format.', 'wp-module-performance' ),
95                    ),
96                    400
97                );
98            }
99            $result = update_option( CacheExclusion::OPTION_CACHE_EXCLUSION, $normalized );
100            if ( $result ) {
101                return new \WP_REST_Response( array( 'result' => true ), 200 );
102            }
103            return new \WP_REST_Response( array( 'result' => false ), 400 );
104        }
105
106        if ( $request->has_param( 'cacheLevel' ) ) {
107            $cache_level = (int) $request->get_param( 'cacheLevel' );
108            $result      = update_option( CacheManager::OPTION_CACHE_LEVEL, $cache_level );
109            if ( $result ) {
110                // When cache is disabled, turn off object caching too so the UI stays in sync.
111                if ( $cache_level <= 0 ) {
112                    ObjectCache::disable();
113                }
114                return new \WP_REST_Response(
115                    array(
116                        'result'      => true,
117                        'objectCache' => ObjectCache::get_state(),
118                    ),
119                    200
120                );
121            }
122            return new \WP_REST_Response( array( 'result' => false ), 400 );
123        }
124
125        if ( $request->has_param( 'objectCache' ) ) {
126            $object_cache = $request->get_param( 'objectCache' );
127            if ( is_array( $object_cache ) && isset( $object_cache['enabled'] ) ) {
128                $enable = (bool) $object_cache['enabled'];
129                if ( $enable ) {
130                    $out = ObjectCache::enable();
131                } else {
132                    $out = ObjectCache::disable();
133                }
134                if ( $out['success'] ) {
135                    // When enabling: only purge page caches so we don't flush object cache (avoids logging out the user).
136                    // When disabling: purge everything including object cache.
137                    $purger = container()->get( 'cachePurger' );
138                    if ( $enable ) {
139                        $purger->purge_page_caches();
140                    } else {
141                        $purger->purge_all();
142                    }
143                    return new \WP_REST_Response(
144                        array(
145                            'result'      => true,
146                            'objectCache' => ObjectCache::get_state(),
147                        ),
148                        200
149                    );
150                }
151                return new \WP_REST_Response(
152                    array(
153                        'result'      => false,
154                        'message'     => isset( $out['message'] ) ? $out['message'] : '',
155                        'code'        => isset( $out['code'] ) ? (string) $out['code'] : '',
156                        'objectCache' => ObjectCache::get_state(),
157                    ),
158                    400
159                );
160            }
161        }
162
163        return new \WP_REST_Response( array( 'result' => false ), 400 );
164    }
165
166    /**
167     * Clears the entire cache (page cache and object cache when enabled).
168     */
169    public function purge_all() {
170
171        container()->get( 'cachePurger' )->purge_all();
172        ObjectCache::flush_object_cache();
173
174        return array(
175            'status'  => 'success',
176            'message' => __( 'Cache purged', 'wp-module-performance' ),
177        );
178    }
179}