diff --git a/includes/transformer/class-post.php b/includes/transformer/class-post.php index 0267e2e..eb710fa 100644 --- a/includes/transformer/class-post.php +++ b/includes/transformer/class-post.php @@ -9,6 +9,7 @@ use Activitypub\Activity\Base_Object; use function Activitypub\esc_hashtag; use function Activitypub\is_single_user; use function Activitypub\get_rest_url_by_path; +use function Activitypub\site_supports_blocks; /** * WordPress Post Transformer @@ -166,6 +167,66 @@ class Post { return Users::get_by_id( $this->wp_post->post_author )->get_url(); } + /** + * Returns the Image Attachments for this Post, parsed from blocks. + * @param int $max_images The maximum number of images to return. + * @param array $image_ids The image IDs to append new IDs to. + * + * @return array The image IDs. + */ + protected function get_block_image_ids( $max_images, $image_ids = [] ) { + $blocks = \parse_blocks( $this->wp_post->post_content ); + return self::get_image_ids_from_blocks( $blocks, $image_ids, $max_images ); + } + + /** + * Recursively get image IDs from blocks. + * @param array $blocks The blocks to search for image IDs + * @param array $image_ids The image IDs to append new IDs to + * @param int $max_images The maximum number of images to return. + * + * @return array The image IDs. + */ + protected static function get_image_ids_from_blocks( $blocks, $image_ids, $max_images ) { + foreach ( $blocks as $block ) { + // recurse into inner blocks + if ( ! empty( $block['innerBlocks'] ) ) { + $image_ids = self::get_image_ids_from_blocks( $block['innerBlocks'], $image_ids, $max_images ); + } + + switch ( $block['blockName'] ) { + case 'core/image': + case 'core/cover': + if ( ! empty( $block['attrs']['id'] ) ) { + $image_ids[] = $block['attrs']['id']; + } + break; + case 'jetpack/slideshow': + case 'jetpack/tiled-gallery': + if ( ! empty( $block['attrs']['ids'] ) ) { + $image_ids = array_merge( $image_ids, $block['attrs']['ids'] ); + } + break; + case 'jetpack/image-compare': + if ( ! empty( $block['attrs']['beforeImageId'] ) ) { + $image_ids[] = $block['attrs']['beforeImageId']; + } + if ( ! empty( $block['attrs']['afterImageId'] ) ) { + $image_ids[] = $block['attrs']['afterImageId']; + } + break; + } + + // we could be at or over max, stop unneeded work + if ( count( $image_ids ) >= $max_images ) { + break; + } + } + + // still need to slice it because one gallery could knock us over the limit + return \array_slice( $image_ids, 0, $max_images ); + } + /** * Generates all Image Attachments for a Post. * @@ -192,21 +253,26 @@ class Post { } if ( $max_images > 0 ) { - // then list any image attachments - $query = new \WP_Query( - array( - 'post_parent' => $id, - 'post_status' => 'inherit', - 'post_type' => 'attachment', - 'post_mime_type' => 'image', - 'order' => 'ASC', - 'orderby' => 'menu_order ID', - 'posts_per_page' => $max_images, - ) - ); - foreach ( $query->get_posts() as $attachment ) { - if ( ! \in_array( $attachment->ID, $image_ids, true ) ) { - $image_ids[] = $attachment->ID; + // first try to get images that are actually in the post content + if ( site_supports_blocks() && \has_blocks( $this->wp_post->post_content ) ) { + $image_ids = $this->get_block_image_ids( $max_images, $image_ids ); + } else { + // fallback to images attached to the post + $query = new \WP_Query( + array( + 'post_parent' => $id, + 'post_status' => 'inherit', + 'post_type' => 'attachment', + 'post_mime_type' => 'image', + 'order' => 'ASC', + 'orderby' => 'menu_order ID', + 'posts_per_page' => $max_images, + ) + ); + foreach ( $query->get_posts() as $attachment ) { + if ( ! \in_array( $attachment->ID, $image_ids, true ) ) { + $image_ids[] = $attachment->ID; + } } } }