@@ -5215,12 +5215,13 @@ function get_media_embedded_in_content( $content, $types = null ) {
52155215 *
52165216 * @since 3.6.0
52175217 *
5218- * @param int|WP_Post $post Post ID or object.
5219- * @param bool $html Optional. Whether to return HTML or data in the array. Default true.
5218+ * @param int|WP_Post $post Post ID or object.
5219+ * @param bool $html Optional. Whether to return HTML or data in the array. Default true.
5220+ * @param int $max_galleries Optional. Only collect up to this many galleries. Default unlimited.
52205221 * @return array A list of arrays, each containing gallery data and srcs parsed
52215222 * from the expanded shortcode.
52225223 */
5223- function get_post_galleries ( $ post , $ html = true ) {
5224+ function get_post_galleries ( $ post , $ html = true , $ max_galleries = PHP_INT_MAX ) {
52245225 $ post = get_post ( $ post );
52255226
52265227 if ( ! $ post ) {
@@ -5266,95 +5267,161 @@ function get_post_galleries( $post, $html = true ) {
52665267 }
52675268 }
52685269
5269- if ( has_block ( ' gallery ' , $ post ->post_content ) ) {
5270- $ post_blocks = parse_blocks ( $ post -> post_content ) ;
5270+ $ processor = WP_Block_Processor:: create ( $ post ->post_content );
5271+ $ found = 0 ;
52715272
5272- while ( $ block = array_shift ( $ post_blocks ) ) {
5273- $ has_inner_blocks = ! empty ( $ block ['innerBlocks ' ] );
5273+ while ( $ processor ->next_delimiter () ) {
5274+ if ( ! $ processor ->opens_block ( 'gallery ' ) ) {
5275+ continue ;
5276+ }
52745277
5275- // Skip blocks with no blockName and no innerHTML.
5276- if ( ! $ block ['blockName ' ] ) {
5277- continue ;
5278+ /*
5279+ * It’s not clear yet whether this will have inner blocks.
5280+ * Until then, start computing for both paths, then bail
5281+ * once the block vintage is known.
5282+ */
5283+ $ gallery_depth = $ processor ->get_depth ();
5284+ $ has_inner_blocks = false ;
5285+ $ gallery_ids = $ processor ->allocate_and_return_parsed_attributes ()['attrs ' ]['ids ' ] ?? array ();
5286+
5287+ $ html_chunks = array ();
5288+ $ top_chunks = array ();
5289+ while ( $ processor ->next_delimiter ( 'visit-html ' ) && $ processor ->get_depth () >= $ gallery_depth ) {
5290+ if ( $ processor ->opens_block ( 'freeform ' ) ) {
5291+ $ opener = $ processor ->get_span ();
5292+ $ processor ->next_delimiter ( 'visit-html ' );
5293+ $ closer = $ processor ->get_span ();
5294+
5295+ $ chunk = substr ( $ post ->post_content , $ opener ->start , $ closer ->start - $ opener ->start );
5296+ $ html_chunks [] = $ chunk ;
5297+ if ( $ gallery_depth === $ processor ->get_depth () ) {
5298+ $ top_chunks [] = $ chunk ;
5299+ }
5300+ } else {
5301+ $ has_inner_blocks = true ;
5302+ break ;
52785303 }
5304+ }
5305+
5306+ // New Gallery block format as HTML.
5307+ if ( $ has_inner_blocks && $ html ) {
5308+
5309+ // Get the rest of the innerHTML of the Gallery’s direct children.
5310+ while ( $ processor ->next_delimiter ( 'visit-html ' ) && $ processor ->get_depth () >= $ gallery_depth ) {
5311+ if ( $ processor ->opens_block ( 'freeform ' ) ) {
5312+ $ opener = $ processor ->get_span ();
5313+ $ processor ->next_delimiter ( 'visit-html ' );
5314+ $ closer = $ processor ->get_span ();
52795315
5280- // Skip non-Gallery blocks.
5281- if ( 'core/gallery ' !== $ block ['blockName ' ] ) {
5282- // Move inner blocks into the root array before skipping.
5283- if ( $ has_inner_blocks ) {
5284- array_push ( $ post_blocks , ...$ block ['innerBlocks ' ] );
5316+ $ html_chunks [] = substr ( $ post ->post_content , $ opener ->start , $ closer ->start - $ opener ->start );
52855317 }
5286- continue ;
52875318 }
52885319
5289- // New Gallery block format as HTML.
5290- if ( $ has_inner_blocks && $ html ) {
5291- $ block_html = wp_list_pluck ( $ block [ ' innerBlocks ' ], ' innerHTML ' ) ;
5292- $ galleries [] = ' <figure> ' . implode ( ' ' , $ block_html ) . ' </figure> ' ;
5320+ $ galleries [] = ' <figure> ' . implode ( ' ' , $ html_chunks ) . ' </figure> ' ;
5321+ if ( ++ $ found >= $ max_galleries ) {
5322+ break ;
5323+ } else {
52935324 continue ;
52945325 }
5326+ }
52955327
5328+ // New Gallery block format as an array.
5329+ if ( $ has_inner_blocks ) {
5330+ // There are inner blocks and this is the first one.
5331+ $ ids = array ();
52965332 $ srcs = array ();
52975333
5298- // New Gallery block format as an array.
5299- if ( $ has_inner_blocks ) {
5300- $ attrs = wp_list_pluck ( $ block [ ' innerBlocks ' ], ' attrs ' );
5301- $ ids = wp_list_pluck ( $ attrs , ' id ' );
5334+ /**
5335+ * @todo Could avoid computation by tracking seen ids and only looking up the
5336+ * attachment url if the id hasn’t already been resolved.
5337+ */
53025338
5303- foreach ( $ ids as $ id ) {
5304- $ url = wp_get_attachment_url ( $ id );
5339+ /** @var @todo Perfect use-case for lazy parsing here — only the `id` is wanted. */
5340+ $ attrs = $ processor ->allocate_and_return_parsed_attributes ();
5341+ $ id = $ attrs ['id ' ] ?? null ;
5342+ if ( isset ( $ id ) ) {
5343+ $ ids [] = $ id ;
5344+ $ url = wp_get_attachment_url ( $ id );
5345+ if ( is_string ( $ url ) ) {
5346+ $ srcs [] = $ url ;
5347+ }
5348+ }
53055349
5306- if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5307- $ srcs [] = $ url ;
5350+ while ( $ processor ->next_delimiter () && $ processor ->get_depth () >= $ gallery_depth ) {
5351+ // Examine only the direct children of the gallery block.
5352+ if ( $ processor ->get_depth () === $ gallery_depth && $ processor ->opens_block () ) {
5353+ $ attrs = $ processor ->allocate_and_return_parsed_attributes ();
5354+ $ id = $ attrs ['id ' ] ?? null ;
5355+ if ( isset ( $ id ) ) {
5356+ $ ids [] = $ id ;
5357+ $ url = wp_get_attachment_url ( $ id );
5358+
5359+ if ( is_string ( $ url ) && !in_array ( $ url , $ srcs , true ) ) {
5360+ $ srcs [] = $ url ;
5361+ }
53085362 }
53095363 }
5364+ }
53105365
5311- $ galleries [] = array (
5312- 'ids ' => implode ( ', ' , $ ids ),
5313- 'src ' => $ srcs ,
5314- );
5366+ $ galleries [] = array (
5367+ 'ids ' => implode ( ', ' , $ ids ),
5368+ 'src ' => $ srcs ,
5369+ );
53155370
5371+ if ( ++$ found >= $ max_galleries ) {
5372+ break ;
5373+ } else {
53165374 continue ;
53175375 }
5376+ }
53185377
5319- // Old Gallery block format as HTML.
5320- if ( $ html ) {
5321- $ galleries [] = $ block ['innerHTML ' ];
5378+ // Old Gallery block format as HTML.
5379+ if ( $ html ) {
5380+ $ galleries [] = implode ( '' , $ top_chunks );
5381+ if ( ++$ found >= $ max_galleries ) {
5382+ break ;
5383+ } else {
53225384 continue ;
53235385 }
5386+ }
53245387
5325- // Old Gallery block format as an array.
5326- $ ids = ! empty ( $ block ['attrs ' ]['ids ' ] ) ? $ block ['attrs ' ]['ids ' ] : array ();
5388+ // Old Gallery block format as an array.
53275389
5328- // If present, use the image IDs from the JSON blob as canonical.
5329- if ( ! empty ( $ ids ) ) {
5330- foreach ( $ ids as $ id ) {
5331- $ url = wp_get_attachment_url ( $ id );
5390+ // If present, use the image IDs from the JSON blob as canonical.
5391+ if ( ! empty ( $ gallery_ids ) ) {
5392+ foreach ( $ ids as $ id ) {
5393+ $ url = wp_get_attachment_url ( $ id );
53325394
5333- if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5334- $ srcs [] = $ url ;
5335- }
5395+ if ( is_string ( $ url ) && ! in_array ( $ url , $ srcs , true ) ) {
5396+ $ srcs [] = $ url ;
53365397 }
5398+ }
53375399
5338- $ galleries [] = array (
5339- 'ids ' => implode ( ', ' , $ ids ),
5340- 'src ' => $ srcs ,
5341- );
5400+ $ galleries [] = array (
5401+ 'ids ' => implode ( ', ' , $ ids ),
5402+ 'src ' => $ srcs ,
5403+ );
53425404
5405+ if ( ++$ found >= $ max_galleries ) {
5406+ break ;
5407+ } else {
53435408 continue ;
53445409 }
5410+ }
53455411
5346- // Otherwise, extract srcs from the innerHTML.
5347- preg_match_all ( '#src=([ \'"])(.+?)\1#is ' , $ block ['innerHTML ' ], $ found_srcs , PREG_SET_ORDER );
5348-
5349- if ( ! empty ( $ found_srcs [0 ] ) ) {
5350- foreach ( $ found_srcs as $ src ) {
5351- if ( isset ( $ src [2 ] ) && ! in_array ( $ src [2 ], $ srcs , true ) ) {
5352- $ srcs [] = $ src [2 ];
5353- }
5354- }
5412+ // Otherwise, extract srcs from the innerHTML.
5413+ $ inner_html = implode ( '' , $ top_chunks );
5414+ $ src_finder = new WP_HTML_Tag_Processor ( $ inner_html );
5415+ while ( $ src_finder ->next_tag () ) {
5416+ $ src = $ src_finder ->get_attribute ( 'src ' );
5417+ if ( is_string ( $ src ) && ! in_array ( $ src , $ srcs , true ) ) {
5418+ $ srcs [] = $ src ;
53555419 }
5420+ }
53565421
5357- $ galleries [] = array ( 'src ' => $ srcs );
5422+ $ galleries [] = array ( 'src ' => $ srcs );
5423+ if ( ++$ found >= $ max_galleries ) {
5424+ break ;
53585425 }
53595426 }
53605427
@@ -5379,8 +5446,8 @@ function get_post_galleries( $post, $html = true ) {
53795446 * @return string|array Gallery data and srcs parsed from the expanded shortcode.
53805447 */
53815448function get_post_gallery ( $ post = 0 , $ html = true ) {
5382- $ galleries = get_post_galleries ( $ post , $ html );
5383- $ gallery = reset ( $ galleries ) ;
5449+ $ galleries = get_post_galleries ( $ post , $ html, 1 );
5450+ $ gallery = $ galleries[ 0 ] ?? false ;
53845451
53855452 /**
53865453 * Filters the first-found post gallery.
0 commit comments