Skip to content

Instantly share code, notes, and snippets.

@seanlanglands
Created December 6, 2024 21:46
Show Gist options
  • Save seanlanglands/0f7e0395f94f7e53a265445d62baf2a5 to your computer and use it in GitHub Desktop.
Save seanlanglands/0f7e0395f94f7e53a265445d62baf2a5 to your computer and use it in GitHub Desktop.
Fix failed X/Twitter embeds by rendering them client-side when oembed has failed.
<?php
add_filter( 'the_content', 'fix_failed_twitter_embeds', 11 );
/**
* Fix failed X/Twitter embeds by rendering them client-side when oEmbed has failed.
*
* Does not prevent WordPress core's oEmbed from being attempted, which can result in
* a server-side 404 request to Twitter's API.
*
* @param string $content The post content.
*
* @return string The modified post content.
*/
function fix_failed_twitter_embeds( $content ) {
// Determine the width (for classic themes).
global $content_width;
if ( ! wp_is_block_theme() ) {
$data_width = isset( $content_width ) && ! empty( $content_width ) ? intval( $content_width ) : 500;
} else {
$data_width = 500;
}
// Ensure the width stays within Twitter's constraints (220px to 550px).
$data_width = max( 220, min( 550, $data_width ) );
// Store the original content, in case there are no matches.
$original_content = $content;
// Use regex to find raw Twitter URLs NOT inside an <a> tag.
$content = preg_replace_callback(
'/<a.*?<\/a>(*SKIP)(*F)|https?:\/\/(?:twitter\.com|x\.com)\/[a-zA-Z0-9_]+\/status\/\d+(?:\?[^\s"<]*)?(?=\s|$|<)/',
function ( $matches ) use ( $data_width ) {
$tweet_url = $matches[0];
// Wrap the raw URL in the fallback blockquote structure.
$fallback_html = sprintf(
'<blockquote class="twitter-tweet" data-width="%d"><a href="%s"></a></blockquote>',
intval( $data_width ),
esc_url( $tweet_url )
);
return $fallback_html;
},
$content
);
// If no match, return the original content and return early, so no need to enqueue enqueue_twitter_widgets_script.
if ( null === $content ) {
return $original_content;
}
// (Maybe) add the required widgets.js script.
add_action( 'wp_footer', 'enqueue_twitter_widgets_script' );
return $content;
}
/**
* Enqueue the Twitter widgets.js script (once). Omit for themes that include it already.
*/
function enqueue_twitter_widgets_script() {
static $twitter_script_enqueued = false;
if ( ! $twitter_script_enqueued ) {
echo '<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>';
$twitter_script_enqueued = true;
}
}
add_filter('add_post_metadata', 'prevent_bad_oembed_cache', 10, 5);
add_filter('update_post_metadata', 'prevent_bad_oembed_cache', 10, 5);
/**
* Prevents the addition or update of oEmbed metadata with the value '{{unknown}}'.
*/
function prevent_bad_oembed_cache($check, $object_id, $meta_key, $meta_value, $prev_value) {
if (strpos($meta_key, '_oembed_') === 0 && $meta_value === '{{unknown}}') {
return true; // Short-circuit the meta update/addition.
}
return null; // Proceed with the normal meta update/addition.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment