@@ -5248,12 +5248,13 @@ function get_media_embedded_in_content( $content, $types = null ) {
52485248 *
52495249 * @since 3.6.0
52505250 *
5251- * @param int|WP_Post $post Post ID or object.
5252- * @param bool $html Optional. Whether to return HTML or data in the array. Default true.
5251+ * @param int|WP_Post $post Post ID or object.
5252+ * @param bool $html Optional. Whether to return HTML or data in the array. Default true.
5253+ * @param int $max_galleries Optional. Only collect up to this many galleries. Default unlimited.
52535254 * @return array A list of arrays, each containing gallery data and srcs parsed
52545255 * from the expanded shortcode.
52555256 */
5256- function get_post_galleries ( $ post , $ html = true ) {
5257+ function get_post_galleries ( $ post , $ html = true , $ max_galleries = PHP_INT_MAX ) {
52575258 $ post = get_post ( $ post );
52585259
52595260 if ( ! $ post ) {
@@ -5299,95 +5300,149 @@ function get_post_galleries( $post, $html = true ) {
52995300 }
53005301 }
53015302
5302- if ( has_block ( ' gallery ' , $ post ->post_content ) ) {
5303- $ post_blocks = parse_blocks ( $ post -> post_content ) ;
5303+ $ processor = new WP_Block_Processor ( $ post ->post_content );
5304+ $ found = 0 ;
53045305
5305- while ( $ block = array_shift ( $ post_blocks ) ) {
5306- $ has_inner_blocks = ! empty ( $ block ['innerBlocks ' ] );
5307-
5308- // Skip blocks with no blockName and no innerHTML.
5309- if ( ! $ block ['blockName ' ] ) {
5310- continue ;
5306+ while ( $ processor ->next_block ( 'gallery ' ) ) {
5307+ /*
5308+ * It’s not clear yet whether this will have inner blocks.
5309+ * Until then, start computing for both paths, then bail
5310+ * once the block vintage is known.
5311+ */
5312+ $ gallery_depth = $ processor ->get_depth ();
5313+ $ has_inner_blocks = false ;
5314+ $ gallery_ids = $ processor ->allocate_and_return_parsed_attributes ()['attrs ' ]['ids ' ] ?? array ();
5315+
5316+ $ html_chunks = array ();
5317+ $ top_chunks = array ();
5318+ while ( $ processor ->next_token () && $ processor ->get_depth () > $ gallery_depth ) {
5319+ if ( $ processor ->is_html () ) {
5320+ $ chunk_span = $ processor ->get_span ();
5321+ $ chunk = substr ( $ post ->post_content , $ chunk_span ->start , $ chunk_span ->length );
5322+ $ html_chunks [] = $ chunk ;
5323+ if ( $ gallery_depth === $ processor ->get_depth () - 1 ) {
5324+ $ top_chunks [] = $ chunk ;
5325+ }
5326+ } else {
5327+ $ has_inner_blocks = true ;
5328+ break ;
53115329 }
5330+ }
53125331
5313- // Skip non-Gallery blocks.
5314- if ( 'core/gallery ' !== $ block ['blockName ' ] ) {
5315- // Move inner blocks into the root array before skipping.
5316- if ( $ has_inner_blocks ) {
5317- array_push ( $ post_blocks , ...$ block ['innerBlocks ' ] );
5332+ // New Gallery block format as HTML.
5333+ if ( $ has_inner_blocks && $ html ) {
5334+
5335+ // Get the rest of the innerHTML of the Gallery’s direct children.
5336+ while ( $ processor ->next_token () && $ processor ->get_depth () > $ gallery_depth ) {
5337+ if ( $ processor ->is_html () && $ processor ->get_depth () === $ gallery_depth + 2 ) {
5338+ $ chunk_span = $ processor ->get_span ();
5339+ $ html_chunks [] = substr ( $ post ->post_content , $ chunk_span ->start , $ chunk_span ->length );
53185340 }
5319- continue ;
53205341 }
53215342
5322- // New Gallery block format as HTML.
5323- if ( $ has_inner_blocks && $ html ) {
5324- $ block_html = wp_list_pluck ( $ block [ ' innerBlocks ' ], ' innerHTML ' ) ;
5325- $ galleries [] = ' <figure> ' . implode ( ' ' , $ block_html ) . ' </figure> ' ;
5343+ $ galleries [] = ' <figure> ' . implode ( ' ' , $ html_chunks ) . ' </figure> ' ;
5344+ if ( ++ $ found >= $ max_galleries ) {
5345+ break ;
5346+ } else {
53265347 continue ;
53275348 }
5349+ }
53285350
5351+ // New Gallery block format as an array.
5352+ if ( $ has_inner_blocks ) {
5353+ // There are inner blocks and this is the first one.
5354+ $ ids = array ();
53295355 $ srcs = array ();
53305356
5331- // New Gallery block format as an array.
5332- if ( $ has_inner_blocks ) {
5333- $ attrs = wp_list_pluck ( $ block ['innerBlocks ' ], 'attrs ' );
5334- $ ids = wp_list_pluck ( $ attrs , 'id ' );
5357+ /**
5358+ * @todo Could avoid computation by tracking seen ids and only looking up the
5359+ * attachment url if the id hasn’t already been resolved.
5360+ */
5361+
5362+ /** @var @todo Perfect use-case for lazy parsing here — only the `id` is wanted. */
5363+ $ id = $ processor ->allocate_and_return_parsed_attributes ()['id ' ] ?? null ;
5364+ if ( isset ( $ id ) ) {
5365+ $ ids [] = $ id ;
5366+ $ url = wp_get_attachment_url ( $ id );
5367+ if ( is_string ( $ url ) ) {
5368+ $ srcs [] = $ url ;
5369+ }
5370+ }
53355371
5336- foreach ( $ ids as $ id ) {
5337- $ url = wp_get_attachment_url ( $ id );
5372+ while ( $ processor ->next_block () && $ processor ->get_depth () > $ gallery_depth ) {
5373+ // Examine only the direct children of the gallery block.
5374+ if ( $ processor ->get_depth () === $ gallery_depth + 1 ) {
5375+ $ id = $ processor ->allocate_and_return_parsed_attributes ()['id ' ] ?? null ;
5376+ if ( isset ( $ id ) ) {
5377+ $ ids [] = $ id ;
5378+ $ url = wp_get_attachment_url ( $ id );
53385379
5339- if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5340- $ srcs [] = $ url ;
5380+ if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5381+ $ srcs [] = $ url ;
5382+ }
53415383 }
53425384 }
5385+ }
53435386
5344- $ galleries [] = array (
5345- 'ids ' => implode ( ', ' , $ ids ),
5346- 'src ' => $ srcs ,
5347- );
5387+ $ galleries [] = array (
5388+ 'ids ' => implode ( ', ' , $ ids ),
5389+ 'src ' => $ srcs ,
5390+ );
53485391
5392+ if ( ++$ found >= $ max_galleries ) {
5393+ break ;
5394+ } else {
53495395 continue ;
53505396 }
5397+ }
53515398
5352- // Old Gallery block format as HTML.
5353- if ( $ html ) {
5354- $ galleries [] = $ block ['innerHTML ' ];
5399+ // Old Gallery block format as HTML.
5400+ if ( $ html ) {
5401+ $ galleries [] = implode ( '' , $ top_chunks );
5402+ if ( ++$ found >= $ max_galleries ) {
5403+ break ;
5404+ } else {
53555405 continue ;
53565406 }
5407+ }
53575408
5358- // Old Gallery block format as an array.
5359- $ ids = ! empty ( $ block ['attrs ' ]['ids ' ] ) ? $ block ['attrs ' ]['ids ' ] : array ();
5409+ // Old Gallery block format as an array.
53605410
5361- // If present, use the image IDs from the JSON blob as canonical.
5362- if ( ! empty ( $ ids ) ) {
5363- foreach ( $ ids as $ id ) {
5364- $ url = wp_get_attachment_url ( $ id );
5411+ // If present, use the image IDs from the JSON blob as canonical.
5412+ if ( ! empty ( $ gallery_ids ) ) {
5413+ foreach ( $ ids as $ id ) {
5414+ $ url = wp_get_attachment_url ( $ id );
53655415
5366- if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5367- $ srcs [] = $ url ;
5368- }
5416+ if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5417+ $ srcs [] = $ url ;
53695418 }
5419+ }
53705420
5371- $ galleries [] = array (
5372- 'ids ' => implode ( ', ' , $ ids ),
5373- 'src ' => $ srcs ,
5374- );
5421+ $ galleries [] = array (
5422+ 'ids ' => implode ( ', ' , $ ids ),
5423+ 'src ' => $ srcs ,
5424+ );
53755425
5426+ if ( ++$ found >= $ max_galleries ) {
5427+ break ;
5428+ } else {
53765429 continue ;
53775430 }
5431+ }
53785432
5379- // Otherwise, extract srcs from the innerHTML.
5380- preg_match_all ( '#src=([ \'"])(.+?)\1#is ' , $ block ['innerHTML ' ], $ found_srcs , PREG_SET_ORDER );
5381-
5382- if ( ! empty ( $ found_srcs [0 ] ) ) {
5383- foreach ( $ found_srcs as $ src ) {
5384- if ( isset ( $ src [2 ] ) && ! in_array ( $ src [2 ], $ srcs , true ) ) {
5385- $ srcs [] = $ src [2 ];
5386- }
5387- }
5433+ // Otherwise, extract srcs from the innerHTML.
5434+ $ inner_html = implode ( '' , $ top_chunks );
5435+ $ src_finder = new WP_HTML_Tag_Processor ( $ inner_html );
5436+ while ( $ src_finder ->next_tag () ) {
5437+ $ src = $ src_finder ->get_attribute ( 'src ' );
5438+ if ( is_string ( $ src ) && ! in_array ( $ src , $ srcs , true ) ) {
5439+ $ srcs [] = $ src ;
53885440 }
5441+ }
53895442
5390- $ galleries [] = array ( 'src ' => $ srcs );
5443+ $ galleries [] = array ( 'src ' => $ srcs );
5444+ if ( ++$ found >= $ max_galleries ) {
5445+ break ;
53915446 }
53925447 }
53935448
@@ -5412,8 +5467,8 @@ function get_post_galleries( $post, $html = true ) {
54125467 * @return string|array Gallery data and srcs parsed from the expanded shortcode.
54135468 */
54145469function get_post_gallery ( $ post = 0 , $ html = true ) {
5415- $ galleries = get_post_galleries ( $ post , $ html );
5416- $ gallery = reset ( $ galleries ) ;
5470+ $ galleries = get_post_galleries ( $ post , $ html, 1 );
5471+ $ gallery = $ galleries[ 0 ] ?? false ;
54175472
54185473 /**
54195474 * Filters the first-found post gallery.
0 commit comments