Почему do_shortcode может не работать в AJAX запросе плагина?

25 мая 2012 г., 20:02:18
Просмотры: 19K
Голосов: 9

Кратко: Шорткод 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();
}
7
Комментарии

Возможно, потому что функция шорткода ещё не была зарегистрирована на этот момент?

onetrickpony onetrickpony
25 мая 2012 г. 20:10:15

@OneTrickPony - Согласен, это кажется вероятным. Вопрос в том, как заставить её зарегистрироваться (если вы понимаете, о чём я)?

djb djb
26 мая 2012 г. 13:56:05

Просто обработайте ajax-запрос самостоятельно в действиях "wp" или "init". WP admin-ajax изначально предназначен для использования в административной части

onetrickpony onetrickpony
26 мая 2012 г. 15:05:00

@OneTrickPony, спасибо. Это работает. Оставлю рабочий код выше для потомков.

djb djb
26 мая 2012 г. 16:54:57

В последний раз, когда я смотрел Contact Form 7, они не использовали встроенный API шорткодов, а создали свой собственный. Стоит проверить.

chrisguitarguy chrisguitarguy
31 июл. 2012 г. 21:47:41

Я не понимаю, что происходит в ajax-запросе. Потому что если я проверяю function_exists как выше для get_option() вот так: if(function_exists('get_option')){echo 'exist';}else{echo 'not exist';}, это выводит not exist, но когда я просто вывожу, например, название блога get_option('blogname');, оно печатает название блога. Я вижу это в ответе ajax. Если функция не существует, как это может работать? do_shortcode() также работает, когда я пытаюсь получить заголовок сайта. Но когда я пытаюсь получить заголовок поста, он не выводится. В чем может быть проблема? @onetrickpony

sun sun
27 мая 2014 г. 16:04:35

@sun Пожалуйста, прочитайте [вопрос] и задайте свой собственный вопрос.

kaiser kaiser
27 мая 2014 г. 16:07:44
Показать остальные 2 комментариев
Все ответы на вопрос 2
2

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.

25 мая 2012 г. 21:28:18
Комментарии

@djb Пожалуйста, добавьте ваше решение не в вопрос, а как новый ответ и затем отметьте его как решение. Спасибо.

kaiser kaiser
27 мая 2012 г. 18:35:24

сделаю. можете пролить свет на загадку с function_exists?

djb djb
28 мая 2012 г. 12:50:30
0

Решение заключается в том, чтобы обойти ограничения 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(); 
} 
28 мая 2012 г. 12:51:37