@@ -5250,12 +5250,13 @@ function get_media_embedded_in_content( $content, $types = null ) {
52505250 *
52515251 * @since 3.6.0
52525252 *
5253- * @param int|WP_Post $post Post ID or object.
5254- * @param bool $html Optional. Whether to return HTML or data in the array. Default true.
5253+ * @param int|WP_Post $post Post ID or object.
5254+ * @param bool $html Optional. Whether to return HTML or data in the array. Default true.
5255+ * @param int $max_galleries Optional. Only collect up to this many galleries. Default unlimited.
52555256 * @return array A list of arrays, each containing gallery data and srcs parsed
52565257 * from the expanded shortcode.
52575258 */
5258- function get_post_galleries ( $ post , $ html = true ) {
5259+ function get_post_galleries ( $ post , $ html = true , $ max_galleries = PHP_INT_MAX ) {
52595260 $ post = get_post ( $ post );
52605261
52615262 if ( ! $ post ) {
@@ -5301,95 +5302,161 @@ function get_post_galleries( $post, $html = true ) {
53015302 }
53025303 }
53035304
5304- if ( has_block ( ' gallery ' , $ post ->post_content ) ) {
5305- $ post_blocks = parse_blocks ( $ post -> post_content ) ;
5305+ $ processor = WP_Block_Processor:: create ( $ post ->post_content );
5306+ $ found = 0 ;
53065307
5307- while ( $ block = array_shift ( $ post_blocks ) ) {
5308- $ has_inner_blocks = ! empty ( $ block ['innerBlocks ' ] );
5308+ while ( $ processor ->next_delimiter () ) {
5309+ if ( ! $ processor ->opens_block ( 'gallery ' ) ) {
5310+ continue ;
5311+ }
53095312
5310- // Skip blocks with no blockName and no innerHTML.
5311- if ( ! $ block ['blockName ' ] ) {
5312- continue ;
5313+ /*
5314+ * It’s not clear yet whether this will have inner blocks.
5315+ * Until then, start computing for both paths, then bail
5316+ * once the block vintage is known.
5317+ */
5318+ $ gallery_depth = $ processor ->get_depth ();
5319+ $ has_inner_blocks = false ;
5320+ $ gallery_ids = $ processor ->allocate_and_return_parsed_attributes ()['attrs ' ]['ids ' ] ?? array ();
5321+
5322+ $ html_chunks = array ();
5323+ $ top_chunks = array ();
5324+ while ( $ processor ->next_delimiter ( 'visit-html ' ) && $ processor ->get_depth () >= $ gallery_depth ) {
5325+ if ( $ processor ->opens_block ( 'freeform ' ) ) {
5326+ $ opener = $ processor ->get_span ();
5327+ $ processor ->next_delimiter ( 'visit-html ' );
5328+ $ closer = $ processor ->get_span ();
5329+
5330+ $ chunk = substr ( $ post ->post_content , $ opener ->start , $ closer ->start - $ opener ->start );
5331+ $ html_chunks [] = $ chunk ;
5332+ if ( $ gallery_depth === $ processor ->get_depth () ) {
5333+ $ top_chunks [] = $ chunk ;
5334+ }
5335+ } else {
5336+ $ has_inner_blocks = true ;
5337+ break ;
53135338 }
5339+ }
5340+
5341+ // New Gallery block format as HTML.
5342+ if ( $ has_inner_blocks && $ html ) {
5343+
5344+ // Get the rest of the innerHTML of the Gallery’s direct children.
5345+ while ( $ processor ->next_delimiter ( 'visit-html ' ) && $ processor ->get_depth () >= $ gallery_depth ) {
5346+ if ( $ processor ->opens_block ( 'freeform ' ) ) {
5347+ $ opener = $ processor ->get_span ();
5348+ $ processor ->next_delimiter ( 'visit-html ' );
5349+ $ closer = $ processor ->get_span ();
53145350
5315- // Skip non-Gallery blocks.
5316- if ( 'core/gallery ' !== $ block ['blockName ' ] ) {
5317- // Move inner blocks into the root array before skipping.
5318- if ( $ has_inner_blocks ) {
5319- array_push ( $ post_blocks , ...$ block ['innerBlocks ' ] );
5351+ $ html_chunks [] = substr ( $ post ->post_content , $ opener ->start , $ closer ->start - $ opener ->start );
53205352 }
5321- continue ;
53225353 }
53235354
5324- // New Gallery block format as HTML.
5325- if ( $ has_inner_blocks && $ html ) {
5326- $ block_html = wp_list_pluck ( $ block [ ' innerBlocks ' ], ' innerHTML ' ) ;
5327- $ galleries [] = ' <figure> ' . implode ( ' ' , $ block_html ) . ' </figure> ' ;
5355+ $ galleries [] = ' <figure> ' . implode ( ' ' , $ html_chunks ) . ' </figure> ' ;
5356+ if ( ++ $ found >= $ max_galleries ) {
5357+ break ;
5358+ } else {
53285359 continue ;
53295360 }
5361+ }
53305362
5363+ // New Gallery block format as an array.
5364+ if ( $ has_inner_blocks ) {
5365+ // There are inner blocks and this is the first one.
5366+ $ ids = array ();
53315367 $ srcs = array ();
53325368
5333- // New Gallery block format as an array.
5334- if ( $ has_inner_blocks ) {
5335- $ attrs = wp_list_pluck ( $ block [ ' innerBlocks ' ], ' attrs ' );
5336- $ ids = wp_list_pluck ( $ attrs , ' id ' );
5369+ /**
5370+ * @todo Could avoid computation by tracking seen ids and only looking up the
5371+ * attachment url if the id hasn’t already been resolved.
5372+ */
53375373
5338- foreach ( $ ids as $ id ) {
5339- $ url = wp_get_attachment_url ( $ id );
5374+ /** @var @todo Perfect use-case for lazy parsing here — only the `id` is wanted. */
5375+ $ attrs = $ processor ->allocate_and_return_parsed_attributes ();
5376+ $ id = $ attrs ['id ' ] ?? null ;
5377+ if ( isset ( $ id ) ) {
5378+ $ ids [] = $ id ;
5379+ $ url = wp_get_attachment_url ( $ id );
5380+ if ( is_string ( $ url ) ) {
5381+ $ srcs [] = $ url ;
5382+ }
5383+ }
53405384
5341- if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5342- $ srcs [] = $ url ;
5385+ while ( $ processor ->next_delimiter () && $ processor ->get_depth () >= $ gallery_depth ) {
5386+ // Examine only the direct children of the gallery block.
5387+ if ( $ processor ->get_depth () === $ gallery_depth && $ processor ->opens_block () ) {
5388+ $ attrs = $ processor ->allocate_and_return_parsed_attributes ();
5389+ $ id = $ attrs ['id ' ] ?? null ;
5390+ if ( isset ( $ id ) ) {
5391+ $ ids [] = $ id ;
5392+ $ url = wp_get_attachment_url ( $ id );
5393+
5394+ if ( is_string ( $ url ) && !in_array ( $ url , $ srcs , true ) ) {
5395+ $ srcs [] = $ url ;
5396+ }
53435397 }
53445398 }
5399+ }
53455400
5346- $ galleries [] = array (
5347- 'ids ' => implode ( ', ' , $ ids ),
5348- 'src ' => $ srcs ,
5349- );
5401+ $ galleries [] = array (
5402+ 'ids ' => implode ( ', ' , $ ids ),
5403+ 'src ' => $ srcs ,
5404+ );
53505405
5406+ if ( ++$ found >= $ max_galleries ) {
5407+ break ;
5408+ } else {
53515409 continue ;
53525410 }
5411+ }
53535412
5354- // Old Gallery block format as HTML.
5355- if ( $ html ) {
5356- $ galleries [] = $ block ['innerHTML ' ];
5413+ // Old Gallery block format as HTML.
5414+ if ( $ html ) {
5415+ $ galleries [] = implode ( '' , $ top_chunks );
5416+ if ( ++$ found >= $ max_galleries ) {
5417+ break ;
5418+ } else {
53575419 continue ;
53585420 }
5421+ }
53595422
5360- // Old Gallery block format as an array.
5361- $ ids = ! empty ( $ block ['attrs ' ]['ids ' ] ) ? $ block ['attrs ' ]['ids ' ] : array ();
5423+ // Old Gallery block format as an array.
53625424
5363- // If present, use the image IDs from the JSON blob as canonical.
5364- if ( ! empty ( $ ids ) ) {
5365- foreach ( $ ids as $ id ) {
5366- $ url = wp_get_attachment_url ( $ id );
5425+ // If present, use the image IDs from the JSON blob as canonical.
5426+ if ( ! empty ( $ gallery_ids ) ) {
5427+ foreach ( $ ids as $ id ) {
5428+ $ url = wp_get_attachment_url ( $ id );
53675429
5368- if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5369- $ srcs [] = $ url ;
5370- }
5430+ if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5431+ $ srcs [] = $ url ;
53715432 }
5433+ }
53725434
5373- $ galleries [] = array (
5374- 'ids ' => implode ( ', ' , $ ids ),
5375- 'src ' => $ srcs ,
5376- );
5435+ $ galleries [] = array (
5436+ 'ids ' => implode ( ', ' , $ ids ),
5437+ 'src ' => $ srcs ,
5438+ );
53775439
5440+ if ( ++$ found >= $ max_galleries ) {
5441+ break ;
5442+ } else {
53785443 continue ;
53795444 }
5445+ }
53805446
5381- // Otherwise, extract srcs from the innerHTML.
5382- preg_match_all ( '#src=([ \'"])(.+?)\1#is ' , $ block ['innerHTML ' ], $ found_srcs , PREG_SET_ORDER );
5383-
5384- if ( ! empty ( $ found_srcs [0 ] ) ) {
5385- foreach ( $ found_srcs as $ src ) {
5386- if ( isset ( $ src [2 ] ) && ! in_array ( $ src [2 ], $ srcs , true ) ) {
5387- $ srcs [] = $ src [2 ];
5388- }
5389- }
5447+ // Otherwise, extract srcs from the innerHTML.
5448+ $ inner_html = implode ( '' , $ top_chunks );
5449+ $ src_finder = new WP_HTML_Tag_Processor ( $ inner_html );
5450+ while ( $ src_finder ->next_tag () ) {
5451+ $ src = $ src_finder ->get_attribute ( 'src ' );
5452+ if ( is_string ( $ src ) && ! in_array ( $ src , $ srcs , true ) ) {
5453+ $ srcs [] = $ src ;
53905454 }
5455+ }
53915456
5392- $ galleries [] = array ( 'src ' => $ srcs );
5457+ $ galleries [] = array ( 'src ' => $ srcs );
5458+ if ( ++$ found >= $ max_galleries ) {
5459+ break ;
53935460 }
53945461 }
53955462
@@ -5414,8 +5481,8 @@ function get_post_galleries( $post, $html = true ) {
54145481 * @return string|array Gallery data and srcs parsed from the expanded shortcode.
54155482 */
54165483function get_post_gallery ( $ post = 0 , $ html = true ) {
5417- $ galleries = get_post_galleries ( $ post , $ html );
5418- $ gallery = reset ( $ galleries ) ;
5484+ $ galleries = get_post_galleries ( $ post , $ html, 1 );
5485+ $ gallery = $ galleries[ 0 ] ?? false ;
54195486
54205487 /**
54215488 * Filters the first-found post gallery.
0 commit comments