Почему do_shortcode может не работать в AJAX запросе плагина?
Кратко: Шорткод Contact Form 7 не работает в AJAX запросе при вызове через 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'}
}
});
});
Однако,
echo do_shortcode( '[contact-form-7 id="397" title="Contact form 1"]' )
возвращает сам строковый шорткод. В шаблоне он работает нормально.
Что бы я ни пробовал (абсурдные вещи вроде оборачивания в пост/применения фильтра the_content, ручного вызова различных экшенов, которые использует CF7 и т.д.), он отказывается преобразовываться в форму.
Как это можно отладить?
ОБНОВЛЕНИЕ
@Kaiser разумно предположил, что у меня нет доступа к do_shortcode. Я попытался проверить это, получив следующий результат:
function ps_get_survey_form() {
//include( ABSPATH . 'wp-includes/shortcodes.php' );
//Вызывает фатальную ошибку: нельзя переобъявить add_shortcode
if ( function_exists( 'do_shortcode ' ) ) {
echo "do_shortcode существует";
} else {
echo "do_shortcode не существует"; // выводится это
}
do_shortcode( 'foo' ); // молча завершается ошибкой, хотя функция, по-видимому, не определена
//foo(); // Вызывает фатальную ошибку, как и ожидалось
//echo do_shortcode( '[contact-form-7 id="397" title="contact form 1"]' );
die();
}

WP Ajax выполняет как публичные, так и закрытые вызовы через admin.php
. Это означает, что у вас нет доступа ко всей среде WordPress, такой как do_shortcode()
, которая находится в /wp-includes/shortcodes.php
.
Это всё ещё можно обойти (а также для oEmbed). Смотрите следующий пример, который можно использовать в вашем AJAX-обработчике, чтобы включить как обработчики oEmbed, так и обработчики шорткодов для свойства \WP_Post::post_content
.
/** \WP_Post $post */
$post = get_post();
/** @var \WP_Embed $wp_embed */
global $wp_embed;
$wp_embed->post_ID = $post->ID;
// шорткод [embed]
$wp_embed->run_shortcode( $post->post_content );
// обычные ссылки на отдельной строке
$wp_embed->autoembed( $post->post_content );
// Включение шорткодов
do_shortcode( $post->post_content );
PRO Совет: Никогда не вызывайте echo do_shortcode( '[some-short-code arg="foo"]' );
напрямую. Шорткод — это просто заполнитель для редактора. Каждый шорткод должен иметь привязанный обработчик. Используйте обработчик напрямую. Это избавит вас от дорогостоящих проверок с помощью Regex.

Решение заключается в том, чтобы обойти ограничения admin-ajax, обрабатывая запросы самостоятельно, как предложил @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="Контактная форма 1"]' );
die();
}
