Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support changing autoload value for largest autoloaded options in Site Health check #1048

Merged
merged 20 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/php-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
wp: [ 'latest' ]
include:
- php: '7.4'
wp: '6.3'
wp: '6.4'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mukeshpanchal27 @swissspidy Strange that this is not failing in trunk 🤔

But anyway, great to fix here.

- php: '8.3'
wp: 'trunk'
env:
Expand Down
81 changes: 76 additions & 5 deletions includes/site-health/audit-autoloaded-options/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function perflab_aao_autoloaded_options_test() {
'<p>' . esc_html( $base_description ) . ' ' . __( 'Your site has %1$s autoloaded options (size: %2$s) in the options table, which could cause your site to be slow. You can reduce the number of autoloaded options by cleaning up your site\'s options table.', 'performance-lab' ) . '</p>',
$autoloaded_options_count,
size_format( $autoloaded_options_size )
) . perflab_aao_get_autoloaded_options_table();
) . perflab_aao_get_autoloaded_options_table() . perflab_aao_get_disabled_autoloaded_options_table();

/**
* Filters description to be shown on Site Health warning when threshold is met.
Expand Down Expand Up @@ -144,13 +144,84 @@ function perflab_aao_get_autoloaded_options_table() {
$autoload_summary = perflab_aao_query_autoloaded_options();

$html_table = sprintf(
'<table class="widefat striped"><thead><tr><th scope="col">%s</th><th scope="col">%s</th></tr></thead><tbody>',
__( 'Option Name', 'performance-lab' ),
__( 'Size', 'performance-lab' )
'<table class="widefat striped"><thead><tr><th scope="col">%s</th><th scope="col">%s</th><th scope="col">%s</th></tr></thead><tbody>',
esc_html__( 'Option Name', 'performance-lab' ),
esc_html__( 'Size', 'performance-lab' ),
esc_html__( 'Action', 'performance-lab' )
);

$nonce = wp_create_nonce( 'perflab_aao_update_autoload' );
foreach ( $autoload_summary as $value ) {
$html_table .= sprintf( '<tr><td>%s</td><td>%s</td></tr>', $value->option_name, size_format( $value->option_value_length, 2 ) );
$url = esc_url_raw(
add_query_arg(
array(
'action' => 'perflab_aao_update_autoload',
'_wpnonce' => $nonce,
'option_name' => $value->option_name,
'autoload' => 'false',
),
admin_url( 'site-health.php' )
)
);
$disable_button = sprintf( '<a class="button" href="%s">%s</a>', esc_url( $url ), esc_html__( 'Disable Autoload', 'performance-lab' ) );
$html_table .= sprintf( '<tr><td>%s</td><td>%s</td><td>%s</td></tr>', esc_html( $value->option_name ), size_format( $value->option_value_length, 2 ), $disable_button );
}
$html_table .= '</tbody></table>';

return $html_table;
}

/**
* Gets disabled autoload options table.
*
* @since n.e.x.t
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @return string HTML formatted table.
*/
function perflab_aao_get_disabled_autoloaded_options_table() {
global $wpdb;

$disabled_options = get_option( 'perflab_aao_disabled_options', array() );

if ( empty( $disabled_options ) ) {
return '';
}

mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved
$disabled_options_summary = $wpdb->get_results(
$wpdb->prepare(
sprintf(
"SELECT option_name, LENGTH(option_value) AS option_value_length FROM $wpdb->options WHERE option_name IN (%s) ORDER BY option_value_length DESC",
implode( ',', array_fill( 0, count( $disabled_options ), '%s' ) )
),
$disabled_options
)
);

$html_table = sprintf(
'<p>%s</p><table class="widefat striped"><thead><tr><th scope="col">%s</th><th scope="col">%s</th><th scope="col">%s</th></tr></thead><tbody>',
__( 'The following table shows the options for which you have previously disabled Autoload.', 'performance-lab' ),
esc_html__( 'Option Name', 'performance-lab' ),
esc_html__( 'Size', 'performance-lab' ),
esc_html__( 'Action', 'performance-lab' )
);

$nonce = wp_create_nonce( 'perflab_aao_update_autoload' );
foreach ( $disabled_options_summary as $value ) {
$url = esc_url_raw(
add_query_arg(
array(
'action' => 'perflab_aao_update_autoload',
'_wpnonce' => $nonce,
'option_name' => $value->option_name,
'autoload' => 'true',
),
admin_url( 'site-health.php' )
)
);
$disable_button = sprintf( '<a class="button" href="%s">%s</a>', esc_url( $url ), esc_html__( 'Revert to Autoload', 'performance-lab' ) );
$html_table .= sprintf( '<tr><td>%s</td><td>%s</td><td>%s</td></tr>', esc_html( $value->option_name ), size_format( $value->option_value_length, 2 ), $disable_button );
}
$html_table .= '</tbody></table>';

Expand Down
85 changes: 85 additions & 0 deletions includes/site-health/audit-autoloaded-options/hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,88 @@ function perflab_aao_add_autoloaded_options_test( $tests ) {
return $tests;
}
add_filter( 'site_status_tests', 'perflab_aao_add_autoloaded_options_test' );

/**
* Register admin actions for handling autoload enable/disable.
*
* @since n.e.x.t
*/
function perflab_aao_register_admin_actions() {
add_action( 'admin_action_perflab_aao_update_autoload', 'perflab_aao_handle_update_autoload' );
}
add_action( 'admin_init', 'perflab_aao_register_admin_actions' );

/**
* Callback for handling disable autoload action.
*
* @since n.e.x.t
*/
function perflab_aao_handle_update_autoload() {
check_admin_referer( 'perflab_aao_update_autoload' );

if ( ! isset( $_GET['option_name'], $_GET['autoload'] ) ) {
wp_die( esc_html__( 'Missing required parameter.', 'performance-lab' ) );
}

mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved
$option_name = sanitize_text_field( wp_unslash( $_GET['option_name'] ) );
$autoload = isset( $_GET['autoload'] ) ? rest_sanitize_boolean( $_GET['autoload'] ) : false;

if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Permission denied.', 'performance-lab' ) );
}

if ( empty( $option_name ) ) {
wp_die( esc_html__( 'Invalid option name.', 'performance-lab' ) );
}

// Check if the option exists.
if ( false === get_option( $option_name ) ) {
// Option doesn't exist, return an error or handle the situation accordingly.
wp_die( esc_html__( 'The option does not exist.', 'performance-lab' ) );
}

$result = wp_set_option_autoload( $option_name, $autoload );
mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved

if ( $result ) {
// Update disabled options list.
$disabled_options = get_option( 'perflab_aao_disabled_options', array() );

$key = array_search( $option_name, $disabled_options, true );
if ( ! $autoload && false === $key ) {
$disabled_options[] = $option_name;
} elseif ( $autoload && false !== $key ) {
unset( $disabled_options[ $key ] );
}

update_option( 'perflab_aao_disabled_options', $disabled_options );

if ( wp_safe_redirect( admin_url( 'site-health.php?autoload_updated=true' ) ) ) {
exit;
}
} else {
wp_die( esc_html__( 'Failed to disable autoload.', 'performance-lab' ) );
}
}

