Perché il 'do_shortcode' di un plugin potrebbe non funzionare in una richiesta AJAX?
tl;dr: Il shortcode di Contact Form 7 non funziona in una richiesta AJAX quando chiamato 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="Contact form 1"]' );
die();
}
script.js
jQuery(document).ready(function($){
$('#survey-modal').fancybox({
href: ajaxurl,
ajax: {
type : "POST",
data : {action: 'ps_get_survey_form'}
}
});
});
Tuttavia,
echo do_shortcode( '[contact-form-7 id="397" title="Contact form 1"]' )
restituisce la stringa del shortcode stessa. Funziona correttamente se inserito in un template.
Per quanto ci abbia provato (cose assurde come avvolgerlo in un post/applicare il filtro the_content, attivare manualmente varie azioni a cui CF7 si aggancia, ecc.) si rifiuta di trasformarsi in un form.
Come posso debuggar questo problema?
EDIT
@Kaiser suggerisce saggiamente che potrei non avere accesso a do_shortcode. Ho provato a verificarlo, con il seguente risultato:
function ps_get_survey_form() {
//include( ABSPATH . 'wp-includes/shortcodes.php' );
//Causa errore fatale: non è possibile ridefinire add_shortcode
if ( function_exists( 'do_shortcode ' ) ) {
echo "do_shortcode esiste";
} else {
echo "do_shortcode non esiste"; // viene stampato questo
}
do_shortcode( 'foo' ); // fallisce silenziosamente, anche se apparentemente la funzione non è stata definita
//foo(); // Causa errore fatale come previsto
//echo do_shortcode( '[contact-form-7 id="397" title="contact form 1"]' );
die();
}

WP Ajax esegue chiamate sia pubbliche che private tramite admin.php
. Ciò significa che non hai accesso all'intero ambiente WordPress, come ad esempio do_shortcode()
, che si trova in /wp-includes/shortcodes.php
.
Esiste comunque una soluzione alternativa (e lo stesso vale per oEmbed). Ecco un esempio che puoi utilizzare nel tuo callback AJAX per abilitare sia i gestori oEmbed che i gestori di shortcode per la proprietà \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 );
// link semplici su una riga autonoma
$wp_embed->autoembed( $post->post_content );
// Abilita gli shortcode
do_shortcode( $post->post_content );
PROTip: Non chiamare mai direttamente echo do_shortcode( '[some-short-code arg="foo"]' );
. Uno shortcode è semplicemente un segnaposto per l'editor. Ogni shortcode deve avere un callback associato. Utilizza invece il callback. Questo ti evita di eseguire controlli Regex dispendiosi.

La soluzione è aggirare le restrizioni di admin-ajax gestendolo autonomamente, come suggerito da @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="contact form 1"]' );
die();
}
