Filtering WordPress oEmbed provider list

How would I filter the WordPress oEmbed provider list? My aim is to allow just Twitter and Youtube.

EDIT: Could I do something like this?

Read More
function filter_oembed_provider_list( $array ) {
    $array = array( 'http://youtu.be/*' => array( 'http://www.youtube.com/oembed',                     false ) );
    return $array;
}
add_filter( 'oembed_providers', 'filter_oembed_provider_list' );

But this doesn’t seem to work.

Please see the relevant code in class-oembed.php:

apply_filters( 'oembed_providers', array(
        '#https?://(www.)?youtube.com/watch.*#i'           => array( 'http://www.youtube.com/oembed',                     true  ),
        'http://youtu.be/*'                                  => array( 'http://www.youtube.com/oembed',                     false ),
        'http://blip.tv/*'                                   => array( 'http://blip.tv/oembed/',                            false ),
        '#https?://(www.)?vimeo.com/.*#i'                  => array( 'http://vimeo.com/api/oembed.{format}',              true  ),
        '#https?://(www.)?dailymotion.com/.*#i'            => array( 'http://www.dailymotion.com/services/oembed',        true  ),
        'http://dai.ly/*'                                    => array( 'http://www.dailymotion.com/services/oembed',        false ),
        '#https?://(www.)?flickr.com/.*#i'                 => array( 'http://www.flickr.com/services/oembed/',            true  ),
        'http://flic.kr/*'                                   => array( 'http://www.flickr.com/services/oembed/',            false ),
        '#https?://(.+.)?smugmug.com/.*#i'                 => array( 'http://api.smugmug.com/services/oembed/',           true  ),
        '#https?://(www.)?hulu.com/watch/.*#i'             => array( 'http://www.hulu.com/api/oembed.{format}',           true  ),
        '#https?://(www.)?viddler.com/.*#i'                => array( 'http://lab.viddler.com/services/oembed/',           true  ),
        'http://qik.com/*'                                   => array( 'http://qik.com/api/oembed.{format}',                false ),
        'http://revision3.com/*'                             => array( 'http://revision3.com/api/oembed/',                  false ),
        'http://i*.photobucket.com/albums/*'                 => array( 'http://photobucket.com/oembed',                     false ),
        'http://gi*.photobucket.com/groups/*'                => array( 'http://photobucket.com/oembed',                     false ),
        '#https?://(www.)?scribd.com/.*#i'                 => array( 'http://www.scribd.com/services/oembed',             true  ),
        'http://wordpress.tv/*'                              => array( 'http://wordpress.tv/oembed/',                       false ),
        '#https?://(.+.)?polldaddy.com/.*#i'               => array( 'http://polldaddy.com/oembed/',                      true  ),
        '#https?://(www.)?funnyordie.com/videos/.*#i'      => array( 'http://www.funnyordie.com/oembed',                  true  ),
        '#https?://(www.)?twitter.com/.+?/status(es)?/.*#i'=> array( 'http://api.twitter.com/1/statuses/oembed.{format}', true  ),
        '#https?://(www.)?soundcloud.com/.*#i'             => array( 'http://soundcloud.com/oembed',                      true  ),
        '#https?://(www.)?slideshare.net/*#'               => array( 'http://www.slideshare.net/api/oembed/2',            true  ),
        '#http://instagr(.am|am.com)/p/.*#i'               => array( 'http://api.instagram.com/oembed',                   true  ),
        '#https?://(www.)?rdio.com/.*#i'                   => array( 'http://www.rdio.com/api/oembed/',                   true  ),
        '#https?://rd.io/x/.*#i'                            => array( 'http://www.rdio.com/api/oembed/',                   true  ),
        '#https?://(open|play).spotify.com/.*#i'           => array( 'https://embed.spotify.com/oembed/',                 true  ),
    ) );

Related posts

Leave a Reply

