wp/wp-includes/class-wp-embed.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Embed
     6  * @subpackage Embed
     7  * @since 2.9.0
     7  * @since 2.9.0
     8  */
     8  */
     9 class WP_Embed {
     9 class WP_Embed {
    10 	var $handlers = array();
    10 	public $handlers = array();
    11 	var $post_ID;
    11 	public $post_ID;
    12 	var $usecache = true;
    12 	public $usecache = true;
    13 	var $linkifunknown = true;
    13 	public $linkifunknown = true;
       
    14 
       
    15 	/**
       
    16 	 * When an URL cannot be embedded, return false instead of returning a link
       
    17 	 * or the URL. Bypasses the 'embed_maybe_make_link' filter.
       
    18 	 */
       
    19 	public $return_false_on_fail = false;
    14 
    20 
    15 	/**
    21 	/**
    16 	 * Constructor
    22 	 * Constructor
    17 	 */
    23 	 */
    18 	function __construct() {
    24 	public function __construct() {
    19 		// Hack to get the [embed] shortcode to run before wpautop()
    25 		// Hack to get the [embed] shortcode to run before wpautop()
    20 		add_filter( 'the_content', array( $this, 'run_shortcode' ), 8 );
    26 		add_filter( 'the_content', array( $this, 'run_shortcode' ), 8 );
    21 
    27 
    22 		// Shortcode placeholder for strip_shortcodes()
    28 		// Shortcode placeholder for strip_shortcodes()
    23 		add_shortcode( 'embed', '__return_false' );
    29 		add_shortcode( 'embed', '__return_false' );
    24 
    30 
    25 		// Attempts to embed all URLs in a post
    31 		// Attempts to embed all URLs in a post
    26 		add_filter( 'the_content', array( $this, 'autoembed' ), 8 );
    32 		add_filter( 'the_content', array( $this, 'autoembed' ), 8 );
    27 
       
    28 		// When a post is saved, invalidate the oEmbed cache
       
    29 		add_action( 'pre_post_update', array( $this, 'delete_oembed_caches' ) );
       
    30 
    33 
    31 		// After a post is saved, cache oEmbed items via AJAX
    34 		// After a post is saved, cache oEmbed items via AJAX
    32 		add_action( 'edit_form_advanced', array( $this, 'maybe_run_ajax_cache' ) );
    35 		add_action( 'edit_form_advanced', array( $this, 'maybe_run_ajax_cache' ) );
    33 	}
    36 	}
    34 
    37 
    38 	 * Since the [embed] shortcode needs to be run earlier than other shortcodes,
    41 	 * Since the [embed] shortcode needs to be run earlier than other shortcodes,
    39 	 * this function removes all existing shortcodes, registers the [embed] shortcode,
    42 	 * this function removes all existing shortcodes, registers the [embed] shortcode,
    40 	 * calls {@link do_shortcode()}, and then re-registers the old shortcodes.
    43 	 * calls {@link do_shortcode()}, and then re-registers the old shortcodes.
    41 	 *
    44 	 *
    42 	 * @uses $shortcode_tags
    45 	 * @uses $shortcode_tags
    43 	 * @uses remove_all_shortcodes()
       
    44 	 * @uses add_shortcode()
       
    45 	 * @uses do_shortcode()
       
    46 	 *
    46 	 *
    47 	 * @param string $content Content to parse
    47 	 * @param string $content Content to parse
    48 	 * @return string Content with shortcode parsed
    48 	 * @return string Content with shortcode parsed
    49 	 */
    49 	 */
    50 	function run_shortcode( $content ) {
    50 	public function run_shortcode( $content ) {
    51 		global $shortcode_tags;
    51 		global $shortcode_tags;
    52 
    52 
    53 		// Back up current registered shortcodes and clear them all out
    53 		// Back up current registered shortcodes and clear them all out
    54 		$orig_shortcode_tags = $shortcode_tags;
    54 		$orig_shortcode_tags = $shortcode_tags;
    55 		remove_all_shortcodes();
    55 		remove_all_shortcodes();
    67 
    67 
    68 	/**
    68 	/**
    69 	 * If a post/page was saved, then output JavaScript to make
    69 	 * If a post/page was saved, then output JavaScript to make
    70 	 * an AJAX request that will call WP_Embed::cache_oembed().
    70 	 * an AJAX request that will call WP_Embed::cache_oembed().
    71 	 */
    71 	 */
    72 	function maybe_run_ajax_cache() {
    72 	public function maybe_run_ajax_cache() {
    73 		$post = get_post();
    73 		$post = get_post();
    74 
    74 
    75 		if ( ! $post || empty($_GET['message']) || 1 != $_GET['message'] )
    75 		if ( ! $post || empty( $_GET['message'] ) )
    76 			return;
    76 			return;
    77 
    77 
    78 ?>
    78 ?>
    79 <script type="text/javascript">
    79 <script type="text/javascript">
    80 /* <![CDATA[ */
       
    81 	jQuery(document).ready(function($){
    80 	jQuery(document).ready(function($){
    82 		$.get("<?php echo admin_url( 'admin-ajax.php?action=oembed-cache&post=' . $post->ID, 'relative' ); ?>");
    81 		$.get("<?php echo admin_url( 'admin-ajax.php?action=oembed-cache&post=' . $post->ID, 'relative' ); ?>");
    83 	});
    82 	});
    84 /* ]]> */
       
    85 </script>
    83 </script>
    86 <?php
    84 <?php
    87 	}
    85 	}
    88 
    86 
    89 	/**
    87 	/**
    93 	 * @param string $id An internal ID/name for the handler. Needs to be unique.
    91 	 * @param string $id An internal ID/name for the handler. Needs to be unique.
    94 	 * @param string $regex The regex that will be used to see if this handler should be used for a URL.
    92 	 * @param string $regex The regex that will be used to see if this handler should be used for a URL.
    95 	 * @param callback $callback The callback function that will be called if the regex is matched.
    93 	 * @param callback $callback The callback function that will be called if the regex is matched.
    96 	 * @param int $priority Optional. Used to specify the order in which the registered handlers will be tested (default: 10). Lower numbers correspond with earlier testing, and handlers with the same priority are tested in the order in which they were added to the action.
    94 	 * @param int $priority Optional. Used to specify the order in which the registered handlers will be tested (default: 10). Lower numbers correspond with earlier testing, and handlers with the same priority are tested in the order in which they were added to the action.
    97 	 */
    95 	 */
    98 	function register_handler( $id, $regex, $callback, $priority = 10 ) {
    96 	public function register_handler( $id, $regex, $callback, $priority = 10 ) {
    99 		$this->handlers[$priority][$id] = array(
    97 		$this->handlers[$priority][$id] = array(
   100 			'regex'    => $regex,
    98 			'regex'    => $regex,
   101 			'callback' => $callback,
    99 			'callback' => $callback,
   102 		);
   100 		);
   103 	}
   101 	}
   106 	 * Unregister a previously registered embed handler. Do not use this function directly, use {@link wp_embed_unregister_handler()} instead.
   104 	 * Unregister a previously registered embed handler. Do not use this function directly, use {@link wp_embed_unregister_handler()} instead.
   107 	 *
   105 	 *
   108 	 * @param string $id The handler ID that should be removed.
   106 	 * @param string $id The handler ID that should be removed.
   109 	 * @param int $priority Optional. The priority of the handler to be removed (default: 10).
   107 	 * @param int $priority Optional. The priority of the handler to be removed (default: 10).
   110 	 */
   108 	 */
   111 	function unregister_handler( $id, $priority = 10 ) {
   109 	public function unregister_handler( $id, $priority = 10 ) {
   112 		if ( isset($this->handlers[$priority][$id]) )
   110 		if ( isset($this->handlers[$priority][$id]) )
   113 			unset($this->handlers[$priority][$id]);
   111 			unset($this->handlers[$priority][$id]);
   114 	}
   112 	}
   115 
   113 
   116 	/**
   114 	/**
   117 	 * The {@link do_shortcode()} callback function.
   115 	 * The {@link do_shortcode()} callback function.
   118 	 *
   116 	 *
   119 	 * Attempts to convert a URL into embed HTML. Starts by checking the URL against the regex of the registered embed handlers.
   117 	 * Attempts to convert a URL into embed HTML. Starts by checking the URL against the regex of the registered embed handlers.
   120 	 * If none of the regex matches and it's enabled, then the URL will be given to the {@link WP_oEmbed} class.
   118 	 * If none of the regex matches and it's enabled, then the URL will be given to the {@link WP_oEmbed} class.
   121 	 *
   119 	 *
   122 	 * @uses wp_oembed_get()
   120 	 * @param array $attr {
   123 	 * @uses wp_parse_args()
   121 	 *     Shortcode attributes. Optional.
   124 	 * @uses wp_embed_defaults()
   122 	 *
   125 	 * @uses WP_Embed::maybe_make_link()
   123 	 *     @type int $width  Width of the embed in pixels.
   126 	 * @uses get_option()
   124 	 *     @type int $height Height of the embed in pixels.
   127 	 * @uses author_can()
   125 	 * }
   128 	 * @uses wp_cache_get()
       
   129 	 * @uses wp_cache_set()
       
   130 	 * @uses get_post_meta()
       
   131 	 * @uses update_post_meta()
       
   132 	 *
       
   133 	 * @param array $attr Shortcode attributes.
       
   134 	 * @param string $url The URL attempting to be embedded.
   126 	 * @param string $url The URL attempting to be embedded.
   135 	 * @return string The embed HTML on success, otherwise the original URL.
   127 	 * @return string|false The embed HTML on success, otherwise the original URL.
   136 	 */
   128 	 *                      `->maybe_make_link()` can return false on failure.
   137 	function shortcode( $attr, $url = '' ) {
   129 	 */
       
   130 	public function shortcode( $attr, $url = '' ) {
   138 		$post = get_post();
   131 		$post = get_post();
       
   132 
       
   133 		if ( empty( $url ) && ! empty( $attr['src'] ) ) {
       
   134 			$url = $attr['src'];
       
   135 		}
       
   136 
   139 
   137 
   140 		if ( empty( $url ) )
   138 		if ( empty( $url ) )
   141 			return '';
   139 			return '';
   142 
   140 
   143 		$rawattr = $attr;
   141 		$rawattr = $attr;
   144 		$attr = wp_parse_args( $attr, wp_embed_defaults() );
   142 		$attr = wp_parse_args( $attr, wp_embed_defaults( $url ) );
   145 
   143 
   146 		// kses converts & into &amp; and we need to undo this
   144 		// kses converts & into &amp; and we need to undo this
   147 		// See http://core.trac.wordpress.org/ticket/11311
   145 		// See https://core.trac.wordpress.org/ticket/11311
   148 		$url = str_replace( '&amp;', '&', $url );
   146 		$url = str_replace( '&amp;', '&', $url );
   149 
   147 
   150 		// Look for known internal handlers
   148 		// Look for known internal handlers
   151 		ksort( $this->handlers );
   149 		ksort( $this->handlers );
   152 		foreach ( $this->handlers as $priority => $handlers ) {
   150 		foreach ( $this->handlers as $priority => $handlers ) {
   156 						/**
   154 						/**
   157 						 * Filter the returned embed handler.
   155 						 * Filter the returned embed handler.
   158 						 *
   156 						 *
   159 						 * @since 2.9.0
   157 						 * @since 2.9.0
   160 						 *
   158 						 *
       
   159 						 * @see WP_Embed::shortcode()
       
   160 						 *
   161 						 * @param mixed  $return The shortcode callback function to call.
   161 						 * @param mixed  $return The shortcode callback function to call.
   162 						 * @param string $url    The attempted embed URL.
   162 						 * @param string $url    The attempted embed URL.
   163 						 * @param array  $attr   An array of shortcode attributes.
   163 						 * @param array  $attr   An array of shortcode attributes.
   164 						 */
   164 						 */
   165 						return apply_filters( 'embed_handler_html', $return, $url, $attr );
   165 						return apply_filters( 'embed_handler_html', $return, $url, $attr );
   173 
   173 
   174 		// Unknown URL format. Let oEmbed have a go.
   174 		// Unknown URL format. Let oEmbed have a go.
   175 		if ( $post_ID ) {
   175 		if ( $post_ID ) {
   176 
   176 
   177 			// Check for a cached result (stored in the post meta)
   177 			// Check for a cached result (stored in the post meta)
   178 			$cachekey = '_oembed_' . md5( $url . serialize( $attr ) );
   178 			$key_suffix = md5( $url . serialize( $attr ) );
   179 			if ( $this->usecache ) {
   179 			$cachekey = '_oembed_' . $key_suffix;
   180 				$cache = get_post_meta( $post_ID, $cachekey, true );
   180 			$cachekey_time = '_oembed_time_' . $key_suffix;
   181 
   181 
   182 				// Failures are cached
   182 			/**
       
   183 			 * Filter the oEmbed TTL value (time to live).
       
   184 			 *
       
   185 			 * @since 4.0.0
       
   186 			 *
       
   187 			 * @param int    $time    Time to live (in seconds).
       
   188 			 * @param string $url     The attempted embed URL.
       
   189 			 * @param array  $attr    An array of shortcode attributes.
       
   190 			 * @param int    $post_ID Post ID.
       
   191 			 */
       
   192 			$ttl = apply_filters( 'oembed_ttl', DAY_IN_SECONDS, $url, $attr, $post_ID );
       
   193 
       
   194 			$cache = get_post_meta( $post_ID, $cachekey, true );
       
   195 			$cache_time = get_post_meta( $post_ID, $cachekey_time, true );
       
   196 
       
   197 			if ( ! $cache_time ) {
       
   198 				$cache_time = 0;
       
   199 			}
       
   200 
       
   201 			$cached_recently = ( time() - $cache_time ) < $ttl;
       
   202 
       
   203 			if ( $this->usecache || $cached_recently ) {
       
   204 				// Failures are cached. Serve one if we're using the cache.
   183 				if ( '{{unknown}}' === $cache )
   205 				if ( '{{unknown}}' === $cache )
   184 					return $this->maybe_make_link( $url );
   206 					return $this->maybe_make_link( $url );
   185 
   207 
   186 				if ( ! empty( $cache ) )
   208 				if ( ! empty( $cache ) ) {
   187 					/**
   209 					/**
   188 					 * Filter the cached oEmbed HTML.
   210 					 * Filter the cached oEmbed HTML.
   189 					 *
   211 					 *
   190 					 * @since 2.9.0
   212 					 * @since 2.9.0
       
   213 					 *
       
   214 					 * @see WP_Embed::shortcode()
   191 					 *
   215 					 *
   192 					 * @param mixed  $cache   The cached HTML result, stored in post meta.
   216 					 * @param mixed  $cache   The cached HTML result, stored in post meta.
   193 					 * @param string $url     The attempted embed URL.
   217 					 * @param string $url     The attempted embed URL.
   194 					 * @param array  $attr    An array of shortcode attributes.
   218 					 * @param array  $attr    An array of shortcode attributes.
   195 					 * @param int    $post_ID Post ID.
   219 					 * @param int    $post_ID Post ID.
   196 					 */
   220 					 */
   197 					return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $post_ID );
   221 					return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $post_ID );
       
   222 				}
   198 			}
   223 			}
   199 
   224 
   200 			/**
   225 			/**
   201 			 * Filter whether to inspect the given URL for discoverable <link> tags.
   226 			 * Filter whether to inspect the given URL for discoverable link tags.
       
   227 			 *
       
   228 			 * @since 2.9.0
   202 			 *
   229 			 *
   203 			 * @see WP_oEmbed::discover()
   230 			 * @see WP_oEmbed::discover()
   204 			 *
   231 			 *
   205 			 * @param bool false Whether to enable <link> tag discovery. Default false.
   232 			 * @param bool $enable Whether to enable `<link>` tag discovery. Default false.
   206 			 */
   233 			 */
   207 			$attr['discover'] = ( apply_filters( 'embed_oembed_discover', false ) && author_can( $post_ID, 'unfiltered_html' ) );
   234 			$attr['discover'] = ( apply_filters( 'embed_oembed_discover', false ) && author_can( $post_ID, 'unfiltered_html' ) );
   208 
   235 
   209 			// Use oEmbed to get the HTML
   236 			// Use oEmbed to get the HTML
   210 			$html = wp_oembed_get( $url, $attr );
   237 			$html = wp_oembed_get( $url, $attr );
   211 
   238 
   212 			// Cache the result
   239 			// Maybe cache the result
   213 			$cache = ( $html ) ? $html : '{{unknown}}';
   240 			if ( $html ) {
   214 			update_post_meta( $post_ID, $cachekey, $cache );
   241 				update_post_meta( $post_ID, $cachekey, $html );
       
   242 				update_post_meta( $post_ID, $cachekey_time, time() );
       
   243 			} elseif ( ! $cache ) {
       
   244 				update_post_meta( $post_ID, $cachekey, '{{unknown}}' );
       
   245 			}
   215 
   246 
   216 			// If there was a result, return it
   247 			// If there was a result, return it
   217 			if ( $html ) {
   248 			if ( $html ) {
   218 				/** This filter is documented in wp-includes/class-wp-embed.php */
   249 				/** This filter is documented in wp-includes/class-wp-embed.php */
   219 				return apply_filters( 'embed_oembed_html', $html, $url, $attr, $post_ID );
   250 				return apply_filters( 'embed_oembed_html', $html, $url, $attr, $post_ID );
   223 		// Still unknown
   254 		// Still unknown
   224 		return $this->maybe_make_link( $url );
   255 		return $this->maybe_make_link( $url );
   225 	}
   256 	}
   226 
   257 
   227 	/**
   258 	/**
   228 	 * Delete all oEmbed caches.
   259 	 * Delete all oEmbed caches. Unused by core as of 4.0.0.
   229 	 *
   260 	 *
   230 	 * @param int $post_ID Post ID to delete the caches for.
   261 	 * @param int $post_ID Post ID to delete the caches for.
   231 	 */
   262 	 */
   232 	function delete_oembed_caches( $post_ID ) {
   263 	public function delete_oembed_caches( $post_ID ) {
   233 		$post_metas = get_post_custom_keys( $post_ID );
   264 		$post_metas = get_post_custom_keys( $post_ID );
   234 		if ( empty($post_metas) )
   265 		if ( empty($post_metas) )
   235 			return;
   266 			return;
   236 
   267 
   237 		foreach( $post_metas as $post_meta_key ) {
   268 		foreach( $post_metas as $post_meta_key ) {
   243 	/**
   274 	/**
   244 	 * Triggers a caching of all oEmbed results.
   275 	 * Triggers a caching of all oEmbed results.
   245 	 *
   276 	 *
   246 	 * @param int $post_ID Post ID to do the caching for.
   277 	 * @param int $post_ID Post ID to do the caching for.
   247 	 */
   278 	 */
   248 	function cache_oembed( $post_ID ) {
   279 	public function cache_oembed( $post_ID ) {
   249 		$post = get_post( $post_ID );
   280 		$post = get_post( $post_ID );
   250 
   281 
   251 		$post_types = array( 'post', 'page' );
   282 		$post_types = get_post_types( array( 'show_ui' => true ) );
   252 		/**
   283 		/**
   253 		 * Filter the array of post types to cache oEmbed results for.
   284 		 * Filter the array of post types to cache oEmbed results for.
   254 		 *
   285 		 *
   255 		 * @since 2.9.0
   286 		 * @since 2.9.0
   256 		 *
   287 		 *
   257 		 * @param array $post_types Array of post types to cache oEmbed results for. Default 'post', 'page'.
   288 		 * @param array $post_types Array of post types to cache oEmbed results for. Defaults to post types with `show_ui` set to true.
   258 		 */
   289 		 */
   259 		if ( empty($post->ID) || !in_array( $post->post_type, apply_filters( 'embed_cache_oembed_types', $post_types ) ) )
   290 		if ( empty( $post->ID ) || ! in_array( $post->post_type, apply_filters( 'embed_cache_oembed_types', $post_types ) ) ){
   260 			return;
   291 			return;
       
   292 		}
   261 
   293 
   262 		// Trigger a caching
   294 		// Trigger a caching
   263 		if ( !empty($post->post_content) ) {
   295 		if ( ! empty( $post->post_content ) ) {
   264 			$this->post_ID = $post->ID;
   296 			$this->post_ID = $post->ID;
   265 			$this->usecache = false;
   297 			$this->usecache = false;
   266 
   298 
   267 			$content = $this->run_shortcode( $post->post_content );
   299 			$content = $this->run_shortcode( $post->post_content );
   268 			$this->autoembed( $content );
   300 			$this->autoembed( $content );
   277 	 * @uses WP_Embed::autoembed_callback()
   309 	 * @uses WP_Embed::autoembed_callback()
   278 	 *
   310 	 *
   279 	 * @param string $content The content to be searched.
   311 	 * @param string $content The content to be searched.
   280 	 * @return string Potentially modified $content.
   312 	 * @return string Potentially modified $content.
   281 	 */
   313 	 */
   282 	function autoembed( $content ) {
   314 	public function autoembed( $content ) {
   283 		return preg_replace_callback( '|^\s*(https?://[^\s"]+)\s*$|im', array( $this, 'autoembed_callback' ), $content );
   315 		return preg_replace_callback( '|^(\s*)(https?://[^\s"]+)(\s*)$|im', array( $this, 'autoembed_callback' ), $content );
   284 	}
   316 	}
   285 
   317 
   286 	/**
   318 	/**
   287 	 * Callback function for {@link WP_Embed::autoembed()}.
   319 	 * Callback function for {@link WP_Embed::autoembed()}.
   288 	 *
       
   289 	 * @uses WP_Embed::shortcode()
       
   290 	 *
   320 	 *
   291 	 * @param array $match A regex match array.
   321 	 * @param array $match A regex match array.
   292 	 * @return string The embed HTML on success, otherwise the original URL.
   322 	 * @return string The embed HTML on success, otherwise the original URL.
   293 	 */
   323 	 */
   294 	function autoembed_callback( $match ) {
   324 	public function autoembed_callback( $match ) {
   295 		$oldval = $this->linkifunknown;
   325 		$oldval = $this->linkifunknown;
   296 		$this->linkifunknown = false;
   326 		$this->linkifunknown = false;
   297 		$return = $this->shortcode( array(), $match[1] );
   327 		$return = $this->shortcode( array(), $match[2] );
   298 		$this->linkifunknown = $oldval;
   328 		$this->linkifunknown = $oldval;
   299 
   329 
   300 		return "\n$return\n";
   330 		return $match[1] . $return . $match[3];
   301 	}
   331 	}
   302 
   332 
   303 	/**
   333 	/**
   304 	 * Conditionally makes a hyperlink based on an internal class variable.
   334 	 * Conditionally makes a hyperlink based on an internal class variable.
   305 	 *
   335 	 *
   306 	 * @param string $url URL to potentially be linked.
   336 	 * @param string $url URL to potentially be linked.
   307 	 * @return string Linked URL or the original URL.
   337 	 * @return false|string Linked URL or the original URL. False if 'return_false_on_fail' is true.
   308 	 */
   338 	 */
   309 	function maybe_make_link( $url ) {
   339 	public function maybe_make_link( $url ) {
       
   340 		if ( $this->return_false_on_fail ) {
       
   341 			return false;
       
   342 		}
       
   343 
   310 		$output = ( $this->linkifunknown ) ? '<a href="' . esc_url($url) . '">' . esc_html($url) . '</a>' : $url;
   344 		$output = ( $this->linkifunknown ) ? '<a href="' . esc_url($url) . '">' . esc_html($url) . '</a>' : $url;
   311 
   345 
   312 		/**
   346 		/**
   313 		 * Filter the returned, maybe-linked embed URL.
   347 		 * Filter the returned, maybe-linked embed URL.
   314 		 *
   348 		 *