web-dev-qa-db-fra.com

Pourquoi le "do_shortcode" d'un plugin ne fonctionne-t-il pas dans un AJAX demande?

tl; dr: Le code court du formulaire de contact 7 ne fonctionne pas dans une demande AJAX lorsqu'il est appelé avec 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'}
        }
    });
});

Cependant,

echo do_shortcode( '[contact-form-7 id="397" title="Contact form 1"]' )

renvoie la chaîne de shortcode elle-même. Cela fonctionne bien si je le mets dans un modèle.

Essayez comme je pourrais (des choses ridicules comme l'envelopper dans un filtre de publication/appliquer le filtre the_content, déclencher manuellement diverses actions auxquelles CF7 s'accroche, etc.), il refuse de se convertir en un formulaire.

Comment puis-je déboguer cela?

MODIFIER

@ Kaiser suggère judicieusement que je n'ai pas accès à do_shortcode. J'ai essayé de vérifier cela, avec le résultat suivant:

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

La solution consiste à contourner les restrictions admin-ajax en les manipulant vous-même, comme le suggère @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
djb

WP Ajax exécute des appels publics et fermés via admin.php. Cela signifie que vous n'avez pas accès à tout l'environnement wp, tel que do_shortcode(), qui se trouve à l'intérieur de /wp-includes/shortcodes.php.

Cela peut encore être contourné (et aussi pour oEmbed). Voir l'exemple suivant que vous pouvez utiliser dans votre rappel AJAX pour activer les deux oEmbed gestionnaires ainsi que des gestionnaires de code court pour une propriété \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 );

PROTip: N'appelez jamais echo do_shortcode( '[some-short-code arg="foo"]' ); directement. Un shortcode est juste un espace réservé pour l'éditeur . Chaque shortcode must doit avoir un rappel attaché. Utilisez le rappel à la place. Cela vous évite d'exécuter des contrôles Regex coûteux.

5
kaiser