Skip to content

Instantly share code, notes, and snippets.

@joemcgill
Last active October 10, 2024 18:10
Show Gist options
  • Save joemcgill/77a37e862d49bf47db9c06c8265338e0 to your computer and use it in GitHub Desktop.
Save joemcgill/77a37e862d49bf47db9c06c8265338e0 to your computer and use it in GitHub Desktop.
Experimental: image sizes calculation during block rendering
<?php
/**
* Plugin Name: Experimental Image Sizes
* Description: MU plugin for experiemnting with `sizes` calulations.
* Version: 0.1.0
*/
add_filter( 'render_block_core/image', 'wpp_add_image_block_sizes', 10, 3 );
/**
* Calculate image sizes attribute for an image block during rendering.
*
* @param string $block_content The block content.
* @param array $parsed_block The parsed block data.
* @param WP_Block $wp_block The block instance.
* @return string The updated block content.
*/
function wpp_add_image_block_sizes( $block_content, $parsed_block, $wp_block ) {
/**
* Callback for calculating image sizes attribute value for an image block.
*
* This is a workaround to use block context data when calculating the img sizes attribute.
*
* @since 😎
*
* @param string $sizes The image sizes attribute value.
* @param array $size The image size data.
*/
$filter = function( $sizes, $size ) use ( $wp_block ) {
$alignment = $wp_block->attributes['align'] ?? '';
// Hypotehtical function to calculate better sizes.
$sizes = wpp_better_sizes_calc( $size, $alignment );
return $sizes;
};
// Hook this filter early, before default fitlers are run.
add_filter( 'wp_calculate_image_sizes', $filter, 9, 2 );
/*
* A performance problem to still be solved with this approach is that
* wp_calculate_image_sizes() will make a DB query to get the image metadata.
* It does this to get the image width, which is needed to calculate
* the sizes attribute. Currently, this function is called from `wp_filter_content_tags`
* which has already primed the cache with the image metadata. That cache priming
* will need to be hanlded earlier if sizes is calculated during block rendering.
*/
$sizes = wp_calculate_image_sizes(
// If we don't have a size slug, assume the full size was used.
$parsed_block['attrs']['sizeSlug'] ?? 'full',
null,
null,
$parsed_block['attrs']['id'] ?? 0
);
remove_filter( 'wp_calculate_image_sizes', $filter, 9 );
// Bail early if sizes are not calculated.
if ( ! $sizes ) {
return $block_content;
}
// Add the sizes attribute to the image tag here.
$processor = new WP_HTML_Tag_Processor( $block_content );
$processor->next_tag( 'img' );
$processor->set_attribute( 'sizes', $sizes );
$return = $processor->get_updated_html();
return $return;
};
/**
* Hypothetical function to calculate better sizes.
*
* @param array $size The image size data.
* @param string $alignment The image alignment.
* @return string The sizes attribute value.
*/
function wpp_better_sizes_calc( $size, $alignment ) {
switch ( $alignment ) {
case 'full':
return '100vw';
break;
case 'wide':
// Hard coded wide size from TT4 theme for demo only.
return '(max-width: 1280px) 100vw, 1280px';
break;
default:
// Hard coded wide size from TT4 theme for demo only.
return '(max-width: 620px) 100vw, 620px';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment