From e687f58a60d14391b52d33f936ee67ae2201c412 Mon Sep 17 00:00:00 2001 From: Russell Heimlich Date: Wed, 27 Sep 2023 22:52:34 -0400 Subject: [PATCH 1/8] Add Tachyon filters to our liking --- functions/class-rh-media.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/functions/class-rh-media.php b/functions/class-rh-media.php index 10bfa6d..7cc4ea1 100644 --- a/functions/class-rh-media.php +++ b/functions/class-rh-media.php @@ -33,6 +33,20 @@ public function setup_filters() { add_filter( 'embed_oembed_html', array( $this, 'filter_oembed_lite_youtube' ), 10, 3 ); add_filter( 'oembed_result', array( $this, 'filter_oembed_lite_youtube' ), 11, 2 ); add_filter( 'upload_mimes', array( $this, 'filter_upload_mimes' ), 10 ); + + // Tachyon modifications + add_filter( 'tachyon_remove_size_attributes', '__return_false' ); + add_filter( 'tachyon_disable_in_admin', '__return_false' ); + add_filter( 'tachyon_override_image_downsize', '__return_true' ); + add_filter( 'tachyon_pre_args', function ( $args ) { + if ( !empty( $args['resize'] ) ) { + $parts = explode( ',', $args['resize'] ); + $args['w'] = $parts[0]; + unset( $args['resize'] ); + } + + return $args; + } ); } /** From cb2489962619b8d2567b1eba834073cace1d4710 Mon Sep 17 00:00:00 2001 From: Russell Heimlich Date: Mon, 2 Oct 2023 23:34:28 -0400 Subject: [PATCH 2/8] Make sure the `get_field()` function exists --- functions/class-rh-posts.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/functions/class-rh-posts.php b/functions/class-rh-posts.php index 0fac563..248e091 100644 --- a/functions/class-rh-posts.php +++ b/functions/class-rh-posts.php @@ -81,6 +81,9 @@ public function action_acf_init() { * @param object|WP_Post $post Post data that was recently updated */ public function action_wp_after_insert_post( $post_id = 0, $post = null ) { + if ( ! function_exists( 'get_field' ) ) { + return; + } $field_name = 'field_processing_options_markdown'; $process_markdown = get_field( $field_name, $post_id ); if ( empty( $process_markdown ) ) { From d76210c2011e8ac71de644404329f71d41867b46 Mon Sep 17 00:00:00 2001 From: Russell Heimlich Date: Mon, 2 Oct 2023 23:40:01 -0400 Subject: [PATCH 3/8] Modify the attachment meta data being saved to the database --- functions/class-rh-media.php | 115 ++++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 9 deletions(-) diff --git a/functions/class-rh-media.php b/functions/class-rh-media.php index 7cc4ea1..697f3c4 100644 --- a/functions/class-rh-media.php +++ b/functions/class-rh-media.php @@ -4,6 +4,13 @@ */ class RH_Media { + /** + * References reconstructed sizes for an attachment + * + * @var array + */ + public static $image_sizes = null; + /** * Get an instance of this class */ @@ -34,19 +41,26 @@ public function setup_filters() { add_filter( 'oembed_result', array( $this, 'filter_oembed_lite_youtube' ), 11, 2 ); add_filter( 'upload_mimes', array( $this, 'filter_upload_mimes' ), 10 ); + // Prevent WordPress from generating intermediate sizes on upload + add_filter( 'intermediate_image_sizes_advanced', '__return_empty_array', 999 ); + add_filter( 'wp_update_attachment_metadata', array( $this, 'filter_wp_update_attachment_metadata' ), 10, 2 ); + // Tachyon modifications add_filter( 'tachyon_remove_size_attributes', '__return_false' ); add_filter( 'tachyon_disable_in_admin', '__return_false' ); add_filter( 'tachyon_override_image_downsize', '__return_true' ); - add_filter( 'tachyon_pre_args', function ( $args ) { - if ( !empty( $args['resize'] ) ) { - $parts = explode( ',', $args['resize'] ); - $args['w'] = $parts[0]; - unset( $args['resize'] ); - } + add_filter( + 'tachyon_pre_args', + function ( $args ) { + if ( ! empty( $args['resize'] ) ) { + $parts = explode( ',', $args['resize'] ); + $args['w'] = $parts[0]; + unset( $args['resize'] ); + } - return $args; - } ); + return $args; + } + ); } /** @@ -71,7 +85,6 @@ public function action_init() { $ver = null, $in_footer = true ); - } /** @@ -179,6 +192,90 @@ public function filter_upload_mimes( $mimes = array() ) { return $mimes; } + /** + * Generate our own image sizes for attachment meta data + * + * @param array $data The attachment metadata to modify + * @param integer $post_id The ID of the attachment post being updated + */ + public function filter_wp_update_attachment_metadata( $data = array(), $post_id = 0 ) { + wp_log( $data ); + $width = $data['width']; + $height = $data['height']; + $file_name = basename( $data['file'] ); + $upload_dir = wp_upload_dir(); + $absolute_path = $upload_dir['basedir'] . '/' . $data['file']; + $file_size = $data['filesize']; + $mime_type = wp_check_filetype_and_ext( $absolute_path, $file_name ); + + $sizes = array(); + $image_sizes = static::get_image_sizes(); + foreach ( $image_sizes as $key => $image_size ) { + $sizes[ $key ] = array( + 'file' => $file_name, + 'width' => $width, + 'height' => $height, + 'mime-type' => $mime_type['type'], + 'filesize' => $file_size, + ); + } + $data['sizes'] = $sizes; + return $data; + } + + /** + * Get a list of image sizes registered with WordPress + */ + public static function get_image_sizes() { + if ( static::$image_sizes !== null ) { + return static::$image_sizes; + } + + $_wp_additional_image_sizes = wp_get_additional_image_sizes(); + $sizes = array(); + /* + * Remove filter preventing WordPress from reading the sizes, it's meant + * to prevent creation of intermediate files, which are not really being used. + */ + remove_filter( 'intermediate_image_sizes', '__return_empty_array' ); + $intermediate_image_sizes = get_intermediate_image_sizes(); + add_filter( 'intermediate_image_sizes', '__return_empty_array' ); + foreach ( $intermediate_image_sizes as $s ) { + $sizes[ $s ] = array( + 'width' => '', + 'height' => '', + 'crop' => false, + ); + if ( isset( $_wp_additional_image_sizes[ $s ]['width'] ) ) { + // For theme-added sizes. + $sizes[ $s ]['width'] = intval( $_wp_additional_image_sizes[ $s ]['width'] ); + } else { + // For default sizes set in options. + $sizes[ $s ]['width'] = get_option( "{$s}_size_w" ); + } + + if ( isset( $_wp_additional_image_sizes[ $s ]['height'] ) ) { + // For theme-added sizes. + $sizes[ $s ]['height'] = intval( $_wp_additional_image_sizes[ $s ]['height'] ); + } else { + // For default sizes set in options. + $sizes[ $s ]['height'] = get_option( "{$s}_size_h" ); + } + + if ( isset( $_wp_additional_image_sizes[ $s ]['crop'] ) ) { + // For theme-added sizes. + $sizes[ $s ]['crop'] = $_wp_additional_image_sizes[ $s ]['crop']; + } else { + // For default sizes set in options. + $sizes[ $s ]['crop'] = get_option( "{$s}_crop" ); + } + } + + static::$image_sizes = $sizes; + + return $sizes; + } + /** * Get a list of human friendly image size names keyed to their image size name registered with WordPress */ From 440ad7b384a974c1edbd4c00cce64083c59f6c58 Mon Sep 17 00:00:00 2001 From: Russell Heimlich Date: Mon, 2 Oct 2023 23:56:03 -0400 Subject: [PATCH 4/8] Constrain dimensions? --- functions/class-rh-media.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/functions/class-rh-media.php b/functions/class-rh-media.php index 697f3c4..d1db672 100644 --- a/functions/class-rh-media.php +++ b/functions/class-rh-media.php @@ -199,7 +199,6 @@ public function filter_upload_mimes( $mimes = array() ) { * @param integer $post_id The ID of the attachment post being updated */ public function filter_wp_update_attachment_metadata( $data = array(), $post_id = 0 ) { - wp_log( $data ); $width = $data['width']; $height = $data['height']; $file_name = basename( $data['file'] ); @@ -210,11 +209,12 @@ public function filter_wp_update_attachment_metadata( $data = array(), $post_id $sizes = array(); $image_sizes = static::get_image_sizes(); - foreach ( $image_sizes as $key => $image_size ) { - $sizes[ $key ] = array( + foreach ( $image_sizes as $key => $image ) { + $the_dimensions = wp_constrain_dimensions( $image['width'], $image['height'], $width, $height ); + $sizes[ $key ] = array( 'file' => $file_name, - 'width' => $width, - 'height' => $height, + 'width' => $the_dimensions[0], + 'height' => $the_dimensions[1], 'mime-type' => $mime_type['type'], 'filesize' => $file_size, ); From 0dde404813468ecb44187c18df2bbecec4af6df0 Mon Sep 17 00:00:00 2001 From: Russell Heimlich Date: Tue, 3 Oct 2023 23:26:38 -0400 Subject: [PATCH 5/8] If the 'intermediate_image_sizes_advanced' filter is called during the wp_create_image_subsizes() function then return an empty array so no intermediate image sizes will be generated --- functions/class-rh-media.php | 195 ++++++++++++++++++++++++++++++++++- 1 file changed, 190 insertions(+), 5 deletions(-) diff --git a/functions/class-rh-media.php b/functions/class-rh-media.php index d1db672..7ce892a 100644 --- a/functions/class-rh-media.php +++ b/functions/class-rh-media.php @@ -41,9 +41,10 @@ public function setup_filters() { add_filter( 'oembed_result', array( $this, 'filter_oembed_lite_youtube' ), 11, 2 ); add_filter( 'upload_mimes', array( $this, 'filter_upload_mimes' ), 10 ); - // Prevent WordPress from generating intermediate sizes on upload - add_filter( 'intermediate_image_sizes_advanced', '__return_empty_array', 999 ); + // Remove intermediate sizes only if we're uploading an image + add_filter( 'intermediate_image_sizes_advanced', array( $this, 'filter_intermediate_image_sizes_advanced' ), 999 ); add_filter( 'wp_update_attachment_metadata', array( $this, 'filter_wp_update_attachment_metadata' ), 10, 2 ); + add_filter( 'image_downsize', array( $this, 'filter_image_resize' ), 5, 3 ); // Tachyon modifications add_filter( 'tachyon_remove_size_attributes', '__return_false' ); @@ -192,6 +193,21 @@ public function filter_upload_mimes( $mimes = array() ) { return $mimes; } + /** + * Disable generating intermediate images when images are uploaded + * + * @param array $sizes The intermediate sizes that will be generated + */ + public function filter_intermediate_image_sizes_advanced( $sizes = array() ) { + // If the 'intermediate_image_sizes_advanced' filter is called during the wp_create_image_subsizes() function then return an empty array so no intermediate image sizes will be generated + $backtrace = wp_debug_backtrace_summary( null, 0, false ); + $needle = array_search( 'wp_create_image_subsizes', $backtrace, true ); + if ( $needle !== false ) { + return array(); + } + return $sizes; + } + /** * Generate our own image sizes for attachment meta data * @@ -210,7 +226,7 @@ public function filter_wp_update_attachment_metadata( $data = array(), $post_id $sizes = array(); $image_sizes = static::get_image_sizes(); foreach ( $image_sizes as $key => $image ) { - $the_dimensions = wp_constrain_dimensions( $image['width'], $image['height'], $width, $height ); + $the_dimensions = wp_constrain_dimensions( $width, $height, $image['width'], $image['height'] ); $sizes[ $key ] = array( 'file' => $file_name, 'width' => $the_dimensions[0], @@ -223,6 +239,176 @@ public function filter_wp_update_attachment_metadata( $data = array(), $post_id return $data; } + /** + * Image resizing service. Takes place of image_downsize(). + * + * @param bool $ignore Unused. + * @param int $id Attachment ID for image. + * @param array|string $size Optional, default is 'medium'. Size of image, either array or string. + * @return bool|array False on failure, array on success. + * @see image_downsize() + */ + public function filter_image_resize( $ignore = false, $id = 0, $size = '' ) { + global $_wp_additional_image_sizes, $post; + + // Don't bother resizing non-image (and non-existent) attachment. + // We fallthrough to core's image_downsize but that bails as well. + $is_img = wp_attachment_is_image( $id ); + if ( ! $is_img ) { + return false; + } + + $content_width = isset( $GLOBALS['content_width'] ) ? $GLOBALS['content_width'] : null; + $crop = false; + $args = array(); + + // For resize requests coming from an image's attachment page, override + // the supplied $size and use the user-defined $content_width if the + // theme-defined $content_width has been manually passed in. + if ( is_attachment() && $id === $post->ID ) { + if ( is_array( $size ) && ! empty( $size ) && isset( $GLOBALS['content_width'] ) && $size[0] == $GLOBALS['content_width'] ) { + $size = array( $content_width, $content_width ); + } + } + + if ( 'tellyworth' == $size ) { // 'full' is reserved because some themes use it (see image_constrain_size_for_editor) + $_max_w = 4096; + $_max_h = 4096; + } elseif ( 'thumbnail' == $size ) { + $_max_w = get_option( 'thumbnail_size_w' ); + $_max_h = get_option( 'thumbnail_size_h' ); + if ( ! $_max_w && ! $_max_h ) { + $_max_w = 128; + $_max_h = 96; + } + if ( get_option( 'thumbnail_crop' ) ) { + $crop = true; + } + } elseif ( 'medium' == $size ) { + $_max_w = get_option( 'medium_size_w' ); + $_max_h = get_option( 'medium_size_h' ); + if ( ! $_max_w && ! $_max_h ) { + $_max_w = 300; + $_max_h = 300; + } + } elseif ( 'large' == $size ) { + $_max_w = get_option( 'large_size_w' ); + $_max_h = get_option( 'large_size_h' ); + } elseif ( is_array( $size ) ) { + $_max_w = $size[0] ?? 0; + $_max_h = $size[1] ?? 0; + $w = $_max_w; + $h = $_max_h; + } elseif ( ! empty( $_wp_additional_image_sizes[ $size ] ) ) { + $_max_w = $_wp_additional_image_sizes[ $size ]['width']; + $_max_h = $_wp_additional_image_sizes[ $size ]['height']; + $w = $_max_w; + $h = $_max_h; + $crop = $_wp_additional_image_sizes[ $size ]['crop']; + } elseif ( $content_width > 0 ) { + $_max_w = $content_width; + $_max_h = 0; + } else { + $_max_w = 1024; + $_max_h = 0; + } + + // Constrain default image sizes to the theme's content width, if available. + if ( $content_width > 0 && in_array( $size, array( 'thumbnail', 'medium', 'large' ) ) ) { + $_max_w = min( $_max_w, $content_width ); + } + + $resized = false; + $img_url = wp_get_attachment_url( $id ); + + /** + * Filter the original image Photon-compatible parameters before changes are + * + * @param array|string $args Array of Photon-compatible arguments. + * @param string $img_url Image URL. + */ + $args = apply_filters( 'vip_go_image_resize_pre_args', $args, $img_url ); + + if ( ! $crop ) { + $imagedata = wp_get_attachment_metadata( $id ); + + if ( ! empty( $imagedata['width'] ) || ! empty( $imagedata['height'] ) ) { + $h = $imagedata['height']; + $w = $imagedata['width']; + + list ($w, $h) = wp_constrain_dimensions( $w, $h, $_max_w, $_max_h ); + if ( $w < $imagedata['width'] || $h < $imagedata['height'] ) { + $resized = true; + } + } else { + $w = $_max_w; + $h = $_max_h; + } + } + + if ( $crop ) { + $constrain = false; + + $imagedata = wp_get_attachment_metadata( $id ); + if ( $imagedata ) { + $w = $imagedata['width'] ?? 0; + $h = $imagedata['height'] ?? 0; + } + + if ( empty( $w ) ) { + $w = $_max_w; + } + + if ( empty( $h ) ) { + $h = $_max_h; + } + + // If the image width is bigger than the allowed max, scale it to match + if ( $w >= $_max_w ) { + $w = $_max_w; + } else { + $constrain = true; + } + + // If the image height is bigger than the allowed max, scale it to match + if ( $h >= $_max_h ) { + $h = $_max_h; + } else { + $constrain = true; + } + + if ( $constrain ) { + list( $w, $h ) = wp_constrain_dimensions( $w, $h, $_max_w, $_max_h ); + } + + $args['w'] = $w; + $args['h'] = $h; + + $args['crop'] = '1'; + $resized = true; + } elseif ( 'full' != $size ) { + // we want users to be able to resize full size images with tinymce. + // the image_add_wh() filter will add the ?w= query string at display time. + $args['w'] = $w; + $resized = true; + } + + if ( is_array( $args ) ) { + // Convert values that are arrays into strings + foreach ( $args as $arg => $value ) { + if ( is_array( $value ) ) { + $args[ $arg ] = implode( ',', $value ); + } + } + // Encode values + // See http://core.trac.wordpress.org/ticket/17923 + $args = rawurlencode_deep( $args ); + } + $img_url = add_query_arg( $args, $img_url ); + + return array( $img_url, $w, $h, $resized ); + } + /** * Get a list of image sizes registered with WordPress */ @@ -233,13 +419,12 @@ public static function get_image_sizes() { $_wp_additional_image_sizes = wp_get_additional_image_sizes(); $sizes = array(); + /* * Remove filter preventing WordPress from reading the sizes, it's meant * to prevent creation of intermediate files, which are not really being used. */ - remove_filter( 'intermediate_image_sizes', '__return_empty_array' ); $intermediate_image_sizes = get_intermediate_image_sizes(); - add_filter( 'intermediate_image_sizes', '__return_empty_array' ); foreach ( $intermediate_image_sizes as $s ) { $sizes[ $s ] = array( 'width' => '', From deb860d3f0bc76e432b31f84f564743cbc2377a0 Mon Sep 17 00:00:00 2001 From: Russell Heimlich Date: Tue, 3 Oct 2023 23:32:17 -0400 Subject: [PATCH 6/8] Only modify the behavior of intermediate-sized image generation functionality if TACHYON_URL is defined --- functions/class-rh-media.php | 42 +++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/functions/class-rh-media.php b/functions/class-rh-media.php index 7ce892a..6e88093 100644 --- a/functions/class-rh-media.php +++ b/functions/class-rh-media.php @@ -41,27 +41,29 @@ public function setup_filters() { add_filter( 'oembed_result', array( $this, 'filter_oembed_lite_youtube' ), 11, 2 ); add_filter( 'upload_mimes', array( $this, 'filter_upload_mimes' ), 10 ); - // Remove intermediate sizes only if we're uploading an image - add_filter( 'intermediate_image_sizes_advanced', array( $this, 'filter_intermediate_image_sizes_advanced' ), 999 ); - add_filter( 'wp_update_attachment_metadata', array( $this, 'filter_wp_update_attachment_metadata' ), 10, 2 ); - add_filter( 'image_downsize', array( $this, 'filter_image_resize' ), 5, 3 ); - - // Tachyon modifications - add_filter( 'tachyon_remove_size_attributes', '__return_false' ); - add_filter( 'tachyon_disable_in_admin', '__return_false' ); - add_filter( 'tachyon_override_image_downsize', '__return_true' ); - add_filter( - 'tachyon_pre_args', - function ( $args ) { - if ( ! empty( $args['resize'] ) ) { - $parts = explode( ',', $args['resize'] ); - $args['w'] = $parts[0]; - unset( $args['resize'] ); + if ( defined( 'TACHYON_URL' ) && ! empty( TACHYON_URL ) ) { + // Remove intermediate sizes only if we're uploading an image + add_filter( 'intermediate_image_sizes_advanced', array( $this, 'filter_intermediate_image_sizes_advanced' ), 999 ); + add_filter( 'wp_update_attachment_metadata', array( $this, 'filter_wp_update_attachment_metadata' ), 10, 2 ); + add_filter( 'image_downsize', array( $this, 'filter_image_resize' ), 5, 3 ); + + // Tachyon modifications + add_filter( 'tachyon_remove_size_attributes', '__return_false' ); + add_filter( 'tachyon_disable_in_admin', '__return_false' ); + add_filter( 'tachyon_override_image_downsize', '__return_true' ); + add_filter( + 'tachyon_pre_args', + function ( $args ) { + if ( ! empty( $args['resize'] ) ) { + $parts = explode( ',', $args['resize'] ); + $args['w'] = $parts[0]; + unset( $args['resize'] ); + } + + return $args; } - - return $args; - } - ); + ); + } } /** From 1a6361632822fc473405537f3fc77a853ee1bc3d Mon Sep 17 00:00:00 2001 From: Russell Heimlich Date: Wed, 4 Oct 2023 22:53:23 -0400 Subject: [PATCH 7/8] Move Tachyon related functionality to it's own file --- functions.php | 3 +- functions/class-rh-media.php | 244 ----------------------------- functions/class-rh-tachyon.php | 275 +++++++++++++++++++++++++++++++++ 3 files changed, 277 insertions(+), 245 deletions(-) create mode 100644 functions/class-rh-tachyon.php diff --git a/functions.php b/functions.php index 3eec2e2..f50629b 100755 --- a/functions.php +++ b/functions.php @@ -23,6 +23,7 @@ 'class-rh-menus.php', 'class-rh-breadcrumbs.php', 'class-rh-media.php', + 'class-rh-tachyon.php', 'class-rh-scripts-and-styles.php', 'class-rh-search.php', 'class-rh-slack.php', @@ -126,7 +127,7 @@ function filter_sprig_twig_functions( $functions = array() ) { */ add_action( 'init', - function() { + function () { add_theme_support( 'title-tag' ); } ); diff --git a/functions/class-rh-media.php b/functions/class-rh-media.php index 6e88093..0616348 100644 --- a/functions/class-rh-media.php +++ b/functions/class-rh-media.php @@ -40,30 +40,6 @@ public function setup_filters() { add_filter( 'embed_oembed_html', array( $this, 'filter_oembed_lite_youtube' ), 10, 3 ); add_filter( 'oembed_result', array( $this, 'filter_oembed_lite_youtube' ), 11, 2 ); add_filter( 'upload_mimes', array( $this, 'filter_upload_mimes' ), 10 ); - - if ( defined( 'TACHYON_URL' ) && ! empty( TACHYON_URL ) ) { - // Remove intermediate sizes only if we're uploading an image - add_filter( 'intermediate_image_sizes_advanced', array( $this, 'filter_intermediate_image_sizes_advanced' ), 999 ); - add_filter( 'wp_update_attachment_metadata', array( $this, 'filter_wp_update_attachment_metadata' ), 10, 2 ); - add_filter( 'image_downsize', array( $this, 'filter_image_resize' ), 5, 3 ); - - // Tachyon modifications - add_filter( 'tachyon_remove_size_attributes', '__return_false' ); - add_filter( 'tachyon_disable_in_admin', '__return_false' ); - add_filter( 'tachyon_override_image_downsize', '__return_true' ); - add_filter( - 'tachyon_pre_args', - function ( $args ) { - if ( ! empty( $args['resize'] ) ) { - $parts = explode( ',', $args['resize'] ); - $args['w'] = $parts[0]; - unset( $args['resize'] ); - } - - return $args; - } - ); - } } /** @@ -195,222 +171,6 @@ public function filter_upload_mimes( $mimes = array() ) { return $mimes; } - /** - * Disable generating intermediate images when images are uploaded - * - * @param array $sizes The intermediate sizes that will be generated - */ - public function filter_intermediate_image_sizes_advanced( $sizes = array() ) { - // If the 'intermediate_image_sizes_advanced' filter is called during the wp_create_image_subsizes() function then return an empty array so no intermediate image sizes will be generated - $backtrace = wp_debug_backtrace_summary( null, 0, false ); - $needle = array_search( 'wp_create_image_subsizes', $backtrace, true ); - if ( $needle !== false ) { - return array(); - } - return $sizes; - } - - /** - * Generate our own image sizes for attachment meta data - * - * @param array $data The attachment metadata to modify - * @param integer $post_id The ID of the attachment post being updated - */ - public function filter_wp_update_attachment_metadata( $data = array(), $post_id = 0 ) { - $width = $data['width']; - $height = $data['height']; - $file_name = basename( $data['file'] ); - $upload_dir = wp_upload_dir(); - $absolute_path = $upload_dir['basedir'] . '/' . $data['file']; - $file_size = $data['filesize']; - $mime_type = wp_check_filetype_and_ext( $absolute_path, $file_name ); - - $sizes = array(); - $image_sizes = static::get_image_sizes(); - foreach ( $image_sizes as $key => $image ) { - $the_dimensions = wp_constrain_dimensions( $width, $height, $image['width'], $image['height'] ); - $sizes[ $key ] = array( - 'file' => $file_name, - 'width' => $the_dimensions[0], - 'height' => $the_dimensions[1], - 'mime-type' => $mime_type['type'], - 'filesize' => $file_size, - ); - } - $data['sizes'] = $sizes; - return $data; - } - - /** - * Image resizing service. Takes place of image_downsize(). - * - * @param bool $ignore Unused. - * @param int $id Attachment ID for image. - * @param array|string $size Optional, default is 'medium'. Size of image, either array or string. - * @return bool|array False on failure, array on success. - * @see image_downsize() - */ - public function filter_image_resize( $ignore = false, $id = 0, $size = '' ) { - global $_wp_additional_image_sizes, $post; - - // Don't bother resizing non-image (and non-existent) attachment. - // We fallthrough to core's image_downsize but that bails as well. - $is_img = wp_attachment_is_image( $id ); - if ( ! $is_img ) { - return false; - } - - $content_width = isset( $GLOBALS['content_width'] ) ? $GLOBALS['content_width'] : null; - $crop = false; - $args = array(); - - // For resize requests coming from an image's attachment page, override - // the supplied $size and use the user-defined $content_width if the - // theme-defined $content_width has been manually passed in. - if ( is_attachment() && $id === $post->ID ) { - if ( is_array( $size ) && ! empty( $size ) && isset( $GLOBALS['content_width'] ) && $size[0] == $GLOBALS['content_width'] ) { - $size = array( $content_width, $content_width ); - } - } - - if ( 'tellyworth' == $size ) { // 'full' is reserved because some themes use it (see image_constrain_size_for_editor) - $_max_w = 4096; - $_max_h = 4096; - } elseif ( 'thumbnail' == $size ) { - $_max_w = get_option( 'thumbnail_size_w' ); - $_max_h = get_option( 'thumbnail_size_h' ); - if ( ! $_max_w && ! $_max_h ) { - $_max_w = 128; - $_max_h = 96; - } - if ( get_option( 'thumbnail_crop' ) ) { - $crop = true; - } - } elseif ( 'medium' == $size ) { - $_max_w = get_option( 'medium_size_w' ); - $_max_h = get_option( 'medium_size_h' ); - if ( ! $_max_w && ! $_max_h ) { - $_max_w = 300; - $_max_h = 300; - } - } elseif ( 'large' == $size ) { - $_max_w = get_option( 'large_size_w' ); - $_max_h = get_option( 'large_size_h' ); - } elseif ( is_array( $size ) ) { - $_max_w = $size[0] ?? 0; - $_max_h = $size[1] ?? 0; - $w = $_max_w; - $h = $_max_h; - } elseif ( ! empty( $_wp_additional_image_sizes[ $size ] ) ) { - $_max_w = $_wp_additional_image_sizes[ $size ]['width']; - $_max_h = $_wp_additional_image_sizes[ $size ]['height']; - $w = $_max_w; - $h = $_max_h; - $crop = $_wp_additional_image_sizes[ $size ]['crop']; - } elseif ( $content_width > 0 ) { - $_max_w = $content_width; - $_max_h = 0; - } else { - $_max_w = 1024; - $_max_h = 0; - } - - // Constrain default image sizes to the theme's content width, if available. - if ( $content_width > 0 && in_array( $size, array( 'thumbnail', 'medium', 'large' ) ) ) { - $_max_w = min( $_max_w, $content_width ); - } - - $resized = false; - $img_url = wp_get_attachment_url( $id ); - - /** - * Filter the original image Photon-compatible parameters before changes are - * - * @param array|string $args Array of Photon-compatible arguments. - * @param string $img_url Image URL. - */ - $args = apply_filters( 'vip_go_image_resize_pre_args', $args, $img_url ); - - if ( ! $crop ) { - $imagedata = wp_get_attachment_metadata( $id ); - - if ( ! empty( $imagedata['width'] ) || ! empty( $imagedata['height'] ) ) { - $h = $imagedata['height']; - $w = $imagedata['width']; - - list ($w, $h) = wp_constrain_dimensions( $w, $h, $_max_w, $_max_h ); - if ( $w < $imagedata['width'] || $h < $imagedata['height'] ) { - $resized = true; - } - } else { - $w = $_max_w; - $h = $_max_h; - } - } - - if ( $crop ) { - $constrain = false; - - $imagedata = wp_get_attachment_metadata( $id ); - if ( $imagedata ) { - $w = $imagedata['width'] ?? 0; - $h = $imagedata['height'] ?? 0; - } - - if ( empty( $w ) ) { - $w = $_max_w; - } - - if ( empty( $h ) ) { - $h = $_max_h; - } - - // If the image width is bigger than the allowed max, scale it to match - if ( $w >= $_max_w ) { - $w = $_max_w; - } else { - $constrain = true; - } - - // If the image height is bigger than the allowed max, scale it to match - if ( $h >= $_max_h ) { - $h = $_max_h; - } else { - $constrain = true; - } - - if ( $constrain ) { - list( $w, $h ) = wp_constrain_dimensions( $w, $h, $_max_w, $_max_h ); - } - - $args['w'] = $w; - $args['h'] = $h; - - $args['crop'] = '1'; - $resized = true; - } elseif ( 'full' != $size ) { - // we want users to be able to resize full size images with tinymce. - // the image_add_wh() filter will add the ?w= query string at display time. - $args['w'] = $w; - $resized = true; - } - - if ( is_array( $args ) ) { - // Convert values that are arrays into strings - foreach ( $args as $arg => $value ) { - if ( is_array( $value ) ) { - $args[ $arg ] = implode( ',', $value ); - } - } - // Encode values - // See http://core.trac.wordpress.org/ticket/17923 - $args = rawurlencode_deep( $args ); - } - $img_url = add_query_arg( $args, $img_url ); - - return array( $img_url, $w, $h, $resized ); - } - /** * Get a list of image sizes registered with WordPress */ @@ -422,10 +182,6 @@ public static function get_image_sizes() { $_wp_additional_image_sizes = wp_get_additional_image_sizes(); $sizes = array(); - /* - * Remove filter preventing WordPress from reading the sizes, it's meant - * to prevent creation of intermediate files, which are not really being used. - */ $intermediate_image_sizes = get_intermediate_image_sizes(); foreach ( $intermediate_image_sizes as $s ) { $sizes[ $s ] = array( diff --git a/functions/class-rh-tachyon.php b/functions/class-rh-tachyon.php new file mode 100644 index 0000000..36f4ae9 --- /dev/null +++ b/functions/class-rh-tachyon.php @@ -0,0 +1,275 @@ +setup_actions(); + $instance->setup_filters(); + } + return $instance; + } + + /** + * Hook in to WordPress via filters + */ + public function setup_actions() {} + + /** + * Hook in to WordPress via filters + */ + public function setup_filters() { + // Bail if the TACHYON_URL constant isn't set up + if ( ! defined( 'TACHYON_URL' ) || empty( TACHYON_URL ) ) { + return; + } + + // Remove intermediate sizes only if we're uploading an image + add_filter( 'intermediate_image_sizes_advanced', array( $this, 'filter_intermediate_image_sizes_advanced' ), 999 ); + add_filter( 'wp_update_attachment_metadata', array( $this, 'filter_wp_update_attachment_metadata' ), 10, 2 ); + add_filter( 'image_downsize', array( $this, 'filter_image_resize' ), 5, 3 ); + + // Tachyon modifications + add_filter( 'tachyon_remove_size_attributes', '__return_false' ); + add_filter( 'tachyon_disable_in_admin', '__return_false' ); + add_filter( 'tachyon_override_image_downsize', '__return_true' ); + add_filter( + 'tachyon_pre_args', + function ( $args ) { + if ( ! empty( $args['resize'] ) ) { + $parts = explode( ',', $args['resize'] ); + $args['w'] = $parts[0]; + unset( $args['resize'] ); + } + + return $args; + } + ); + } + + /** + * Disable generating intermediate images when images are uploaded + * + * @param array $sizes The intermediate sizes that will be generated + */ + public function filter_intermediate_image_sizes_advanced( $sizes = array() ) { + /** + * If the 'intermediate_image_sizes_advanced' filter is called during the + * wp_create_image_subsizes() function then return an empty array so + * no intermediate image sizes will be generated + */ + $backtrace = wp_debug_backtrace_summary( null, 0, false ); + $needle = array_search( 'wp_create_image_subsizes', $backtrace, true ); + if ( $needle !== false ) { + return array(); + } + return $sizes; + } + + /** + * Generate our own image sizes for attachment meta data + * + * @param array $data The attachment metadata to modify + * @param integer $post_id The ID of the attachment post being updated + */ + public function filter_wp_update_attachment_metadata( $data = array(), $post_id = 0 ) { + $width = $data['width']; + $height = $data['height']; + $file_name = basename( $data['file'] ); + $upload_dir = wp_upload_dir(); + $absolute_path = $upload_dir['basedir'] . '/' . $data['file']; + $file_size = $data['filesize']; + $mime_type = wp_check_filetype_and_ext( $absolute_path, $file_name ); + + $sizes = array(); + $image_sizes = RH_Media::get_image_sizes(); + foreach ( $image_sizes as $key => $image ) { + $the_dimensions = wp_constrain_dimensions( $width, $height, $image['width'], $image['height'] ); + $sizes[ $key ] = array( + 'file' => $file_name, + 'width' => $the_dimensions[0], + 'height' => $the_dimensions[1], + 'mime-type' => $mime_type['type'], + 'filesize' => $file_size, + ); + } + $data['sizes'] = $sizes; + return $data; + } + + /** + * Image resizing service. Takes place of image_downsize(). + * + * @param bool $ignore Unused. + * @param int $id Attachment ID for image. + * @param array|string $size Optional, default is 'medium'. Size of image, either array or string. + * @return bool|array False on failure, array on success. + * @see image_downsize() + */ + public function filter_image_resize( $ignore = false, $id = 0, $size = '' ) { + global $_wp_additional_image_sizes, $post; + + // Don't bother resizing non-image (and non-existent) attachment. + // We fallthrough to core's image_downsize but that bails as well. + $is_img = wp_attachment_is_image( $id ); + if ( ! $is_img ) { + return false; + } + + $content_width = isset( $GLOBALS['content_width'] ) ? $GLOBALS['content_width'] : null; + $crop = false; + $args = array(); + + // For resize requests coming from an image's attachment page, override + // the supplied $size and use the user-defined $content_width if the + // theme-defined $content_width has been manually passed in. + if ( is_attachment() && $id === $post->ID ) { + if ( is_array( $size ) && ! empty( $size ) && isset( $GLOBALS['content_width'] ) && $size[0] == $GLOBALS['content_width'] ) { + $size = array( $content_width, $content_width ); + } + } + + if ( 'tellyworth' == $size ) { // 'full' is reserved because some themes use it (see image_constrain_size_for_editor) + $_max_w = 4096; + $_max_h = 4096; + } elseif ( 'thumbnail' == $size ) { + $_max_w = get_option( 'thumbnail_size_w' ); + $_max_h = get_option( 'thumbnail_size_h' ); + if ( ! $_max_w && ! $_max_h ) { + $_max_w = 128; + $_max_h = 96; + } + if ( get_option( 'thumbnail_crop' ) ) { + $crop = true; + } + } elseif ( 'medium' == $size ) { + $_max_w = get_option( 'medium_size_w' ); + $_max_h = get_option( 'medium_size_h' ); + if ( ! $_max_w && ! $_max_h ) { + $_max_w = 300; + $_max_h = 300; + } + } elseif ( 'large' == $size ) { + $_max_w = get_option( 'large_size_w' ); + $_max_h = get_option( 'large_size_h' ); + } elseif ( is_array( $size ) ) { + $_max_w = $size[0] ?? 0; + $_max_h = $size[1] ?? 0; + $w = $_max_w; + $h = $_max_h; + } elseif ( ! empty( $_wp_additional_image_sizes[ $size ] ) ) { + $_max_w = $_wp_additional_image_sizes[ $size ]['width']; + $_max_h = $_wp_additional_image_sizes[ $size ]['height']; + $w = $_max_w; + $h = $_max_h; + $crop = $_wp_additional_image_sizes[ $size ]['crop']; + } elseif ( $content_width > 0 ) { + $_max_w = $content_width; + $_max_h = 0; + } else { + $_max_w = 1024; + $_max_h = 0; + } + + // Constrain default image sizes to the theme's content width, if available. + if ( $content_width > 0 && in_array( $size, array( 'thumbnail', 'medium', 'large' ) ) ) { + $_max_w = min( $_max_w, $content_width ); + } + + $resized = false; + $img_url = wp_get_attachment_url( $id ); + + /** + * Filter the original image Photon-compatible parameters before changes are + * + * @param array|string $args Array of Photon-compatible arguments. + * @param string $img_url Image URL. + */ + $args = apply_filters( 'vip_go_image_resize_pre_args', $args, $img_url ); + + if ( ! $crop ) { + $imagedata = wp_get_attachment_metadata( $id ); + $w = $_max_w; + $h = $_max_h; + if ( ! empty( $imagedata['width'] ) || ! empty( $imagedata['height'] ) ) { + $h = $imagedata['height']; + $w = $imagedata['width']; + + list ($w, $h) = wp_constrain_dimensions( $w, $h, $_max_w, $_max_h ); + if ( $w < $imagedata['width'] || $h < $imagedata['height'] ) { + $resized = true; + } + } + } + + if ( $crop ) { + $constrain = false; + + $imagedata = wp_get_attachment_metadata( $id ); + if ( $imagedata ) { + $w = $imagedata['width'] ?? 0; + $h = $imagedata['height'] ?? 0; + } + + if ( empty( $w ) ) { + $w = $_max_w; + } + + if ( empty( $h ) ) { + $h = $_max_h; + } + + // If the image width is bigger than the allowed max, scale it to match + if ( $w >= $_max_w ) { + $w = $_max_w; + } else { + $constrain = true; + } + + // If the image height is bigger than the allowed max, scale it to match + if ( $h >= $_max_h ) { + $h = $_max_h; + } else { + $constrain = true; + } + + if ( $constrain ) { + list( $w, $h ) = wp_constrain_dimensions( $w, $h, $_max_w, $_max_h ); + } + + $args['w'] = $w; + $args['h'] = $h; + + $args['crop'] = '1'; + $resized = true; + } elseif ( 'full' != $size ) { + // we want users to be able to resize full size images with tinymce. + // the image_add_wh() filter will add the ?w= query string at display time. + $args['w'] = $w; + $resized = true; + } + + if ( is_array( $args ) ) { + // Convert values that are arrays into strings + foreach ( $args as $arg => $value ) { + if ( is_array( $value ) ) { + $args[ $arg ] = implode( ',', $value ); + } + } + // Encode values + // See http://core.trac.wordpress.org/ticket/17923 + $args = rawurlencode_deep( $args ); + } + $img_url = add_query_arg( $args, $img_url ); + + return array( $img_url, $w, $h, $resized ); + } +} +RH_Tachyon::get_instance(); From c8075c5550147279aa4a2e3a7aa87c83e1dd6dd6 Mon Sep 17 00:00:00 2001 From: Russell Heimlich Date: Wed, 4 Oct 2023 23:40:15 -0400 Subject: [PATCH 8/8] If the image size is cropped then make sure we're not scaling the sizes up --- functions/class-rh-tachyon.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/functions/class-rh-tachyon.php b/functions/class-rh-tachyon.php index 36f4ae9..79859c1 100644 --- a/functions/class-rh-tachyon.php +++ b/functions/class-rh-tachyon.php @@ -91,8 +91,18 @@ public function filter_wp_update_attachment_metadata( $data = array(), $post_id $sizes = array(); $image_sizes = RH_Media::get_image_sizes(); foreach ( $image_sizes as $key => $image ) { - $the_dimensions = wp_constrain_dimensions( $width, $height, $image['width'], $image['height'] ); - $sizes[ $key ] = array( + if ( $image['crop'] ) { + if ( $width < $image['width'] && $height < $image['height'] ) { + continue; + } + $the_dimensions = array( + $image['width'], + $image['height'], + ); + } else { + $the_dimensions = wp_constrain_dimensions( $width, $height, $image['width'], $image['height'] ); + } + $sizes[ $key ] = array( 'file' => $file_name, 'width' => $the_dimensions[0], 'height' => $the_dimensions[1],