/** * Get the "Continue Reading" URL for a novel. * * @param int $novel_id Novel post ID. * @return string|null Chapter permalink or null. */ function webnovel_get_continue_reading_url( $novel_id ) { // Check server-side history for logged-in users. if ( is_user_logged_in() ) { $history = \WebNovel\Reading_Tracker::get_last_read( $novel_id ); if ( $history && ! empty( $history['chapter_id'] ) ) { $chapter = get_post( $history['chapter_id'] ); if ( $chapter && 'publish' === $chapter->post_status ) { return get_permalink( $chapter->ID ); } } } // Fallback to first chapter. $chapters = \WebNovel\CPT_Chapter::get_chapters_by_novel( $novel_id, array( 'posts_per_page' => 1 ) ); if ( ! empty( $chapters ) ) { return get_permalink( $chapters[0]->ID ); } return null; } /** * Output Open Graph and Twitter Card meta tags. * * @return void */ function webnovel_social_meta_tags() { if ( ! is_singular( array( 'novel', 'chapter' ) ) && ! is_post_type_archive( 'novel' ) && ! is_tax( array( 'genre', 'novel_status' ) ) ) { return; } $title = wp_get_document_title(); $url = esc_url( home_url( add_query_arg( array() ) ) ); $site_name = get_bloginfo( 'name' ); $description = ''; // Determine image and description. $image = ''; if ( is_singular( 'novel' ) && has_post_thumbnail() ) { $image = get_the_post_thumbnail_url( null, 'novel-cover-large' ); $description = get_post_meta( get_the_ID(), '_webnovel_synopsis', true ); if ( ! $description ) { $description = get_the_excerpt(); } } elseif ( is_singular( 'chapter' ) ) { $novel_id = wp_get_post_parent_id( get_the_ID() ); if ( $novel_id && has_post_thumbnail( $novel_id ) ) { $image = get_the_post_thumbnail_url( $novel_id, 'novel-cover-large' ); } $description = get_the_excerpt(); if ( ! $description ) { $description = sprintf( /* translators: %s: Novel title */ __( 'Read the latest chapter of %s.', 'webnovel' ), get_the_title( $novel_id ) ); } } elseif ( is_post_type_archive( 'novel' ) ) { $description = __( 'Discover amazing web novels and stories.', 'webnovel' ); } $description = $description ? wp_strip_all_tags( $description ) : get_bloginfo( 'description' ); $description = wp_trim_words( $description, 40 ); // Open Graph. echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; if ( $image ) { echo '' . "\n"; } // Twitter Card. echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; if ( $image ) { echo '' . "\n"; } // Schema.org JSON-LD. if ( is_singular( 'novel' ) ) { webnovel_schema_novel(); } elseif ( is_singular( 'chapter' ) ) { webnovel_schema_chapter(); } } add_action( 'wp_head', 'webnovel_social_meta_tags', 5 ); /** * Output Schema.org Book structured data for a novel. * * @return void */ function webnovel_schema_novel() { $novel_id = get_the_ID(); $author = get_post_meta( $novel_id, '_webnovel_author', true ); $synopsis = get_post_meta( $novel_id, '_webnovel_synopsis', true ); $genres = get_the_terms( $novel_id, 'genre' ); $status = get_the_terms( $novel_id, 'novel_status' ); $image = has_post_thumbnail() ? get_the_post_thumbnail_url( null, 'full' ) : ''; $chapter_count = webnovel_get_chapter_count( $novel_id ); $schema = array( '@context' => 'https://schema.org', '@type' => 'Book', 'name' => get_the_title(), 'url' => get_permalink(), 'description' => $synopsis ? wp_strip_all_tags( $synopsis ) : get_the_excerpt(), 'numberOfPages' => $chapter_count, ); if ( $author ) { $schema['author'] = array( '@type' => 'Person', 'name' => $author, ); } if ( $image ) { $schema['image'] = $image; } if ( $genres && ! is_wp_error( $genres ) ) { $schema['genre'] = wp_list_pluck( $genres, 'name' ); } if ( $status && ! is_wp_error( $status ) ) { $schema['bookEdition'] = $status[0]->name; } // BreadcrumbList. $schema = array( '@context' => 'https://schema.org', '@graph' => array( $schema, array( '@type' => 'BreadcrumbList', 'itemListElement' => array( array( '@type' => 'ListItem', 'position' => 1, 'name' => __( 'Home', 'webnovel' ), 'item' => home_url( '/' ), ), array( '@type' => 'ListItem', 'position' => 2, 'name' => __( 'Novels', 'webnovel' ), 'item' => get_post_type_archive_link( 'novel' ), ), array( '@type' => 'ListItem', 'position' => 3, 'name' => get_the_title(), 'item' => get_permalink(), ), ), ), ), ); echo '' . "\n"; } /** * Output Schema.org Chapter / Article structured data. * * @return void */ function webnovel_schema_chapter() { $chapter_id = get_the_ID(); $novel_id = wp_get_post_parent_id( $chapter_id ); $novel = $novel_id ? get_post( $novel_id ) : null; $word_count = get_post_meta( $chapter_id, '_webnovel_word_count', true ); $image = $novel_id && has_post_thumbnail( $novel_id ) ? get_the_post_thumbnail_url( $novel_id, 'full' ) : ''; $schema = array( '@context' => 'https://schema.org', '@type' => 'Chapter', 'headline' => get_the_title(), 'url' => get_permalink(), 'datePublished' => get_the_date( 'c' ), 'dateModified' => get_the_modified_date( 'c' ), 'wordCount' => absint( $word_count ), ); if ( $image ) { $schema['image'] = $image; } if ( $novel ) { $schema['isPartOf'] = array( '@type' => 'Book', 'name' => $novel->post_title, 'url' => get_permalink( $novel_id ), ); } echo '' . "\n"; } studentfocusspots.com https://validator.w3.org/feed/docs/rss2.html Latest Updates Privacy Policy Pick-Up Request PBS Ch66: Afraid of Losing ICSST CH69: Progress: 100% ICSST CH68: The Victim WTNL Chapter 378.2 WTNL Chapter 379 PBS CH69: Test PBS CH68: Stimulation PBS CH67: The Test Subject ICSST CH70: Performance UE CH49: Connecting Link UE CH48: Connecting Link WTNL Chapter 378.1 POST PAGE The World Controlled By Dice ICSST CH67: Twin Carvings WTNL Chapter 375.2 WTNL Chapter 374.2 WTNL Chapter 377.2 WTNL Chapter 377.1 ICSST CH66: Just Ridiculous WTNL Chapter 375.1 WTNL Chapter 376 ICSST CH65: Home Turf  PBS CH65: The Past WTNL Chapter 374.1 Stairs of Paradox ICSST CH64: Kill the Boss UE CH47: Connecting Link WTNL Chapter 373 Lantern: Reflection of the Peach Blossoms UE CH46: Connecting Links PBS Ch64: Chief of Technology Peach Blossom Spring Welcome to the Nightmare Live ICSST CH63: Tide Rider This marriage won’t end in divorce?! The Daily Life of the Reborn Adopted Son of a Wealthy Family Untamed Enemy The Substitute Awakens Privacy Policy Survivorship Bias Mirror Puzzle Replacing the Evil Way Terms and Conditions The Feast of Filth