From e9558f0122af5c645ba3a6dc118da7e3e100590b Mon Sep 17 00:00:00 2001 From: Matthew Denton Date: Wed, 23 Sep 2020 15:04:00 -0400 Subject: [PATCH] props @jmdodd - filter out set_object_terms actions that don't perform any update. Includes unit tests. (#17171) --- packages/sync/src/modules/class-terms.php | 18 ++++++++++++++++ .../sync/test_class.jetpack-sync-terms.php | 21 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/packages/sync/src/modules/class-terms.php b/packages/sync/src/modules/class-terms.php index 394eba0708a7a..a7ab85bd4f108 100644 --- a/packages/sync/src/modules/class-terms.php +++ b/packages/sync/src/modules/class-terms.php @@ -104,6 +104,7 @@ public function init_listeners( $callable ) { add_action( 'delete_term', $callable, 10, 4 ); add_action( 'set_object_terms', $callable, 10, 6 ); add_action( 'deleted_term_relationships', $callable, 10, 2 ); + add_filter( 'jetpack_sync_before_enqueue_set_object_terms', array( $this, 'filter_set_object_terms_no_update' ) ); add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_save_term', array( $this, 'filter_blacklisted_taxonomies' ) ); add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_add_term', array( $this, 'filter_blacklisted_taxonomies' ) ); } @@ -255,6 +256,23 @@ public function filter_blacklisted_taxonomies( $args ) { return $args; } + /** + * Filter out set_object_terms actions where the terms have not changed. + * + * @param array $args Hook args. + * @return array|boolean False if no change in terms, the original hook args otherwise. + */ + public function filter_set_object_terms_no_update( $args ) { + // There is potential for other plugins to modify args, therefore lets validate # of and types. + // $args[2] is $tt_ids, $args[5] is $old_tt_ids see wp-includes/taxonomy.php L2740. + if ( 6 === count( $args ) && is_array( $args[2] ) && is_array( $args[5] ) ) { + if ( empty( array_diff( $args[2], $args[5] ) ) && empty( array_diff( $args[5], $args[2] ) ) ) { + return false; + } + } + return $args; + } + /** * Expand the term taxonomy IDs to terms within a hook before they are serialized and sent to the server. * diff --git a/tests/php/sync/test_class.jetpack-sync-terms.php b/tests/php/sync/test_class.jetpack-sync-terms.php index dcfc26cdbcc8d..9adfefbe3403f 100644 --- a/tests/php/sync/test_class.jetpack-sync-terms.php +++ b/tests/php/sync/test_class.jetpack-sync-terms.php @@ -133,6 +133,27 @@ public function test_delete_object_term_relationships() { $this->assertEquals( $object_terms, $server_object_terms ); } + /** + * Validate filter_set_object_terms_no_update filters out set_object_terms without changes. + */ + public function test_filter_set_object_terms_no_update() { + $anther_term = wp_insert_term( 'mouse', $this->taxonomy ); + wp_set_post_terms( $this->post_id, array( $anther_term['term_id'] ), $this->taxonomy, false ); + + // Sync actions. + $this->sender->do_sync(); + // Verify set_object_terms was triggered. + $this->assertNotFalse( $this->server_event_storage->get_most_recent_event( 'set_object_terms' ) ); + // Reset event (actions) storage. + $this->server_event_storage->reset(); + + // Re-trigger and Sync actions. + wp_set_post_terms( $this->post_id, array( $anther_term['term_id'] ), $this->taxonomy, false ); + $this->sender->do_sync(); + // Verify set_object_terms was *not* triggered. + $this->assertFalse( $this->server_event_storage->get_most_recent_event( 'set_object_terms' ) ); + } + public function test_filters_out_blacklisted_taxonomies() { register_taxonomy( 'bloginfo_rss', 'post' );