19 */ |
19 */ |
20 class WP_oEmbed { |
20 class WP_oEmbed { |
21 var $providers = array(); |
21 var $providers = array(); |
22 |
22 |
23 /** |
23 /** |
24 * PHP4 constructor |
24 * Constructor |
25 */ |
|
26 function WP_oEmbed() { |
|
27 return $this->__construct(); |
|
28 } |
|
29 |
|
30 /** |
|
31 * PHP5 constructor |
|
32 * |
25 * |
33 * @uses apply_filters() Filters a list of pre-defined oEmbed providers. |
26 * @uses apply_filters() Filters a list of pre-defined oEmbed providers. |
34 */ |
27 */ |
35 function __construct() { |
28 function __construct() { |
36 // List out some popular sites that support oEmbed. |
29 // 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. |
30 // 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). |
31 // Add to this list using the wp_oembed_add_provider() function (see its PHPDoc for details). |
39 $this->providers = apply_filters( 'oembed_providers', array( |
32 $this->providers = apply_filters( 'oembed_providers', array( |
40 '#http://(www\.)?youtube.com/watch.*#i' => array( 'http://www.youtube.com/oembed', true ), |
33 '#http://(www\.)?youtube.com/watch.*#i' => array( 'http://www.youtube.com/oembed', true ), |
41 'http://blip.tv/file/*' => array( 'http://blip.tv/oembed/', false ), |
34 'http://youtu.be/*' => array( 'http://www.youtube.com/oembed', false ), |
42 '#http://(www\.)?vimeo\.com/.*#i' => array( 'http://www.vimeo.com/api/oembed.{format}', true ), |
35 'http://blip.tv/*' => array( 'http://blip.tv/oembed/', false ), |
43 '#http://(www\.)?dailymotion\.com/.*#i' => array( 'http://www.dailymotion.com/api/oembed', true ), |
36 '#http://(www\.)?vimeo\.com/.*#i' => array( 'http://vimeo.com/api/oembed.{format}', true ), |
44 '#http://(www\.)?flickr\.com/.*#i' => array( 'http://www.flickr.com/services/oembed/', true ), |
37 '#http://(www\.)?dailymotion\.com/.*#i' => array( 'http://www.dailymotion.com/services/oembed', true ), |
45 '#http://(www\.)?hulu\.com/watch/.*#i' => array( 'http://www.hulu.com/api/oembed.{format}', true ), |
38 '#http://(www\.)?flickr\.com/.*#i' => array( 'http://www.flickr.com/services/oembed/', true ), |
46 '#http://(www\.)?viddler\.com/.*#i' => array( 'http://lab.viddler.com/services/oembed/', true ), |
39 '#http://(.+\.)?smugmug\.com/.*#i' => array( 'http://api.smugmug.com/services/oembed/', true ), |
47 'http://qik.com/*' => array( 'http://qik.com/api/oembed.{format}', false ), |
40 '#http://(www\.)?hulu\.com/watch/.*#i' => array( 'http://www.hulu.com/api/oembed.{format}', true ), |
48 'http://revision3.com/*' => array( 'http://revision3.com/api/oembed/', false ), |
41 '#http://(www\.)?viddler\.com/.*#i' => array( 'http://lab.viddler.com/services/oembed/', true ), |
49 'http://i*.photobucket.com/albums/*' => array( 'http://photobucket.com/oembed', false ), |
42 'http://qik.com/*' => array( 'http://qik.com/api/oembed.{format}', false ), |
50 'http://gi*.photobucket.com/groups/*' => array( 'http://photobucket.com/oembed', false ), |
43 'http://revision3.com/*' => array( 'http://revision3.com/api/oembed/', false ), |
51 '#http://(www\.)?scribd\.com/.*#i' => array( 'http://www.scribd.com/services/oembed', true ), |
44 'http://i*.photobucket.com/albums/*' => array( 'http://photobucket.com/oembed', false ), |
52 'http://wordpress.tv/*' => array( 'http://wordpress.tv/oembed/', false ), |
45 'http://gi*.photobucket.com/groups/*' => array( 'http://photobucket.com/oembed', false ), |
|
46 '#http://(www\.)?scribd\.com/.*#i' => array( 'http://www.scribd.com/services/oembed', true ), |
|
47 'http://wordpress.tv/*' => array( 'http://wordpress.tv/oembed/', false ), |
|
48 '#http://(.+\.)?polldaddy\.com/.*#i' => array( 'http://polldaddy.com/oembed/', true ), |
|
49 '#http://(www\.)?funnyordie\.com/videos/.*#i' => array( 'http://www.funnyordie.com/oembed', true ), |
|
50 '#https?://(www\.)?twitter.com/.+?/status(es)?/.*#i' => array( 'http://api.twitter.com/1/statuses/oembed.{format}', true ), |
53 ) ); |
51 ) ); |
54 |
52 |
55 // Fix Scribd embeds. They contain new lines in the middle of the HTML which breaks wpautop(). |
53 // Fix any embeds that contain new lines in the middle of the HTML which breaks wpautop(). |
56 add_filter( 'oembed_dataparse', array(&$this, 'strip_scribd_newlines'), 10, 3 ); |
54 add_filter( 'oembed_dataparse', array(&$this, '_strip_newlines'), 10, 3 ); |
57 } |
55 } |
58 |
56 |
59 /** |
57 /** |
60 * The do-it-all function that takes a URL and attempts to return the HTML. |
58 * The do-it-all function that takes a URL and attempts to return the HTML. |
61 * |
59 * |
159 * @return bool|object False on failure, otherwise the result in the form of an object. |
157 * @return bool|object False on failure, otherwise the result in the form of an object. |
160 */ |
158 */ |
161 function fetch( $provider, $url, $args = '' ) { |
159 function fetch( $provider, $url, $args = '' ) { |
162 $args = wp_parse_args( $args, wp_embed_defaults() ); |
160 $args = wp_parse_args( $args, wp_embed_defaults() ); |
163 |
161 |
164 $provider = add_query_arg( 'format', 'json', $provider ); // JSON is easier to deal with than XML |
162 $provider = add_query_arg( 'maxwidth', (int) $args['width'], $provider ); |
165 |
163 $provider = add_query_arg( 'maxheight', (int) $args['height'], $provider ); |
166 $provider = add_query_arg( 'maxwidth', $args['width'], $provider ); |
|
167 $provider = add_query_arg( 'maxheight', $args['height'], $provider ); |
|
168 $provider = add_query_arg( 'url', urlencode($url), $provider ); |
164 $provider = add_query_arg( 'url', urlencode($url), $provider ); |
169 |
165 |
170 if ( !$result = wp_remote_retrieve_body( wp_remote_get( $provider ) ) ) |
166 foreach( array( 'json', 'xml' ) as $format ) { |
|
167 $result = $this->_fetch_with_format( $provider, $format ); |
|
168 if ( is_wp_error( $result ) && 'not-implemented' == $result->get_error_code() ) |
|
169 continue; |
|
170 return ( $result && ! is_wp_error( $result ) ) ? $result : false; |
|
171 } |
|
172 return false; |
|
173 } |
|
174 |
|
175 /** |
|
176 * Fetches result from an oEmbed provider for a specific format and complete provider URL |
|
177 * |
|
178 * @since 3.0.0 |
|
179 * @access private |
|
180 * @param string $provider_url_with_args URL to the provider with full arguments list (url, maxheight, etc.) |
|
181 * @param string $format Format to use |
|
182 * @return bool|object False on failure, otherwise the result in the form of an object. |
|
183 */ |
|
184 function _fetch_with_format( $provider_url_with_args, $format ) { |
|
185 $provider_url_with_args = add_query_arg( 'format', $format, $provider_url_with_args ); |
|
186 $response = wp_remote_get( $provider_url_with_args ); |
|
187 if ( 501 == wp_remote_retrieve_response_code( $response ) ) |
|
188 return new WP_Error( 'not-implemented' ); |
|
189 if ( ! $body = wp_remote_retrieve_body( $response ) ) |
171 return false; |
190 return false; |
172 |
191 $parse_method = "_parse_$format"; |
173 $result = trim( $result ); |
192 return $this->$parse_method( $body ); |
174 |
193 } |
175 // JSON? |
194 |
176 // Example content: http://vimeo.com/api/oembed.json?url=http%3A%2F%2Fvimeo.com%2F240975 |
195 /** |
177 if ( $data = json_decode($result) ) { |
196 * Parses a json response body. |
178 return $data; |
197 * |
179 } |
198 * @since 3.0.0 |
180 |
199 * @access private |
181 // Must be XML. Only parse it if PHP5 is installed. (PHP4 isn't worth the trouble.) |
200 */ |
182 // Example content: http://vimeo.com/api/oembed.xml?url=http%3A%2F%2Fvimeo.com%2F240975 |
201 function _parse_json( $response_body ) { |
183 elseif ( function_exists('simplexml_load_string') ) { |
202 return ( ( $data = json_decode( trim( $response_body ) ) ) && is_object( $data ) ) ? $data : false; |
|
203 } |
|
204 |
|
205 /** |
|
206 * Parses an XML response body. |
|
207 * |
|
208 * @since 3.0.0 |
|
209 * @access private |
|
210 */ |
|
211 function _parse_xml( $response_body ) { |
|
212 if ( function_exists('simplexml_load_string') ) { |
184 $errors = libxml_use_internal_errors( 'true' ); |
213 $errors = libxml_use_internal_errors( 'true' ); |
185 |
214 $data = simplexml_load_string( $response_body ); |
186 $data = simplexml_load_string( $result ); |
|
187 |
|
188 libxml_use_internal_errors( $errors ); |
215 libxml_use_internal_errors( $errors ); |
189 |
216 if ( ! is_object( $data ) ) |
190 if ( is_object($data) ) |
217 return false; |
191 return $data; |
218 |
192 } |
219 $return = new stdClass; |
193 |
220 foreach ( $data as $key => $value ) |
|
221 $return->$key = (string) $value; |
|
222 |
|
223 return $return; |
|
224 } |
194 return false; |
225 return false; |
195 } |
226 } |
196 |
227 |
197 /** |
228 /** |
198 * Converts a data object from {@link WP_oEmbed::fetch()} and returns the HTML. |
229 * Converts a data object from {@link WP_oEmbed::fetch()} and returns the HTML. |
200 * @param object $data A data object result from an oEmbed provider. |
231 * @param object $data A data object result from an oEmbed provider. |
201 * @param string $url The URL to the content that is desired to be embedded. |
232 * @param string $url The URL to the content that is desired to be embedded. |
202 * @return bool|string False on error, otherwise the HTML needed to embed. |
233 * @return bool|string False on error, otherwise the HTML needed to embed. |
203 */ |
234 */ |
204 function data2html( $data, $url ) { |
235 function data2html( $data, $url ) { |
205 if ( !is_object($data) || empty($data->type) ) |
236 if ( ! is_object( $data ) || empty( $data->type ) ) |
206 return false; |
237 return false; |
|
238 |
|
239 $return = false; |
207 |
240 |
208 switch ( $data->type ) { |
241 switch ( $data->type ) { |
209 case 'photo': |
242 case 'photo': |
210 if ( empty($data->url) || empty($data->width) || empty($data->height) ) |
243 if ( empty( $data->url ) || empty( $data->width ) || empty( $data->height ) ) |
211 return false; |
244 break; |
212 |
245 if ( ! is_string( $data->url ) || ! is_numeric( $data->width ) || ! is_numeric( $data->height ) ) |
213 $title = ( !empty($data->title) ) ? $data->title : ''; |
246 break; |
214 $return = '<img src="' . esc_attr( clean_url( $data->url ) ) . '" alt="' . esc_attr($title) . '" width="' . esc_attr($data->width) . '" height="' . esc_attr($data->height) . '" />'; |
247 |
|
248 $title = ! empty( $data->title ) && is_string( $data->title ) ? $data->title : ''; |
|
249 $return = '<a href="' . esc_url( $url ) . '"><img src="' . esc_url( $data->url ) . '" alt="' . esc_attr($title) . '" width="' . esc_attr($data->width) . '" height="' . esc_attr($data->height) . '" /></a>'; |
215 break; |
250 break; |
216 |
251 |
217 case 'video': |
252 case 'video': |
218 case 'rich': |
253 case 'rich': |
219 $return = ( !empty($data->html) ) ? $data->html : false; |
254 if ( ! empty( $data->html ) && is_string( $data->html ) ) |
|
255 $return = $data->html; |
220 break; |
256 break; |
221 |
257 |
222 case 'link': |
258 case 'link': |
223 $return = ( !empty($data->title) ) ? '<a href="' . clean_url($url) . '">' . esc_html($data->title) . '</a>' : false; |
259 if ( ! empty( $data->title ) && is_string( $data->title ) ) |
|
260 $return = '<a href="' . esc_url( $url ) . '">' . esc_html( $data->title ) . '</a>'; |
224 break; |
261 break; |
225 |
262 |
226 default; |
263 default: |
227 $return = false; |
264 $return = false; |
228 } |
265 } |
229 |
266 |
230 // You can use this filter to add support for custom data types or to filter the result |
267 // You can use this filter to add support for custom data types or to filter the result |
231 return apply_filters( 'oembed_dataparse', $return, $data, $url ); |
268 return apply_filters( 'oembed_dataparse', $return, $data, $url ); |
232 } |
269 } |
233 |
270 |
234 /** |
271 /** |
235 * Strip new lines from the HTML if it's a Scribd embed. |
272 * Strip any new lines from the HTML. |
236 * |
273 * |
|
274 * @access private |
237 * @param string $html Existing HTML. |
275 * @param string $html Existing HTML. |
238 * @param object $data Data object from WP_oEmbed::data2html() |
276 * @param object $data Data object from WP_oEmbed::data2html() |
239 * @param string $url The original URL passed to oEmbed. |
277 * @param string $url The original URL passed to oEmbed. |
240 * @return string Possibly modified $html |
278 * @return string Possibly modified $html |
241 */ |
279 */ |
242 function strip_scribd_newlines( $html, $data, $url ) { |
280 function _strip_newlines( $html, $data, $url ) { |
243 if ( preg_match( '#http://(www\.)?scribd.com/.*#i', $url ) ) |
281 if ( false !== strpos( $html, "\n" ) ) |
244 $html = str_replace( array( "\r\n", "\n" ), '', $html ); |
282 $html = str_replace( array( "\r\n", "\n" ), '', $html ); |
245 |
283 |
246 return $html; |
284 return $html; |
247 } |
285 } |
248 } |
286 } |