禁用单个短码或至少所有内部链接的oEmed

时间:2016-07-13 作者:Sledge Hammer

是否有任何方法仅对的特定调用禁用oEmbed功能do_shortcode() 功能仅在一个脚本中实现,或者如果无法实现,是否可以对当前运行WordPress 4.5.3的站点上的所有内部链接禁用该功能?

我试过用这句话,但没有效果:

wp_oembed_remove_provider( \'http://www.example.com/*\' );
到目前为止,唯一有用的是这句话:

remove_filter( \'the_content\', array( $GLOBALS[\'wp_embed\'], \'autoembed\' ), 8 );
但据我所知,它禁用了所有oEmbed内容,而不仅仅是内部链接。

1 个回复
最合适的回答,由SO网友:birgire 整理而成

在此,我们考虑以下问题:

对于当前运行WordPress 4.5.3的站点上的所有内部链接,是否可以禁用后期嵌入?

如果我们想禁用后嵌入internal links, 但允许在外部网站上使用,然后我们可以使用:

/**
 * Disable post embeds for internal links but allow it on external sites
 */
add_filter( \'pre_oembed_result\', function( $result, $url, $args )
{    
    if( parse_url( home_url(), PHP_URL_HOST ) ===  parse_url( $url, PHP_URL_HOST ) )
        $result = false;

    return $result;

}, PHP_INT_MAX, 3 );
这里我们检查链接是否针对当前主机。这可以根据我们的需要进一步调整。

因此,我们不需要此筛选器回调:

add_action( \'init\', function()
{
    remove_filter( \'pre_oembed_result\', \'wp_filter_pre_oembed_result\', 10 );
} );
可能还有其他人。

请注意,默认情况下,嵌入缓存24小时。这里有一些examples 如何重新生成它。

很抱歉下面的内容太长,但我决定把它写下来,以便更好地理解;-)

粘贴帖子url时的较长版本:

http://example.tld/hello-world
在可视化编辑器中,然后

[embed]http://example.tld/hello-world[/embed]
发送到wp_ajax_parse_embed() 通过ajax请求调用$wp_embed->run_shortcode().

类似地,内容通过$wp_embed->autoembed()$wp_embed->run_shortcode() 通过the_content 滤器

两者都基于WP_Embed::shortcode() 方法src

Within the shortcode method

如果数据没有缓存在post meta中,那么wp_oembed_get() 启动,包括以下顺序:

WP_oEmbed::get_html()
    WP_oEmbed::fetch()
        WP_oEmbed::_fetch_with_format()
            wp_safe_remote_get()
            wp_remote_retrieve_body()
并通过以下请求获取数据:

http://example.tld/wp-json/oembed/1.0/embed?url=http%3A%2F%2Fexample.tld%2Fhello-world%2F&
maxwidth=900&maxheight=1000&format=json
此rest端点使用get_oembed_response_data() 函数,并应用oembed_request_post_id 过滤器src

此过滤器是在中引入的#36767 在WordPress版本4.5.3中。

默认情况下,链接发现处于活动状态。这意味着我们会收到一个额外的请求wp_safe_remote_get() 能够分析相关<link> 远程站点的标签,用于确定provder的url:

http://example.tld/wp-json/oembed/1.0/embed?url=http%3A%2F%2Fexample.tld%2Fhello-world%2F

The pre_oembed_result filter

中还引入了一种新的过滤器#36767, 在内部WP_oEmbed::get_html() src

$pre = apply_filters( \'pre_oembed_result\', null, $url, $args ); 

if ( null !== $pre ) { 
    return $pre; 
}    
避免外部HTTP请求内部链接。它将使wp_oembed_get() 如果筛选器返回除null.

在core中,我们现在有:

add_filter( \'pre_oembed_result\', \'wp_filter_pre_oembed_result\', 10, 3 );
过滤器的回调wp_filter_pre_oembed_result() 使用生成数据get_oembed_response_data() 函数,就像嵌入rest端点一样。它可以通过oembed_response_data 滤器这个get_oembed_response_data_rich() 回调通过以下方式连接到其中:

add_filter( \'oembed_response_data\',   \'get_oembed_response_data_rich\', 10, 4 ); 
它包含get_post_embed_html() 生成<blockquote>, <script><iframe> 密码

Disable internal post embeds

为了禁用内部链接的post嵌入,我们的建议是确保pre_oembed_result 筛选器返回false (不同于null):

/**
 * Disable post embeds for internal links but allow it on external sites
 */
add_filter( \'pre_oembed_result\', function( $result, $url, $args )
{    
    if( parse_url( home_url(), PHP_URL_HOST ) ===  parse_url( $url, PHP_URL_HOST ) )
        $result = false;
    return $result;

}, PHP_INT_MAX, 3 );
其中,我们尽可能晚地返回false,因此我们使用一个大的优先级PHP_INT_MAX.

那么我们不需要wp_filter_pre_oembed_result() 回调以运行,因此我们还可以通过以下方式删除它:

remove_filter( \'pre_oembed_result\', \'wp_filter_pre_oembed_result\', 10 );
我们必须以与添加时相同的优先级删除它。

另一种方法是:

add_filter( \'oembed_request_post_id\', \'__return_false\' );
这意味着我们将通过错误向rest端点发送HTTP请求,因为post id无效。

Simple Testing

这里有一个测试方法。首先,我们需要WP_Embed 类别:

$e = new WP_Embed(); 
或使用全局$wp_embed 对象然后,我们设置内部和外部帖子链接:

$internal = \'http://internal.tld/hello-world/\';
$external = \'http://external.tld/hello-world/\';
并运行:

$internal_is_embeddable = $internal !== $e->run_shortcode( 
    sprintf( \'[embed]%s[/embed]\', 
    $internal 
);

$external_is_embeddable = $external !== $e->run_shortcode( 
    sprintf( \'[embed]%s[/embed]\', 
    $external 
);
我们还可以使用以下方法进行测试,无需使用短代码:

$internal_is_embeddable = $internal !== $e->autoembed( $internal );
$external_is_embeddable = $external !== $e->autoembed( $external );
我们只需要知道oembed(post-meta)缓存,并为测试链接使用缓存破坏参数。这里有一些examples 如何重新生成它。

相关推荐

Show form per shortcode

这是我的密码。我想按短代码显示它。$user_id = get_current_user_id(); $balance = mycred_get_users_balance( $user_id ); echo "Current Balance: ".$balance."<br><br>"; if ($_POST && $_SERVER["REQUEST_METHOD"] == &qu