web-dev-qa-db-fra.com

comment inclure d'autres fichiers css de plugins dans un shortcode?

J'ai codé un plugin qui crée un shortcode, entre autres choses. Ce shortcode attend un paramètre post_id, il extrait le contenu de cette publication et renvoie le contenu filtré de cette publication (par exemple, il applique tous les filtres afin que tout autre code court contenu dans ce contenu soit terminé). Voici une version simplifiée du code:

public static function myshortcode($atts = null, $content = "")
{
  global $wp_filter, $merged_filters, $wp_current_filter, $post;

  if (is_array($atts))
    extract($atts, EXTR_OVERWRITE);

  $save_wp_filter = $wp_filter;
  $save_merged_filters = $merged_filters;
  $save_wp_current_filter = $wp_current_filter;
  $post = get_post($post_id);
  setup_postdata($post);
  $content = $post->post_content;
  $content = apply_filters('the_content', $content);        
  $content = str_replace(']]>', ']]>', $content);
  $wp_filter = $save_wp_filter;
  $merged_filters = $save_merged_filters;
  $wp_current_filter = $save_wp_current_filter;

  return $content;
}

Tout fonctionne très bien, sauf que les autres codes courts de plugins ne parviennent pas à inclure leurs propres fichiers CSS (par exemple, Ultimate Addons pour Visual Composer a ses propres fichiers CSS à inclure, mais il ne les inclut pas lorsqu'il est appelé de cette façon). Je soupçonne que le problème est que lorsque WP exécute le hook "the_content" pour mon shortcode (pas celui que j'appelle explicitement, mais le hook que WP appelle lui-même en premier lieu et que mène à mon exécution de shortcode) il est déjà trop tard pour inclure des fichiers CSS dans la page (par exemple, la balise <head> est déjà fermée), et Wordpress, à ce stade, a donné une chance d'inclure des fichiers CSS uniquement aux plug-ins qu'il voit au besoin pour la page (par exemple, seulement mon plugin, car la page ne contient initialement que mon shortcode).

Je pourrais utiliser wp_enqueue_style pour ajouter explicitement les fichiers CSS tiers requis, mais le problème est que je souhaite les inclure de manière portable. Aujourd'hui, le problème est Ultimate Addons for VC, demain ce sera Content Egg ou autre chose. La meilleure solution serait d'appeler la fonction WP qui prend la décision sur quels sont les plugins requis pour la page et les appelle, en remettant à cette fonction le contenu réel de la page après mon shortcode. exécuté, au lieu du contenu de la page avant que mon shortcode soit terminé.

Une telle fonction WP existe-t-elle?

MODIFIER:

Pour clarification après les commentaires, oui, mon shortcode ressemble à [embed_page id = "123"], sauf que j'en ai besoin dans le sens inverse, par exemple. [embed_post id = "123"] dans une page. Il n'y a aucun risque de bouclage car il est conçu pour être utilisé uniquement pour intégrer des publications dans des pages et non pour être utilisé dans des publications. Et enfin, oui, le contenu intégré inclut d'autres codes courts tiers qui devraient automatiquement mettre en file d'attente leurs propres CSS, JS, peu importe.

ÉDITER APRÈS LES RÉPONSES REÇUES:

La réponse courte est non, il n'existe pas une telle fonction dans Wordpress. La réponse longue est ci-dessous. J'aimerais récompenser @majick et @cjbj pour leurs réponses complètes et détaillées, mais je dois en choisir une ...

5
Lucio Crusca

Je pense que vous pourriez contourner ce problème en pré-exécutant les codes abrégés sur la page en appliquant les filtres de contenu avant la sortie de l'en-tête. Cela devrait permettre à tous les codes courts internes exécutés à l’intérieur de la publication incluse d’ajouter correctement les crochets d’action et donc les feuilles de style/ressources nécessaires.

add_action('wp_loaded','maybe_prerun_shortcodes');
function maybe_prerun_shortcodes() {
    if (is_page()) {
        global $post; 
        if (has_shortcode($post->post_content,'embed_post')) {
            $content = apply_filters('the_content',$post->post_content);
        }
    }
}

EDITCe qui précède ne mettra en file d'attente que les feuilles de style et les ressources mises en file d'attente au sein de tous les appels de shortcode dans la publication incorporée (bien qu'il soit préférable de ne pas le faire très souvent.) devrait fonctionner pour ces cas, car l'application des filtres au contenu de la page actuelle exécutera le shortcode incorporé, qui appliquera ensuite des filtres à la publication incorporée (dans votre fonction existante).

Cependant, pour obtenir les feuilles de style d'une publication particulière, vous devez aller chercher cette publication particulière (c'est pourquoi la méthode iframe fonctionne, en quelque sorte, étant donné les problèmes déjà abordés à ce sujet.)

La solution que je préconise dans ce cas consiste à stocker les ressources de style chargées sur un message lorsque celui-ci est chargé ...

