default_settings()); } } public function default_settings(): array { return [ 'auto_resize' => 1, 'webp' => 0, 'keep_original' => 1, 'presets' => [ ['name' => 'Card Thumbnail', 'slug' => 'card-thumb', 'width' => 480, 'height' => 320, 'crop' => 1], ['name' => 'Content Medium', 'slug' => 'content-medium', 'width' => 960, 'height' => 0, 'crop' => 0], ['name' => 'Hero Banner', 'slug' => 'hero-banner', 'width' => 1600, 'height' => 900, 'crop' => 1], ['name' => 'Square Social', 'slug' => 'square-social', 'width' => 1080, 'height' => 1080, 'crop' => 1], ], ]; } public function get_settings(): array { $settings = get_option(self::OPTION, []); return wp_parse_args(is_array($settings) ? $settings : [], $this->default_settings()); } public function admin_menu(): void { add_media_page( __('Smart Image Resizer', 'smart-image-resizer'), __('Image Resizer', 'smart-image-resizer'), 'upload_files', 'smart-image-resizer', [$this, 'render_admin_page'] ); } public function admin_assets(string $hook): void { if ($hook !== 'media_page_smart-image-resizer') { return; } wp_enqueue_style('sir-admin', plugin_dir_url(__FILE__) . 'assets/admin.css', [], '0.1.0'); } public function handle_admin_actions(): void { if (!is_admin() || empty($_POST['sir_action'])) { return; } if (!current_user_can('upload_files')) { wp_die(esc_html__('You do not have permission to resize images.', 'smart-image-resizer')); } check_admin_referer(self::NONCE_ACTION); $action = sanitize_key($_POST['sir_action']); if ($action === 'save_settings') { $this->save_settings_from_post(); wp_safe_redirect(add_query_arg(['page' => 'smart-image-resizer', 'sir_notice' => 'settings_saved'], admin_url('upload.php'))); exit; } if ($action === 'bulk_resize') { $preset_slug = sanitize_title(wp_unslash($_POST['preset_slug'] ?? '')); $limit = max(1, min(50, absint($_POST['limit'] ?? 20))); $result = $this->bulk_resize($preset_slug, $limit); set_transient('sir_last_bulk_result_' . get_current_user_id(), $result, MINUTE_IN_SECONDS * 5); wp_safe_redirect(add_query_arg(['page' => 'smart-image-resizer', 'sir_notice' => 'bulk_done'], admin_url('upload.php'))); exit; } } private function save_settings_from_post(): void { $presets = []; $names = array_map('sanitize_text_field', wp_unslash($_POST['preset_name'] ?? [])); $slugs = array_map('sanitize_title', wp_unslash($_POST['preset_slug'] ?? [])); $widths = array_map('absint', wp_unslash($_POST['preset_width'] ?? [])); $heights = array_map('absint', wp_unslash($_POST['preset_height'] ?? [])); $crops = isset($_POST['preset_crop']) ? array_map('absint', wp_unslash($_POST['preset_crop'])) : []; for ($i = 0; $i < 6; $i++) { $name = trim($names[$i] ?? ''); $slug = sanitize_title($slugs[$i] ?? $name); $width = $widths[$i] ?? 0; $height = $heights[$i] ?? 0; if (!$name || !$slug || $width < 1) { continue; } $presets[] = [ 'name' => $name, 'slug' => $slug, 'width' => $width, 'height' => $height, 'crop' => !empty($crops[$i]) ? 1 : 0, ]; } if (!$presets) { $presets = $this->default_settings()['presets']; } update_option(self::OPTION, [ 'auto_resize' => !empty($_POST['auto_resize']) ? 1 : 0, 'webp' => !empty($_POST['webp']) ? 1 : 0, 'keep_original' => 1, 'presets' => $presets, ]); } public function render_admin_page(): void { $settings = $this->get_settings(); $presets = array_values($settings['presets']); $notice = sanitize_key($_GET['sir_notice'] ?? ''); $last = get_transient('sir_last_bulk_result_' . get_current_user_id()); ?>

'','slug'=>'','width'=>'','height'=>'','crop'=>0]; ?>
NameSlugWidthHeightCrop

