diff --git a/plugins/woocommerce-admin/changelogs/fix-7680_category_lookup_class b/plugins/woocommerce-admin/changelogs/fix-7680_category_lookup_class new file mode 100644 index 00000000000..42cf8a3b2bc --- /dev/null +++ b/plugins/woocommerce-admin/changelogs/fix-7680_category_lookup_class @@ -0,0 +1,4 @@ +Significance: patch +Type: Fix + +Fix category lookup logic to update children correctly. #7709 diff --git a/plugins/woocommerce-admin/src/CategoryLookup.php b/plugins/woocommerce-admin/src/CategoryLookup.php index d3d9125160c..770475fcde1 100644 --- a/plugins/woocommerce-admin/src/CategoryLookup.php +++ b/plugins/woocommerce-admin/src/CategoryLookup.php @@ -179,16 +179,17 @@ class CategoryLookup { protected function update( $category_id ) { global $wpdb; - $ancestors = get_ancestors( $category_id, 'product_cat', 'taxonomy' ); - $children = get_term_children( $category_id, 'product_cat' ); - $inserts = array(); - $inserts[] = $this->get_insert_sql( $category_id, $category_id ); + $ancestors = get_ancestors( $category_id, 'product_cat', 'taxonomy' ); + $children = get_term_children( $category_id, 'product_cat' ); + $inserts = array(); + $inserts[] = $this->get_insert_sql( $category_id, $category_id ); + $children_ids = array_map( 'intval', array_unique( array_filter( $children ) ) ); foreach ( $ancestors as $ancestor ) { $inserts[] = $this->get_insert_sql( $category_id, $ancestor ); - foreach ( $children as $child ) { - $inserts[] = $this->get_insert_sql( $child->category_id, $ancestor ); + foreach ( $children_ids as $child_category_id ) { + $inserts[] = $this->get_insert_sql( $child_category_id, $ancestor ); } } diff --git a/plugins/woocommerce-admin/tests/category-lookup.php b/plugins/woocommerce-admin/tests/category-lookup.php new file mode 100644 index 00000000000..1c6cdd97856 --- /dev/null +++ b/plugins/woocommerce-admin/tests/category-lookup.php @@ -0,0 +1,139 @@ + $parent['term_id'], + ) + ); + $this->parent_term_id = $parent['term_id']; + $this->parent2_term_id = $parent2['term_id']; + $this->child_term_id = $child['term_id']; + CategoryLookup::instance()->init(); + } + + /** + * Tear Down + */ + public function tearDown() { + parent::tearDown(); + wp_delete_term( $this->parent_term_id, 'product_cat' ); + wp_delete_term( $this->parent2_term_id, 'product_cat' ); + wp_delete_term( $this->child_term_id, 'product_cat' ); + } + + /** + * @param int $category_id category id. + * @return int[] list of category tree ids + */ + public function get_category_parent_id( $category_id ) { + global $wpdb; + + return wp_parse_id_list( + $wpdb->get_col( + $wpdb->prepare( + "SELECT category_tree_id FROM $wpdb->wc_category_lookup WHERE category_id = %d", + $category_id + ) + ) + ); + } + + /** + * Test on_create callback for when product category is created. + */ + public function test_create_product_category_update_lookup_table() { + $parent_ids = $this->get_category_parent_id( $this->parent_term_id ); + $this->assertCount( 1, $parent_ids ); + $this->assertContains( $this->parent_term_id, $parent_ids ); + $parent2_ids = $this->get_category_parent_id( $this->parent2_term_id ); + $this->assertCount( 1, $parent2_ids ); + $this->assertContains( $this->parent2_term_id, $parent2_ids ); + $child_ids = $this->get_category_parent_id( $this->child_term_id ); + $this->assertCount( 2, $child_ids ); + $this->assertContains( $this->parent_term_id, $child_ids ); + } + + /** + * Test update callback for product category update. + */ + public function test_product_category_edit_should_update_table() { + wp_update_term( + $this->child_term_id, + 'product_cat', + array( + 'slug' => 'test', + ) + ); + $child_parent_ids = $this->get_category_parent_id( $this->child_term_id ); + $this->assertCount( 2, $child_parent_ids ); + $this->assertContains( $this->parent_term_id, $child_parent_ids ); + } + + /** + * Test update of product category with children. + */ + public function test_product_category_update_with_children() { + wp_update_term( + $this->parent_term_id, + 'product_cat', + array( + 'parent' => $this->parent2_term_id, + ) + ); + $parent_parent_ids = $this->get_category_parent_id( $this->parent_term_id ); + + $this->assertCount( 2, $parent_parent_ids ); + $this->assertContains( $this->parent2_term_id, $parent_parent_ids ); + } + + /** + * Test deleting old lookup data upon product category update. + */ + public function test_product_category_update_should_delete_old_lookups() { + $parent_parent_ids = $this->get_category_parent_id( $this->parent_term_id ); + $this->assertCount( 1, $parent_parent_ids ); + $this->assertNotContains( $this->parent2_term_id, $parent_parent_ids ); + + wp_update_term( + $this->parent_term_id, + 'product_cat', + array( + 'parent' => $this->parent2_term_id, + ) + ); + $parent_parent_ids = $this->get_category_parent_id( $this->parent_term_id ); + + $this->assertCount( 2, $parent_parent_ids ); + $this->assertContains( $this->parent2_term_id, $parent_parent_ids ); + } +}