/**
* Callback function hooked to admin_notices to render admin notices on the site health screen.
*
* @since n.e.x.t
*
* @global string $pagenow The filename of the current screen.
*/
function perflab_aao_admin_notices() {
if ( 'site-health.php' !== $GLOBALS['pagenow'] ) {
return;
}

if ( isset( $_GET['autoload_updated'] ) && 'true' === $_GET['autoload_updated'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
wp_admin_notice(
esc_html__( 'The option has been successfully updated.', 'performance-lab' ),
array(
'type' => 'success',
)
);
}
}
add_action( 'admin_notices', 'perflab_aao_admin_notices' );
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,78 @@ public function test_perflab_aao_autoloaded_options_size() {
$this->assertSame( $autoloaded_options_size + $test_option_string_bytes, perflab_aao_autoloaded_options_size() );
}

public function test_perflab_aao_autoloaded_options_disable_revert_functionality() {

$user_id = self::factory()->user->create( array( 'role' => 'administrator' ) );
wp_set_current_user( $user_id );

// Mock wp_redirect to avoid actual redirection.
add_filter(
'wp_redirect',
static function () {
return false;
}
);

// Add an autoload option with small size length value for testing.
$test_option_string = 'test';
$test_option_string_bytes = mb_strlen( $test_option_string, '8bit' );
self::set_autoloaded_option( $test_option_string_bytes );

// Test that the autoloaded option is not displayed in the table because value lower then it's threshold value.
$table_html = perflab_aao_get_autoloaded_options_table();
$this->assertStringNotContainsString( self::AUTOLOADED_OPTION_KEY, $table_html );

// Delete autoloaded option.
self::delete_autoloaded_option();

// Add an autoload option with bigger size length value for testing.
self::set_autoloaded_option( self::WARNING_AUTOLOADED_SIZE_LIMIT_IN_BYTES );

$table_html = perflab_aao_get_autoloaded_options_table();
$this->assertStringContainsString( self::AUTOLOADED_OPTION_KEY, $table_html );

// Check disable autoloaded option functionality.
$_REQUEST['_wpnonce'] = wp_create_nonce( 'perflab_aao_update_autoload' );
$_GET['action'] = 'perflab_aao_update_autoload';
$_GET['option_name'] = self::AUTOLOADED_OPTION_KEY;
$_GET['autoload'] = 'false';

perflab_aao_handle_update_autoload();

// Test that the autoloaded option is not displayed in the perflab_aao_get_autoloaded_options_table() after disabling.
$table_html = perflab_aao_get_autoloaded_options_table();
$this->assertStringNotContainsString( self::AUTOLOADED_OPTION_KEY, $table_html );

// Test that the disabled autoloaded option is displayed in the disabled options perflab_aao_get_disabled_autoloaded_options_table().
$table_html = perflab_aao_get_disabled_autoloaded_options_table();
$this->assertStringContainsString( self::AUTOLOADED_OPTION_KEY, $table_html );

// Revert the disabled autoloaded option.
$_REQUEST['_wpnonce'] = wp_create_nonce( 'perflab_aao_update_autoload' );
$_GET['action'] = 'perflab_aao_update_autoload';
$_GET['option_name'] = self::AUTOLOADED_OPTION_KEY;
$_GET['autoload'] = 'true';

perflab_aao_handle_update_autoload();

// Test that the disabled autoloaded option is not displayed in the disabled options perflab_aao_get_disabled_autoloaded_options_table() after reverting.
$table_html = perflab_aao_get_disabled_autoloaded_options_table();
$this->assertStringNotContainsString( self::AUTOLOADED_OPTION_KEY, $table_html );

// Test that the reverted autoloaded option is displayed in the autoloaded options perflab_aao_get_autoloaded_options_table().
$table_html = perflab_aao_get_autoloaded_options_table();
$this->assertStringContainsString( self::AUTOLOADED_OPTION_KEY, $table_html );

// Remove the mock filter.
remove_filter(
'wp_redirect',
static function () {
return false;
}
);
}

/**
* Sets a test autoloaded option.
*
Expand Down