render_logs(); ?>
' . esc_html__('No resize jobs yet. Upload an image or run a bulk job to see activity here.', 'smart-image-resizer') . '

'; return; } echo ''; } public function resize_on_upload(int $attachment_id): void { $settings = $this->get_settings(); if (empty($settings['auto_resize']) || !wp_attachment_is_image($attachment_id)) { return; } foreach ($settings['presets'] as $preset) { $this->resize_attachment($attachment_id, $preset, !empty($settings['webp'])); } } public function bulk_resize(string $preset_slug, int $limit): array { $settings = $this->get_settings(); $preset = null; foreach ($settings['presets'] as $candidate) { if ($candidate['slug'] === $preset_slug) { $preset = $candidate; break; } } if (!$preset) { return ['resized' => 0, 'skipped' => 0, 'errors' => 1]; } $ids = get_posts([ 'post_type' => 'attachment', 'post_mime_type' => 'image', 'post_status' => 'inherit', 'posts_per_page' => $limit, 'fields' => 'ids', 'orderby' => 'date', 'order' => 'DESC', ]); $result = ['resized' => 0, 'skipped' => 0, 'errors' => 0]; foreach ($ids as $id) { $status = $this->resize_attachment((int) $id, $preset, !empty($settings['webp'])); if ($status === true) { $result['resized']++; } elseif ($status === 'exists') { $result['skipped']++; } else { $result['errors']++; } } return $result; } private function resize_attachment(int $attachment_id, array $preset, bool $make_webp = false) { $file = get_attached_file($attachment_id); if (!$file || !file_exists($file)) { return false; } $editor = wp_get_image_editor($file); if (is_wp_error($editor)) { return false; } $info = pathinfo($file); $slug = sanitize_title($preset['slug']); $width = absint($preset['width']); $height = absint($preset['height']); $dest = trailingslashit($info['dirname']) . $info['filename'] . '-' . $slug . '-' . $width . 'x' . ($height ?: 'auto') . '.' . strtolower($info['extension']); $existing = get_post_meta($attachment_id, self::META_KEY, true); $existing = is_array($existing) ? $existing : []; if (file_exists($dest)) { return 'exists'; } $resized = $editor->resize($width, $height ?: null, !empty($preset['crop'])); if (is_wp_error($resized)) { return false; } $saved = $editor->save($dest); if (is_wp_error($saved) || empty($saved['path'])) { return false; } $existing[$slug] = [ 'path' => $saved['path'], 'file' => wp_basename($saved['path']), 'width' => $saved['width'] ?? $width, 'height' => $saved['height'] ?? $height, 'created' => current_time('mysql'), ]; if ($make_webp && function_exists('imagewebp')) { $webp_editor = wp_get_image_editor($saved['path']); if (!is_wp_error($webp_editor)) { $webp_dest = preg_replace('/\.[^.]+$/', '.webp', $saved['path']); $webp_saved = $webp_editor->save($webp_dest, 'image/webp'); if (!is_wp_error($webp_saved) && !empty($webp_saved['path'])) { $existing[$slug]['webp'] = wp_basename($webp_saved['path']); } } } update_post_meta($attachment_id, self::META_KEY, $existing); $this->add_log(get_the_title($attachment_id), sprintf('Created %s at %sx%s', $preset['name'], $existing[$slug]['width'], $existing[$slug]['height'])); return true; } private function add_log(string $title, string $message): void { $logs = get_option(self::LOG_OPTION, []); $logs[] = ['time' => current_time('mysql'), 'title' => $title ?: 'Untitled image', 'message' => $message]; update_option(self::LOG_OPTION, array_slice($logs, -30)); } } Smart_Image_Resizer::instance();