Skip to content

Commit 9c410e5

Browse files
authored
Merge pull request #1260 from WordPress/fix/server-timing-output-buffer-priority
Fix Server-Timing compatibility with other plugins that do output buffering
2 parents d998aa9 + 934e7a7 commit 9c410e5

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

plugins/performance-lab/includes/server-timing/class-perflab-server-timing.php

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,25 @@ public function use_output_buffer(): bool {
225225
return (bool) apply_filters( 'perflab_server_timing_use_output_buffer', $enabled );
226226
}
227227

228+
/**
229+
* Adds hooks to send the Server-Timing header.
230+
*
231+
* When output buffering is enabled, buffer as early as possible so that any other plugins that also do output
232+
* buffering will be able to register Server-Timing metrics. The first output buffer callback to be registered
233+
* is the last one to be called, so by starting the Server-Timing output buffer as soon as possible we can be
234+
* assured that other plugins' output buffer callbacks will run before the Server-Timing one that sends the
235+
* Server-Timing header.
236+
*
237+
* @since n.e.x.t
238+
*/
239+
public function add_hooks(): void {
240+
if ( $this->use_output_buffer() ) {
241+
add_action( 'template_redirect', array( $this, 'start_output_buffer' ), PHP_INT_MIN );
242+
} else {
243+
add_filter( 'template_include', array( $this, 'on_template_include' ), PHP_INT_MAX );
244+
}
245+
}
246+
228247
/**
229248
* Hook callback for the 'template_include' filter.
230249
*
@@ -238,18 +257,22 @@ public function use_output_buffer(): bool {
238257
* @return mixed Unmodified value of $passthrough.
239258
*/
240259
public function on_template_include( $passthrough = null ) {
241-
if ( ! $this->use_output_buffer() ) {
242-
$this->send_header();
243-
return $passthrough;
244-
}
260+
$this->send_header();
261+
return $passthrough;
262+
}
245263

264+
/**
265+
* Starts output buffering to send the Server-Timing header right before returning the buffer.
266+
*
267+
* @since n.e.x.t
268+
*/
269+
public function start_output_buffer(): void {
246270
ob_start(
247271
function ( $output ) {
248272
$this->send_header();
249273
return $output;
250274
}
251275
);
252-
return $passthrough;
253276
}
254277

255278
/**

plugins/performance-lab/includes/server-timing/load.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function perflab_server_timing(): Perflab_Server_Timing {
4545
return $server_timing;
4646
}
4747

48-
add_filter( 'template_include', array( $server_timing, 'on_template_include' ), PHP_INT_MAX );
48+
$server_timing->add_hooks();
4949
}
5050

5151
return $server_timing;

tests/plugins/performance-lab/includes/server-timing/test-load.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,29 @@ public function test_perflab_server_timing(): void {
1616
$this->assertTrue( has_filter( 'template_include' ) );
1717

1818
$server_timing = perflab_server_timing();
19+
$this->assertFalse( $server_timing->use_output_buffer() );
1920
$this->assertSame( PHP_INT_MAX, has_filter( 'template_include', array( $server_timing, 'on_template_include' ) ), 'template_include filter not added' );
21+
$this->assertFalse( has_action( 'template_redirect', array( $server_timing, 'start_output_buffer' ) ), 'template_redirect action added' );
2022

2123
$server_timing2 = perflab_server_timing();
2224
$this->assertSame( $server_timing, $server_timing2, 'Different instance returned' );
2325
}
2426

27+
/**
28+
* @covers Perflab_Server_Timing::add_hooks
29+
*/
30+
public function test_perflab_server_timing_with_output_buffering(): void {
31+
remove_all_actions( 'template_redirect' );
32+
remove_all_filters( 'template_include' );
33+
34+
$server_timing = perflab_server_timing();
35+
add_filter( 'perflab_server_timing_use_output_buffer', '__return_true' );
36+
$this->assertTrue( $server_timing->use_output_buffer() );
37+
$server_timing->add_hooks();
38+
$this->assertFalse( has_filter( 'template_include', array( $server_timing, 'on_template_include' ) ), 'template_include filter added' );
39+
$this->assertSame( PHP_INT_MIN, has_action( 'template_redirect', array( $server_timing, 'start_output_buffer' ) ), 'template_redirect action not added' );
40+
}
41+
2542
public function test_perflab_server_timing_register_metric(): void {
2643
$this->assertFalse( perflab_server_timing()->has_registered_metric( 'test-metric' ) );
2744

0 commit comments

Comments
 (0)