| | 936 | |
| | 937 | |
| | 938 | |
| | 939 | |
| | 940 | |
| | 941 | |
| | 942 | |
| | 943 | |
| | 944 | |
| | 945 | // Embed class |
| | 946 | class WP_Embed { |
| | 947 | var $handlers = array(); |
| | 948 | var $post_ID; |
| | 949 | var $usecache = true; |
| | 950 | var $linkifunknown = true; |
| | 951 | |
| | 952 | // PHP4 constructor |
| | 953 | function WP_Embed() { |
| | 954 | return $this->__construct(); |
| | 955 | } |
| | 956 | |
| | 957 | // PHP5 constructor |
| | 958 | function __construct() { |
| | 959 | // After a post is saved, cache oEmbed items via AJAX |
| | 960 | add_action( 'edit_form_advanced', array(&$this, 'maybe_run_ajax_cache') ); |
| | 961 | |
| | 962 | // Hack to get the [embed] shortcode to run before wpautop() |
| | 963 | add_filter( 'the_content', array(&$this, 'runshortcode'), 9 ); |
| | 964 | |
| | 965 | // Per Matt's idea, this attempts to embed all URLs in a post |
| | 966 | add_filter( 'the_content', array(&$this, 'autoembed'), 9 ); |
| | 967 | } |
| | 968 | |
| | 969 | |
| | 970 | // Run do_shortcode() with only the [embed] shortcode active |
| | 971 | // This is so it can be run earlier than normal |
| | 972 | function runshortcode( $content ) { |
| | 973 | global $shortcode_tags; |
| | 974 | |
| | 975 | // Backup current registered shortcodes and clear them all out |
| | 976 | $orig_shortcode_tags = $shortcode_tags; |
| | 977 | remove_all_shortcodes(); |
| | 978 | |
| | 979 | add_shortcode( 'embed', array(&$this, 'shortcode') ); |
| | 980 | |
| | 981 | // Do the shortcode (only the [embed] one is registered) |
| | 982 | $content = do_shortcode( $content ); |
| | 983 | |
| | 984 | // Put the original shortcodes back |
| | 985 | $shortcode_tags = $orig_shortcode_tags; |
| | 986 | |
| | 987 | return $content; |
| | 988 | } |
| | 989 | |
| | 990 | // If a post was saved, then cache oEmbed results via AJAX |
| | 991 | function maybe_run_ajax_cache() { |
| | 992 | global $post_ID; |
| | 993 | |
| | 994 | if ( empty($_GET['message']) || 1 != $_GET['message'] ) |
| | 995 | return; |
| | 996 | |
| | 997 | ?> |
| | 998 | <script type="text/javascript"> |
| | 999 | /* <![CDATA[ */ |
| | 1000 | jQuery(document).ready(function($){ |
| | 1001 | $.get("<?php echo admin_url( 'admin-ajax.php?action=oembed-cache&post=' . $post_ID ); ?>"); |
| | 1002 | }); |
| | 1003 | /* ]]> */ |
| | 1004 | </script> |
| | 1005 | <?php |
| | 1006 | } |
| | 1007 | |
| | 1008 | |
| | 1009 | // Register a handler for WP_Embed::shortcode() |
| | 1010 | // wp_embed_register_handler() is a wrapper for this |
| | 1011 | function register_handler( $id, $regex, $callback, $priority = 10 ) { |
| | 1012 | $this->handlers[$priority][$id] = array( |
| | 1013 | 'regex' => $regex, |
| | 1014 | 'callback' => $callback, |
| | 1015 | ); |
| | 1016 | } |
| | 1017 | |
| | 1018 | // [embed] handler |
| | 1019 | function shortcode( $atts, $url = '' ) { |
| | 1020 | global $post; |
| | 1021 | |
| | 1022 | $atts = wp_parse_args( $atts, wp_embed_defaults() ); |
| | 1023 | |
| | 1024 | // Allow plugins to add their own handler |
| | 1025 | if ( false !== $filter = apply_filters( 'embed_other_before', false, $atts, $url ) ) |
| | 1026 | return $filter; |
| | 1027 | |
| | 1028 | // Look for known internal handlers |
| | 1029 | ksort( $this->handlers ); |
| | 1030 | foreach ( $this->handlers as $handlers ) { |
| | 1031 | foreach ( $handlers as $id => $handler ) { |
| | 1032 | if ( preg_match( $handler['regex'], $url, $matches ) && is_callable( $handler['callback'] ) ) { |
| | 1033 | return call_user_func( $handler['callback'], $matches, $atts, $url ); |
| | 1034 | } |
| | 1035 | } |
| | 1036 | } |
| | 1037 | |
| | 1038 | // Unknown URL format. Let oEmbed have a go. |
| | 1039 | if ( current_user_can('unfiltered_html') ) { |
| | 1040 | $cachekey = '_oembed_' . md5( $url . implode( '|', $atts ) ); |
| | 1041 | |
| | 1042 | $post_ID = ( !empty($post->ID) ) ? $post->ID : null; |
| | 1043 | if ( !empty($this->post_ID) ) // Potentially set by WP_Embed::cache_oembed() |
| | 1044 | $post_ID = $this->post_ID; |
| | 1045 | |
| | 1046 | // Check for a cached result (stored in the post meta) |
| | 1047 | if ( $post_ID && $this->usecache ) { |
| | 1048 | $cache = get_post_meta( $post_ID, $cachekey, true ); |
| | 1049 | |
| | 1050 | // Failures are cached |
| | 1051 | if ( '{{unknown}}' === $cache ) |
| | 1052 | return $this->make_link( $url ); |
| | 1053 | |
| | 1054 | if ( !empty($cache) ) |
| | 1055 | return $cache; |
| | 1056 | } |
| | 1057 | |
| | 1058 | $html = wp_oembed_get( $url, $atts ); |
| | 1059 | |
| | 1060 | // Cache the result |
| | 1061 | if ( $post_ID ) { |
| | 1062 | $cache = ( $html ) ? $html : '{{unknown}}'; |
| | 1063 | update_post_meta( $post_ID, $cachekey, $cache ); |
| | 1064 | } |
| | 1065 | |
| | 1066 | if ( $html ) |
| | 1067 | return $html; |
| | 1068 | } |
| | 1069 | |
| | 1070 | // Allow plugins to add their own handler |
| | 1071 | if ( false !== $filter = apply_filters( 'embed_other_after', false, $atts, $url ) ) |
| | 1072 | return $filter; |
| | 1073 | |
| | 1074 | // Still unknown |
| | 1075 | return $this->make_link( $url ); |
| | 1076 | } |
| | 1077 | |
| | 1078 | // On save_post, run the shortcode on the post in order to trigger WP_Embed::shortcode() to cache oEmbed results |
| | 1079 | function cache_oembed( $post_ID ) { |
| | 1080 | $post = get_post( $post_ID ); |
| | 1081 | |
| | 1082 | if ( empty($post->ID) ) |
| | 1083 | return false; |
| | 1084 | |
| | 1085 | if ( !in_array( $post->post_type, array( 'post', 'page' ) ) ) |
| | 1086 | return; |
| | 1087 | |
| | 1088 | // Dump existing caches |
| | 1089 | $post_metas = get_post_custom_keys( $post->ID ); |
| | 1090 | foreach( $post_metas as $post_meta_key ) { |
| | 1091 | if ( '_oembed_' == substr( $post_meta_key, 0, 8 ) ) |
| | 1092 | delete_post_meta($post->ID, $post_meta_key ); |
| | 1093 | } |
| | 1094 | |
| | 1095 | // Trigger a caching |
| | 1096 | if ( !empty($post->post_content) ) { |
| | 1097 | $this->post_ID = $post->ID; |
| | 1098 | $this->usecache = false; |
| | 1099 | $this->autoembed( $this->runshortcode( $post->post_content ) ); |
| | 1100 | $this->usecache = true; |
| | 1101 | } |
| | 1102 | |
| | 1103 | return true; |
| | 1104 | } |
| | 1105 | |
| | 1106 | // Helper function that makes a HTML link to the passed URL |
| | 1107 | function make_link( $url ) { |
| | 1108 | return ( $this->linkifunknown ) ? apply_filters( 'embed_urllink', '<a href="' . esc_attr($url) . '">' . esc_html($url) . '</a>' ) : $url; |
| | 1109 | } |
| | 1110 | |
| | 1111 | // With help from WP_Emebed::_autoembed(), this attempts to convert all URLs in a post into embeds |
| | 1112 | // This incorrectly turns links where the clickable text is a URL into an embed |
| | 1113 | // For example, it incorectly processes this: <a href="http://example.com/">http://example.com/</a> |
| | 1114 | function autoembed( $content ) { |
| | 1115 | // Stolen from make_clickable() |
| | 1116 | $content = ' ' . $content; |
| | 1117 | $content = preg_replace_callback('#(?<=[\s>])(\()?([\w]+?://(?:[\w\\x80-\\xff\#$%&~/\-=?@\[\](+]|[.,;:](?![\s<])|(?(1)\)(?![\s<])|\)))+)#is', array(&$this, '_autoembed'), $content); |
| | 1118 | return trim( $content ); |
| | 1119 | } |
| | 1120 | |
| | 1121 | // A helper function for WP_Embed::autoembed() that converts a URL into an embed |
| | 1122 | function _autoembed( $match ) { |
| | 1123 | $this->linkifunknown = false; |
| | 1124 | $return = $this->shortcode( array(), $match[2] ); |
| | 1125 | $this->linkifunknown = true; |
| | 1126 | return $return; |
| | 1127 | } |
| | 1128 | } |
| | 1129 | |
| | 1130 | $wp_embed = new WP_Embed(); |
| | 1131 | |
| | 1132 | // Wrapper to register a new hander for a URL format inside [embed] |
| | 1133 | function wp_embed_register_handler( $id, $regex, $callback ) { |
| | 1134 | global $wp_embed; |
| | 1135 | return $wp_embed->register_handler( $id, $regex, $callback ); |
| | 1136 | } |
| | 1137 | |
| | 1138 | // A helper function to return some default attributes for embeds |
| | 1139 | function wp_embed_defaults() { |
| | 1140 | return apply_filters( 'embed_defaults', array( |
| | 1141 | 'width' => 500, |
| | 1142 | 'height' => 700, |
| | 1143 | ) ); |
| | 1144 | } |
| | 1145 | |
| | 1146 | // Based on a supplied width/height ratio, return the biggest possible dimensions based on the max width/height |
| | 1147 | function wp_embed_calcdims( $example_width, $example_height, $max_width, $max_height ) { |
| | 1148 | return wp_constrain_dimensions( $example_width * 1000000, $example_height * 1000000, $max_width, $max_height ); |
| | 1149 | } |
| | 1150 | |
| | 1151 | // Wrapper to load the WP_oEmbed class and use it to get some HTML |
| | 1152 | function wp_oembed_get( $url, $args = '' ) { |
| | 1153 | require_once( 'class-oembed.php' ); |
| | 1154 | $oembed_object = _wp_oembed_get_object(); |
| | 1155 | return $oembed_object->getHTML( $url, $args ); |
| | 1156 | } |
| | 1157 | |
| | 1158 | |
| | 1159 | |
| | 1160 | // YouTube doesn't support oEmbed, so handle it internally |
| | 1161 | 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' ); |
| | 1162 | function wp_embed_handler_youtube( $matches, $atts, $url ) { |
| | 1163 | list($width, $height) = wp_embed_calcdims( 425, 344, $atts['width'], $atts['height'] ); |
| | 1164 | return "<object width='$width' height='$height'><param name='movie' value='http://www.youtube.com/v/{$matches[3]}&hl=en&fs=1'></param><param name='allowFullScreen' value='true'></param><param name='allowscriptaccess' value='always'></param><embed src='http://www.youtube.com/v/{$matches[3]}&hl=en&fs=1' type='application/x-shockwave-flash' allowscriptaccess='always' allowfullscreen='true' width='$width' height='$height'></embed></object>"; |
| | 1165 | } |
| | 1166 | |
| | 1167 | |
| | 1168 | // PollDaddy |
| | 1169 | wp_embed_register_handler( 'polldaddy', '#http://answers.polldaddy.com/poll/(\d+)(.*?)#i', 'wp_embed_handler_polldaddy' ); |
| | 1170 | function wp_embed_handler_polldaddy( $matches, $atts, $url ) { |
| | 1171 | return '<script type="text/javascript" src="http://s3.polldaddy.com/p/' . esc_attr($matches[1]) . '"></script>'; |
| | 1172 | } |
| | 1173 | No newline at end of file |