在进行了一些横向思考和大量测试之后,我能够想出一个解决方案,消除了跨范围变量的需要,或者使用了一个全局变量。
代码如下:
拆分嵌套的$content
(嵌套的短代码)到具有preg_match_all
应用do_shortcode
对于每个带有for循环的短码,每个嵌套的短码函数返回一个字符串,该字符串将被另一个字符串拆分为两个字符串preg_match
函数,第一个是主要内容数据,第二个是nav
数据将所有主要内容数据分配给一个数组,将导航数据分配给另一个数组,然后只需处理两个数组并返回字符串我在下面提供了我的代码的精简版本。实现这一切的诀窍是使用一个健壮的preg\\u match表达式来分离短代码,这样在输入不规则的用户数据时它们就不会中断。
<?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\'] . "\'>";
}
以及用户将在文本编辑器中键入的短代码:
[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]
输出应该是这样的:
<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>
已准备好由javascript选项卡函数处理!