Commit 6d3ca5fde30 for woocommerce
commit 6d3ca5fde30c2bf0ffc6ae33acd0978b49b27e1c
Author: SH Sajal Chowdhury <72102985+shsajalchowdhury@users.noreply.github.com>
Date: Tue Jul 7 04:57:16 2026 +0600
Fix: Skip brands product column when taxonomy is deregistered (#64612)
* Fix: Skip brands product column when taxonomy is deregistered
Avoid accessing the product_brand column when the taxonomy has been
deregistered by a third-party plugin. This prevents PHP notices on the
products list table and leaves the admin UI unchanged when brands are
not registered.
Closes #64065
* Add tests for product_columns() and hide product_tag column when taxonomy deregistered
- Add 3 PHPUnit tests for WC_Brands_Admin::product_columns(): normal
reordering, taxonomy-not-registered guard, and column-not-present guard
- Hide custom product_tag column when the taxonomy is deregistered
(addresses reviewer feedback on PR #64612)
* Add changefile(s) from automation for the following project(s): woocommerce
* Address review feedback: use is_object_in_taxonomy, fix test assertions
- Change taxonomy_exists() to is_object_in_taxonomy() for product_tag
guard, since unregister_taxonomy_for_object_type() removes the
post-type association, not the taxonomy itself
- Simplify brand guard to isset()-only (taxonomy_exists was redundant
since WP only adds the column when taxonomy is registered)
- Fix test_product_columns_reorders_brand_column: correct assertions
to match actual array_slice reorder position (third-to-last)
- Remove broken test_product_columns_returns_unchanged_when_taxonomy_not_registered
(never actually unregistered the taxonomy)
- Add tearDown() to restore taxonomy state between tests
- Add more columns to reorder test fixture for realistic assertion
* Fix test fixture: move brand column earlier so reorder is not a no-op
The previous fixture placed taxonomy-product_brand in the third-to-last
position, which is where the reorder moves it, making the test a no-op
and causing assertNotEquals to fail. Move it earlier in the input
(after name) so the reorder actually changes the column position.
* Fix product_columns reorder test assertion and array alignment
The reorder test used assertNotEquals to confirm the columns changed,
but assertEquals/assertNotEquals compare associative arrays
order-insensitively. product_columns() only reorders (same keys and
values), so the two arrays are loosely equal and assertNotEquals
always failed. Switch to assertNotSame, which is order-sensitive, so
the reorder is detected correctly.
Also correct the array double-arrow alignment in the test fixture to
satisfy phpcs (WordPress.Arrays.MultipleStatementAlignment).
* Realign featured/date column assignments after product_tag guard
Wrapping the product_tag column in an is_object_in_taxonomy() guard
removed it from the equals-sign alignment group, leaving the adjacent
featured and date assignments over-padded. Reduce their alignment to
match phpcs (Generic.Formatting.MultipleStatementAlignment).
* fix: add trailing newline to changelog fragment
* Add changefile(s) from automation for the following project(s): woocommerce
---------
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
Co-authored-by: Brandon Kraft <public@brandonkraft.com>
diff --git a/docs/block-development/reference/block-references.md b/docs/block-development/reference/block-references.md
index 297144044fd..aae0ac5f878 100644
--- a/docs/block-development/reference/block-references.md
+++ b/docs/block-development/reference/block-references.md
@@ -1235,7 +1235,7 @@ Display a product's description, attributes, and reviews
## Product Filters - woocommerce/product-filters
-Let shoppers filter products displayed on the page.
+Add a set of filters shoppers can use.
- **Name:** woocommerce/product-filters
- **Category:** woocommerce
@@ -1244,7 +1244,7 @@ Let shoppers filter products displayed on the page.
## Active Filters - woocommerce/product-filter-active
-Display the currently active filters.
+Display all active filters.
- **Name:** woocommerce/product-filter-active
- **Category:** woocommerce
@@ -1253,7 +1253,7 @@ Display the currently active filters.
## Attribute Filter - woocommerce/product-filter-attribute
-Enable customers to filter the product grid by selecting one or more attributes, such as color.
+Let shoppers filter products by attribute.
- **Name:** woocommerce/product-filter-attribute
- **Category:** woocommerce
@@ -1263,7 +1263,7 @@ Enable customers to filter the product grid by selecting one or more attributes,
## List - woocommerce/product-filter-checkbox-list
-Display a list of filter options.
+Display filter options as a list.
- **Name:** woocommerce/product-filter-checkbox-list
- **Category:** woocommerce
@@ -1283,7 +1283,7 @@ Display filter options as chips.
## Clear filters - woocommerce/product-filter-clear-button
-Allows shoppers to clear active filters.
+Let shoppers clear any active filters.
- **Name:** woocommerce/product-filter-clear-button
- **Category:** woocommerce
@@ -1292,7 +1292,7 @@ Allows shoppers to clear active filters.
## Price Filter - woocommerce/product-filter-price
-Let shoppers filter products by choosing a price range.
+Let shoppers filter products by price.
- **Name:** woocommerce/product-filter-price
- **Category:** woocommerce
@@ -1301,7 +1301,7 @@ Let shoppers filter products by choosing a price range.
## Price Slider - woocommerce/product-filter-price-slider
-A slider helps shopper choose a price range.
+Let shoppers choose a price range with a slider.
- **Name:** woocommerce/product-filter-price-slider
- **Category:** woocommerce
@@ -1311,7 +1311,7 @@ A slider helps shopper choose a price range.
## Rating Filter - woocommerce/product-filter-rating
-Enable customers to filter the product collection by rating.
+Let shoppers filter products by rating.
- **Name:** woocommerce/product-filter-rating
- **Category:** woocommerce
@@ -1321,7 +1321,7 @@ Enable customers to filter the product collection by rating.
## Chips - woocommerce/product-filter-removable-chips
-Display removable active filters as chips.
+Display active filters as removable chips.
- **Name:** woocommerce/product-filter-removable-chips
- **Category:** woocommerce
@@ -1329,7 +1329,7 @@ Display removable active filters as chips.
- **Supports:** interactivity, layout (default, ~~allowInheriting~~, ~~allowSwitching~~, ~~allowVerticalAlignment~~)
- **Attributes:** chipBackground, chipBorder, chipText, customChipBackground, customChipBorder, customChipText
-## Availability filter - woocommerce/product-filter-status
+## Availability Filter - woocommerce/product-filter-status
Let shoppers filter products by availability.
@@ -1341,7 +1341,7 @@ Let shoppers filter products by availability.
## Taxonomy Filter - woocommerce/product-filter-taxonomy
-Enable customers to filter the product collection by selecting one or more taxonomy terms, such as categories, brands, or tags.
+Let shoppers filter products by category, brand, or tag.
- **Name:** woocommerce/product-filter-taxonomy
- **Category:** woocommerce
diff --git a/plugins/woocommerce/changelog/64612-fix-64065-brands-admin-deregistered b/plugins/woocommerce/changelog/64612-fix-64065-brands-admin-deregistered
new file mode 100644
index 00000000000..9a3f8f395fd
--- /dev/null
+++ b/plugins/woocommerce/changelog/64612-fix-64065-brands-admin-deregistered
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Skip the brands product column when the product_brand taxonomy is deregistered
\ No newline at end of file
diff --git a/plugins/woocommerce/includes/admin/class-wc-admin-brands.php b/plugins/woocommerce/includes/admin/class-wc-admin-brands.php
index 53c0a6fe200..411f980d69e 100644
--- a/plugins/woocommerce/includes/admin/class-wc-admin-brands.php
+++ b/plugins/woocommerce/includes/admin/class-wc-admin-brands.php
@@ -523,7 +523,12 @@ class WC_Brands_Admin {
return $columns;
}
- $column_index = 'taxonomy-product_brand';
+ $column_index = 'taxonomy-product_brand';
+
+ if ( ! isset( $columns[ $column_index ] ) ) {
+ return $columns;
+ }
+
$brands_column = $columns[ $column_index ];
unset( $columns[ $column_index ] );
return array_merge(
diff --git a/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php b/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php
index 1cce6802fad..6591e4c2463 100644
--- a/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php
+++ b/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php
@@ -209,9 +209,11 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
$show_columns['cogs_value'] = __( 'Cost', 'woocommerce' );
}
$show_columns['product_cat'] = __( 'Categories', 'woocommerce' );
- $show_columns['product_tag'] = __( 'Tags', 'woocommerce' );
- $show_columns['featured'] = '<span class="wc-featured parent-tips" data-tip="' . esc_attr__( 'Featured', 'woocommerce' ) . '">' . __( 'Featured', 'woocommerce' ) . '</span>';
- $show_columns['date'] = __( 'Date', 'woocommerce' );
+ if ( is_object_in_taxonomy( 'product', 'product_tag' ) ) {
+ $show_columns['product_tag'] = __( 'Tags', 'woocommerce' );
+ }
+ $show_columns['featured'] = '<span class="wc-featured parent-tips" data-tip="' . esc_attr__( 'Featured', 'woocommerce' ) . '">' . __( 'Featured', 'woocommerce' ) . '</span>';
+ $show_columns['date'] = __( 'Date', 'woocommerce' );
return array_merge( $show_columns, $columns );
}
diff --git a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-brands-test.php b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-brands-test.php
index 60691f69c7a..7b437a0e9b4 100644
--- a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-brands-test.php
+++ b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-brands-test.php
@@ -15,6 +15,92 @@ require_once WC_ABSPATH . '/includes/class-wc-brands.php';
*/
class WC_Admin_Brands_Test extends WC_Unit_Test_Case {
+ /**
+ * Keep track of whether we manually unregistered the taxonomy
+ * so we can restore it in tearDown.
+ *
+ * @var bool
+ */
+ private static $unregistered_brand_taxonomy = false;
+
+ /**
+ * Restore the product_brand taxonomy after tests that unregister it.
+ *
+ * @return void
+ */
+ public function tearDown(): void {
+ if ( self::$unregistered_brand_taxonomy ) {
+ WC_Brands::init_taxonomy();
+ self::$unregistered_brand_taxonomy = false;
+ }
+ parent::tearDown();
+ }
+
+ /**
+ * Tests that product_columns() moves the taxonomy-product_brand column
+ * to the third-to-last position (before the last two columns) when
+ * the taxonomy is registered.
+ *
+ * The reorder logic uses array_slice( $columns, 0, -2 ) for the
+ * "before" portion and array_slice( $columns, -2 ) for the last two
+ * columns, inserting the brand column between them.
+ *
+ * @return void
+ */
+ public function test_product_columns_reorders_brand_column() {
+ WC_Brands::init_taxonomy();
+
+ // Brand column starts after "name" so the reorder actually moves it.
+ $columns = array(
+ 'cb' => '<input type="checkbox" />',
+ 'name' => __( 'Name', 'woocommerce' ),
+ 'taxonomy-product_brand' => __( 'Brands', 'woocommerce' ),
+ 'sku' => __( 'SKU', 'woocommerce' ),
+ 'product_cat' => __( 'Categories', 'woocommerce' ),
+ 'featured' => __( 'Featured', 'woocommerce' ),
+ 'date' => __( 'Date', 'woocommerce' ),
+ );
+
+ $brands_admin = new WC_Brands_Admin();
+ $result = $brands_admin->product_columns( $columns );
+ $result_keys = array_keys( $result );
+
+ /*
+ * After reorder: cb, name, sku, product_cat, taxonomy-product_brand, featured, date.
+ * Brand column is inserted before the last 2 columns (featured, date).
+ * Use assertNotSame because the reorder only changes column order, and
+ * assertEquals/assertNotEquals compare arrays order-insensitively.
+ */
+ $this->assertNotSame( $columns, $result, 'Columns should have been reordered.' );
+
+ // The brand column should be at the third-to-last position.
+ $last_index = count( $result_keys ) - 1;
+ $this->assertEquals( 'date', $result_keys[ $last_index ], 'Last column should be date.' );
+ $this->assertEquals( 'featured', $result_keys[ $last_index - 1 ], 'Second-to-last column should be featured.' );
+ $this->assertEquals( 'taxonomy-product_brand', $result_keys[ $last_index - 2 ], 'Brand column should be third-to-last.' );
+ }
+
+ /**
+ * Tests that product_columns() returns columns unchanged when
+ * the product_brand column is not present in the columns array.
+ *
+ * @return void
+ */
+ public function test_product_columns_returns_unchanged_when_column_not_present() {
+ WC_Brands::init_taxonomy();
+
+ $columns = array(
+ 'cb' => '<input type="checkbox" />',
+ 'name' => __( 'Name', 'woocommerce' ),
+ 'date' => __( 'Date', 'woocommerce' ),
+ );
+
+ $brands_admin = new WC_Brands_Admin();
+ $result = $brands_admin->product_columns( $columns );
+
+ // Without the brand column present, columns should remain untouched.
+ $this->assertEquals( $columns, $result );
+ }
/**
* Tests brands filter outputs as a standard dropdown.