From 410fcc2e423ac62c613d1d21631c9bf16a00a00e Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 13 Oct 2009 17:04:22 +0000 Subject: [PATCH] Embeds. Props Viper007Bond. see #10337 git-svn-id: http://svn.automattic.com/wordpress/trunk@12023 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/admin-ajax.php | 4 + wp-admin/includes/schema.php | 8 +- wp-admin/options-media.php | 36 +++- wp-admin/options.php | 2 +- wp-includes/capabilities.php | 24 +++ wp-includes/class-oembed.php | 236 +++++++++++++++++++++ wp-includes/default-embeds.php | 101 +++++++++ wp-includes/default-filters.php | 1 + wp-includes/formatting.php | 2 + wp-includes/functions.php | 14 ++ wp-includes/media.php | 351 ++++++++++++++++++++++++++++++++ 11 files changed, 775 insertions(+), 4 deletions(-) create mode 100644 wp-includes/class-oembed.php create mode 100644 wp-includes/default-embeds.php diff --git a/wp-admin/admin-ajax.php b/wp-admin/admin-ajax.php index 5884e6e18..b683b1140 100644 --- a/wp-admin/admin-ajax.php +++ b/wp-admin/admin-ajax.php @@ -124,6 +124,10 @@ case 'imgedit-preview' : die(); break; +case 'oembed-cache' : + $return = ( $wp_embed->cache_oembed( $_GET['post'] ) ) ? '1' : '0'; + die( $return ); + break; default : do_action( 'wp_ajax_' . $_GET['action'] ); die('0'); diff --git a/wp-admin/includes/schema.php b/wp-admin/includes/schema.php index eae2cbbf0..897fa9d96 100644 --- a/wp-admin/includes/schema.php +++ b/wp-admin/includes/schema.php @@ -313,7 +313,13 @@ function populate_options() { 'widget_rss' => array(), // 2.8 - 'timezone_string' => '' + 'timezone_string' => '', + + // 2.9 + 'embed_useoembed' => 1, + 'embed_autourls' => 1, + 'embed_size_w' => '', + 'embed_size_h' => 600, ); // Set autoload to no for these options diff --git a/wp-admin/options-media.php b/wp-admin/options-media.php index e5abf4e56..4f17e3e8f 100644 --- a/wp-admin/options-media.php +++ b/wp-admin/options-media.php @@ -44,7 +44,7 @@ include('admin-header.php'); -
+
@@ -54,7 +54,7 @@ include('admin-header.php'); -
+
@@ -65,6 +65,38 @@ include('admin-header.php'); +

+ + + + + + + + + + + + + + + + + + + +
oEmbed to assist in rich content embedding'), 'http://codex.wordpress.org/oEmbed' ); ?> + +
+ +
+ + + + +' . __("If the width value is left blank, embeds will default to the max width of your theme."); ?> +
+

