-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensure the entire template is passed to the output buffer callback for Optimization Detective to process #1317
Changes from 9 commits
b3ce59e
13e068d
523fc7a
3235f3b
15ca2f0
78967f5
f218dc8
0b4f2cd
2c6ec0c
35085e8
364fa43
1b62c1a
26e859d
21ebb97
8cbcbd6
85e9c2b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,8 +31,34 @@ | |
* @return string Unmodified value of $passthrough. | ||
*/ | ||
function od_buffer_output( string $passthrough ): string { | ||
/* | ||
* Instead of the default PHP_OUTPUT_HANDLER_STDFLAGS (cleanable, flushable, and removable) being used for flags, | ||
* we need to omit PHP_OUTPUT_HANDLER_FLUSHABLE. If the buffer were flushable, then each time that ob_flush() is | ||
* called, it would send a fragment of the output into the output buffer callback. When buffering the entire | ||
* response as an HTML document, this would result in broken HTML processing. | ||
* | ||
* If this ends up being problematic, then PHP_OUTPUT_HANDLER_FLUSHABLE could be added to the $flags and the | ||
* output buffer callback could check if the phase is PHP_OUTPUT_HANDLER_FLUSH and abort any subsequent | ||
* processing while also emitting a _doing_it_wrong(). | ||
* | ||
* The output buffer needs to be removable because WordPress calls wp_ob_end_flush_all() and then calls | ||
* wp_cache_close(). If the buffers are not all flushed before wp_cache_close() is closed, then some output buffer | ||
* handlers (e.g. for caching plugins) may fail to be able to store the page output in the object cache. | ||
* See <https://github.com/WordPress/performance/pull/1317#issuecomment-2271955356>. | ||
*/ | ||
$flags = PHP_OUTPUT_HANDLER_STDFLAGS ^ PHP_OUTPUT_HANDLER_FLUSHABLE; | ||
|
||
ob_start( | ||
static function ( string $output ): string { | ||
static function ( string $output, ?int $phase ): string { | ||
// When the output is being cleaned (e.g. pending template is replaced with error page), do not send it through the filter. | ||
if ( ( $phase & PHP_OUTPUT_HANDLER_CLEAN ) !== 0 ) { | ||
return $output; | ||
} | ||
|
||
// Since ob_start() was called without PHP_OUTPUT_HANDLER_FLUSHABLE, at this point the phase should never be flush, and it should always be final. | ||
assert( ( $phase & ( PHP_OUTPUT_HANDLER_FLUSH ) ) === 0 ); | ||
assert( ( $phase & ( PHP_OUTPUT_HANDLER_FINAL ) ) !== 0 ); | ||
|
||
/** | ||
* Filters the template output buffer prior to sending to the client. | ||
* | ||
|
@@ -42,7 +68,9 @@ static function ( string $output ): string { | |
* @return string Filtered output buffer. | ||
*/ | ||
return (string) apply_filters( 'od_template_output_buffer', $output ); | ||
} | ||
}, | ||
0, // Unlimited buffer size. | ||
$flags | ||
); | ||
return $passthrough; | ||
} | ||
|
@@ -139,7 +167,7 @@ function od_is_response_html_content_type(): bool { | |
* @return string Filtered template output buffer. | ||
*/ | ||
function od_optimize_template_output_buffer( string $buffer ): string { | ||
if ( ! od_is_response_html_content_type() ) { | ||
if ( ! od_is_response_html_content_type() ) { // TODO: This should check to see if there is an HTML tag. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I'm opening a sub-PR for this. It's unrelated to output buffering. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See #1442 |
||
return $buffer; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about using
assert()
as I don't think there's a precedent in WP or this plugin for that. Can we use one of the more common ways to aid debugging in WordPress?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are sanity checks that should not ever return false given the flags.
There are instances of
assert()
being used in core, although in bundled libraries: https://github.com/search?q=repo%3AWordPress%2Fwordpress-develop+%2Fassert%5C%28%2F+path%3A%2Fsrc%2F&type=codeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but not in WordPress itself, and I don't know how relevant the presence of these flags is in said code, e.g. whether the code paths are even reached.
If they should never return
false
, then I'd say we should either go with what's more established for debugging in WordPress, or simply omit them.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Removed in 364fa43.