web-dev-qa-db-fra.com

Scripts/styles en file d'attente en présence d'un shortcode

Quel est le moyen idéal pour enregistrer/mettre en file d'attente des scripts et/ou des styles à utiliser dans des plugins?

J'ai récemment fait un plugin plugin simple pour ajouter l'avatar/gravatar de l'utilisateur avec un shortcode. J'ai différentes options de style pour afficher l'avatar (carré, rond, etc.) et j'ai décidé de mettre le css directement dans le shortcode lui-même.

Cependant, je me rends compte maintenant que ce n'est pas une bonne approche car il répète le css chaque fois que le shortcode est utilisé sur une page. J'ai vu plusieurs autres approches sur ce site et le codex wp en a même deux exemples. Il est donc difficile de savoir quelle approche est la plus cohérente et la plus rapide.

Voici les méthodes que je connais actuellement:

Méthode 1: Inclure directement dans le shortcode - C'est ce que je suis en train de faire dans le plugin, mais cela ne semble pas bien, car cela répète du code.

class My_Shortcode {
function handle_shortcode( $atts, $content="" ) {
/* simply enqueue or print the scripts/styles in the shortcode itself */
?>
<style type="text/css">

</style>
<?php
    return "$content";
     }
}
add_shortcode( 'myshortcode', array( 'My_Shortcode', 'handle_shortcode' ) );

Méthode 2: Utiliser la classe pour mettre en file d'attente des scripts ou des styles

class My_Shortcode {
    static $add_script;
    static function init() {
        add_shortcode('myshortcode', array(__CLASS__, 'handle_shortcode'));
        add_action('init', array(__CLASS__, 'register_script'));
        add_action('wp_footer', array(__CLASS__, 'print_script'));
    }
    static function handle_shortcode($atts) {
        self::$add_script = true;
        // shortcode handling here
    }
    static function register_script() {
        wp_register_script('my-script', plugins_url('my-script.js', __FILE__), array('jquery'), '1.0', true);
    }
    static function print_script() {
        if ( ! self::$add_script )
            return;
        wp_print_scripts('my-script');
    }
}
My_Shortcode::init();

Méthode 3: Utiliser get_shortcode_regex();

function your_prefix_detect_shortcode() {

    global $wp_query;   
    $posts = $wp_query->posts;
    $pattern = get_shortcode_regex();

    foreach ($posts as $post){
        if (   preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches )
            && array_key_exists( 2, $matches )
            && in_array( 'myshortcode', $matches[2] ) )
        {
            // css/js 
            break;  
        }    
    }
}
add_action( 'wp', 'your_prefix_detect_shortcode' );

Méthode 4: Utilisation de has_shortcode();

function custom_shortcode_scripts() {
    global $post;
    if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'myshortcode') ) {
        wp_enqueue_script( 'my-script');
    }
}
add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');
51
Bryan Willis

J'ai trouvé un autre moyen qui fonctionne bien pour moi:

Voici un exemple de plugin utilisant cette méthode qui vous permet d'utiliser get_avatar en tant que shortcode. La feuille de style n'est mise en file d'attente que lorsque le shortcode est présent.

Usage (id par défaut pour l'utilisateur actuel):

[get_avatar id="" size="32" default="mystery" alt="Profile Photo" class="round"]

function wpse_165754_avatar_shortcode_wp_enqueue_scripts() {
    wp_register_style( 'get-avatar-style', plugins_url( '/css/style.css', __FILE__ ), array(), '1.0.0', 'all' );
}

add_action( 'wp_enqueue_scripts', 'wpse_165754_avatar_shortcode_wp_enqueue_scripts' );
if ( function_exists( 'get_avatar' ) ) {
    function wpse_165754_user_avatar_shortcode( $attributes ) {

        global $current_user;
        get_currentuserinfo();

        extract( shortcode_atts(
                     array(
                         "id"      => $current_user->ID,
                         "size"    => 32,
                         "default" => 'mystery',
                         "alt"     => '',
                         "class"   => '',
                     ), $attributes, 'get_avatar' ) );

        $get_avatar = get_avatar( $id, $size, $default, $alt );

        wp_enqueue_style( 'get-avatar-style' );

        return '<span class="get_avatar ' . $class . '">' . $get_avatar . '</span>';
    }

    add_shortcode( 'get_avatar', wpse_165754_user_avatar_shortcode' );
}
42
jblanche

Avant de commencer à répondre, je dois dire que css et js ne sont pas les mêmes sur ce sujet.

La raison est simple: bien que l'ajout de js au corps de la page (en pied de page) soit un moyen simple et valable, les fichiers CSS doivent être placés dans la section <head> de la page: même si la majorité des navigateurs peuvent effectuer correctement le rendu en CSS corps de la page, ce n'est pas un code HTML valide.

Quand un shortcode est rendu, la section <head> était déjà imprimée, cela signifie que js peut être ajouté sans problème sur le pied de page, mais css doit être ajouté avant le shortcode est rendu.

Les scripts

Si votre shortcode n'a besoin que de js, vous avez de la chance et pouvez simplement utiliser wp_enqueue_script dans le corps du rappel de shortcode:

add_shortcode( 'myshortcode', 'my_handle_shortcode' );

function my_handle_shortcode() {
  wp_enqueue_script( 'myshortcodejs', '/path/to/js/file.js' );
  // rest of code here...
}

Ce faisant, votre script est ajouté au pied de page et une seule fois, même si le shortcode est utilisé plusieurs fois dans la page.

Modes

Si votre code a besoin de styles, vous devez alors agir avant que shortcode soit réellement rendu.

Il y a d'autres façons de le faire:

  1. examinez tous les articles de la requête en cours et ajoutez les styles de shortcode si nécessaire. C'est ce que vous faites dans les méthodes 3 et 4 de l'OP. En fait, les deux méthodes font la même chose, mais has_shortcode a été ajouté dans WP 3.6, alors que get_shortcode_regex est disponible depuis la version 2.5, utilisez donc get_shortcode_regex uniquement si vous souhaitez rendre votre plug-in compatible avec les versions antérieures.

  2. toujours ajouter un style shortcode, dans toutes les pages

Problèmes

Le problème avec # 1 est la performance. Les regex sont des opérations assez lentes et lancer regex dans une boucle de toutes les publications peut ralentir la page de manière cohérente. En outre, il est assez commun dans les thèmes de ne montrer que les extraits de messages dans les archives et d'afficher le contenu complet avec des codes abrégés uniquement dans des vues uniques. Si cela se produit, lorsqu’une archive est affichée, votre plugin lancera une correspondance regex dans une boucle dans le but d’ajouter un style qui ne sera jamais utilisé: un double impact inutile sur les performances: ralentir la génération de la page + demande HTTP inutile supplémentaire.

Le problème avec # 2 est la performance, encore. Ajouter du style à toutes les pages signifie ajouter une requête HTTP supplémentaire pour toutes les pages, même si elles ne sont pas nécessaires. Même si le temps de génération de page côté serveur n'est pas affecté, le temps de rendu de page total sera appliqué à toutes les pages du site.

Alors, que doit faire un développeur de plugin?

Je pense que la meilleure chose à faire est d’ajouter une page d’option au plugin, dans laquelle les utilisateurs peuvent choisir si le shortcode doit être traité en vue unique ou même dans des archives. Dans les deux cas, il est préférable de fournir une autre option pour choisir les types de publication pour lesquels le code abrégé est activé.

De cette façon, il est possible de crocheter "template_redirect" pour vérifier si la requête actuelle satisfait aux exigences et, dans ce cas, ajouter le style.

Si l'utilisateur choisit d'utiliser le shortcode uniquement dans les affichages uniques, c'est une bonne idée de vérifier si post a un shortcode: une fois qu'une seule expression régulière est requise, la page ne doit pas être ralentie autant.

Si l'utilisateur choisit d'utiliser le shortcode même dans les archives, j'éviterais alors d'exécuter regex pour toutes les publications si le nombre de publications est élevé et de simplement mettre le style en file d'attente si les exigences de la requête sont correctes.

Ce qu’il faut considérer comme "élevé" à cet égard devrait être d’utiliser des tests de performance ou, au lieu de cela, d’ajouter une autre option et de donner le choix aux utilisateurs.

25
gmazzap

Pour mon plugin, j'ai constaté que parfois les utilisateurs ont un générateur de thème qui a un shortcode stocké dans post meta data . Voici ce que j'utilise pour détecter si mon shortcode de plugin est présent dans les méta-données actuelles post ou post :

function abcd_load_my_shorcode_resources() {
       global $post, $wpdb;

       // determine whether this page contains "my_shortcode" shortcode
       $shortcode_found = false;
       if ( has_shortcode($post->post_content, 'my_shortcode') ) {
          $shortcode_found = true;
       } else if ( isset($post->ID) ) {
          $result = $wpdb->get_var( $wpdb->prepare(
            "SELECT count(*) FROM $wpdb->postmeta " .
            "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'", $post->ID ) );
          $shortcode_found = ! empty( $result );
       }

       if ( $shortcode_found ) {
          wp_enqueue_script(...);
          wp_enqueue_style(...);
       }
}
add_action( 'wp_enqueue_scripts', 'abcd_load_my_shorcode_resources' );
5
zdenekca

Je le fais:

class My_Shortcode {

    function __construct() {
        do_action('my_start_shortcode'); // call
....

et accrocher le crochet dans d'autres fonctions (ou d'autres plugins):

function wpse_3232_load_script(){
    wp_enqueue_script('js-myjs');
}
add_action('my_start_shortcode','wpse_3232_load_script',10);
2
Wladimir Druzhaev

J'ai découvert pour mon propre plugin, si le shortcode est présent dans le widget de texte.

function check_shortcode($text) {

  $pattern = get_shortcode_regex();

   if (   preg_match_all( '/'. $pattern .'/s', $text, $matches )
        && array_key_exists( 2, $matches )
        && in_array( 'myshortcode', $matches[2] ) )
    {
        // myshortcode is being used

        // enque my css and js
        /****** Enqueu RFNB  ******/
        wp_enqueue_style('css-mycss');
        wp_enqueue_script('js-myjs');

        // OPTIONAL ALLOW SHORTCODE TO WORK IN TEXT WIDGET
        add_filter( 'widget_text', 'shortcode_unautop');
        add_filter( 'widget_text', 'do_shortcode'); 

    }

  return $text;

}
add_filter('widget_text', 'check_shortcode');
1
Gino

WordPress possède une fonction intégrée permettant de faire quelque chose en fonction d'un statut de présentation de Shortcode spécifique. Le nom de la fonction est has_shortcode() . Vous pouvez utiliser le code suivant pour mettre en file d'attente votre style et vos scripts.

Ici, j'ai utilisé la fonction is_a( $post, 'WP_Post' ) pour vérifier si l'objet $post est de la classe WP_Post et j'ai utilisé $post->post_content pour vérifier le contenu du message.

if ( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'shortcode_tag') ) {
    wp_enqueue_style( 'handle', get_template_directory_uri() . '/your_file_filename.css' );
}
1
Arif Rahman

J'ai fait une combinaison de l'exemple de code de la page Wordpress pour has_shortcode () et de la réponse zndencka . J'ai remarqué que la fonction has_shortcode est ajoutée dans Wordpress 3.6, c'est pourquoi je vérifie d'abord si la fonction existe. Peut-être que cette vérification est un peu obsolète cependant, car il n’ya plus beaucoup d’utilisateurs en dessous de wordpress 3.6 selon wordpress leurs propres statistiques.

// This makes sure the styling is already enqueued in the header, so before the shortcode loads in the page/post
function enqueue_shortcode_header_script() {
    global $post;
    if ( function_exists( 'has_shortcode' ) ){  // is added in wordpress 3.6
        // Source: https://codex.wordpress.org/Function_Reference/has_shortcode
        if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'my_shortcode') ) {
            wp_enqueue_style( 'shortcode-css' );
        }
    }
    else if ( isset($post->ID) ) { // Small percentage wordpress users are below 3.6 https://wordpress.org/about/stats/
        global $wpdb;
        $result = $wpdb->get_var(
          $wpdb->prepare(
              "SELECT count(*) FROM $wpdb->postmeta " .
              "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'",
               $post->ID )
        );
        if (!empty( $result )) { wp_enqueue_style( 'shortcode-css' ); }
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_shortcode_header_script');
0
Vasco