为什么WP不喜欢我的<a>容器?

时间:2016-01-26 作者:luukvhoudt

最近,我一直在研究一些短代码,其中短代码生成的所有元素都封装在一个标记中。不幸的是,这并不像所希望的那样呈现,因为在\\u内容上有过滤器wpautop,或者您正在使用的任何东西来显示短代码和/或常规内容。

设置设想我们创建了以下短代码:

<?php

function example_shortcode($atts, $content = null) {
    extract(shortcode_atts(
        array(
           \'before\' => \'\',
           \'after\' => \'\',
           \'link\' => \'\',
        ), $atts)
    );

    $before = (!empty($atts[\'before\'])) ? \'<div class="before">\'.$atts[\'before\'].\'</div>\' : \'\';
    $after = (!empty($atts[\'after\'])) ? \'<div class="after">\'.$atts[\'after\'].\'</div>\' : \'\';
    $link = (!empty($atts[\'link\'])) ? \' href="\'.$atts[\'link\'].\'"\' : \'\';

    return \'<a\'.$link.\'>\'.$before.do_shortcode($content).$after.\'</a>\';
}
add_shortcode(\'example_shortcode\', \'example_shortcode\');
我们还创建了一个包含以下内容的页面。

some text before the shortcode

[example_shortcode before="Welcome" after="Goodbye" link="#"]

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

[/example_shortcode]

some text after the shortcode
测试wpautop 使用默认优先级添加的过滤器输出如下所示:

<p>some text before the shortcode</p>
<a href="#"><div class="before">Welcome</div></p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
<p><div class="after">Goodbye</div></a>
<p>some text after the shortcode</p>
或与remove_filter(\'the_content\', \'wpautop\'); 添加后,它还会返回正确的HTML:

some text before the shortcode

<a href="#"><div class="before">Welcome</div>

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

<div class="after">Goodbye</div></a>

some text after the shortcode
但是当wpautop过滤器添加了更高的优先级时,例如。。。

<?php
remove_filter(\'the_content\', \'wpautop\');
add_filter(\'the_content\', \'wpautop\', PHP_INT_MAX);
然后输出返回所有混乱的结果,如下所示:

<p>some text before the shortcode</p>
<p><a href="#">
</a></p><div class="before"><a href="#">Welcome</a></div><a href="#">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
<div class="after">Goodbye</div>
</a><p><a href="#"></a></p>
<p>some text after the shortcode</p>
问题和我的目标为什么<a> 标签添加了多次,但只应打开和关闭一次?

这是我想要呈现的HTML,在更改<a> example\\u shortcode函数内的标记,例如a<div> 标签为什么这些标签的输出不同?

<p>some text before the shortcode</p>
<a href="#">
<div class="before">Welcome</div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
<div class="after">Goodbye</div>
</a>
<p>some text after the shortcode</p>

1 个回复
SO网友:bonger

我认为这样说很安全wpautop() 是一个不会伤害任何人感情的篮子,但我不会移除&;按不同的优先级添加它,因为这只会让事情变得更糟,正如所示(尽管您发布的内容是浏览器试图理解损坏的html,而不是实际的输出,而实际的输出只有<a> 标记一次)。

为了修复以正常优先级生成的损坏html,我发现将此代码应用于短代码内容可以解决大多数问题:

function cleanup_sc_content( $sc_content ) {
    $sc_content = force_balance_tags( $sc_content );
    $sc_content = preg_replace( \'/<p>\\s*+(<br\\s*\\/*>)?\\s*<\\/p>/i\', \'\', $sc_content );
    return $sc_content;
}
这是对原始版本的重新调整(稍作修改)remove_empty_p() 作用posted 作者:Michelle,这又是由于作者:mtinsley(GithubNinnyPants,原文gist ).

要使用它,我个人不会将其添加为过滤器,而是直接将其应用于短代码内容,例如:

return \'<a\' . $link . \'>\' . $before  
   . cleanup_sc_content( do_shortcode( shortcode_unautop( $content ) ) ) 
   . $after . \'</a>\';
(注意shortcode_unautop() 还需要黑客,虽然wpautop() 在短代码的内容上运行,shortcode_unautop() 没有-是的,真的)。然而,考虑到持续不断的“修正”wpautop() 而且,许多悬而未决和令人困惑的bug(跨越数年)可能适用,也可能不适用,这种(以及任何)解决方案都将是不稳定的。