From 526599fbe1d4f14a413dc8972f351abf5e2bb36a Mon Sep 17 00:00:00 2001 From: Zakariae Filali Date: Tue, 18 Jun 2024 00:23:56 +0300 Subject: [PATCH 1/3] add(EnterpriseMigrator): main migration command --- newspack-custom-content-migrator.php | 1 + .../PublisherSpecific/EnterpriseMigrator.php | 377 ++++++++++++++++++ src/Logic/GutenbergBlockGenerator.php | 27 +- 3 files changed, 401 insertions(+), 4 deletions(-) create mode 100644 src/Command/PublisherSpecific/EnterpriseMigrator.php diff --git a/newspack-custom-content-migrator.php b/newspack-custom-content-migrator.php index 866d73e63..6d3d13d9f 100644 --- a/newspack-custom-content-migrator.php +++ b/newspack-custom-content-migrator.php @@ -91,5 +91,6 @@ Command\PublisherSpecific\BigBendSentinelMigrator::class, Command\PublisherSpecific\LAFocusMigrator::class, Command\PublisherSpecific\TheFifthEstateMigrator::class, + Command\PublisherSpecific\EnterpriseMigrator::class, ) ); diff --git a/src/Command/PublisherSpecific/EnterpriseMigrator.php b/src/Command/PublisherSpecific/EnterpriseMigrator.php new file mode 100644 index 000000000..f9dc1a229 --- /dev/null +++ b/src/Command/PublisherSpecific/EnterpriseMigrator.php @@ -0,0 +1,377 @@ + 'Enterprise Staff', + 'email' => 'staff@enterprise.news', + ]; + + /** + * @var null|InterfaceCommand Instance. + */ + private static $instance = null; + + /** + * Logger instance. + * + * @var Logger Logger instance. + */ + private $logger; + + /** + * JsonIterator instance. + * + * @var JsonIterator + */ + private $json_iterator; + + /** + * Instance of Attachments logic. + * + * @var null|Attachments + */ + private $attachments; + + /** + * GutenbergBlockGenerator instance. + * + * @var GutenbergBlockGenerator. + */ + private $gutenberg_block_generator; + + /** + * Crawler instance. + * + * @var Crawler Crawler instance. + */ + private $crawler; + + /** + * Constructor. + */ + private function __construct() { + $this->logger = new Logger(); + $this->json_iterator = new JsonIterator(); + $this->attachments = new Attachments(); + $this->gutenberg_block_generator = new GutenbergBlockGenerator(); + $this->crawler = new Crawler(); + } + + /** + * Singleton get_instance(). + * + * @return InterfaceCommand|null + */ + public static function get_instance() { + $class = get_called_class(); + if ( null === self::$instance ) { + self::$instance = new $class(); + } + + return self::$instance; + } + + /** + * See InterfaceCommand::register_commands. + */ + public function register_commands() { + WP_CLI::add_command( + 'newspack-content-migrator enterprise-migrate-content', + [ $this, 'cmd_enterprise_migrate_content' ], + [ + 'shortdesc' => 'Searches all asset JSONs and finds equivalent already imported attachment post_ids. Accuracy of this should be high but it is expected that it is not perfect, HTML galleries for QA and verification of results are produced.', + 'synopsis' => [ + [ + 'type' => 'assoc', + 'name' => 'parsing-issue-json-file', + 'description' => 'The path to the JSON file containing parsing issues (ParsingIssue.json).', + 'optional' => false, + 'repeating' => false, + ], + [ + 'type' => 'assoc', + 'name' => 'story-json-file', + 'description' => 'The path to the JSON file containing stories (Story.json).', + 'optional' => false, + 'repeating' => false, + ], + [ + 'type' => 'assoc', + 'name' => 'story-tag-json-file', + 'description' => 'The path to the JSON file containing stories tags (StoryTag.json).', + 'optional' => false, + 'repeating' => false, + ], + [ + 'type' => 'assoc', + 'name' => 'language', + 'description' => 'The language of the content to be migrated (1: Arabic, 2: English). Default: 2.', + 'default' => 2, + 'optional' => false, + 'repeating' => false, + ], + [ + 'type' => 'assoc', + 'name' => 'brand-id', + 'description' => 'The brand ID of the content to be migrated.', + 'optional' => false, + 'repeating' => false, + ], + [ + 'type' => 'flag', + 'name' => 'refresh-content', + 'description' => 'Refresh content if it already exists.', + 'default' => false, + 'optional' => true, + 'repeating' => false, + ], + ], + ] + ); + } + + /** + * Callable for `newspack-content-migrator enterprise-migrate-content`. + * + * @param array $args CLI args. + * @param array $assoc_args CLI args. + */ + public function cmd_enterprise_migrate_content( $args, $assoc_args ) { + $log_file = 'cmd_enterprise_migrate_content.log'; + + $parsing_issue_json_file = $assoc_args['parsing-issue-json-file']; + $story_json_file = $assoc_args['story-json-file']; + $story_tag_json_file = $assoc_args['story-tag-json-file']; + $language = $assoc_args['language']; + $brand_id = $assoc_args['brand-id']; + $refresh_content = isset( $assoc_args['refresh-content'] ) ? true : false; + + $author_id = $this->get_unique_author_id(); + + if ( is_wp_error( $author_id ) ) { + $this->logger->log( $log_file, ' -- Error creating author: ' . $author_id->get_error_message(), Logger::WARNING ); + return false; + } + + if ( ! in_array( $language, [ 1, 2 ] ) ) { + $this->logger->log( $log_file, 'Invalid language. Please provide a valid language (1: Arabic, 2: English).', Logger::ERROR ); + return; + } + + $existing_original_ids = $this->get_existing_original_ids(); + + $total_stories = $this->json_iterator->count_json_array_entries( $story_json_file ); + $counter = 0; + + foreach ( $this->json_iterator->items( $story_json_file ) as $story ) { + ++$counter; + $this->logger->log( $log_file, "Processing story {$counter} of {$total_stories}...", Logger::INFO ); + + if ( $language !== $story->LanguageId ) { + continue; + } + + if ( $story->WebExclude ) { + $this->logger->log( $log_file, "Story with ID {$story->StoryId} is excluded from the web. Skipping.", Logger::INFO ); + continue; + } + + if ( empty( $story->StoryContent ) ) { + $this->logger->log( $log_file, "Story with ID {$story->StoryId} has no content. Skipping.", Logger::WARNING ); + continue; + } + + // Skip the story if it's already imported and we're not refreshing content. + if ( in_array( $story->StoryId, $existing_original_ids ) && ! $refresh_content ) { + $this->logger->log( $log_file, "Story with ID {$story->StoryId} already imported. Skipping.", Logger::INFO ); + continue; + } + + $wp_story_post_id = $this->migrate_story( $story, $brand_id, $author_id, $log_file ); + $this->logger->log( $log_file, "Migrated story with ID {$story->StoryId} to post ID {$wp_story_post_id}.", Logger::SUCCESS ); + } + } + + /** + * Migrate story. + * + * @param object $story Story object. + * @param string $brand_id Brand ID. + * @param string $author_id Author ID. + * @param string $log_file Log file. + * @return int|WP_Error Story post ID or WP_Error. + */ + private function migrate_story( $story, $brand_id, $author_id, $log_file ) { + $post_content = $this->clean_content( $story->StoryContent ); + + // Generate post. + $post_data = [ + 'post_title' => $story->Head, + 'post_content' => $post_content, + 'post_status' => $story->IsPublished ? 'publish' : 'draft', + 'post_date' => $story->PublishDate->{'$date'}, + 'post_author' => $author_id, + 'post_type' => 'post', + ]; + + // Insert or get the existing post. + $wp_post_id = $this->get_post_id_by_meta( self::ORIGINAL_ID_META_KEY, $story->StoryId ); + + if ( ! $wp_post_id ) { + $wp_post_id = wp_insert_post( $post_data ); + } else { + $post_data['ID'] = $wp_post_id; + wp_update_post( $post_data ); + } + + // Audio File. + if ( ! empty( $story->VoiceFileUrl ) ) { + $audio_file_post_id = $this->attachments->import_external_file( $story->VoiceFileUrl, null, null, null, null, $wp_post_id ); + + if ( is_wp_error( $audio_file_post_id ) ) { + $this->logger->log( $log_file, sprintf( 'Could not upload file %s: %s', $story->VoiceFileUrl, $audio_file_post_id->get_error_message() ), Logger::WARNING ); + } else { + wp_update_post( + [ + 'ID' => $wp_post_id, + 'post_content' => serialize_block( $this->gutenberg_block_generator->get_audio( $audio_file_post_id ) ) . $post_content, + ] + ); + } + } + + // Post category. + $cateogry_id = wp_create_category( $story->SectionHead ); + wp_set_post_categories( $wp_post_id, $cateogry_id ); + + // Post tags. + wp_set_post_tags( $wp_post_id, implode( ',', $story->StoryTags ) ); + + // Post subtitle. + update_post_meta( $wp_post_id, 'newspack_post_subtitle', $story->StoryTeaser ); + + // Featured image. + if ( ! empty( $story->WebImageURL ) ) { + $file_post_id = $this->attachments->import_external_file( $story->WebImageURL, null, null, null, null, $wp_post_id ); + + if ( is_wp_error( $file_post_id ) ) { + $this->logger->log( $log_file, sprintf( 'Could not upload file %s: %s', $story->WebImageURL, $file_post_id->get_error_message() ), Logger::WARNING ); + } else { + set_post_thumbnail( $wp_post_id, $file_post_id ); + } + } + + // A few meta fields. + update_post_meta( $wp_post_id, self::ORIGINAL_ID_META_KEY, $story->StoryId ); + update_post_meta( $wp_post_id, self::STORY_ISSUE_ORIGINAL_ID, $story->IssueId ); + + // Set the post brand. + wp_set_post_terms( $wp_post_id, [ $brand_id ], 'brand' ); + + return $wp_post_id; + } + + /** + * Clean content. + * + * @param string $content Content to clean. + * + * @return string Cleaned content. + */ + private function clean_content( $content ) { + // Remove the subscription block. + $this->crawler->clear(); + $this->crawler->add( $content ); + + // Remove the subscription block. + $subscribe_box_panel = $this->crawler->filter( '.subscribe-box-panel' ); + if ( $subscribe_box_panel->count() > 0 ) { + $subscribe_box_panel->each( + function ( $node ) { + $node->getNode( 0 )->parentNode->removeChild( $node->getNode( 0 ) ); + } + ); + } + + return $this->crawler->html(); + } + + /** + * Add or return author ID by display name. + * + * @return int|WP_Error Author ID or WP_Error. + */ + private function get_unique_author_id() { + $username = sanitize_user( self::DEFAULT_AUTHOR['display_name'], true ); + $author = get_user_by( 'login', $username ); + + if ( $author instanceof \WP_User ) { + return $author->ID; + } + + $author_id = wp_insert_user( + [ + 'display_name' => self::DEFAULT_AUTHOR['display_name'], + 'user_login' => $username, + // 'user_email' => self::DEFAULT_AUTHOR['email'], + 'user_pass' => wp_generate_password(), + 'role' => 'author', + ] + ); + + return $author_id; + } + + /** + * Get existing original IDs. + * + * @return array Existing original IDs. + */ + private function get_existing_original_ids() { + global $wpdb; + + $existing_original_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = %s", self::ORIGINAL_ID_META_KEY ) ); + + return $existing_original_ids; + } + + /** + * Get post ID by meta. + * + * @param string $meta_name Meta name. + * @param string $meta_value Meta value. + * @return int|null + */ + private function get_post_id_by_meta( $meta_name, $meta_value ) { + global $wpdb; + + if ( empty( $meta_value ) ) { + return null; + } + + return $wpdb->get_var( + $wpdb->prepare( + "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s", + $meta_name, + $meta_value + ) + ); + } +} diff --git a/src/Logic/GutenbergBlockGenerator.php b/src/Logic/GutenbergBlockGenerator.php index e8ef87141..922c920a4 100644 --- a/src/Logic/GutenbergBlockGenerator.php +++ b/src/Logic/GutenbergBlockGenerator.php @@ -15,7 +15,7 @@ namespace NewspackCustomContentMigrator\Logic; -use \NewspackCustomContentMigrator\Utils\Logger; +use NewspackCustomContentMigrator\Utils\Logger; use WP_Post; /** @@ -71,7 +71,7 @@ public function get_jetpack_tiled_gallery( $attachment_ids, $link_to = null, $ti ' ', array_filter( array_map( - function( $index, $attachment_id ) use ( &$tile_sizes, &$non_existing_attachment_indexes, $tile_sizes_list ) { + function ( $index, $attachment_id ) use ( &$tile_sizes, &$non_existing_attachment_indexes, $tile_sizes_list ) { $attachment_url = wp_get_attachment_url( $attachment_id ); if ( ! $attachment_url ) { @@ -819,7 +819,7 @@ public function get_twitter( string $src, string $caption = '' ): array { 'type' => 'rich', 'providerNameSlug' => 'twitter', 'responsive' => true, - 'className' => $class_names + 'className' => $class_names, ], 'innerBlocks' => [], 'innerHTML' => $block_content, @@ -945,6 +945,26 @@ private function get_list_item( $content ) { ]; } + /** + * Generate an audio block. + * + * @param int $attachment_post_id Attachment post ID. + * + * @return array to be used in the serialize_blocks function to get the raw content of a Gutenberg Block. + */ + public function get_audio( $attachment_post_id ) { + $attachment_url = wp_get_attachment_url( $attachment_post_id ); + $inner_html = '
'; + + return [ + 'blockName' => 'core/audio', + 'attrs' => [ 'id' => $attachment_post_id ], + 'innerBlocks' => [], + 'innerHTML' => $inner_html, + 'innerContent' => [ $inner_html ], + ]; + } + /** * Generate tile size based on its index. * @@ -1042,5 +1062,4 @@ public function get_homepage_articles_for_specific_posts( array $post_ids, array 'innerContent' => [], ]; } - } From a232dd35b00c2fb8b915da90089ff87d8fb8eb21 Mon Sep 17 00:00:00 2001 From: Zakariae Filali Date: Mon, 15 Jul 2024 11:13:48 +0100 Subject: [PATCH 2/3] feat(EntepriseMigrator): migrate issues --- .../PublisherSpecific/EnterpriseMigrator.php | 247 +++++++++++++++--- 1 file changed, 213 insertions(+), 34 deletions(-) diff --git a/src/Command/PublisherSpecific/EnterpriseMigrator.php b/src/Command/PublisherSpecific/EnterpriseMigrator.php index f9dc1a229..f1cde1eac 100644 --- a/src/Command/PublisherSpecific/EnterpriseMigrator.php +++ b/src/Command/PublisherSpecific/EnterpriseMigrator.php @@ -17,6 +17,7 @@ class EnterpriseMigrator implements InterfaceCommand { const ORIGINAL_ID_META_KEY = '_newspack_original_id'; const STORY_ISSUE_ORIGINAL_ID = '_newspack_story_issue_original_id'; + const ISSUE_ORIGINAL_ID = '_newspack_issue_original_id'; const DEFAULT_AUTHOR = [ 'display_name' => 'Enterprise Staff', @@ -96,15 +97,8 @@ public function register_commands() { 'newspack-content-migrator enterprise-migrate-content', [ $this, 'cmd_enterprise_migrate_content' ], [ - 'shortdesc' => 'Searches all asset JSONs and finds equivalent already imported attachment post_ids. Accuracy of this should be high but it is expected that it is not perfect, HTML galleries for QA and verification of results are produced.', + 'shortdesc' => 'Command to migrate stories.', 'synopsis' => [ - [ - 'type' => 'assoc', - 'name' => 'parsing-issue-json-file', - 'description' => 'The path to the JSON file containing parsing issues (ParsingIssue.json).', - 'optional' => false, - 'repeating' => false, - ], [ 'type' => 'assoc', 'name' => 'story-json-file', @@ -114,23 +108,33 @@ public function register_commands() { ], [ 'type' => 'assoc', - 'name' => 'story-tag-json-file', - 'description' => 'The path to the JSON file containing stories tags (StoryTag.json).', + 'name' => 'brand-id', + 'description' => 'The brand ID of the content to be migrated.', 'optional' => false, 'repeating' => false, ], [ - 'type' => 'assoc', - 'name' => 'language', - 'description' => 'The language of the content to be migrated (1: Arabic, 2: English). Default: 2.', - 'default' => 2, - 'optional' => false, + 'type' => 'flag', + 'name' => 'refresh-content', + 'description' => 'Refresh content if it already exists.', + 'default' => false, + 'optional' => true, 'repeating' => false, ], + ], + ] + ); + + WP_CLI::add_command( + 'newspack-content-migrator enterprise-migrate-issues', + [ $this, 'cmd_enterprise_migrate_issues' ], + [ + 'shortdesc' => 'Migrate issues.', + 'synopsis' => [ [ 'type' => 'assoc', - 'name' => 'brand-id', - 'description' => 'The brand ID of the content to be migrated.', + 'name' => 'parsing-issue-json-file', + 'description' => 'The path to the JSON file containing parsing issues (ParsingIssue.json).', 'optional' => false, 'repeating' => false, ], @@ -156,12 +160,9 @@ public function register_commands() { public function cmd_enterprise_migrate_content( $args, $assoc_args ) { $log_file = 'cmd_enterprise_migrate_content.log'; - $parsing_issue_json_file = $assoc_args['parsing-issue-json-file']; - $story_json_file = $assoc_args['story-json-file']; - $story_tag_json_file = $assoc_args['story-tag-json-file']; - $language = $assoc_args['language']; - $brand_id = $assoc_args['brand-id']; - $refresh_content = isset( $assoc_args['refresh-content'] ) ? true : false; + $story_json_file = $assoc_args['story-json-file']; + $brand_id = $assoc_args['brand-id']; + $refresh_content = isset( $assoc_args['refresh-content'] ) ? true : false; $author_id = $this->get_unique_author_id(); @@ -170,11 +171,6 @@ public function cmd_enterprise_migrate_content( $args, $assoc_args ) { return false; } - if ( ! in_array( $language, [ 1, 2 ] ) ) { - $this->logger->log( $log_file, 'Invalid language. Please provide a valid language (1: Arabic, 2: English).', Logger::ERROR ); - return; - } - $existing_original_ids = $this->get_existing_original_ids(); $total_stories = $this->json_iterator->count_json_array_entries( $story_json_file ); @@ -184,10 +180,6 @@ public function cmd_enterprise_migrate_content( $args, $assoc_args ) { ++$counter; $this->logger->log( $log_file, "Processing story {$counter} of {$total_stories}...", Logger::INFO ); - if ( $language !== $story->LanguageId ) { - continue; - } - if ( $story->WebExclude ) { $this->logger->log( $log_file, "Story with ID {$story->StoryId} is excluded from the web. Skipping.", Logger::INFO ); continue; @@ -209,6 +201,47 @@ public function cmd_enterprise_migrate_content( $args, $assoc_args ) { } } + /** + * Callable for `newspack-content-migrator enterprise-migrate-issues`. + * + * @param array $args CLI args. + * @param array $assoc_args CLI args. + */ + public function cmd_enterprise_migrate_issues( $args, $assoc_args ) { + $log_file = 'cmd_enterprise_migrate_issues.log'; + + $parsing_issue_file = $assoc_args['parsing-issue-json-file']; + $refresh_content = isset( $assoc_args['refresh-content'] ) ? true : false; + + $author_id = $this->get_unique_author_id(); + + if ( is_wp_error( $author_id ) ) { + $this->logger->log( $log_file, ' -- Error creating author: ' . $author_id->get_error_message(), Logger::WARNING ); + return false; + } + + $existing_original_ids = $this->get_existing_original_ids( self::STORY_ISSUE_ORIGINAL_ID ); + + $total_issues = $this->json_iterator->count_json_array_entries( $parsing_issue_file ); + $counter = 0; + + foreach ( $this->json_iterator->items( $parsing_issue_file ) as $issue ) { + ++$counter; + $this->logger->log( $log_file, "Processing issue {$counter} of {$total_issues}...", Logger::INFO ); + + // Skip the story if it's already imported and we're not refreshing content. + if ( in_array( $issue->IssueId, $existing_original_ids ) && ! $refresh_content ) { + $this->logger->log( $log_file, "Issue with ID {$issue->IssueId} already imported. Skipping.", Logger::INFO ); + continue; + } + + $wp_issue_post_id = $this->migrate_issue( $issue, $author_id, $log_file ); + if ( $wp_issue_post_id ) { + $this->logger->log( $log_file, "Migrated issue with ID {$issue->IssueId} to post ID {$wp_issue_post_id}.", Logger::SUCCESS ); + } + } + } + /** * Migrate story. * @@ -288,6 +321,103 @@ private function migrate_story( $story, $brand_id, $author_id, $log_file ) { return $wp_post_id; } + /** + * Migrate issue. + * + * @param object $issue Issue object. + * @param string $author_id Author ID. + * @param string $log_file Log file. + * @return int|WP_Error Issue post ID or WP_Error. + */ + private function migrate_issue( $issue, $author_id, $log_file ) { + // Get all Issues's posts. + $issue_posts = get_posts( + [ + 'post_type' => 'post', + 'posts_per_page' => -1, + 'meta_key' => self::STORY_ISSUE_ORIGINAL_ID, + 'meta_value' => $issue->IssueId, + ] + ); + + if ( empty( $issue_posts ) ) { + return false; + } + + // Migrate all posts to the issue category. + // Create "Issues" the main category. + $issue_category_id = wp_create_category( 'Issues' ); + // Create the issue category. + $category_id = wp_create_category( $issue->WebHead, $issue_category_id ); + + // Append the category to each post. + foreach ( $issue_posts as $issue_post ) { + wp_set_post_categories( $issue_post->ID, [ $category_id ], true ); + } + + // Migrate the issue as a post. + $post_content = $this->generate_issue_content( $issue, $issue_posts ); + + // Generate post. + $post_data = [ + 'post_title' => $issue->WebHead, + 'post_content' => $post_content, + 'post_status' => $issue->IsPublishedWeb ? 'publish' : 'draft', + 'post_date' => $issue->PublishDate->{'$date'}, + 'post_author' => $author_id, + 'post_type' => 'post', + ]; + + // Insert or get the existing post. + $wp_post_id = $this->get_post_id_by_meta( self::ORIGINAL_ID_META_KEY, $issue->IssueId ); + + if ( ! $wp_post_id ) { + $wp_post_id = wp_insert_post( $post_data ); + } else { + $post_data['ID'] = $wp_post_id; + wp_update_post( $post_data ); + } + + // Audio File. + if ( ! empty( $issue->IntroductionVoiceUrl ) ) { + $audio_file_post_id = $this->attachments->import_external_file( $issue->IntroductionVoiceUrl, null, null, null, null, $wp_post_id ); + + if ( is_wp_error( $audio_file_post_id ) ) { + $this->logger->log( $log_file, sprintf( 'Could not upload file %s: %s', $issue->IntroductionVoiceUrl, $audio_file_post_id->get_error_message() ), Logger::WARNING ); + } else { + wp_update_post( + [ + 'ID' => $wp_post_id, + 'post_content' => serialize_block( $this->gutenberg_block_generator->get_audio( $audio_file_post_id ) ) . $post_content, + ] + ); + } + } + + // Post category. + $cateogry_id = wp_create_category( 'Issues Posts' ); + wp_set_post_categories( $wp_post_id, $cateogry_id ); + + // Post subtitle. + update_post_meta( $wp_post_id, 'newspack_post_subtitle', $issue->IssueTeaser ); + + // Featured image. + if ( ! empty( $issue->EditionWebImage ) ) { + $file_post_id = $this->attachments->import_external_file( $issue->EditionWebImage, null, null, null, null, $wp_post_id ); + + if ( is_wp_error( $file_post_id ) ) { + $this->logger->log( $log_file, sprintf( 'Could not upload file %s: %s', $issue->EditionWebImage, $file_post_id->get_error_message() ), Logger::WARNING ); + } else { + set_post_thumbnail( $wp_post_id, $file_post_id ); + } + } + + // A few meta fields. + update_post_meta( $wp_post_id, self::ISSUE_ORIGINAL_ID, $issue->IssueId ); + + return $wp_post_id; + } + /** * Clean content. * @@ -313,6 +443,53 @@ function ( $node ) { return $this->crawler->html(); } + /** + * Generate issue content. + * + * @param object $issue Issue object. + * @param array $issue_posts Issue posts. + * + * @return string Issue content. + */ + private function generate_issue_content( $issue, $issue_posts ) { + $content_blocks = []; + + // TLDR. + $content_blocks[] = $this->gutenberg_block_generator->get_heading( 'TL;DR' ); + + // TLDR list. + $content_blocks[] = $this->gutenberg_block_generator->get_list( + array_map( + function ( $issue ) { + $text = $issue->TLDRLineText; + if ( ! empty( $issue->TLDRLineCategory ) ) { + $text .= ' | ' . $issue->TLDRLineCategory; + } + return $text; + }, + $issue->TLDR + ) + ); + + // Homepage Blog Posts block. + $content_blocks[] = $this->gutenberg_block_generator->get_homepage_articles_for_specific_posts( + array_map( + function ( $issue_post ) { + return $issue_post->ID; + }, + $issue_posts + ), + [ + 'excerptLength' => 100, + 'showReadMore' => false, + 'showDate' => false, + 'showAuthor' => false, + ] + ); + + return serialize_blocks( $content_blocks ); + } + /** * Add or return author ID by display name. * @@ -342,12 +519,14 @@ private function get_unique_author_id() { /** * Get existing original IDs. * + * @param string $key Meta key, default is self::ORIGINAL_ID_META_KEY. + * * @return array Existing original IDs. */ - private function get_existing_original_ids() { + private function get_existing_original_ids( $key = self::ORIGINAL_ID_META_KEY ) { global $wpdb; - $existing_original_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = %s", self::ORIGINAL_ID_META_KEY ) ); + $existing_original_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = %s", $key ) ); return $existing_original_ids; } From 32e111a9ffd1b45c1001f8f71e14e69982943bca Mon Sep 17 00:00:00 2001 From: Zakariae Filali Date: Mon, 15 Jul 2024 11:14:29 +0100 Subject: [PATCH 3/3] chore(GutenbergBlockGenerator): set specific mode for specific posts in the homepage posts block --- src/Logic/GutenbergBlockGenerator.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Logic/GutenbergBlockGenerator.php b/src/Logic/GutenbergBlockGenerator.php index 922c920a4..0205fc4fe 100644 --- a/src/Logic/GutenbergBlockGenerator.php +++ b/src/Logic/GutenbergBlockGenerator.php @@ -1044,6 +1044,7 @@ public function get_homepage_articles_for_specific_posts( array $post_ids, array if ( empty( $post_ids ) ) { return []; } + $args['specificMode'] = true; $args['specificPosts'] = $post_ids; if ( is_array( $args['className'] ?? false ) ) { $args['className'] = implode( ' ', $args['className'] );