preg_replace_callback与Spoilers进入Spoilers

时间:2014-04-07 12:49:48

标签: php regex preg-replace-callback

我写了[spoiler=Spoiler Title]text inside the Spoiler[/spoiler]之类的东西 并使用preg_replace_callback("/\[spoiler=(.*)\](.*)\[\/spoiler\]/Usi", 'BBCode_spoiler', $text);创建一个真正的扰流器,一个或多个扰流器的结果是:

<script type="text/javascript">
    function show_0() {
        if(document.getElementById("0").style.display == "inline-block")
            document.getElementById("0").style.display = "none";
        else document.getElementById("0").style.display = "inline-block"; }
</script>
<a href="javascript:show_0();"><i>Show Spiler:</i> <b>Spoiler Title</a></b><br>
<div id="0" style="display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;">
    Text inside the Spoiler
</div>

如何让它与扰流板一起使用到扰流板中 像[spoiler=Spoiler Title][spoiler=Second Spoiler]Another Text[/spoiler][/spoiler] 我的当前函数由无扰流器返回扰流器

<script type="text/javascript">
    function show_0() {
        if(document.getElementById("0").style.display == "inline-block")
            document.getElementById("0").style.display = "none";
        else document.getElementById("0").style.display = "inline-block"; }
</script>
<a href="javascript:show_0();"><i>Show Spiler:</i> <b>Spoiler Title</a></b><br>
<div id="0" style="display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;">
    [spoiler=Second&nbsp;Spoiler]Another Text</div>[/spoiler]

我的回调函数是

<?php
// Spoiler
$counter = 0;
function BBCode_spoiler($hits) {
    global $central_lang;
    global $counter;
    $title = htmlentities(trim($hits[1]));
    $text = htmlentities($hits[2]);
    $return = "<script type=\"text/javascript\">";
    $return .= "function show_".$counter."() {";
    $return .= "if(document.getElementById(\"".$counter."\").style.display == \"inline-block\") document.getElementById(\"".$counter."\").style.display = \"none\";";
    $return .= "else document.getElementById(\"".$counter."\").style.display = \"inline-block\"; }";
    $return .= "</script>";
    $return .= "<a href=\"javascript:show_".$counter."();\"><i>".$central_lang['bbcodes']['spoiler']['text'].":</i> <b>".$title."</a></b><br>";
    $return .= "<div id=\"".$counter."\" style=\"display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;\">".$text."</div>";
    $counter++;
    return $return; }
?>

我尝试制作的输出似乎是

<script type="text/javascript">
    function show_0() {
        if(document.getElementById("0").style.display == "inline-block")
            document.getElementById("0").style.display = "none";
        else document.getElementById("0").style.display = "inline-block"; }
</script>
<a href="javascript:show_0();"><i>Show Spoiler:</i> <b>Spoiler Title</a></b><br>
<div id="0" style="display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;">
    <script type="text/javascript">
        function show_1() {
            if(document.getElementById("1").style.display == "inline-block")
                document.getElementById("1").style.display = "none";
            else document.getElementById("1").style.display = "inline-block"; }
    </script>
    <a href="javascript:show_1();"><i>Show Spoiler:</i> <b>Second Spoiler</a></b><br>
    <div id="1" style="display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;">
        Another text
    </div>
</div>

我希望我的问题有答案,谢谢!

2 个答案:

答案 0 :(得分:0)

这一般适用于BBCode:重新运行替换代码,直到它停止更改它。

preg_replace_callback接受“count”引用变量,该变量将填充所做的替换次数。只要这个数字不为零,你应该重新运行替换(do..while是完美的)

他们被越过并不重要。假设我们有一个BBC代码用[div]替换<div> ...

[div]Blah[div]123[/div]Fish[/div]

一次更换后:

<div>Blah[div]123</div>Fish[/div]

再次替换后:

<div>Blah<div>123</div>Fish</div>

因此即使它们是以交叉顺序处理的,结果也是正确嵌套的。

答案 1 :(得分:0)

您可以使用preg_replace_callback的count参数来处理从最里面到最外层的替换,直到没有更多的标记要替换:

$pattern = '~\[spoiler=([^]]*)]((?>[^[]+|\[(?!/?spoiler\b))*)\[/spoiler]~i';

do {
    $result = preg_replace_callback($pattern, 'BBCode_spoiler', $text, -1, $count);
} while ($count>0);

我改变了一点模式以确保匹配是最里面的标记。