2

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.

  • "but I don't understand why the # is there and the /'s are not escaped" - We can use other delimiters than the forward slash (/) to increase the readability, to avoid the frequent \/ escaping. More about it in the PHP docs here where it says: "When using the PCRE functions, it is required that the pattern is enclosed by delimiters. A delimiter can be any non-alphanumeric, non-backslash, non-whitespace character." – birgire Apr 29 '16 at 10:08
  • Oh, perfect! Thanks so much for clarifying that for me @birgire – Tim Malone Apr 29 '16 at 10:24
2

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.

  • I think there's still stuff I don't get about oembeds though. As a test, I tried removing the Facebook endpoint I added, and the embed still works. I'm not running any caching plugins nor caching anything myself, Facebook definitely isn't with the defaults in /wp-includes/class-oembed.php, and oembed providers appear to be added at runtime not stored in the DB. scratches head At least it's working! – Tim Malone Apr 29 '16 at 1:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.