web-dev-qa-db-ja.com

Wordpressは、ショートコード呼び出し内から自分自身を呼び出すショートコードをサポートしていますか?

私は100万と1つのショートコードを持つ超クレイジーなWordpressフレームワークを構築しました。そのうちの1つはカラムを定義することを可能にするcountパラメータをサポートするcolumnsショートコードです、そして適切なクラスは追加されます。

私のショートコードは次のとおりです。

add_shortcode('column', 'column_shortcode');
function column_shortcode($atts, $content = '')
{
    extract(shortcode_atts(array(
       'count' => 12
    ), $atts));

    if (stripos($count, '_') === FALSE)
    {
        if ((int) $count > 12)
        {
            $count = 12;
        }
    }

    $html = '<div class="column-'.$count.' column">';
    $html .= do_shortcode($content);
    $html .= '</div>';

    return $html;
}

しかし、列のショートコードが列内で使用されている場合は問題があるようですが、これは既知の問題なのか、それともWordpressが同じ名前のショートコードを互いに入れ子にしてサポートしていませんか。

本質的に起こることは内部の列が出力されたHTMLで時期尚早に閉じられていて、私がフロントエンドに表示されている段落タグで囲まれているのを見ます。しかし、別のショートコードを作成してchildという名前にした場合、上記とまったく同じコードを使用すると、子のshrotcodeだけが[column]ではなく[child]になり、すべて正常に機能します。

これが私のWordpressインストールのWYSIWYGエディタからのコードです。図Aは理想的なシナリオです。同じことをする2つの異なるショートコードを使用する必要はありません。図Bは、単にショートコードを複製することによって機能します。

図A - は機能しません

[column count="9"]

[column count="8_9"]

Welcome to the site.

Who's brave enough to fly into something we all keep calling a death sphere? Well, then good news! It's a suppository. A true inspiration for the children. Ah, computer dating. It's like pimping, but you rarely have to use the phrase "upside your head."

[/column]

[/column]

展示物B - 作品

[column count="9"]

[child count="8_9"]

Welcome to the site.

Who's brave enough to fly into something we all keep calling a death sphere? Well, then good news! It's a suppository. A true inspiration for the children. Ah, computer dating. It's like pimping, but you rarely have to use the phrase "upside your head."

[/child]

[/column]
2

これは既知の問題です。同じ名前のショートコードが別のショートコードの中にあると、ワードプレスパーサーはそれらを正しく処理できません。これはショートコードAPIの codexページにも記載されています 制限があります。

リンクされているページからHowever the parser will fail if a shortcode macro is used to enclose another macro of the same name

私が提案する解決策は、追加のパラメータをメインのショートコード呼び出しに追加することで、あなたのショートコード関数で、それらの追加のパラメータが存在するかどうかに基づいてそれ自身を再帰的に呼び出すことです

[column count="9" child="8_9" 8_9_text="

Welcome to the site.

Who's brave enough to fly into something we all keep calling a death sphere? Well, then good news! It's a suppository. A true inspiration for the children. Ah, computer dating. It's like pimping, but you rarely have to use the phrase "upside your head."
" /]

次にコードで

function shortcode_handler($atts, $content, $tag) {
    if(isset($atts['child']))
        $output = shortcode_handler(array('count'=>$atts['child']), $atts[$atts['child'].'_text'])

    // Do something else with the output

}

見栄えがよくないことはわかっていますが、アプリケーションのコンテキスト内で何か問題を解決できる可能性があります。

2
Mridul Aggarwal

私は自分自身の中でショートコードを有効にする小さな機能を書きました。それはあなたの問題に対して完璧に機能するはずです。私にとってはとても役に立ちました。

ファイル 'wp-includes/shortcodes.php'を開き、do_shortcode()関数(201行目)を次のように変更します。

function do_shortcode($content) {
    global $shortcode_tags;

    if (empty($shortcode_tags) || !is_array($shortcode_tags))
        return $content;

    $content = enable_recursive_shortcodes($content);

    $pattern = get_shortcode_regex();
    return preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );
}

