Si necesitas crear un plugin para WordPress o un código a medida de algún tipo que entre otras labores, inserte entradas (o páginas o productos) de forma programática, seguramente conozcas la función wp_insert_post. Esta instrucción permite dar de alta cualquier post en WordPress usando su API. Un uso básico sería algo así:
// creamos un array con datos del post que vamos a entrar $my_post = array( 'post_title' => wp_strip_all_tags( $_POST['tituko'] ), 'post_content' => $_POST['contenido'], 'post_status' => 'publish', 'post_author' => 1, ); // ejecutamos la instrucción para crear el post y guardarlo en la base de datos wp_insert_post( $my_post );
A priori, como veis, además de sencilla es una función que parece que no tiene mayor complejidad: no maneja fechas, ni a priori hay bloqueos, ni cosas «raras» que puedan fastidiarte. Es una función que guardar una entrada, una página, un producto o cualquier otro custom post type que estés usando en la base de datos. ¿Qué problema iba a haber? Pues a veces lo hay
Bucle infinito con wp_insert_post
Este bucle lo veréis de diferentes formas:
- el sistema al ejecutar wp_insert_post se queda en blanco tras un rato
- ves un error 500 por exceso del tiempo de ejecución
- o simplemente no se ejecuta tras un rato
¿Por qué ocurre? El fondo del asunto está en que esta instrucción además de dar de alta los datos en la base de datos, ejecuta, como todas las funciones de la API de WordPress, una serie de hooks para que otros plugins puedan hacer una tarea cuando se está dando esta entrada de alta. De todos los hooks que se ejecutan, hay uno de tipo action, llamado save_post que todos los que desarrollamos con WordPress en algún momento usamos. Total, al llamar a save_post puede que entres en una dinámica sin fin, un bucle, donde save_post no pare de ejecutar algo que vuelva a llamarlo. Es parecido el error al problema de hacer un wp_insert_post en un save_post. Anoche me ocurrió programando un panel gestor de entradas multi-idioma y hoy quería contaros el problema y la solución (porque no está muy documentado en la red).
Solución: desactivar el hook que crea el bucle de forma temporal
Lo primero es ver qué hook está creando el problema. Una forma sencilla de ver las funciones y métodos asociadas a un hook sería la siguiente:
global $wp_filter; echo '<pre>'; var_dump( $wp_filter['save_post'] ); echo '</pre>';
Si tienes claro cuál es el hook que te esté creando el problema (puedes hacerlo activando/desactivando plugins y viendo qué hooks se eliminan cuando desaparece el problema), puedes hacer directamente una desactivación selectiva:
remove_action( 'save_post', 'funcion_problematica' ); wp_insert_post( $my_post ); add_action( 'save_post', 'funcion_problematica' );
O si no tienes claro qué hook es y:
- El script que usas es puntual y no va a afectar al resto de tu sitio
- Y sabes arreglar posibles defectos de desactivar hooks (de los que sí son buenos) como por ejemplo el de poner la información de idioma por defecto en WPML
Puedes desactivar todos completamente:
remove_all_actions( 'save_post' ); wp_insert_post( $my_post );
Si sois desarrolladores con WordPress seguro que se os habrá dado esta y otras mil circunstancias.