Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: memory leaks from legacy term utilities #81

Merged
merged 4 commits into from
Jun 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 0 additions & 104 deletions includes/class-newspack-listings-core.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public static function instance() {
public function __construct() {
add_action( 'admin_menu', [ __CLASS__, 'add_plugin_page' ] );
add_action( 'init', [ __CLASS__, 'register_post_types' ] );
add_action( 'admin_init', [ __CLASS__, 'convert_legacy_taxonomies' ] );
add_filter( 'body_class', [ __CLASS__, 'set_template_class' ] );
add_action( 'save_post', [ __CLASS__, 'sync_post_meta' ], 10, 2 );
add_filter( 'newspack_listings_hide_author', [ __CLASS__, 'hide_author' ] );
Expand Down Expand Up @@ -842,109 +841,6 @@ public static function support_newspack_sponsors( $post_types ) {
array_values( self::NEWSPACK_LISTINGS_POST_TYPES )
);
}

/**
* Convert legacy custom taxonomies to regular post categories and tags.
* Helpful for sites that have been using v1 of the Listings plugin.
*/
public static function convert_legacy_taxonomies() {
$custom_category_slug = 'newspack_lst_cat';
$custom_tag_slug = 'newspack_lst_tag';

$category_args = [
'hierarchical' => true,
'public' => false,
'rewrite' => false,
'show_in_menu' => false,
'show_in_rest' => false,
'show_tagcloud' => false,
'show_ui' => false,
];
$tag_args = [
'hierarchical' => false,
'public' => false,
'rewrite' => false,
'show_in_menu' => false,
'show_in_rest' => false,
'show_tagcloud' => false,
'show_ui' => false,
];

// Temporarily register the taxonomies for all Listing CPTs.
$post_types = array_values( self::NEWSPACK_LISTINGS_POST_TYPES );
register_taxonomy( $custom_category_slug, $post_types, $category_args );
register_taxonomy( $custom_tag_slug, $post_types, $tag_args );

// Get a list of the custom terms.
$custom_terms = get_terms(
[
'taxonomy' => [ $custom_category_slug, $custom_tag_slug ],
'hide_empty' => false,
]
);

// If we don't have any terms from the legacy taxonomies, no need to proceed.
if ( is_wp_error( $custom_terms ) || 0 === count( $custom_terms ) ) {
unregister_taxonomy( $custom_category_slug );
unregister_taxonomy( $custom_tag_slug );
return;
}

foreach ( $custom_terms as $term ) {
// See if we have any corresponding terms already.
$corresponding_taxonomy = $custom_category_slug === $term->taxonomy ? 'category' : 'post_tag';
$corresponding_term = get_term_by( 'name', $term->name, $corresponding_taxonomy, ARRAY_A );

// If not, create the term.
if ( ! $corresponding_term ) {
$corresponding_term = wp_insert_term(
$term->name,
$corresponding_taxonomy,
[
'description' => $term->description,
'slug' => $term->slug,
]
);
}

// Get any posts with the legacy term.
$posts_with_custom_term = new \WP_Query(
[
'post_type' => $post_types,
'per_page' => 1000,
'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
[
'taxonomy' => $term->taxonomy,
'field' => 'term_id',
'terms' => $term->term_id,
],
],
]
);

// Apply the new term to the post.
if ( $posts_with_custom_term->have_posts() ) {
while ( $posts_with_custom_term->have_posts() ) {
$posts_with_custom_term->the_post();
wp_set_post_terms(
get_the_ID(), // Post ID to apply the new term.
[ $corresponding_term['term_id'] ], // Term ID of the new term.
$corresponding_taxonomy, // Category or tag.
true // Append the term without deleting existing terms.
);
}
}

// Finally, delete the legacy term.
if ( defined( 'NEWSPACK_LISTINGS_ENV' ) && 'production' === NEWSPACK_LISTINGS_ENV ) {
wp_delete_term( $term->term_id, $term->taxonomy );
}
}

// Unregister the legacy taxonomies.
unregister_taxonomy( $custom_category_slug );
unregister_taxonomy( $custom_tag_slug );
}
}

