{$key} ) ? $all_settings->{$key} : null; // Cast to boolean for checkbox fields if ( in_array( $key, $bool_keys, true ) && $val !== null ) { $val = (bool) $val; } $settings[ $key ] = $val; } $preload_status = [ 'status' => 'idle', 'processed' => 0, 'total' => 0, 'remaining' => 0, ]; if ( class_exists( '\Upress\EzCache\Preload' ) ) { $preload_status = Preload::instance()->get_status(); } return wp_send_json_success( array_merge( $settings, [ 'preload_status' => $preload_status, ] ) ); } /** * Update performance settings * @param WP_REST_Request $request */ function update( $request ) { $input = (array) $request->get_json_params(); $current_settings = (array) Settings::get_settings(); foreach ( self::$performance_keys as $key ) { if ( isset( $input[ $key ] ) ) { $current_settings[ $key ] = $this->sanitize_value( $key, $input[ $key ] ); } } Settings::set_settings( $current_settings ); return wp_send_json_success(); } /** * Run preload */ function runPreload() { if ( class_exists( '\Upress\EzCache\Preload' ) ) { Preload::instance()->start(); } return wp_send_json_success( [ 'message' => 'Preload started' ] ); } /** * Stop preload */ function stopPreload() { if ( class_exists( '\Upress\EzCache\Preload' ) ) { Preload::instance()->stop(); } return wp_send_json_success( [ 'message' => 'Preload stopped' ] ); } /** * Run database cleanup */ function runDbCleanup( $request ) { // The Vue UI posts an associative map ( { db_cleanup_revisions: true, … } ) // and does NOT persist the toggles before running, so the selected tasks // must be taken from the request body. DatabaseOptimizer::clean() expects a // flat list of enabled task keys, so filter out the false values and keep the // keys. An empty body falls back to the saved settings. $params = $request ? (array) $request->get_json_params() : []; $tasks = ! empty( $params ) ? array_keys( array_filter( $params ) ) : null; $optimizer = new DatabaseOptimizer(); $results = $optimizer->clean( $tasks ); return wp_send_json_success( [ 'message' => 'Database cleanup completed', 'results' => $results, ] ); } /** * Sanitize a value based on its key */ private function sanitize_value( $key, $value ) { // Boolean fields $booleans = [ 'enable_preload', 'preload_on_cache_clear', 'preload_crawl_homepage_links', 'lazy_load_images', 'lazy_load_iframes', 'defer_js', 'remove_query_strings', 'heartbeat_control', 'cdn_enabled', 'db_cleanup_revisions', 'db_cleanup_auto_drafts', 'db_cleanup_trashed_posts', 'db_cleanup_spam_comments', 'db_cleanup_trashed_comments', 'db_cleanup_expired_transients', 'db_cleanup_orphan_postmeta', 'db_optimize_tables', // v2.2.0 'enable_redis_object_cache', 'enable_redis_fullpage', 'enable_critical_css', 'enable_speculative_loading', 'enable_early_hints', ]; if ( in_array( $key, $booleans, true ) ) { return (bool) $value; } // Integer fields if ( $key === 'preload_batch_size' ) { return max( 1, min( 50, (int) $value ) ); } // Select fields if ( $key === 'heartbeat_mode' ) { return in_array( $value, [ 'reduce', 'disable' ], true ) ? $value : 'reduce'; } if ( $key === 'db_cleanup_schedule' ) { return in_array( $value, [ 'never', 'daily', 'weekly' ], true ) ? $value : 'never'; } if ( $key === 'speculative_mode' ) { return in_array( $value, [ 'conservative', 'moderate', 'eager' ], true ) ? $value : 'moderate'; } // Text fields return sanitize_textarea_field( $value ); } }