Getting results from wp_oembed_add_provider

I’m having trouble getting results from wp_oembed_add_provider().

I’m developing a site which needs to embed video content from Facebook, and I came across this handy list of Facebook URL structures.

The one I’m focusing on to start with is #https?://(www\.)?facebook\.com/.*/videos/.*#i as this matches the video I’m testing with.

Side point: This may or may not be an issue, but I don’t understand why the # is there and the /‘s are not escaped, as these practices usually would not be valid in a regex (according to my limited understanding of regexes). However, it does match the format of the YouTube example in the codex.

This is in my theme’s functions.php:

add_action("init", function(){

    wp_oembed_add_provider(
        '#https?://(www\.)?facebook\.com/.*/videos/.*#i',
        'https://www.facebook.com/plugins/video/oembed.json/',
        true
    );

});

The URL I’m attempting to match is: https://www.facebook.com/899lightfm/videos/972261526144646/

And the endpoint for Facebook seems to be correct, as https://www.facebook.com/plugins/video/oembed.json/?url=https://www.facebook.com/899lightfm/videos/972261526144646/ returns a valid response.

In a post, I have the video URL on its own line, followed by a similar YouTube URL on its own line. The YouTube URL is successfully detected and turned into an oembed – as one would expect, given WordPress supports it natively – but the Facebook URL does not get modified and instead is just printed out in plain text.

Am I using and hooking wp_oembed_add_provider() correctly? Is there something else I should be doing so WordPress picks this up?

EDIT: I did try hooking into after_setup_theme in case init was too late, but am getting the same problem. Around the web init seemed to be the more common action to hook wp_oembed_add_provider() into.

1 Answer
1

Ok I managed to solve this!

Did some digging through how the embed system works, and it turns out it wasn’t the use of wp_oembed_add_provider() that was wrong. Debugging autoembed_callback() in wp-includes\class-wp-embed.php showed that my YouTube URL was coming through but my Facebook URL never made it to this function.

Echo’ing the post content before it went through the autoembed() function (hooked to the_content()) showed that for some reason, the Facebook URL was ‘not on a new line’ as required by autoembed() and was wrapped in <p></p> tags, and part of another line, even though it was clearly on its own new line in the editor.

I’m not sure why the FB URL didn’t make it to its own line, but taking a cue from how autoembed() works, I’ve added the following to my functions.php:

add_filter("the_content", function($content){

    // Find URLs that are on their own line but are wrapped in <p></p> tags

    return preg_replace_callback(
        '|^\<p\>(\s*)(https?://[^\s"]+)(\s*)\</p\>$|im',
        array($GLOBALS["wp_embed"], "autoembed_callback"),
        $content
    );

}, 11);

As long as this runs after wpautop() (which runs on the_content at default priority 10), both links are correctly moved to a new line, wrapped in <p></p> tags, and this function sends the detected URLs through to the autoembed_callback, at which point everything kicks in as it should.

Whew. So the real problem is something to do with line breaks, and possibly the way WordPress detects URLs to auto embed. I imagine that regex in core could probably be better in order to pick up edge cases, but hopefully this additional function catches that issue for now. I’ll update this if I come across any additional issues that this causes.

Leave a Comment