¿Por qué el 'do_shortcode' de un plugin podría no funcionar en una solicitud AJAX?
tl;dr: El shortcode de Contact Form 7 no funciona en una solicitud AJAX cuando se llama con do_shortcode
functions.php
add_action('wp_ajax_ps_get_survey_form', 'ps_get_survey_form');
add_action('wp_ajax_nopriv_ps_get_survey_form', 'ps_get_survey_form');
function ps_get_survey_form() {
echo do_shortcode( '[contact-form-7 id="397" title="Formulario de contacto 1"]' );
die();
}
script.js
jQuery(document).ready(function($){
$('#survey-modal').fancybox({
href: ajaxurl,
ajax: {
type : "POST",
data : {action: 'ps_get_survey_form'}
}
});
});
Sin embargo,
echo do_shortcode( '[contact-form-7 id="397" title="Formulario de contacto 1"]' )
devuelve el propio string del shortcode. Funciona bien si lo coloco en una plantilla.
Por más que lo intente (cosas absurdas como envolverlo en un post/aplicar el filtro the_content, activar manualmente varias acciones a las que CF7 se engancha, etc) se niega a convertirse en un formulario.
¿Cómo puedo depurar esto?
EDIT
@Kaiser sugiere sensatamente que no tengo acceso a do_shortcode. Intenté comprobarlo, con el siguiente resultado:
function ps_get_survey_form() {
//include( ABSPATH . 'wp-includes/shortcodes.php' );
//Causa error fatal: no se puede redeclarar add_shortcode
if ( function_exists( 'do_shortcode ' ) ) {
echo "do_shortcode existe";
} else {
echo "do_shortcode no existe"; // esto es lo que se muestra
}
do_shortcode( 'foo' ); // esto falla silenciosamente, aunque aparentemente la función no está definida
//foo(); // Causa error fatal como se esperaba
//echo do_shortcode( '[contact-form-7 id="397" title="formulario de contacto 1"]' );
die();
}

WP Ajax ejecuta llamadas tanto públicas como cerradas a través de admin.php
. Esto significa que no tienes acceso a todo el entorno de WordPress, como do_shortcode()
, que se encuentra dentro de /wp-includes/shortcodes.php
.
Aún así, se puede solucionar (también para oEmbed). Mira el siguiente ejemplo que podrías usar en tu callback de AJAX para habilitar tanto los manejadores de oEmbed como los manejadores de shortcodes para una propiedad \WP_Post::post_content
.
/** \WP_Post $post */
$post = get_post();
/** @var \WP_Embed $wp_embed */
global $wp_embed;
$wp_embed->post_ID = $post->ID;
// Shortcode [embed]
$wp_embed->run_shortcode( $post->post_content );
// Enlaces simples en su propia línea
$wp_embed->autoembed( $post->post_content );
// Habilitar shortcodes
do_shortcode( $post->post_content );
PROTip: Nunca llames directamente echo do_shortcode( '[some-short-code arg="foo"]' );
. Un shortcode es solo un marcador de posición para el editor. Todos los shortcodes deben tener un callback asociado. Usa el callback en su lugar. Esto te ahorra ejecutar costosas verificaciones con Regex.

La solución es evitar las restricciones de admin-ajax manejándolo tú mismo, como sugiere @OneTrickPony.
add_action( 'init', function() {
ps_register_shortcode_ajax( 'ps_get_survey_form', 'ps_get_survey_form' );
} );
function ps_register_shortcode_ajax( $callable, $action ) {
if ( empty( $_POST['action'] ) || $_POST['action'] != $action )
return;
call_user_func( $callable );
}
function ps_get_survey_form() {
echo do_shortcode( '[contact-form-7 id="397" title="formulario de contacto 1"]' );
die();
}
