5
5
* @package automattic/jetpack
6
6
*/
7
7
8
+ use Automattic \Block_Delimiter ;
8
9
use Automattic \Jetpack \Image_CDN \Image_CDN_Core ;
9
10
10
11
/**
@@ -421,6 +422,7 @@ public static function from_thumbnail( $post_id, $width = 200, $height = 200 ) {
421
422
* Get images from Gutenberg Image blocks.
422
423
*
423
424
* @since 6.9.0
425
+ * @since $$next-version$$ Updated to use Block_Delimiter for improved performance.
424
426
*
425
427
* @param mixed $html_or_id The HTML string to parse for images, or a post id.
426
428
* @param int $width Minimum Image width.
@@ -435,32 +437,36 @@ public static function from_blocks( $html_or_id, $width = 200, $height = 200 ) {
435
437
return $ images ;
436
438
}
437
439
438
- // Look for block information in the HTML.
439
- $ blocks = parse_blocks ( $ html_info ['html ' ] );
440
- if ( empty ( $ blocks ) ) {
441
- return $ images ;
442
- }
443
-
444
440
/*
445
- * Let's loop through our blocks.
446
- * Some blocks may include some other blocks. Let's go 2 levels deep to look for blocks
447
- * that we support and that may include images (see get_images_from_block)
448
- *
449
- * @to-do: instead of looping manually (that's a lot of if and loops), search recursively instead.
441
+ * Use Block_Delimiter to parse our post content HTML,
442
+ * and find all the block delimiters for supported blocks,
443
+ * whether they're parent or nested blocks.
450
444
*/
451
- foreach ( $ blocks as $ block ) {
452
- if ( ! self ::is_nested_block ( $ block ) || 'core/media-text ' === $ block ['blockName ' ] ) {
453
- $ images = self ::get_images_from_block ( $ images , $ block , $ html_info , $ width , $ height );
454
- } else {
455
- foreach ( $ block ['innerBlocks ' ] as $ inner_block ) {
456
- if ( ! self ::is_nested_block ( $ inner_block ) ) {
457
- $ images = self ::get_images_from_block ( $ images , $ inner_block , $ html_info , $ width , $ height );
458
- } else {
459
- foreach ( $ inner_block ['innerBlocks ' ] as $ inner_inner_block ) {
460
- $ images = self ::get_images_from_block ( $ images , $ inner_inner_block , $ html_info , $ width , $ height );
461
- }
462
- }
463
- }
445
+ $ supported_blocks = array (
446
+ 'core/image ' ,
447
+ 'core/media-text ' ,
448
+ 'core/gallery ' ,
449
+ 'jetpack/tiled-gallery ' ,
450
+ 'jetpack/slideshow ' ,
451
+ 'jetpack/story ' ,
452
+ );
453
+
454
+ foreach ( Block_Delimiter::scan_delimiters ( $ html_info ['html ' ] ) as $ where => $ delimiter ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
455
+ // Only process opening delimiters for supported block types.
456
+ if ( Block_Delimiter::OPENER !== $ delimiter ->get_delimiter_type () ) {
457
+ continue ;
458
+ }
459
+
460
+ $ block_type = $ delimiter ->allocate_and_return_block_type ();
461
+ if ( ! in_array ( $ block_type , $ supported_blocks , true ) ) {
462
+ continue ;
463
+ }
464
+
465
+ $ attributes = $ delimiter ->allocate_and_return_parsed_attributes () ?? array ();
466
+ $ block_images = self ::get_images_from_block_attributes ( $ block_type , $ attributes , $ html_info , $ width , $ height );
467
+
468
+ if ( ! empty ( $ block_images ) ) {
469
+ $ images = array_merge ( $ images , $ block_images );
464
470
}
465
471
}
466
472
@@ -471,6 +477,64 @@ public static function from_blocks( $html_or_id, $width = 200, $height = 200 ) {
471
477
return array_filter ( $ images );
472
478
}
473
479
480
+ /**
481
+ * Extract images from block attributes based on block type.
482
+ *
483
+ * @since $$next-version$$
484
+ *
485
+ * @param string $block_type Block type name.
486
+ * @param array $attributes Block attributes.
487
+ * @param array $html_info Info about the post where the block is found.
488
+ * @param int $width Desired image width.
489
+ * @param int $height Desired image height.
490
+ *
491
+ * @return array Array of images found.
492
+ */
493
+ private static function get_images_from_block_attributes ( $ block_type , $ attributes , $ html_info , $ width , $ height ) {
494
+ $ images = array ();
495
+
496
+ switch ( $ block_type ) {
497
+ case 'core/image ' :
498
+ case 'core/media-text ' :
499
+ $ id_key = 'core/image ' === $ block_type ? 'id ' : 'mediaId ' ;
500
+ if ( ! empty ( $ attributes [ $ id_key ] ) ) {
501
+ $ image = self ::get_attachment_data ( $ attributes [ $ id_key ], $ html_info ['post_url ' ], $ width , $ height );
502
+ if ( false !== $ image ) {
503
+ $ images [] = $ image ;
504
+ }
505
+ }
506
+ break ;
507
+
508
+ case 'core/gallery ' :
509
+ case 'jetpack/tiled-gallery ' :
510
+ case 'jetpack/slideshow ' :
511
+ if ( ! empty ( $ attributes ['ids ' ] ) && is_array ( $ attributes ['ids ' ] ) ) {
512
+ foreach ( $ attributes ['ids ' ] as $ img_id ) {
513
+ $ image = self ::get_attachment_data ( $ img_id , $ html_info ['post_url ' ], $ width , $ height );
514
+ if ( false !== $ image ) {
515
+ $ images [] = $ image ;
516
+ }
517
+ }
518
+ }
519
+ break ;
520
+
521
+ case 'jetpack/story ' :
522
+ if ( ! empty ( $ attributes ['mediaFiles ' ] ) && is_array ( $ attributes ['mediaFiles ' ] ) ) {
523
+ foreach ( $ attributes ['mediaFiles ' ] as $ media_file ) {
524
+ if ( ! empty ( $ media_file ['id ' ] ) ) {
525
+ $ image = self ::get_attachment_data ( $ media_file ['id ' ], $ html_info ['post_url ' ], $ width , $ height );
526
+ if ( false !== $ image ) {
527
+ $ images [] = $ image ;
528
+ }
529
+ }
530
+ }
531
+ }
532
+ break ;
533
+ }
534
+
535
+ return $ images ;
536
+ }
537
+
474
538
/**
475
539
* Very raw -- just parse the HTML and pull out any/all img tags and return their src
476
540
*
@@ -1028,81 +1092,6 @@ public static function get_alt_text( $attachment_id ) {
1028
1092
return (string ) get_post_meta ( $ attachment_id , '_wp_attachment_image_alt ' , true );
1029
1093
}
1030
1094
1031
- /**
1032
- * Get an image from a block.
1033
- *
1034
- * @since 7.8.0
1035
- *
1036
- * @param array $images Images found.
1037
- * @param array $block Block and its attributes.
1038
- * @param array $html_info Info about the post where the block is found.
1039
- * @param int $width Desired image width.
1040
- * @param int $height Desired image height.
1041
- *
1042
- * @return array Array of images found.
1043
- */
1044
- private static function get_images_from_block ( $ images , $ block , $ html_info , $ width , $ height ) {
1045
- /**
1046
- * Parse content from Core Image blocks.
1047
- * If it is an image block for an image hosted on our site, it will have an ID.
1048
- * If it does not have an ID, let `from_html` parse that content later,
1049
- * and extract an image if it has size parameters.
1050
- */
1051
- if (
1052
- 'core/image ' === $ block ['blockName ' ]
1053
- && ! empty ( $ block ['attrs ' ]['id ' ] )
1054
- ) {
1055
- $ images [] = self ::get_attachment_data ( $ block ['attrs ' ]['id ' ], $ html_info ['post_url ' ], $ width , $ height );
1056
- } elseif (
1057
- 'core/media-text ' === $ block ['blockName ' ]
1058
- && ! empty ( $ block ['attrs ' ]['mediaId ' ] )
1059
- ) {
1060
- $ images [] = self ::get_attachment_data ( $ block ['attrs ' ]['mediaId ' ], $ html_info ['post_url ' ], $ width , $ height );
1061
- } elseif (
1062
- /**
1063
- * Parse content from Core Gallery blocks as well from Jetpack's Tiled Gallery and Slideshow blocks.
1064
- * Gallery blocks include the ID of each one of the images in the gallery.
1065
- */
1066
- in_array ( $ block ['blockName ' ], array ( 'core/gallery ' , 'jetpack/tiled-gallery ' , 'jetpack/slideshow ' ), true )
1067
- && ! empty ( $ block ['attrs ' ]['ids ' ] )
1068
- ) {
1069
- foreach ( $ block ['attrs ' ]['ids ' ] as $ img_id ) {
1070
- $ images [] = self ::get_attachment_data ( $ img_id , $ html_info ['post_url ' ], $ width , $ height );
1071
- }
1072
- } elseif (
1073
- /**
1074
- * Parse content from Jetpack's Story block.
1075
- */
1076
- 'jetpack/story ' === $ block ['blockName ' ]
1077
- && ! empty ( $ block ['attrs ' ]['mediaFiles ' ] )
1078
- ) {
1079
- foreach ( $ block ['attrs ' ]['mediaFiles ' ] as $ media_file ) {
1080
- if ( ! empty ( $ media_file ['id ' ] ) ) {
1081
- $ images [] = self ::get_attachment_data ( $ media_file ['id ' ], $ html_info ['post_url ' ], $ width , $ height );
1082
- }
1083
- }
1084
- }
1085
-
1086
- return $ images ;
1087
- }
1088
-
1089
- /**
1090
- * Check if a block has inner blocks.
1091
- *
1092
- * @since 7.8.0
1093
- *
1094
- * @param array $block Block and its attributes.
1095
- *
1096
- * @return bool
1097
- */
1098
- private static function is_nested_block ( $ block ) {
1099
- if ( ! empty ( $ block ['innerBlocks ' ] ) ) {
1100
- return true ;
1101
- }
1102
-
1103
- return false ;
1104
- }
1105
-
1106
1095
/**
1107
1096
* Determine the size to use with Photon for a thumbnail image.
1108
1097
* Images larger than the maximum thumbnail dimension in either dimension are resized to maintain aspect ratio.
0 commit comments