PluginProbe
ezCache / 2.5
ezCache v2.5
2.6.5 2.6.4 2.6.2 2.6.3 2.6.1 2.6.0 2.5.6 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5 2.2.1 2.2.2 trunk 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.3 1.3.1 1.3.10 1.3.11 All 49 releases
ezcache / includes / AdvancedSettingsPage.php

AdvancedSettingsPage.php in ezCache 2.5, at includes/AdvancedSettingsPage.php

426 lines 15.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Upress\EzCache;
4
5 /**
6 * Server-rendered settings page for the 1.7.0 modules.
7 *
8 * The original ezCache options screen is a compiled JS app that we cannot
9 * extend without re-building it. Instead, this class registers an additional
10 * submenu page (`ezcache-performance`) underneath the ezCache top-level menu
11 * and renders a plain PHP form for the new Preload, Optimizations, CDN,
12 * Heartbeat and Database modules. The form posts to admin-post.php and is
13 * persisted through the existing Settings class so all storage stays in the
14 * single ezcache-config.json file.
15 */
16 class AdvancedSettingsPage {
17
18 const MENU_SLUG = 'ezcache-performance';
19 const NONCE = 'ezcache_perf_nonce';
20
21 public function __construct() {
22 // Performance page is now integrated into the Vue app
23 // Keep legacy form handlers for backwards compatibility
24 add_action( 'admin_post_ezcache_save_performance', [ $this, 'handle_save' ] );
25 add_action( 'admin_post_ezcache_run_preload', [ $this, 'handle_run_preload' ] );
26 add_action( 'admin_post_ezcache_stop_preload', [ $this, 'handle_stop_preload' ] );
27 add_action( 'admin_post_ezcache_run_db_cleanup', [ $this, 'handle_run_db_cleanup' ] );
28 }
29
30 public function register_menu() {
31 // No longer needed - Performance is now a Vue route
32 }
33
34 /**
35 * Render the settings screen.
36 */
37 public function render() {
38 if ( ! current_user_can( 'manage_options' ) ) {
39 return;
40 }
41
42 $settings = Settings::get_settings();
43 $preload_status = Preload::instance()->get_status();
44 $action_url = admin_url( 'admin-post.php' );
45 $flash = isset( $_GET['ezcache_msg'] ) ? sanitize_text_field( wp_unslash( $_GET['ezcache_msg'] ) ) : '';
46 $flash_messages = [
47 'saved' => __( 'Settings saved.', 'ezcache' ),
48 'preload_run' => __( 'Preload started in the background.', 'ezcache' ),
49 'preload_stop' => __( 'Preload cancelled.', 'ezcache' ),
50 'db_cleaned' => __( 'Database cleanup completed.', 'ezcache' ),
51 ];
52
53 $checkbox = function ( $key ) use ( $settings ) {
54 $checked = ! empty( $settings->{$key} ) ? 'checked' : '';
55 printf(
56 '<input type="checkbox" name="%1$s" id="%1$s" value="1" %2$s>',
57 esc_attr( $key ),
58 $checked
59 );
60 };
61
62 $text = function ( $key, $placeholder = '' ) use ( $settings ) {
63 $value = isset( $settings->{$key} ) ? $settings->{$key} : '';
64 printf(
65 '<input type="text" class="regular-text" name="%1$s" id="%1$s" value="%2$s" placeholder="%3$s">',
66 esc_attr( $key ),
67 esc_attr( $value ),
68 esc_attr( $placeholder )
69 );
70 };
71
72 $number = function ( $key, $min = 1, $max = 100 ) use ( $settings ) {
73 $value = isset( $settings->{$key} ) ? (int) $settings->{$key} : $min;
74 printf(
75 '<input type="number" name="%1$s" id="%1$s" value="%2$d" min="%3$d" max="%4$d">',
76 esc_attr( $key ),
77 $value,
78 $min,
79 $max
80 );
81 };
82
83 $textarea = function ( $key, $placeholder = '' ) use ( $settings ) {
84 $value = isset( $settings->{$key} ) ? $settings->{$key} : '';
85 printf(
86 '<textarea name="%1$s" id="%1$s" rows="4" class="large-text code" placeholder="%3$s">%2$s</textarea>',
87 esc_attr( $key ),
88 esc_textarea( $value ),
89 esc_attr( $placeholder )
90 );
91 };
92
93 $select = function ( $key, $options ) use ( $settings ) {
94 $current = isset( $settings->{$key} ) ? $settings->{$key} : '';
95 printf( '<select name="%1$s" id="%1$s">', esc_attr( $key ) );
96 foreach ( $options as $value => $label ) {
97 printf(
98 '<option value="%1$s"%2$s>%3$s</option>',
99 esc_attr( $value ),
100 selected( $current, $value, false ),
101 esc_html( $label )
102 );
103 }
104 echo '</select>';
105 };
106
107 ?>
108 <div class="wrap">
109 <h1><?php esc_html_e( 'ezCache Performance', 'ezcache' ); ?></h1>
110
111 <?php if ( $flash && isset( $flash_messages[ $flash ] ) ) : ?>
112 <div class="notice notice-success is-dismissible"><p><?php echo esc_html( $flash_messages[ $flash ] ); ?></p></div>
113 <?php endif; ?>
114
115 <p class="description">
116 <?php esc_html_e( 'These options expose the new performance modules introduced in ezCache 1.7.0. They are stored in the same configuration file as the rest of the ezCache settings.', 'ezcache' ); ?>
117 </p>
118
119 <h2 class="title"><?php esc_html_e( 'Cache Preload', 'ezcache' ); ?></h2>
120 <form method="post" action="<?php echo esc_url( $action_url ); ?>" style="margin-bottom: 20px;">
121 <?php wp_nonce_field( self::NONCE ); ?>
122 <input type="hidden" name="action" value="ezcache_run_preload">
123 <p>
124 <strong><?php esc_html_e( 'Status:', 'ezcache' ); ?></strong>
125 <?php echo esc_html( $preload_status['status'] ); ?>
126 &middot;
127 <?php
128 /* translators: 1: processed, 2: total, 3: remaining */
129 printf(
130 esc_html__( 'Processed: %1$d / %2$d (%3$d remaining)', 'ezcache' ),
131 (int) $preload_status['processed'],
132 (int) $preload_status['total'],
133 (int) $preload_status['remaining']
134 );
135 ?>
136 </p>
137 <p>
138 <button type="submit" class="button button-primary"><?php esc_html_e( 'Run Preload Now', 'ezcache' ); ?></button>
139 <button type="submit" class="button" formaction="<?php echo esc_url( $action_url ); ?>" name="action" value="ezcache_stop_preload"><?php esc_html_e( 'Stop Preload', 'ezcache' ); ?></button>
140 </p>
141 </form>
142
143 <form method="post" action="<?php echo esc_url( $action_url ); ?>">
144 <?php wp_nonce_field( self::NONCE ); ?>
145 <input type="hidden" name="action" value="ezcache_save_performance">
146
147 <table class="form-table" role="presentation">
148 <tr>
149 <th scope="row"><label for="enable_preload"><?php esc_html_e( 'Enable Preload', 'ezcache' ); ?></label></th>
150 <td>
151 <?php $checkbox( 'enable_preload' ); ?>
152 <p class="description"><?php esc_html_e( 'Activate the cache preloader. Pages will be crawled in the background to keep the cache warm.', 'ezcache' ); ?></p>
153 </td>
154 </tr>
155 <tr>
156 <th scope="row"><label for="preload_on_cache_clear"><?php esc_html_e( 'Preload after cache clear', 'ezcache' ); ?></label></th>
157 <td><?php $checkbox( 'preload_on_cache_clear' ); ?></td>
158 </tr>
159 <tr>
160 <th scope="row"><label for="preload_crawl_homepage_links"><?php esc_html_e( 'Crawl homepage links', 'ezcache' ); ?></label></th>
161 <td><?php $checkbox( 'preload_crawl_homepage_links' ); ?></td>
162 </tr>
163 <tr>
164 <th scope="row"><label for="preload_sitemap_url"><?php esc_html_e( 'Sitemap URL (optional)', 'ezcache' ); ?></label></th>
165 <td>
166 <?php $text( 'preload_sitemap_url', home_url( '/sitemap.xml' ) ); ?>
167 <p class="description"><?php esc_html_e( 'Leave blank to auto-detect /wp-sitemap.xml, /sitemap_index.xml or /sitemap.xml.', 'ezcache' ); ?></p>
168 </td>
169 </tr>
170 <tr>
171 <th scope="row"><label for="preload_batch_size"><?php esc_html_e( 'URLs per batch', 'ezcache' ); ?></label></th>
172 <td><?php $number( 'preload_batch_size', 1, 50 ); ?></td>
173 </tr>
174 </table>
175
176 <h2 class="title"><?php esc_html_e( 'Front-end Optimizations', 'ezcache' ); ?></h2>
177 <table class="form-table" role="presentation">
178 <tr>
179 <th scope="row"><label for="lazy_load_images"><?php esc_html_e( 'Lazy load images', 'ezcache' ); ?></label></th>
180 <td><?php $checkbox( 'lazy_load_images' ); ?></td>
181 </tr>
182 <tr>
183 <th scope="row"><label for="lazy_load_iframes"><?php esc_html_e( 'Lazy load iframes', 'ezcache' ); ?></label></th>
184 <td><?php $checkbox( 'lazy_load_iframes' ); ?></td>
185 </tr>
186 <tr>
187 <th scope="row"><label for="defer_js"><?php esc_html_e( 'Defer JavaScript', 'ezcache' ); ?></label></th>
188 <td>
189 <?php $checkbox( 'defer_js' ); ?>
190 <p class="description"><?php esc_html_e( 'Adds defer to local script tags to reduce render-blocking JS.', 'ezcache' ); ?></p>
191 </td>
192 </tr>
193 <tr>
194 <th scope="row"><label for="defer_js_exclusions"><?php esc_html_e( 'Defer JS exclusions', 'ezcache' ); ?></label></th>
195 <td>
196 <?php $textarea( 'defer_js_exclusions', "jquery.js\njquery-migrate" ); ?>
197 <p class="description"><?php esc_html_e( 'One match per line. URLs containing any of these strings will not be deferred.', 'ezcache' ); ?></p>
198 </td>
199 </tr>
200 <tr>
201 <th scope="row"><label for="remove_query_strings"><?php esc_html_e( 'Remove query strings from static assets', 'ezcache' ); ?></label></th>
202 <td><?php $checkbox( 'remove_query_strings' ); ?></td>
203 </tr>
204 <tr>
205 <th scope="row"><label for="dns_prefetch"><?php esc_html_e( 'DNS prefetch hosts', 'ezcache' ); ?></label></th>
206 <td>
207 <?php $textarea( 'dns_prefetch', "//fonts.googleapis.com\n//cdn.example.com" ); ?>
208 </td>
209 </tr>
210 <tr>
211 <th scope="row"><label for="preconnect"><?php esc_html_e( 'Preconnect hosts', 'ezcache' ); ?></label></th>
212 <td>
213 <?php $textarea( 'preconnect', "https://fonts.gstatic.com" ); ?>
214 </td>
215 </tr>
216 </table>
217
218 <h2 class="title"><?php esc_html_e( 'Heartbeat Control', 'ezcache' ); ?></h2>
219 <table class="form-table" role="presentation">
220 <tr>
221 <th scope="row"><label for="heartbeat_control"><?php esc_html_e( 'Enable heartbeat control', 'ezcache' ); ?></label></th>
222 <td><?php $checkbox( 'heartbeat_control' ); ?></td>
223 </tr>
224 <tr>
225 <th scope="row"><label for="heartbeat_mode"><?php esc_html_e( 'Mode', 'ezcache' ); ?></label></th>
226 <td>
227 <?php $select( 'heartbeat_mode', [
228 'reduce' => __( 'Reduce activity (60s ticks)', 'ezcache' ),
229 'disable' => __( 'Disable completely', 'ezcache' ),
230 ] ); ?>
231 </td>
232 </tr>
233 </table>
234
235 <h2 class="title"><?php esc_html_e( 'CDN', 'ezcache' ); ?></h2>
236 <table class="form-table" role="presentation">
237 <tr>
238 <th scope="row"><label for="cdn_enabled"><?php esc_html_e( 'Enable CDN rewriting', 'ezcache' ); ?></label></th>
239 <td><?php $checkbox( 'cdn_enabled' ); ?></td>
240 </tr>
241 <tr>
242 <th scope="row"><label for="cdn_url"><?php esc_html_e( 'CDN URL', 'ezcache' ); ?></label></th>
243 <td>
244 <?php $text( 'cdn_url', 'https://cdn.example.com' ); ?>
245 <p class="description"><?php esc_html_e( 'Static assets under /wp-content/uploads, /themes and /plugins will be rewritten to this host.', 'ezcache' ); ?></p>
246 </td>
247 </tr>
248 </table>
249
250 <h2 class="title"><?php esc_html_e( 'Database Cleanup', 'ezcache' ); ?></h2>
251 <table class="form-table" role="presentation">
252 <tr>
253 <th scope="row"><label for="db_cleanup_revisions"><?php esc_html_e( 'Delete post revisions', 'ezcache' ); ?></label></th>
254 <td><?php $checkbox( 'db_cleanup_revisions' ); ?></td>
255 </tr>
256 <tr>
257 <th scope="row"><label for="db_cleanup_auto_drafts"><?php esc_html_e( 'Delete auto drafts', 'ezcache' ); ?></label></th>
258 <td><?php $checkbox( 'db_cleanup_auto_drafts' ); ?></td>
259 </tr>
260 <tr>
261 <th scope="row"><label for="db_cleanup_trashed_posts"><?php esc_html_e( 'Delete trashed posts', 'ezcache' ); ?></label></th>
262 <td><?php $checkbox( 'db_cleanup_trashed_posts' ); ?></td>
263 </tr>
264 <tr>
265 <th scope="row"><label for="db_cleanup_spam_comments"><?php esc_html_e( 'Delete spam comments', 'ezcache' ); ?></label></th>
266 <td><?php $checkbox( 'db_cleanup_spam_comments' ); ?></td>
267 </tr>
268 <tr>
269 <th scope="row"><label for="db_cleanup_trashed_comments"><?php esc_html_e( 'Delete trashed comments', 'ezcache' ); ?></label></th>
270 <td><?php $checkbox( 'db_cleanup_trashed_comments' ); ?></td>
271 </tr>
272 <tr>
273 <th scope="row"><label for="db_cleanup_expired_transients"><?php esc_html_e( 'Delete expired transients', 'ezcache' ); ?></label></th>
274 <td><?php $checkbox( 'db_cleanup_expired_transients' ); ?></td>
275 </tr>
276 <tr>
277 <th scope="row"><label for="db_cleanup_orphan_postmeta"><?php esc_html_e( 'Delete orphan post meta', 'ezcache' ); ?></label></th>
278 <td><?php $checkbox( 'db_cleanup_orphan_postmeta' ); ?></td>
279 </tr>
280 <tr>
281 <th scope="row"><label for="db_optimize_tables"><?php esc_html_e( 'Run OPTIMIZE TABLE on all tables', 'ezcache' ); ?></label></th>
282 <td><?php $checkbox( 'db_optimize_tables' ); ?></td>
283 </tr>
284 <tr>
285 <th scope="row"><label for="db_cleanup_schedule"><?php esc_html_e( 'Automatic cleanup schedule', 'ezcache' ); ?></label></th>
286 <td>
287 <?php $select( 'db_cleanup_schedule', [
288 'never' => __( 'Never (manual only)', 'ezcache' ),
289 'daily' => __( 'Daily', 'ezcache' ),
290 'weekly' => __( 'Weekly', 'ezcache' ),
291 ] ); ?>
292 </td>
293 </tr>
294 </table>
295
296 <?php submit_button( __( 'Save Performance Settings', 'ezcache' ) ); ?>
297 </form>
298
299 <form method="post" action="<?php echo esc_url( $action_url ); ?>">
300 <?php wp_nonce_field( self::NONCE ); ?>
301 <input type="hidden" name="action" value="ezcache_run_db_cleanup">
302 <p>
303 <button type="submit" class="button button-secondary"><?php esc_html_e( 'Run Database Cleanup Now', 'ezcache' ); ?></button>
304 <span class="description"><?php esc_html_e( 'Runs the cleanup tasks ticked above immediately.', 'ezcache' ); ?></span>
305 </p>
306 </form>
307 </div>
308 <?php
309 }
310
311 /**
312 * Persist the form values to the ezCache settings.
313 */
314 public function handle_save() {
315 $this->verify();
316
317 $boolean_keys = [
318 'enable_preload',
319 'preload_on_cache_clear',
320 'preload_crawl_homepage_links',
321 'lazy_load_images',
322 'lazy_load_iframes',
323 'defer_js',
324 'remove_query_strings',
325 'heartbeat_control',
326 'cdn_enabled',
327 'db_cleanup_revisions',
328 'db_cleanup_auto_drafts',
329 'db_cleanup_trashed_posts',
330 'db_cleanup_spam_comments',
331 'db_cleanup_trashed_comments',
332 'db_cleanup_expired_transients',
333 'db_cleanup_orphan_postmeta',
334 'db_optimize_tables',
335 ];
336
337 $text_keys = [
338 'preload_sitemap_url',
339 'cdn_url',
340 ];
341
342 $textarea_keys = [
343 'defer_js_exclusions',
344 'dns_prefetch',
345 'preconnect',
346 ];
347
348 $select_keys = [
349 'heartbeat_mode' => [ 'reduce', 'disable' ],
350 'db_cleanup_schedule' => [ 'never', 'daily', 'weekly' ],
351 ];
352
353 $new_settings = [];
354
355 foreach ( $boolean_keys as $key ) {
356 $new_settings[ $key ] = ! empty( $_POST[ $key ] );
357 }
358
359 foreach ( $text_keys as $key ) {
360 $new_settings[ $key ] = isset( $_POST[ $key ] ) ? esc_url_raw( wp_unslash( $_POST[ $key ] ) ) : '';
361 }
362
363 foreach ( $textarea_keys as $key ) {
364 $new_settings[ $key ] = isset( $_POST[ $key ] ) ? sanitize_textarea_field( wp_unslash( $_POST[ $key ] ) ) : '';
365 }
366
367 foreach ( $select_keys as $key => $allowed ) {
368 $value = isset( $_POST[ $key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) : '';
369 if ( ! in_array( $value, $allowed, true ) ) {
370 $value = $allowed[0];
371 }
372 $new_settings[ $key ] = $value;
373 }
374
375 $batch = isset( $_POST['preload_batch_size'] ) ? max( 1, min( 50, (int) $_POST['preload_batch_size'] ) ) : 5;
376 $new_settings['preload_batch_size'] = $batch;
377
378 Settings::set_settings( $new_settings );
379
380 $this->redirect_back( 'saved' );
381 }
382
383 public function handle_run_preload() {
384 $this->verify();
385 Preload::instance()->start();
386 $this->redirect_back( 'preload_run' );
387 }
388
389 public function handle_stop_preload() {
390 $this->verify();
391 Preload::instance()->stop();
392 $this->redirect_back( 'preload_stop' );
393 }
394
395 public function handle_run_db_cleanup() {
396 $this->verify();
397 ( new DatabaseOptimizer() )->clean();
398 $this->redirect_back( 'db_cleaned' );
399 }
400
401 protected function verify() {
402 if ( ! current_user_can( 'manage_options' ) ) {
403 wp_die( esc_html__( 'Forbidden', 'ezcache' ), 403 );
404 }
405 check_admin_referer( self::NONCE );
406 }
407
408 protected function redirect_back( $message ) {
409 wp_safe_redirect( add_query_arg(
410 [
411 'page' => self::MENU_SLUG,
412 'ezcache_msg' => $message,
413 ],
414 admin_url( 'admin.php' )
415 ) );
416 exit;
417 }
418
419 /**
420 * No longer needed - Performance is now a Vue route
421 */
422 public function reorder_menu() {
423 // Deprecated - Performance is integrated into Vue app
424 }
425 }
426