add_filter('style_loader_tag','custom_store_style_tags',11,2)
function custom_store_style_tags($tag,$handle) {
    global $styletags; $styletags[$handle] = $tag;}
}

add_action('wp_footer','custom_save_style_tags');
function custom_save_style_tags() {
    global $embedstyles;
    if (is_single()) {
        global $styletags, $post; 
        update_post_meta($post->ID,'styletags',$styletags);
    } elseif (is_array($embedstyles)) {
        global $styletags;
        foreach ($embedstyles as $handle => $tag) {
            if (!array_key_exists($handle,$styletags)) {echo $tag;}
        }
    }
}

Ensuite, vous pouvez utiliser le shortcode pour récupérer les balises de style à récupérer et la deuxième partie de la fonction ci-dessus les affichera dans le pied de page:

public static function myshortcode($atts = null, $content = "")
{
  // EXISTING CODE SNIPPED

  global $embedstyles;
  $embedstyle = get_post_meta($post_id,'styletags',true);
  if (is_array($embedstyle)) {
      if (!is_array($embedstyles)) {$embedstyles = array();}
      $embedstyles = array_merge($embedstyle,$embedstyles);
  }

  return $content;
}

Et vous pourriez faire la même chose pour les scripts via le filtre script_loader_tag et simplement changer les variables pour qu'elles correspondent ...

Bien sûr, il est toujours possible que certaines classes body ne soient pas ciblées par les styles déjà mentionnés par @cjbj ... ou que certains scripts s'initialisent dans le pied de page même s'ils sont correctement mis en file d'attente.

... et cela ne prend pas en compte les styles/scripts en ligne imprimés (non mis en file d'attente) sur la page ... mais c'est un bon début ... dépend de la distance que vous souhaitez atteindre.

4
majick

C'est peut-être une idée idiote, mais ça pourrait marcher:

1 Laissez votre code abrégé exploser en une iframe avec un query_var personnalisé ( tutorial ). Comme ça:

<iframe src="http://www.example.com/?p=123&my_query_var=content_only"></iframe>

2 Dans votre single.php, détectez le query_var et, dans ce cas, ignorez l'en-tête visuel, les barres latérales et le pied de page - tout ce qui n'est pas connecté au contenu de la publication.

De cette façon, vous chargez le message de la manière habituelle et évitez tous les problèmes liés aux autres codes courts qui ne font pas complètement ce qu'ils doivent faire.

EDIT - CLARIFICATION APRES COMMENTAIRES

La philosophie derrière cette approche est que vous n’avez aucune idée de ce que font les plugins tiers, peut-être même indépendamment de l’exécution du shortcode. Donc, si vous essayez de comprendre ce que fait le shortcode, vous risquez encore de rater des choses. Par exemple, un shortcode peut entraîner la génération de html et l'inclusion d'un fichier css, mais le plug-in peut également ajouter un body_class dont dépend css. Il n'y a aucun moyen de savoir. Ainsi, pour vous assurer que le plugin externe/shortcode se comporte comme prévu, le meilleur moyen consiste à faire en sorte que WP effectue un chargement complet de la page. D'où la iframe.

Maintenant, cela vous laisse avec le problème que vous obtenez une page complète, y compris l'en-tête, le menu, les barres latérales et ainsi de suite. Vous avez donc besoin d'un modèle qui n'exécute que the_title() et the_content() et peut-être d'autres parties du message. D'une certaine manière, vous devez dire à WP que vous ne le souhaitez pas. WP doit savoir s'il est censé générer un single.php normal ou un bare bones. C’est là que le query_var entre en jeu. En l’ajoutant à l’URL générée dans votre shortcode, vous donnez à WP un indice qu'il ne s'agit pas d'un appel normal à single.php. Cela reste relativement facile, car vous pouvez configurer un query_var personnalisé avec seulement quelques lignes de code.

Les choses se compliquent si vous voulez insérer votre shortcode dans un plugin, car vous ne savez pas non plus ce que fait le thème. Vous devrez remplacer le thème et insérer votre corps nu single.php. Comme vous ne savez pas comment le thème est construit, vous ne saurez pas si le message a le même format que dans le thème. Vous pouvez également demander à votre plugin d’analyser single.php et de supprimer les éléments non désirés, mais c’est une supposition sauvage. Il peut également y avoir des modèles personnalisés tels que single-custompage.php. Par conséquent, si vous suivez ce chemin, il peut être préférable d’inclure une page d’option permettant aux utilisateurs de définir les styles des publications incluses dans les pages.

3
cjbj
  • Charger Visual Composer CSS

    function get_visual_composer_style($id) {
        return '<style>' . get_post_meta( $id, '_wpb_shortcodes_custom_css', true  ) .                 '</style>';
    }
    
  • Charger le css basé sur le shortcode

    function custom_shortcode_scripts() {
        global $post;
        if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'custom-shortcode') ) {
           wp_enqueue_script( 'custom-script');
        }
    }
    add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');
    
2
Nefro