Skip to content

Commit 1f4d891

Browse files
committed
Refactor get_post_galleries to use Block_Processor
1 parent 43e2ff9 commit 1f4d891

File tree

1 file changed

+127
-60
lines changed

1 file changed

+127
-60
lines changed

src/wp-includes/media.php

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

Comments
 (0)