Skip to content

Instantly share code, notes, and snippets.

@quasel
Created June 18, 2018 06:29
Show Gist options
  • Select an option

  • Save quasel/fbf9552fa057126faceb79381dea9fd2 to your computer and use it in GitHub Desktop.

Select an option

Save quasel/fbf9552fa057126faceb79381dea9fd2 to your computer and use it in GitHub Desktop.
Heartbeat API example usage for Post Locking on frontend
<?php
/**
* Add display name / role for post locking dialogs.
*
* @param array $response The Heartbeat response.
* @param array $data The $_POST data sent.
* @param string $screen_id The screen id.
*
* @return array The Heartbeat response.
*/
function post_lock_add_display_name_role( $response, $data, $screen_id ) {
if ( ! empty( $response['wp-refresh-post-lock']['lock_error'] ) ) {
$post_id = absint( $data['wp-refresh-post-lock']['post_id'] );
$user_id = wp_check_post_lock( $post_id );
if ( ! $user_id ) {
return $response;
}
$display_name_role = post_lock_get_display_name_role( $user_id );
$response['wp-refresh-post-lock']['lock_error']['display_name'] = esc_html( $display_name_role['display_name'] );
$response['wp-refresh-post-lock']['lock_error']['role'] = esc_html( $display_name_role['role'] );
}
return $response;
}
add_filter( 'heartbeat_received', 'post_lock_add_display_name_role', 11, 3 );
/**
* Get Display Name / Role text from user.
*
* @param int $user_id User ID.
*
* @return array|false Display name and role of user, false if user not found.
*/
function post_lock_get_display_name_role( $user_id ) {
$user = get_userdata( $user_id );
if ( ! $user ) {
return false;
}
$roles = array();
// Loop through the roles and convert them to labels.
foreach ( $user->roles as $role ) {
$roles[] = ucwords( str_replace( array( '-', '_' ), ' ', $role ) );
}
// Combine multiple roles into one string.
$role_text = implode( ', ', $roles );
$display_name_role = array(
'display_name' => $user->display_name,
'role' => $role_text,
);
return $display_name_role;
}
/**
* Get notice text if a post is locked.
*
* @param int $post_id Post ID.
*
* @return string|false Notice text if post is locked, false if it is not locked.
*/
function post_lock_get_display_name_role_from_post( $post_id ) {
/**
* Check if the post is locked.
*
* @param int|string $post_id Post ID.
*
* @return string|false User ID who is currently editing or false if the post is not locked.
*/
$user_id = wp_check_post_lock( $post_id );
if ( ! $user_id ) {
return false;
}
return post_lock_get_display_name_role( $user_id );
}
/**
* Render the post locking frontend notice.
*
* @param int $post_id Post ID.
*
* @return bool Whether the post is currenty locked by another user.
*/
function post_lock_frontend_notice( $post_id ) {
wp_enqueue_script( 'heartbeat', '', array(), false, true );
// Include necessary files.
require_once ABSPATH . 'wp-admin/includes/post.php';
require_once ABSPATH . 'wp-admin/includes/misc.php';
require_once ABSPATH . 'wp-admin/includes/admin-filters.php';
// Get the display name / role for post lock (if there is one).
$display_name_role = post_lock_get_display_name_role_from_post( $post_id );
$hidden = 'hidden';
$is_locked = false;
$active_post_lock = array();
if ( false !== $display_name_role ) {
$hidden = '';
$is_locked = true;
} else {
$display_name_role = array(
'display_name' => '',
'role' => '',
);
if ( is_user_logged_in() ) {
$active_post_lock = wp_set_post_lock( $post_id );
}
}
?>
<div id="post-lock-dialog" class="<?php echo esc_attr( $hidden ); ?>">
<?php
printf(
'<span class="user-display-name">%1$s</span> (<span class="user-role">%2$s</span>) is editing.',
esc_html( $display_name_role['display_name'] ),
esc_html( $display_name_role['role'] )
);
?>
</div>
<input type="hidden" id="_wpnonce" value="<?php echo esc_attr( wp_create_nonce( 'heartbeat-nonce' ) ); ?>" />
<input type="hidden" id="post_ID" value="<?php echo esc_attr( $post_id ); ?>" />
<input type="hidden" id="active_post_lock" value="<?php echo esc_attr( implode( ':', $active_post_lock ) ); ?>" />
<?php
return $is_locked;
}
/***********************************************
* This CSS is needed in the theme because of how
* the notice renders. The notice element is
* always on the page, it is updated and shown/
* hidden depending on the circumstance.
***********************************************/
.hidden {
display: none;
}
/***********************************************
* This JS handles all of the heartbeat API calls
* and post locking integration.
***********************************************/
(function($) {
// Check every 15 seconds for post lock changes.
var heartbeat_interval = 15;
$(document).on( 'heartbeat-send.refresh-lock', function( e, data ) {
/**
* Heartbeat locks.
*
* Used to lock editing of an object by only one user at a time.
*
* When the user does not send a heartbeat in a heartbeat-time
* the user is no longer editing and another user can start editing.
*/
var lock = $('#active_post_lock').val(),
post_id = $('#post_ID').val(),
send = {};
if ( ! post_id || ! $('#post-lock-dialog').length ) {
return;
}
send.post_id = post_id;
if ( lock ) {
send.lock = lock;
}
data['wp-refresh-post-lock'] = send;
}).on( 'heartbeat-tick.refresh-lock', function( e, data ) {
// Post locks: update the lock string or show the dialog if somebody has taken over editing.
var received, wrap;
if ( data['wp-refresh-post-lock'] ) {
received = data['wp-refresh-post-lock'];
if ( received.lock_error ) {
// Show "editing taken over" message.
wrap = $('#post-lock-dialog');
if ( wrap.length ) {
// Show wrap if it is hidden.
if ( wrap.hasClass('hidden') ) {
wrap.removeClass( 'hidden' );
}
// Set user fields.
$('.user-display-name', wrap).text( received.lock_error.display_name );
$('.user-role', wrap).text( received.lock_error.role );
}
} else if ( received.new_lock ) {
// Save current active lock.
$('#active_post_lock').val( received.new_lock );
}
}
}).ready( function() {
// Set the heartbeat interval.
if ( typeof wp !== 'undefined' && wp.heartbeat ) {
wp.heartbeat.interval( heartbeat_interval );
}
});
}(jQuery));
<?php get_header(); ?>
<div class="wrap">
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">
<!--********************************************
* Start of Heartbeat API example code.
*********************************************-->
<?php
$is_locked = post_lock_frontend_notice( get_the_ID() );
if ( ! $is_locked ) {
// Show an edit form.
}
?>
<!--********************************************
* End of Heartbeat API example code.
*********************************************-->
</main><!-- #main -->
</div><!-- #primary -->
<?php get_sidebar(); ?>
</div><!-- .wrap -->
<?php
get_footer();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment