it-swarm.com.de

Verschachtelte Shortcode-Funktionen für den Zugriff auf Variablen

Ich habe versucht, eine Shortcode-Funktion zu erstellen, die HTML-Code für eine Galerie mit Registerkarten ausgibt, und nach vielen Tagen bin ich noch nicht weit gekommen. Hier ist ein Beispiel für den Shortcode:

[thumbTab id="test1" nav="top" shadow="off"]
    [imgTab id="1" src="source1" width="1280" height="720" ]
    [vidTab id="2" src="source2" width="1280" height="720" ]
    [htmlTab id="4" preview_src="source3"] Other HTML stuff in here [/html]
[/thumbTab]

Ich möchte, dass der zurückgegebene HTML-Code ungefähr so ​​aussieht (vereinfacht zum Beispiel):

<div>
    <nav>
        <img .../>    /* 1st nested shortcode */
        <img.../>     /* 2st nested shortcode */
        <img.../>     /* 3st nested shortcode */
    </nav>
    <div>
        <img.../>         /* 1st nested shortcode */
        <video.../>       /* 2st nested shortcode */
        <section.../>     /* 3st nested shortcode */
    </div>
</div>

Daher benötige ich die verschachtelten Shortcodes, um Daten in ein nav -Tag auszugeben und in ein div-Element. Das Problem dabei ist (glaube ich), dass es eine Variable erfordert, auf die die Haupt- und verschachtelten Shortcode-Funktionen zugreifen können, woran ich festgehalten habe.

Mein Versuch, das Shortcode-Plugin zu verwenden, ist unten (schwerwiegender Fehler bei versuchter Installation). Ich würde mich über eine Korrektur meines vorhandenen Codes oder einen Ratschlag zu einer besseren Lösung des Problems freuen.

add_shortcode('thumbTab', 'thumbTab_func');

function thumbTab_func( $atts, $content = null ) {  
    $a = shortcode_atts( array(
        'id' => 'theID',
        'nav' => 'top',
        'shadow' => 'off'
    ), $atts );

    class thumbTab_class
    {
        //Array to hold tabbed content
        $tabCon = array();

        //Array to hold navigation tabs
        $navCon = array();

        //run nested shortcodes
        do_shortcode( $content, $ignore_html = false); 

        //combine $navCon array elements into the navigation tab html
        function navCreate(){
            $navReturn = '<div><nav><ul>';
            for ($i = 0; $i < count($this->navCon) ; ++$i) {
                $navReturn .= $this->navCon["$i"];
            }
            $navReturn .= '</ul></nav></div>';
            return $navReturn;
        }
        //combine $tabCon array elements into tabbed content html
        function tabCreate(){
            $tabReturn = '';
            for ($i = 0; $i < count($this->tabCon) ; ++$i) {
                $tabReturn .= $this->tabCon["$i"];
            }
            $tabReturn .= '</ul></nav></div>';
            return $tabReturn;
        }

        // Assigning processed html code to variable
        $thumbReturn = '<div id="'.$a["id"].'" class="thumbTAB">';
        $thumbReturn .= navCreate();
        $thumbReturn .= tabCreate();
        $thumbReturn .= '</div>';

    }

    $thumbTab_class = new thumbTab_class();

    // output processed html
    return $thumbTab_class->thumbReturn; 

}

//One nested shortcode function for testing
add_shortcode('imgTab', 'imgTab_func');

function imgTab_func( $atts ) { 
    $a = shortcode_atts( array(
        'id' => 'no_order',
        'src' => 'no_source',
        'width' => '100%',
        'height' => 'auto'
    ), $atts );

    //create baseline structure
    $img = '<img src="'.$a["src"].'" width="'.$a["width"].'" height="'.$a["height"].'">';

    //assign tabbed html string to tabCon array using the id number to place in order
    $this->tabCon["a['id']"] = '<section class="tabPage tabPage_'.$a["id"].'>'.$img.'</section>';

    //same for nav html string
    $this->navCon["a['id']"] = '<li class="sDS tabHeader_'.$a["id"].'">'.$img.'</li>';
}
2
Kayboy Bebop

