Skip to content

Commit 9d664d6

Browse files
authored
Embed: Add Fediverse fallback to oembed attempts (#1576)
1 parent ce1f564 commit 9d664d6

File tree

2 files changed

+63
-9
lines changed

2 files changed

+63
-9
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: added
3+
4+
Fallback embed support for Fediverse content that lacks native oEmbed responses.

includes/class-embed.php

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
namespace Activitypub;
99

10-
use WP_REST_Response;
11-
1210
/**
1311
* Class to handle embedding ActivityPub content
1412
*/
@@ -18,8 +16,9 @@ class Embed {
1816
* Initialize the embed handler
1917
*/
2018
public static function init() {
21-
add_filter( 'pre_oembed_result', array( __CLASS__, 'maybe_use_activitypub_embed' ), 10, 3 );
22-
add_filter( 'oembed_dataparse', array( __CLASS__, 'handle_filtered_oembed_result' ), 11, 3 );
19+
\add_filter( 'pre_oembed_result', array( self::class, 'maybe_use_activitypub_embed' ), 10, 3 );
20+
\add_filter( 'oembed_dataparse', array( self::class, 'handle_filtered_oembed_result' ), 11, 3 );
21+
\add_filter( 'oembed_request_post_id', array( self::class, 'register_fallback_hook' ) );
2322
}
2423

2524
/**
@@ -131,13 +130,13 @@ public static function get_html_for_object( $activity_object, $inline_css = true
131130
*/
132131
public static function has_real_oembed( $url, $args = array() ) {
133132
// Temporarily remove our filter to avoid infinite loops.
134-
remove_filter( 'pre_oembed_result', array( __CLASS__, 'maybe_use_activitypub_embed' ), 10, 3 );
133+
\remove_filter( 'pre_oembed_result', array( self::class, 'maybe_use_activitypub_embed' ), 10, 3 );
135134

136135
// Try to get a "real" oEmbed result. If found, it'll be cached to avoid unnecessary HTTP requests in `wp_oembed_get`.
137-
$oembed_result = wp_oembed_get( $url, $args );
136+
$oembed_result = \wp_oembed_get( $url, $args );
138137

139138
// Add our filter back.
140-
add_filter( 'pre_oembed_result', array( __CLASS__, 'maybe_use_activitypub_embed' ), 10, 3 );
139+
\add_filter( 'pre_oembed_result', array( self::class, 'maybe_use_activitypub_embed' ), 10, 3 );
141140

142141
return false !== $oembed_result;
143142
}
@@ -192,12 +191,12 @@ public static function handle_filtered_oembed_result( $html, $data, $url ) {
192191
}
193192

194193
// If this isn't a rich or video type, we can't help.
195-
if ( ! isset( $data->type ) || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) {
194+
if ( ! isset( $data->type ) || ! \in_array( $data->type, array( 'rich', 'video' ), true ) ) {
196195
return $html;
197196
}
198197

199198
// If there's no HTML in the data, we can't help.
200-
if ( empty( $data->html ) || ! is_string( $data->html ) ) {
199+
if ( empty( $data->html ) || ! \is_string( $data->html ) ) {
201200
return $html;
202201
}
203202

@@ -210,4 +209,55 @@ public static function handle_filtered_oembed_result( $html, $data, $url ) {
210209
// Return our safer ActivityPub embed HTML.
211210
return $activitypub_html;
212211
}
212+
213+
/**
214+
* Register the fallback hook for oEmbed requests.
215+
*
216+
* Avoids filtering every single API request.
217+
*
218+
* @param int $post_id The post ID.
219+
* @return int The post ID.
220+
*/
221+
public static function register_fallback_hook( $post_id ) {
222+
\add_filter( 'rest_request_after_callbacks', array( self::class, 'oembed_fediverse_fallback' ), 10, 3 );
223+
224+
return $post_id;
225+
}
226+
227+
/**
228+
* Fallback for oEmbed requests to the Fediverse.
229+
*
230+
* @param \WP_REST_Response|\WP_Error $response Result to send to the client.
231+
* @param array $handler Route handler used for the request.
232+
* @param \WP_REST_Request $request Request used to generate the response.
233+
*
234+
* @return \WP_REST_Response|\WP_Error The response to send to the client.
235+
*/
236+
public static function oembed_fediverse_fallback( $response, $handler, $request ) {
237+
if ( is_wp_error( $response ) && 'oembed_invalid_url' === $response->get_error_code() ) {
238+
$url = $request->get_param( 'url' );
239+
$html = get_embed_html( $url );
240+
241+
if ( $html ) {
242+
$args = $request->get_params();
243+
$data = (object) array(
244+
'provider_name' => 'Embed Handler',
245+
'html' => $html,
246+
'scripts' => array(),
247+
);
248+
249+
/** This filter is documented in wp-includes/class-wp-oembed.php */
250+
$data->html = apply_filters( 'oembed_result', $data->html, $url, $args );
251+
252+
/** This filter is documented in wp-includes/class-wp-oembed-controller.php */
253+
$ttl = apply_filters( 'rest_oembed_ttl', DAY_IN_SECONDS, $url, $args );
254+
255+
set_transient( 'oembed_' . md5( serialize( $args ) ), $data, $ttl ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
256+
257+
$response = new \WP_REST_Response( $data );
258+
}
259+
}
260+
261+
return $response;
262+
}
213263
}

0 commit comments

Comments
 (0)