Newspack_Listings_Core::instance();
87 changes: 0 additions & 87 deletions includes/class-newspack-listings-taxonomies.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ public static function instance() {
*/
public function __construct() {
add_action( 'init', [ __CLASS__, 'init' ] );
add_action( 'admin_init', [ __CLASS__, 'handle_missing_terms' ] );
add_action( 'admin_init', [ __CLASS__, 'handle_orphaned_terms' ] );
add_filter( 'rest_prepare_taxonomy', [ __CLASS__, 'hide_taxonomy_sidebar' ], 10, 2 );
register_activation_hook( NEWSPACK_LISTINGS_FILE, [ __CLASS__, 'activation_hook' ] );
}
Expand Down Expand Up @@ -395,91 +393,6 @@ public static function create_shadow_term( $post, $taxonomy = null ) {
return $new_term;
}

/**
* Handle any published posts of the relevant types that are missing a corresponding shadow term.
*/
public static function handle_missing_terms() {
$tax_query = [ 'relation' => 'OR' ];

foreach ( self::NEWSPACK_LISTINGS_TAXONOMIES as $post_type_to_shadow => $shadow_taxonomy ) {
$tax_query[] = [
'taxonomy' => $shadow_taxonomy,
'operator' => 'NOT EXISTS',
];
}

$query = new \WP_Query(
[
'post_type' => self::get_post_types_to_shadow(),
'post_status' => 'publish',
'posts_per_page' => 100,
'tax_query' => $tax_query, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
]
);

if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$post_id = get_the_ID();
$post = get_post( $post_id );
$post_type = $post->post_type;
$term_slug = array_keys( Core::NEWSPACK_LISTINGS_POST_TYPES, $post_type );
$term_slug = reset( $term_slug );

// Bail if not a post type to be shadowed.
if ( empty( $term_slug ) || ! self::should_update_shadow_term( $post ) ) {
continue;
}

// Check for a shadow term associated with this post.
$shadow_term = self::get_shadow_term( $post, self::NEWSPACK_LISTINGS_TAXONOMIES[ $term_slug ] );

// If there isn't already a shadow term, create it. Otherwise, apply the term to the post.
if ( empty( $shadow_term ) ) {
self::create_shadow_term( $post, self::NEWSPACK_LISTINGS_TAXONOMIES[ $term_slug ] );
} else {
wp_set_post_terms( $post_id, $shadow_term->term_id, self::NEWSPACK_LISTINGS_TAXONOMIES[ $term_slug ], true );
}
}
}
}

/**
* Delete any shadow terms that no longer have a post to shadow.
*/
public static function handle_orphaned_terms() {
$all_terms = get_terms(
[
'taxonomy' => array_values( self::NEWSPACK_LISTINGS_TAXONOMIES ),
'hide_empty' => false,
]
);
$term_slugs = array_column( $all_terms, 'slug' );
$query = new \WP_Query(
[
'post_type' => self::get_post_types_to_shadow(),
'post_status' => 'publish',
'posts_per_page' => 100,
'post_name__in' => $term_slugs,
]
);

if ( $query->have_posts() ) {
$post_slugs = array_column( $query->posts, 'post_name' );
$orphaned_slugs = array_diff( $term_slugs, $post_slugs );
$orphaned_terms = array_filter(
$all_terms,
function( $term ) use ( $orphaned_slugs ) {
return in_array( $term->slug, $orphaned_slugs );
}
);

foreach ( $orphaned_terms as $orphaned_term ) {
wp_delete_term( $orphaned_term->term_id, $orphaned_term->taxonomy );
}
}
}

/**
* Workaround to hide the default taxonomy sidebars, since we're registering our own UI for managing shadow terms.
* The taxonomies must be available via REST from our custom UI, but hidden to Gutenberg's default taxonomy UI.
Expand Down
8 changes: 4 additions & 4 deletions includes/importer/class-newspack-listings-importer.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,13 @@ public static function run_cli_command( $args, $assoc_args ) {
}

if ( self::$is_dry_run ) {
WP_CLI::line( "\n===================\n= Dry Run =\n===================\n" );
WP_CLI::log( "\n===================\n= Dry Run =\n===================\n" );
}

if ( 0 < $start_row ) {
WP_CLI::line( 'Starting CSV import at row ' . $start_row . '...' );
WP_CLI::log( 'Starting CSV import at row ' . $start_row . '...' );
} else {
WP_CLI::line( 'Starting CSV import...' );
WP_CLI::log( 'Starting CSV import...' );
}
self::import_data( $file_path, $start_row, $max_rows );
WP_CLI::success( 'Completed! Processed ' . ( self::$row_number - $start_row ) . ' records.' );
Expand Down Expand Up @@ -301,7 +301,7 @@ public static function import_listing( $data ) {
],
];

WP_CLI::line( 'Importing data for ' . $post['post_title'] . '...' );
WP_CLI::log( 'Importing data for ' . $post['post_title'] . '...' );

// If a post already exists, update it.
if ( $existing_post ) {
Expand Down
Loading