$deadline ) { break; } } self::unlock( 'queue' ); if ( 'working' === $state && self::next_id() ) { self::schedule( 5 ); } elseif ( 'working' === $state ) { $state = 'idle'; delete_option( self::BULK_OPTION ); } return $state; } /** * Put the queue on hold after an error that would hit every image. * * @param WP_Error $error The error. */ private static function pause( WP_Error $error ) { $code = $error->get_error_code(); switch ( $code ) { case 'rate_limited': $wait = MINUTE_IN_SECONDS; break; case 'quota_exceeded': $wait = HOUR_IN_SECONDS; break; case 'invalid_key': case 'key_suspended': case 'site_limit': case 'site_unverified': case 'not_connected': $wait = YEAR_IN_SECONDS; // Needs the site owner; cleared when they reconnect or press Start. break; default: $wait = 5 * MINUTE_IN_SECONDS; } update_option( self::PAUSE, array( 'code' => $code, 'message' => $error->get_error_message(), 'until' => time() + $wait, ), false ); if ( $wait < YEAR_IN_SECONDS ) { wp_clear_scheduled_hook( self::HOOK ); wp_schedule_single_event( time() + $wait, self::HOOK ); } } /** @return int ID of the next attachment to process, or 0. */ public static function next_id() { $meta_query = array( 'relation' => 'OR', array( 'key' => LeanPixel_Optimizer::STATUS, 'value' => 'queued', ), ); if ( self::is_bulk_running() ) { $meta_query[] = array( 'key' => LeanPixel_Optimizer::STATUS, 'compare' => 'NOT EXISTS', ); } $ids = get_posts( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_mime_type' => LeanPixel_Optimizer::mimes(), 'posts_per_page' => 1, 'fields' => 'ids', 'orderby' => 'ID', 'order' => 'DESC', 'no_found_rows' => true, 'meta_query' => $meta_query, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- one row. ) ); return $ids ? (int) $ids[0] : 0; } /** * Numbers for the bulk screen. * * @return array { total, optimized, error, queued, restored, excluded, remaining } */ public static function counts() { global $wpdb; $total = 0; $mimes = (array) wp_count_attachments(); foreach ( LeanPixel_Optimizer::mimes() as $mime ) { $total += isset( $mimes[ $mime ] ) ? (int) $mimes[ $mime ] : 0; } $counts = array( 'total' => $total, 'optimized' => 0, 'error' => 0, 'queued' => 0, 'restored' => 0, 'excluded' => 0, ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- live progress numbers. $rows = $wpdb->get_results( $wpdb->prepare( "SELECT pm.meta_value AS status, COUNT(*) AS n FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id AND p.post_type = 'attachment' WHERE pm.meta_key = %s GROUP BY pm.meta_value", LeanPixel_Optimizer::STATUS ) ); foreach ( (array) $rows as $row ) { if ( isset( $counts[ $row->status ] ) ) { $counts[ $row->status ] = (int) $row->n; } } $counts['remaining'] = max( 0, $total - $counts['optimized'] - $counts['error'] - $counts['restored'] - $counts['excluded'] ); return $counts; } }