feat(comic): add featured_image and featured_image_url with attachment fallback to comic read ops

This commit is contained in:
John Smith
2026-09-04 19:11:49 -04:00
parent 5c4606fc77
commit bf93cc08bf
2 changed files with 137 additions and 31 deletions
@@ -39,20 +39,15 @@ class EMCP_Tools_Comic_Read_Operations {
}
/**
* Get full details of a single comic post.
* Resolves the featured image for a comic post.
*
* @param array $args Arguments: { id?: int, slug?: string }
* @return array|\WP_Error
* Returns the full-resolution image URL, attachment ID, dimensions, and alt text.
* If no post thumbnail is explicitly set, falls back to the comic's first image attachment.
*
* @param int $post_id Comic post ID.
* @return array { id: int, url: string, width: ?int, height: ?int, alt: string }
*/
public static function get_comic( array $args ) {
$post = self::resolve_comic_post( $args );
if ( is_wp_error( $post ) ) {
return $post;
}
$post_id = $post->ID;
// Featured media (Page 1)
public static function resolve_featured_image( int $post_id ): array {
$featured_id = (int) get_post_thumbnail_id( $post_id );
$featured_url = '';
$featured_w = null;
@@ -69,6 +64,64 @@ class EMCP_Tools_Comic_Read_Operations {
$featured_alt = (string) get_post_meta( $featured_id, '_wp_attachment_image_alt', true );
}
// Fallback: If no post thumbnail is set, search for the first attached image
if ( empty( $featured_url ) && function_exists( 'get_posts' ) ) {
$attachments = get_posts(
array(
'post_type' => 'attachment',
'post_parent' => $post_id,
'post_mime_type' => 'image',
'posts_per_page' => 1,
'order' => 'ASC',
'orderby' => 'menu_order ID',
)
);
if ( ! empty( $attachments ) ) {
$att = reset( $attachments );
$featured_id = (int) ( $att->ID ?? 0 );
if ( $featured_id > 0 && function_exists( 'wp_get_attachment_image_src' ) ) {
$src = wp_get_attachment_image_src( $featured_id, 'full' );
if ( is_array( $src ) && ! empty( $src[0] ) ) {
$featured_url = $src[0];
$featured_w = (int) $src[1];
$featured_h = (int) $src[2];
}
$featured_alt = (string) get_post_meta( $featured_id, '_wp_attachment_image_alt', true );
}
}
}
return array(
'id' => $featured_id,
'url' => $featured_url,
'width' => $featured_w,
'height' => $featured_h,
'alt' => $featured_alt,
);
}
/**
* Get full details of a single comic post.
*
* @param array $args Arguments: { id?: int, slug?: string }
* @return array|\WP_Error
*/
public static function get_comic( array $args ) {
$post = self::resolve_comic_post( $args );
if ( is_wp_error( $post ) ) {
return $post;
}
$post_id = $post->ID;
// Featured media (Page 1) with fallback to attachments
$featured_media = self::resolve_featured_image( $post_id );
$featured_id = $featured_media['id'];
$featured_url = $featured_media['url'];
$featured_w = $featured_media['width'];
$featured_h = $featured_media['height'];
$featured_alt = $featured_media['alt'];
// Multi-image field (Pages 2..N)
$html_below = (string) get_post_meta( $post_id, 'comic-html-below', true );
if ( '' === $html_below ) {
@@ -133,13 +186,21 @@ class EMCP_Tools_Comic_Read_Operations {
),
'content' => $post->post_content,
'excerpt' => $post->post_excerpt,
'featured_media' => array(
'featured_media' => array(
'id' => $featured_id,
'url' => $featured_url,
'width' => $featured_w,
'height' => $featured_h,
'alt' => $featured_alt,
),
'featured_image' => array(
'id' => $featured_id,
'url' => $featured_url,
'width' => $featured_w,
'height' => $featured_h,
'alt' => $featured_alt,
),
'featured_image_url' => $featured_url,
'comic_html_below' => $html_below,
'additional_images' => $additional_images,
'all_images' => $all_images,
@@ -234,31 +295,39 @@ class EMCP_Tools_Comic_Read_Operations {
foreach ( $query->posts as $p ) {
$p_id = $p->ID;
$thumb_id = (int) get_post_thumbnail_id( $p_id );
$thumb_url = '';
$featured = self::resolve_featured_image( $p_id );
$featured_url = $featured['url'];
$thumb_id = $featured['id'];
$thumb_url = '';
if ( $thumb_id > 0 && function_exists( 'wp_get_attachment_image_src' ) ) {
$src = wp_get_attachment_image_src( $thumb_id, 'medium' );
if ( is_array( $src ) && ! empty( $src[0] ) ) {
$thumb_url = $src[0];
}
}
if ( empty( $thumb_url ) ) {
$thumb_url = $featured_url;
}
$html_below = (string) get_post_meta( $p_id, 'comic-html-below', true );
$add_count = count( EMCP_Tools_Comic_Html_Helper::parse_html_below( $html_below ) );
$total_pgs = ( ! empty( $thumb_url ) ? 1 : 0 ) + $add_count;
$total_pgs = ( ! empty( $featured_url ) ? 1 : 0 ) + $add_count;
$comics[] = array(
'id' => $p_id,
'slug' => $p->post_name,
'title' => get_the_title( $p_id ),
'url' => get_permalink( $p_id ),
'date' => $p->post_date,
'status' => $p->post_status,
'thumbnail_url' => $thumb_url,
'total_pages' => $total_pgs,
'source_tweet_id' => (string) get_post_meta( $p_id, 'source_tweet_id', true ),
'source_url' => (string) get_post_meta( $p_id, 'source_url', true ),
'chapters' => self::get_term_summaries( $p_id, 'chapters' ),
'id' => $p_id,
'slug' => $p->post_name,
'title' => get_the_title( $p_id ),
'url' => get_permalink( $p_id ),
'date' => $p->post_date,
'status' => $p->post_status,
'thumbnail_url' => $thumb_url,
'featured_image' => $featured,
'featured_image_url' => $featured_url,
'total_pages' => $total_pgs,
'source_tweet_id' => (string) get_post_meta( $p_id, 'source_tweet_id', true ),
'source_url' => (string) get_post_meta( $p_id, 'source_url', true ),
'chapters' => self::get_term_summaries( $p_id, 'chapters' ),
);
}
+41 -4
View File
@@ -49,6 +49,8 @@ class WP_Post {
public $post_date_gmt;
public $post_modified;
public $post_author = 1;
public $post_parent = 0;
public $post_mime_type = '';
}
class WP_Term {
@@ -76,6 +78,20 @@ function get_post( $id ) {
return $GLOBALS['wp_posts'][ $id ] ?? null;
}
function get_posts( $args = array() ) {
$results = array();
$parent = $args['post_parent'] ?? 0;
$type = $args['post_type'] ?? 'post';
$mime = $args['post_mime_type'] ?? '';
foreach ( $GLOBALS['wp_posts'] as $p ) {
if ( $type && $p->post_type !== $type ) continue;
if ( $parent && $p->post_parent != $parent ) continue;
if ( $mime && 0 !== strpos( $p->post_mime_type, $mime ) ) continue;
$results[] = $p;
}
return $results;
}
function wp_insert_post( $args, $wp_error = false ) {
$id = ++$GLOBALS['wp_post_counter'];
$p = new WP_Post();
@@ -351,10 +367,31 @@ assert( $find_res2['found'] === true );
assert( $find_res2['comic']['id'] === $created_id );
echo 'Found by source_url: ID ' . $find_res2['comic']['id'] . "\n";
// Find nonexistent source
$find_empty = EMCP_Tools_Comic_Read_Operations::find_by_source( array( 'source_tweet_id' => '999999999999' ) );
assert( $find_empty['found'] === false );
echo "PASS: find_by_source verified for scrapers and idempotency!\n\n";
// Verify featured_image and featured_image_url on get_comic
assert( isset( $read_res['featured_image']['url'] ) && ! empty( $read_res['featured_image']['url'] ) );
assert( isset( $read_res['featured_image_url'] ) && $read_res['featured_image_url'] === $read_res['featured_image']['url'] );
// Verify list_comics returns featured_image and featured_image_url
$list_res = EMCP_Tools_Comic_Read_Operations::list_comics( array( 'status' => 'publish' ) );
assert( ! empty( $list_res['comics'] ) );
assert( isset( $list_res['comics'][0]['featured_image']['url'] ) );
assert( isset( $list_res['comics'][0]['featured_image_url'] ) );
// Verify fallback to attached image when _thumbnail_id is missing
$no_thumb_id = wp_insert_post( array( 'post_title' => 'Legacy Attached Comic', 'post_type' => 'comic', 'post_status' => 'publish' ) );
$att_p = new WP_Post();
$att_id = ++$GLOBALS['wp_post_counter'];
$att_p->ID = $att_id;
$att_p->post_type = 'attachment';
$att_p->post_mime_type = 'image/jpeg';
$att_p->post_parent = $no_thumb_id;
$GLOBALS['wp_posts'][ $att_id ] = $att_p;
$legacy_res = EMCP_Tools_Comic_Read_Operations::get_comic( array( 'id' => $no_thumb_id ) );
assert( ! is_wp_error( $legacy_res ) );
assert( $legacy_res['featured_image']['id'] === $att_id );
assert( ! empty( $legacy_res['featured_image_url'] ) );
echo "PASS: featured_image, featured_image_url, and attachment fallback verified!\n";
echo "=== TEST 4: Update Comic (Append Images & Set Source) ===\n";
$update_res = EMCP_Tools_Comic_Write_Operations::update_comic(