Commit 743c6e3444 for woocommerce
commit 743c6e34440a071b7fba05e5a24d5cd418e3bb0e
Author: Jan Lysý <lysyjan@users.noreply.github.com>
Date: Tue Nov 18 07:20:04 2025 +0100
Ensure `Post_Content` compatibility with non-email contexts (#61874)
* Ensure `Post_Content` compatibility with non-email contexts and add test coverage
* Add changelog
* Ensure `Post_Content` renderer uses stateless logic only in email contexts and swap callback dynamically to prevent conflicts with other plugins
diff --git a/packages/php/email-editor/changelog/fix-post-content-context-aware-rendering b/packages/php/email-editor/changelog/fix-post-content-context-aware-rendering
new file mode 100644
index 0000000000..c3b44b3d77
--- /dev/null
+++ b/packages/php/email-editor/changelog/fix-post-content-context-aware-rendering
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Swap core/post-content render callback only during email rendering to prevent conflicts with other plugins like MailPoet.
diff --git a/packages/php/email-editor/src/Engine/Renderer/ContentRenderer/class-content-renderer.php b/packages/php/email-editor/src/Engine/Renderer/ContentRenderer/class-content-renderer.php
index 2922e5c38f..3c0e3d7741 100644
--- a/packages/php/email-editor/src/Engine/Renderer/ContentRenderer/class-content-renderer.php
+++ b/packages/php/email-editor/src/Engine/Renderer/ContentRenderer/class-content-renderer.php
@@ -12,6 +12,7 @@ use Automattic\WooCommerce\EmailEditor\Engine\Logger\Email_Editor_Logger;
use Automattic\WooCommerce\EmailEditor\Engine\Renderer\Css_Inliner;
use Automattic\WooCommerce\EmailEditor\Engine\Theme_Controller;
use Automattic\WooCommerce\EmailEditor\Integrations\Core\Renderer\Blocks\Fallback;
+use Automattic\WooCommerce\EmailEditor\Integrations\Core\Renderer\Blocks\Post_Content;
use WP_Block_Template;
use WP_Block_Type_Registry;
use WP_Post;
@@ -92,6 +93,13 @@ class Content_Renderer {
*/
private Email_Editor_Logger $logger;
+ /**
+ * Backup of the original core/post-content render callback.
+ *
+ * @var callable|null
+ */
+ private $backup_post_content_callback;
+
/**
* Content_Renderer constructor.
*
@@ -123,6 +131,19 @@ class Content_Renderer {
add_filter( 'render_block', array( $this, 'render_block' ), 10, 2 );
add_filter( 'block_parser_class', array( $this, 'block_parser' ) );
add_filter( 'woocommerce_email_blocks_renderer_parsed_blocks', array( $this, 'preprocess_parsed_blocks' ) );
+
+ // Swap core/post-content render callback for email rendering.
+ // This prevents issues with WordPress's static $seen_ids array when rendering
+ // multiple emails in a single request (e.g., MailPoet batch processing).
+ $post_content_type = $this->block_type_registry->get_registered( 'core/post-content' );
+ if ( $post_content_type ) {
+ // Save the original callback (may be null or WordPress's default).
+ $this->backup_post_content_callback = $post_content_type->render_callback;
+
+ // Replace with our stateless renderer.
+ $post_content_renderer = new Post_Content();
+ $post_content_type->render_callback = array( $post_content_renderer, 'render_stateless' );
+ }
}
/**
@@ -247,6 +268,14 @@ class Content_Renderer {
remove_filter( 'block_parser_class', array( $this, 'block_parser' ) );
remove_filter( 'woocommerce_email_blocks_renderer_parsed_blocks', array( $this, 'preprocess_parsed_blocks' ) );
+ // Restore the original core/post-content render callback.
+ // Note: We always restore it, even if it was null originally.
+ $post_content_type = $this->block_type_registry->get_registered( 'core/post-content' );
+ if ( $post_content_type ) {
+ // @phpstan-ignore-next-line -- WordPress core allows null for render_callback despite type definition.
+ $post_content_type->render_callback = $this->backup_post_content_callback;
+ }
+
// Restore globals to their original values.
global $_wp_current_template_content, $_wp_current_template_id, $wp_query, $post;
diff --git a/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-post-content.php b/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-post-content.php
index 22963b97cd..7601bc6355 100644
--- a/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-post-content.php
+++ b/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-post-content.php
@@ -32,12 +32,17 @@ class Post_Content {
* - Uses direct post content access instead of get_the_content()
* - Properly backs up and restores global state
*
+ * IMPORTANT: This method is only set as the render_callback during email rendering.
+ * Outside of email rendering, the original callback is restored, so this method
+ * will never be called in non-email contexts.
+ *
* @param array $attributes Block attributes.
* @param string $content Block content.
* @param \WP_Block $block Block instance.
* @return string Rendered post content HTML.
*/
public function render_stateless( $attributes, $content, $block ): string {
+ // This method is only called during email rendering, so we always use stateless logic.
$post_id = $block->context['postId'] ?? null;
if ( ! $post_id ) {
diff --git a/packages/php/email-editor/src/Integrations/Core/class-initializer.php b/packages/php/email-editor/src/Integrations/Core/class-initializer.php
index 5e6232a95f..e402e0f1de 100644
--- a/packages/php/email-editor/src/Integrations/Core/class-initializer.php
+++ b/packages/php/email-editor/src/Integrations/Core/class-initializer.php
@@ -150,14 +150,6 @@ class Initializer {
$settings['render_email_callback'] = array( $this, 'render_block' );
}
- // Special handling for core/post-content to use stateless renderer.
- // This prevents issues with WordPress's static $seen_ids array when rendering
- // multiple emails in a single request (e.g., MailPoet batch processing).
- if ( 'core/post-content' === $settings['name'] ) {
- $post_content_renderer = new Post_Content();
- $settings['render_callback'] = array( $post_content_renderer, 'render_stateless' );
- }
-
return $settings;
}
diff --git a/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Post_Content_Test.php b/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Post_Content_Test.php
index dd5e5da5d2..b460b73013 100644
--- a/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Post_Content_Test.php
+++ b/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Post_Content_Test.php
@@ -35,15 +35,14 @@ class Post_Content_Test extends \Email_Editor_Integration_Test_Case {
$this->initializer = $this->di_container->get( Initializer::class );
$this->initializer->initialize();
- // Manually trigger block settings update for core/post-content
- // This simulates what the block_type_metadata_settings filter does in Bootstrap.
+ // Manually swap the core/post-content render callback to simulate email rendering.
+ // In production, this is done by Content_Renderer::initialize() when rendering emails.
$registry = \WP_Block_Type_Registry::get_instance();
$block_type = $registry->get_registered( 'core/post-content' );
if ( $block_type ) {
- $settings = (array) $block_type;
- $settings['name'] = 'core/post-content';
- $updated_settings = $this->initializer->update_block_settings( $settings );
- $block_type->render_callback = $updated_settings['render_callback'] ?? null;
+ // Replace with our stateless renderer.
+ $post_content_renderer = new Post_Content();
+ $block_type->render_callback = array( $post_content_renderer, 'render_stateless' );
}
}