Nach einigem Querdenken und vielen Tests konnte ich eine Lösung finden, die die Notwendigkeit von Variablen zum Überschreiten des Gültigkeitsbereichs oder die Verwendung einer globalen Variablen für diese Angelegenheit zunichte machte.

Der Code sieht folgendermaßen aus:

  1. Teilen Sie den verschachtelten $content (verschachtelte Shortcodes) mit preg_match_all in einzelne Shortcodes auf
  2. Wenden Sie do_shortcode auf jeden Shortcode mit einer for-Schleife an
  3. Jede verschachtelte Shortcode-Funktion gibt eine Zeichenfolge zurück, die von einer anderen preg_match-Funktion in zwei Zeichenfolgen aufgeteilt wird, wobei die erste die Hauptinhaltsdaten und die zweite die nav-Daten sind
  4. Weisen Sie einem Array alle Hauptinhaltsdaten und einem anderen Array die Navigationsdaten zu
  5. Dann müssen Sie nur noch die beiden Arrays verarbeiten und den String zurückgeben!

Ich habe unten eine abgespeckte Version meines Codes angegeben. Der Trick dabei ist, dass die Shortcodes durch einen robusten preg_match-Ausdruck getrennt werden, damit sie bei der Eingabe unregelmäßiger Benutzerdaten nicht beschädigt werden.

<?php
add_shortcode('tabs', 'tabs_func');
//Main shortcode function
function tabs_func( $atts, $content = null ) {  
    $a = shortcode_atts( array(
        'id' => '',
    ), $atts );

    //array to store nav data
    $navCon = array();

    //array to store main content data
    $tabCon = array();

    /* 
    Preg_match_all splits $content into predefined individual shortcodes [imgTab], [vidTab] and [htmlTab][/htmlTab]

    A basic explanation of the expression I used. If you want a more detailed breakdown, plug the expression below into "https://regexr.com/"

        (?<!\[)    <= checks if there's a square bracket behind the proceeding match, to avoid matching escaped shortcode
        \[    <= matches the opening bracket
        (?:(?:imgTab|vidTab).*(?<!\])\](?!\])|htmlTab[\S\s]*?\[\/htmlTab\](?!\]))    <= can't break this into parts easily, but in essence this part tries to match a string which next part goes 'imgTab', 'vidTab', or 'htmlTab' (although the 'htmlTab' is put in it's own non-capture group as it has to deal with possible linebreaks). It then matches the remaining characters until it gets to a closing square bracket (or in the case of htmlTab, '[/htmlTab]. It then checks that there aren't two closing brackets next to each other before finishing the match. 
    */
    preg_match_all( '@(?<!\[)\[(?:(?:imgTab|vidTab).*(?<!\])\](?!\])|htmlTab[\S\s]*?\[\/htmlTab\](?!\]))@', $content, $matches );   

    $matchLI = 1;
    //loops through each of the shortcode matches
    foreach ($matches[0] as $match) {

        //runs current shortcode and assigns to variable
        $match_processed = do_shortcode($match);

        /*
        This expression is much more simple than the last one :D

            ([\S\s]+)    <= this capture group basically takes all the characters that aren't matched by the next part of the expression. This capture group contains the main content
            (<[\S\s]+>)    <= this capture group matches a 'less-than' character, a string of any characters and finally a 'greater-than' character. Since this expression is greedy it won't false match any 'greater-than' symbols in the first capture group, as it will look for the last 'greater-than' in the string
        */
        preg_match( '@([\S\s]+)(<[\S\s]{4,}>)@', $match_processed, $navMatch );

        //assigns nav data of current shortcode to the $navCon array, using the $matchLI value to index it
        $navCon[$matchLI] .= "<li class='nav_NUM_" . $matchLI . "'>" . $navMatch[2] . "</li>";

        //assigns main content data of current shortcode to the $tabCon array, using the $matchLI value to index it
        $tabCon[$matchLI] = "<section class='content_NUM_" . $matchLI . "'>" . $navMatch[1] . "</section>";
        }

        //increments the value for the next loop
        $matchLI++;

    }

    //constructing html in $tabReturn variable
    $tabReturn = "<div id='" . $a['id'] . "'>";
    $tabReturn .= "<nav><ul>";
    //loops through and assigns content of $navCon array to $tabReturn
    foreach ($navCon as $navElement) {
        $tabReturn .= $navElement;
    }
    $tabReturn .= "</ul></nav>";
    //loops through and assigns content of $tabCon array to $tabReturn
    foreach ($tabCon as $tabElement) {
        $tabReturn .= $tabElement;
    }
    $tabReturn .= "</div>";

    //finished html string is returned. Mission complete!
    return $tabReturn;

}

