Come disabilitare il "Post Lock/Edit Lock"?

26 ott 2013, 17:22:05
Visualizzazioni: 18.2K
Voti: 16

Vorrei disabilitare questa funzionalità solo per un Post Type specifico, dato che non è rilevante se un altro utente sta modificando lo stesso contenuto (l'area principale di modifica utilizza Ajax e gli utenti non admin possono solo visualizzarla).

Blocco di modifica in WordPress

Ho esaminato le funzioni core ma non ho trovato un punto di ingresso. Dalla funzione wp_set_post_lock presumo che dovrei intercettare il get_post_meta, ma esiste un modo ufficiale per farlo?

Inoltre c'è un secondo blocco che non sembra essere influenzato dal filtro wp_check_post_lock_window (come mostrato da birgire, qui in una risposta). Ho provato remove_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10, 3 ); in diversi punti ma continua a funzionare senza rispettare il remove_filter.

Secondo meccanismo di blocco

1
Commenti

Ho aggiunto una precisazione riguardo ai motivi, e mi viene in mente una soluzione: mostrare questo contenuto agli utenti non amministratori in un'altra schermata. Ma sarebbe comunque utile conoscere un hook appropriato per post_lock.

brasofilo brasofilo
26 ott 2013 18:32:24
Tutte le risposte alla domanda 4
3
11

Come aggiunta alla risposta di @birgire

Scoperte

register_post_type() permette di registrare un supporto per il tipo di post, che può anche essere aggiunto successivamente utilizzando add_post_type_support(). E questo può essere verificato anche più tardi usando l'onnipotente post_type_supports( $cpt, $feat ).

Un mini plugin generico che aggiunge una nuova funzionalità

Ora il seguente (mu-)plugin verifica un nuovo tipo di supporto per il post type che disabilita la funzionalità di blocco del post. Si chiama 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' );
}

Un plugin per CPT

Quindi possiamo facilmente aggiungere mini plugin per disabilitare il supporto del post type per i nostri o per plugin di terze parti (risparmiando larghezza di banda e dimensione del DB nella tabella user meta):

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

Non appena il secondo plugin viene attivato, il nostro post type beer non avrà più il blocco del post. Questo dovrebbe funzionare bene ed è facilmente reversibile attraverso la schermata di amministrazione dei plugin.

Disabilitare l'API heartbeat

Estendendo il plugin per disabilitare anche l'API heartbeat:

<?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 );
        } );
    }
}
27 ott 2013 06:16:07
Commenti

Questa è una soluzione davvero elegante, come gestiresti la parte relativa a admin-ajax.php (domanda aggiornata e risposta aggiunta)?

brasofilo brasofilo
27 ott 2013 09:39:27

@brasofilo Ho aggiunto una modifica per disabilitare completamente l'API Heartbeat. Non sono sicuro di come tu voglia gestirlo, ma puoi comunque eseguire l'API heartbeat nei plugin utilizzando wp.heartbeat.start(); nel tuo JavaScript.

kaiser kaiser
27 ott 2013 12:34:11

è un'ottima idea usare post_type_supports per gestire questo aspetto per ogni custom post type, vorrei poterti dare più upvote ;-)

birgire birgire
27 ott 2013 13:12:18
2

Per rimuovere la finestra popup di edit-lock, puoi provare:

add_filter( 'wp_check_post_lock_window', '__return_zero' );

Non sono sicuro che sia il modo migliore, ma ho controllato il codice sorgente di wp_check_post_lock() e abbiamo queste righe:

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

L'idea è modificare $time_window in modo che la condizione if restituisca false.

Aggiornamento:

Per applicarlo alla schermata edit.php, con un custom post type come beer ad esempio:

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

Poi possiamo aggiungere:

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

per rimuoverlo anche dalla schermata post.php.

Approfondimento...

La funzione _admin_notice_post_locked() è definita appena sotto la funzione wp_set_post_lock(). Contiene queste righe:

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

quindi si può provare anche il filtro show_post_locked_dialog:

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;
}
26 ott 2013 19:34:51
Commenti

Non sarebbe più semplice usare direttamente __return_false() come primo controllo per $time, dato che il primo controllo si riduce a un bool TRUE?

kaiser kaiser
27 ott 2013 06:03:49

ok forse, ma non sono sicuro di come impostare $time a false quindi ho optato per $time_window invece...

birgire birgire
27 ott 2013 14:34:47
8

La combinazione finale che ho finito per utilizzare è

# Gestisce il messaggio "Qualcun altro sta modificando questo post"
add_action( 'load-edit.php', function()
{
    if( 'beer' === get_current_screen()->post_type )
        add_filter( 'wp_check_post_lock_window', '__return_false' );
});

# Gestisce post.php e il messaggio "L'utente ha preso il controllo"
add_filter( 'show_post_locked_dialog', function( $bool, $post, $user )
{
    if( 'beer' === $post->post_type )
        return false;
    return $bool;
}, 
10, 3 );

ma se qualcuno ha un altro approccio, mi piacerebbe sentirlo, dato che non capisco perfettamente l'intero panorama dei filtri disponibili.

In precedenza, usando load-edit.php + load-post.php, dovevo rimuovere il filtro wp_refresh_post_lock con:

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

ma caricarlo ad ogni admin_init non sembra una buona idea.

27 ott 2013 09:36:50
Commenti

Per favore usa get_current_screen()->post_type invece. Ecco un bel plugin chiamato Current Admin Info per aiutarti a recuperare queste informazioni.

kaiser kaiser
27 ott 2013 12:36:13

@kaiser, la mia intenzione qui è bloccare il heartbeat per Ajax, forse dovrei aggiungere un controllo DOING_AJAX... E come ho capito, Ajax non ha global $current_screen (restituito da get_current_screen()).

brasofilo brasofilo
27 ott 2013 12:46:36

Ah, forse. Non lo so al momento. Comunque, c'è wp_is_autosave() - non sono sicuro se si applica a una di queste azioni.

kaiser kaiser
27 ott 2013 13:11:41

Mi chiedo se add_filter( 'show_post_locked_dialog', '__return_false' );, dalla funzione _admin_notice_post_locked(), possa essere d'aiuto?

birgire birgire
27 ott 2013 14:37:59

@birgire, no, non ha funzionato. Penso che non sia possibile fermare wp_ajax_heartbeat() (wp-admin/includes/ajax-actions.php) usando la catena load-$hook -> get_current_something(). . . . . Inoltre, ci sono 3 hook in quella funzione, ma non riesco a fermare il "battito" utilizzandoli (e hanno $screen_id, che corrisponde al post type.

brasofilo brasofilo
27 ott 2013 14:59:55

Sembra come cercare di provocare un infarto a WordPress... ;-) Ma funziona se aggiungi/rimuovi i filtri direttamente (quindi per tutti i CPT?)

birgire birgire
27 ott 2013 15:11:55

@birgire, sì signore, quello è quello che ferma il battito :) Abbiamo dato un infarto al vecchio WP! Il filtro accetta anche $post e $user come argomenti, è stato il colpo di grazia. Per favore, aggiungilo alla tua Risposta.

brasofilo brasofilo
27 ott 2013 15:26:17

ok perfetto, povero vecchio WP ;-)

birgire birgire
27 ott 2013 16:07:10
Mostra i restanti 3 commenti
0

Ecco la soluzione finale che funziona per me:

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

    // Disabilita il blocco per pagine, articoli e alcuni tipi di post personalizzati
    $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');
26 apr 2015 18:23:01