Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: first pass at enforcing image dimensions #867

Draft
wants to merge 6 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions wp/headless-wp/includes/classes/Integrations/Gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,79 @@ class Gutenberg {
*/
public function register() {
add_filter( 'render_block', [ $this, 'render_block' ], 10, 3 );
add_filter( 'render_block_core/image', [ $this, 'ensure_image_has_dimensions' ], 9999, 2 );
}

/**
* Get the image ID by URL
*
* @param string $url The image URL
*
* @return int
*/
protected function get_image_by_url( $url ) {
if ( function_exists( '\wpcom_vip_attachment_url_to_postid' ) ) {
return \wpcom_vip_attachment_url_to_postid( $url );
}

$cache_key = sprintf( 'get_image_by_%s', md5( $url ) );
$url = esc_url_raw( $url );
$id = wp_cache_get( $cache_key, 'headstartwp', false );

if ( false === $id ) {
$id = attachment_url_to_postid( $url );

/**
* If no ID was found, maybe we're dealing with a scaled big image. So, let's try that.
*
* @see https://core.trac.wordpress.org/ticket/51058
*/
if ( empty( $id ) ) {
$path_parts = pathinfo( $url );

if ( isset( $path_parts['dirname'], $path_parts['filename'], $path_parts['extension'] ) ) {
$scaled_url = trailingslashit( $path_parts['dirname'] ) . $path_parts['filename'] . '-scaled.' . $path_parts['extension'];
$id = attachment_url_to_postid( $scaled_url );
}
}

wp_cache_set( $cache_key, $id, 'headstartwp', 3 * HOUR_IN_SECONDS );
}

return $id;
}

/**
* Ensure that images have dimensions set
*
* @param string $block_content the html for the block
* @param array $block the block's schema
*
* @return string
*/
public function ensure_image_has_dimensions( $block_content, $block ) {
$doc = new \WP_HTML_Tag_Processor( $block_content );

if ( $doc->next_tag( 'img' ) ) {
$src = $doc->get_attribute( 'src' );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicholasio maybe worth checking here if it has width and heigh attributes already to bail early. As if in the case something else added it before this hook runs


$src_check = str_replace( 'http://', 'https://', $src );
$site_url = str_replace( 'http://', 'https://', get_site_url() );

// check if $src is a image hosted in the current wp install and block has no ID
if ( str_contains( $src_check, $site_url ) && empty( $block['attrs']['id'] ) ) {
$image_id = $this->get_image_by_url( $src );

if ( $image_id ) {
$img = wp_img_tag_add_width_and_height_attr( $block_content, 'the_content', $image_id );
$img = wp_img_tag_add_srcset_and_sizes_attr( $img, 'the_content', $image_id );

return $img;
}
}
}

return $block_content;
}

/**
Expand Down
34 changes: 32 additions & 2 deletions wp/headless-wp/tests/php/tests/TestGutenbergIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
namespace HeadlessWP\Tests;

use HeadlessWP\Integrations\Gutenberg;
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
use WP_HTML_Tag_Processor;
use WP_UnitTestCase;

/**
* Covers the test for the Gutenberg integration
*/
class TestGutenbergIntegration extends TestCase {
class TestGutenbergIntegration extends WP_UnitTestCase {

/**
* The Gutenberg parser
Expand Down Expand Up @@ -150,4 +151,33 @@ public function test_render_classic_block_tag_api() {

remove_filter( 'tenup_headless_wp_render_block_use_tag_processor', '__return_true' );
}

/**
* Tests that all uploaded images have width and height attributes when rendered
*
* @return void
*/
public function test_ensure_image_width_height() {
$post = $this->factory()->post->create_and_get();
$attachment_id = $this->factory()->attachment->create_upload_object( __DIR__ . '/assets/dummy-image.png', $post->ID );
$src = wp_get_attachment_image_url( $attachment_id, 'full' );

// simulate an image without dimensions
$block = $this->render_from_block_markup( "<!-- wp:image {} --> <figure class=\"wp-block-image\"><img src=\"$src\" alt=\"\"/></figure> <!-- /wp:image -->" );
$enhanced_block = $this->parser->ensure_image_has_dimensions( $block['html'], $block['parsed_block'] );

$doc = new WP_HTML_Tag_Processor( $enhanced_block );
$doc->next_tag( 'img' );

$this->assertEquals( $doc->get_attribute( 'width' ), 213 );
$this->assertEquals( $doc->get_attribute( 'height' ), 237 );

// simulate an image with dimensions
$block = $this->render_from_block_markup( "<!-- wp:image {\"id\":$attachment_id} --> <figure class=\"wp-block-image\"><img class=\"wp-image-$attachment_id\" src=\"$src\" alt=\"\"/></figure> <!-- /wp:image -->" );
$doc = new WP_HTML_Tag_Processor( $block['html'] );
$doc->next_tag( 'img' );

$this->assertEquals( $doc->get_attribute( 'width' ), 213 );
$this->assertEquals( $doc->get_attribute( 'height' ), 237 );
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading