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


Tl;dr: Шорткод контактной формы 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"]' )

Возвращает саму строку шорткода. Это прекрасно работает, если я помещу его в шаблон.

Как бы я ни старался (нелепые вещи, такие как упаковка в сообщение/применение фильтра_контента, запуск вручную различных действий, к которым подключается CF7, и т. Д.), Он отказывается чтобы перевести себя в форму.

Как мне это отладить?

РЕДАКТИРОВАТЬ

@Kaiser разумно предполагает, что у меня нет доступа к do_shortcode. Я попытался проверить это, со следующим результатом:

function ps_get_survey_form() {

    //include( ABSPATH . 'wp-includes/shortcodes.php' ); 
    //Causes fatal error: cannot redeclare add_shortcode

    if ( function_exists( 'do_shortcode ' ) )  {
        echo "do_shortcode exists";
    } else {
        echo "do_shortcode doesn't exist";  // this gets echoed
    }

    do_shortcode( 'foo' );      // this fails silently, even though the function apparently hasn't been defined
    //foo();                    // Causes fatal error as expected

    //echo do_shortcode( '[contact-form-7 id="397" title="contact form 1"]' );
    die();
}
Author: djb, 2012-05-25

2 answers

WP Ajax выполняет как публичные, так и закрытые вызовы через admin.php. Это означает, что у вас нет доступа ко всей среде wp, такой как 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] shortcode
$wp_embed->run_shortcode( $post->post_content );

// plain links on their own line
$wp_embed->autoembed( $post->post_content );

// Enable shortcodes
do_shortcode( $post->post_content );

Подсказка: Никогда не звоните echo do_shortcode( '[some-short-code arg="foo"]' ); напрямую. Короткий код - это просто заполнитель для редактора. Каждый короткий код должен иметь прикрепленный обратный вызов. Вместо этого используйте обратный вызов. Это избавляет вас от выполнения дорогостоящих проверок регулярных выражений.

 6
Author: kaiser, 2015-09-17 23:31:35

Ответ заключается в том, чтобы обойти ограничения 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="contact form 1"]' );
    die(); 
} 
 3
Author: djb, 2012-05-28 09:51:37