How to disable the “Post Lock/Edit Lock”?

I want to disable this just for one Post Type, as it doesn’t really matters if there’s another user editing it (the main content editing area is Ajaxified and non-admins can only see that).

enter image description here

I looked at the core functions but couldn’t find an entry point. From the function wp_set_post_lock I’m guessing that I’d have to intercept the get_post_meta, but is there an official way to do it?

And there’s a second lock that doesn’t seem to be affected by the filter wp_check_post_lock_window (as shown by birgire, here in an Answer). I’ve tried remove_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10, 3 ); at various points but it keeps beating without respecting remove_filter.

enter image description here

Solutions Collecting From Web of "How to disable the “Post Lock/Edit Lock”?"

As an addition to @birgire answer…

Findings

register_post_type() allows to register a post type support, which can as well be done later on using add_post_type_support(). And that can get checked against even later using the all mighty post_type_supports( $cpt, $feat ).

A general mini plugin that adds a new feature

Now the following (mu-)plugin checks for a new kind of post type support that disables the post lock feature. It’s named disabled_post_lock.

<?php
defined( 'ABSPATH' );
/** Plugin Name: (#120179) Maybe Disable Post Type Support */

add_action( 'load-edit.php', 'wpse120179MaybeDisablePostLock' );
function wpse120179MaybeDisablePostLock()
{
    if ( post_type_supports( get_current_screen()->post_type, 'disabled_post_lock' ) )
        add_filter( 'wp_check_post_lock_window', '__return_false' );
}

One plugin per CPT

Then we can easily add mini plugins to disable post type support for our own or third party plugins (saving us some bandwidth and DB size in the user meta table):

<?php
defined( 'ABSPATH' );
/** Plugin Name: (#120179) Disable Post Type Support for "Beer" Posts */

add_action( 'init', function()
{
    add_post_type_support( 'beer', 'disabled_post_lock' );
} );

As soon as the second plugin is activated our beer post type has no more post lock. This should work nice and is easily revertable through the plugins admin screen.

Disabling the heartbeat API

Extending the plugin to disable the hearbeat API as well:

<?php
defined( 'ABSPATH' );
/** Plugin Name: (#120179) Maybe Disable Post Type Support */

add_action( 'load-edit.php', 'wpse120179MaybeDisablePostLock' );
function wpse120179MaybeDisablePostLock()
{
    if ( post_type_supports( get_current_screen()->post_type, 'disabled_post_lock' ) )
    {
        add_filter( 'wp_check_post_lock_window', '__return_false' );
        add_filter( 'heartbeat_settings', function( $settings )
        {
            return wp_parse_args( [ 'autostart' => false ], $settings );
        } );
    }
}

To remove the edit-lock popup window, you could try:

add_filter( 'wp_check_post_lock_window', '__return_zero' );

I’m not sure if this is the way to go, but I checked the source of wp_check_post_lock()
and there we have these lines:

...cut...

$time_window = apply_filters( 'wp_check_post_lock_window', 120 );

if ( $time && $time > time() - $time_window && $user != get_current_user_id() )
    return $user;
return false;

...cut...

so the idea is to change $time_window so the if condition is false.

Update:

To apply this on the edit.php screen, with the custom post type beer for example:

function wpse_120179()
{
    if( 'beer' === get_current_screen()->post_type )
        add_filter( 'wp_check_post_lock_window', '__return_zero' );

}
add_action( 'load-edit.php', 'wpse_120179' );

And then we can add:

add_action( 'load-post.php', 'wpse_120179' );

to remove it for the post.php screen as well.

More digging …

The function _admin_notice_post_locked() is defined just below the wp_set_post_lock() function. It contains these lines:

...cut...
if ( ! apply_filters( 'show_post_locked_dialog', true, $post, $user ) )
    return;
...cut...

so one can also try the show_post_locked_dialog filter:

add_filter( 'show_post_locked_dialog', 'wpse_120179_close_dialog', 99, 3 );

function wpse_120179_close_dialog( $show, $post, $user )
{
    if( 'beer' === $post->post_type )
        return FALSE;

    return $show;
}

The final combination I’ve ended using is

# Takes care of the message "Someone else is editing this"
add_action( 'load-edit.php', function()
{
    if( 'beer' === get_current_screen()->post_type )
        add_filter( 'wp_check_post_lock_window', '__return_false' );
});

# Takes care of post.php and the "User has taken over" message
add_filter( 'show_post_locked_dialog', function( $bool, $post, $user )
{
    if( 'beer' === $post->post_type )
        return false;
    return $bool;
}, 
10, 3 );

but if anyone has another take, I’d love to hear, as I’m not really understanding the whole picture of filters available.

Previously, using load-edit.php + load-post.php, I had to remove
the filter wp_refresh_post_lock with:

add_action( 'admin_init', function()
{
    if( !defined('DOING_AJAX') || !isset( $_POST['screen_id'] ) || 'beer' !== $_POST['screen_id'] )
        return;

    remove_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10 );
});

but loading at every admin_init doesn’t seem a good idea.

Here is the final solution that works for me. :

function my_remove_post_locked() {
    $current_post_type = get_current_screen()->post_type;   

    // Disable locking for page, post and some custom post type
    $post_types_arr = array(
        'page',
        'post',
        'custom_post_type'
    );

    if(in_array($current_post_type, $post_types_arr)) {
        add_filter( 'show_post_locked_dialog', '__return_false' );
        add_filter( 'wp_check_post_lock_window', '__return_false' );
        wp_deregister_script('heartbeat');
    }
}

add_action('load-edit.php', 'my_remove_post_locked');
add_action('load-post.php', 'my_remove_post_locked');