16

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

1
  • 1
    I've added a clarification about the motives, and it brings a solution to mind: showing this content to non-admins in another screen. But would be nice to know a proper hook to post_lock nonetheless.
    – brasofilo
    Oct 26, 2013 at 15:32

4 Answers 4

11

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 );
        } );
    }
}
3
  • This is a really classy solution, how would you handle the admin-ajax.php part (Q updated and A added)?
    – brasofilo
    Oct 27, 2013 at 7:39
  • @brasofilo I added an edit to disable the Heartbeat API completely. Not sure how you want to handle that, but you can still run the heartbeat API in plugins by using wp.heartbeat.start(); in your JavaScript.
    – kaiser
    Oct 27, 2013 at 10:34
  • 3
    it's great idea using the post_type_supports to handle this for each custom post type, I wish I could give you more upvotes ;-)
    – birgire
    Oct 27, 2013 at 11:12
7

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;
}
2
  • Wouldn't it be easier to just use __return_false() instead as the first check for $time just sums up as a bool TRUE?
    – kaiser
    Oct 27, 2013 at 4:03
  • ok maybe, but I'm not sure how to set $time to false so I went for $time_window instead ...
    – birgire
    Oct 27, 2013 at 12:34
3

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.

8
  • Please use get_current_screen()->post_type instead. Here's a nice plugin called Current Admin Info to assist you with retrieving such info.
    – kaiser
    Oct 27, 2013 at 10:36
  • 1
    @kaiser, my intention here is to block the heartbeat for Ajax, maybe I should add some DOING_AJAX check... And as I understand it, Ajax has no global $current_screen (returned by get_current_screen()).
    – brasofilo
    Oct 27, 2013 at 10:46
  • Ah, maybe. Dunno at the moment. Btw, there's wp_is_autosave() - not sure if that accounts to any of those actions.
    – kaiser
    Oct 27, 2013 at 11:11
  • I wonder if add_filter( 'show_post_locked_dialog', '__return_false' );, from the function _admin_notice_post_locked(), is of any help?
    – birgire
    Oct 27, 2013 at 12:37
  • @birgire, nope, didn't work. I'm thinking that's not possible to stop wp_ajax_heartbeat() (wp-admin/includes/ajax-actions.php) using the chain load-$hook -> get_current_something(). . . . . Also, there are 3 hooks in that function, but I'm not being able to stop the beat using them (and they have $screen_id, which matches the post type.
    – brasofilo
    Oct 27, 2013 at 12:59
3

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');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.