Skip to content

Commit faf88d9

Browse files
committed
Refactor get_post_galleries to use Block_Processor
1 parent 5ba2ec5 commit faf88d9

1 file changed

Lines changed: 127 additions & 60 deletions

File tree

src/wp-includes/media.php

Lines changed: 127 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*/
53815448
function 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

Comments
 (0)