Make WordPress Core

Ticket #13172: class-oembed.php

File class-oembed.php, 23.2 KB (added by artgibby, 15 years ago)

class-oembed.php with 53 more providers

Line 
1<?php
2/**
3 * API for fetching the HTML to embed remote content based on a provided URL.
4 * Used internally by the {@link WP_Embed} class, but is designed to be generic.
5 *
6 * @link http://codex.wordpress.org/oEmbed oEmbed Codex Article
7 * @link http://oembed.com/ oEmbed Homepage
8 *
9 * @package WordPress
10 * @subpackage oEmbed
11 */
12
13/**
14 * oEmbed class.
15 *
16 * @package WordPress
17 * @subpackage oEmbed
18 * @since 2.9.0
19 */
20class WP_oEmbed {
21        var $providers = array();
22
23        /**
24         * PHP4 constructor
25         */
26        function WP_oEmbed() {
27                return $this->__construct();
28        }
29
30        /**
31         * PHP5 constructor
32         *
33         * @uses apply_filters() Filters a list of pre-defined oEmbed providers.
34         */
35        function __construct() {
36                // List out some popular sites that support oEmbed.
37                // The WP_Embed class disables discovery for non-unfiltered_html users, so only providers in this array will be used for them.
38                // Add to this list using the wp_oembed_add_provider() function (see it's PHPDoc for details).
39                $this->providers = apply_filters( 'oembed_providers', array(
40                        '#http://(www\.)?youtube.com/watch.*#i'         => array( 'http://www.youtube.com/oembed',            true  ),
41                        'http://youtu.be/*'                             => array( 'http://www.youtube.com/oembed',            false ),
42                        'http://blip.tv/file/*'                         => array( 'http://blip.tv/oembed/',                   false ),
43                        '#http://(www\.)?vimeo\.com/.*#i'               => array( 'http://www.vimeo.com/api/oembed.{format}', true  ),
44                        '#http://(www\.)?dailymotion\.com/.*#i'         => array( 'http://www.dailymotion.com/api/oembed',    true  ),
45                        '#http://(www\.)?flickr\.com/.*#i'              => array( 'http://www.flickr.com/services/oembed/',   true  ),
46                        '#http://(.+)?smugmug\.com/.*#i'                => array( 'http://api.smugmug.com/services/oembed/',  true  ),
47                        '#http://(www\.)?hulu\.com/watch/.*#i'          => array( 'http://www.hulu.com/api/oembed.{format}',  true  ),
48                        '#http://(www\.)?viddler\.com/.*#i'             => array( 'http://lab.viddler.com/services/oembed/',  true  ),
49                        'http://qik.com/*'                              => array( 'http://qik.com/api/oembed.{format}',       false ),
50                        'http://revision3.com/*'                        => array( 'http://revision3.com/api/oembed/',         false ),
51                        'http://i*.photobucket.com/albums/*'            => array( 'http://photobucket.com/oembed',            false ),
52                        'http://gi*.photobucket.com/groups/*'           => array( 'http://photobucket.com/oembed',            false ),
53                        '#http://(www\.)?scribd\.com/.*#i'              => array( 'http://www.scribd.com/services/oembed',    true  ),
54                        'http://wordpress.tv/*'                         => array( 'http://wordpress.tv/oembed/',              false ),
55                        '#http://(answers|surveys)\.polldaddy.com/.*#i' => array( 'http://polldaddy.com/oembed/',             true  ),
56                        '#http://(www\.)?funnyordie\.com/videos/.*#i'   => array( 'http://www.funnyordie.com/oembed',         true  ),
57                        '#http://www\.veoh\.com/.*/watch/.*'            => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
58                        '#http://.*justin\.tv/.*'                       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
59                        '#http://.*justin\.tv/.*/b/.*'                  => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
60                        '#http://www\.ustream\.tv/recorded/.*'          => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
61                        '#http://www\.ustream\.tv/channel/.*'           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
62                        '#http://www\.collegehumor\.com/video:.*'       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
63                        '#http://.*twitvid\.com/.*'                     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
64                        '#http://www\.break\.com/.*/.*'                 => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
65                        '#http://vids\.myspace\.com/index\.cfm\?'+\
66                        'fuseaction=vids\.individual&videoid.*'         => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
67                        '#http://www\.myspace\.com/index\.cfm\?'+\
68                        'fuseaction=.*&videoid.*'                       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
69                        '#http://www\.metacafe\.com/watch/.*'           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
70                        '#http://video\.google\.com/videoplay\?.*'      => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
71                        '#http://.*revver\.com/video/.*'                => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
72                        '#http://video\.yahoo\.com/watch/.*/.*'         => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
73                        '#http://video\.yahoo\.com/network/.*'          => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
74                        '#http://liveleak\.com/view\?.*'                => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
75                        '#http://www\.liveleak\.com/view\?.*'           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
76                        '#http://animoto\.com/play/.*'                  => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
77                        '#http://dotsub\.com/view/.*'                   => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
78                        '#http://www\.overstream\.net/view\.php\?oid=.*'=> array( 'http://api.embed.ly/v1/api/oembed',        true  ),
79                        '#http://.*yfrog\..*/.*'                        => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
80                        '#http://tweetphoto\.com/.*'                    => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
81                        '#http://.*twitpic\.com/.*'                     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
82                        '#http://.*imgur\.com/.*'                       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
83                        '#http://.*\.posterous\.com/.*'                 => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
84                        '#http://post\.ly/.*'                           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
85                        '#http://twitgoo\.com/.*'                       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
86                        '#http://i.*\.photobucket\.com/albums/.*'       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
87                        '#http://gi.*\.photobucket\.com/groups/.*'      => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
88                        '#http://phodroid\.com/.*/.*/.*'                => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
89                        '#http://xkcd\.com/.*'                          => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
90                        '#http://www\.asofterworld\.com'+\
91                        '/index\.php\?id=.*'                            => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
92                        '#http://www\.qwantz\.com/index\.php\?comic=.*' => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
93                        '#http://23hq\.com/.*/photo/.*'                 => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
94                        '#http://www\.23hq\.com/.*/photo/.*'            => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
95                        '#http://.*dribbble\.com/shots/.*'              => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
96                        '#http://drbl\.in/.*'                           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
97                        '#http://www\.whitehouse\.gov/'+\
98                        'photos-and-video/video/.*'                     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
99                        '#http://www\.whitehouse\.gov/video/.*'         => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
100                        '#http://wh\.gov/photos-and-video/video/.*'     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
101                        '#http://wh\.gov/video/.*'                      => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
102                        '#http://movieclips\.com/watch/.*/.*/'          => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
103                        '#http://movieclips\.com/watch/.*/.*/.*/.*'     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
104                        '#http://.*crackle\.com/c/.*'                   => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
105                        '#http://www\.fancast\.com/.*/videos'           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
106                        '#http://www\.funnyordie\.com/videos/.*'        => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
107                        '#http://www\.vimeo\.com/groups/.*/videos/.*'   => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
108                        '#http://www\.vimeo\.com/.*'                    => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
109                        '#http://vimeo\.com/groups/.*/videos/.*'        => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
110                        '#http://vimeo\.com/.*'                         => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
111                        '#http://www\.ted\.com/talks/.*\.html.*'        => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
112                        '#http://www\.ted\.com/talks/'+\
113                        'lang/.*/.*\.html.*'                            => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
114                        '#http://www\.ted\.com/index\.php/'+\
115                        'talks/.*\.html.*'                              => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
116                        '#http://www\.ted\.com/index\.php/talks/'+\
117                        'lang/.*/.*\.html.*'                            => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
118                        '#http://.*omnisio\.com/.*'                     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
119                        '#http://.*nfb\.ca/film/.*'                     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
120                        '#http://www\.thedailyshow\.com/watch/.*'       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
121                        '#http://www\.thedailyshow\.com/'+\
122                        'full-episodes/.*'                              => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
123                        '#http://www\.thedailyshow\.com/'+\
124                        'collection/.*/.*/.*'                           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
125                        '#http://movies\.yahoo\.com/movie/.*/video/.*'  => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
126                        '#http://movies\.yahoo\.com/movie/.*/info'      => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
127                        '#http://movies\.yahoo\.com/movie/.*/trailer'   => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
128                        '#http://www\.colbertnation\.com/'+\
129                        'the-colbert-report-collections/.*'             => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
130                        '#http://www\.colbertnation\.com/'+\
131                        'full-episodes/.*'                              => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
132                        '#http://www\.colbertnation\.com/'+\
133                        'the-colbert-report-videos/.*'                  => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
134                        '#http://www\.comedycentral\.com/'+\
135                        'videos/index\.jhtml\?.*'                       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
136                        '#http://www\.theonion\.com/video/.*'           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
137                        '#http://theonion\.com/video/.*'                => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
138                        '#http://wordpress\.tv/.*/.*/.*/.*/'            => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
139                        '#http://www\.traileraddict\.com/trailer/.*'    => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
140                        '#http://www\.traileraddict\.com/clip/.*'       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
141                        '#http://www\.traileraddict\.com/poster/.*'     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
142                        '#http://www\.escapistmagazine\.com/videos/.*'  => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
143                        '#http://www\.trailerspy\.com/trailer/.*/.*'    => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
144                        '#http://www\.trailerspy\.com/trailer/.*'       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
145                        '#http://www\.trailerspy\.com/view_video\.php.*'=> array( 'http://api.embed.ly/v1/api/oembed',        true  ),
146                        '#http://soundcloud\.com/.*'                    => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
147                        '#http://soundcloud\.com/.*/.*'                 => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
148                        '#http://soundcloud\.com/.*/sets/.*'            => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
149                        '#http://soundcloud\.com/groups/.*'             => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
150                        '#http://www\.lala\.com/#album/.*'              => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
151                        '#http://www\.lala\.com/album/.*'               => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
152                        '#http://www\.lala\.com/#song/.*'               => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
153                        '#http://www\.lala\.com/song/.*'                => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
154                        '#http://.*amazon\..*/gp/product/.*'            => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
155                        '#http://.*amazon\..*/.*/dp/.*'                 => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
156                        '#http://.*amazon\..*/dp/.*'                    => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
157                        '#http://.*amazon\..*/o/ASIN/.*'                => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
158                        '#http://.*amazon\..*/gp/offer-listing/.*'      => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
159                        '#http://.*amazon\..*/.*/ASIN/.*'               => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
160                        '#http://.*amazon\..*/gp/product/images/.*'     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
161                        '#http://www\.amzn\.com/.*'                     => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
162                        '#http://amzn\.com/.*'                          => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
163                        '#http://twitter\.com/.*/status/.*'             => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
164                        '#http://twitter\.com/.*/statuses/.*'           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
165                        '#http://www\.slideshare\.net/.*/.*'            => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
166                        '#http://screenr\.com/.*'                       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
167                        '#http://www\.5min\.com/Video/.*'               => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
168                        '#http://www\.howcast\.com/videos/.*'           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
169                        '#http://www\.screencast\.com/.*/media/.*'      => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
170                        '#http://screencast\.com/.*/media/.*'           => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
171                        '#http://www\.screencast\.com/t/.*'             => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
172                        '#http://screencast\.com/t/.*'                  => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
173                        '#http://www\.clearspring\.com/widgets/.*'      => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
174                        '#http://my\.opera\.com/.*/'+\
175                        'albums/show\.dml\?id=.*'                       => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
176                        '#http://my\.opera\.com/.*/albums/'+\
177                        'showpic\.dml\?album=.*&picture=.*'             => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
178                        '#http://tumblr\.com/.*'                        => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
179                        '#http://.*\.tumblr\.com/post/.*'               => array( 'http://api.embed.ly/v1/api/oembed',        true  ),
180                ) );
181
182                // Fix any embeds that contain new lines in the middle of the HTML which breaks wpautop().
183                add_filter( 'oembed_dataparse', array(&$this, '_strip_newlines'), 10, 3 );
184        }
185
186        /**
187         * The do-it-all function that takes a URL and attempts to return the HTML.
188         *
189         * @see WP_oEmbed::discover()
190         * @see WP_oEmbed::fetch()
191         * @see WP_oEmbed::data2html()
192         *
193         * @param string $url The URL to the content that should be attempted to be embedded.
194         * @param array $args Optional arguments. Usually passed from a shortcode.
195         * @return bool|string False on failure, otherwise the UNSANITIZED (and potentially unsafe) HTML that should be used to embed.
196         */
197        function get_html( $url, $args = '' ) {
198                $provider = false;
199
200                if ( !isset($args['discover']) )
201                        $args['discover'] = true;
202
203                foreach ( $this->providers as $matchmask => $data ) {
204                        list( $providerurl, $regex ) = $data;
205
206                        // Turn the asterisk-type provider URLs into regex
207                        if ( !$regex )
208                                $matchmask = '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $matchmask ), '#' ) ) . '#i';
209
210                        if ( preg_match( $matchmask, $url ) ) {
211                                $provider = str_replace( '{format}', 'json', $providerurl ); // JSON is easier to deal with than XML
212                                break;
213                        }
214                }
215
216                if ( !$provider && $args['discover'] )
217                        $provider = $this->discover( $url );
218
219                if ( !$provider || false === $data = $this->fetch( $provider, $url, $args ) )
220                        return false;
221
222                return apply_filters( 'oembed_result', $this->data2html( $data, $url ), $url, $args );
223        }
224
225        /**
226         * Attempts to find oEmbed provider discovery <link> tags at the given URL.
227         *
228         * @param string $url The URL that should be inspected for discovery <link> tags.
229         * @return bool|string False on failure, otherwise the oEmbed provider URL.
230         */
231        function discover( $url ) {
232                $providers = array();
233
234                // Fetch URL content
235                if ( $html = wp_remote_retrieve_body( wp_remote_get( $url ) ) ) {
236
237                        // <link> types that contain oEmbed provider URLs
238                        $linktypes = apply_filters( 'oembed_linktypes', array(
239                                'application/json+oembed' => 'json',
240                                'text/xml+oembed' => 'xml',
241                                'application/xml+oembed' => 'xml', // Incorrect, but used by at least Vimeo
242                        ) );
243
244                        // Strip <body>
245                        $html = substr( $html, 0, stripos( $html, '</head>' ) );
246
247                        // Do a quick check
248                        $tagfound = false;
249                        foreach ( $linktypes as $linktype => $format ) {
250                                if ( stripos($html, $linktype) ) {
251                                        $tagfound = true;
252                                        break;
253                                }
254                        }
255
256                        if ( $tagfound && preg_match_all( '/<link([^<>]+)>/i', $html, $links ) ) {
257                                foreach ( $links[1] as $link ) {
258                                        $atts = shortcode_parse_atts( $link );
259
260                                        if ( !empty($atts['type']) && !empty($linktypes[$atts['type']]) && !empty($atts['href']) ) {
261                                                $providers[$linktypes[$atts['type']]] = $atts['href'];
262
263                                                // Stop here if it's JSON (that's all we need)
264                                                if ( 'json' == $linktypes[$atts['type']] )
265                                                        break;
266                                        }
267                                }
268                        }
269                }
270
271                // JSON is preferred to XML
272                if ( !empty($providers['json']) )
273                        return $providers['json'];
274                elseif ( !empty($providers['xml']) )
275                        return $providers['xml'];
276                else
277                        return false;
278        }
279
280        /**
281         * Connects to a oEmbed provider and returns the result.
282         *
283         * @param string $provider The URL to the oEmbed provider.
284         * @param string $url The URL to the content that is desired to be embedded.
285         * @param array $args Optional arguments. Usually passed from a shortcode.
286         * @return bool|object False on failure, otherwise the result in the form of an object.
287         */
288        function fetch( $provider, $url, $args = '' ) {
289                $args = wp_parse_args( $args, wp_embed_defaults() );
290
291                $provider = add_query_arg( 'maxwidth', $args['width'], $provider );
292                $provider = add_query_arg( 'maxheight', $args['height'], $provider );
293                $provider = add_query_arg( 'url', urlencode($url), $provider );
294               
295                foreach( array( 'json', 'xml' ) as $format ) {
296                        $result = $this->_fetch_with_format( $provider, $format );
297                        if ( is_wp_error( $result ) && 'not-implemented' == $result->get_error_code() )
298                                continue;
299                        return ( $result && ! is_wp_error( $result ) ) ? $result : false;
300                }
301                return false;
302        }
303
304        /**
305         * Fetches result from an oEmbed provider for a specific format and complete provider URL
306         *
307         * @since 3.0.0
308         * @access private
309         * @param string $provider_url_with_args URL to the provider with full arguments list (url, maxheight, etc.)
310         * @param string $format Format to use
311         * @return bool|object False on failure, otherwise the result in the form of an object.
312         */
313        function _fetch_with_format( $provider_url_with_args, $format ) {
314                $provider_url_with_args = add_query_arg( 'format', $format, $provider_url_with_args );
315                $response = wp_remote_get( $provider_url_with_args );
316                if ( 501 == wp_remote_retrieve_response_code( $response ) )
317                        return new WP_Error( 'not-implemented' );
318                if ( ! $body = wp_remote_retrieve_body( $response ) )
319                        return false;
320                $parse_method = "_parse_$format";
321                return $this->$parse_method( $body );
322        }
323
324        /**
325         * Parses a json response body.
326         *
327         * @since 3.0.0
328         * @access private
329         */
330        function _parse_json( $response_body ) {
331                return ( ( $data = json_decode( trim( $response_body ) ) ) && is_object( $data ) ) ? $data : false;
332        }
333
334        /**
335         * Parses an XML response body.
336         *
337         * @since 3.0.0
338         * @access private
339         */
340        function _parse_xml( $response_body ) {
341                if ( function_exists('simplexml_load_string') ) {
342                        $errors = libxml_use_internal_errors( 'true' );
343                        $data = simplexml_load_string( $response_body );
344                        libxml_use_internal_errors( $errors );
345                        if ( is_object( $data ) )
346                                return $data;
347                }
348                return false;
349        }
350
351        /**
352         * Converts a data object from {@link WP_oEmbed::fetch()} and returns the HTML.
353         *
354         * @param object $data A data object result from an oEmbed provider.
355         * @param string $url The URL to the content that is desired to be embedded.
356         * @return bool|string False on error, otherwise the HTML needed to embed.
357         */
358        function data2html( $data, $url ) {
359                if ( !is_object($data) || empty($data->type) )
360                        return false;
361
362                switch ( $data->type ) {
363                        case 'photo':
364                                if ( empty($data->url) || empty($data->width) || empty($data->height) )
365                                        return false;
366
367                                $title = ( !empty($data->title) ) ? $data->title : '';
368                                $return = '<img src="' . esc_url( $data->url ) . '" alt="' . esc_attr($title) . '" width="' . esc_attr($data->width) . '" height="' . esc_attr($data->height) . '" />';
369                                break;
370
371                        case 'video':
372                        case 'rich':
373                                $return = ( !empty($data->html) ) ? $data->html : false;
374                                break;
375
376                        case 'link':
377                                $return = ( !empty($data->title) ) ? '<a href="' . esc_url($url) . '">' . esc_html($data->title) . '</a>' : false;
378                                break;
379
380                        default;
381                                $return = false;
382                }
383
384                // You can use this filter to add support for custom data types or to filter the result
385                return apply_filters( 'oembed_dataparse', $return, $data, $url );
386        }
387
388        /**
389         * Strip any new lines from the HTML.
390         *
391         * @access private
392         * @param string $html Existing HTML.
393         * @param object $data Data object from WP_oEmbed::data2html()
394         * @param string $url The original URL passed to oEmbed.
395         * @return string Possibly modified $html
396         */
397        function _strip_newlines( $html, $data, $url ) {
398                if ( false !== strpos( "\n", $html ) )
399                        $html = str_replace( array( "\r\n", "\n" ), '', $html );
400
401                return $html;
402        }
403}
404
405/**
406 * Returns the initialized {@link WP_oEmbed} object
407 *
408 * @since 2.9.0
409 * @access private
410 *
411 * @see WP_oEmbed
412 * @uses WP_oEmbed
413 *
414 * @return WP_oEmbed object.
415 */
416function &_wp_oembed_get_object() {
417        static $wp_oembed;
418
419        if ( is_null($wp_oembed) )
420                $wp_oembed = new WP_oEmbed();
421
422        return $wp_oembed;
423}
424
425?>