parent = $parent; $this->has = $parent->has_sqlite(); $this->base = 'sqlite_object_cache_'; // Initialise settings. add_action( 'init', [ $this, 'init_settings' ], 11 ); // Register plugin settings. add_action( 'admin_init', [ $this, 'register_my_settings' ] ); // Add settings page to menu. add_action( 'admin_menu', [ $this, 'add_menu_item' ] ); // Add settings link to plugins page. add_filter( 'plugin_action_links_' . plugin_basename( $this->parent->file ), [ $this, 'add_settings_link', ] ); // Configure placement of plugin settings page. See readme for implementation. add_filter( $this->base . 'menu_settings', [ $this, 'configure_settings' ] ); // Load admin JS & CSS. add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ], 10, 1 ); } /** * Initialize settings * * @return void */ public function init_settings() { $this->settings = $this->settings_fields(); } /** * Build settings fields * * @return array Fields to be displayed on settings page */ private function settings_fields() { $settings['standard'] = [ 'title' => __( 'Settings', 'sqlite-object-cache' ), 'submit' => __( 'Save Settings', 'sqlite-object-cache' ), 'description' => '', 'render_section_header' => [ $this, 'settings_section_header' ], 'form_post_callback' => [ $this, 'validate_settings' ], 'fields' => [ [ 'id' => 'flush', 'label' => __( 'Flush now', 'sqlite-object-cache' ), 'description' => __( 'Check to flush the cache (delete all its entries).', 'sqlite-object-cache' ), 'type' => 'checkbox', 'default' => '', 'reset' => '', ], [ 'id' => 'retention', 'label' => __( 'Cached data expires after', 'sqlite-object-cache' ), 'description' => __( 'hours.', 'sqlite-object-cache' ), 'type' => 'number', 'default' => 24, 'max' => 24 * 7, 'min' => 1, 'step' => 'any', 'cssclass' => 'narrow', 'placeholder' => __( 'Hours to retain.', 'sqlite-object-cache' ), ], [ 'id' => 'cleanup', 'label' => __( 'Clean up now', 'sqlite-object-cache' ), 'description' => __( 'Check to clean up the cache (delete expired data).', 'sqlite-object-cache' ), 'type' => 'checkbox', 'default' => '', 'reset' => '', ], [ 'id' => 'capture', 'label' => __( 'Measure performance', 'sqlite-object-cache' ), 'description' => __( 'Check to measure cache performance. ', 'sqlite-object-cache' ), 'type' => 'checkbox', 'default' => '', ], [ 'id' => 'frequency', 'label' => __( 'Measure', 'sqlite-object-cache' ), 'description' => __( 'times per hour.', 'sqlite-object-cache' ), 'type' => 'number', 'default' => 10, 'max' => 36000, 'min' => 0.001, 'step' => 'any', 'cssclass' => 'narrow', 'placeholder' => __( 'Times per hour to measure.', 'sqlite-object-cache' ), ], [ 'id' => 'retainmeasurements', 'label' => __( 'Retain measurements for', 'sqlite-object-cache' ), 'description' => __( 'hours.', 'sqlite-object-cache' ), 'type' => 'number', 'default' => 2, 'min' => 0.1, 'step' => 'any', 'cssclass' => 'narrow', 'placeholder' => __( 'Hours to retain.', 'sqlite-object-cache' ), ], ], ]; $settings['stats'] = [ 'title' => __( 'Statistics', 'sqlite-object-cache' ), 'submit' => __( 'Reset Statistics', 'sqlite-object-cache' ), 'render_section_header' => [ $this, 'stats_section_header' ], 'form_post_callback' => [ $this, 'validate_reset_stats' ], ]; return apply_filters( $this->parent->_token . '_settings_fields', $settings ); } /** * Validate the options presented to the Settings tab. * * This is an options update filter. It filters an option value following sanitization. * * @param mixed $option The sanitized option value. * @param string $name The option name. * @param string $original_value The original value passed to the function. * * @throws Exception Announce SQLite failure. * @since 2.3.0 * @since 4.3.0 Added the `$original_value` parameter. * * @noinspection PhpUnusedParameterInspection */ public function validate_settings( $option, $name, $original_value ) { if ( ! is_array( $option ) ) { /* weird. not an option array */ return $option; } global $wp_object_cache; if ( array_key_exists( 'flush', $option ) && $option ['flush'] === 'on' ) { if ( method_exists( $wp_object_cache, 'flush' ) ) { $wp_object_cache->flush( true ); } unset ( $option['flush'] ); } $retention = $this->numeric_option( $option, 'retention', 7 ); if ( array_key_exists( 'cleanup', $option ) && $option ['cleanup'] === 'on' ) { $this->parent->clean(); unset ( $option['cleanup'] ); } $this->numeric_option( $option, 'frequency', 10 ); $this->numeric_option( $option, 'retainmeasurements', 2 ); if ( array_key_exists( 'capture', $option ) && $option['capture'] === 'on' ) { $option['previouscapture'] = 0; } return $option; } /** * Retrieve a numeric option, and set the default if it isn't present. * * @param array $option Option array value. * @param string $name Name of the element in the option array. * @param mixed $default Default value to use. * * @return float|int|mixed|string */ private function numeric_option( &$option, $name, $default ) { $result = $default; if ( array_key_exists( $name, $option ) && is_numeric( $option[ $name ] ) ) { $result = $option[ $name ]; $result = $result ?: $default; } else { $option[ $name ] = $default; } return $result; } /** * Filters an option value following sanitization. * * @param string $option The sanitized option value. * @param string $name The option name. * @param string $original_value The original value passed to the function. * * @throws Exception Announce SQLite failure. * @since 2.3.0 * @since 4.3.0 Added the `$original_value` parameter. * * @noinspection PhpUnusedParameterInspection */ public function validate_reset_stats( $option, $name, $original_value ) { global $wp_object_cache; if ( method_exists( $wp_object_cache, 'sqlite_reset_statistics' ) ) { $wp_object_cache->sqlite_reset_statistics(); } /* for this post operation, we don't want to change any plugin options. */ return get_option( $name ); } /** * Add settings page to admin menu * * @return void */ public function add_menu_item() { $args = $this->menu_settings(); // Do nothing if wrong location key is set. if ( is_array( $args ) && isset( $args['location'] ) && function_exists( 'add_' . $args['location'] . '_page' ) ) { switch ( $args['location'] ) { case 'options': case 'submenu': $page = add_submenu_page( $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] ); break; case 'menu': $page = add_menu_page( $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'], $args['icon_url'], $args['position'] ); break; default: return; } add_action( 'admin_print_styles-' . $page, [ $this, 'settings_assets' ] ); } } /** * Prepare default settings page arguments * * @return mixed|void */ private function menu_settings() { $this->complain_if_sqlite3_unavailable(); return apply_filters( $this->base . 'menu_settings', [ 'location' => 'options', // Possible settings: options, menu, submenu. 'parent_slug' => 'options-general.php', 'page_title' => __( 'SQLite Persistent Object Cache', 'sqlite-object-cache' ), 'menu_title' => __( 'Object Cache', 'sqlite-object-cache' ), 'capability' => 'manage_options', 'menu_slug' => $this->parent->_token . '_settings', 'function' => [ $this, 'settings_page' ], 'icon_url' => '', 'position' => null, ] ); } /** * Emit a message if SQLite3 is not available. * * @param bool $verbose False means emit a notice. True means emit a longer explanation. * * @return void */ private function complain_if_sqlite3_unavailable( $verbose = false ) { if ( true !== $this->has ) { if ( ! $verbose ) { echo '
'; if ( ! class_exists( 'SQLite3' ) || ! extension_loaded( 'sqlite3' ) ) { echo esc_html__( 'The SQLite Persistent Object Cache plugin requires php\'s SQLite3 extension.', 'sqlite-object-cache' ) . ' '; echo esc_html__( 'That extension is not installed in your server, so the plugin cannot work.', 'sqlite-object-cache' ) . ' '; } $sqlite_version = $this->parent->sqlite_get_version(); if ( version_compare( $sqlite_version, $this->parent->minimum_sqlite_version ) < 0 ) { echo esc_html( sprintf( /* translators: 1 actual SQLite version. 2 required SQLite version) */ __( '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' ), $sqlite_version, $this->parent->minimum_sqlite_version ) ); } echo '
' . esc_html( $this->settings[ $section['id'] ]['description'] ) . '
' . PHP_EOL; } } /** * Display support and rating links. * * @return void */ private function support_links() { $supportUrl = "https://wordpress.org/support/plugin/sqlite-object-cache/"; $reviewUrl = "https://wordpress.org/support/plugin/sqlite-object-cache/reviews/"; echo ''; echo esc_html__( 'For support please', 'sqlite-object-cache' ) . ' '; echo '' . esc_html__( 'click here', 'sqlite-object-cache' ) . '. '; echo esc_html__( 'To rate this plugin please', 'sqlite-object-cache' ) . ' '; echo '' . esc_html__( 'click here', 'sqlite-object-cache' ) . '. '; echo esc_html__( 'Your feedback helps make it better, faster, and more useful', 'sqlite-object-cache' ) . '.'; echo '
'; } /** * Display versions. * * @return void * @throws Exception Announce database failure. */ private function versions() { global $wp_object_cache; if ( method_exists( $wp_object_cache, 'sqlite_get_version' ) ) { echo '' . esc_html( sprintf( /* translators: 1: version for sqlite 2: version for php 3: version for plugin */ __( 'Versions: SQLite: %1$s php: %2$s Plugin: %3$s.', 'sqlite-object-cache' ), $wp_object_cache->sqlite_get_version(), PHP_VERSION, $this->parent->_version ) ) . '
'; } } /** * Statistics tab section. * * @param array $section Array of section ids. * * @return void * @throws Exception Announce Database Failure. * @noinspection PhpUnusedParameterInspection */ public function stats_section_header( $section ) { $this->support_links(); $this->versions(); $stats = new SQLite_Object_Cache_Statistics (); $stats->init(); $stats->render(); } /** * Load settings page content. * * @return void */ public function settings_page() { /* get the tab chosen by the user ('standard' by default or 'stats') */ $tab = isset ( $_REQUEST['tab'] ) ? sanitize_key( $_REQUEST['tab'] ) : 'standard'; // Build page HTML. echo '