| @@ -8,38 +8,139 @@ | ||
| 8 | 8 | |
| 9 | 9 | class WPO_Webp_Convert_Image_Task extends Updraft_Task_1_2 { |
| 10 | 10 | |
| 11 | 11 | /** |
| 12 | - * Default options. | |
| 12 | + * Meta key used to mark attachments as WebP-converted. | |
| 13 | 13 | */ |
| 14 | - public function get_default_options() { | |
| 14 | + const WEBP_CONVERSION_META_KEY = '_wpo-webp-conversion-complete'; | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * Returns the default task options. | |
| 18 | + * | |
| 19 | + * @return array<mixed> | |
| 20 | + */ | |
| 21 | + public function get_default_options(): array { | |
| 15 | 22 | return array(); |
| 16 | 23 | } |
| 17 | 24 | |
| 18 | 25 | /** |
| 19 | - * Run webp conversion for compressed images | |
| 26 | + * Runs WebP conversion for a compressed attachment's images. | |
| 20 | 27 | * |
| 28 | + * Converts all registered image sizes (including the original) to WebP, | |
| 29 | + * then marks the attachment as converted when the original succeeds. | |
| 30 | + * | |
| 21 | 31 | * @return bool |
| 22 | 32 | */ |
| 23 | - public function run() { | |
| 33 | + public function run(): bool { | |
| 34 | + $options = $this->get_task_options(); | |
| 35 | + if (!$this->is_valid_task_options($options)) { | |
| 36 | + return false; | |
| 37 | + } | |
| 38 | + | |
| 39 | + $this->switch_to_blog($options['blog_id']); | |
| 40 | + | |
| 41 | + $images = $this->get_all_attachment_images($options['attachment_id'], $options['source']); | |
| 42 | + $this->convert_images($images); | |
| 43 | + | |
| 44 | + if ($this->webp_file_exists($options['source'])) { | |
| 45 | + update_post_meta($options['attachment_id'], self::WEBP_CONVERSION_META_KEY, true); | |
| 46 | + } | |
| 47 | + | |
| 48 | + $this->restore_blog(); | |
| 49 | + | |
| 50 | + return true; | |
| 51 | + } | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * Extracts and normalizes task options into typed values. | |
| 55 | + * | |
| 56 | + * @return array{blog_id: int, attachment_id: int, source: string} | |
| 57 | + */ | |
| 58 | + private function get_task_options(): array { | |
| 24 | 59 | $blog_id = $this->get_option('blog_id'); |
| 25 | 60 | $attachment_id = $this->get_option('attachment_id'); |
| 26 | 61 | $source = $this->get_option('attachment_source'); |
| 27 | 62 | |
| 28 | - if (is_multisite()) switch_to_blog($blog_id); | |
| 63 | + return array( | |
| 64 | + 'blog_id' => is_numeric($blog_id) ? (int) $blog_id : 0, | |
| 65 | + 'attachment_id' => is_numeric($attachment_id) ? (int) $attachment_id : 0, | |
| 66 | + 'source' => is_string($source) ? $source : '', | |
| 67 | + ); | |
| 68 | + } | |
| 69 | + | |
| 70 | + /** | |
| 71 | + * Checks whether all task options contain valid, non-empty values. | |
| 72 | + * | |
| 73 | + * @param array{blog_id: int, attachment_id: int, source: string} $options | |
| 74 | + * | |
| 75 | + * @return bool | |
| 76 | + */ | |
| 77 | + private function is_valid_task_options(array $options): bool { | |
| 78 | + return !empty($options['blog_id']) | |
| 79 | + && !empty($options['attachment_id']) | |
| 80 | + && !empty($options['source']); | |
| 81 | + } | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Switches to the target blog on multisite installations. | |
| 85 | + * | |
| 86 | + * @param int $blog_id The blog ID to switch to | |
| 87 | + * | |
| 88 | + * @return void | |
| 89 | + */ | |
| 90 | + private function switch_to_blog(int $blog_id): void { | |
| 91 | + if (is_multisite()) { | |
| 92 | + switch_to_blog($blog_id); | |
| 93 | + } | |
| 94 | + } | |
| 95 | + | |
| 96 | + /** | |
| 97 | + * Restores the previous blog on multisite installations. | |
| 98 | + * | |
| 99 | + * @return void | |
| 100 | + */ | |
| 101 | + private function restore_blog(): void { | |
| 102 | + if (is_multisite()) { | |
| 103 | + restore_current_blog(); | |
| 104 | + } | |
| 105 | + } | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * Collects all image file paths for an attachment, including the original. | |
| 109 | + * | |
| 110 | + * @param int $attachment_id The attachment post ID. | |
| 111 | + * @param string $source The path to the original attachment file. | |
| 112 | + * | |
| 113 | + * @return array<string, string> Associative array of image size => file path. | |
| 114 | + */ | |
| 115 | + private function get_all_attachment_images(int $attachment_id, string $source): array { | |
| 29 | 116 | $images = WPO_Image_Utils::get_attachment_files($attachment_id); |
| 30 | 117 | $images['original'] = $source; |
| 31 | 118 | |
| 119 | + return $images; | |
| 120 | + } | |
| 121 | + | |
| 122 | + /** | |
| 123 | + * Converts each image in the list to WebP format. | |
| 124 | + * | |
| 125 | + * @param array<string, string> $images Associative array of image size => file path. | |
| 126 | + * | |
| 127 | + * @return void | |
| 128 | + */ | |
| 129 | + private function convert_images(array $images): void { | |
| 32 | 130 | foreach ($images as $image) { |
| 33 | 131 | WPO_WebP_Utils::do_webp_conversion($image); |
| 34 | 132 | } |
| 133 | + } | |
| 35 | 134 | |
| 36 | - $destination = WPO_WebP_Utils::get_destination_path($source); | |
| 37 | - if (file_exists($destination)) { | |
| 38 | - update_post_meta($attachment_id, 'wpo-webp-conversion-complete', true); | |
| 39 | - } | |
| 40 | - | |
| 41 | - if (is_multisite()) restore_current_blog(); | |
| 42 | - return true; | |
| 135 | + /** | |
| 136 | + * Checks whether a WebP version of the source file exists on disk. | |
| 137 | + * | |
| 138 | + * @param string $source The original image file path. | |
| 139 | + * | |
| 140 | + * @return bool | |
| 141 | + */ | |
| 142 | + private function webp_file_exists(string $source): bool { | |
| 143 | + return file_exists(WPO_WebP_Utils::get_destination_path($source)); | |
| 43 | 144 | } |
| 44 | 145 | } |
| 45 | 146 | endif; |