Cómo desactivar el "Bloqueo de publicación/Bloqueo de edición"
Quiero desactivar esto solo para un Tipo de Publicación específico, ya que no importa realmente si otro usuario lo está editando (el área principal de edición de contenido usa Ajax y los no-administradores solo pueden ver eso).
Revisé las funciones principales pero no encontré un punto de entrada. Por la función wp_set_post_lock
supongo que tendría que interceptar el get_post_meta
, pero ¿existe una forma oficial de hacerlo?
Además hay un segundo bloqueo que no parece verse afectado por el filtro wp_check_post_lock_window
(como mostró birgire, aquí en una Respuesta). Intenté usar remove_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10, 3 );
en varios puntos pero sigue funcionando sin respetar el remove_filter
.

Como complemento a la respuesta de @birgire…
Hallazgos
register_post_type()
permite registrar soporte para un tipo de post, lo cual también puede hacerse después usando add_post_type_support()
. Y esto puede verificarse más tarde usando el todopoderoso post_type_supports( $cpt, $feat )
.
Un mini plugin general que añade una nueva característica
El siguiente (mu-)plugin verifica un nuevo tipo de soporte para tipos de post que deshabilita la característica de bloqueo de posts. Se llama 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 por CPT
Luego podemos fácilmente añadir mini plugins para deshabilitar el soporte de tipos de post para nuestros propios plugins o de terceros (ahorrando ancho de banda y tamaño en la tabla de metadatos de usuario):
<?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' );
} );
Tan pronto como se active el segundo plugin, nuestro tipo de post beer ya no tendrá bloqueo de posts. Esto debería funcionar bien y es fácilmente reversible desde la pantalla de administración de plugins.
Deshabilitar la API Heartbeat
Extendiendo el plugin para también deshabilitar la 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 );
} );
}
}

Esta es una solución realmente elegante, ¿cómo manejarías la parte de admin-ajax.php
(Pregunta actualizada y Respuesta añadida)?

@brasofilo Añadí una edición para deshabilitar completamente la API Heartbeat. No estoy seguro de cómo quieres manejar eso, pero aún puedes ejecutar la API heartbeat en plugins usando wp.heartbeat.start();
en tu JavaScript.

Para eliminar la ventana emergente de edit-lock, podrías intentar:
add_filter( 'wp_check_post_lock_window', '__return_zero' );
No estoy seguro si es la mejor manera, pero revisé el código fuente de wp_check_post_lock()
y encontramos estas líneas:
...cortado...
$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;
...cortado...
así que la idea es cambiar $time_window
para que la condición if
sea false
.
Actualización:
Para aplicar esto en la pantalla de edit.php
, con el tipo de post personalizado beer
por ejemplo:
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' );
Y luego podemos añadir:
add_action( 'load-post.php', 'wpse_120179' );
para eliminarlo también en la pantalla de post.php
.
Profundizando más...
La función _admin_notice_post_locked()
está definida justo debajo de la función wp_set_post_lock()
. Contiene estas líneas:
...cortado...
if ( ! apply_filters( 'show_post_locked_dialog', true, $post, $user ) )
return;
...cortado...
así que también se puede probar el 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;
}

¿No sería más fácil simplemente usar __return_false()
en lugar de la primera verificación para $time
que básicamente se resume como un bool TRUE
?

La combinación final que terminé usando es
# Se encarga del mensaje "Alguien más está editando esto"
add_action( 'load-edit.php', function()
{
if( 'beer' === get_current_screen()->post_type )
add_filter( 'wp_check_post_lock_window', '__return_false' );
});
# Se encarga de post.php y el mensaje "El usuario ha tomado el control"
add_filter( 'show_post_locked_dialog', function( $bool, $post, $user )
{
if( 'beer' === $post->post_type )
return false;
return $bool;
},
10, 3 );
pero si alguien tiene otra perspectiva, me encantaría escucharla, ya que no termino de entender completamente el panorama completo de filtros disponibles.
Anteriormente, usando
load-edit.php
+load-post.php
, tuve que eliminar el filtrowp_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 ); });
pero cargarlo en cada
admin_init
no parece una buena idea.

Por favor usa get_current_screen()->post_type
en su lugar. Aquí hay un buen plugin llamado Current Admin Info para ayudarte a obtener esta información.

@kaiser, mi intención aquí es bloquear el heartbeat para Ajax, tal vez debería agregar alguna verificación DOING_AJAX
... Y según lo entiendo, Ajax no tiene global $current_screen
(devuelto por get_current_screen()
).

Ah, tal vez. No lo sé en este momento. Por cierto, existe wp_is_autosave()
- no estoy seguro si eso aplica a alguna de esas acciones.

Me pregunto si add_filter( 'show_post_locked_dialog', '__return_false' );
, de la función _admin_notice_post_locked()
, podría ser de ayuda.

@birgire, no, no funcionó. Estoy pensando que no es posible detener wp_ajax_heartbeat()
(wp-admin/includes/ajax-actions.php) usando la cadena load-$hook
-> get_current_something()
. . . . . Además, hay 3 hooks en esa función, pero no he logrado detener el latido usándolos (y tienen $screen_id
, que coincide con el tipo de publicación.

Se siente como intentar darle un ataque al corazón a WordPress... ;-) Pero ¿funciona si agregas/eliminas los filtros directamente (así que para todos los CPT?)

@birgire, sí señor, ese es el que detiene el ritmo :) ¡Le dimos un infarto al viejo WP! El filtro también toma $post
y $user
como argumentos, fue el clavo final. Por favor, agrégalo a tu Respuesta.

Aquí está la solución final que funciona para mí:
function my_remove_post_locked() {
$current_post_type = get_current_screen()->post_type;
// Deshabilitar bloqueo para página, entrada y algún tipo de contenido personalizado
$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');
