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

Optimize the process of deleting AMP data during uninstallation #6840

Merged
merged 17 commits into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
99 changes: 49 additions & 50 deletions includes/uninstall-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,33 +59,23 @@ function delete_posts() {

global $wpdb;

$current_page = 0;
$per_page = 1000;
$post_type = 'amp_validated_url';

do {
$offset = $per_page * $current_page;

// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Cannot cache result since we're deleting the records.
$post_ids = $wpdb->get_col(
$wpdb->prepare(
"SELECT ID FROM $wpdb->posts WHERE post_type = %s LIMIT %d OFFSET %d;",
$post_type,
$per_page,
$offset
)
);

if ( empty( $post_ids ) || ! is_array( $post_ids ) ) {
break;
}
$post_type = 'amp_validated_url';
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

foreach ( $post_ids as $post_id ) {
wp_delete_post( $post_id );
}
// Delete all post meta data related to "amp_validated_url" post_type.
$wpdb->query(
$wpdb->prepare(
"DELETE meta FROM $wpdb->postmeta AS meta INNER JOIN $wpdb->posts AS posts ON posts.ID = meta.post_id WHERE posts.post_type = %s;",
$post_type
)
);

$current_page++;
} while ( ! empty( $result ) );
$wpdb->delete(
$wpdb->posts,
compact( 'post_type' )
);

// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}

/**
Expand All @@ -98,33 +88,39 @@ function delete_terms() {

global $wpdb;

$current_page = 0;
$per_page = 1000;
$taxonomy = 'amp_validation_error';

do {
$offset = $per_page * $current_page;

// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Cannot cache result since we're deleting the records.
$term_ids = $wpdb->get_col(
$wpdb->prepare(
"SELECT term_id FROM $wpdb->term_taxonomy WHERE taxonomy = %s LIMIT %d OFFSET %d;",
$taxonomy,
$per_page,
$offset
)
);

if ( empty( $term_ids ) || ! is_array( $term_ids ) ) {
break;
}
$taxonomy = 'amp_validation_error';
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

foreach ( $term_ids as $term_id ) {
wp_delete_term( $term_id, $taxonomy );
}
// Delete term meta.
$wpdb->query(
$wpdb->prepare(
"DELETE tm from $wpdb->termmeta AS tm INNER JOIN $wpdb->term_taxonomy AS tt ON tm.term_id = tt.term_id WHERE tt.taxonomy = %s;",
$taxonomy
)
);

$current_page++;
} while ( ! empty( $result ) );
// Delete term relationship.
$wpdb->query(
$wpdb->prepare(
"DELETE tr from $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy = %s;",
$taxonomy
)
);

// Delete terms.
$wpdb->query(
$wpdb->prepare(
"DELETE terms from $wpdb->terms AS terms INNER JOIN $wpdb->term_taxonomy AS tt ON terms.term_id = tt.term_id WHERE tt.taxonomy = %s;",
$taxonomy
)
);

// Delete term taxonomy.
$wpdb->delete(
$wpdb->term_taxonomy,
compact( 'taxonomy' )
);
// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}

/**
Expand Down Expand Up @@ -200,5 +196,8 @@ function remove_plugin_data() {
delete_posts();
delete_terms();
delete_transients();

// Clear any cached data that has been removed.
wp_cache_flush();
}
}
58 changes: 55 additions & 3 deletions tests/php/test-uninstall.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,14 @@ public function tearDown() {
* @covers \AmpProject\AmpWP\remove_plugin_data()
*/
public function test_uninstall_php() {
global $wpdb;
wp_using_ext_object_cache( false );

// Create dummy data.
$blog_name = 'Sample Blog Name';
$blog_name = 'Sample Blog Name';
$meta_key = 'amp_meta_key';
$meta_value = 'amp_meta_value';

update_option( 'blogname', $blog_name );
update_option(
'amp-options',
Expand All @@ -50,18 +54,25 @@ public function test_uninstall_php() {

foreach ( $users as $user ) {
update_user_meta( $user, 'amp_dev_tools_enabled', 'Yes' );
update_user_meta( $user, 'amp_review_panel_dismissed_for_template_mode', 'Yes' );
update_user_meta( $user, 'additional_user_meta', 'Yes' );
}

$amp_validated_post = $this->factory()->post->create_and_get(
[
'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG,
'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG,
'meta_input' => [
$meta_key => $meta_value,
],
]
);

$page_post = $this->factory()->post->create_and_get(
[
'post_type' => 'page',
'post_type' => 'page',
'meta_input' => [
$meta_key => $meta_value,
],
]
);

Expand All @@ -71,12 +82,18 @@ public function test_uninstall_php() {
]
);

update_term_meta( $amp_error_term->term_id, $meta_key, $meta_value );
wp_add_object_terms( $amp_validated_post->ID, $amp_error_term->term_id, 'amp_validation_error' );

$post_tag_term = $this->factory()->term->create_and_get(
[
'taxonomy' => 'post_tag',
]
);

update_term_meta( $post_tag_term->term_id, $meta_key, $meta_value );
wp_add_object_terms( $page_post->ID, $post_tag_term->term_id, 'post_tag' );

$theme_mod_name = 'amp_customize_setting_modified_timestamps';
set_theme_mod( 'color', 'blue' );
set_theme_mod( $theme_mod_name, [ 'color' => time() ] );
Expand Down Expand Up @@ -127,12 +144,46 @@ public function test_uninstall_php() {

$this->flush_cache();

// Assert that AMP related data does get deleted.
$this->assertEmpty( get_option( AMP_Options_Manager::OPTION_NAME, false ) );

$this->assertEmpty( get_post( $amp_validated_post->ID ) );
$this->assertEmpty( get_post_meta( $amp_validated_post->ID, $meta_key, true ) );

$this->assertEmpty( get_term( $amp_error_term->term_id ) );
$this->assertEmpty( get_term_meta( $amp_error_term->term_id, $meta_key, true ) );

// Assert that there is no data left for `amp_validation_error` taxonomy.
$this->assertEmpty(
$wpdb->query( "SELECT * FROM {$wpdb->term_taxonomy} WHERE taxonomy = 'amp_validation_error';" )
);
$this->assertEmpty(
$wpdb->query(
$wpdb->prepare(
"SELECT * FROM {$wpdb->term_relationships} WHERE term_taxonomy_id = %d",
$amp_error_term->term_id
)
)
);

// Assert that other than AMP related data does not get deleted.
$this->assertTrue( is_a( get_post( $page_post->ID ), 'WP_Post' ) );
$this->assertEquals( $meta_value, get_post_meta( $page_post->ID, $meta_key, true ) );
$this->assertTrue( is_a( get_term( $post_tag_term->term_id ), 'WP_Term' ) );
$this->assertEquals( $meta_value, get_term_meta( $post_tag_term->term_id, $meta_key, true ) );

// Assert that there is no deleted other than `amp_validation_error` taxonomy.
$this->assertNotEmpty(
$wpdb->query( "SELECT * FROM {$wpdb->term_taxonomy} WHERE taxonomy = 'post_tag';" )
);
$this->assertNotEmpty(
$wpdb->query(
$wpdb->prepare(
"SELECT * FROM {$wpdb->term_relationships} WHERE term_taxonomy_id = %d",
$post_tag_term->term_id
)
)
);

$this->assertEquals( $blog_name, get_option( 'blogname', false ) );

Expand All @@ -150,6 +201,7 @@ public function test_uninstall_php() {

foreach ( $users as $user ) {
$this->assertEmpty( get_user_meta( $user, 'amp_dev_tools_enabled', true ) );
$this->assertEmpty( get_user_meta( $user, 'amp_review_panel_dismissed_for_template_mode', true ) );
$this->assertEquals( 'Yes', get_user_meta( $user, 'additional_user_meta', true ) );
}
}
Expand Down