Jak wyłączyć „Blokadę post / Edycja blokady”?

16

Chcę to wyłączyć tylko dla jednego typu postu, ponieważ tak naprawdę nie ma znaczenia, czy jest edytowany przez innego użytkownika (główny obszar edycji treści jest Ajaxified, a nie-administratorzy mogą to zobaczyć).

wprowadź opis zdjęcia tutaj

Spojrzałem na podstawowe funkcje, ale nie mogłem znaleźć punktu wejścia. Z funkcji wp_set_post_lockdomyślam się, że musiałbym przechwycić get_post_meta, ale czy istnieje oficjalny sposób, aby to zrobić?

Jest też druga blokada , na którą filtr nie wydaje się mieć wpływu wp_check_post_lock_window( jak pokazuje birgire , tutaj w odpowiedzi). Próbowałem remove_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10, 3 );w różnych momentach, ale wciąż bije bez szacunku remove_filter.

wprowadź opis zdjęcia tutaj

brasofilo
źródło
1
Dodałem wyjaśnienie motywów i przywołuje to na myśl rozwiązanie: pokazywanie tej treści osobom niebędącym administratorami na innym ekranie. Byłoby jednak miło poznać właściwy haczyk do post_locktego.
brasofilo

Odpowiedzi:

10

Jako dodatek do odpowiedzi @birgire

Wyniki

register_post_type()pozwala zarejestrować wsparcie typu post, co równie dobrze można zrobić późniejadd_post_type_support() . I to można sprawdzić nawet później, używając wszystkich potężnych post_type_supports( $cpt, $feat ).

Ogólna mini wtyczka, która dodaje nową funkcję

Teraz następująca wtyczka (mu-) sprawdza, czy istnieje nowy rodzaj wsparcia typu post, który wyłącza funkcję post lock. To się nazywa 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' );
}

Jedna wtyczka na CPT

Następnie możemy łatwo dodać mini wtyczki, aby wyłączyć obsługę typu post dla wtyczek własnych lub zewnętrznych (oszczędzając nam trochę przepustowości i rozmiaru bazy danych w meta tabeli użytkownika):

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

Gdy tylko druga wtyczka zostanie aktywowana, nasz typ postu piwa nie ma już blokady postu. Powinno to działać dobrze i można je łatwo przywrócić na ekranie administratora wtyczek.

Wyłączanie interfejsu API pulsu

Rozszerzenie wtyczki w celu wyłączenia interfejsu API funkcjibeekbeat:

<?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 );
        } );
    }
}
kajzer
źródło
To naprawdę eleganckie rozwiązanie, jak poradziłbyś sobie z admin-ajax.phpczęścią (zaktualizowano Q i dodano A)?
brasofilo
@brasofilo Dodałem zmianę, aby całkowicie wyłączyć interfejs API pulsu. Nie wiesz, jak chcesz to obsłużyć, ale nadal możesz uruchomić interfejs API pulsu we wtyczkach, używając wp.heartbeat.start();w swoim JavaScript.
kaiser
2
to świetny pomysł, post_type_supportsaby obsłużyć to dla każdego niestandardowego typu posta, chciałbym móc dać więcej głosów pozytywnych ;-)
birgire
7

Aby usunąć wyskakujące okno blokady edycji , możesz spróbować:

add_filter( 'wp_check_post_lock_window', '__return_zero' );

Nie jestem pewien, czy tak jest, ale sprawdziłem źródło wp_check_post_lock() i mamy następujące linie:

...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...

więc pomysł polega na zmianie, $time_windowwięc ifwarunek jest false.

Aktualizacja:

Aby zastosować to na edit.phpekranie, beerna przykład z niestandardowym typem posta :

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

A następnie możemy dodać:

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

aby usunąć go również z post.phpekranu.

Więcej kopania ...

Funkcja _admin_notice_post_locked()jest zdefiniowana tuż pod wp_set_post_lock()funkcją. Zawiera następujące linie:

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

więc można również wypróbować show_post_locked_dialogfiltr:

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;
}
birgire
źródło
Czy nie byłoby łatwiej użyć __return_false()zamiast tego jako pierwszego czeku $timesumującego się jako bool TRUE?
kaiser
ok może, ale nie jestem pewien, jak ustawić $timesię falsewięc poszedłem do $time_windowzamiast ...
birgire
3

Ostatnią kombinacją, której użyłem, jest

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

ale jeśli ktoś ma inne ujęcie, chciałbym usłyszeć, ponieważ tak naprawdę nie rozumiem całego obrazu dostępnych filtrów.

Wcześniej za pomocą load-edit.php+ load-post.phpmusiałem usunąć filtr za wp_refresh_post_lockpomocą:

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

ale ładowanie za każdym razem admin_initnie wydaje się dobrym pomysłem.

brasofilo
źródło
Użyj get_current_screen()->post_typezamiast tego. Oto ładna wtyczka o nazwie Current Admin Info, która pomaga w wyszukiwaniu takich informacji.
kaiser
1
@kaiser, moim zamiarem tutaj jest zablokowanie bicia serca dla Ajax, może powinienem dodać trochę DOING_AJAXczeku ... I jak rozumiem, Ajax nie ma global $current_screen(zwrócone przez get_current_screen()).
brasofilo
Ach, może. W tej chwili nie wiem. Przy okazji, nie wp_is_autosave()ma pewności, czy to odpowiada którejkolwiek z tych akcji.
kaiser
Zastanawiam się, czy add_filter( 'show_post_locked_dialog', '__return_false' );z funkcji _admin_notice_post_locked()jest pomocna?
birgire
@ Birgire, nie, nie działało. Myślę, że nie można zatrzymać wp_ajax_heartbeat()(wp-admin / include / ajax-Actions.php) za pomocą łańcucha load-$hook-> get_current_something(). . . . . Ponadto w tej funkcji są 3 zaczepy, ale nie jestem w stanie zatrzymać ich używania (i mają takie $screen_id, które pasują do typu postu.
brasofilo,
3

Oto ostatnie rozwiązanie, które działa dla mnie. :

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');
Trubisza
źródło