web-dev-qa-db-ja.com

他のプラグインのCSSファイルをショートコードに含めるにはどうすればいいですか?

私は、とりわけショートコードを作成するプラグインをコーディングしました。そのショートコードはpost_idパラメータを期待し、それはそのポストのコンテンツを抽出し、それはそのポストのフィルタリングされたコンテンツを返します(例えば、それはそのコンテンツ内の他のショートコードが行われるようにすべてのフィルタを適用します)。これがコードの縮小版です。

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;
}

他のプラグインのショートコードが独自のCSSファイルをインクルードできないことを除けば、すべてがうまく機能します(例:Ultimate Addons for Visual Composerには独自のCSSファイルを含める必要がありますが、この方法で呼び出された場合は含まれません)。私の問題は、WPが私のショートコードに対して "the_content"フックを実行したとき(私が明示的に呼び出したものではなく、WP自身が最初に呼び出すフックです)私のショートコードの実行につながります)CSSファイルをページに含めるのはもう手遅れであり(例:<head>タグはすでに閉じられています)、その時点でWordpressはCSSファイルのみをプラグインに含める機会を与えました。ページに必要に応じて表示されます(たとえば、最初のページには私のショートコードしか含まれていないため、私のプラグインのみ)。

必要なサードパーティのCSSファイルを明示的に追加するのにwp_enqueue_styleを使用できますが、問題はそれらを移植可能な方法で含めたいということです。今日の問題はVCのUltimate Addonsです、明日はContent Eggか何か他のものになるでしょう。最善の解決策はWPの関数を呼び出すことです。これはページに必要なプラグインを決定してそれらを呼び出し、その関数に私のショートコードの後のページの実際のコンテンツを渡します。私のショートコードが行われる前にページが持っていたコンテンツの代わりに実行されました。

そのようなWP関数は存在しますか?

編集:

コメントの後の説明のために、はい、私のショートコードは[embed_pa​​ge id = "123"]のようなものです。 [embed_post id = "123"]をページに挿入します。これは、投稿をページに埋め込むためだけに使用されることを目的としており、投稿内で使用されることを意図していないため、ループする危険性はありません。そして最後に、埋め込みコンテンツには他のサードパーティのショートコードが含まれています。これらのショートコードには、独自のCSS、JSなどが自動的にエンキューされます。

受け取った回答の後に編集する:

簡単な答えはノーです、Wordpressにはそのような機能はありません。長い答えは以下の通りです。私は@majickと@cjbjの両方に、彼らの広範囲にわたる詳細な回答に対して報酬を与えたいのですが、私はどちらかを選ばなければなりません...

5
Lucio Crusca

ヘッダが出力される前にコンテンツフィルタを適用することによってページ上でショートコードを事前実行することでこれを回避できると思います。これにより、含まれている投稿内で内部のショートコードが実行され、アクションフックが適切に追加され、必要なスタイルシートやリソースが追加されます。

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);
        }
    }
}

_ edit _ 上記ではエンキューされているスタイルシートとリソースのみをエンキューします 埋め込まれた投稿内のショートコード呼び出し(これはより良い方法ですが、実際にはあまり行われません)。現在のページのコンテンツにフィルタを適用すると、埋め込みショートコードが実行され、埋め込まれた投稿にフィルタが適用されるためです(既存の関数内)。

ただし、特定の投稿のスタイルシートを取得するには、その特定の投稿を取得する必要があります(そのため、すでに説明した問題を考えると、iframeメソッドはうまく機能します)。

その場合の私の提案した回避策は投稿がロードされたときに投稿にロードされたスタイルリソースを保存することです...

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;}
        }
    }
}

それから、取得するスタイルタグを取得するためにショートコードを使用することができ、上記の関数の2番目の部分はそれらをフッターに出力します。

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;
}

そして、script_loader_tagフィルタを通してスクリプトに同じことをすることができて、単に一致するように変数を変えることができます...

もちろん、いくつかのbodyクラスは@cjbjで既に述べたようにスタイルの対象にならないかもしれません...あるいはそれらが適切にキューに入れられていてもフッターで初期化されるかもしれません。

...そしてそれはまだページ上に印刷されている(キューに入れられていない)インラインスタイル/スクリプトを考慮に入れていません...しかしそれは良いスタートです...あなたがそれをどのくらい遠くに使いたいかによって異なります。

4
majick

これは愚かな考えかもしれませんが、うまくいくかもしれません:

1カスタムのquery_varを使ってショートコードをiframeに展開します( tutorial )。このような:

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

2 single.phpquery_varを検出し、その場合はビジュアルヘッダ、サイドバー、フッタをスキップします - 投稿コンテンツ自体に関連しないものは何でも。

このように、あなたは通常の方法で投稿をロードして、彼らがするべきであることを完全にしない他のショートコードに関するすべての問題を避けます。

編集 - コメント後の説明

このアプローチの背後にある哲学は、おそらくショートコードの実行とは無関係に、サードパーティのプラグインが何をするのかわからないということです。そのため、ショートコードが何をしているのかを捉えようとしても、まだ見逃している可能性があります。例えば、ショートコードはhtmlの生成とcssファイルのインクルードにつながるかもしれませんが、プラグインはcssが依存するbody_classも追加するかもしれません。知る方法はありません。ですから、外部プラグイン/ショートコードが期待通りに振る舞うようにするには、WPを全ページロードさせるのが最善の方法です。それゆえiframe

今、これはあなたがヘッダー、メニュー、サイドバーなどを含むフルページを得るという問題をあなたに残します。だから、あなたはthe_title()the_content()そしておそらくポストの他の部分を実行するだけのテンプレートが必要です。何らかの方法で、あなたはこれを望まないことをWPに伝えなければなりません。 WPは、通常のsingle.phpを生成するのか、それとも裸の骨を生成するのかを知っている必要があります。これがquery_varの出番です。ショートコードで生成されたURLに追加することで、WPにこれがsingle.phpの通常の呼び出しではないことを示す手掛かりを与えます。あなたはほんの数行のコードでカスタムquery_varを設定することができるので、これはまだ比較的簡単です。

ショートコードがプラグインに必要な場合は事態が複雑になります。その場合、テーマの機能がわからなくなります。あなたはテーマを却下し、あなたの裸の骨single.phpを挿入しなければなりません。テーマがどのように構築されているのかわからないので、投稿がテーマと同じ形式であるかどうかはわかりません。プラグインにsingle.phpを分析させて不要な要素を削除させることもできますが、それはワイルドな推測です。 single-custompage.phpのようなカスタムテンプレートもあります。あなたがこの道をたどるなら、それはユーザーがページに含まれる投稿のスタイルを設定することを可能にするオプションページを含めることが最善かもしれません。

3
cjbj
  • ビジュアルコンポーズCSSの読み込み

    function get_visual_composer_style($id) {
        return '<style>' . get_post_meta( $id, '_wpb_shortcodes_custom_css', true  ) .                 '</style>';
    }
    
  • ショートコードに基づいてCSSをロード

    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