PluginProbe
SQLite Object Cache / 1.5.4
SQLite Object Cache v1.5.4
1.6.5 trunk 0.1.7 1.0.0 1.1.0 1.1.1 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.4.0 1.4.1 1.5.1 1.5.4 1.5.5 1.5.6 1.5.7 All 30 releases
sqlite-object-cache / includes / class-sqlite-object-cache-settings.php

class-sqlite-object-cache-settings.php in SQLite Object Cache 1.5.4, at includes/class-sqlite-object-cache-settings.php

781 lines 26.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Settings class file.
4 *
5 * @package SQLite Object Cache
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Only make one instance of this, please.
14 *
15 * Settings class.
16 */
17 class SQLite_Object_Cache_Settings {
18
19 /**
20 * The main plugin object.
21 *
22 * @var object
23 */
24 public $parent;
25
26 /**
27 * Prefix for plugin settings.
28 *
29 * @var string
30 */
31 public $base = '';
32
33 /**
34 * Available settings for plugin.
35 *
36 * @var array
37 */
38 public $settings = array();
39
40 /**
41 * SQLite3 is available.
42 *
43 * @var string|bool If it's true, we're good. If it's a string, an explanation.
44 */
45 public $has = '';
46
47 /**
48 * Constructor function.
49 *
50 * @param object $parent Parent object.
51 */
52 public function __construct( $parent ) {
53 $this->parent = $parent;
54 $this->has = $parent->has_sqlite();
55 $this->base = 'sqlite_object_cache_';
56
57 // Register plugin settings.
58 add_action( 'admin_init', array( $this, 'register_my_settings' ) );
59
60 // Add settings page to menu.
61 add_action( 'admin_menu', array( $this, 'add_menu_item' ) );
62
63 // Add settings link to plugins page.
64 add_filter(
65 'plugin_action_links_' . plugin_basename( $this->parent->file ),
66 array(
67 $this,
68 'add_settings_link',
69 )
70 );
71
72 // Configure placement of plugin settings page. See readme for implementation.
73 add_filter( $this->base . 'menu_settings', array( $this, 'configure_settings' ) );
74
75 // Load admin JS & CSS.
76 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ), 10, 1 );
77 }
78
79 /**
80 * Build settings fields
81 *
82 * @return array Fields to be displayed on settings page
83 */
84 private function settings_fields() {
85
86 $fields = array(
87 array(
88 'id' => 'flush',
89 'label' => __( 'Flush now', 'sqlite-object-cache' ),
90 'description' => __( 'Check to flush the cache (delete all its entries) now.', 'sqlite-object-cache' ) . ' ' .
91 __( 'This briefly puts your site into maintenance mode.', 'sqlite-object-cache' ),
92 'type' => 'checkbox',
93 'default' => '',
94 'reset' => '',
95 ),
96 array(
97 'id' => 'vacuum',
98 'label' => __( 'Vacuum now', 'sqlite-object-cache' ),
99 'description' => __( 'Check to vacuum (defragment) the cache now.', 'sqlite-object-cache' ) . ' ' .
100 __( 'This briefly puts your site into maintenance mode.', 'sqlite-object-cache' ),
101 'type' => 'checkbox',
102 'default' => '',
103 'reset' => '',
104 ),
105 array(
106 'id' => 'target_size',
107 'label' => __( 'Cached data size', 'sqlite-object-cache' ),
108 'description' => __( 'MiB. When data in the cache grows larger than this, hourly cleanup removes the oldest entries.', 'sqlite-object-cache' ),
109 'type' => 'number',
110 'default' => 16,
111 'min' => 1,
112 'step' => 'any',
113 'cssclass' => 'narrow',
114 'placeholder' => __( 'MiB.', 'sqlite-object-cache' ),
115 ),
116 array(
117 'id' => 'cleanup',
118 'label' => __( 'Clean up now', 'sqlite-object-cache' ),
119 'description' => __( 'Check to clean up the cache (delete old data) now.', 'sqlite-object-cache' ),
120 'type' => 'checkbox',
121 'default' => '',
122 'reset' => '',
123 ),
124 array(
125 'id' => 'capture',
126 'label' => __( 'Measure performance', 'sqlite-object-cache' ),
127 'description' => __( 'Check to enable cache performance measurement. ', 'sqlite-object-cache' ),
128 'type' => 'checkbox',
129 'default' => '',
130 ),
131 array(
132 'id' => 'samplerate',
133 'label' => __( 'Measure', 'sqlite-object-cache' ),
134 'description' => __( 'percent of requests, randomly sampled.', 'sqlite-object-cache' ),
135 'type' => 'number',
136 'default' => 1,
137 'max' => 100,
138 'min' => 0,
139 'step' => 'any',
140 'cssclass' => 'narrow',
141 'placeholder' => __( 'Sampling percentage.', 'sqlite-object-cache' ),
142 ),
143 array(
144 'id' => 'retainmeasurements',
145 'label' => __( 'Retain measurements for', 'sqlite-object-cache' ),
146 'description' => __( 'hours.', 'sqlite-object-cache' ),
147 'type' => 'number',
148 'default' => 2,
149 'min' => 0.1,
150 'step' => 'any',
151 'cssclass' => 'narrow',
152 'placeholder' => __( 'Hours to retain.', 'sqlite-object-cache' ),
153 )
154 );
155
156 if ( $this->parent->apcu_extension_is_enabled() ) {
157 array_unshift( $fields, array(
158 'id' => 'use_apcu',
159 'label' => __( 'Use APCu', 'sqlite-object-cache' ),
160 'description' => __( 'Check to enable the use of php\'s APCu cache to improve performance.', 'sqlite-object-cache' ),
161 'type' => 'checkbox',
162 'default' => '',
163 ) );
164
165 }
166
167 $settings['standard'] = array(
168 'title' => __( 'Settings', 'sqlite-object-cache' ),
169 'submit' => __( 'Save Settings', 'sqlite-object-cache' ),
170 'description' => '',
171 'render_section_header' => array( $this, 'settings_section_header' ),
172 'form_post_callback' => array( $this, 'validate_settings' ),
173 'fields' => $fields,
174 );
175
176 $settings['stats'] = array(
177 'title' => __( 'Statistics', 'sqlite-object-cache' ),
178 'submit' => __( 'Reset Statistics', 'sqlite-object-cache' ),
179 'render_section_header' => array( $this, 'stats_section_header' ),
180 'form_post_callback' => array( $this, 'validate_reset_stats' ),
181 );
182
183 return apply_filters( $this->parent->_token . '_settings_fields', $settings );
184 }
185
186 /**
187 * Validate the options presented to the Settings tab.
188 *
189 * This is an options update filter. It filters an option value following sanitization.
190 *
191 * @param mixed $option The sanitized option value.
192 * @param string $name The option name.
193 * @param string $original_value The original value passed to the function.
194 *
195 * @throws Exception Announce SQLite failure.
196 * @since 2.3.0
197 * @since 4.3.0 Added the `$original_value` parameter.
198 *
199 * @noinspection PhpUnusedParameterInspection
200 */
201 public function validate_settings( $option, $name, $original_value ) {
202 if ( ! is_array( $option ) ) {
203 /* Weird. not an option array */
204 return $option;
205 }
206 global $wp_object_cache;
207 $former_value = get_option( $name, array() );
208
209 /* Opt in or opt out of the APCu. */
210 if ( $this->parent->apcu_extension_is_enabled() ) {
211 $apcu_choice = array_key_exists( 'use_apcu', $option ) && $option ['use_apcu'] === 'on';
212 $apcu_former = array_key_exists( 'use_apcu', $former_value ) && $former_value ['use_apcu'] === 'on';
213 if ( $apcu_choice !== $apcu_former ) {
214 if ( method_exists( $wp_object_cache, 'apcu_clear_cache' ) ) {
215 $wp_object_cache->apcu_clear_cache();
216 }
217 $this->update_wp_config_constant( 'WP_SQLITE_OBJECT_CACHE_APCU', $apcu_choice );
218 $option['use_apcu_updated'] = true;
219 }
220 $option['use_apcu'] = $apcu_choice ? 'on' : 'off';
221 }
222 if ( array_key_exists( 'flush', $option ) && $option ['flush'] === 'on' ) {
223 if ( method_exists( $wp_object_cache, 'flush' ) ) {
224 try {
225 $this->enter_maintenance_mode();
226 $wp_object_cache->flush( true );
227 } finally {
228 $this->exit_maintenance_mode();
229 }
230 } else {
231 wp_cache_flush();
232 }
233 unset ( $option['flush'] );
234 }
235 if ( array_key_exists( 'vacuum', $option ) && $option ['vacuum'] === 'on' ) {
236 if ( method_exists( $wp_object_cache, 'vacuum' ) ) {
237 try {
238 $this->enter_maintenance_mode();
239 $wp_object_cache->vacuum();
240 } finally {
241 $this->exit_maintenance_mode();
242 }
243 } else {
244 wp_cache_flush();
245 }
246 unset ( $option['vacuum'] );
247 }
248 if ( array_key_exists( 'cleanup', $option ) && $option ['cleanup'] === 'on' ) {
249 $this->parent->clean_job();
250 unset ( $option['cleanup'] );
251 }
252
253 $this->numeric_option( $option, 'target_size', 4 );
254 $this->numeric_option( $option, 'samplerate', 10 );
255 $this->numeric_option( $option, 'retainmeasurements', 2 );
256
257 if ( array_key_exists( 'capture', $option ) && $option['capture'] === 'on' ) {
258 $option['previouscapture'] = 0;
259 }
260
261 return $option;
262 }
263
264 /**
265 * Retrieve a numeric option, and set the default if it isn't present.
266 *
267 * @param array $option Option array value.
268 * @param string $name Name of the element in the option array.
269 * @param mixed $default Default value to use.
270 *
271 * @return float|int|mixed|string
272 */
273 private function numeric_option( &$option, $name, $default ) {
274 $result = $default;
275 if ( array_key_exists( $name, $option ) && is_numeric( $option[ $name ] ) ) {
276 $result = $option[ $name ];
277 $result = $result ?: $default;
278 } else {
279 $option[ $name ] = $default;
280 }
281
282 return $result;
283 }
284
285 /**
286 * Filters an option value following sanitization.
287 *
288 * @param string $option The sanitized option value.
289 * @param string $name The option name.
290 * @param string $original_value The original value passed to the function.
291 *
292 * @throws Exception Announce SQLite failure.
293 * @since 2.3.0
294 * @since 4.3.0 Added the `$original_value` parameter.
295 *
296 * @noinspection PhpUnusedParameterInspection
297 */
298 public function validate_reset_stats( $option, $name, $original_value ) {
299
300 global $wp_object_cache;
301 if ( method_exists( $wp_object_cache, 'sqlite_reset_statistics' ) ) {
302 $wp_object_cache->sqlite_reset_statistics();
303 }
304
305 /* for this post operation, we don't want to change any plugin options. */
306
307 return get_option( $name );
308 }
309
310 /**
311 * Add settings page to admin menu
312 *
313 * @return void
314 */
315 public function add_menu_item() {
316
317 $args = $this->menu_settings();
318
319 // Do nothing if wrong location key is set.
320 if ( is_array( $args ) && isset( $args['location'] ) && function_exists( 'add_' . $args['location'] . '_page' ) ) {
321 switch ( $args['location'] ) {
322 case 'options':
323 case 'submenu':
324 $page =
325 add_submenu_page( $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
326 break;
327 case 'menu':
328 $page =
329 add_menu_page( $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'], $args['icon_url'], $args['position'] );
330 break;
331 default:
332 return;
333 }
334 add_action( 'admin_print_styles-' . $page, array( $this, 'settings_assets' ) );
335 }
336 }
337
338 /**
339 * Prepare default settings page arguments
340 *
341 * @return mixed|void
342 */
343 private function menu_settings() {
344 $this->complain_if_sqlite3_unavailable();
345
346 return apply_filters(
347 $this->base . 'menu_settings',
348 array(
349 'location' => 'options', // Possible settings: options, menu, submenu.
350 'parent_slug' => 'options-general.php',
351 'page_title' => __( 'SQLite Persistent Object Cache', 'sqlite-object-cache' ),
352 'menu_title' => __( 'Object Cache', 'sqlite-object-cache' ),
353 'capability' => 'manage_options',
354 'menu_slug' => $this->parent->_token . '_settings',
355 'function' => array( $this, 'settings_page' ),
356 'icon_url' => '',
357 'position' => null,
358 )
359 );
360 }
361
362 /**
363 * Emit a message if SQLite3 is not available.
364 *
365 * @param bool $verbose False means emit a notice. True means emit a longer explanation.
366 *
367 * @return void
368 */
369 private function complain_if_sqlite3_unavailable( $verbose = false ) {
370 if ( true !== $this->has ) {
371 if ( ! $verbose ) {
372 echo '<div class="notice notice-error sql-object-cache">';
373 echo esc_html( $this->has );
374 echo '</div>';
375 } else {
376 echo '<div>';
377 echo '<h3 style="color: #d63638">' . esc_html__( 'Server configuration problem', 'sqlite-object-cache' ) . '</h3>';
378 echo '<p>';
379
380 if ( ! class_exists( 'SQLite3' ) || ! extension_loaded( 'sqlite3' ) ) {
381 echo esc_html__( 'The SQLite Persistent Object Cache plugin requires php\'s SQLite3 extension.', 'sqlite-object-cache' ) . ' ';
382 echo esc_html__( 'That extension is not installed in your server, so the plugin cannot work.', 'sqlite-object-cache' ) . ' ';
383 }
384
385 $sqlite_version = $this->parent->sqlite_get_version();
386 if ( version_compare( $sqlite_version, $this->parent->minimum_sqlite_version ) < 0 ) {
387 echo esc_html( sprintf(
388 /* translators: 1 actual SQLite version. 2 required SQLite version) */
389 __( 'You cannot use the SQLite Object Cache plugin. Your server only offers SQLite3 version %1$s, but at least %2$s is required.', 'sqlite-object-cache' ),
390 $sqlite_version, $this->parent->minimum_sqlite_version ) );
391 }
392
393 echo '</p></div>' . PHP_EOL;
394 }
395 }
396 }
397
398 /**
399 * Container for settings page arguments
400 *
401 * @param array $settings Settings array.
402 *
403 * @return array
404 */
405 public function configure_settings( $settings = array() ) {
406 return $settings;
407 }
408
409 /**
410 * Load settings JS & CSS
411 *
412 * @return void
413 */
414 public function settings_assets() {
415
416 }
417
418 /**
419 * Add settings link to plugin list table
420 *
421 * @param array $links Existing links.
422 *
423 * @return array Modified links.
424 */
425 public function add_settings_link( $links ) {
426 if ( true !== $this->has ) {
427 $settings_link =
428 '<a style="color: #d63638" href="options-general.php?page=' . $this->parent->_token . '_settings">' . __( 'Settings', 'sqlite-object-cache' ) . '</a>';
429 array_unshift( $links, $settings_link );
430 } else {
431 $settings_link =
432 '<a href="options-general.php?page=' . $this->parent->_token . '_settings">' . __( 'Settings', 'sqlite-object-cache' ) . '</a>';
433 $statistics_link =
434 '<a href="options-general.php?page=' . $this->parent->_token . '_settings&tab=stats">' . __( 'Statistics', 'sqlite-object-cache' ) . '</a>';
435 array_unshift( $links, $settings_link, $statistics_link );
436 }
437
438 return $links;
439 }
440
441 /**
442 * Register plugin settings
443 *
444 * @return void
445 */
446 public function register_my_settings() {
447 $this->parent->sync_apcu_global_to_option( false );
448 $this->settings = $this->settings_fields();
449
450 if ( is_array( $this->settings ) ) {
451
452 /* get the tab chosen by the user ('standard' or 'stats') */
453 $tab = isset ( $_REQUEST['tab'] ) ? sanitize_key( $_REQUEST['tab'] ) : 'standard';
454
455 $default_option = array();
456 $option_name = $this->base . 'settings';
457
458 foreach ( $this->settings as $section => $data ) {
459
460 if ( $tab && $tab !== $section ) {
461 continue;
462 }
463
464 $setting_args = array(
465 'description' => $data['title'],
466 'default' => $default_option,
467 );
468
469 // Validation callback for section.
470 if ( isset( $data['form_post_callback'] ) ) {
471 add_filter( "sanitize_option_$option_name", $data['form_post_callback'], 10, 3 );
472 }
473
474 // Add section to page.
475 add_settings_section( $section, '',
476 $data ['render_section_header'],
477 $this->parent->_token . '_settings' );
478
479 if ( array_key_exists( 'fields', $data ) && is_array( $data['fields'] ) ) {
480 foreach ( $data['fields'] as $field ) {
481 $default_option [ $field['id'] ] = $field['default'];
482 }
483
484 foreach ( $data['fields'] as $field ) {
485 // Add field to page.
486 add_settings_field(
487 $field['id'],
488 $field['label'],
489 array( $this->parent->admin, 'echo_field' ),
490 $this->parent->_token . '_settings',
491 $section,
492 array(
493 'field' => $field,
494 'option' => $option_name,
495 )
496 );
497 }
498 }
499 /* register the settings object */
500 register_setting( $this->parent->_token . '_settings', $option_name, $setting_args );
501 }
502 }
503 }
504
505 /**
506 * Settings section.
507 *
508 * @param array $section Array of section ids.
509 *
510 * @return void
511 * @throws Exception Announce Database Failure.
512 */
513 public function settings_section_header( $section ) {
514
515 $this->support_links();
516 $this->apcu_admonition();
517 $this->versions();
518
519 if ( array_key_exists( 'description', $this->settings[ $section['id'] ] ) ) {
520 echo '<p> ' . esc_html( $this->settings[ $section['id'] ]['description'] ) . '</p>' . PHP_EOL;
521 }
522 }
523
524 /**
525 * Display support and rating links.
526 *
527 * @return void
528 */
529 private function support_links() {
530
531 $supportUrl = "https://wordpress.org/support/plugin/sqlite-object-cache/";
532 $reviewUrl = "https://wordpress.org/support/plugin/sqlite-object-cache/reviews/";
533 echo '<p>';
534 echo esc_html__( 'For support please', 'sqlite-object-cache' ) . ' ';
535 echo '<a href="' . esc_url( $supportUrl ) . '">' . esc_html__( 'click here', 'sqlite-object-cache' ) . '</a>. ';
536 echo esc_html__( 'To rate this plugin please', 'sqlite-object-cache' ) . ' ';
537 echo '<a href="' . esc_url( $reviewUrl ) . '">' . esc_html__( 'click here', 'sqlite-object-cache' ) . '</a>. ';
538 echo esc_html__( 'Your feedback helps make it better, faster, and more useful', 'sqlite-object-cache' ) . '.';
539 echo '</p>';
540
541 }
542
543 private function apcu_admonition() {
544 echo '<p>';
545 echo esc_html__( 'You can use WP-CLI to configure this plugin. Please type', 'sqlite-object-cache' ) . ' ';
546 echo '<code>wp help sqlite-object-cache</code> ';
547 echo esc_html__( 'into your shell for details', 'sqlite-object-cache' ) . '.';
548 echo '</p>';
549 $option = get_option( $this->parent->_token . '_settings', array() );
550 $apcu_active = array_key_exists( 'use_apcu', $option ) && 'on' == $option['use_apcu'];
551 $apcu_enabled = $this->parent->apcu_extension_is_enabled();
552 if ( $apcu_enabled && ! $apcu_active ) {
553 echo '<p>';
554 echo esc_html__( 'On your site you can use php\'s', 'sqlite-object-cache' ) . ' ';
555 echo '<a href="https://www.php.net/manual/en/book.apcu.php" target="_blank">' . esc_html__( 'APCu User Cache', 'sqlite-object-cache' ) . '</a> ';
556 echo esc_html__( 'to improve the performance of this SQLite Object Cache. ', 'sqlite-object-cache' );
557 echo esc_html__( 'To enable APCu caching please check the "Use APCu" box.', 'sqlite-object-cache' ) . ' ';
558 echo '</p>';
559 }
560 if ( $apcu_enabled && $apcu_active ) {
561 echo '<p>';
562 echo esc_html__( 'You are using php\'s', 'sqlite-object-cache' ) . ' ';
563 echo '<a href="https://www.php.net/manual/en/book.apcu.php" target="_blank">' . esc_html__( 'APCu User Cache', 'sqlite-object-cache' ) . '</a> ';
564 echo esc_html__( 'to improve the performance of this SQLite Object Cache. ', 'sqlite-object-cache' ) . ' ';
565 echo esc_html__( 'To disable APCu caching please uncheck the "Use APCu" box.', 'sqlite-object-cache' ) . ' ';
566 echo '</p>';
567 }
568 if ( ! $apcu_enabled ) {
569 echo '<p>';
570 echo esc_html__( 'This object cache performs better when used with php\'s', 'sqlite-object-cache' ) . ' ';
571 echo '<a href="https://www.php.net/manual/en/book.apcu.php" target="_blank">' . esc_html__( 'APCu User Cache', 'sqlite-object-cache' ) . '</a> ';
572 echo esc_html__( 'extension. ', 'sqlite-object-cache' ) . ' ';
573 echo esc_html__( 'However, it is not available on your server.', 'sqlite-object-cache' ) . ' ';
574 echo esc_html__( 'It may be possible for you or your hosting service to install it.', 'sqlite-object-cache' ) . ' ';
575 echo '</p>';
576 }
577 }
578
579 /**
580 * Display versions.
581 *
582 * @return void
583 * @throws Exception Announce database failure.
584 */
585 private function versions() {
586 global $wp_object_cache;
587 global $wp_version;
588 $igbinary = function_exists( 'igbinary_serialize' ) && function_exists( 'igbinary_unserialize' )
589 ? phpversion( 'igbinary' )
590 : __( 'unavailable', 'sqlite-object-cache' );
591 $force_serialize = defined( 'WP_SQLITE_OBJECT_CACHE_SERIALIZE' ) && WP_SQLITE_OBJECT_CACHE_SERIALIZE;
592 $igbinary .= $force_serialize ? esc_html__( '(disabled by WP_SQLITE_OBJECT_CACHE_SERIALIZE)', 'sqlite-object-cache' ) : '';
593
594 $apcu_version = $this->parent->apcu_extension_is_enabled()
595 ? phpversion( "apcu" )
596 : __( 'unavailable', 'sqlite-object-cache' );
597
598 if ( method_exists( $wp_object_cache, 'sqlite_get_version' ) ) {
599 echo '<p>' . esc_html( sprintf(
600 /* translators: 1: version for sqlite 2: version for php 3: webserver version 4: version for plugin 5: igbinary 6:APCu 7:WordPress */
601 __( 'Versions: WordPress: %7$s SQLite: %1$s php: %2$s Server: %3$s Plugin: %4$s APCu: %6$s igbinary: %5$s.', 'sqlite-object-cache' ),
602 $wp_object_cache->sqlite_get_version(),
603 PHP_VERSION,
604 $_SERVER['SERVER_SOFTWARE'],
605 $this->parent->_version,
606 $igbinary,
607 $apcu_version,
608 $wp_version ) ) . '</p>';
609 }
610 }
611
612 /**
613 * Statistics tab section.
614 *
615 * @param array $section Array of section ids.
616 *
617 * @return void
618 * @throws Exception Announce Database Failure.
619 * @noinspection PhpUnusedParameterInspection
620 */
621 public function stats_section_header( $section ) {
622
623 $this->support_links();
624 $this->versions();
625
626 $stats = new SQLite_Object_Cache_Statistics ( get_option( $this->parent->_token . '_settings', array() ) );
627 $stats->init();
628 $stats->render();
629 $stats->render_usage();
630 }
631
632 /**
633 * Load settings page content.
634 *
635 * @return void
636 */
637 public function settings_page() {
638
639 /* get the tab chosen by the user ('standard' by default or 'stats') */
640 $tab = isset ( $_REQUEST['tab'] ) ? sanitize_key( $_REQUEST['tab'] ) : 'standard';
641
642 // Build page HTML.
643 echo '<div class="wrap" id="' . esc_attr( $this->parent->_token . '_settings' ) . '">' . PHP_EOL;
644 echo '<h2>' . esc_html__( 'SQLite Persistent Object Cache', 'sqlite-object-cache' ) . '</h2>' . PHP_EOL;
645
646 $submit_caption = __( 'Save Settings', 'sqlite-object-cache' );
647 $this->complain_if_sqlite3_unavailable( true );
648
649 // Show page tabs.
650 if ( is_array( $this->settings ) && 1 < count( $this->settings ) ) {
651
652 echo '<h2 class="nav-tab-wrapper">' . PHP_EOL;
653
654 foreach ( $this->settings as $section => $data ) {
655
656 // Set tab class.
657 $class = 'nav-tab';
658 if ( $section === $tab ) {
659 $class .= ' nav-tab-active';
660 $submit_caption = $data['submit'];
661 }
662
663 // Set tab link.
664 $tab_link = add_query_arg( array( 'tab' => $section ) );
665 $tab_link = remove_query_arg( 'settings-updated', $tab_link );
666
667 // Output tab.
668 echo '<a href="' . esc_url( $tab_link ) . '" class="' . esc_attr( $class ) . '">' . esc_html( $data['title'] ) . '</a>' . PHP_EOL;
669 }
670
671 echo '</h2>' . PHP_EOL;
672 }
673
674 /** @noinspection HtmlUnknownTarget */
675 echo '<form method="post" action="options.php" enctype="multipart/form-data">' . PHP_EOL;
676
677 // Get settings fields.
678 settings_fields( $this->parent->_token . '_settings' );
679 do_settings_sections( $this->parent->_token . '_settings' );
680
681 echo '<p class="submit">' . PHP_EOL;
682 echo '<input type="hidden" name="tab" value="' . esc_attr( $tab ) . '" />' . PHP_EOL;
683 echo '<input name="Submit" type="submit" class="button-primary" value="' . esc_attr( $submit_caption ) . '" />' . PHP_EOL;
684 echo '</p></form></div>' . PHP_EOL;
685 }
686
687 /**
688 * Admin enqueue assets
689 *
690 * @param string $hook Hook parameter.
691 *
692 * @return void
693 * @noinspection PhpUnusedParameterInspection
694 */
695 public function enqueue_assets( $hook = '' ) {
696 wp_register_style( $this->parent->_token . '-admin',
697 esc_url( $this->parent->assets_url ) . 'css/admin.css',
698 array(), $this->parent->_version );
699 wp_enqueue_style( $this->parent->_token . '-admin' );
700 }
701
702 /**
703 * Enters maintenance mode.
704 *
705 * @return void
706 */
707 private function enter_maintenance_mode() {
708 $maintenanceFileName = ABSPATH . '.maintenance';
709 $maintain = array();
710 array_push( $maintain,
711 '<?php',
712 '$upgrading = ' . time() . ';',
713 '?>' );
714 file_put_contents( $maintenanceFileName, implode( PHP_EOL, $maintain ) );
715 }
716
717 /**
718 * Exits maintenance mode.
719 *
720 * @return void
721 */
722 private function exit_maintenance_mode() {
723 $maintenanceFileName = ABSPATH . '.maintenance';
724 unlink( $maintenanceFileName );
725 }
726
727 /**
728 * Update a variable in the wp-config.php file.
729 *
730 * If enabling, check if the variable is defined, and if not, define it.
731 * Vice versa for disabling.
732 *
733 * @author https://profiles.wordpress.org/litespeedtech/
734 */
735 private function update_wp_config_constant( $symbol, $enable ) {
736 if ( $enable ) {
737 if ( defined( $symbol ) && constant( $symbol ) ) {
738 return false;
739 }
740 } elseif ( ! defined( $symbol ) || ( defined( $symbol ) && ! constant( $symbol ) ) ) {
741 return false;
742 }
743
744 /**
745 * Follow WP's logic to locate wp-config file
746 * @see wp-load.php
747 */
748 $conf_file = ABSPATH . 'wp-config.php';
749 if ( ! file_exists( $conf_file ) ) {
750 $conf_file = dirname( ABSPATH ) . '/wp-config.php';
751 }
752
753 $content = SQLite_Object_Cache_File::read( $conf_file );
754 if ( ! $content ) {
755 throw new Exception( 'wp-config file content is empty: ' . $conf_file );
756 }
757
758 // Remove the line `define('WHATEVER', true/false);` first
759 if ( defined( $symbol ) ) {
760 $re = '/define\(\s*([\'"])' . $symbol . '\1\s*,\s*\w+\s*\)\s*;\s*[' . "\r\n" . ']*?/sU';
761 $content = preg_replace( $re, '', $content );
762 }
763
764 // Insert const
765 if ( $enable ) {
766 $replacement = "<?php" . PHP_EOL . "define( '" . $symbol . "', true );";
767 $content = preg_replace( '/^<\?php/', $replacement, $content );
768 }
769
770 $res = SQLite_Object_Cache_File::save( $conf_file, $content, false, false, false );
771
772 if ( $res !== true ) {
773 throw new Exception( 'wp-config.php operation failed when changing `WP_CACHE` const: ' . $res );
774 }
775
776 return true;
777 }
778
779
780 }
781