plugin_name = $plugin_name; $this->version = $version; } /** * Register cron jobs */ public function crons_registrations( $schedules ) { $schedules['bulk_optimization'] = array( 'interval' => MINUTE_IN_SECONDS, 'display' => __( 'Every minute', 'quickwebp' ) ); return $schedules; } /** * excute bulk optimization */ public function excute_bulk_optimization() { $lock_token = $this->acquire_bulk_optimization_lock(); if ( ! $lock_token ) { return; } $time_start = microtime( true ); $quickwebp_image_optimizer = new Quickwebp_Image_Optimizer( QUICKWEBP_TEXT_DOMAIN, QUICKWEBP_VERSION ); $settings = $quickwebp_image_optimizer->get_settings(); $mode_enabled = $settings['quickwebp_settings_conversion']; if ( '0' === $mode_enabled ) { $this->end_cron_job(); $this->release_bulk_optimization_lock( $lock_token ); return; } $media_ids = $quickwebp_image_optimizer->get_unoptimized_media_ids( 5 ); if ( empty( $media_ids ) ) { $this->end_cron_job(); $this->release_bulk_optimization_lock( $lock_token ); return; } $status = get_option( 'quickwebp_bulk_optimize_status', 'finish' ); if ( $status != 'running' ) { $this->end_cron_job(); $this->release_bulk_optimization_lock( $lock_token ); return; } $current = (int) get_option( 'quickwebp_bulk_optimize_current', 0 ); $batch_stats = array( 'images_optimized' => 0, 'bytes_before' => 0, 'bytes_after' => 0, ); foreach ( $media_ids as $id ) { if ( $time_start + 55 < microtime( true ) ) { break; } $sizes = $quickwebp_image_optimizer->get_media_files( $id ); $new_sizes = array(); foreach ( $sizes as $key => $size ) { $result = $quickwebp_image_optimizer->optimize_local_file( $size ); if ( $result ) { $new_sizes[$key] = $result; } } if ( ! empty( $new_sizes ) ) { $attachment_stats = $quickwebp_image_optimizer->get_attachment_optimization_stats( $new_sizes ); $batch_stats['images_optimized'] += $attachment_stats['images_optimized']; $batch_stats['bytes_before'] += $attachment_stats['bytes_before']; $batch_stats['bytes_after'] += $attachment_stats['bytes_after']; $data = get_post_meta( $id, 'quickwebp_data', true ); if ( ! empty( $data ) ) { $quickwebp_image_optimizer->remove_related_files( $data ); } if ( '1' == $mode_enabled ) { update_post_meta( $id, 'quickwebp_already_optimized', '1' ); } elseif ( '2' == $mode_enabled ) { update_post_meta( $id, 'quickwebp_already_optimized', '2' ); } update_post_meta( $id, 'quickwebp_data', $new_sizes ); delete_post_meta( $id, 'quickwebp_has_error' ); } else { update_post_meta( $id, 'quickwebp_has_error', '1' ); delete_post_meta( $id, 'quickwebp_already_optimized' ); delete_post_meta( $id, 'quickwebp_data' ); } $current++; } if ( $batch_stats['images_optimized'] ) { $quickwebp_image_optimizer->record_optimization_stats( $batch_stats['bytes_before'], $batch_stats['bytes_after'], $batch_stats['images_optimized'] ); } update_option( 'quickwebp_bulk_optimize_current', $current ); if ( empty( $quickwebp_image_optimizer->get_unoptimized_media_ids( 1 ) ) ) { $this->end_cron_job(); } $this->release_bulk_optimization_lock( $lock_token ); } /** * Acquire an expiring lock for the bulk optimization worker. * * @return string|false */ private function acquire_bulk_optimization_lock() { $lock_token = wp_generate_uuid4(); $lock = array( 'token' => $lock_token, 'expires' => time() + ( 2 * MINUTE_IN_SECONDS ), ); if ( add_option( 'quickwebp_bulk_optimization_lock', $lock, '', false ) ) { return $lock_token; } $existing_lock = get_option( 'quickwebp_bulk_optimization_lock', array() ); if ( is_array( $existing_lock ) && absint( $existing_lock['expires'] ?? 0 ) < time() ) { delete_option( 'quickwebp_bulk_optimization_lock' ); if ( add_option( 'quickwebp_bulk_optimization_lock', $lock, '', false ) ) { return $lock_token; } } return false; } /** * Release the bulk optimization lock owned by this process. * * @param string $lock_token Lock ownership token. */ private function release_bulk_optimization_lock( $lock_token ) { $lock = get_option( 'quickwebp_bulk_optimization_lock', array() ); if ( is_array( $lock ) && hash_equals( (string) ( $lock['token'] ?? '' ), $lock_token ) ) { delete_option( 'quickwebp_bulk_optimization_lock' ); } } /** * Start bulk optimization */ public function start_bulk_optimization() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( __( 'You are not allowed to manage plugin settings.', 'quickwebp' ), 403 ); } // verify the nonce. $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; if( !wp_verify_nonce( $nonce, 'image_optimize_nonce' ) ) { wp_send_json_error( __( 'Refresh the page and try again.', 'quickwebp' ) ); } $quickwebp_image_optimizer = new Quickwebp_Image_Optimizer( QUICKWEBP_TEXT_DOMAIN, QUICKWEBP_VERSION ); $settings = $quickwebp_image_optimizer->get_settings(); $mode_enabled = $settings['quickwebp_settings_conversion']; if ( '0' === $mode_enabled ) { wp_send_json_error( __( 'Choose an image format and save the settings.', 'quickwebp' ) ); } $total = $quickwebp_image_optimizer->get_unoptimized_media_count(); if ( ! $total ) { wp_send_json_error( __( 'No images to optimize.', 'quickwebp' ) ); } $status = get_option( 'quickwebp_bulk_optimize_status', 'finish' ); if ( $status != 'finish' ) { wp_send_json_error( __( 'Bulk optimization is already running.', 'quickwebp' ) ); } if ( ! wp_next_scheduled( 'quickwebp_bulk_optimization_hook' ) ) { wp_schedule_event( time(), 'bulk_optimization', 'quickwebp_bulk_optimization_hook' ); $current = 0; update_option( 'quickwebp_bulk_optimize_total', $total ); update_option( 'quickwebp_bulk_optimize_current', $current ); update_option( 'quickwebp_bulk_optimize_status', 'running' ); $data = array( 'progress' => $current . '/' . $total, 'percent' => $total ? round( abs( ( $current / $total ) ) * 100 ) . '%' : '0%' ); wp_send_json_success( $data ); } wp_send_json_error( __( 'Refresh the page and try again.', 'quickwebp' ) ); } /** * Stop bulk optimization */ public function stop_bulk_optimization() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( __( 'You are not allowed to manage plugin settings.', 'quickwebp' ), 403 ); } // verify the nonce. $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; if( !wp_verify_nonce( $nonce, 'image_optimize_nonce' ) ) { wp_send_json_error( __( 'Refresh the page and try again.', 'quickwebp' ) ); } if ( $this->clear_bulk_optimization() ) { wp_send_json_success( __( 'Bulk optimization stopped.', 'quickwebp' ) ); } wp_send_json_error( __( 'Refresh the page and try again.', 'quickwebp' ) ); } /** * Check bulk optimization progress */ public function check_bulk_optimization_progress() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( __( 'You are not allowed to manage plugin settings.', 'quickwebp' ), 403 ); } // verify the nonce. $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; if( !wp_verify_nonce( $nonce, 'image_optimize_nonce' ) ) { wp_send_json_error( __( 'Refresh the page and try again.', 'quickwebp' ) ); } $status = get_option( 'quickwebp_bulk_optimize_status', '' ); $total = (int)get_option( 'quickwebp_bulk_optimize_total', 0 ); $current = (int)get_option( 'quickwebp_bulk_optimize_current', 0 ); $is_running = $status == 'running' ? true : false; $data = array( 'running' => $is_running, 'progress' => $current . '/' . $total, 'percent' => $total ? round( abs( ( $current / $total ) ) * 100 ) . '%' : '0%' ); wp_send_json_success( $data ); } /** * Clear bulk optimization */ private function clear_bulk_optimization() { update_option( 'quickwebp_bulk_optimize_status', 'finish' ); if ( wp_next_scheduled( 'quickwebp_bulk_optimization_hook' ) ) { wp_clear_scheduled_hook( 'quickwebp_bulk_optimization_hook' ); return true; } return false; } /** * End cron job */ private function end_cron_job() { $this->clear_bulk_optimization(); } }