mirror of
https://github.com/Heretek-AI/heretek-control-core.git
synced 2026-10-12 02:03:55 +00:00
feat(comic): add featured_image and featured_image_url with attachment fallback to comic read ops
This commit is contained in:
@@ -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' ),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user