<?php

defined('ABSPATH') || exit;
class WC_Regenerate_Images
{
    protected static $background_process;
    protected static $regenerate_size;
    public static function init()
    {
        add_action('image_get_intermediate_size', array(__CLASS__, 'filter_image_get_intermediate_size'), 10, 3);
        add_filter('wp_generate_attachment_metadata', array(__CLASS__, 'add_uncropped_metadata'));
        add_filter('wp_get_attachment_image_src', array(__CLASS__, 'maybe_resize_image'), 10, 4);
        if (method_exists('Jetpack', 'is_module_active') && Jetpack::is_module_active('photon')) {
            return;
        }
        if (apply_filters('woocommerce_background_image_regeneration', true)) {
            include_once WC_ABSPATH . 'includes/class-wc-regenerate-images-request.php';
            self::$background_process = new WC_Regenerate_Images_Request();
            add_action('admin_init', array(__CLASS__, 'regenerating_notice'));
            add_action('woocommerce_hide_regenerating_thumbnails_notice', array(__CLASS__, 'dismiss_regenerating_notice'));
            if (!is_multisite()) {
                add_action('customize_save_after', array(__CLASS__, 'maybe_regenerate_images'));
                add_action('after_switch_theme', array(__CLASS__, 'maybe_regenerate_images'));
            }
        }
    }
    public static function filter_image_get_intermediate_size($data, $attachment_id, $size)
    {
        if (!is_string($size) || !in_array($size, apply_filters('woocommerce_image_sizes_to_resize', array('woocommerce_thumbnail', 'woocommerce_gallery_thumbnail', 'woocommerce_single', 'shop_thumbnail', 'shop_catalog', 'shop_single')), true)) {
            return $data;
        }
        if (!isset($data['width'], $data['height'])) {
            return $data;
        }
        if (!self::image_size_matches_settings($data, $size)) {
            if (method_exists('Jetpack', 'is_module_active') && Jetpack::is_module_active('photon')) {
                return false;
            } else {
                $size_data = wc_get_image_size($size);
                return image_get_intermediate_size($attachment_id, array(absint($size_data['width']), absint($size_data['height'])));
            }
        }
        return $data;
    }
    public static function add_uncropped_metadata($meta_data)
    {
        $size_data = wc_get_image_size('woocommerce_thumbnail');
        if (isset($meta_data['sizes'], $meta_data['sizes']['woocommerce_thumbnail'])) {
            $meta_data['sizes']['woocommerce_thumbnail']['uncropped'] = empty($size_data['height']);
        }
        return $meta_data;
    }
    protected static function image_size_matches_settings($image, $size)
    {
        $target_size = wc_get_image_size($size);
        $uncropped = '' === $target_size['width'] || '' === $target_size['height'];
        if (!$uncropped) {
            $ratio_match = wp_image_matches_ratio($image['width'], $image['height'], $target_size['width'], $target_size['height']);
            if ($ratio_match && $target_size['width'] !== $image['width']) {
                return false;
            }
            if ($ratio_match && $target_size['height'] && $target_size['height'] !== $image['height']) {
                return false;
            }
        }
        if ($uncropped && empty($image['uncropped'])) {
            return false;
        }
        return true;
    }
    public static function regenerating_notice()
    {
        if (!self::$background_process->is_running()) {
            WC_Admin_Notices::add_notice('regenerating_thumbnails');
        } else {
            WC_Admin_Notices::remove_notice('regenerating_thumbnails');
        }
    }
    public static function dismiss_regenerating_notice()
    {
        if (self::$background_process) {
            self::$background_process->kill_process();
            $log = wc_get_logger();
            $log->info(__('Cancelled product image regeneration job.', 'woocommerce'), array('source' => 'wc-image-regeneration'));
        }
        WC_Admin_Notices::remove_notice('regenerating_thumbnails');
    }
    public static function maybe_regenerate_images()
    {
        $size_hash = md5(wp_json_encode(array(wc_get_image_size('thumbnail'), wc_get_image_size('single'), wc_get_image_size('gallery_thumbnail'))));
        if (update_option('woocommerce_maybe_regenerate_images_hash', $size_hash)) {
            self::queue_image_regeneration();
        }
    }
    public static function maybe_resize_image($image, $attachment_id, $size, $icon)
    {
        if (!apply_filters('woocommerce_resize_images', true)) {
            return $image;
        }
        if (!$image || !in_array($size, apply_filters('woocommerce_image_sizes_to_resize', array('woocommerce_thumbnail', 'woocommerce_gallery_thumbnail', 'woocommerce_single', 'shop_thumbnail', 'shop_catalog', 'shop_single')), true)) {
            return $image;
        }
        $target_size = wc_get_image_size($size);
        $image_width = $image[1];
        $image_height = $image[2];
        $ratio_match = false;
        $target_uncropped = '' === $target_size['width'] || '' === $target_size['height'] || !$target_size['crop'];
        if ($target_uncropped) {
            $full_size = self::get_full_size_image_dimensions($attachment_id);
            if (!$full_size || !$full_size['width'] || !$full_size['height']) {
                return $image;
            }
            $ratio_match = wp_image_matches_ratio($image_width, $image_height, $full_size['width'], $full_size['height']);
        } else {
            $ratio_match = wp_image_matches_ratio($image_width, $image_height, $target_size['width'], $target_size['height']);
        }
        if (!$ratio_match) {
            $full_size = self::get_full_size_image_dimensions($attachment_id);
            if (!$full_size) {
                return $image;
            }
            if ($image_width === $target_size['width'] && $full_size['height'] < $target_size['height']) {
                return $image;
            }
            if ($image_height === $target_size['height'] && $full_size['width'] < $target_size['width']) {
                return $image;
            }
            if ($full_size['height'] < $target_size['height'] && $full_size['width'] < $target_size['width']) {
                return $image;
            }
            return self::resize_and_return_image($attachment_id, $image, $size, $icon);
        }
        return $image;
    }
    private static function get_full_size_image_dimensions($attachment_id)
    {
        $imagedata = wp_get_attachment_metadata($attachment_id);
        if (!$imagedata) {
            return array();
        }
        if (!isset($imagedata['file']) && isset($imagedata['sizes']['full'])) {
            $imagedata['height'] = $imagedata['sizes']['full']['height'];
            $imagedata['width'] = $imagedata['sizes']['full']['width'];
        }
        return array('width' => $imagedata['width'], 'height' => $imagedata['height']);
    }
    public static function is_regeneratable($attachment)
    {
        if ('site-icon' === get_post_meta(is_object($attachment) ? $attachment->ID : $attachment, '_wp_attachment_context', true)) {
            return false;
        }
        if (wp_attachment_is_image($attachment)) {
            return true;
        }
        return false;
    }
    public static function adjust_intermediate_image_sizes($sizes)
    {
        return array(self::$regenerate_size);
    }
    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);
    }
    private static function resize_and_return_image($attachment_id, $image, $size, $icon)
    {
        if (!self::is_regeneratable($attachment_id)) {
            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';
        }
        self::$regenerate_size = is_customize_preview() ? $size . '_preview' : $size;
        if (is_customize_preview()) {
            $image_size = wc_get_image_size($size);
            add_image_size(self::$regenerate_size, absint($image_size['width']), absint($image_size['height']), $image_size['crop']);
            $thumbnail = self::get_image($fullsizepath, absint($image_size['width']), absint($image_size['height']), $image_size['crop']);
            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']);
            }
        }
        $metadata = wp_get_attachment_metadata($attachment_id);
        if (!is_array($metadata)) {
            $metadata = array();
        }
        add_filter('intermediate_image_sizes', array(__CLASS__, 'adjust_intermediate_image_sizes'));
        $new_metadata = wp_generate_attachment_metadata($attachment_id, $fullsizepath);
        remove_filter('intermediate_image_sizes', array(__CLASS__, 'adjust_intermediate_image_sizes'));
        if (is_wp_error($new_metadata) || empty($new_metadata)) {
            return $image;
        }
        if (isset($new_metadata['sizes'][self::$regenerate_size])) {
            $metadata['sizes'][self::$regenerate_size] = $new_metadata['sizes'][self::$regenerate_size];
            wp_update_attachment_metadata($attachment_id, $metadata);
        }
        $new_image = self::unfiltered_image_downsize($attachment_id, self::$regenerate_size);
        return $new_image ? $new_image : $image;
    }
    private static function unfiltered_image_downsize($attachment_id, $size)
    {
        remove_action('image_get_intermediate_size', array(__CLASS__, 'filter_image_get_intermediate_size'), 10, 3);
        $return = image_downsize($attachment_id, $size);
        add_action('image_get_intermediate_size', array(__CLASS__, 'filter_image_get_intermediate_size'), 10, 3);
        return $return;
    }
    public static function queue_image_regeneration()
    {
        global $wpdb;
        self::$background_process->kill_process();
        $images = $wpdb->get_results("SELECT ID\n\t\t\tFROM {$wpdb->posts}\n\t\t\tWHERE post_type = 'attachment'\n\t\t\tAND post_mime_type LIKE 'image/%'\n\t\t\tORDER BY ID DESC");
        foreach ($images as $image) {
            self::$background_process->push_to_queue(array('attachment_id' => $image->ID));
        }
        self::$background_process->save()->dispatch();
    }
}
add_action('init', array('WC_Regenerate_Images', 'init'));