77
88namespace 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