Skip to content

Commit

Permalink
Merge pull request #1704 from WordPress/update/poc-pass-alignment-by-…
Browse files Browse the repository at this point in the history
…context

POC - Pass group block alignment context to image block
  • Loading branch information
mukeshpanchal27 authored Nov 28, 2024
2 parents ee5f028 + 5a9ce37 commit 2085845
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/php-test-plugins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
coverage: [false]
include:
- php: '7.4'
wp: '6.5'
wp: '6.6'
- php: '8.3'
wp: 'trunk'
- php: '8.2'
Expand Down
2 changes: 2 additions & 0 deletions plugins/auto-sizes/hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ function auto_sizes_render_generator(): void {
add_filter( 'the_content', 'auto_sizes_prime_attachment_caches', 9 ); // This must run before 'do_blocks', which runs at priority 9.
add_filter( 'render_block_core/image', 'auto_sizes_filter_image_tag', 10, 3 );
add_filter( 'render_block_core/cover', 'auto_sizes_filter_image_tag', 10, 3 );
add_filter( 'get_block_type_uses_context', 'auto_sizes_allowed_uses_context_for_image_blocks', 10, 2 );
add_filter( 'render_block_context', 'auto_sizes_modify_render_block_context', 10, 2 );
108 changes: 91 additions & 17 deletions plugins/auto-sizes/includes/improve-calculate-sizes.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ function auto_sizes_filter_image_tag( $content, array $parsed_block, WP_Block $b
if ( ! is_string( $content ) ) {
return '';
}

$processor = new WP_HTML_Tag_Processor( $content );
$has_image = $processor->next_tag( array( 'tag_name' => 'IMG' ) );

Expand All @@ -98,12 +99,14 @@ function auto_sizes_filter_image_tag( $content, array $parsed_block, WP_Block $b
* @param string $sizes The image sizes attribute value.
* @param string $size The image size data.
*/
$filter = static function ( $sizes, $size ) use ( $block ) {
$id = $block->attributes['id'] ?? 0;
$alignment = $block->attributes['align'] ?? '';
$width = $block->attributes['width'] ?? '';
$filter = static function ( $sizes, $size ) use ( $block, $parsed_block ) {
$id = $block->attributes['id'] ?? 0;
$alignment = $block->attributes['align'] ?? '';
$width = $block->attributes['width'] ?? '';
$has_parent_block = isset( $parsed_block['parentLayout'] );
$ancestor_block_align = $block->context['ancestor_block_align'] ?? '';

return auto_sizes_calculate_better_sizes( (int) $id, (string) $size, (string) $alignment, (string) $width );
return auto_sizes_calculate_better_sizes( (int) $id, (string) $size, (string) $alignment, (string) $width, $has_parent_block, (string) $ancestor_block_align );
};

// Hook this filter early, before default filters are run.
Expand Down Expand Up @@ -135,50 +138,121 @@ function auto_sizes_filter_image_tag( $content, array $parsed_block, WP_Block $b
/**
* Modifies the sizes attribute of an image based on layout context.
*
* @param int $id The image id.
* @param string $size The image size data.
* @param string $align The image alignment.
* @param string $resize_width Resize image width.
* @since n.e.x.t
*
* @param int $id The image id.
* @param string $size The image size data.
* @param string $align The image alignment.
* @param string $resize_width Resize image width.
* @param bool $has_parent_block Check if image block has parent block.
* @param string $ancestor_block_align The ancestor block alignment.
* @return string The sizes attribute value.
*/
function auto_sizes_calculate_better_sizes( int $id, string $size, string $align, string $resize_width ): string {
$sizes = '';
function auto_sizes_calculate_better_sizes( int $id, string $size, string $align, string $resize_width, bool $has_parent_block, string $ancestor_block_align ): string {
$image = wp_get_attachment_image_src( $id, $size );

if ( false === $image ) {
return $sizes;
return '';
}

// Retrieve width from the image tag itself.
$image_width = '' !== $resize_width ? (int) $resize_width : $image[1];

if ( $has_parent_block ) {
if ( 'full' === $ancestor_block_align && 'full' === $align ) {
return auto_sizes_get_sizes_by_block_alignments( $align, $image_width, true );
} elseif ( 'full' !== $ancestor_block_align && 'full' === $align ) {
return auto_sizes_get_sizes_by_block_alignments( $ancestor_block_align, $image_width, true );
} elseif ( 'full' !== $ancestor_block_align ) {
$parent_block_alignment_width = auto_sizes_get_sizes_by_block_alignments( $ancestor_block_align, $image_width );
$block_alignment_width = auto_sizes_get_sizes_by_block_alignments( $align, $image_width );
if ( (int) $parent_block_alignment_width < (int) $block_alignment_width ) {
return sprintf( '(max-width: %1$s) 100vw, %1$s', $parent_block_alignment_width );
} else {
return sprintf( '(max-width: %1$s) 100vw, %1$s', $block_alignment_width );
}
}
}

return auto_sizes_get_sizes_by_block_alignments( $align, $image_width, true );
}

/**
* Generates the `sizes` attribute value based on block information.
*
* @since n.e.x.t
*
* @param string $alignment The alignment.
* @param int $image_width The image width.
* @param bool $print_sizes Print the sizes attribute. Default is false.
* @return string The sizes attribute value.
*/
function auto_sizes_get_sizes_by_block_alignments( string $alignment, int $image_width, bool $print_sizes = false ): string {
$sizes = '';

$layout = wp_get_global_settings( array( 'layout' ) );

// Handle different alignment use cases.
switch ( $align ) {
switch ( $alignment ) {
case 'full':
$sizes = '100vw';
break;

case 'wide':
if ( array_key_exists( 'wideSize', $layout ) ) {
$sizes = sprintf( '(max-width: %1$s) 100vw, %1$s', $layout['wideSize'] );
$sizes = $layout['wideSize'];
}
break;

case 'left':
case 'right':
case 'center':
$sizes = sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $image_width );
$sizes = auto_sizes_get_width( '', $image_width );
break;

default:
if ( array_key_exists( 'contentSize', $layout ) ) {
$width = auto_sizes_get_width( $layout['contentSize'], $image_width );
$sizes = sprintf( '(max-width: %1$s) 100vw, %1$s', $width );
$sizes = auto_sizes_get_width( $layout['contentSize'], $image_width );
}
break;
}

if ( $print_sizes ) {
$sizes = 'full' === $alignment ? $sizes : sprintf( '(max-width: %1$s) 100vw, %1$s', $sizes );
}

return $sizes;
}

/**
* Filters the context keys that a block type uses.
*
* @since n.e.x.t
*
* @param array<string> $uses_context Array of registered uses context for a block type.
* @param WP_Block_Type $block_type The full block type object.
* @return array<string> The filtered context keys used by the block type.
*/
function auto_sizes_allowed_uses_context_for_image_blocks( array $uses_context, WP_Block_Type $block_type ): array {
if ( 'core/image' === $block_type->name ) {
// Use array_values to reset the array keys after merging.
return array_values( array_unique( array_merge( $uses_context, array( 'ancestor_block_align' ) ) ) );
}
return $uses_context;
}

/**
* Modifies the block context during rendering to blocks.
*
* @since n.e.x.t
*
* @param array<string, mixed> $context Current block context.
* @param array<string, mixed> $block The block being rendered.
* @return array<string, mixed> Modified block context.
*/
function auto_sizes_modify_render_block_context( array $context, array $block ): array {
if ( 'core/group' === $block['blockName'] || 'core/columns' === $block['blockName'] ) {
$context['ancestor_block_align'] = $block['attrs']['align'] ?? '';
}
return $context;
}
137 changes: 121 additions & 16 deletions plugins/auto-sizes/tests/test-improve-calculate-sizes.php
Original file line number Diff line number Diff line change
Expand Up @@ -389,41 +389,146 @@ public function test_no_image(): void {
/**
* Test that the layout property of a group block is passed by context to the image block.
*
* @group test
* @dataProvider data_ancestor_and_image_block_alignment
*
* @param string $ancestor_block_alignment Ancestor block alignment.
* @param string $image_block_alignment Image block alignment.
* @param string $expected Expected output.
*/
public function test_ancestor_layout_is_passed_by_context(): void {
public function test_ancestor_layout_is_passed_by_context( string $ancestor_block_alignment, string $image_block_alignment, string $expected ): void {
$block_content = $this->get_group_block_markup(
$this->get_image_block_markup( self::$image_id, 'large', 'full' )
$this->get_image_block_markup( self::$image_id, 'large', $image_block_alignment ),
array(
'align' => $ancestor_block_alignment,
)
);

$result = apply_filters( 'the_content', $block_content );

$this->assertStringContainsString( 'sizes="(max-width: 620px) 100vw, 620px" ', $result );
$this->assertStringContainsString( $expected, $result );
}

/**
* Data provider.
*
* @return array<string, array<int, bool|string>> The ancestor and image alignments.
*/
public function data_ancestor_and_image_block_alignment(): array {
return array(
// Parent default alignment.
'Return contentSize 620px, parent block default alignment, image block default alignment' => array(
'',
'',
'sizes="(max-width: 620px) 100vw, 620px" ',
),
'Return contentSize 620px, parent block default alignment, image block wide alignment' => array(
'',
'wide',
'sizes="(max-width: 620px) 100vw, 620px" ',
),
'Return contentSize 620px, parent block default alignment, image block full alignment' => array(
'',
'full',
'sizes="(max-width: 620px) 100vw, 620px" ',
),
'Return contentSize 620px, parent block default alignment, image block left alignment' => array(
'',
'left',
'sizes="(max-width: 620px) 100vw, 620px" ',
),
'Return contentSize 620px, parent block default alignment, image block center alignment' => array(
'',
'center',
'sizes="(max-width: 620px) 100vw, 620px" ',
),
'Return contentSize 620px, parent block default alignment, image block right alignment' => array(
'',
'right',
'sizes="(max-width: 620px) 100vw, 620px" ',
),

// Parent wide alignment.
'Return contentSize 620px, parent block wide alignment, image block default alignment' => array(
'wide',
'',
'sizes="(max-width: 620px) 100vw, 620px" ',
),
'Return wideSize 1280px, parent block wide alignment, image block wide alignment' => array(
'wide',
'wide',
'sizes="(max-width: 1280px) 100vw, 1280px" ',
),
'Return wideSize 1280px, parent block wide alignment, image block full alignment' => array(
'wide',
'full',
'sizes="(max-width: 1280px) 100vw, 1280px" ',
),
'Return image size 1024px, parent block wide alignment, image block left alignment' => array(
'wide',
'left',
'sizes="(max-width: 1024px) 100vw, 1024px" ',
),
'Return image size 1024px, parent block wide alignment, image block center alignment' => array(
'wide',
'center',
'sizes="(max-width: 1024px) 100vw, 1024px" ',
),
'Return image size 1024px, parent block wide alignment, image block right alignment' => array(
'wide',
'right',
'sizes="(max-width: 1024px) 100vw, 1024px" ',
),

// Parent full alignment.
'Return contentSize 620px, parent block full alignment, image block default alignment' => array(
'full',
'',
'sizes="(max-width: 620px) 100vw, 620px" ',
),
'Return wideSize 1280px, parent block full alignment, image block wide alignment' => array(
'full',
'wide',
'sizes="(max-width: 1280px) 100vw, 1280px" ',
),
'Return full size, parent block full alignment, image block full alignment' => array(
'full',
'full',
'sizes="100vw" ',
),
'Return image size 1024px, parent block full alignment, image block left alignment' => array(
'full',
'left',
'sizes="(max-width: 1024px) 100vw, 1024px" ',
),
'Return image size 1024px, parent block full alignment, image block center alignment' => array(
'full',
'center',
'sizes="(max-width: 1024px) 100vw, 1024px" ',
),
'Return image size 1024px, parent block full alignment, image block right alignment' => array(
'full',
'right',
'sizes="(max-width: 1024px) 100vw, 1024px" ',
),
);
}

/**
* Helper to generate image block markup.
*
* @param int $attachment_id Attachment ID.
* @param string $size Optional. Image size. Default 'full'.
* @param string $align Optional. Image alignment. Default null.
* @param string $align Optional. Image alignment. Default null.
* @return string Image block markup.
*/
public function get_image_block_markup( int $attachment_id, string $size = 'full', string $align = null ): string {
$image_url = wp_get_attachment_image_url( $attachment_id, $size );

$atts = wp_parse_args(
array(
'id' => $attachment_id,
'sizeSlug' => $size,
'align' => $align,
),
array(
'id' => $attachment_id,
'sizeSlug' => 'large',
'linkDestination' => 'none',
)
$atts = array(
'id' => $attachment_id,
'sizeSlug' => $size,
'align' => $align,
'linkDestination' => 'none',
);

return '<!-- wp:image ' . wp_json_encode( $atts ) . ' --><figure class="wp-block-image size-' . $size . '"><img src="' . $image_url . '" alt="" class="wp-image-' . $attachment_id . '"/></figure><!-- /wp:image -->';
Expand Down

0 comments on commit 2085845

Please sign in to comment.