diff --git a/wp-admin/options.php b/wp-admin/options.php index 6bc056155..4881444a6 100644 --- a/wp-admin/options.php +++ b/wp-admin/options.php @@ -25,7 +25,7 @@ $whitelist_options = array( 'general' => array( 'blogname', 'blogdescription', 'admin_email', 'users_can_register', 'gmt_offset', 'date_format', 'time_format', 'start_of_week', 'default_role', 'timezone_string' ), 'discussion' => array( 'default_pingback_flag', 'default_ping_status', 'default_comment_status', 'comments_notify', 'moderation_notify', 'comment_moderation', 'require_name_email', 'comment_whitelist', 'comment_max_links', 'moderation_keys', 'blacklist_keys', 'show_avatars', 'avatar_rating', 'avatar_default', 'close_comments_for_old_posts', 'close_comments_days_old', 'thread_comments', 'thread_comments_depth', 'page_comments', 'comments_per_page', 'default_comments_page', 'comment_order', 'comment_registration' ), 'misc' => array( 'use_linksupdate', 'uploads_use_yearmonth_folders', 'upload_path', 'upload_url_path' ), - 'media' => array( 'thumbnail_size_w', 'thumbnail_size_h', 'thumbnail_crop', 'medium_size_w', 'medium_size_h', 'large_size_w', 'large_size_h', 'image_default_size', 'image_default_align', 'image_default_link_type' ), + 'media' => array( 'thumbnail_size_w', 'thumbnail_size_h', 'thumbnail_crop', 'medium_size_w', 'medium_size_h', 'large_size_w', 'large_size_h', 'image_default_size', 'image_default_align', 'image_default_link_type', 'embed_useoembed', 'embed_autourls', 'embed_size_w', 'embed_size_h' ), 'privacy' => array( 'blog_public' ), 'reading' => array( 'posts_per_page', 'posts_per_rss', 'rss_use_excerpt', 'blog_charset', 'show_on_front', 'page_on_front', 'page_for_posts' ), 'writing' => array( 'default_post_edit_rows', 'use_smilies', 'ping_sites', 'mailserver_url', 'mailserver_port', 'mailserver_login', 'mailserver_pass', 'default_category', 'default_email_category', 'use_balanceTags', 'default_link_category', 'enable_app', 'enable_xmlrpc' ), diff --git a/wp-includes/capabilities.php b/wp-includes/capabilities.php index 62938d91b..3077f2b60 100644 --- a/wp-includes/capabilities.php +++ b/wp-includes/capabilities.php @@ -959,6 +959,30 @@ function current_user_can( $capability ) { return call_user_func_array( array( &$current_user, 'has_cap' ), $args ); } +/** + * Whether author of supplied post has capability or role. + * + * @since 2.9 + * + * @param int|object $post Post ID or post object. + * @param string $capability Capability or role name. + * @return bool + */ +function author_can( $post, $capability ) { + if ( !$post = get_post($post) ) + return false; + + $author = new WP_User( $post->post_author ); + + if ( empty( $author ) ) + return false; + + $args = array_slice( func_get_args(), 2 ); + $args = array_merge( array( $capability ), $args ); + + return call_user_func_array( array( &$author, 'has_cap' ), $args ); +} + /** * Retrieve role object. * diff --git a/wp-includes/class-oembed.php b/wp-includes/class-oembed.php new file mode 100644 index 000000000..d2885a971 --- /dev/null +++ b/wp-includes/class-oembed.php @@ -0,0 +1,236 @@ +__construct(); + } + + /** + * PHP5 constructor + * + * @uses apply_filters() Filters a list of pre-defined oEmbed providers. + */ + function __construct() { + // List out some popular sites, mainly ones that don't have discovery tags in their + // The WP_Embed class disables discovery for non-unfiltered_html users, + // so only providers in this array will be used for them. + $this->providers = apply_filters( 'oembed_providers', array( + 'http://blip.tv/file/*' => 'http://blip.tv/oembed/', + 'http://*.flickr.com/*' => 'http://www.flickr.com/services/oembed/', + 'http://*.viddler.com/*' => 'http://lab.viddler.com/services/oembed/', + 'http://qik.com/*' => 'http://qik.com/api/oembed.{format}', + 'http://*.revision3.com/*' => 'http://revision3.com/api/oembed/', + 'http://www.hulu.com/watch/*' => 'http://www.hulu.com/api/oembed.{format}', + + // Vimeo uses the discovery , so leave this commented to use it as a discovery test + //'http://www.vimeo.com/*' => 'http://www.vimeo.com/api/oembed.{format}', + ) ); + } + + /** + * The do-it-all function that takes a URL and attempts to return the HTML. + * + * @see WP_oEmbed::discover() + * @see WP_oEmbed::fetch() + * @see WP_oEmbed::data2html() + * + * @param string $url The URL to the content that should be attempted to be embedded. + * @param array $args Optional arguments. Usually passed from a shortcode. + * @return bool|string False on failure, otherwise the UNSANITIZED (and potentially unsafe) HTML that should be used to embed. + */ + function get_html( $url, $args = '' ) { + $provider = false; + + if ( !isset($args['discover']) ) + $args['discover'] = true; + + foreach ( $this->providers as $matchmask => $providerurl ) { + // Turn the asterisk-type provider URLs into regex + $regex = '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $matchmask ), '#' ) ) . '#i'; + + if ( preg_match( $regex, $url ) ) { + $provider = str_replace( '{format}', 'json', $providerurl ); // JSON is easier to deal with than XML + break; + } + } + + if ( !$provider && $args['discover'] ) + $provider = $this->discover( $url ); + + if ( !$provider || false === $data = $this->fetch( $provider, $url, $args ) ) + return false; + + return apply_filters( 'oembed_output', $this->data2html( $data, $url ), $url, $args ); + } + + /** + * Attempts to find oEmbed provider discovery tags at the given URL. + * + * @param string $url The URL that should be inspected for discovery tags. + * @return bool|string False on failure, otherwise the oEmbed provider URL. + */ + function discover( $url ) { + $providers = array(); + + // Fetch URL content + if ( $html = wp_remote_retrieve_body( wp_remote_get( $url ) ) ) { + + // types that contain oEmbed provider URLs + $linktypes = apply_filters( 'oembed_linktypes', array( + 'application/json+oembed' => 'json', + 'text/xml+oembed' => 'xml', + 'application/xml+oembed' => 'xml', // Incorrect, but used by at least Vimeo + ) ); + + // Strip + $html = substr( $html, 0, stripos( $html, '' ) ); + + // Do a quick check + $tagfound = false; + foreach ( $linktypes as $linktype => $format ) { + if ( stripos($html, $linktype) ) { + $tagfound = true; + break; + } + } + + if ( $tagfound && preg_match_all( '/]+)>/i', $html, $links ) ) { + foreach ( $links[1] as $link ) { + $atts = shortcode_parse_atts( $link ); + + if ( !empty($atts['type']) && !empty($linktypes[$atts['type']]) && !empty($atts['href']) ) { + $providers[$linktypes[$atts['type']]] = $atts['href']; + + // Stop here if it's JSON (that's all we need) + if ( 'json' == $linktypes[$atts['type']] ) + break; + } + } + } + } + + // JSON is preferred to XML + if ( !empty($providers['json']) ) + return $providers['json']; + elseif ( !empty($providers['xml']) ) + return $providers['xml']; + else + return false; + } + + /** + * Connects to a oEmbed provider and returns the result. + * + * @param string $provider The URL to the oEmbed provider. + * @param string $url The URL to the content that is desired to be embedded. + * @param array $args Optional arguments. Usually passed from a shortcode. + * @return bool|object False on failure, otherwise the result in the form of an object. + */ + function fetch( $provider, $url, $args = '' ) { + $args = wp_parse_args( $args, wp_embed_defaults() ); + + $provider = add_query_arg( 'format', 'json', $provider ); // JSON is easier to deal with than XML + + $provider = add_query_arg( 'maxwidth', $args['width'], $provider ); + $provider = add_query_arg( 'maxheight', $args['height'], $provider ); + $provider = add_query_arg( 'url', urlencode($url), $provider ); + + if ( !$result = wp_remote_retrieve_body( wp_remote_get( $provider ) ) ) + return false; + + $result = trim( $result ); + + // JSON? + // Example content: http://vimeo.com/api/oembed.json?url=http%3A%2F%2Fvimeo.com%2F240975 + if ( $data = json_decode($result) ) { + return $data; + } + + // Must be XML. Only parse it if PHP5 is installed. (PHP4 isn't worth the trouble.) + // Example content: http://vimeo.com/api/oembed.xml?url=http%3A%2F%2Fvimeo.com%2F240975 + elseif ( function_exists('simplexml_load_string') ) { + $errors = libxml_use_internal_errors( 'true' ); + + $data = simplexml_load_string( $result ); + + libxml_use_internal_errors( $errors ); + + if ( is_object($data) ) + return $data; + } + + return false; + } + + /** + * Converts a data object from {@link WP_oEmbed::fetch()} and returns the HTML. + * + * @param object $data A data object result from an oEmbed provider. + * @param string $url The URL to the content that is desired to be embedded. + * @return bool|string False on error, otherwise the HTML needed to embed. + */ + function data2html( $data, $url ) { + if ( !is_object($data) || empty($data->type) ) + return false; + + switch ( $data->type ) { + case 'photo': + if ( empty($data->url) || empty($data->width) || empty($data->height) ) + return false; + + $title = ( !empty($data->title) ) ? $data->title : ''; + return '' . esc_attr($title) . ''; + + case 'video': + case 'rich': + return ( !empty($data->html) ) ? $data->html : false; + + case 'link': + return ( !empty($data->title) ) ? '' . esc_html($data->title) . '' : false; + } + + return false; + } +} + +/** + * Returns the initialized {@link WP_oEmbed} object + * + * @since 2.9.0 + * @access private + * + * @see WP_oEmbed + * @uses WP_oEmbed + * + * @return WP_oEmbed object. + */ +function &_wp_oembed_get_object() { + static $wp_oembed; + + if ( is_null($wp_oembed) ) + $wp_oembed = new WP_oEmbed(); + + return $wp_oembed; +} diff --git a/wp-includes/default-embeds.php b/wp-includes/default-embeds.php new file mode 100644 index 000000000..e3c938c6d --- /dev/null +++ b/wp-includes/default-embeds.php @@ -0,0 +1,101 @@ +', $matches, $attr, $url, $rawattr ); +} +wp_embed_register_handler( 'youtube', '#http://(www.youtube|youtube|[A-Za-z]{2}.youtube)\.com/(watch\?v=|w/\?v=|\?v=)([\w-]+)(.*?)#i', 'wp_embed_handler_youtube' ); + + +/** + * The Google Video embed handler callback. Google Video does not support oEmbed. + * + * @see WP_Embed::register_handler() + * @see WP_Embed::shortcode() + * + * @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}. + * @param array $attr Embed attributes. + * @param string $url The original URL that was matched by the regex. + * @param array $rawattr The original unmodified attributes. + * @return string The embed HTML. + */ +function wp_embed_handler_googlevideo( $matches, $attr, $url, $rawattr ) { + // If the user supplied a fixed width AND height, use it + if ( !empty($rawattr['width']) && !empty($rawattr['height']) ) { + $width = (int) $rawattr['width']; + $height = (int) $rawattr['height']; + } else { + list( $width, $height ) = wp_expand_dimensions( 425, 344, $attr['width'], $attr['height'] ); + } + + return apply_filters( 'embed_googlevideo', '', $matches, $attr, $url, $rawattr ); +} +wp_embed_register_handler( 'googlevideo', '#http://video\.google\.([A-Za-z.]{2,5})/videoplay\?docid=([\d-]+)(.*?)#i', 'wp_embed_handler_googlevideo' ); + +/** + * The PollDaddy.com embed handler callback. PollDaddy does not support oEmbed, at least not yet. + * + * @see WP_Embed::register_handler() + * @see WP_Embed::shortcode() + * + * @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}. + * @param array $attr Embed attributes. + * @param string $url The original URL that was matched by the regex. + * @param array $rawattr The original unmodified attributes. + * @return string The embed HTML. + */ +function wp_embed_handler_polldaddy( $matches, $attr, $url, $rawattr ) { + return apply_filters( 'embed_polldaddy', '', $matches, $attr, $url, $rawattr ); +} +wp_embed_register_handler( 'polldaddy', '#http://answers.polldaddy.com/poll/(\d+)(.*?)#i', 'wp_embed_handler_polldaddy' ); + +/** + * The DailyMotion.com embed handler callback. DailyMotion does not support oEmbed. + * + * @see WP_Embed::register_handler() + * @see WP_Embed::shortcode() + * + * @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}. + * @param array $attr Embed attributes. + * @param string $url The original URL that was matched by the regex. + * @param array $rawattr The original unmodified attributes. + * @return string The embed HTML. + */ +function wp_embed_handler_dailymotion( $matches, $attr, $url, $rawattr ) { + // If the user supplied a fixed width AND height, use it + if ( !empty($rawattr['width']) && !empty($rawattr['height']) ) { + $width = (int) $rawattr['width']; + $height = (int) $rawattr['height']; + } else { + list( $width, $height ) = wp_expand_dimensions( 480, 291, $attr['width'], $attr['height'] ); + } + + return apply_filters( 'embed_dailymotion', '', $matches, $attr, $url, $rawattr );; +} +wp_embed_register_handler( 'dailymotion', '#http://(www.dailymotion|dailymotion)\.com/(.+)/([0-9a-zA-Z]+)\_(.*?)#i', 'wp_embed_handler_dailymotion' ); diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php index 382644263..ce4127a97 100644 --- a/wp-includes/default-filters.php +++ b/wp-includes/default-filters.php @@ -206,6 +206,7 @@ add_action('admin_print_footer_scripts', 'print_footer_scripts', 20); add_action('admin_print_styles', 'print_admin_styles', 20); add_action('init', 'smilies_init', 5); add_action( 'plugins_loaded', 'wp_maybe_load_widgets', 0 ); +add_action( 'plugins_loaded', 'wp_maybe_load_embeds', 0 ); add_action( 'shutdown', 'wp_ob_end_flush_all', 1); add_action( 'pre_post_update', 'wp_save_post_revision' ); add_action('publish_post', '_publish_post_hook', 5, 1); diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php index 00ba9ddd1..71d5cdad8 100644 --- a/wp-includes/formatting.php +++ b/wp-includes/formatting.php @@ -2358,6 +2358,8 @@ function sanitize_option($option, $value) { case 'medium_size_h': case 'large_size_w': case 'large_size_h': + //case 'embed_size_w': + case 'embed_size_h': case 'default_post_edit_rows': case 'mailserver_port': case 'comment_max_links': diff --git a/wp-includes/functions.php b/wp-includes/functions.php index faa4853e0..08463ca18 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -2741,6 +2741,20 @@ function wp_parse_args( $args, $defaults = '' ) { return $r; } +/** + * Determines if default embed handlers should be loaded. + * + * Checks to make sure that the embeds library hasn't already been loaded. If + * it hasn't, then it will load the embeds library. + * + * @since 2.9 + */ +function wp_maybe_load_embeds() { + if ( ! apply_filters('load_default_embeds', true) ) + return; + require_once( ABSPATH . WPINC . '/default-embeds.php' ); +} + /** * Determines if Widgets library should be loaded. * diff --git a/wp-includes/media.php b/wp-includes/media.php index dfc927eb8..23baea1f6 100644 --- a/wp-includes/media.php +++ b/wp-includes/media.php @@ -860,3 +860,354 @@ function wp_imagecreatetruecolor($width, $height) { return $img; } +/** + * API for easily embedding rich media such as videos and images into content. + * + * @package WordPress + * @subpackage Embed + * @since 2.9.0 + */ +class WP_Embed { + var $handlers = array(); + var $post_ID; + var $usecache = true; + var $linkifunknown = true; + + /** + * PHP4 constructor + */ + function WP_Embed() { + return $this->__construct(); + } + + /** + * PHP5 constructor + */ + function __construct() { + // Hack to get the [embed] shortcode to run before wpautop() + add_filter( 'the_content', array(&$this, 'run_shortcode'), 8 ); + + // Attempts to embed all URLs in a post + if ( get_option('embed_autourls') ) + add_filter( 'the_content', array(&$this, 'autoembed'), 8 ); + + // After a post is saved, cache oEmbed items via AJAX + if ( get_option('embed_useoembed') ) + add_action( 'edit_form_advanced', array(&$this, 'maybe_run_ajax_cache') ); + } + + /** + * Process the [embed] shortcode. + * + * Since the [embed] shortcode needs to be run earlier than other shortcodes, + * this function removes all existing shortcodes, registers the [embed] shortcode, + * calls {@link do_shortcode()}, and then re-registers the old shortcodes. + * + * @uses $shortcode_tags + * @uses remove_all_shortcodes() + * @uses add_shortcode() + * @uses do_shortcode() + * + * @param string $content Content to parse + * @return string Content with shortcode parsed + */ + function run_shortcode( $content ) { + global $shortcode_tags; + + // Backup current registered shortcodes and clear them all out + $orig_shortcode_tags = $shortcode_tags; + remove_all_shortcodes(); + + add_shortcode( 'embed', array(&$this, 'shortcode') ); + + // Do the shortcode (only the [embed] one is registered) + $content = do_shortcode( $content ); + + // Put the original shortcodes back + $shortcode_tags = $orig_shortcode_tags; + + return $content; + } + + /** + * If a post/page was saved, then output Javascript to make + * an AJAX request that will call WP_Embed::cache_oembed(). + */ + function maybe_run_ajax_cache() { + global $post_ID; + + if ( empty($post_ID) || empty($_GET['message']) || 1 != $_GET['message'] ) + return; + +?> + +handlers[$priority][$id] = array( + 'regex' => $regex, + 'callback' => $callback, + ); + } + + /** + * Unregister a previously registered embed handler. Do not use this function directly, use {@link wp_embed_unregister_handler()} instead. + * + * @param string $id The handler ID that should be removed. + * @param int $priority Optional. The priority of the handler to be removed (default: 10). + */ + function unregister_handler( $id, $priority = 10 ) { + if ( isset($this->handlers[$priority][$id]) ) + unset($this->handlers[$priority][$id]); + } + + /** + * The {@link do_shortcode()} callback function. + * + * Attempts to convert a URL into embed HTML. Starts by checking the URL against the regex of the registered embed handlers. + * If none of the regex matches and it's enabled, then the URL will be given to the {@link WP_oEmbed} class. + * + * @uses wp_oembed_get() + * @uses wp_parse_args() + * @uses wp_embed_defaults() + * @uses WP_Embed::maybe_make_link() + * @uses get_option() + * @uses current_user_can() + * @uses wp_cache_get() + * @uses wp_cache_set() + * @uses get_post_meta() + * @uses update_post_meta() + * + * @param array $attr Shortcode attributes. + * @param string $url The URL attempting to be embeded. + * @return string The embed HTML on success, otherwise the original URL. + */ + function shortcode( $attr, $url = '' ) { + global $post, $_wp_using_ext_object_cache; + + if ( empty($url) ) + return ''; + + $rawattr = $attr; + $attr = wp_parse_args( $attr, wp_embed_defaults() ); + + // Look for known internal handlers + ksort( $this->handlers ); + foreach ( $this->handlers as $priority => $handlers ) { + foreach ( $handlers as $id => $handler ) { + if ( preg_match( $handler['regex'], $url, $matches ) && is_callable( $handler['callback'] ) ) { + if ( false !== $return = call_user_func( $handler['callback'], $matches, $attr, $url, $rawattr ) ) + return $return; + } + } + } + + $post_ID = ( !empty($post->ID) ) ? $post->ID : null; + if ( !empty($this->post_ID) ) // Potentially set by WP_Embed::cache_oembed() + $post_ID = $this->post_ID; + + // Unknown URL format. Let oEmbed have a go. + if ( $post_ID && get_option('embed_useoembed') ) { + + // Check for a cached result (stored in the post meta) + $cachekey = '_oembed_' . md5( $url . implode( '|', $attr ) ); + if ( $this->usecache ) { + $cache = ( $_wp_using_ext_object_cache ) ? wp_cache_get( "{$post_ID}_{$cachekey}", 'oembed' ) : get_post_meta( $post_ID, $cachekey, true ); + + // Failures are cached + if ( '{{unknown}}' === $cache ) + return $this->maybe_make_link( $url ); + + if ( !empty($cache) ) + return $cache; + } + + // Use oEmbed to get the HTML + $attr['discover'] = author_can( $post_ID, 'unfiltered_html' ); + $html = wp_oembed_get( $url, $attr ); + + // Cache the result + $cache = ( $html ) ? $html : '{{unknown}}'; + if ( $_wp_using_ext_object_cache ) + wp_cache_set( "{$post_ID}_{$cachekey}", $cache, 'oembed' ); + else + update_post_meta( $post_ID, $cachekey, $cache ); + + // If there was a result, return it + if ( $html ) + return $html; + } + + // Still unknown + return $this->maybe_make_link( $url ); + } + + /** + * Triggers a caching of all oEmbed results. + * + * @param int $post_ID Post ID to do the caching for. + */ + function cache_oembed( $post_ID ) { + $post = get_post( $post_ID ); + + // post_type check is incase of "save_post" usage + if ( empty($post->ID) || !in_array( $post->post_type, apply_filters( 'embed_cache_oembed_types', array( 'post', 'page' ) ) ) ) + return; + + // Dump existing caches + $post_metas = get_post_custom_keys( $post->ID ); + foreach( $post_metas as $post_meta_key ) { + if ( '_oembed_' == substr( $post_meta_key, 0, 8 ) ) + delete_post_meta( $post->ID, $post_meta_key ); + } + + // Trigger a caching + if ( !empty($post->post_content) ) { + $this->post_ID = $post->ID; + $this->usecache = false; + + $content = $this->run_shortcode( $post->post_content ); + if ( get_option('embed_autourls') ) + $this->autoembed( $content ); + + $this->usecache = true; + } + } + + /** + * Passes any unlinked URLs that are on their own line to {@link WP_Embed::shortcode()} for potential embedding. + * + * @uses WP_Embed::autoembed_callback() + * + * @param string $content The content to be searched. + * @return string Potentially modified $content. + */ + function autoembed( $content ) { + return preg_replace_callback( '|^\s*(https?://[^\s"]+)\s*$|im', array(&$this, 'autoembed_callback'), $content ); + } + + /** + * Callback function for {@link WP_Embed::autoembed()}. + * + * @uses WP_Embed::shortcode() + * + * @param array $match A regex match array. + * @return string The embed HTML on success, otherwise the original URL. + */ + function autoembed_callback( $match ) { + $oldval = $this->linkifunknown; + $this->linkifunknown = false; + $return = $this->shortcode( array(), $match[1] ); + $this->linkifunknown = $oldval; + + return "\n$return\n"; + } + + /** + * Conditionally makes a hyperlink based on an internal class variable. + * + * @param string $url URL to potentially be linked. + * @return string Linked URL or the original URL. + */ + function maybe_make_link( $url ) { + return ( $this->linkifunknown ) ? '' . esc_html($url) . '' : $url; + } +} +$wp_embed = new WP_Embed(); + +/** + * Register an embed handler. This function should probably only be used for sites that do not support oEmbed. + * + * @see WP_Embed::register_handler() + */ +function wp_embed_register_handler( $id, $regex, $callback, $priority = 10 ) { + global $wp_embed; + $wp_embed->register_handler( $id, $regex, $callback, $priority ); +} + +/** + * Unregister a previously registered embed handler. + * + * @see WP_Embed::unregister_handler() + */ +function wp_embed_unregister_handler( $id, $priority = 10 ) { + global $wp_embed; + $wp_embed->unregister_handler( $id, $priority ); +} + +/** + * Create default array of embed parameters. + * + * @return array Default embed parameters. + */ +function wp_embed_defaults() { + if ( !empty($GLOBALS['content_width']) ) + $theme_width = (int) $GLOBALS['content_width']; + + $width = get_option('embed_size_w'); + + if ( !$width && !empty($theme_width) ) + $width = $theme_width; + + if ( !$width ) + $width = 500; + + return apply_filters( 'embed_defaults', array( + 'width' => $width, + 'height' => 700, + ) ); +} + +/** + * Based on a supplied width/height example, return the biggest possible dimensions based on the max width/height. + * + * @uses wp_constrain_dimensions() This function passes the widths and the heights. + * + * @param int $example_width The width of an example embed. + * @param int $example_height The height of an example embed. + * @param int $max_width The maximum allowed width. + * @param int $max_height The maximum allowed height. + * @return array The maximum possible width and height based on the example ratio. + */ +function wp_expand_dimensions( $example_width, $example_height, $max_width, $max_height ) { + $example_width = (int) $example_width; + $example_height = (int) $example_height; + $max_width = (int) $max_width; + $max_height = (int) $max_height; + + return wp_constrain_dimensions( $example_width * 1000000, $example_height * 1000000, $max_width, $max_height ); +} + +/** + * Attempts to fetch the embed HTML for a provided URL using oEmbed. + * + * @see WP_oEmbed + * + * @uses _wp_oembed_get_object() + * @uses WP_oEmbed::get_html() + * + * @param string $url The URL that should be embeded. + * @param array $args Addtional arguments and parameters. + * @return string The original URL on failure or the embed HTML on success. + */ +function wp_oembed_get( $url, $args = '' ) { + require_once( 'class-oembed.php' ); + $oembed = _wp_oembed_get_object(); + return $oembed->get_html( $url, $args ); +}