Commit c629b627d0b for woocommerce

commit c629b627d0b2e46e48061aa07d6f96c2ccfdcffe
Author: Ján Mikláš <neosinner@gmail.com>
Date:   Tue Jun 23 14:50:32 2026 +0200

    Add email preview shipping details filter (#65857)

    * Add email preview shipping details filter

    * Add changelog entry for preview shipping filter

diff --git a/plugins/woocommerce/changelog/wooplug-6842-email-preview-shipping-details-filter b/plugins/woocommerce/changelog/wooplug-6842-email-preview-shipping-details-filter
new file mode 100644
index 00000000000..7774d937b1c
--- /dev/null
+++ b/plugins/woocommerce/changelog/wooplug-6842-email-preview-shipping-details-filter
@@ -0,0 +1,4 @@
+Significance: patch
+Type: enhancement
+
+Add a filter to hide shipping details in email previews.
diff --git a/plugins/woocommerce/src/Internal/Admin/EmailPreview/EmailPreview.php b/plugins/woocommerce/src/Internal/Admin/EmailPreview/EmailPreview.php
index be2461779a0..73f3f418dc8 100644
--- a/plugins/woocommerce/src/Internal/Admin/EmailPreview/EmailPreview.php
+++ b/plugins/woocommerce/src/Internal/Admin/EmailPreview/EmailPreview.php
@@ -429,28 +429,33 @@ class EmailPreview {
 		$order->set_date_created( time() );
 		$order->set_currency( 'USD' );
 		$order->set_discount_total( 10 );
-		$order->set_shipping_total( 5 );
-		$order->set_total( 80 );
 		$order->set_payment_method_title( __( 'Direct bank transfer', 'woocommerce' ) );
 		$order->set_transaction_id( '999999999' );
 		$order->set_customer_note( __( "This is a customer note. Customers can add a note to their order on checkout.\n\nIt can be multiple lines. If there's no note, this section is hidden.", 'woocommerce' ) );

 		$order = $this->apply_dummy_order_status( $order );

-		// Add shipping method.
-		$shipping_item = new WC_Order_Item_Shipping();
-		$shipping_item->set_props(
-			array(
-				'method_title' => __( 'Flat rate', 'woocommerce' ),
-				'method_id'    => 'flat_rate',
-				'total'        => '5.00',
-			)
-		);
-		$order->add_item( $shipping_item );
+		$show_shipping_details = $this->should_show_shipping_details( $order );
+		$order->set_shipping_total( $show_shipping_details ? 5 : 0 );
+		$order->set_total( $show_shipping_details ? 80 : 75 );
+
+		if ( $show_shipping_details ) {
+			$shipping_item = new WC_Order_Item_Shipping();
+			$shipping_item->set_props(
+				array(
+					'method_title' => __( 'Flat rate', 'woocommerce' ),
+					'method_id'    => 'flat_rate',
+					'total'        => '5.00',
+				)
+			);
+			$order->add_item( $shipping_item );
+		}

 		$address = $this->get_dummy_address();
 		$order->set_billing_address( $address );
-		$order->set_shipping_address( $address );
+		if ( $show_shipping_details ) {
+			$order->set_shipping_address( $address );
+		}

 		/**
 		 * A dummy WC_Order used in email preview.
@@ -621,8 +626,8 @@ class EmailPreview {
 	 */
 	public function set_up_filters() {
 		$this->switch_to_site_locale();
-		// Always show shipping address in the preview email.
-		add_filter( 'woocommerce_order_needs_shipping_address', array( $this, 'enable_shipping_address' ) );
+		// Show shipping address in preview emails unless preview shipping details are hidden.
+		add_filter( 'woocommerce_order_needs_shipping_address', array( $this, 'enable_shipping_address' ), 10, 3 );
 		// Email templates fetch product from the database to show additional information, which are not
 		// saved in WC_Order_Item_Product. This filter enables fetching that data also in email preview.
 		add_filter( 'woocommerce_order_item_product', array( $this, 'get_dummy_product_when_not_set' ), 10, 1 );
@@ -652,13 +657,34 @@ class EmailPreview {
 	}

 	/**
-	 * Enable shipping address in the preview email. Not using __return_true so
-	 * we don't accidentally remove the same filter used by other plugin or theme.
+	 * Enable shipping address in the preview email unless shipping details are hidden.
 	 *
-	 * @return true
+	 * @param bool          $needs_shipping_address Current value.
+	 * @param array         $hidden_shipping_methods Hidden shipping method IDs.
+	 * @param WC_Order|null $order Order object.
+	 * @return bool
 	 */
-	public function enable_shipping_address() {
-		return true;
+	public function enable_shipping_address( $needs_shipping_address = true, $hidden_shipping_methods = array(), $order = null ) {
+		return $this->should_show_shipping_details( $order );
+	}
+
+	/**
+	 * Check whether preview shipping details should be shown.
+	 *
+	 * @param WC_Order|null $order Preview order object.
+	 * @return bool
+	 */
+	private function should_show_shipping_details( $order = null ) {
+		/**
+		 * Filters whether shipping details should be shown in email previews.
+		 *
+		 * @since 11.0.0
+		 *
+		 * @param bool          $show_shipping_details Whether to show shipping details. Default true.
+		 * @param WC_Order|null $order Preview order object.
+		 * @param string|null   $email_type Email type being previewed.
+		 */
+		return (bool) apply_filters( 'woocommerce_email_preview_show_shipping_details', true, $order, $this->email_type );
 	}

 	/**
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/EmailPreview/EmailPreviewTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/EmailPreview/EmailPreviewTest.php
index 38e059f89bc..d09018deb36 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/EmailPreview/EmailPreviewTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/EmailPreview/EmailPreviewTest.php
@@ -183,6 +183,37 @@ class EmailPreviewTest extends WC_Unit_Test_Case {
 		remove_filter( 'woocommerce_email_preview_dummy_order', $order_filter, 10 );
 	}

+	/**
+	 * @testdox Email preview shipping details can be hidden.
+	 */
+	public function test_shipping_details_filter_can_hide_preview_shipping_details(): void {
+		$captured_order = null;
+		$captured_args  = null;
+		$hide_shipping  = function ( $show_shipping_details, $order, $email_type ) use ( &$captured_args ) {
+			$captured_args = array( $show_shipping_details, $order, $email_type );
+			return false;
+		};
+		$capture_order  = function ( $order ) use ( &$captured_order ) {
+			$captured_order = $order;
+			return $order;
+		};
+		add_filter( 'woocommerce_email_preview_show_shipping_details', $hide_shipping, 10, 3 );
+		add_filter( 'woocommerce_email_preview_dummy_order', $capture_order, 10, 1 );
+
+		$content = $this->sut->render();
+
+		remove_filter( 'woocommerce_email_preview_show_shipping_details', $hide_shipping, 10 );
+		remove_filter( 'woocommerce_email_preview_dummy_order', $capture_order, 10 );
+
+		$this->assertInstanceOf( PreviewOrder::class, $captured_order );
+		$this->assertSame( array(), $captured_order->get_shipping_methods(), 'Hidden preview shipping details should remove the dummy shipping method.' );
+		$this->assertSame( '0', $captured_order->get_shipping_total(), 'Hidden preview shipping details should remove the dummy shipping total.' );
+		$this->assertSame( '', $captured_order->get_shipping_address_1(), 'Hidden preview shipping details should remove the dummy shipping address.' );
+		$this->assertSame( array( true, $captured_order, EmailPreview::DEFAULT_EMAIL_TYPE ), $captured_args, 'Filter should receive the default visibility, preview order, and email type.' );
+		$this->assertStringNotContainsString( 'Flat rate', $content, 'Hidden preview shipping details should not render the dummy shipping method.' );
+		$this->assertStringNotContainsString( 'Shipping address', $content, 'Hidden preview shipping details should not render the shipping address section.' );
+	}
+
 	/**
 	 * Test dummy address filter - woocommerce_email_preview_dummy_address
 	 */