Implementation:
- public static functions provide the methods that are called by the filter
- most of the work is common to all filters (URL analysis, directory gymnastics, file caching, error management) and done by private static functions
- the specific part (actual image processing) is delegated to dedicated subclasses of TimberImageOperation
/** * Generate image sizes defined for Timmy with TimberImageHelper. * * @param int $attachment_id The attachment ID for which all images should be resized * @return void */ private function timber_generate_sizes($attachment_id) { $img_sizes = get_image_sizes(); $attachment = get_post($attachment_id); // Timber needs the file src as an url $file_src = wp_get_attachment_url($attachment_id); /** * Delete all existing image sizes for that file. * * This way, when Regenerate Thumbnails will be used, * all non-registered image sizes will be deleted as well. * Because Timber creates image sizes when they’re needed, * we can safely do this. */ Timber\ImageHelper::delete_generated_files($file_src); foreach ($img_sizes as $key => $img_size) { if (!$this->timber_should_resize($attachment->post_parent, $img_size)) { continue; } $resize = $img_size['resize']; // Get values for the default image $crop = isset($resize[2]) ? $resize[2] : 'default'; $force = isset($resize[3]) ? $resize[3] : false; image_downsize($attachment_id, $key); if (isset($img_size['generate_srcset_sizes']) && false === $img_size['generate_srcset_sizes']) { continue; } // Generate additional image sizes used for srcset if (isset($img_size['srcset'])) { foreach ($img_size['srcset'] as $src) { // Get width and height for the additional src if (is_array($src)) { $width = $src[0]; $height = isset($src[1]) ? $src[1] : 0; } else { $width = (int) round($resize[0] * $src); $height = isset($resize[1]) ? (int) round($resize[1] * $src) : 0; } // For the new source, we use the same $crop and $force values as the default image self::resize($img_size, $file_src, $width, $height, $crop, $force); } } } }
/** * @codeCoverageIgnore */ protected static function init() { if (class_exists('\\WP') && !defined('TIMBER_LOADED')) { Twig::init(); ImageHelper::init(); Admin::init(); Integrations::init(); define('TIMBER_LOADED', true); } }
/** * Deletes all resized versions of an image when the source is deleted */ protected static function add_actions() { add_action('delete_attachment', function ($post_id) { $post = get_post($post_id); $image_types = array('image/jpeg', 'image/png', 'image/gif', 'image/jpg'); if (in_array($post->post_mime_type, $image_types)) { $attachment = new Image($post_id); if ($attachment->file_loc) { ImageHelper::delete_generated_files($attachment->file_loc); } } }); }
/** * Checks if attachment is an image before deleting generated files * * @param int $post_id an attachment post id * */ public static function _delete_generated_if_image($post_id) { if (wp_attachment_is_image($post_id)) { $attachment = new Image($post_id); if ($attachment->file_loc) { ImageHelper::delete_generated_files($attachment->file_loc); } } }
/** * Deletes all resized versions of an image when the source is deleted * or its meta data is regenerated */ protected static function add_actions() { add_action('delete_attachment', function ($post_id) { \Timber\ImageHelper::_delete_generated_if_image($post_id); }); add_filter('wp_generate_attachment_metadata', function ($metadata, $post_id) { \Timber\ImageHelper::_delete_generated_if_image($post_id); return $metadata; }, 10, 2); }
/** * Performs the actual image manipulation, * including saving the target file. * * @param string $load_filename filepath (not URL) to source file * (ex: /src/var/www/wp-content/uploads/my-pic.jpg) * @param string $save_filename filepath (not URL) where result file should be saved * (ex: /src/var/www/wp-content/uploads/my-pic-300x200-c-default.jpg) * @return boolean|null true if everything went fine, false otherwise */ public function run($load_filename, $save_filename) { //should be resized by gif resizer if (\Timber\ImageHelper::is_animated_gif($load_filename)) { //attempt to resize //return if successful //proceed if not $gif = self::run_animated_gif($load_filename, $save_filename); if ($gif) { return true; } } $image = wp_get_image_editor($load_filename); if (!is_wp_error($image)) { $crop = self::get_target_sizes($load_filename); $image->crop($crop['x'], $crop['y'], $crop['src_w'], $crop['src_h'], $crop['target_w'], $crop['target_h']); $result = $image->save($save_filename); if (is_wp_error($result)) { // @codeCoverageIgnoreStart Helper::error_log('Error resizing image'); Helper::error_log($result); return false; // @codeCoverageIgnoreEnd } else { return true; } } else { if (isset($image->error_data['error_loading_image'])) { // @codeCoverageIgnoreStart Helper::error_log('Error loading ' . $image->error_data['error_loading_image']); } else { Helper::error_log($image); // @codeCoverageIgnoreEnd } } }