add_shortcode('imgTab', 'imgTab_func');
function imgTab_func( $atts ) { 
    $a = shortcode_atts( array(
        'src' => '',
        'width' => '100%',
        'height' => 'auto'
    ), $atts );

    //First img element is the main content, and the second is the nav preview 
    return "<img src='" . $a['src'] . "' width='" . $a['width'] . "' height='" . $a['height'] . "'>
    <img src='". $a['src'] . "' width='" . $a['width'] . "' height='" . $a['height'] . "'>";


}

add_shortcode('vidTab', 'vidTab_func');
function vidTab_func( $atts ) { 
    $a = shortcode_atts( array(
        'poster' => '',
        'src' => '',
        'width' => '100%',
        'height' => 'auto'
    ), $atts );

    //vid element is the main content, and the img is the nav preview 
    return "<video width='" . $a['width'] . "' height='" . $a['height'] . "' poster='" . $a['poster'] . "' controls>
        <source src='" . $a['src'] . "' type='video/mp4'>
    </video>
    <img src='". $a['poster'] . "' width='" . $a['width'] . "' height='" . $a['height'] . "'>";

}

add_shortcode('htmlTab', 'htmlTab_func');
function htmlTab_func( $atts, $content = null ) {   
    $a = shortcode_atts( array(
        'poster' => '',
        'width' => '100%',
        'height' => 'auto'
    ), $atts );

    //$content is the main content, and the img is the nav preview.
    return $content . "<img src='". $a['poster'] . "' width='" . $a['width'] . "' height='" . $a['height'] . "'>";
}

Und der Shortcode, den der Benutzer in den Texteditor eingeben würde:

[tabs id="test1"]

//any number and combination of these elements

[imgTab src="imgTab.jpg" width="100" height="100"]

[vidTab poster="vidTab.jpg" src="vidTab.mp4" width="128" height="72"]

[htmlTab poster="htmlTab.jpg" width="100" height="100"] 
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam scelerisque maximus neque gravida gravida.</p>
[/htmlTab]

[/tabs]

Und die Ausgabe sollte ungefähr so ​​aussehen:

<div id='test1'>
    <nav><ul>
        <li class='nav_NUM_1'> 
            <img src='imgTab.jpg' width='100' height='100'>
        </li>
        <li class='nav_NUM_2'> 
            <img src='vidTab.jpg' width='128' height='72'>
        </li>
        <li class='nav_NUM_3'> 
            <img src='htmlTab.jpg' width='100' height='100'>
        </li>
    </ul></nav>
    <section class='content_NUM_1'>
        <img src='imgTab.jpg' width='100' height='100'>
    </section>
    <section class='content_NUM_2'>
        <video width='128' height='72' poster='vidTab.jpg' controls>
            <source src='vidTab.mp4' type='video/mp4'>
        </video>
    </section>
    <section class='content_NUM_3'>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam scelerisque maximus neque gravida gravida.</p>
    </section>
</div>

Bereit, von einer JavaScript-Tab-Funktion verarbeitet zu werden!

1
Kayboy Bebop