options = $options; add_action( 'admin_init', [ $this, 'init' ] ); } /** * Option keys that only the Pro settings UI writes. * * @return string[] */ protected function get_pro_only_option_keys(): array { return [ 'delete_transient', 'deep_cleaning', 'continuous_cleaning', 'delete_revisions_day' ]; } /** * Start the engine running * * @return void */ public function init() { $this->settings_options = [ [ 'option_group' => DB_Cleaner::OPTION_NAME, 'option_name' => DB_Cleaner::OPTION_NAME, 'option_value' => $this->options, 'args' => [ 'sanitize_callback' => [ $this, 'sanitize_settings' ] ], ], ]; $this->settings_sections = [ [ 'id' => 'adminoptimizer-db-scheduler', 'title' => '', 'description' => '', 'menu_slug' => DB_Cleaner::OPTION_NAME, 'option_name' => DB_Cleaner::OPTION_NAME, 'fields' => [ [ 'type' => 'callback', 'id' => 'enable-db-cleanup', 'title' => __( 'Schedule Database Cleanup', 'admin-optimizer' ), 'callback' => [ $this, 'render_enable_cleanup_field' ], ], [ 'type' => 'checkbox', 'title' => __( 'Enable logs', 'admin-optimizer' ), 'id' => 'enable-logging', 'name' => 'enable_logging', 'label' => __( 'Keep a log of the execution of the database cleanup.', 'admin-optimizer' ), ], ], ], [ 'id' => 'adminoptimizer-db-cleanup', 'title' => __( 'Items to Clean Up', 'admin-optimizer' ), 'description' => '', 'menu_slug' => DB_Cleaner::OPTION_NAME, 'option_name' => DB_Cleaner::OPTION_NAME, 'fields' => [ [ 'type' => 'checkbox', 'title' => __( 'Post Revisions', 'admin-optimizer' ), 'id' => 'delete-revisions', 'name' => 'delete_revisions', 'label' => __( 'Delete all post revisions', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Auto Draft', 'admin-optimizer' ), 'id' => 'delete-auto-draft', 'name' => 'delete_auto_draft', 'label' => __( 'Delete auto draft.', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Trashed Posts', 'admin-optimizer' ), 'id' => 'delete-trashed-posts', 'name' => 'delete_trashed_posts', 'label' => __( 'Clean up trashed posts.', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Orphaned Post Meta', 'admin-optimizer' ), 'id' => 'delete-orphaned-postmeta', 'name' => 'delete_orphaned_postmeta', 'label' => __( 'Delete orphaned post meta', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Duplicate Post Meta', 'admin-optimizer' ), 'id' => 'delete-duplicate-postmeta', 'name' => 'delete_duplicate_postmeta', 'label' => __( 'Delete duplicate post meta', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Post Meta with empty value', 'admin-optimizer' ), 'id' => 'delete-empty-postmeta', 'name' => 'delete_empty_postmeta', 'label' => __( 'Delete unused post meta', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'oEmbed cache', 'admin-optimizer' ), 'id' => 'delete-oembed-cache', 'name' => 'delete_oembed_cache', 'label' => __( 'Delete oEmbed cache', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Unapproved Comments', 'admin-optimizer' ), 'id' => 'delete-unapproved-comments', 'name' => 'delete_unapproved_comments', 'label' => __( 'Delete all unapproved/pending comments', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Spam Comments', 'admin-optimizer' ), 'id' => 'delete-spam-comments', 'name' => 'delete_spam_comments', 'label' => __( 'Delete all spam comments', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Trashed Comments', 'admin-optimizer' ), 'id' => 'delete-trashed-comments', 'name' => 'delete_trashed_comments', 'label' => __( 'Delete all trashed comments', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Duplicate Comment Meta', 'admin-optimizer' ), 'id' => 'delete-duplicate-commentmeta', 'name' => 'delete_duplicate_commentmeta', 'label' => __( 'Delete duplicate comment meta', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Orphaned Comment Meta', 'admin-optimizer' ), 'id' => 'delete-orphaned-commentmeta', 'name' => 'delete_orphaned_commentmeta', 'label' => __( 'Delete orphaned comment meta', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Comment Meta with empty value', 'admin-optimizer' ), 'id' => 'delete-empty-commentmeta', 'name' => 'delete_empty_commentmeta', 'label' => __( 'Delete comment meta with empty value', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Pingbacks', 'admin-optimizer' ), 'id' => 'delete-pingbacks', 'name' => 'delete_pingbacks', 'label' => __( 'Delete pingbacks.', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Unused Terms', 'admin-optimizer' ), 'id' => 'delete-unused-terms', 'name' => 'delete_unused_terms', 'label' => __( 'Delete unused Terms (post tags and categories)', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Duplicate Term Meta', 'admin-optimizer' ), 'id' => 'delete-duplicate-termmeta', 'name' => 'delete_duplicate_termmeta', 'label' => __( 'Delete duplicate Term Meta', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Orphaned Term Meta', 'admin-optimizer' ), 'id' => 'delete-orphaned-termmeta', 'name' => 'delete_orphaned_termmeta', 'label' => __( 'Delete orphaned Term Meta', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Orphaned Term Relationship', 'admin-optimizer' ), 'id' => 'delete-orphaned-term-rs', 'name' => 'delete_orphaned_term_rs', 'label' => __( 'Delete orphaned Term relationship', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Duplicate User Meta', 'admin-optimizer' ), 'id' => 'delete-duplicate-usermeta', 'name' => 'delete_duplicate_usermeta', 'label' => __( 'Delete duplicate user meta', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Orphaned User Meta', 'admin-optimizer' ), 'id' => 'delete-orphaned-usermeta', 'name' => 'delete_orphaned_usermeta', 'label' => __( 'Delete orphaned user meta', 'admin-optimizer' ), ], ], ], [ 'id' => 'adminoptimizer-db-cleanup-settings', 'title' => __( 'Clean Up Settings', 'admin-optimizer' ), 'description' => '', 'menu_slug' => DB_Cleaner::OPTION_NAME, 'option_name' => DB_Cleaner::OPTION_NAME, 'fields' => [ [ 'type' => 'number', 'id' => 'batch-size', 'name' => 'batch_size', 'min' => 100, 'max' => 2000, 'default' => 500, 'title' => __( 'Batch job size', 'admin-optimizer' ), 'desc' => __( 'The maximum amount of entries to delete at the same time. As this is an intensive process, for a huge database, a big batch job size might crash the database. For a good server, 500 - 1000 is a good starting point. For a slow/shared hosting, start with 100 and increase gradually.', 'admin-optimizer' ), ], ], ], ]; if ( $this->is_pro_active() ) { $this->settings_sections = $this->replace_field( $this->settings_sections, 'adminoptimizer-db-cleanup', 'delete-revisions', [ 'type' => 'callback', 'id' => 'delete-revisions', 'title' => __( 'Post Revisions', 'admin-optimizer' ), 'callback' => [ $this, 'render_delete_revisions_field' ], ] ); $this->settings_sections = $this->inject_pro_fields( $this->settings_sections, 'adminoptimizer-db-cleanup', [ [ 'type' => 'radio', 'title' => __( 'Transient Objects', 'admin-optimizer' ), 'id' => 'delete-transient', 'name' => 'delete_transient', 'choices' => [ 'all' => __( 'Delete all transient object', 'admin-optimizer' ), 'expired' => __( 'Delete expired transient object', 'admin-optimizer' ), '0' => __( 'Do not delete transient object', 'admin-optimizer' ), ], 'desc' => __( 'Transient objects are temporary data in the database with a time limit. It doesn\'t always get deleted upon expiry, which can cause bloat to your database.', 'admin-optimizer' ), ], ] ); $this->settings_sections = $this->inject_pro_fields( $this->settings_sections, 'adminoptimizer-db-cleanup-settings', [ [ 'type' => 'checkbox', 'title' => __( 'Deep Cleaning', 'admin-optimizer' ), 'id' => 'deep-cleaning', 'name' => 'deep_cleaning', 'label' => __( 'Use WordPress internal functions to delete items. This will ensure no residual are left behind during the clean up.', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Continuous Cleaning', 'admin-optimizer' ), 'id' => 'continuous-cleaning', 'name' => 'continuous_cleaning', 'label' => __( 'Continue to clean the database in the background until all the unwanted items are removed. This is useful for a large database with lots of cruft.', 'admin-optimizer' ), ], ] ); } else { $this->settings_sections[] = [ 'id' => 'adminoptimizer-db-optimization-pro', 'title' => __( 'Pro Options', 'admin-optimizer' ), /* translators: %1$s is the anchor link to the Pro version. %2$s is the closing anchor tag */ 'description' => sprintf( __( 'Upgrade to the %1$sPro version%2$s to access these features', 'admin-optimizer' ), '', '' ), 'menu_slug' => DB_Cleaner::MENU_SLUG . '_pro', 'option_name' => DB_Cleaner::OPTION_NAME, 'args' => [ 'before_section' => '
', 'after_section' => '
', ], 'fields' => [ [ 'type' => 'callback', 'id' => 'delete-revisions-pro', 'title' => __( 'Post Revisions', 'admin-optimizer' ), 'callback' => [ $this, 'render_disabled_delete_revisions_field' ], ], [ 'type' => 'radio', 'title' => __( 'Transient Objects', 'admin-optimizer' ), 'id' => 'delete-transient-pro', 'name' => 'delete_transient_pro', 'choices' => [ 'all' => __( 'Delete all transient object', 'admin-optimizer' ), 'expired' => __( 'Delete expired transient object', 'admin-optimizer' ), '0' => __( 'Do not delete transient object', 'admin-optimizer' ), ], 'disabled' => 'disabled', 'desc' => __( 'Transient objects are temporary data in the database with a time limit. It doesn\'t always get deleted upon expiry, which can cause bloat to your database.', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Deep Cleaning', 'admin-optimizer' ), 'id' => 'deep-cleaning', 'name' => 'deep_cleaning', 'disabled' => 'disabled', 'label' => __( 'Items will be deleted using WordPress functions. This will ensure no residual are left being during the clean up.', 'admin-optimizer' ), ], [ 'type' => 'checkbox', 'title' => __( 'Continuous Cleaning', 'admin-optimizer' ), 'id' => 'continuous-cleaning', 'name' => 'continuous_cleaning', 'disabled' => 'disabled', 'label' => __( 'Continue to clean the database in the background until all the unwanted items are removed. This is useful for a large database with lots of cruft.', 'admin-optimizer' ), ], ], ]; } $this->setup(); } /** * Render enable database cleanup settings field * * @return void */ public function render_enable_cleanup_field() { $option_name = DB_Cleaner::OPTION_NAME; $enabled = $this->options['enable'] ?? '0'; $enabled_day = $this->options['enable_day'] ?? 'sunday'; $enabled_time_hour = $this->options['enable_time_hour'] ?? '12am'; $enabled_time_min = $this->options['enable_time_min'] ?? '00'; $day_select_field = ''; $hour_select_field = ''; $min_select_field = ''; ?>

options['delete_revisions_day'] ) ? absint( $this->options['delete_revisions_day'] ) : 30; $revision_option = $this->options['delete_revisions'] ?? ''; ?>



render_logs_on_page(); ?> render_manual_actions_tab(); ?> render_options_table_tab(); ?> render_settings_on_page( DB_Cleaner::OPTION_NAME ); ?> is_pro_active() ) : ?> render_settings_on_page( DB_Cleaner::MENU_SLUG . '_pro', [ 'remove_submit_button' => true ] ); ?>
is_pro_active(); if ( is_array( $options ) ) { if ( isset( $options['enable'] ) ) { $sanitized_options['enable'] = '1'; } if ( isset( $options['enable_day'] ) ) { $sanitized_options['enable_day'] = in_array( $options['enable_day'], [ 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ], true ) ? $options['enable_day'] : 'sunday'; if ( isset( $this->options['enable_day'] ) && $this->options['enable_day'] !== $sanitized_options['enable_day'] ) { if ( as_has_scheduled_action( 'adminoptim_database_cleanup' ) ) { as_unschedule_all_actions( 'adminoptim_database_cleanup' ); } } } if ( isset( $options['enable_time_hour'] ) ) { $sanitized_options['enable_time_hour'] = in_array( $options['enable_time_hour'], array_map( 'strval', range( '0', '23' ) ), true ) ? $options['enable_time_hour'] : '0'; if ( isset( $this->options['enable_time_hour'] ) && $this->options['enable_time_hour'] !== $sanitized_options['enable_time_hour'] ) { if ( as_has_scheduled_action( 'adminoptim_database_cleanup' ) ) { as_unschedule_all_actions( 'adminoptim_database_cleanup' ); } } } if ( isset( $options['enable_time_min'] ) ) { $sanitized_options['enable_time_min'] = in_array( $options['enable_time_min'], array_map( 'strval', range( '0', '59' ) ), true ) ? $options['enable_time_min'] : '0'; if ( isset( $this->options['enable_time_min'] ) && $this->options['enable_time_min'] !== $sanitized_options['enable_time_min'] ) { if ( as_has_scheduled_action( 'adminoptim_database_cleanup' ) ) { as_unschedule_all_actions( 'adminoptim_database_cleanup' ); } } } if ( $is_pro ) { if ( isset( $options['delete_revisions'] ) ) { $sanitized_options['delete_revisions'] = in_array( $options['delete_revisions'], [ 'all', 'custom', '0' ], true ) ? $options['delete_revisions'] : '0'; if ( 'custom' === $sanitized_options['delete_revisions'] && isset( $options['delete_revisions_day'] ) ) { $sanitized_options['delete_revisions_day'] = absint( $options['delete_revisions_day'] ); } } else { $sanitized_options['delete_revisions'] = '0'; } if ( isset( $options['delete_transient'] ) ) { $sanitized_options['delete_transient'] = in_array( $options['delete_transient'], [ '0', 'expired', 'all' ], true ) ? $options['delete_transient'] : '0'; } if ( isset( $options['deep_cleaning'] ) ) { $sanitized_options['deep_cleaning'] = '1'; } if ( isset( $options['continuous_cleaning'] ) ) { $sanitized_options['continuous_cleaning'] = '1'; } } elseif ( isset( $options['delete_revisions'] ) ) { $sanitized_options['delete_revisions'] = '1'; } if ( isset( $options['delete_auto_draft'] ) ) { $sanitized_options['delete_auto_draft'] = '1'; } if ( isset( $options['delete_trashed_posts'] ) ) { $sanitized_options['delete_trashed_posts'] = '1'; } if ( isset( $options['delete_orphaned_postmeta'] ) ) { $sanitized_options['delete_orphaned_postmeta'] = '1'; } if ( isset( $options['delete_duplicate_postmeta'] ) ) { $sanitized_options['delete_duplicate_postmeta'] = '1'; } if ( isset( $options['delete_empty_postmeta'] ) ) { $sanitized_options['delete_empty_postmeta'] = '1'; } if ( isset( $options['delete_oembed_cache'] ) ) { $sanitized_options['delete_oembed_cache'] = '1'; } if ( isset( $options['delete_unapproved_comments'] ) ) { $sanitized_options['delete_unapproved_comments'] = '1'; } if ( isset( $options['delete_spam_comments'] ) ) { $sanitized_options['delete_spam_comments'] = '1'; } if ( isset( $options['delete_trashed_comments'] ) ) { $sanitized_options['delete_trashed_comments'] = '1'; } if ( isset( $options['delete_duplicate_commentmeta'] ) ) { $sanitized_options['delete_duplicate_commentmeta'] = '1'; } if ( isset( $options['delete_orphaned_commentmeta'] ) ) { $sanitized_options['delete_orphaned_commentmeta'] = '1'; } if ( isset( $options['delete_empty_commentmeta'] ) ) { $sanitized_options['delete_empty_commentmeta'] = '1'; } if ( isset( $options['delete_pingbacks'] ) ) { $sanitized_options['delete_pingbacks'] = '1'; } if ( isset( $options['delete_unused_terms'] ) ) { $sanitized_options['delete_unused_terms'] = '1'; } if ( isset( $options['delete_duplicate_termmeta'] ) ) { $sanitized_options['delete_duplicate_termmeta'] = '1'; } if ( isset( $options['delete_orphaned_termmeta'] ) ) { $sanitized_options['delete_orphaned_termmeta'] = '1'; } if ( isset( $options['delete_orphaned_term_rs'] ) ) { $sanitized_options['delete_orphaned_term_rs'] = '1'; } if ( isset( $options['delete_duplicate_usermeta'] ) ) { $sanitized_options['delete_duplicate_usermeta'] = '1'; } if ( isset( $options['delete_orphaned_usermeta'] ) ) { $sanitized_options['delete_orphaned_usermeta'] = '1'; } if ( isset( $options['batch_size'] ) ) { if ( 100 <= (int) $options['batch_size'] && 2000 >= (int) $options['batch_size'] ) { $sanitized_options['batch_size'] = (int) $options['batch_size']; } else { $sanitized_options['batch_size'] = 500; } } else { $sanitized_options['batch_size'] = 500; } if ( isset( $options['enable_logging'] ) ) { $sanitized_options['enable_logging'] = '1'; } } return $this->carry_forward_inactive_pro_keys( $sanitized_options ); } /** * Enqueue scripts * * @param string $hook_suffix Hook suffix. * * @return void */ public function enqueue_settings_assets( string $hook_suffix ): void { wp_enqueue_style( 'adminoptim-modules-pro-settings' ); } /** * Render logs Settings page * * @return void */ public function render_logs_on_page() { if ( isset( $_POST['adminoptim_delete_logs'] ) && '1' === sanitize_text_field( wp_unslash( $_POST['adminoptim_delete_logs'] ) ) ) { if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_POST['_wpnonce'] ), 'adminoptim-db-delete-logs' ) ) { delete_option( 'adminoptim_db_log' ); delete_option( 'adminoptim_db_remnant_log' ); ao_admin_notice( __( 'Log files deleted.', 'admin-optimizer' ), [ 'type' => 'success', ] ); } } $db_log = get_option( 'adminoptim_db_log', [] ); $remnant_db_log = get_option( 'adminoptim_db_remnant_log', [] ); $db_log = array_merge( $db_log, $remnant_db_log ); if ( 1 < count( $db_log ) ) { usort( $db_log, static function ( $a, $b ) { return $b['start'] <=> $a['start']; } ); } ?>

  • ', $clean_log ); ?>
    • [] ] ); ?>

    .

  • is_pro_active() ) { do_action( 'adminoptim_db_cleaner_render_manual_actions' ); return; } ?>

    ', '' ); ?>

    manual-actions
    is_pro_active() ) { do_action( 'adminoptim_db_cleaner_render_options_table' ); return; } ?>

    ', '' ); ?>

    admin optimizer pro options table optimizer