Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions inc/classes/class-imagify-admin-ajax-post.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
protected $post_only_actions = [
// Custom folders optimization.
'imagify_scan_custom_folders',
// Settings page.
'imagify_reset_internal_state',
// Various.
'imagify_dismiss_ad',
];
Expand Down Expand Up @@ -1135,6 +1137,31 @@ public function imagify_dismiss_ad_callback() {
wp_send_json_success();
}

/**
* Reset Imagify internal optimization state from the settings page.
*
* @since 2.2.8
*
* @return void
*/
public function imagify_reset_internal_state_callback() {
if ( ! imagify_get_context( 'wp' )->current_user_can( 'manage' ) ) {
imagify_die();
return;
}

imagify_check_nonce( 'imagify-reset-internal-state' );

$result = imagify_reset_internal_state();

if ( is_wp_error( $result ) ) {
imagify_maybe_redirect( $result );
return;
}

imagify_maybe_redirect( __( 'Imagify internal state has been reset.', 'imagify' ) );
}


/** ----------------------------------------------------------------------------------------- */
/** VARIOUS HELPERS ========================================================================= */
Expand Down
138 changes: 138 additions & 0 deletions inc/functions/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,144 @@
die();
}

/**
* Reset transient and queue data related to Imagify internal optimization state.
*
* This is intended for troubleshooting stuck optimization states without
* deleting user settings.
*
* @since 2.2.8
*
* @return bool|WP_Error True on success. WP_Error if any cleanup query failed.
*/
function imagify_reset_internal_state() {

Check warning on line 389 in inc/functions/admin.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

inc/functions/admin.php#L389

The function imagify_reset_internal_state() has 127 lines of code. Current threshold is set to 100. Avoid really long methods.

Check warning on line 389 in inc/functions/admin.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

inc/functions/admin.php#L389

The function imagify_reset_internal_state() has a Cyclomatic Complexity of 11. The configured cyclomatic complexity threshold is 10.

Check warning on line 389 in inc/functions/admin.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

inc/functions/admin.php#L389

The function imagify_reset_internal_state() has an NPath complexity of 288. The configured NPath complexity threshold is 200.
global $wpdb;

$errors = new WP_Error();

$site_transients = [
'imagify_check_licence_1',
'imagify_user',
'imagify_themes_plugins_to_sync',
'do_imagify_rating_cron',
'imagify_seen_rating_notice',
'imagify_user_images_count',
'imagify_check_api_version',
'imagify_optimize_media_process_lock',
];

$transients = [
'imagify_bulk_optimization_level',
'imagify_bulk_optimization_infos',
'imagify_bulk_optimization_result',
'imagify_bulk_optimization_complete',
'imagify_custom-folders_optimize_running',
'imagify_wp_optimize_running',
'imagify_missing_next_gen_total',
'imagify_large_library',
'imagify_max_image_size',
'imagify_user',
'imagify_stat_without_next_gen',
'imagify_attachments_number_modal',
'imagify_user_cache',
];

foreach ( $site_transients as $transient ) {
delete_site_transient( $transient );
}

foreach ( $transients as $transient ) {
delete_transient( $transient );
}

imagify_delete_cached_user();

$like_patterns = [
'_transient_%imagify-auto-optimize-%',
'_transient_timeout_%imagify-auto-optimize-%',
'_transient_%imagify\_rpc\_%',
'_transient_timeout_%imagify\_rpc\_%',
'_transient_imagify\_%\_process\_locked',
'_transient_timeout_imagify\_%\_process\_locked',
'_site_transient_imagify\_%\_process\_lock%',
'_site_transient_timeout_imagify\_%\_process\_lock%',
];

$options_sql = 'DELETE FROM ' . $wpdb->options . ' WHERE ' . implode( ' OR ', array_fill( 0, count( $like_patterns ), 'option_name LIKE %s' ) );
$deleted = $wpdb->query( $wpdb->prepare( $options_sql, $like_patterns ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

if ( false === $deleted ) {
$errors->add( 'imagify_reset_options_transients', __( 'An error occurred while clearing transient data.', 'imagify' ) );
}

$batch_prefix = $wpdb->esc_like( 'imagify_optimize_media_batch_' ) . '%';

if ( is_multisite() ) {
$network_id = get_current_network_id();

$sitemeta_patterns = [
$network_id,
$batch_prefix,
'imagify_optimize_media_status',
];

$sitemeta_sql = 'DELETE FROM ' . $wpdb->sitemeta . ' WHERE site_id = %d AND ( meta_key LIKE %s OR meta_key = %s )';
$deleted = $wpdb->query( $wpdb->prepare( $sitemeta_sql, $sitemeta_patterns ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

if ( false === $deleted ) {
$errors->add( 'imagify_reset_batches', __( 'An error occurred while clearing optimization batches.', 'imagify' ) );
}

$sitemeta_like_patterns = array_merge( [ $network_id ], $like_patterns );
$sitemeta_sql = 'DELETE FROM ' . $wpdb->sitemeta . ' WHERE site_id = %d AND (' . implode( ' OR ', array_fill( 0, count( $like_patterns ), 'meta_key LIKE %s' ) ) . ')';
$deleted = $wpdb->query( $wpdb->prepare( $sitemeta_sql, $sitemeta_like_patterns ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

if ( false === $deleted ) {
$errors->add( 'imagify_reset_sitemeta_transients', __( 'An error occurred while clearing network transient data.', 'imagify' ) );
}
} else {
$options_patterns = [
$batch_prefix,
'imagify_optimize_media_status',
];

$options_sql = 'DELETE FROM ' . $wpdb->options . ' WHERE option_name LIKE %s OR option_name = %s';
$deleted = $wpdb->query( $wpdb->prepare( $options_sql, $options_patterns ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

if ( false === $deleted ) {
$errors->add( 'imagify_reset_batches', __( 'An error occurred while clearing optimization batches.', 'imagify' ) );
}
}

// Cancel pending async jobs that can keep the UI in a stuck state.
if ( function_exists( 'as_unschedule_all_actions' ) ) {
$action_scheduler_groups = [
'imagify-wp-optimize-media',
'imagify-custom-folders-optimize-media',
'imagify-wp-convert-nextgen',
'imagify-custom-folders-convert-nextgen',
];

foreach ( $action_scheduler_groups as $group ) {
as_unschedule_all_actions( 'imagify_optimize_media', [], $group );
as_unschedule_all_actions( 'imagify_convert_next_gen', [], $group );
}

as_unschedule_all_actions( 'imagify_optimize_media' );
as_unschedule_all_actions( 'imagify_convert_next_gen' );
}

wp_clear_scheduled_hook( 'imagify_rating_event' );
wp_clear_scheduled_hook( 'imagify_update_library_size_calculations_event' );
wp_clear_scheduled_hook( 'imagify_optimize_media_cron' );

if ( ! $errors->has_errors() ) {
return true;
}

return $errors;
}

/**
* Get cached Imagify user data.
* This is usefull to prevent triggering an HTTP request to our server on every page load, but it can be used only where the data doesn't need to be in real time.
Expand Down
2 changes: 1 addition & 1 deletion views/page-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@
</div>
</div>
<?php endif; ?>
<?php $this->print_template( 'part-settings-troubleshooting' ); ?>
<?php
if ( Imagify_Requirements::is_api_key_valid() ) {
$this->print_template( 'part-settings-footer' );
Expand All @@ -200,4 +201,3 @@
?>

</div>

19 changes: 19 additions & 0 deletions views/part-settings-troubleshooting.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
defined( 'ABSPATH' ) || exit;

$reset_url = wp_nonce_url(
self_admin_url( 'admin-post.php?action=imagify_reset_internal_state' ),
'imagify-reset-internal-state'
);
?>
<div class="imagify-settings-section imagify-clear">
<h2 class="imagify-options-title"><?php esc_html_e( 'Troubleshooting', 'imagify' ); ?></h2>
<p>
<?php esc_html_e( 'If optimization appears stuck, reset Imagify internal state to clear transient and queue data without changing your settings.', 'imagify' ); ?>
</p>
<p>
<a class="button imagify-button-secondary" href="<?php echo esc_url( $reset_url ); ?>">
<?php esc_html_e( 'Reset internal state', 'imagify' ); ?>
</a>
</p>
</div>