Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
58.62% covered (warning)
58.62%
17 / 29
0.00% covered (danger)
0.00%
0 / 2
CRAP
n/a
0 / 0
jetpack_proxy_twitter_oembed_provider
52.94% covered (warning)
52.94%
9 / 17
0.00% covered (danger)
0.00%
0 / 1
9.75
jetpack_twitter_oembed_remote_get_args
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
3.01
1<?php
2/**
3 * Twitter/X oEmbed proxy functionality.
4 *
5 * This file handles proxying Twitter/X oEmbed requests through Automattic's infrastructure
6 * to minimize issues with rate limiting with 404 responses from Twitter/X.
7 *
8 * Unlike tweet.php which handles the [tweet] shortcode, this file provides core oEmbed support
9 * and is force-loaded via module-extras.php regardless of module status.
10 *
11 * @package automattic/jetpack
12 * @since 14.5
13 */
14
15use Automattic\Jetpack\Connection\Client;
16use Automattic\Jetpack\Constants;
17use Automattic\Jetpack\Status;
18
19if ( ! defined( 'ABSPATH' ) ) {
20    exit( 0 );
21}
22
23/**
24 * Update Twitter providers to use Automattic's Twitter/X oEmbed proxy.
25 *
26 * See paFLeq-3QD-p2.
27 *
28 * @param string $provider The URL of the oEmbed provider.
29 *
30 * @return string The modified URL of the oEmbed provider.
31 */
32function jetpack_proxy_twitter_oembed_provider( $provider ) {
33    if ( ! wp_startswith( $provider, 'https://publish.twitter.com/oembed' ) ) {
34        return $provider;
35    }
36
37    // Allow other plugins to override the proxy URL. This constant should be set on the WordPress.com side
38    // to handle proxying after we're authenticated the request with the Jetpack token.
39    $oembed_proxy_url = Constants::is_defined( 'JETPACK__TWITTER_OEMBED_PROXY_URL' )
40        ? Constants::get_constant( 'JETPACK__TWITTER_OEMBED_PROXY_URL' )
41        : '';
42
43    // If we don't have a proxy URL, then we'll try to proxy through the WordPress.com.
44    // To that end, we need to make sure that we're connected to WP.com and that we're not in offline mode.
45    if ( empty( $oembed_proxy_url ) ) {
46        if ( ! Jetpack::is_connection_ready() || ( new Status() )->is_offline_mode() ) {
47            return $provider;
48        }
49
50        $oembed_proxy_url = esc_url_raw(
51            sprintf(
52                '%s/wpcom/v2/oembed-proxy',
53                JETPACK__WPCOM_JSON_API_BASE,
54                Jetpack_Options::get_option( 'id' )
55            )
56        );
57
58        add_filter( 'oembed_remote_get_args', 'jetpack_twitter_oembed_remote_get_args', 10, 2 );
59    }
60
61    return str_replace( 'https://publish.twitter.com/oembed', $oembed_proxy_url, $provider );
62}
63add_filter( 'oembed_fetch_url', 'jetpack_proxy_twitter_oembed_provider', 10 );
64
65/**
66 * Add JP auth headers if we're proxying through WP.com.
67 *
68 * @param array  $args oEmbed remote get arguments.
69 * @param string $url  URL to be inspected.
70 */
71function jetpack_twitter_oembed_remote_get_args( $args, $url ) {
72    if ( ! wp_startswith( $url, Constants::get_constant( 'JETPACK__WPCOM_JSON_API_BASE' ) ) ) {
73        return $args;
74    }
75
76    $method         = 'GET';
77    $signed_request = Client::build_signed_request(
78        compact( 'url', 'method' )
79    );
80
81    if ( is_wp_error( $signed_request ) ) {
82        return $args;
83    }
84
85    return $signed_request['request'];
86}