Skip to content

Commit

Permalink
Merge Conflict FIXED trunk to Media Credit Plugin Migrator
Browse files Browse the repository at this point in the history
  • Loading branch information
ronchambers committed Apr 1, 2024
2 parents 5dea1d6 + 07c86c0 commit f32717c
Show file tree
Hide file tree
Showing 6 changed files with 692 additions and 19 deletions.
2 changes: 2 additions & 0 deletions newspack-custom-content-migrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
Command\General\BlockTransformerCommand::class,
Command\General\PostDateMigrator::class,
Command\General\MediaCreditPluginMigrator::class,
Command\General\SimplyGuestAuthorNameMigrator::class,

// Publisher specific, remove when launched.
Command\PublisherSpecific\SoccerAmericaMigrator::class,
Expand All @@ -88,5 +89,6 @@
Command\PublisherSpecific\CityViewMigrator::class,
Command\PublisherSpecific\BigBendSentinelMigrator::class,
Command\PublisherSpecific\LAFocusMigrator::class,
Command\PublisherSpecific\TheFifthEstateMigrator::class,
)
);
230 changes: 218 additions & 12 deletions src/Command/General/EmbarcaderoMigrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,13 @@ public function register_commands() {
'optional' => false,
'repeating' => false,
],
[
'type' => 'assoc',
'name' => 'target-story-ids',
'description' => 'CSV list of target story IDs to re-process the "more posts" block for.',
'optional' => true,
'repeating' => false,
],
],
]
);
Expand Down Expand Up @@ -1077,6 +1084,32 @@ public function register_commands() {
'synopsis' => [],
]
);

WP_CLI::add_command(
'newspack-content-migrator embarcadero-establish-primary-categories',
[ $this, 'cmd_embarcadero_establish_primary_categories' ],
[
'shortdesc' => 'Establishes primary categories for migrated posts that don\'t already have them.',
'synopsis' => [],
]
);

WP_CLI::add_command(
'newspack-content-migrator embarcadero-create-missing-categories',
[ $this, 'cmd_embarcadero_create_missing_categories' ],
[
'shortdesc' => 'Creates missing categories based from a single curated list.',
'synopsis' => [
[
'type' => 'assoc',
'name' => 'csv-path',
'description' => 'Path to the CSV file containing the categories that exist per site.',
'optional' => false,
'repeating' => false,
],
],
]
);
}

/**
Expand Down Expand Up @@ -2146,20 +2179,36 @@ private function highlight_text( $text, $search, $chars_to_show = 10 ) {
public function cmd_embarcadero_migrate_more_posts_block( $args, $assoc_args ) {
$story_csv_file_path = $assoc_args['story-csv-file-path'];
$story_media_csv_file_path = $assoc_args['story-media-file-path'];
$target_story_ids = $assoc_args['target-story-ids'] ?? '';
$target_story_ids = explode( ',', $target_story_ids );

$posts = $this->get_data_from_csv_or_tsv( $story_csv_file_path );
$media_list = $this->get_data_from_csv_or_tsv( $story_media_csv_file_path );
$imported_original_ids = $this->get_posts_meta_values_by_key( self::EMBARCADERO_IMPORTED_MORE_POSTS_META_KEY );
$posts = $this->get_data_from_csv_or_tsv( $story_csv_file_path );
$media_list = $this->get_data_from_csv_or_tsv( $story_media_csv_file_path );

// Skip already imported posts.
$posts = array_values(
array_filter(
$posts,
function ( $post ) use ( $imported_original_ids ) {
return ! in_array( $post['story_id'], $imported_original_ids );
}
)
);
if ( ! empty( $target_story_ids ) ) {
$posts = array_values(
array_filter(
$posts,
function ( $post ) use ( $target_story_ids ) {
// phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict -- don't need strict comparison for this.
return in_array( $post['story_id'], $target_story_ids );
}
)
);
} else {
$imported_original_ids = $this->get_posts_meta_values_by_key( self::EMBARCADERO_IMPORTED_MORE_POSTS_META_KEY );

// Skip already imported posts.
$posts = array_values(
array_filter(
$posts,
function ( $post ) use ( $imported_original_ids ) {
// phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict -- don't need strict comparison for this.
return ! in_array( $post['story_id'], $imported_original_ids );
}
)
);
}

foreach ( $posts as $post_index => $post ) {
$this->logger->log( self::LOG_FILE, sprintf( 'Importing post %d/%d: %d', $post_index + 1, count( $posts ), $post['story_id'] ), Logger::LINE );
Expand Down Expand Up @@ -3533,6 +3582,163 @@ public function cmd_embarcadero_delete_disallowed_tags(): void {
}
}

/**
* This script helps establish the primary category for posts that were imported from Embarcadero's legacy system.
*
* @return void
*/
public function cmd_embarcadero_establish_primary_categories(): void {
global $wpdb;

// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$posts_without_primary_category = $wpdb->get_results(
"SELECT
p.ID
FROM $wpdb->posts p
WHERE p.ID IN (
SELECT post_id
FROM $wpdb->postmeta
WHERE meta_key IN ( '_newspack_import_id', 'original_article_id' )
)
AND p.ID NOT IN (
SELECT post_id
FROM $wpdb->postmeta
WHERE meta_key = '_yoast_wpseo_primary_category'
AND meta_value <> ''
)"
);
$posts_without_primary_category_count = count( $posts_without_primary_category );

$this->logger->log( self::LOG_FILE, sprintf( 'Found %s posts without a primary category.', number_format( $posts_without_primary_category_count ) ), Logger::INFO );

if ( 0 === $posts_without_primary_category_count ) {
$this->logger->log( self::LOG_FILE, 'No posts without a primary category found.', Logger::SUCCESS );

return;
}

// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$categories_by_slug = $wpdb->get_results(
"SELECT t.slug, t.name, t.term_id FROM $wpdb->terms t LEFT JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id WHERE tt.taxonomy = 'category'",
OBJECT_K
);

// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- Need handle to file to write CSV data.
$handle = fopen( 'establish_primary_categories.csv', 'w' );
fputcsv(
$handle,
[
'Post ID',
'Story ID',
'Permalink',
'Extracted Category',
'Current Categories',
'Status',
]
);
foreach ( $posts_without_primary_category as $post ) {
$permalink = get_permalink( $post->ID );
$url_path = wp_parse_url( $permalink, PHP_URL_PATH );
$exploded_url_path = array_filter( explode( '/', $url_path ) );
$story_id = get_post_meta( $post->ID, '_newspack_import_id', true );
if ( empty( $story_id ) ) {
$temp = get_post_meta( $post->ID, 'original_article_id', true );
if ( ! empty( $temp ) ) {
$story_id = $temp;
}
}

$csv_row_data = [
'Post ID' => $post->ID,
'Story ID' => $story_id,
'Permalink' => $permalink,
'Extracted Category' => null,
'Current Categories' => implode( ' <> ', wp_get_post_terms( $post->ID, 'category', [ 'fields' => 'names' ] ) ),
'Status' => null,
];

if ( empty( $exploded_url_path ) ) {
$this->logger->log( self::LOG_FILE, sprintf( 'Could not find a category within the slug (Post ID: %d) %s', $post->ID, $permalink ), Logger::ERROR );
fputcsv( $handle, array_values( $csv_row_data ) );
continue;
}

$first = array_shift( $exploded_url_path );
$csv_row_data['Extracted Category'] = $first;
if ( ! array_key_exists( $first, $categories_by_slug ) ) {
$this->logger->log( self::LOG_FILE, sprintf( 'Category not found %s', $permalink ), Logger::ERROR );
$csv_row_data['Status'] = 'Not Found';
fputcsv( $handle, array_values( $csv_row_data ) );
continue;
}

if ( 'uncategorized' === $first ) {
$this->logger->log( self::LOG_FILE, sprintf( 'Category is uncategorized, skipping post %d', $post->ID ), Logger::ERROR );
$csv_row_data['Status'] = 'Skipped';
fputcsv( $handle, array_values( $csv_row_data ) );
continue;
}

$this->logger->log( self::LOG_FILE, sprintf( 'Found %s, setting primary category for post %d to %s', $first, $post->ID, $categories_by_slug[ $first ]->name ), Logger::SUCCESS );

$category = $categories_by_slug[ $first ];

$update = update_post_meta( $post->ID, '_yoast_wpseo_primary_category', $category->term_id );

if ( $update ) {
$this->logger->log( self::LOG_FILE, sprintf( 'Primary category set for post %d', $post->ID ), Logger::SUCCESS );
$csv_row_data['Status'] = 'Updated';
} else {
$this->logger->log( self::LOG_FILE, sprintf( 'Could not set primary category for post %d', $post->ID ), Logger::ERROR );
$csv_row_data['Status'] = 'Failed';
}

fputcsv( $handle, array_values( $csv_row_data ) );
}

// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Need to close the file handle.
fclose( $handle );
}

/**
* This function uses a pre-defined CSV file that determines which categories and tags are missing from
* each site in the Embarcadero network. Whichever one is missing, the script will create that
* category or tag on the site.
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*
* @return void
* @throws Exception When the CSV file can't be read.
*/
public function cmd_embarcadero_create_missing_categories( $args, $assoc_args ): void {
$csv_path = $assoc_args['csv-path'];
$csv = ( new FileImportFactory() )->get_file( $csv_path )->getIterator();

$site = str_replace( 'https://', '', get_site_url() );

foreach ( $csv as $row_number => $row ) {
$taxonomy = $row['taxonomy'];
$slug = $row['slug'];
$create = 'No' === $row[ $site ];

$this->logger->log( self::LOG_FILE, sprintf( 'Processing row %d - Tax: %s Slug: %s Exists: %s', $row_number, $taxonomy, $slug, $row[ $site ] ), Logger::INFO );

if ( ! $create ) {
$this->logger->log( self::LOG_FILE, 'Skipping', Logger::INFO );
continue;
}

$term = wp_insert_term( $slug, $taxonomy );

if ( is_wp_error( $term ) ) {
$this->logger->log( self::LOG_FILE, sprintf( 'Could not create term %s: %s', $slug, $term->get_error_message() ), Logger::ERROR );
} else {
$this->logger->log( self::LOG_FILE, sprintf( 'Created term %s', $slug ), Logger::SUCCESS );
}
}
}

/**
* Function to save a post's meta data.
*
Expand Down
12 changes: 11 additions & 1 deletion src/Command/General/InlineFeaturedImageMigrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,17 @@ public function cmd_hide_featured_image_if_used_in_post_content( $pos_args, $ass
$featured_image_used_in_post_content = false !== strpos( $post_content, $featured_image_no_host );
if ( ! $featured_image_used_in_post_content ) {
WP_CLI::line( sprintf( 'Featured image not used inline.', $post_id ) );
continue;
}

// Check if Featured Image is used anywhere in post_content blocks.
$image_blocks = $this->get_image_blocks_from_post_content_blocks( parse_blocks( $post_content ) );
foreach ( $image_blocks as $image_block ) {
if ( $image_block['attrs']['id'] == $thumbnail_id ) {
$this->logger->log( $log, sprintf( 'Post ID %d — Featured image used in image block.', $post_id ), $this->logger::SUCCESS );
$featured_image_used_in_post_content = true;

break;
}
}

// Hide featured image.
Expand Down
Loading

0 comments on commit f32717c

Please sign in to comment.