Commit 4e135705da for woocommerce
commit 4e135705da3e2802be67eb918fca0d27671dc5a4
Author: Jaclyn Chen <watertranquil@gmail.com>
Date: Fri May 23 14:53:30 2025 +0800
[Woo POS] Display POS store name in email header HTML (#58124)
* Extract blog name usage from `email-header` template to a variable default to blog name and set to POS store name in POS completed order email.
* Apply the same changes to POS refunded email to display POS store name in the email header.
* Add changelog.
* WC_Email_Header_Template_Test: explicitly set `email_heading` variable for the template in test cases to fix unit test errors.
* Replace `woocommerce_email_header` shared template usage with custom action for POS emails.
* Remove comment on a removed parameter.
diff --git a/plugins/woocommerce/changelog/display-pos-store-name-in-email-header-html b/plugins/woocommerce/changelog/display-pos-store-name-in-email-header-html
new file mode 100644
index 0000000000..d1b378cb3b
--- /dev/null
+++ b/plugins/woocommerce/changelog/display-pos-store-name-in-email-header-html
@@ -0,0 +1,4 @@
+Significance: minor
+Type: add
+
+Display Point of Sale (POS) store name in the header HTML for POS emails by extracting blog name usage in the email header template to a variable.
diff --git a/plugins/woocommerce/includes/class-wc-emails.php b/plugins/woocommerce/includes/class-wc-emails.php
index 122c5c3d94..b090930be7 100644
--- a/plugins/woocommerce/includes/class-wc-emails.php
+++ b/plugins/woocommerce/includes/class-wc-emails.php
@@ -327,7 +327,13 @@ class WC_Emails {
* @param mixed $email_heading Heading for the email.
*/
public function email_header( $email_heading ) {
- wc_get_template( 'emails/email-header.php', array( 'email_heading' => $email_heading ) );
+ wc_get_template(
+ 'emails/email-header.php',
+ array(
+ 'email_heading' => $email_heading,
+ 'store_name' => get_bloginfo( 'name', 'display' ),
+ )
+ );
}
/**
diff --git a/plugins/woocommerce/includes/emails/class-wc-email-customer-pos-completed-order.php b/plugins/woocommerce/includes/emails/class-wc-email-customer-pos-completed-order.php
index b30eb577ab..a47a2e3f31 100644
--- a/plugins/woocommerce/includes/emails/class-wc-email-customer-pos-completed-order.php
+++ b/plugins/woocommerce/includes/emails/class-wc-email-customer-pos-completed-order.php
@@ -115,6 +115,7 @@ if ( ! class_exists( 'WC_Email_Customer_POS_Completed_Order', false ) ) :
*/
public function get_content_html() {
$this->add_pos_customizations();
+ add_action( 'woocommerce_pos_email_header', array( $this, 'email_header' ) );
$content = wc_get_template_html(
$this->template_html,
array(
@@ -132,6 +133,7 @@ if ( ! class_exists( 'WC_Email_Customer_POS_Completed_Order', false ) ) :
)
);
$this->remove_pos_customizations();
+ remove_action( 'woocommerce_pos_email_header', array( $this, 'email_header' ) );
return $content;
}
@@ -256,6 +258,23 @@ if ( ! class_exists( 'WC_Email_Customer_POS_Completed_Order', false ) ) :
remove_filter( 'woocommerce_get_order_item_totals', array( $this, 'order_item_totals' ), 10 );
}
+ /**
+ * Get the email header.
+ *
+ * @param mixed $email_heading Heading for the email.
+ *
+ * @internal For exclusive usage within this class, backwards compatibility not guaranteed.
+ */
+ public function email_header( $email_heading ) {
+ wc_get_template(
+ 'emails/email-header.php',
+ array(
+ 'email_heading' => $email_heading,
+ 'store_name' => $this->get_pos_store_name(),
+ )
+ );
+ }
+
/**
* Add unit price to order item meta start position.
*
diff --git a/plugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.php b/plugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.php
index d6b7153e0f..e8f26d8b80 100644
--- a/plugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.php
+++ b/plugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.php
@@ -225,6 +225,7 @@ if ( ! class_exists( 'WC_Email_Customer_POS_Refunded_Order', false ) ) :
*/
public function get_content_html() {
$this->add_pos_customizations();
+ add_action( 'woocommerce_pos_email_header', array( $this, 'email_header' ) );
$content = wc_get_template_html(
$this->template_html,
array(
@@ -245,6 +246,7 @@ if ( ! class_exists( 'WC_Email_Customer_POS_Refunded_Order', false ) ) :
)
);
$this->remove_pos_customizations();
+ remove_action( 'woocommerce_pos_email_header', array( $this, 'email_header' ) );
return $content;
}
@@ -387,6 +389,23 @@ if ( ! class_exists( 'WC_Email_Customer_POS_Refunded_Order', false ) ) :
remove_filter( 'woocommerce_get_order_item_totals', array( $this, 'order_item_totals' ), 10 );
}
+ /**
+ * Get the email header.
+ *
+ * @param mixed $email_heading Heading for the email.
+ *
+ * @internal For exclusive usage within this class, backwards compatibility not guaranteed.
+ */
+ public function email_header( $email_heading ) {
+ wc_get_template(
+ 'emails/email-header.php',
+ array(
+ 'email_heading' => $email_heading,
+ 'store_name' => $this->get_pos_store_name(),
+ )
+ );
+ }
+
/**
* Add unit price to order item meta start position.
*
diff --git a/plugins/woocommerce/templates/emails/customer-pos-completed-order.php b/plugins/woocommerce/templates/emails/customer-pos-completed-order.php
index ba3f417d6c..ad4a3e8fd7 100644
--- a/plugins/woocommerce/templates/emails/customer-pos-completed-order.php
+++ b/plugins/woocommerce/templates/emails/customer-pos-completed-order.php
@@ -26,10 +26,10 @@ $email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improveme
/**
* Hook for the woocommerce_email_header.
*
- * @hooked WC_Emails::email_header() Output the email header
- * @since 3.7.0
+ * @hooked WC_Email_Customer_POS_*::email_header() Output the email header
+ * @since 10.0.0
*/
-do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
+do_action( 'woocommerce_pos_email_header', $email_heading, $email ); ?>
<div class="email-introduction">
<p>
diff --git a/plugins/woocommerce/templates/emails/customer-pos-refunded-order.php b/plugins/woocommerce/templates/emails/customer-pos-refunded-order.php
index 4dc4e25090..b7d914c090 100644
--- a/plugins/woocommerce/templates/emails/customer-pos-refunded-order.php
+++ b/plugins/woocommerce/templates/emails/customer-pos-refunded-order.php
@@ -24,10 +24,10 @@ $email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improveme
/**
* Hook for the woocommerce_email_header.
*
- * @hooked WC_Emails::email_header() Output the email header
- * @since 3.7.0
+ * @hooked WC_Email_Customer_POS_*::email_header() Output the email header
+ * @since 10.0.0
*/
-do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
+do_action( 'woocommerce_pos_email_header', $email_heading, $email ); ?>
<div class="email-introduction">
<p>
diff --git a/plugins/woocommerce/templates/emails/email-header.php b/plugins/woocommerce/templates/emails/email-header.php
index 62a386cf78..5cf59a53ac 100644
--- a/plugins/woocommerce/templates/emails/email-header.php
+++ b/plugins/woocommerce/templates/emails/email-header.php
@@ -12,16 +12,17 @@
*
* @see https://woocommerce.com/document/template-structure/
* @package WooCommerce\Templates\Emails
- * @version 9.8.0
+ * @version 10.0.0
*/
use Automattic\WooCommerce\Utilities\FeaturesUtil;
if ( ! defined( 'ABSPATH' ) ) {
- exit; // Exit if accessed directly
+ exit; // Exit if accessed directly.
}
$email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improvements' );
+$store_name = $store_name ?? get_bloginfo( 'name', 'display' );
?>
<!DOCTYPE html>
@@ -29,7 +30,7 @@ $email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improveme
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php bloginfo( 'charset' ); ?>" />
<meta content="width=device-width, initial-scale=1.0" name="viewport">
- <title><?php echo get_bloginfo( 'name', 'display' ); ?></title>
+ <title><?php echo esc_html( $store_name ); ?></title>
</head>
<body <?php echo is_rtl() ? 'rightmargin' : 'leftmargin'; ?>="0" marginwidth="0" topmargin="0" marginheight="0" offset="0">
<table width="100%" id="outer_wrapper">
@@ -59,9 +60,9 @@ $email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improveme
<td id="template_header_image">
<?php
if ( $img ) {
- echo '<p style="margin-top:0;"><img src="' . esc_url( $img ) . '" alt="' . esc_attr( get_bloginfo( 'name', 'display' ) ) . '" /></p>';
+ echo '<p style="margin-top:0;"><img src="' . esc_url( $img ) . '" alt="' . esc_attr( $store_name ) . '" /></p>';
} else {
- echo '<p class="email-logo-text">' . esc_html( get_bloginfo( 'name', 'display' ) ) . '</p>';
+ echo '<p class="email-logo-text">' . esc_html( $store_name ) . '</p>';
}
?>
</td>
@@ -71,7 +72,7 @@ $email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improveme
<div id="template_header_image">
<?php
if ( $img ) {
- echo '<p style="margin-top:0;"><img src="' . esc_url( $img ) . '" alt="' . esc_attr( get_bloginfo( 'name', 'display' ) ) . '" /></p>';
+ echo '<p style="margin-top:0;"><img src="' . esc_url( $img ) . '" alt="' . esc_attr( $store_name ) . '" /></p>';
}
?>
</div>
diff --git a/plugins/woocommerce/tests/php/includes/emails/class-wc-email-customer-pos-completed-order-test.php b/plugins/woocommerce/tests/php/includes/emails/class-wc-email-customer-pos-completed-order-test.php
index 5626576ca3..08d5b2026b 100644
--- a/plugins/woocommerce/tests/php/includes/emails/class-wc-email-customer-pos-completed-order-test.php
+++ b/plugins/woocommerce/tests/php/includes/emails/class-wc-email-customer-pos-completed-order-test.php
@@ -194,6 +194,57 @@ class WC_Email_Customer_POS_Completed_Order_Test extends \WC_Unit_Test_Case {
$this->assertStringNotContainsString( __( 'Time of payment:', 'woocommerce' ), $regular_plain_text );
}
+ /**
+ * @testdox POS email includes POS store name in email header HTML while regular email includes blog name.
+ */
+ public function test_pos_email_includes_pos_store_name_in_email_header_html_while_regular_email_includes_blog_name() {
+ // Initialize WC_Emails to set up actions and filters for email header in regular emails.
+ $emails = new WC_Emails();
+
+ // Given POS store name and blog name.
+ update_option( 'woocommerce_pos_store_name', 'Physical Store' );
+ update_option( 'blogname', 'Online Store' );
+
+ // When getting content from both email classes.
+ $pos_email = new WC_Email_Customer_POS_Completed_Order();
+ $regular_email = new WC_Email_Customer_Completed_Order();
+
+ // Set the order on both email classes.
+ $pos_email->object = OrderHelper::create_order();
+ $regular_email->object = OrderHelper::create_order();
+
+ $pos_content = $pos_email->get_content_html();
+ $regular_content = $regular_email->get_content_html();
+
+ // Then POS email should include POS store name.
+ $this->assertStringContainsString( '<title>Physical Store</title>', $pos_content );
+ $this->assertStringNotContainsString( '<title>Online Store</title>', $pos_content );
+
+ // And regular email should include blog name.
+ $this->assertStringNotContainsString( '<title>Physical Store</title>', $regular_content );
+ $this->assertStringContainsString( '<title>Online Store</title>', $regular_content );
+ }
+
+ /**
+ * @testdox POS email includes blog name in email header HTML when POS store name is not set.
+ */
+ public function test_pos_email_header_html_includes_blog_name_when_pos_store_name_is_not_set() {
+ // Given POS store name is not set.
+ delete_option( 'woocommerce_pos_store_name' );
+ update_option( 'blogname', 'Online Store' );
+
+ // When getting content from POS email.
+ $email = new WC_Email_Customer_POS_Completed_Order();
+
+ // Set the order on the email.
+ $email->object = OrderHelper::create_order();
+
+ $content = $email->get_content_html();
+
+ // Then POS email should include blog name.
+ $this->assertStringContainsString( '<title>Online Store</title>', $content );
+ }
+
/**
* @testdox get_default_subject includes blog name when POS store name is not set.
*/
diff --git a/plugins/woocommerce/tests/php/includes/emails/class-wc-email-customer-pos-refunded-order-test.php b/plugins/woocommerce/tests/php/includes/emails/class-wc-email-customer-pos-refunded-order-test.php
index 016f14c6de..1b4166f984 100644
--- a/plugins/woocommerce/tests/php/includes/emails/class-wc-email-customer-pos-refunded-order-test.php
+++ b/plugins/woocommerce/tests/php/includes/emails/class-wc-email-customer-pos-refunded-order-test.php
@@ -170,6 +170,59 @@ class WC_Email_Customer_POS_Refunded_Order_Test extends \WC_Unit_Test_Case {
$this->assertStringNotContainsString( __( 'Time of payment:', 'woocommerce' ), $regular_plain_text );
}
+ /**
+ * @testdox POS email includes POS store name in email header HTML while regular email includes blog name.
+ */
+ public function test_pos_email_includes_pos_store_name_in_email_header_html_while_regular_email_includes_blog_name() {
+ // Initialize WC_Emails to set up actions and filters for email header in regular emails.
+ $emails = new WC_Emails();
+
+ // Given POS store name and blog name.
+ update_option( 'woocommerce_pos_store_name', 'Physical Store' );
+ update_option( 'blogname', 'Online Store' );
+
+ // When getting content from both email classes.
+ $pos_email = new WC_Email_Customer_POS_Refunded_Order();
+ $regular_email = new WC_Email_Customer_Refunded_Order();
+
+ // Set the order on both email classes.
+ $pos_email->object = OrderHelper::create_order();
+ $regular_email->object = OrderHelper::create_order();
+
+ $pos_content = $pos_email->get_content_html();
+ $regular_content = $regular_email->get_content_html();
+
+ // Then POS email should include POS store name.
+ $this->assertStringContainsString( '<title>Physical Store</title>', $pos_content );
+ $this->assertStringNotContainsString( '<title>Online Store</title>', $pos_content );
+
+ // And regular email should include blog name.
+ $this->assertStringNotContainsString( '<title>Physical Store</title>', $regular_content );
+ $this->assertStringContainsString( '<title>Online Store</title>', $regular_content );
+ }
+
+ /**
+ * @testdox POS email includes blog name in email header HTML when POS store name is not set.
+ */
+ public function test_pos_email_header_html_includes_blog_name_when_pos_store_name_is_not_set() {
+ // Given POS store name is not set.
+ delete_option( 'woocommerce_pos_store_name' );
+ update_option( 'blogname', 'Online Store' );
+
+ $emails = new WC_Emails();
+
+ // When getting content from POS email.
+ $email = new WC_Email_Customer_POS_Refunded_Order( $emails );
+
+ // Set the order on the email.
+ $email->object = OrderHelper::create_order();
+
+ $content = $email->get_content_html();
+
+ // Then POS email should include blog name.
+ $this->assertStringContainsString( '<title>Online Store</title>', $content );
+ }
+
/**
* @testdox get_default_subject includes blog name when POS store name is not set.
*/
diff --git a/plugins/woocommerce/tests/php/includes/emails/class-wc-email-header-template-test.php b/plugins/woocommerce/tests/php/includes/emails/class-wc-email-header-template-test.php
new file mode 100644
index 0000000000..036a7ef79f
--- /dev/null
+++ b/plugins/woocommerce/tests/php/includes/emails/class-wc-email-header-template-test.php
@@ -0,0 +1,44 @@
+<?php
+declare( strict_types = 1 );
+
+/**
+ * `email-header.php` test.
+ *
+ * @covers `email-header.php` template
+ */
+class WC_Email_Header_Template_Test extends \WC_Unit_Test_Case {
+ /**
+ * @testdox Email header template includes blog name when store name is not set.
+ */
+ public function test_html_includes_blog_name_when_store_name_is_not_set() {
+ // Given blog name.
+ update_option( 'blogname', 'Online Store' );
+
+ // When getting content from email header.
+ $content = wc_get_template_html( 'emails/email-header.php', array( 'email_heading' => 'Test email heading' ) );
+
+ // Then email header should include blog name.
+ $this->assertStringContainsString( '<title>Online Store</title>', $content );
+ }
+
+ /**
+ * @testdox Email header template includes store name, not blog name, when store name is set.
+ */
+ public function test_html_includes_store_name_when_store_name_is_set() {
+ // Given blog name.
+ update_option( 'blogname', 'Online Store' );
+
+ // When getting content from email header.
+ $content = wc_get_template_html(
+ 'emails/email-header.php',
+ array(
+ 'email_heading' => 'Test email heading',
+ 'store_name' => 'Another store',
+ )
+ );
+
+ // Then email header should include blog name.
+ $this->assertStringContainsString( '<title>Another store</title>', $content );
+ $this->assertStringNotContainsString( '<title>Online Store</title>', $content );
+ }
+}