3 comments

  1. There is a built-in function wp_oembed_remove_provider, respectively wp_oembed_add_provider.

    EDIT

    add to functions.php file

    function customize_oembed() {
    
        //load oembed class
        require_once ABSPATH . DIRECTORY_SEPARATOR . 'wp-includes' . DIRECTORY_SEPARATOR . 'class-oembed.php';
    
        //get a singleton object
        $oembed = _wp_oembed_get_object();
    
        /**
         * Forget about those lines
         *
           //empty the providers list
           $oembed->providers = array();
    
           //add what you want
           wp_oembed_add_provider( 'http://site.com/watchvideo/*', 'http://site.com/oembedprovider' );  
        */
    
        //use applying a filter
        $providers = array(
            'youtube' => array( 'http://www.youtube.com/oembed', false), 
            'twitter'=> array( 'http://api.twitter.com/1/statuses/oembed.{format}', true  )
        );
        $oembed->providers = apply_filters('oembed_providers', $providers);
    }
    add_action('init', 'customize_oembed');
    

    EDIT 2

    I looked into it, and I found out, that you can use a filter oembed_providers exactly in the same way, as it is used in a constructor of the class. Therefore using additional wordpress functions, which would again try to require the class file and instantiate a singleton object, is useless, when you can do it in one function.

    (Despite of the fact, that it works, i still do not get a usage of this filter :-D)

    EDIT 3

    Finally, I got it working.

    It is really similar code to yours, though the argument in the function is basically useless. It only gives you original providers, which you want to override, so you are not using it and you can return an array directly.

    Maybe the important thing to remember is, after editing your list, you need to update your posts, since wordpress is saving some data into table *_postmeta under key _oembed_…

    function filter_oembed_provider_list( ) {
        return array( 'http://youtu.be/*' => array( 'http://www.youtube.com/oembed', false ) );
    }
    add_filter( 'oembed_providers', 'filter_oembed_provider_list' );
    
  2. If the filter you provided (oembed_providers) is working for you, then you might try something like this:

    /**
     * Filter the oembed providers through a whitelist
     *
     * @param array $providers
     * @return array $providers
     */
    function filter_oembed_provider_list( $providers )
    {
        // edit the whitelist to your needs
        $whitelist = array( 'youtu', 'twitter' );
    
        $output = array();
    
        foreach( $providers as $key => $provider )
        {
            foreach( $whitelist as $allowed )
            {
                if( stristr( $key, $allowed ) )
                    $output[$key] = $provider;
    
            }
        }
        return $output; 
    }
    
    add_filter( 'oembed_providers' , 'filter_oembed_provider_list', 99 );
    

    where you must edit the $whitelist to your needs.

    Update:

    Thanks to @Ivan Hanák, for suggesting the post saving part 😉

    This snippet should now work, after you update the oEmbed cache, by saving the post 😉

  3. I had the same need, as instagram Oembeds are broken in WordPress before 4.4.
    what I realized is that the filter for the providers run before your Theme is initialized, so if you want to add this filter, you have to use a plugin.This is what I used

    <?php
    /**
     * Plugin Name: Fix Instagram oEmbed
     * Plugin URI: https://10up.com
     * Description: Fix Instagram oEmbed.
     * Author: 10up
     * Version: 1.0.0
     * Author URI: https://10up.com
     * License: GPL2
     */
    
    namespace TenUpPluginInstagramFix;
    add_filter( 'oembed_providers', __NAMESPACE__ . '\oembed_providers' );
    
    
    function oembed_providers( $providers ) {
        if ( ! isset( $providers['#https?://(www.)?instagr(.am|am.com)/p/.*#i'] ) ) {
            $providers['#https?://(www.)?instagr(.am|am.com)/p/.*#i'] = array(
                'https://api.instagram.com/oembed',
                true
            );
        }
        return $providers;
    }
    

    so you must

    1) create a folder like instagram-oembed-fix in the plugin folder
    2) create a file named instagram-oembed-fix.php
    3) copy over the php code above
    4) activate your plugin ( network activate in a network )
    5) regenerate oEmbed cache by going to any post and presing “Save”