Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 20 additions & 3 deletions src/js/_enqueues/wp/heartbeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,12 @@

// Timer that keeps track of how long needs to be waited before connecting to
// the server again.
beatTimer: 0
beatTimer: 0,

// Post lock window in milliseconds. Synced from PHP via heartbeat_settings.
// Used to calculate the background tab heartbeat interval.
// Default matches the wp_check_post_lock_window default of 150 seconds.
postLockWindow: 150000
};

/**
Expand All @@ -112,7 +117,7 @@
* @return {void}
*/
function initialize() {
var options, hidden, visibilityState, visibilitychange;
var options, hidden, visibilityState, visibilitychange, postLockWindow;

if ( typeof window.pagenow === 'string' ) {
settings.screenId = window.pagenow;
Expand Down Expand Up @@ -172,6 +177,14 @@
if ( options.suspension === 'disable' ) {
settings.suspendEnabled = false;
}

if ( options.post_lock_window ) {
postLockWindow = parseInt( options.post_lock_window, 10 );

if ( postLockWindow > 0 ) {
settings.postLockWindow = postLockWindow * 1000;
}
}
}

// Convert to milliseconds.
Expand Down Expand Up @@ -509,7 +522,11 @@
}

if ( ! settings.hasFocus ) {
interval = 120000; // 120 seconds. Post locks expire after 150 seconds.
// Fire 30 seconds before the post lock window expires so backgrounded
// tabs always refresh the lock in time. For the default 150s window this
// equals 120s, preserving existing behaviour. Floored at 5s for very
// short custom windows.
interval = Math.max( 5000, settings.postLockWindow - 30000 );
} else if ( settings.countdown > 0 && settings.tempInterval ) {
interval = settings.tempInterval;
settings.countdown--;
Expand Down
5 changes: 4 additions & 1 deletion src/wp-admin/includes/misc.php
Original file line number Diff line number Diff line change
Expand Up @@ -1325,7 +1325,7 @@ function wp_refresh_heartbeat_nonces( $response ) {
}

/**
* Disables suspension of Heartbeat on the Add/Edit Post screens.
* Disables suspension of Heartbeat and sets post lock data on the Add/Edit Post screens.
*
* @since 3.8.0
*
Expand All @@ -1339,6 +1339,9 @@ function wp_heartbeat_set_suspension( $settings ) {

if ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) {
$settings['suspension'] = 'disable';

/** This filter is documented in wp-admin/includes/ajax-actions.php */
$settings['post_lock_window'] = apply_filters( 'wp_check_post_lock_window', 150 );
}

return $settings;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,89 @@ public function data_wp_heartbeat_set_suspension(): array {
),
);
}

/**
* Tests that wp_heartbeat_set_suspension() exposes the default post lock window on post screens.
*
* @dataProvider data_post_screens
*
* @ticket 65171
*
* @param string $pagenow_value The value for the $pagenow global.
*/
public function test_wp_heartbeat_set_suspension_sets_post_lock_window_on_post_screens( $pagenow_value ) {
global $pagenow;

$pagenow = $pagenow_value;

$result = wp_heartbeat_set_suspension( array() );

$this->assertArrayHasKey( 'post_lock_window', $result, "'post_lock_window' should be present when \$pagenow is {$pagenow_value}." );
$this->assertSame( 150, $result['post_lock_window'], "'post_lock_window' should default to 150 when \$pagenow is {$pagenow_value}." );
}

/**
* Tests that wp_heartbeat_set_suspension() does not expose a post lock window on non-post screens.
*
* @dataProvider data_non_post_screens
*
* @ticket 65171
*
* @param string $pagenow_value The value for the $pagenow global.
*/
public function test_wp_heartbeat_set_suspension_does_not_set_post_lock_window_on_other_screens( $pagenow_value ) {
global $pagenow;

$pagenow = $pagenow_value;

$result = wp_heartbeat_set_suspension( array() );

$this->assertArrayNotHasKey( 'post_lock_window', $result, "'post_lock_window' should not be set when \$pagenow is {$pagenow_value}." );
}

/**
* Tests that wp_heartbeat_set_suspension() honors the wp_check_post_lock_window filter.
*
* @ticket 65171
*/
public function test_wp_heartbeat_set_suspension_post_lock_window_respects_filter() {
global $pagenow;

$pagenow = 'post.php';

add_filter(
'wp_check_post_lock_window',
static function () {
return 60;
}
);

$result = wp_heartbeat_set_suspension( array() );

$this->assertSame( 60, $result['post_lock_window'], "'post_lock_window' should reflect the wp_check_post_lock_window filter value." );
}

/**
* Data provider: $pagenow values for the Add/Edit Post screens.
*
* @return array<string, array{pagenow_value: string}>
*/
public function data_post_screens(): array {
return array(
'post.php' => array( 'pagenow_value' => 'post.php' ),
'post-new.php' => array( 'pagenow_value' => 'post-new.php' ),
);
}

/**
* Data provider: $pagenow values for screens that are not Add/Edit Post.
*
* @return array<string, array{pagenow_value: string}>
*/
public function data_non_post_screens(): array {
return array(
'index.php' => array( 'pagenow_value' => 'index.php' ),
'edit.php' => array( 'pagenow_value' => 'edit.php' ),
);
}
}
Loading