Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
39a3907
Add output buffering for the rendered template
westonruter Feb 26, 2025
f576c3c
Rework filter to exclusively apply to an HTML output buffer
westonruter Mar 13, 2025
33b524b
Add wp_final_output_buffer action
westonruter Mar 13, 2025
5e49712
Merge branch 'trunk' of https://github.com/WordPress/wordpress-develo…
westonruter Mar 13, 2025
8a6f5a7
Merge branch 'trunk' of https://github.com/WordPress/wordpress-develo…
westonruter Sep 22, 2025
e9a46aa
Add wp_before_include_template action and move OB handling to new fun…
westonruter Sep 22, 2025
2c074fa
Add wp_template_output_buffer filter
westonruter Sep 22, 2025
7f79ebd
Ensure at least one tag is present for HTML content type
westonruter Sep 23, 2025
6637ef5
Add test for ending and cleaning an output buffer to avoid processing
westonruter Sep 23, 2025
b98b81e
Add test case for JSON
westonruter Sep 23, 2025
9f07ad0
Account for multiple content-type headers
westonruter Sep 23, 2025
4e7029b
Fix passing back the filtered output buffer
westonruter Sep 23, 2025
fd79c2a
Remove extra line break
westonruter Sep 23, 2025
322c930
Merge branch 'trunk' into trac-43258
westonruter Sep 26, 2025
32cc514
Add test for calling ob_clean() instead of ob_end_clean()
westonruter Sep 26, 2025
59cf047
Include original buffer in param to filters
westonruter Oct 1, 2025
b755a24
Fix alignment
westonruter Oct 1, 2025
2dabd76
Clarify that the wp_before_include_template action occurs immediately…
westonruter Oct 10, 2025
e65811c
Remove redundant/unreliable HTML content type check for the presence …
westonruter Oct 10, 2025
69df1d0
Eliminate non-HTML output buffering and remove action
westonruter Oct 10, 2025
853082e
Reframe output buffer as being for optimization only
westonruter Oct 10, 2025
d38dc86
Merge branch 'trunk' of https://github.com/WordPress/wordpress-develo…
westonruter Oct 10, 2025
7f309f5
Only start output buffer if filters are present by default
westonruter Oct 10, 2025
6ee2a45
Account for only the first listed content-type header being sent
westonruter Oct 11, 2025
1b4a2c4
Add missing filter param to phpdoc
westonruter Oct 11, 2025
7f43ee5
Fix typo
westonruter Oct 11, 2025
b242dc0
Be explicit about the DOM API to use
westonruter Oct 11, 2025
ad4c8d4
Clarify purpose of filter and why chunking is disabled
westonruter Oct 11, 2025
bbfdaa6
Merge branch 'trunk' into trac-43258
westonruter Oct 11, 2025
80d24ae
Refer to enhancement rather than optimization
westonruter Oct 11, 2025
16d7928
Add wp_should_output_buffer_template_for_enhancement() helper function
westonruter Oct 11, 2025
dfd6e5e
Add assertions for wp_template_enhancement_output_buffer_started action
westonruter Oct 11, 2025
5409e44
Remove unnecessary return phpdoc
westonruter Oct 12, 2025
44d52df
Remove unnecessary default params
westonruter Oct 12, 2025
6bcbf0e
Add missing assertion messages
westonruter Oct 12, 2025
d4a3da3
Merge branch 'trunk' of https://github.com/WordPress/wordpress-develo…
westonruter Oct 12, 2025
6333403
Improve docs for wp_finalize_template_enhancement_output_buffer()
westonruter Oct 15, 2025
611a482
Merge branch 'trunk' into trac-43258
westonruter Oct 15, 2025
f49563c
Remove whitespace at end of line
westonruter Oct 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add wp_template_output_buffer filter
  • Loading branch information
westonruter committed Sep 22, 2025
commit 2c074fa6253d9eb5a9e26622efe8d3f9be7dbc49
14 changes: 14 additions & 0 deletions src/wp-includes/template.php
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,20 @@ function wp_finalize_template_output_buffer( string $output, int $phase ): strin
$filtered_output = (string) apply_filters( 'wp_template_output_buffer_html', $filtered_output );
}

/**
* Filters the template output buffer prior to sending to the client.
*
* This filter applies to HTML and non-HTML template output alike. For example, a "template" could return JSON. Use
* the {@see 'wp_template_output_buffer_html'} filter specifically for filtering HTML output, which is the normal
* case. Notice: It is highly discouraged to use regular expressions to do any kind of replacement on the output.
*
* @since 6.9.0
*
* @param string $output Output buffer.
* @return string Filtered output buffer.
*/
$filtered_output = (string) apply_filters( 'wp_template_output_buffer', $filtered_output );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this can be combined with the wp_template_output_buffer_html filter and $is_html_content_type could be passed as an additional variable. It also might be useful to include $output.

My thinking is that running this through less hooks is going to make it easier for extenders to know where to hook into and introduce a bit less complexity. Additionally, $output being available here makes sense to me since it's in the end of function hook below

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking for wp_template_output_buffer_html was that it would be a convenience for authors to have a filter which would predictably always be sent HTML, and this could always be sent into the HTML API. Otherwise, they'd need to always sniff the type of the output themselves (or look at an additional filter param). So having wp_template_output_buffer_html and wp_template_output_buffer filters is similar to how we have render_block_{$block_name} and render_block filters.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the $output param to the filters in 59cf047

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how this introduces the possibility for a filter to undo any of the other changes that had been done to the $filtered_output.


/**
* Fires after the output buffer has been filtered prior to sending to the client.
*
Expand Down
15 changes: 14 additions & 1 deletion tests/phpunit/tests/template.php
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ function () use ( &$action_args ): void {

add_filter(
'wp_template_output_buffer_html',
function ( string $buffer ): string {
static function ( string $buffer ): string {
$p = WP_HTML_Processor::create_full_parser( $buffer );
while ( $p->next_tag() ) {
echo $p->get_tag() . PHP_EOL;
Expand All @@ -538,6 +538,17 @@ function ( string $buffer ): string {
}
);

add_filter(
'wp_template_output_buffer',
function ( string $buffer ): string {
$this->assertStringNotContainsString( 'Hello', $buffer );
if ( str_starts_with( ltrim( $buffer ), '<!DOCTYPE html>' ) ) {
$buffer .= "\n<!-- Output buffer was processed! -->\n";
}
return $buffer;
}
);

$initial_ob_level = ob_get_level();
$this->assertTrue( wp_start_template_output_buffer() );
$this->assertSame( $initial_ob_level + 1, ob_get_level() );
Expand Down Expand Up @@ -580,12 +591,14 @@ function ( string $buffer ): string {
$this->assertStringContainsString( '<title>Saludo</title>', $action_args[0] );
$this->assertStringContainsString( '<h1>¡Hola, mundo!</h1>', $action_args[0] );
$this->assertStringContainsString( '</html>', $action_args[0] );
$this->assertStringContainsString( '<!-- Output buffer was processed! -->', $action_args[0] );
$this->assertIsString( $action_args[1] );
$this->assertStringContainsString( '<!DOCTYPE html>', $action_args[1] );
$this->assertStringContainsString( '<html lang="en">', $action_args[1] );
$this->assertStringContainsString( '<title>Greeting</title>', $action_args[1] );
$this->assertStringContainsString( '<h1>Hello World!</h1>', $action_args[1] );
$this->assertStringContainsString( '</html>', $action_args[1] );
$this->assertStringNotContainsString( '<!-- Output buffer was processed! -->', $action_args[1] );
}

/**
Expand Down