web-dev-qa-db-ja.com

単一のショートコードまたは少しでもすべての内部リンクに対してoEmbedを無効にする

1つのスクリプト内でdo_shortcode()関数を特定の呼び出しに対してのみoEmbed機能を無効にする方法はありますか。それが不可能な場合は、現在WordPress 4.5.3を実行しているサイトのすべての内部リンクに対して無効にできますか。

私はこの行を使ってみましたが、効果がありませんでした:

wp_oembed_remove_provider( 'http://www.example.com/*' );

これまでのところ、やや有用なのはこの行だけです。

remove_filter( 'the_content', array( $GLOBALS['wp_embed'], 'autoembed' ), 8 );

しかし、私の知る限りでは、内部リンクだけでなくすべてのoEmbedコンテンツを無効にします。

2
Sledge Hammer

ここで私たちは質問を考えます:

埋め込みを投稿 現在WordPress 4.5.3を実行しているサイトのすべての内部リンクに対して無効にできますか。

短編ストーリー

ポスト埋め込み of 内部リンクを無効にしたいが、外部サイトでは許可する場合は、次のようにします。

/**
 * 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時間キャッシュされることに注意してください。これを再生成する方法をいくつか の例 で示します。

以下の長い部分で申し訳ありませんが、理解を深めるために書き留めておくことにしました;-)

長いバージョン

投稿のURLを貼り付けると、

http://example.tld/hello-world

ビジュアルエディタで

[embed]http://example.tld/hello-world[/embed]

ajaxリクエストを介してwp_ajax_parse_embed()関数に送信され、そこで$wp_embed->run_shortcode()が呼び出されます。

同様に、コンテンツはthe_contentフィルタを介して$wp_embed->autoembed()および$wp_embed->run_shortcode()を通してフィルタリングされます。

どちらもWP_Embed::shortcode()メソッドに基づいています src

ショートコードメソッド内

データがポストメタでキャッシュされていない場合、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

この静止エンドポイントは、get_oembed_response_data()関数でデータを生成し、oembed_request_post_idフィルタも適用します src

このフィルタはWordPressバージョン4.5.3の #36767 で導入されました。

デフォルトでは リンク検出 はアクティブです。つまり、リモートサイトから関連する<link>タグを解析して、提供者のURLを特定できるようにするために、wp_safe_remote_get()を指定した追加のリクエストを受け取ることになります。

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

pre_oembed_resultフィルタ

WP_oEmbed::get_html()内の #36767 にも新しいフィルタが導入されました。 src

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

if ( null !== $pre ) { 
    return $pre; 
}    

内部リンクに対する外部HTTP要求を回避するため。フィルタがnull以外のものを返す場合、wp_oembed_get()を短絡します。

コアには、次のものがあります。

add_filter( 'pre_oembed_result', 'wp_filter_pre_oembed_result', 10, 3 );

フィルタのコールバックwp_filter_pre_oembed_result()は、埋め込み残りのエンドポイントと同じように、get_oembed_response_data()関数を使用してデータを生成します。それはoembed_response_dataフィルタを通してフィルタリング可能です。 get_oembed_response_data_rich()コールバックは次のコードでフックされています。

add_filter( 'oembed_response_data',   'get_oembed_response_data_rich', 10, 4 ); 

<blockquote><script>および<iframe>コードを生成するget_post_embed_html()関数が含まれています。

内部投稿の埋め込みを無効にする

内部リンクの投稿埋め込みを無効にするには、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のように大きな priority を使います。

それならwp_filter_pre_oembed_result()コールバックを実行する必要はないので、それを削除することもできます。

remove_filter( 'pre_oembed_result', 'wp_filter_pre_oembed_result', 10 );

それが追加されたのと同じ優先順位でそれを削除しなければならないところ。

別の方法としては、次のものがあります。

add_filter( 'oembed_request_post_id', '__return_false' );

これは、投稿IDが有効でないためにエラーを通過するHTTPリクエストを残りのエンドポイントに送信することを意味します。

簡単なテスト

これをテストする方法は次のとおりです。まず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 );

私たちは、埋め込み型(post meta)キャッシュを知っているだけでいいのです。テストリンクのキャッシュ無効化パラメータ。これを再生成する方法をいくつか の例 で示します。

3
birgire