Skip to content
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

Only apply output buffer filter when in final phase #62770

Draft
wants to merge 1 commit into
base: trunk
Choose a base branch
from

Conversation

westonruter
Copy link
Member

As suggested by @nextend in a follow-up to #61212:

We use output buffering in our 900k+ plugin and based on my experience I suggest the following changes:

<?php
function _gutenberg_buffer_template_output( string $passthrough ): string {
	ob_start(
		static function ( string $output, ?int $phase): string {

			if ($phase & PHP_OUTPUT_HANDLER_FINAL) {
				/**
			 	* Filters the template output buffer prior to sending to the client.
			 	*
			 	* @param string $output Output buffer.
				 * @return string Filtered output buffer.
				 */
				return (string) apply_filters( 'gutenberg_template_output_buffer', $output );
			}

			return $output;
		}
	);
	return $passthrough;
}

As I remember these are related when ob_clean and ob_flush called during the output buffer is open. It skips the processing of the output when its dropped.

Co-authored-by: Roland Soos <roland@nextendweb.com>
@westonruter
Copy link
Member Author

@nextend I'm having a hard time triggering a scenario in which PHP_OUTPUT_HANDLER_FINAL is not passed. I'm marking this as a draft so this doesn't get merged prior to validating the need for it.

@westonruter
Copy link
Member Author

I tried adding a test case in WordPress/performance#1317 but I'm not having success.

@nextend
Copy link

nextend commented Jun 25, 2024

Here is an example that can trigger the $phase argument to not be PHP_OUTPUT_HANDLER_FINAL:

https://bitbucket.org/rolandsoos/workspace/snippets/aq7bnz

The content of the first echo will be dropped by the ob_clean() call. The current implementation in #60280 would apply the filter for this dropped message.

@westonruter
Copy link
Member Author

@nextend Thanks for providing that test case. Sorry for the delay in responding. To be honest I've been having a hard time wrapping my brain around this. I've iterated on the corresponding PR in the WordPress/performance repo and I'm getting closer but I'm still perplexed why it isn't behaving as expected. Could you take a look? https://github.com/WordPress/performance/pull/1317/files

@nextend
Copy link

nextend commented Aug 2, 2024

@westonruter I think the missing piece is to call ob_end_flush(); before calling ob_get_clean();.

On line 91, a new output buffer is created. This output buffer is necessary as it allows you to access the output in the same way the PHP runtime does when outputting the default output buffer.

In the original code, the following happened:

  • System [1] output buffer <- This will be sent to the browser.

In the new code:

  • System [1] output buffer <- This will be sent to the browser.
    • Line 91 -> [2] output buffer
      • od_buffer_output -> [3] output buffer
      • ob_end_flush -> Output buffer [3] is closed -> ob callback gets called -> Result of the callback is flushed into [2] buffer
    • Now we can access the real output with ob_get_clean, which gives us the content of the [2] buffer (and then discards the output).
@westonruter
Copy link
Member Author

@nextend Thank you. I iterated on it a bit more with your change applied and I think it's in a good shape: WordPress/performance#1317

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Interactivity API API to add frontend interactivity to blocks. [Packages] Interactivity /packages/interactivity [Type] Experimental Experimental feature or API.
2 participants