From 0ec36ce0858450516cd66d3312266f331ae077a6 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 15:44:46 +0200 Subject: [PATCH 01/93] phpcbf auto fixes --- includes/class-plugin.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index 801503b0..4ce2e3bb 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -279,8 +279,8 @@ public function enqueue_redis_metrics() { ); wp_localize_script( 'redis-cache', 'rediscache_metrics', $metrics ); - } catch (Exception $exception) { - error_log($exception); + } catch ( Exception $exception ) { + error_log( $exception ); } } @@ -518,12 +518,14 @@ public function do_admin_actions() { $result ? add_settings_error( 'redis-cache', - 'dropin', __( 'Object cache disabled.', 'redis-cache' ), + 'dropin', + __( 'Object cache disabled.', 'redis-cache' ), 'updated' ) : add_settings_error( 'redis-cache', - 'dropin', __( 'Object cache could not be disabled.', 'redis-cache' ), + 'dropin', + __( 'Object cache could not be disabled.', 'redis-cache' ), 'error' ); } @@ -552,7 +554,6 @@ public function do_admin_actions() { 'error' ); } - } $messages = get_settings_errors( 'redis-cache' ); @@ -683,8 +684,8 @@ public function record_metrics() { time(), http_build_query( $metrics, null, ';' ) ); - } catch (Exception $exception) { - error_log($exception); + } catch ( Exception $exception ) { + error_log( $exception ); } } @@ -709,8 +710,8 @@ public function discard_metrics() { 0, time() - HOUR_IN_SECONDS ); - } catch (Exception $exception) { - error_log($exception); + } catch ( Exception $exception ) { + error_log( $exception ); } } @@ -791,9 +792,8 @@ public function initialize_filesystem( $url, $silent = false ) { return true; } - public function test_filesystem_writing() - { - global $wp_filesystem; + public function test_filesystem_writing() { + global $wp_filesystem; if ( ! $this->initialize_filesystem( '', true ) ) { return new WP_Error( 'fs', __( 'Could not initialize filesystem.', 'redis-cache' ) ); From 2ecd9543714362462a29d3f85c811f94384b286a Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 15:45:54 +0200 Subject: [PATCH 02/93] added property and method comments --- includes/class-plugin.php | 234 +++++++++++++++++++++++++++++++++++--- 1 file changed, 218 insertions(+), 16 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index 4ce2e3bb..073b1dfc 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -12,12 +12,30 @@ defined( '\\ABSPATH' ) || exit; +/** + * Main plugin class definition + */ class Plugin { - private $page; + /** + * Settings page uri + * + * @var string $page + */ + private $page = ''; + /** + * Settings page slug + * + * @var string $screen + */ private $screen = ''; + /** + * Allowed setting page actions + * + * @var string[] $actions + */ private $actions = array( 'enable-cache', 'disable-cache', @@ -26,14 +44,14 @@ class Plugin { ); /** - * Plugin instance property. + * Plugin instance property * * @var Plugin */ private static $instance; /** - * Plugin instanciation method. + * Plugin instanciation method * * @return Plugin */ @@ -45,6 +63,9 @@ public static function instance() { return self::$instance; } + /** + * Constructor + */ private function __construct() { require_once ABSPATH . 'wp-admin/includes/plugin.php'; @@ -66,6 +87,11 @@ private function __construct() { } } + /** + * Adds all necessary hooks + * + * @return void + */ public function add_actions_and_filters() { add_action( 'deactivate_plugin', array( $this, 'on_deactivation' ) ); add_action( 'admin_init', array( $this, 'maybe_update_dropin' ) ); @@ -97,8 +123,12 @@ public function add_actions_and_filters() { add_filter( 'qm/outputter/html', array( $this, 'register_qm_output' ) ); } + /** + * Adds a submenu page to "Settings" + * + * @return void + */ public function add_admin_menu_page() { - // add sub-page to "Settings" add_submenu_page( is_multisite() ? 'settings.php' : 'options-general.php', __( 'Redis Object Cache', 'redis-cache' ), @@ -109,18 +139,23 @@ public function add_admin_menu_page() { ); } + /** + * Displays the settings page + * + * @return void + */ public function show_admin_page() { - // request filesystem credentials? + // Request filesystem credentials? if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) { $action = $_GET['action']; foreach ( $this->actions as $name ) { - // verify nonce + // Nonce verification. if ( $action === $name && wp_verify_nonce( $_GET['_wpnonce'], $action ) ) { $url = $this->action_link( $action ); if ( $this->initialize_filesystem( $url ) === false ) { - return; // request filesystem credentials + return; // Request filesystem credentials. } } } @@ -147,10 +182,15 @@ public function show_admin_page() { __( 'Diagnostics', 'redis-cache' ) ); - // show admin page + // Show the admin page. require_once WP_REDIS_PLUGIN_PATH . '/includes/ui/settings.php'; } + /** + * Adds the dashboard metrics widget + * + * @return void + */ public function setup_dashboard_widget() { if ( defined( 'WP_REDIS_DISABLE_METRICS' ) && WP_REDIS_DISABLE_METRICS ) { return; @@ -163,18 +203,33 @@ public function setup_dashboard_widget() { ); } + /** + * Displays the dashboard widget + * + * @return void + */ public function show_dashboard_widget() { require_once WP_REDIS_PLUGIN_PATH . '/includes/ui/widget.php'; } + /** + * Adds the settings page to the plugin action links on the plugin page + * + * @param string[] $links The current plugin action links. + * @return string[] + */ public function add_plugin_actions_links( $links ) { - // add settings link to plugin actions return array_merge( [ sprintf( '%s', network_admin_url( $this->page ), esc_html__( 'Settings', 'redis-cache' ) ) ], $links ); } + /** + * Enqueues admin style resources + * + * @return void + */ public function enqueue_admin_styles() { $screen = get_current_screen(); @@ -195,6 +250,11 @@ public function enqueue_admin_styles() { wp_enqueue_style( 'redis-cache', WP_REDIS_DIR . '/assets/css/admin.css', null, WP_REDIS_VERSION ); } + /** + * Enqueues admin script resources + * + * @return void + */ public function enqueue_admin_scripts() { $screen = get_current_screen(); @@ -242,6 +302,11 @@ public function enqueue_admin_scripts() { ); } + /** + * Enqueues scripts to display recorded metrics + * + * @return void + */ public function enqueue_redis_metrics() { global $wp_object_cache; @@ -284,12 +349,24 @@ public function enqueue_redis_metrics() { } } + /** + * Registers a new cache collector for the Query Monitor plugin + * + * @param array $collectors Array of currently registered collectors. + * @return array + */ public function register_qm_collector( array $collectors ) { $collectors['cache'] = new QM_Collector(); return $collectors; } + /** + * Registers a new cache output using our collector for the Query Monitor plugin + * + * @param array $output Array of current QM_Output handlers. + * @return array + */ public function register_qm_output( $output ) { $collector = \QM_Collectors::get( 'cache' ); @@ -303,10 +380,20 @@ public function register_qm_output( $output ) { return $output; } + /** + * Checks if the `object-cache.php` drop-in exists + * + * @return bool + */ public function object_cache_dropin_exists() { return file_exists( WP_CONTENT_DIR . '/object-cache.php' ); } + /** + * Validates the `object-cache.php` drop-in + * + * @return bool + */ public function validate_object_cache_dropin() { if ( ! $this->object_cache_dropin_exists() ) { return false; @@ -318,6 +405,11 @@ public function validate_object_cache_dropin() { return $dropin['PluginURI'] === $plugin['PluginURI']; } + /** + * Checks if the `object-cache.php` drop-in is outdated + * + * @return bool + */ public function object_cache_dropin_outdated() { if ( ! $this->object_cache_dropin_exists() ) { return false; @@ -333,6 +425,11 @@ public function object_cache_dropin_outdated() { return false; } + /** + * Retrieves the current human-readable status + * + * @return string + */ public function get_status() { global $wp_object_cache; @@ -380,6 +477,12 @@ public function get_redis_status() { return $wp_object_cache->redis_status(); } + /** + * Returns the redis version if possible + * + * @see WP_Object_Cache::redis_version() + * @return null|string + */ public function get_redis_version() { global $wp_object_cache; @@ -392,6 +495,11 @@ public function get_redis_version() { } } + /** + * Returns the currently used redis client (if any) + * + * @return null|string + */ public function get_redis_client_name() { global $wp_object_cache; @@ -404,6 +512,11 @@ public function get_redis_client_name() { } } + /** + * Fetches the redis diagnostics data + * + * @return null|array + */ public function get_diagnostics() { global $wp_object_cache; @@ -412,21 +525,36 @@ public function get_diagnostics() { } } + /** + * Retrieves the redis prefix + * + * @return null|mixed + */ public function get_redis_prefix() { return defined( 'WP_REDIS_PREFIX' ) ? WP_REDIS_PREFIX : null; } + /** + * Retrieves the redis maximum time to live + * + * @return null|mixed + */ public function get_redis_maxttl() { return defined( 'WP_REDIS_MAXTTL' ) ? WP_REDIS_MAXTTL : null; } + /** + * Displays admin notices + * + * @return void + */ public function show_admin_notices() { if ( ! defined( 'WP_REDIS_DISABLE_BANNERS' ) || ! WP_REDIS_DISABLE_BANNERS ) { $this->pro_notice(); $this->wc_pro_notice(); } - // only show admin notices to users with the right capability + // Only show admin notices to users with the right capability. if ( ! current_user_can( is_multisite() ? 'manage_network_options' : 'manage_options' ) ) { return; } @@ -436,11 +564,11 @@ public function show_admin_notices() { if ( $this->validate_object_cache_dropin() ) { if ( $this->object_cache_dropin_outdated() ) { - // translators: %s = Action link to update the drop-in + // translators: %s = Action link to update the drop-in. $message = sprintf( __( 'The Redis object cache drop-in is outdated. Please update the drop-in.', 'redis-cache' ), $url ); } } else { - // translators: %s = Action link to update the drop-in + // translators: %s = Action link to update the drop-in. $message = sprintf( __( 'A foreign object cache drop-in was found. To use Redis for object caching, please enable the drop-in.', 'redis-cache' ), $url ); } @@ -450,13 +578,18 @@ public function show_admin_notices() { } } + /** + * Executes admin actions + * + * @return void + */ public function do_admin_actions() { global $wp_filesystem; if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) { $action = $_GET['action']; - // verify nonce + // Nonce verification. foreach ( $this->actions as $name ) { if ( $action === $name && ! wp_verify_nonce( $_GET['_wpnonce'], $action ) ) { return; @@ -570,6 +703,11 @@ public function do_admin_actions() { } } + /** + * Dismisses the admin notice for the current user + * + * @return void + */ public function dismiss_notice() { $notice = sprintf( 'roc_dismissed_%s', @@ -581,6 +719,11 @@ public function dismiss_notice() { wp_die(); } + /** + * Displays a redis cache pro admin notice + * + * @return void + */ public function pro_notice() { $screen = get_current_screen(); @@ -604,13 +747,18 @@ public function pro_notice() { '

%s %s

', __( 'Object Cache Pro is out!', 'redis-cache' ), sprintf( - // translators: %s = Link to the plugin setting screen + // translators: %s = Link to the plugin setting screen. __( 'A business class object cache backend. Truly reliable, highly-optimized and fully customizable, with a dedicated engineer when you most need it. Learn more »', 'redis-cache' ), network_admin_url( $this->page ) ) ); } + /** + * Displays a redis cache pro admin notice specifically for WooCommerce + * + * @return void + */ public function wc_pro_notice() { if ( ! class_exists( 'WooCommerce' ) ) { return; @@ -638,19 +786,29 @@ public function wc_pro_notice() { '

%s

%s

', __( 'Object Cache Pro + WooCommerce = ❤️', 'redis-cache' ), sprintf( - // translators: %s = Link to the plugin's settings screen + // translators: %s = Link to the plugin's settings screen. __( 'Object Cache Pro is a business class object cache that’s highly-optimized for WooCommerce to provide true reliability, peace of mind and faster load times for your store. Learn more »', 'redis-cache' ), network_admin_url( $this->page ) ) ); } + /** + * Registers all hooks associated with the shutdown hook + * + * @return void + */ public function register_shutdown_hooks() { if ( ! defined( 'WP_REDIS_DISABLE_COMMENT' ) || ! WP_REDIS_DISABLE_COMMENT ) { add_action( 'shutdown', array( $this, 'maybe_print_comment' ), 0 ); } } + /** + * Adds the recorded metrics to redis + * + * @return void + */ public function record_metrics() { global $wp_object_cache; @@ -689,6 +847,11 @@ public function record_metrics() { } } + /** + * Removes recorded metrics after an hour + * + * @return void + */ public function discard_metrics() { global $wp_object_cache; @@ -715,6 +878,11 @@ public function discard_metrics() { } } + /** + * Displays the redis cache html comment + * + * @return void + */ public function maybe_print_comment() { global $wp_object_cache; @@ -766,6 +934,13 @@ function_exists( 'size_format' ) ? size_format( $bytes ) : "{$bytes} bytes", printf( "\n", $message, $debug ); } + /** + * Initializes the WP filesystem API to be ready for use + * + * @param string $url The URL to post the form to. + * @param bool $silent Wheather to ask the user for credentials if necessary or not. + * @return bool + */ public function initialize_filesystem( $url, $silent = false ) { if ( $silent ) { ob_start(); @@ -792,8 +967,13 @@ public function initialize_filesystem( $url, $silent = false ) { return true; } + /** + * Test if we can write in the WP_CONTENT_DIR and modify the `object-cache.php` drop-in + * + * @return true|WP_Error + */ public function test_filesystem_writing() { - global $wp_filesystem; + global $wp_filesystem; if ( ! $this->initialize_filesystem( '', true ) ) { return new WP_Error( 'fs', __( 'Could not initialize filesystem.', 'redis-cache' ) ); @@ -833,6 +1013,11 @@ public function test_filesystem_writing() { return true; } + /** + * Calls the drop-in update method if necessary + * + * @return void + */ public function maybe_update_dropin() { if ( defined( 'WP_REDIS_DISABLE_DROPIN_AUTOUPDATE' ) && WP_REDIS_DISABLE_DROPIN_AUTOUPDATE ) { return; @@ -843,6 +1028,11 @@ public function maybe_update_dropin() { } } + /** + * Updates the `object-cache.php` drop-in + * + * @return void + */ public function update_dropin() { global $wp_filesystem; @@ -862,6 +1052,12 @@ public function update_dropin() { } } + /** + * Plugin deactivation hook + * + * @param string $plugin Plugin basename. + * @return void + */ public function on_deactivation( $plugin ) { global $wp_filesystem; @@ -882,6 +1078,12 @@ public function on_deactivation( $plugin ) { ob_end_clean(); } + /** + * Helper method to retrieve a nonced plugin action link + * + * @param string $action The action to be executed once the link is followed + * @return string + */ public function action_link( $action ) { return wp_nonce_url( network_admin_url( add_query_arg( 'action', $action, $this->page ) ), From ad7a2be36932fa67640803977c510fcc051ab892 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 16:24:10 +0200 Subject: [PATCH 03/93] ignore phpcs error_log function sniff --- includes/class-plugin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index 073b1dfc..a361ba7a 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -345,7 +345,7 @@ public function enqueue_redis_metrics() { wp_localize_script( 'redis-cache', 'rediscache_metrics', $metrics ); } catch ( Exception $exception ) { - error_log( $exception ); + error_log( $exception ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log } } @@ -843,7 +843,7 @@ public function record_metrics() { http_build_query( $metrics, null, ';' ) ); } catch ( Exception $exception ) { - error_log( $exception ); + error_log( $exception ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log } } @@ -874,7 +874,7 @@ public function discard_metrics() { time() - HOUR_IN_SECONDS ); } catch ( Exception $exception ) { - error_log( $exception ); + error_log( $exception ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log } } From c1c2ed596092d1ec1ea9cc014096b150016a5df7 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 15:57:44 +0200 Subject: [PATCH 04/93] Added html comment output escaping --- includes/class-plugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index a361ba7a..4a5df96a 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -916,7 +916,7 @@ public function maybe_print_comment() { ); if ( ! WP_DEBUG ) { - printf( "\n\n", $message ); + printf( "\n\n", esc_html( $message ) ); return; } @@ -931,7 +931,7 @@ function_exists( 'size_format' ) ? size_format( $bytes ) : "{$bytes} bytes", $wp_object_cache->diagnostics['client'] ); - printf( "\n", $message, $debug ); + printf( "\n", esc_html( $message ), esc_html( $debug ) ); } /** From a7c2928b0aaff425ae7f9d731b991b182ee67894 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 16:09:58 +0200 Subject: [PATCH 05/93] yoda style conditions --- includes/class-plugin.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index 4a5df96a..ca3850cd 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -599,7 +599,7 @@ public function do_admin_actions() { if ( in_array( $action, $this->actions ) ) { $url = $this->action_link( $action ); - if ( $action === 'flush-cache' ) { + if ( 'flush-cache' === $action ) { wp_cache_flush() ? add_settings_error( 'redis-cache', @@ -618,7 +618,7 @@ public function do_admin_actions() { // do we have filesystem credentials? if ( $this->initialize_filesystem( $url, true ) ) { - if ( $action === 'enable-cache' ) { + if ( 'enable-cache' === $action ) { $result = $wp_filesystem->copy( WP_REDIS_PLUGIN_PATH . '/includes/object-cache.php', WP_CONTENT_DIR . '/object-cache.php', @@ -643,7 +643,7 @@ public function do_admin_actions() { ); } - if ( $action === 'disable-cache' ) { + if ( 'disable-cache' === $action ) { $result = $wp_filesystem->delete( WP_CONTENT_DIR . '/object-cache.php' ); do_action( 'redis_object_cache_disable', $result ); @@ -663,7 +663,7 @@ public function do_admin_actions() { ); } - if ( $action === 'update-dropin' ) { + if ( 'update-dropin' === $action ) { $result = $wp_filesystem->copy( WP_REDIS_PLUGIN_PATH . '/includes/object-cache.php', WP_CONTENT_DIR . '/object-cache.php', @@ -1002,7 +1002,7 @@ public function test_filesystem_writing() { $meta = get_file_data( $testfile, [ 'Version' => 'Version' ] ); - if ( $meta['Version'] !== WP_REDIS_VERSION ) { + if ( WP_REDIS_VERSION !== $meta['Version'] ) { return new WP_Error( 'version', __( 'Couldn’t verify test file contents.', 'redis-cache' ) ); } @@ -1063,7 +1063,7 @@ public function on_deactivation( $plugin ) { ob_start(); - if ( $plugin === WP_REDIS_BASENAME ) { + if ( WP_REDIS_BASENAME === $plugin ) { if ( $timestamp = wp_next_scheduled( 'rediscache_discard_metrics' ) ) { wp_unschedule_event( $timestamp, 'rediscache_discard_metrics' ); } From 49038590c04669aacc330fdc74a451b333d74bb1 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 17:47:35 +0200 Subject: [PATCH 06/93] Added additional output escaping for admin notices --- includes/class-plugin.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index ca3850cd..8390ff41 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -573,7 +573,7 @@ public function show_admin_notices() { } if ( isset( $message ) ) { - printf( '
%s
', $message ); + printf( '
%s
', wp_kses_post( $message ) ); } } } @@ -745,11 +745,11 @@ public function pro_notice() { printf( '

%s %s

', - __( 'Object Cache Pro is out!', 'redis-cache' ), + esc_html__( 'Object Cache Pro is out!', 'redis-cache' ), sprintf( // translators: %s = Link to the plugin setting screen. - __( 'A business class object cache backend. Truly reliable, highly-optimized and fully customizable, with a dedicated engineer when you most need it. Learn more »', 'redis-cache' ), - network_admin_url( $this->page ) + wp_kses_post( __( 'A business class object cache backend. Truly reliable, highly-optimized and fully customizable, with a dedicated engineer when you most need it. Learn more »', 'redis-cache' ) ), + esc_url( network_admin_url( $this->page ) ) ) ); } @@ -784,11 +784,11 @@ public function wc_pro_notice() { printf( '

%s

%s

', - __( 'Object Cache Pro + WooCommerce = ❤️', 'redis-cache' ), + esc_html__( 'Object Cache Pro + WooCommerce = ❤️', 'redis-cache' ), sprintf( // translators: %s = Link to the plugin's settings screen. - __( 'Object Cache Pro is a business class object cache that’s highly-optimized for WooCommerce to provide true reliability, peace of mind and faster load times for your store. Learn more »', 'redis-cache' ), - network_admin_url( $this->page ) + wp_kses_post( __( 'Object Cache Pro is a business class object cache that’s highly-optimized for WooCommerce to provide true reliability, peace of mind and faster load times for your store. Learn more »', 'redis-cache' ) ), + esc_url( network_admin_url( $this->page ) ) ) ); } From 1a04958a358ed5049e811009847127d036c3a81c Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 17:50:15 +0200 Subject: [PATCH 07/93] strict comparisson for in_array --- includes/class-plugin.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index 8390ff41..d7446932 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -243,7 +243,7 @@ public function enqueue_admin_styles() { 'dashboard-network', ); - if ( ! in_array( $screen->id, $screens ) ) { + if ( ! in_array( $screen->id, $screens, true ) ) { return; } @@ -271,7 +271,7 @@ public function enqueue_admin_scripts() { 'woocommerce_page_wc-admin', ); - if ( ! in_array( $screen->id, $screens ) ) { + if ( ! in_array( $screen->id, $screens, true ) ) { return; } @@ -320,7 +320,7 @@ public function enqueue_redis_metrics() { return; } - if ( ! in_array( $screen->id, array( $this->screen, 'dashboard', 'dashboard-network' ) ) ) { + if ( ! in_array( $screen->id, array( $this->screen, 'dashboard', 'dashboard-network' ), true ) ) { return; } @@ -596,7 +596,7 @@ public function do_admin_actions() { } } - if ( in_array( $action, $this->actions ) ) { + if ( in_array( $action, $this->actions, true ) ) { $url = $this->action_link( $action ); if ( 'flush-cache' === $action ) { @@ -731,7 +731,7 @@ public function pro_notice() { return; } - if ( ! in_array( $screen->id, array( 'dashboard', 'dashboard-network' ) ) ) { + if ( ! in_array( $screen->id, array( 'dashboard', 'dashboard-network' ), true ) ) { return; } @@ -770,7 +770,7 @@ public function wc_pro_notice() { return; } - if ( ! in_array( $screen->id, array( 'edit-shop_order', 'edit-product', 'woocommerce_page_wc-admin' ) ) ) { + if ( ! in_array( $screen->id, array( 'edit-shop_order', 'edit-product', 'woocommerce_page_wc-admin' ), true ) ) { return; } From a6d09bc0f5dfed1d3b389d1dbc1f76f5823afbe1 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 18:09:25 +0200 Subject: [PATCH 08/93] avoided assignments in comparisons --- includes/class-plugin.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index d7446932..975ecdca 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -946,7 +946,8 @@ public function initialize_filesystem( $url, $silent = false ) { ob_start(); } - if ( ( $credentials = request_filesystem_credentials( $url ) ) === false ) { + $credentials = request_filesystem_credentials( $url ); + if ( false === $credentials ) { if ( $silent ) { ob_end_clean(); } @@ -1064,7 +1065,8 @@ public function on_deactivation( $plugin ) { ob_start(); if ( WP_REDIS_BASENAME === $plugin ) { - if ( $timestamp = wp_next_scheduled( 'rediscache_discard_metrics' ) ) { + $timestamp = wp_next_scheduled( 'rediscache_discard_metrics' ); + if ( $timestamp ) { wp_unschedule_event( $timestamp, 'rediscache_discard_metrics' ); } From 3a4a741641c1aef7f6fec52755b43664f6a1ce99 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 18:11:22 +0200 Subject: [PATCH 09/93] changed script loading position to footer --- includes/class-plugin.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index 975ecdca..bfe23f71 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -279,7 +279,8 @@ public function enqueue_admin_scripts() { 'redis-cache', plugins_url( 'assets/js/admin.js', WP_REDIS_FILE ), array( 'jquery', 'underscore' ), - WP_REDIS_VERSION + WP_REDIS_VERSION, + true ); wp_localize_script( @@ -328,7 +329,8 @@ public function enqueue_redis_metrics() { 'redis-cache-charts', plugins_url( 'assets/js/apexcharts.min.js', WP_REDIS_FILE ), null, - WP_REDIS_VERSION + WP_REDIS_VERSION, + true ); if ( ! method_exists( $wp_object_cache, 'redis_instance' ) ) { From 6a16184322e7e2842a2bad956c43b953f2bcad1d Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 18:42:24 +0200 Subject: [PATCH 10/93] added additional sanitization and nonces --- assets/js/admin.js | 4 +++- includes/class-plugin.php | 34 ++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/assets/js/admin.js b/assets/js/admin.js index f7a7816b..760a36f6 100644 --- a/assets/js/admin.js +++ b/assets/js/admin.js @@ -449,9 +449,11 @@ function ( event ) { event.preventDefault(); + var $parent = $( this ).parent(); $.post( ajaxurl, { - notice: $( this ).parent().attr( 'data-dismissible' ), + notice: $parent.data( 'dismissible' ), action: 'roc_dismiss_notice', + _ajax_nonce: $parent.data( 'nonce' ), } ); } ); diff --git a/includes/class-plugin.php b/includes/class-plugin.php index bfe23f71..d633a784 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -147,11 +147,12 @@ public function add_admin_menu_page() { public function show_admin_page() { // Request filesystem credentials? if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) { - $action = $_GET['action']; + $action = sanitize_key( $_GET['action'] ); + $nonce = sanitize_key( $_GET['_wpnonce'] ); foreach ( $this->actions as $name ) { // Nonce verification. - if ( $action === $name && wp_verify_nonce( $_GET['_wpnonce'], $action ) ) { + if ( $action === $name && wp_verify_nonce( $nonce, $action ) ) { $url = $this->action_link( $action ); if ( $this->initialize_filesystem( $url ) === false ) { @@ -589,11 +590,12 @@ public function do_admin_actions() { global $wp_filesystem; if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) { - $action = $_GET['action']; + $action = sanitize_key( $_GET['action'] ); + $nonce = sanitize_key( $_GET['_wpnonce'] ); // Nonce verification. foreach ( $this->actions as $name ) { - if ( $action === $name && ! wp_verify_nonce( $_GET['_wpnonce'], $action ) ) { + if ( $action === $name && ! wp_verify_nonce( $nonce, $action ) ) { return; } } @@ -711,12 +713,15 @@ public function do_admin_actions() { * @return void */ public function dismiss_notice() { - $notice = sprintf( - 'roc_dismissed_%s', - sanitize_key( $_POST['notice'] ) - ); + if ( isset( $_POST['notice'] ) ) { + check_ajax_referer( 'roc_dismiss_notice' ); + $notice = sprintf( + 'roc_dismissed_%s', + sanitize_key( $_POST['notice'] ) + ); - update_user_meta( get_current_user_id(), $notice, '1' ); + update_user_meta( get_current_user_id(), $notice, '1' ); + } wp_die(); } @@ -746,7 +751,8 @@ public function pro_notice() { } printf( - '

%s %s

', + '

%s %s

', + esc_attr( wp_create_nonce( 'roc_dismiss_notice' ) ), esc_html__( 'Object Cache Pro is out!', 'redis-cache' ), sprintf( // translators: %s = Link to the plugin setting screen. @@ -785,7 +791,8 @@ public function wc_pro_notice() { } printf( - '

%s

%s

', + '

%s

%s

', + esc_attr( wp_create_nonce( 'roc_dismiss_notice' ) ), esc_html__( 'Object Cache Pro + WooCommerce = ❤️', 'redis-cache' ), sprintf( // translators: %s = Link to the plugin's settings screen. @@ -1085,10 +1092,13 @@ public function on_deactivation( $plugin ) { /** * Helper method to retrieve a nonced plugin action link * - * @param string $action The action to be executed once the link is followed + * @param string $action The action to be executed once the link is followed. * @return string */ public function action_link( $action ) { + if ( ! in_array( $action, $this->actions, true ) ) { + return ''; + } return wp_nonce_url( network_admin_url( add_query_arg( 'action', $action, $this->page ) ), $action From 36eef2c6ba073b049b55c16965f222a7b4b52c10 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 18:38:17 +0200 Subject: [PATCH 11/93] switched to strict comparison --- includes/class-plugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index d633a784..cdb6abda 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -746,7 +746,7 @@ public function pro_notice() { return; } - if ( get_user_meta( get_current_user_id(), 'roc_dismissed_pro_release_notice', true ) == '1' ) { + if ( 1 === intval( get_user_meta( get_current_user_id(), 'roc_dismissed_pro_release_notice', true ) ) ) { return; } @@ -786,7 +786,7 @@ public function wc_pro_notice() { return; } - if ( get_user_meta( get_current_user_id(), 'roc_dismissed_wc_pro_notice', true ) == '1' ) { + if ( 1 === intval( get_user_meta( get_current_user_id(), 'roc_dismissed_wc_pro_notice', true ) ) ) { return; } From ff517245a72d847342d7e8c914147b1932829df3 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 18:39:07 +0200 Subject: [PATCH 12/93] ignored warning & added todo for `serialize` function --- includes/class-plugin.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/class-plugin.php b/includes/class-plugin.php index cdb6abda..7a986715 100644 --- a/includes/class-plugin.php +++ b/includes/class-plugin.php @@ -930,7 +930,8 @@ public function maybe_print_comment() { return; } - $bytes = strlen( serialize( $wp_object_cache->cache ) ); + // TODO: find a better method to determine cache size as using `serialize` is discouraged. + $bytes = strlen( serialize( $wp_object_cache->cache ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize $debug = sprintf( // translators: %1$d = number of objects. %2$s = human-readable size of cache. %3$s = name of the used client. From c6eed5b95f9414e24919dadd014b1df9d6ca3bb7 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 18:54:22 +0200 Subject: [PATCH 13/93] one function argument per line --- includes/class-ui.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/includes/class-ui.php b/includes/class-ui.php index 4d338807..79a50287 100644 --- a/includes/class-ui.php +++ b/includes/class-ui.php @@ -30,13 +30,16 @@ class UI { * @return void */ public static function register_tab( $slug, $label, $args = [] ) { - self::$tabs[ $slug ] = (object) wp_parse_args( $args, [ - 'label' => $label, - 'file' => WP_REDIS_PLUGIN_PATH . "/includes/ui/tabs/{$slug}.php", - 'slug' => $slug, - 'default' => false, - 'disabled' => false, - ] ); + self::$tabs[ $slug ] = (object) wp_parse_args( + $args, + [ + 'label' => $label, + 'file' => WP_REDIS_PLUGIN_PATH . "/includes/ui/tabs/{$slug}.php", + 'slug' => $slug, + 'default' => false, + 'disabled' => false, + ] + ); } /** From 75a72480197b0cffc8285818a4e9b377c53f0e16 Mon Sep 17 00:00:00 2001 From: naxvog Date: Sat, 15 Aug 2020 19:24:49 +0200 Subject: [PATCH 14/93] ui tab abstraction --- includes/class-ui.php | 11 +- includes/ui/class-tab.php | 219 +++++++++++++++++++++++++++++++ includes/ui/diagnostics.php | 14 +- includes/ui/settings.php | 30 ++--- includes/ui/tabs/diagnostics.php | 2 - includes/ui/tabs/overview.php | 42 +++--- 6 files changed, 263 insertions(+), 55 deletions(-) create mode 100644 includes/ui/class-tab.php diff --git a/includes/class-ui.php b/includes/class-ui.php index 79a50287..b251dcce 100644 --- a/includes/class-ui.php +++ b/includes/class-ui.php @@ -30,16 +30,7 @@ class UI { * @return void */ public static function register_tab( $slug, $label, $args = [] ) { - self::$tabs[ $slug ] = (object) wp_parse_args( - $args, - [ - 'label' => $label, - 'file' => WP_REDIS_PLUGIN_PATH . "/includes/ui/tabs/{$slug}.php", - 'slug' => $slug, - 'default' => false, - 'disabled' => false, - ] - ); + self::$tabs[ $slug ] = new UI\Tab( $slug, $label, $args ); } /** diff --git a/includes/ui/class-tab.php b/includes/ui/class-tab.php new file mode 100644 index 00000000..7759cd12 --- /dev/null +++ b/includes/ui/class-tab.php @@ -0,0 +1,219 @@ + $slug, + 'label' => $label, + 'file' => WP_REDIS_PLUGIN_PATH . "/includes/ui/tabs/{$slug}.php", + ] + ); + foreach ( $args ?: [] as $property => $value ) { + if ( property_exists( $this, $property ) ) { + $this->{$property} = $value; + } else { + $this->custom[ $property ] = $value; + } + } + } + + /** + * Getter for tab slug + * + * @return string + */ + public function slug() { + return $this->slug; + } + + /** + * Getter for tab label + * + * @return string + */ + public function label() { + return $this->label; + } + + /** + * Getter for tab file + * + * @return string + */ + public function file() { + return $this->file; + } + + /** + * Getter for tab disabled state + * + * @return bool + */ + public function is_disabled() { + return $this->disabled; + } + + /** + * Getter for tab default state + * + * @return bool + */ + public function is_default() { + return $this->default; + } + + /** + * Getter for tab custom data + * + * @param $string $key Custom data key. + * @return mixed + */ + public function custom( $key ) { + if ( ! isset( $this->custom[ $key ] ) ) { + return null; + } + return $this->custom[ $key ]; + } + + /** + * Disabled notice for tab + * + * @return string + */ + public function disabled_notice() { + return sprintf( + // translators: %s = Tab label. + __( '%s are disabled for this site.', 'redis-cache' ), + $this->label + ); + } + + /** + * Displays the tab template + * + * @return void + */ + public function display() { + $roc = Plugin::instance(); + include $this->file; + } + + /** + * Returns the tab nav id attribute + * + * @return string + */ + public function nav_id() { + return apply_filters( 'roc_tab_nav_id', "{$this->slug}-tab", $this ); + } + + /** + * Returns the tab nav css classes + * + * @return string + */ + public function nav_classes() { + $classes = [ + 'nav-tab', + ]; + if ( $this->default ) { + $classes[] = 'nav-tab-active'; + } + if ( $this->disabled ) { + $classes[] = 'nav-tab-disabled'; + } + return implode( ' ', apply_filters( 'roc_tab_nav_classes', $classes, $this ) ); + } + + /** + * Returns the tab id attribute + * + * @return string + */ + public function id() { + return apply_filters( 'roc_tab_id', "{$this->slug}-pane", $this ); + } + + /** + * Returns the tab css classes + * + * @return string + */ + public function classes() { + $classes = [ + 'tab-pane', + "tab-pane-{$this->slug}", + ]; + if ( $this->default ) { + $classes[] = 'active'; + } + return implode( ' ', apply_filters( 'roc_tab_classes', $classes, $this ) ); + } + +} diff --git a/includes/ui/diagnostics.php b/includes/ui/diagnostics.php index ce3cb1a0..f8720192 100644 --- a/includes/ui/diagnostics.php +++ b/includes/ui/diagnostics.php @@ -10,14 +10,14 @@ global $wp_object_cache; $info = []; -$filesystem = $plugin->test_filesystem_writing(); -$dropin = $plugin->validate_object_cache_dropin(); +$filesystem = $roc->test_filesystem_writing(); +$dropin = $roc->validate_object_cache_dropin(); $disabled = defined( 'WP_REDIS_DISABLED' ) && WP_REDIS_DISABLED; -$info['Status'] = $plugin->get_status(); -$info['Client'] = $plugin->get_redis_client_name(); -$info['Drop-in'] = $plugin->object_cache_dropin_exists() - ? ($dropin ? 'Valid' : 'Invalid') +$info['Status'] = $roc->get_status(); +$info['Client'] = $roc->get_redis_client_name(); +$info['Drop-in'] = $roc->object_cache_dropin_exists() + ? ( $dropin ? 'Valid' : 'Invalid' ) : 'Not installed'; $info['Disabled'] = $disabled ? 'Yes' : 'No'; $info['Filesystem'] = is_wp_error( $filesystem ) ? $filesystem->get_error_message() : 'Working'; @@ -52,7 +52,7 @@ } $info['Plugin Version'] = WP_REDIS_VERSION; -$info['Redis Version'] = $plugin->get_redis_version() ?: 'Unknown'; +$info['Redis Version'] = $roc->get_redis_version() ?: 'Unknown'; $info['Multisite'] = is_multisite() ? 'Yes' : 'No'; diff --git a/includes/ui/settings.php b/includes/ui/settings.php index 2632a36d..9ba99cd7 100644 --- a/includes/ui/settings.php +++ b/includes/ui/settings.php @@ -26,28 +26,24 @@