¿Por qué el 'do_shortcode' de un plugin podría no funcionar en una solicitud AJAX?

25 may 2012, 20:02:18
Vistas: 19K
Votos: 9

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

¿Quizás porque la función del shortcode aún no se ha registrado en ese momento?

onetrickpony onetrickpony
25 may 2012 20:10:15

@OneTrickPony - Estoy de acuerdo, eso parece probable. La pregunta es, ¿cómo puedo hacer que se registre (si entiendes a lo que me refiero)?

djb djb
26 may 2012 13:56:05

Simplemente maneja la solicitud ajax tú mismo en la acción "wp" o "init". El admin-ajax de WP fue diseñado para usarse en el área de administración de todos modos

onetrickpony onetrickpony
26 may 2012 15:05:00

@OneTrickPony, gracias. eso funciona. publicaré el código funcional arriba para la posteridad.

djb djb
26 may 2012 16:54:57

La última vez que revisé Contact Form 7, no usaban la API de shortcode incorporada, optando por crear la suya propia. Vale la pena echarle un vistazo.

chrisguitarguy chrisguitarguy
31 jul 2012 21:47:41

No sé qué está pasando en la llamada ajax. Porque si intento function_exists como arriba para get_option() así if(function_exists('get_option')){echo 'exist';}else{echo 'not exist';} muestra not exist pero cuando simplemente muestro por ejemplo el nombre del blog get_option('blogname'); está imprimiendo el nombre del blog. Puedo verlo en la respuesta ajax. Si la función no existe entonces ¿cómo puede funcionar? do_shortcode() también funciona cuando intento obtener el título del sitio. pero cuando intento obtener el título del post no se imprime. ¿Cuál podría ser el problema? @onetrickpony

sun sun
27 may 2014 16:04:35

@sun Por favor lee [pregunta] y formula tu propia pregunta.

kaiser kaiser
27 may 2014 16:07:44
Mostrar los 2 comentarios restantes
Todas las respuestas a la pregunta 2
2

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.

25 may 2012 21:28:18
Comentarios

@djb Por favor, agrega tu solución no en la pregunta, sino como una nueva respuesta y márcala luego como solución. Gracias.

kaiser kaiser
27 may 2012 18:35:24

Lo haré. ¿Puedes arrojar algo de luz sobre el misterio de function_exists?

djb djb
28 may 2012 12:50:30
0

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(); 
} 
28 may 2012 12:51:37