J'ai essayé de créer une fonction de shortcode qui génère du html pour une galerie à onglets, et après plusieurs jours, je n'ai pas été aussi loin. Voici un exemple de 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]
Je veux que le HTML retourné soit quelque chose comme ceci (simplifié par exemple):
<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>
Par conséquent, j'ai besoin des codes abrégés imbriqués pour exporter des données dans une balise nav
et en un élément div. Le problème avec ceci est (je pense) que cela nécessite une variable accessible aux fonctions de shortcode principales et imbriquées, ce sur quoi je suis resté bloqué.
Ma tentative au plug-in de shortcode est en dessous (erreur fatale lors d'une tentative d'installation). J'apprécierais une correction de mon code existant ou peut-être un conseil sur une meilleure approche du problème.
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>';
}
Après un peu de réflexion latérale et de nombreux tests, j'ai été en mesure de proposer une solution qui supprime le besoin de variables de croisement de périmètre ou l'utilisation d'une variable globale pour cette question.
Le code va comme ceci:
$content
imbriqué __ (shortcodes imbriqués) en un shortcode avec preg_match_all
do_shortcode
à chaque shortcode avec une boucle forpreg_match
, la première étant la donnée de contenu principale et la deuxième étant la donnée nav
.J'ai fourni une version allégée de mon code ci-dessous. L'astuce pour que tout cela fonctionne consiste à avoir une expression preg_match robuste pour séparer les codes abrégés, de sorte qu'ils ne se cassent pas lorsqu'ils sont alimentés avec des données utilisateur irrégulières.
<?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'] . "'>";
}
Et le shortcode que l'utilisateur taperait dans l'éditeur de texte:
[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]
Et le résultat devrait ressembler à ceci:
<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>
Prêt à être traité par une fonction de tabulation javascript!