変更されたのは* $ content = enable_recursive_shortcodes($ content); *の追加だけです。

この関数は、渡された$コンテンツを調べて、自分自身内のショートコードのショートコード名に接尾辞を追加します。その後、外側のショートコードだけが処理され、その内容が処理されると、接尾辞が削除されて処理されます。それが行くことができる深さのレベルの数に制限はありません。 (例:[箱] [箱] [箱] [箱]内容[箱] [箱] [箱] [箱])

Do_shortcode()関数の上に次の関数を追加します。

/**
 * Add shortcode suffix enabling recursive shortchodes.
 *
 * This function goes inside the set of $recursive_tags and adds a suffix to
 * the shortcode name so it will allow a shortcode to call itself in its content
 *
 * @since 2.5
 * @return string Content with recursive shortcodes modified out.
 */
function enable_recursive_shortcodes($content) {

    $recursive_tags = array( 'column', 'div', 'span', 'table' ); // define recursive shortcodes, these must have closing tags 
    $suffix = '__recursive'; // suffix is added to the tag of recursive shortcodes

    $content = str_replace( $suffix, '', $content ); // remove old suffix on shortcodes to start process over

    foreach( $recursive_tags as $recursive_tag ) {

        $open_tag = '[' . $recursive_tag . ' ';
        $close_tag = '[/'. $recursive_tag . ']';

        $open_tags = 0;

        $open_pos = stripos( $content, $open_tag ); // find first opening tag

        $offset = $open_pos + strlen( $open_tag ); // set offset for first closing tag

        while( $open_pos !== false ) {

            $close_pos = stripos( $content, $close_tag, $offset ); // find first closing tag

            if(++$open_tags > 1) { // if we are inside an open tag

                // modify open tag from original shortcode name
                $content = substr( $content, 0, $open_pos ) . 
                            '[' .$recursive_tag . $suffix . ' ' . 
                              substr( $content, $offset ); 
                // modify closing tag from original shortcode name
                $content = substr( $content, 0, $close_pos + strlen($suffix) ) . 
                            '[/'.$recursive_tag.'__recursive]' . 
                            substr( $content, $close_pos + strlen( $close_tag ) + strlen($suffix) ); 
                $open_tags--;
            }

            $open_pos = stripos( $content, $open_tag, $offset ); // find next opening tag

            if( $close_pos < $open_pos ) $open_tags--; // if closing tag comes before next opening tag, lower open tag count

            $offset = $open_pos + strlen($open_tag); // set new offset for next open tag search

        }

    }

    return $content;

}

必要に応じて$ recursive_tags変数を必ず更新してください。それらのタグだけが同名の子供に対してチェックされます。 [column /]は機能しないため、これらのタグには終了タグ[column] [/ column]が必要です。また、開始タグのショートコード名の後にスペースを入れ、終了タグのスペースを入れないようにする必要があります。これは、関数によるタグの検索方法のためです。 [column]または[column /]スタイルのショートコードが機能するようにコードを更新した場合は、共有してください。

2
Trey Welstad

これに対して私が見つけた最も簡単な(おそらく最良ではないかもしれないが)解決策は、わずかなバリエーションの下でタグを複数回追加することです。たとえば、質問者の場合は、次のようになります。

function render_column( $atts, $content ) {
    // etc.

    return apply_filters( 'the_content', $content );
}

add_shortcode( 'column', 'render_column' );
add_shortcode( 'column-level-2', 'render_column' );
add_shortcode( 'column-level-3', 'render_column' );

これには少し余分なドキュメントが必要で、すぐには理解できないユーザーもいるかもしれませんが、ショートコードの内容を属性に入れるようにユーザーに依頼するよりも、直感的に理解しやすいです。そしてもちろん、その解決策は、ショートコード属性で引用符を扱うという別の問題を引き起こします。

0
John Watkins