From 3711ed03b6cd3c36d009258719445d7c8a23131b Mon Sep 17 00:00:00 2001 From: Sarthak Jaiswal Date: Mon, 16 Feb 2026 23:54:12 +0530 Subject: [PATCH] Server-Timing: Leverage core template enhancement output buffer and wp_before_include_template action when available in WP 6.9+ --- .../class-perflab-server-timing.php | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/plugins/performance-lab/includes/server-timing/class-perflab-server-timing.php b/plugins/performance-lab/includes/server-timing/class-perflab-server-timing.php index ba16cf6218..56ddd5c569 100644 --- a/plugins/performance-lab/includes/server-timing/class-perflab-server-timing.php +++ b/plugins/performance-lab/includes/server-timing/class-perflab-server-timing.php @@ -244,9 +244,21 @@ public function use_output_buffer(): bool { */ public function add_hooks(): void { if ( $this->use_output_buffer() ) { - add_action( 'template_redirect', array( $this, 'start_output_buffer' ), PHP_INT_MIN ); + // In WordPress 6.9+, use the core template enhancement output buffer + // instead of starting a custom one. + if ( function_exists( 'wp_start_template_enhancement_output_buffer' ) ) { + add_filter( 'wp_template_enhancement_output_buffer', array( $this, 'process_output_buffer' ), PHP_INT_MIN ); + } else { + add_action( 'template_redirect', array( $this, 'start_output_buffer' ), PHP_INT_MIN ); + } } else { - add_filter( 'template_include', array( $this, 'on_template_include' ), PHP_INT_MAX ); + // In WordPress 6.9+, use the dedicated action instead of misusing + // the template_include filter. + if ( function_exists( 'wp_start_template_enhancement_output_buffer' ) ) { + add_action( 'wp_before_include_template', array( $this, 'on_before_include_template' ) ); + } else { + add_filter( 'template_include', array( $this, 'on_template_include' ), PHP_INT_MAX ); + } } } @@ -284,6 +296,39 @@ function ( string $output, ?int $phase ): string { ); } + /** + * Callback for the wp_template_enhancement_output_buffer filter. + * + * Sends the Server-Timing header and passes through the output buffer content unchanged. + * + * @since n.e.x.t + * + * @param string|mixed $output The output buffer content. + * @return string The output buffer content, unchanged. + */ + public function process_output_buffer( $output ): string { + if ( ! is_string( $output ) ) { + $output = ''; + } + + $this->send_header(); + + return $output; + } + + /** + * Callback for the wp_before_include_template action. + * + * Sends the Server-Timing header right before the template is included. + * + * @since n.e.x.t + * + * @param string $template The template file path. + */ + public function on_before_include_template( string $template ): void { + $this->send_header(); + } + /** * Formats the header segment for a single metric. *