Commit 67909e8f6b for woocommerce
commit 67909e8f6b6165a57cbb5bc68f24d26995568475
Author: malinajirka <malinajirka@gmail.com>
Date: Thu Jan 15 20:52:56 2026 +0100
Update variation date_modified when toggling POS visibility (#62824)
* Update variation date_modified when toggling POS visibility
When toggling POS visibility on a variable product, variations' date_modified was not being updated because only wp_set_object_terms() was called without saving the variation.
Now each variation is loaded and saved when visibility changes, ensuring date_modified is updated. Also adds an early return optimization to skip all updates when visibility state hasn't changed.
* Add changefile(s) from automation for the following project(s): woocommerce
* Update plugins/woocommerce/tests/php/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySyncTest.php
Co-authored-by: Radoslav Georgiev <rageorgiev@gmail.com>
* Update plugins/woocommerce/tests/php/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySyncTest.php
Co-authored-by: Radoslav Georgiev <rageorgiev@gmail.com>
* Fix WC_Product class reference in test mock
Use fully qualified class name (\WC_Product) to reference the global WooCommerce product class instead of looking in the test's namespace.
---------
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
Co-authored-by: Radoslav Georgiev <rageorgiev@gmail.com>
diff --git a/plugins/woocommerce/changelog/62824-wooplug-6145-addingremoving-pos-hidden-taxonomy-on-variations-doesnt b/plugins/woocommerce/changelog/62824-wooplug-6145-addingremoving-pos-hidden-taxonomy-on-variations-doesnt
new file mode 100644
index 0000000000..842c72f9b1
--- /dev/null
+++ b/plugins/woocommerce/changelog/62824-wooplug-6145-addingremoving-pos-hidden-taxonomy-on-variations-doesnt
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix variation date_modified not updating when toggling POS visibility on variable products.
\ No newline at end of file
diff --git a/plugins/woocommerce/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySync.php b/plugins/woocommerce/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySync.php
index 4781f06c9c..d88e0a85d5 100644
--- a/plugins/woocommerce/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySync.php
+++ b/plugins/woocommerce/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySync.php
@@ -49,6 +49,12 @@ class POSProductVisibilitySync {
* @return void
*/
public function set_product_pos_visibility( int $product_id, bool $visible_in_pos ): void {
+ $is_currently_visible = ! has_term( 'pos-hidden', 'pos_product_visibility', $product_id );
+
+ if ( $is_currently_visible === $visible_in_pos ) {
+ return; // No change detected.
+ }
+
if ( $visible_in_pos ) {
wp_remove_object_terms( $product_id, 'pos-hidden', 'pos_product_visibility' );
} else {
@@ -78,6 +84,12 @@ class POSProductVisibilitySync {
} else {
wp_set_object_terms( $variation_id, 'pos-hidden', 'pos_product_visibility' );
}
+
+ // Save variation to update date_modified.
+ $variation = wc_get_product( $variation_id );
+ if ( $variation ) {
+ $variation->save();
+ }
}
}
diff --git a/plugins/woocommerce/tests/php/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySyncTest.php b/plugins/woocommerce/tests/php/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySyncTest.php
index 312010775c..06b390d4e3 100644
--- a/plugins/woocommerce/tests/php/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySyncTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/ProductFeed/Integrations/POSCatalog/POSProductVisibilitySyncTest.php
@@ -155,4 +155,51 @@ class POSProductVisibilitySyncTest extends \WC_Unit_Test_Case {
// No exception should be thrown - test passes if we reach this point.
$this->assertTrue( true );
}
+
+ /**
+ * Test that variations are saved when POS visibility changes.
+ */
+ public function test_variations_saved_when_visibility_changes(): void {
+ $product = WC_Helper_Product::create_variation_product();
+ $variation_ids = $product->get_children();
+
+ // Track which variations have save() called.
+ $saved_variation_ids = array();
+ $callback = function ( $variation_id ) use ( &$saved_variation_ids ) {
+ $saved_variation_ids[] = $variation_id;
+ };
+ add_action( 'woocommerce_update_product_variation', $callback );
+
+ // Change visibility to hidden.
+ $this->sut->set_product_pos_visibility( $product->get_id(), false );
+
+ remove_action( 'woocommerce_update_product_variation', $callback );
+
+ // Verify save() was called for all variations.
+ $this->assertEquals(
+ $variation_ids,
+ $saved_variation_ids,
+ 'save() should be called for each variation'
+ );
+ }
+
+ /**
+ * Test that no updates occur when visibility state hasn't changed.
+ */
+ public function test_no_updates_when_visibility_unchanged(): void {
+ $product = WC_Helper_Product::create_variation_product();
+
+ // Set product as hidden first.
+ $this->sut->set_product_pos_visibility( $product->get_id(), false );
+
+ // Track if any variations have save() called.
+ // Make sure that `save` is never called.
+ $mock_callback = $this->createMock( \WC_Product::class );
+ $mock_callback->expects( $this->never() )->method( 'save' );
+
+ // Try to set hidden again (no change).
+ add_action( 'woocommerce_update_product_variation', array( $mock_callback, 'save' ) );
+ $this->sut->set_product_pos_visibility( $product->get_id(), false );
+ remove_action( 'woocommerce_update_product_variation', array( $mock_callback, 'save' ) );
+ }
}