Commit f118d351d5f for woocommerce
commit f118d351d5fbc764bf6f7057032e37041ae69855
Author: Ján Mikláš <neosinner@gmail.com>
Date: Wed Apr 8 13:24:16 2026 +0200
Harden email footer placeholder replacements against null input (#64056)
* Harden email footer placeholder replacements against null input.
Prevent PHP 8 TypeErrors when third-party filters return non-string footer text, and add WC_Emails tests covering null handling and site title replacement.
Made-with: Cursor
* Add changefile(s) from automation for the following project(s): woocommerce
---------
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/64056-wooplug-6479-public-function-replace_placeholders-error b/plugins/woocommerce/changelog/64056-wooplug-6479-public-function-replace_placeholders-error
new file mode 100644
index 00000000000..e0000ff2ac9
--- /dev/null
+++ b/plugins/woocommerce/changelog/64056-wooplug-6479-public-function-replace_placeholders-error
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prevent fatal errors in email footer placeholder replacement when third-party filters return non-string values.
\ No newline at end of file
diff --git a/plugins/woocommerce/includes/class-wc-emails.php b/plugins/woocommerce/includes/class-wc-emails.php
index 48f173482cd..a41c109b0bf 100644
--- a/plugins/woocommerce/includes/class-wc-emails.php
+++ b/plugins/woocommerce/includes/class-wc-emails.php
@@ -393,6 +393,10 @@ class WC_Emails {
* @return string Email footer text with any replacements done.
*/
public function replace_placeholders( $text ) {
+ if ( ! is_string( $text ) ) {
+ $text = is_scalar( $text ) ? (string) $text : '';
+ }
+
$domain = wp_parse_url( home_url(), PHP_URL_HOST );
return str_replace(
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 e9f38834385..aa1c329fd0b 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
@@ -506,6 +506,10 @@ if ( ! class_exists( 'WC_Email_Customer_POS_Completed_Order', false ) ) :
return $footer_text;
}
+ if ( ! is_string( $footer_text ) ) {
+ $footer_text = is_scalar( $footer_text ) ? (string) $footer_text : '';
+ }
+
return str_replace(
array(
'{site_title}',
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 9df5da7b226..7797583fd21 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
@@ -620,6 +620,10 @@ if ( ! class_exists( 'WC_Email_Customer_POS_Refunded_Order', false ) ) :
return $footer_text;
}
+ if ( ! is_string( $footer_text ) ) {
+ $footer_text = is_scalar( $footer_text ) ? (string) $footer_text : '';
+ }
+
return str_replace(
array(
'{site_title}',
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-emails-tests.php b/plugins/woocommerce/tests/php/includes/class-wc-emails-tests.php
index 755c314cfda..39bceac5f07 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-emails-tests.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-emails-tests.php
@@ -41,6 +41,26 @@ class WC_Emails_Tests extends \WC_Unit_Test_Case {
$this->assertFalse( empty( $content ) );
}
+ /**
+ * Test that replace_placeholders safely handles null values.
+ */
+ public function test_replace_placeholders_handles_null_value() {
+ $email_object = new WC_Emails();
+ $this->assertSame( '', $email_object->replace_placeholders( null ) );
+ }
+
+ /**
+ * Test that replace_placeholders replaces known placeholders.
+ */
+ public function test_replace_placeholders_replaces_site_title() {
+ $email_object = new WC_Emails();
+ $placeholder = '{site_title}';
+ $actual = $email_object->replace_placeholders( $placeholder );
+ $expected = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
+
+ $this->assertSame( $expected, $actual );
+ }
+
/**
* Test that order meta function outputs linked meta.
*/