ID, '_wp_attachment_context', true ) ) { return false; } if ( wp_attachment_is_image( $attachment ) ) { return true; } return false; } /** * Only regenerate images for the requested size. * * @param array $sizes Array of image sizes. * @return array */ public static function adjust_intermediate_image_sizes( $sizes ) { return array( self::$requested_size ); } /** * Generate the thumbnail filename and dimensions for a given file. * * @param string $fullsizepath Path to full size image. * @param int $thumbnail_width The width of the thumbnail. * @param int $thumbnail_height The height of the thumbnail. * @param bool $crop Whether to crop or not. * @return array|false An array of the filename, thumbnail width, and thumbnail height, or false on failure to resize such as the thumbnail being larger than the fullsize image. */ private static function get_image( $fullsizepath, $thumbnail_width, $thumbnail_height, $crop ) { list( $fullsize_width, $fullsize_height ) = getimagesize( $fullsizepath ); $dimensions = image_resize_dimensions( $fullsize_width, $fullsize_height, $thumbnail_width, $thumbnail_height, $crop ); $editor = wp_get_image_editor( $fullsizepath ); if ( is_wp_error( $editor ) ) { return false; } if ( ! $dimensions || ! is_array( $dimensions ) ) { return false; } list( , , , , $dst_w, $dst_h ) = $dimensions; $suffix = "{$dst_w}x{$dst_h}"; $file_ext = strtolower( pathinfo( $fullsizepath, PATHINFO_EXTENSION ) ); return array( 'filename' => $editor->generate_filename( $suffix, null, $file_ext ), 'width' => $dst_w, 'height' => $dst_h, ); } /** * Regenerate the image according to the required size * * @param int $attachment_id Attachment ID. * @param array $image Original Image. * @param string $size Size to return for new URL. * @param bool $icon If icon or not. * @return string */ private static function resize_and_return_image( $attachment_id, $image, $size, $icon ) { self::$requested_size = $size; $image_size = wc_get_image_size( $size ); $wp_uploads = wp_upload_dir( null, false ); $wp_uploads_dir = $wp_uploads['basedir']; $wp_uploads_url = $wp_uploads['baseurl']; $attachment = get_post( $attachment_id ); if ( ! $attachment || 'attachment' !== $attachment->post_type || ! self::is_regeneratable( $attachment ) ) { return $image; } $fullsizepath = get_attached_file( $attachment_id ); if ( false === $fullsizepath || is_wp_error( $fullsizepath ) || ! file_exists( $fullsizepath ) ) { return $image; } if ( ! function_exists( 'wp_crop_image' ) ) { include ABSPATH . 'wp-admin/includes/image.php'; } // Make sure registered image size matches the size we're requesting. add_image_size( $size, $image_size['width'], $image_size['height'], $image_size['crop'] ); $thumbnail = self::get_image( $fullsizepath, $image_size['width'], $image_size['height'], $image_size['crop'] ); // If the file is already there perhaps just load it. if ( $thumbnail && file_exists( $thumbnail['filename'] ) ) { $wp_uploads = wp_upload_dir( null, false ); $wp_uploads_dir = $wp_uploads['basedir']; $wp_uploads_url = $wp_uploads['baseurl']; return array( 0 => str_replace( $wp_uploads_dir, $wp_uploads_url, $thumbnail['filename'] ), 1 => $thumbnail['width'], 2 => $thumbnail['height'], ); } $old_metadata = wp_get_attachment_metadata( $attachment_id ); // We only want to regen WC images. add_filter( 'intermediate_image_sizes', array( __CLASS__, 'adjust_intermediate_image_sizes' ) ); // This function will generate the new image sizes. $new_metadata = wp_generate_attachment_metadata( $attachment_id, $fullsizepath ); // Remove custom filter. remove_filter( 'intermediate_image_sizes', array( __CLASS__, 'adjust_intermediate_image_sizes' ) ); // If something went wrong lets just return the original image. if ( is_wp_error( $new_metadata ) || empty( $new_metadata ) ) { return $image; } if ( ! empty( $old_metadata ) && ! empty( $old_metadata['sizes'] ) && is_array( $old_metadata['sizes'] ) ) { foreach ( $old_metadata['sizes'] as $old_size => $old_size_data ) { if ( empty( $new_metadata['sizes'][ $old_size ] ) ) { $new_metadata['sizes'][ $old_size ] = $old_metadata['sizes'][ $old_size ]; } } // Handle legacy sizes. if ( isset( $new_metadata['sizes']['shop_thumbnail'], $new_metadata['sizes']['woocommerce_thumbnail'] ) ) { $new_metadata['sizes']['shop_thumbnail'] = $new_metadata['sizes']['woocommerce_thumbnail']; } if ( isset( $new_metadata['sizes']['shop_catalog'], $new_metadata['sizes']['woocommerce_thumbnail'] ) ) { $new_metadata['sizes']['shop_catalog'] = $new_metadata['sizes']['woocommerce_thumbnail']; } if ( isset( $new_metadata['sizes']['shop_single'], $new_metadata['sizes']['woocommerce_single'] ) ) { $new_metadata['sizes']['shop_single'] = $new_metadata['sizes']['woocommerce_single']; } } // Update the meta data with the new size values. wp_update_attachment_metadata( $attachment_id, $new_metadata ); // Now we've done our regen, attempt to return the new size. $new_image = image_downsize( $attachment_id, $size ); return $new_image ? $new_image : $image; } /** * Check if we should regenerate the product images when options change. * * @param mixed $old_value Old option value. * @param mixed $new_value New option value. * @param string $option Option name. */ public static function maybe_regenerate_images_option_update( $old_value, $new_value, $option ) { if ( $new_value === $old_value ) { return; } self::queue_image_regeneration(); } /** * Check if we should generate images when new themes declares custom sizes. */ public static function maybe_regenerate_image_theme_switch() { if ( wc_get_theme_support( 'single_image_width' ) || wc_get_theme_support( 'thumbnail_image_width' ) ) { self::queue_image_regeneration(); } } /** * Get list of images and queue them for regeneration * * @return void */ private static function queue_image_regeneration() { global $wpdb; // First lets cancel existing running queue to avoid running it more than once. self::$background_process->kill_process(); // Now lets find all product image attachments IDs and pop them onto the queue. $images = $wpdb->get_results( // @codingStandardsIgnoreLine "SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' ORDER BY ID DESC" ); foreach ( $images as $image ) { self::$background_process->push_to_queue( array( 'attachment_id' => $image->ID, ) ); } // Lets dispatch the queue to start processing. self::$background_process->save()->dispatch(); } } WC_Regenerate_Images::init();