Heartbeat API: first run, see #23216
git-svn-id: https://develop.svn.wordpress.org/trunk@23355 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
a38f0e16c5
commit
5edc6b2711
@ -56,7 +56,7 @@ $core_actions_post = array(
|
|||||||
'save-widget', 'set-post-thumbnail', 'date_format', 'time_format', 'wp-fullscreen-save-post',
|
'save-widget', 'set-post-thumbnail', 'date_format', 'time_format', 'wp-fullscreen-save-post',
|
||||||
'wp-remove-post-lock', 'dismiss-wp-pointer', 'upload-attachment', 'get-attachment',
|
'wp-remove-post-lock', 'dismiss-wp-pointer', 'upload-attachment', 'get-attachment',
|
||||||
'query-attachments', 'save-attachment', 'save-attachment-compat', 'send-link-to-editor',
|
'query-attachments', 'save-attachment', 'save-attachment-compat', 'send-link-to-editor',
|
||||||
'send-attachment-to-editor', 'save-attachment-order',
|
'send-attachment-to-editor', 'save-attachment-order', 'heartbeat',
|
||||||
);
|
);
|
||||||
|
|
||||||
// Register core Ajax calls.
|
// Register core Ajax calls.
|
||||||
|
@ -2071,3 +2071,32 @@ function wp_ajax_send_link_to_editor() {
|
|||||||
|
|
||||||
wp_send_json_success( $html );
|
wp_send_json_success( $html );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function wp_ajax_heartbeat() {
|
||||||
|
check_ajax_referer( 'heartbeat-nonce', '_nonce' );
|
||||||
|
$response = array( 'pagenow' => '' );
|
||||||
|
|
||||||
|
if ( ! empty($_POST['pagenow']) )
|
||||||
|
$response['pagenow'] = sanitize_key($_POST['pagenow']);
|
||||||
|
|
||||||
|
if ( ! empty($_POST['data']) ) {
|
||||||
|
$data = (array) $_POST['data'];
|
||||||
|
// todo: how much to sanitize and preset and what to leave to be accessed from $data or $_POST..?
|
||||||
|
$user = wp_get_current_user();
|
||||||
|
$data['user_id'] = $user->exists() ? $user->ID : 0;
|
||||||
|
|
||||||
|
// todo: separate filters: 'heartbeat_[action]' so we call different callbacks only when there is data for them,
|
||||||
|
// or all callbacks listen to one filter and run when there is something for them in $data?
|
||||||
|
$response = apply_filters( 'heartbeat_received', $response, $data );
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = apply_filters( 'heartbeat_send', $response );
|
||||||
|
|
||||||
|
// Allow the transport to be replaced with long-polling easily
|
||||||
|
do_action( 'heartbeat_tick', $response );
|
||||||
|
|
||||||
|
// always send the current time acording to the server
|
||||||
|
$response['time'] = time();
|
||||||
|
|
||||||
|
wp_send_json($response);
|
||||||
|
}
|
||||||
|
@ -290,4 +290,7 @@ add_filter( 'default_option_link_manager_enabled', '__return_true' );
|
|||||||
// This option no longer exists; tell plugins we always support auto-embedding.
|
// This option no longer exists; tell plugins we always support auto-embedding.
|
||||||
add_filter( 'default_option_embed_autourls', '__return_true' );
|
add_filter( 'default_option_embed_autourls', '__return_true' );
|
||||||
|
|
||||||
|
// Default settings for heartbeat
|
||||||
|
add_filter( 'heartbeat_settings', 'wp_heartbeat_settings' );
|
||||||
|
|
||||||
unset($filter, $action);
|
unset($filter, $action);
|
||||||
|
@ -2284,3 +2284,18 @@ function __checked_selected_helper( $helper, $current, $echo, $type ) {
|
|||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default settings for heartbeat
|
||||||
|
*
|
||||||
|
* Outputs the nonce used in the heartbeat XHR
|
||||||
|
*
|
||||||
|
* @since 3.6.0
|
||||||
|
*
|
||||||
|
* @param array $settings
|
||||||
|
* @return array $settings
|
||||||
|
*/
|
||||||
|
function wp_heartbeat_settings( $settings ) {
|
||||||
|
$setting['nonce'] = wp_create_nonce( 'heartbeat-nonce' );
|
||||||
|
return $setting;
|
||||||
|
}
|
||||||
|
178
wp-includes/js/heartbeat.js
Normal file
178
wp-includes/js/heartbeat.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/**
|
||||||
|
* Heartbeat API
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Ensure the global `wp` object exists.
|
||||||
|
window.wp = window.wp || {};
|
||||||
|
|
||||||
|
(function($){
|
||||||
|
var Heartbeat = function() {
|
||||||
|
var self = this,
|
||||||
|
running,
|
||||||
|
timeout,
|
||||||
|
nonce,
|
||||||
|
screen = typeof pagenow != 'undefined' ? pagenow : '',
|
||||||
|
settings,
|
||||||
|
tick = 0,
|
||||||
|
queue = {},
|
||||||
|
interval,
|
||||||
|
lastconnect = 0;
|
||||||
|
|
||||||
|
this.url = typeof ajaxurl != 'undefined' ? ajaxurl : 'wp-admin/admin-ajax.php';
|
||||||
|
this.autostart = true;
|
||||||
|
|
||||||
|
if ( typeof( window.heartbeatSettings != 'undefined' ) ) {
|
||||||
|
settings = $.extend( {}, window.heartbeatSettings );
|
||||||
|
delete window.heartbeatSettings;
|
||||||
|
|
||||||
|
// Add private vars
|
||||||
|
nonce = settings.nonce || '';
|
||||||
|
delete settings.nonce;
|
||||||
|
|
||||||
|
interval = settings.interval || 15000; // default interval
|
||||||
|
delete settings.interval;
|
||||||
|
|
||||||
|
// todo: needed?
|
||||||
|
// 'pagenow' can be added from settings if not already defined
|
||||||
|
screen = screen || settings.pagenow;
|
||||||
|
delete settings.pagenow;
|
||||||
|
|
||||||
|
// Add public vars
|
||||||
|
$.extend( this, settings );
|
||||||
|
}
|
||||||
|
|
||||||
|
function time(s) {
|
||||||
|
if ( s )
|
||||||
|
return parseInt( (new Date()).getTime() / 1000 );
|
||||||
|
|
||||||
|
return (new Date()).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set error state and fire an event if it persists for over 3 min
|
||||||
|
function errorstate() {
|
||||||
|
var since;
|
||||||
|
|
||||||
|
if ( lastconnect ) {
|
||||||
|
since = time() - lastconnect;
|
||||||
|
|
||||||
|
if ( since > 180000 ) {
|
||||||
|
self.connectionLost = true;
|
||||||
|
$(document).trigger( 'heartbeat-connection-lost', parseInt(since / 1000) );
|
||||||
|
} else if ( self.connectionLost ) {
|
||||||
|
self.connectionLost = false;
|
||||||
|
$(document).trigger( 'heartbeat-connection-restored' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function connect() {
|
||||||
|
var data = {};
|
||||||
|
tick = time();
|
||||||
|
|
||||||
|
data.data = $.extend( {}, queue );
|
||||||
|
queue = {};
|
||||||
|
|
||||||
|
data.interval = interval / 1000;
|
||||||
|
data._nonce = nonce;
|
||||||
|
data.action = 'heartbeat';
|
||||||
|
data.pagenow = screen;
|
||||||
|
|
||||||
|
self.xhr = $.post( self.url, data, function(r){
|
||||||
|
lastconnect = time();
|
||||||
|
// Clear error state
|
||||||
|
if ( self.connectionLost )
|
||||||
|
errorstate();
|
||||||
|
|
||||||
|
self.tick(r);
|
||||||
|
}, 'json' ).always( function(){
|
||||||
|
next();
|
||||||
|
}).fail( function(r){
|
||||||
|
errorstate();
|
||||||
|
self.error(r);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
var delta = time() - tick;
|
||||||
|
|
||||||
|
if ( !running )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( delta < interval ) {
|
||||||
|
timeout = window.setTimeout(
|
||||||
|
function(){
|
||||||
|
if ( running )
|
||||||
|
connect();
|
||||||
|
},
|
||||||
|
interval - delta
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
window.clearTimeout(timeout); // this has already expired?
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.interval = function(seconds) {
|
||||||
|
if ( seconds ) {
|
||||||
|
// Limit
|
||||||
|
if ( 5 > seconds || seconds > 60 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
interval = seconds * 1000;
|
||||||
|
} else if ( seconds === 0 ) {
|
||||||
|
// Allow long polling to be turned on
|
||||||
|
interval = 0;
|
||||||
|
}
|
||||||
|
return interval / 1000;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.start = function() {
|
||||||
|
// start only once
|
||||||
|
if ( running )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
connect();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.stop = function() {
|
||||||
|
if ( !running )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( self.xhr )
|
||||||
|
self.xhr.abort();
|
||||||
|
|
||||||
|
running = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.send = function(action, data) {
|
||||||
|
if ( action )
|
||||||
|
queue[action] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.autostart ) {
|
||||||
|
$(document).ready( function(){
|
||||||
|
// Start one tick (15 sec) after DOM ready
|
||||||
|
running = true;
|
||||||
|
tick = time();
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$.extend( Heartbeat.prototype, {
|
||||||
|
tick: function(r) {
|
||||||
|
$(document).trigger( 'heartbeat-tick', r );
|
||||||
|
},
|
||||||
|
error: function(r) {
|
||||||
|
$(document).trigger( 'heartbeat-error', r );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
wp.heartbeat = new Heartbeat();
|
||||||
|
|
||||||
|
}(jQuery));
|
@ -107,6 +107,11 @@ function wp_default_scripts( &$scripts ) {
|
|||||||
) );
|
) );
|
||||||
|
|
||||||
$scripts->add( 'autosave', "/wp-includes/js/autosave$suffix.js", array('schedule', 'wp-ajax-response'), false, 1 );
|
$scripts->add( 'autosave', "/wp-includes/js/autosave$suffix.js", array('schedule', 'wp-ajax-response'), false, 1 );
|
||||||
|
|
||||||
|
$scripts->add( 'heartbeat', "/wp-includes/js/heartbeat$suffix.js", array('jquery'), false, 1 );
|
||||||
|
did_action( 'init' ) && $scripts->localize( 'heartbeat', 'heartbeatSettings',
|
||||||
|
apply_filters( 'heartbeat_settings', array() )
|
||||||
|
);
|
||||||
|
|
||||||
$scripts->add( 'wp-lists', "/wp-includes/js/wp-lists$suffix.js", array( 'wp-ajax-response', 'jquery-color' ), false, 1 );
|
$scripts->add( 'wp-lists', "/wp-includes/js/wp-lists$suffix.js", array( 'wp-ajax-response', 'jquery-color' ), false, 1 );
|
||||||
|
|
||||||
@ -371,7 +376,7 @@ function wp_default_scripts( &$scripts ) {
|
|||||||
|
|
||||||
$scripts->add( 'postbox', "/wp-admin/js/postbox$suffix.js", array('jquery-ui-sortable'), false, 1 );
|
$scripts->add( 'postbox', "/wp-admin/js/postbox$suffix.js", array('jquery-ui-sortable'), false, 1 );
|
||||||
|
|
||||||
$scripts->add( 'post', "/wp-admin/js/post$suffix.js", array('suggest', 'wp-lists', 'postbox'), false, 1 );
|
$scripts->add( 'post', "/wp-admin/js/post$suffix.js", array('suggest', 'wp-lists', 'postbox', 'heartbeat'), false, 1 );
|
||||||
did_action( 'init' ) && $scripts->localize( 'post', 'postL10n', array(
|
did_action( 'init' ) && $scripts->localize( 'post', 'postL10n', array(
|
||||||
'ok' => __('OK'),
|
'ok' => __('OK'),
|
||||||
'cancel' => __('Cancel'),
|
'cancel' => __('Cancel'),
|
||||||
|
Loading…
Reference in New Issue
Block a user