Commit b488e58568f for woocommerce

commit b488e58568f7b69698810810726e79555be05408
Author: Soroush Ahmadi <mrsoroushahmadi@gmail.com>
Date:   Tue Sep 8 13:39:12 2026 +0330

    Fix fatal generating receipt when variation parent product was deleted (#68369)

diff --git a/plugins/woocommerce/changelog/68368-fix-receipt-deleted-variation-parent b/plugins/woocommerce/changelog/68368-fix-receipt-deleted-variation-parent
new file mode 100644
index 00000000000..884683c786e
--- /dev/null
+++ b/plugins/woocommerce/changelog/68368-fix-receipt-deleted-variation-parent
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix a fatal error generating receipts for orders with a deleted variation parent.
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 5bbc4147b56..c2d819931d3 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -62976,12 +62976,6 @@ parameters:
 			count: 1
 			path: src/Internal/ReceiptRendering/ReceiptRenderingEngine.php

-		-
-			message: '#^Cannot call method get_name\(\) on WC_Product\|false\|null\.$#'
-			identifier: method.nonObject
-			count: 1
-			path: src/Internal/ReceiptRendering/ReceiptRenderingEngine.php
-
 		-
 			message: '#^Constant Automattic\\WooCommerce\\Internal\\ReceiptRendering\\ReceiptRenderingEngine\:\:KNOWN_CARD_TYPES is unused\.$#'
 			identifier: classConstant.unused
diff --git a/plugins/woocommerce/src/Internal/ReceiptRendering/ReceiptRenderingEngine.php b/plugins/woocommerce/src/Internal/ReceiptRendering/ReceiptRenderingEngine.php
index 0ba28601a94..2b19cdb4c35 100644
--- a/plugins/woocommerce/src/Internal/ReceiptRendering/ReceiptRenderingEngine.php
+++ b/plugins/woocommerce/src/Internal/ReceiptRendering/ReceiptRenderingEngine.php
@@ -301,11 +301,13 @@ class ReceiptRenderingEngine {
 			$line_item_product = $line_item->get_product();
 			if ( false === $line_item_product ) {
 				$line_item_title = $line_item->get_name();
+			} elseif ( $line_item_product instanceof \WC_Product_Variation ) {
+				$parent_product  = wc_get_product( $line_item_product->get_parent_id() );
+				$line_item_title = $parent_product instanceof \WC_Product
+					? $parent_product->get_name() . '. ' . $line_item_product->get_attribute_summary()
+					: $line_item->get_name();
 			} else {
-				$line_item_title =
-					( $line_item_product instanceof \WC_Product_Variation ) ?
-						( wc_get_product( $line_item_product->get_parent_id() )->get_name() ) . '. ' . $line_item_product->get_attribute_summary() :
-						$line_item_product->get_name();
+				$line_item_title = $line_item_product->get_name();
 			}
 			$line_items_info[] = array(
 				'type'     => 'product',
diff --git a/plugins/woocommerce/tests/php/src/Internal/ReceiptRendering/ReceiptRenderingEngineTest.php b/plugins/woocommerce/tests/php/src/Internal/ReceiptRendering/ReceiptRenderingEngineTest.php
index ce76146f156..0bcc0336ba7 100644
--- a/plugins/woocommerce/tests/php/src/Internal/ReceiptRendering/ReceiptRenderingEngineTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/ReceiptRendering/ReceiptRenderingEngineTest.php
@@ -319,4 +319,29 @@ class ReceiptRenderingEngineTest extends \WC_Unit_Test_Case {

 		$this->assertStringNotContainsString( 'payment_method_section_title', $rendered );
 	}
+
+	/**
+	 * @testdox 'generate_receipt' falls back to the line item name when the variation parent lookup dangles.
+	 */
+	public function test_generate_receipt_falls_back_to_item_name_when_variation_parent_is_deleted() {
+		global $wpdb;
+		// Arrange - orphan the variation at the row level: deleting through the API cascades to the children, so it cannot produce this state.
+		$parent    = \WC_Helper_Product::create_variation_product();
+		$variation = wc_get_product( current( $parent->get_children() ) );
+
+		$order = OrderHelper::create_order( 1, $variation );
+
+		$wpdb->delete( $wpdb->posts, array( 'ID' => $parent->get_id() ) );
+		clean_post_cache( $parent->get_id() );
+		$this->assertFalse( wc_get_product( $parent->get_id() ) );
+		$items = $order->get_items();
+		$this->assertInstanceOf( \WC_Product_Variation::class, current( $items )->get_product() );
+
+		// Act - rendering must not fatal on the dangling parent lookup.
+		$rendered = $this->render_receipt( $order );
+
+		// Assert - the line item name is used as the title fallback.
+		$item = current( $items );
+		$this->assertStringContainsString( $item->get_name(), $rendered );
+	}
 }