[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * oEmbed API: Top-level oEmbed functionality 4 * 5 * @package WordPress 6 * @subpackage oEmbed 7 * @since 4.4.0 8 */ 9 10 /** 11 * Registers an embed handler. 12 * 13 * Should probably only be used for sites that do not support oEmbed. 14 * 15 * @since 2.9.0 16 * 17 * @global WP_Embed $wp_embed WordPress Embed object. 18 * 19 * @param string $id An internal ID/name for the handler. Needs to be unique. 20 * @param string $regex The regex that will be used to see if this handler should be used for a URL. 21 * @param callable $callback The callback function that will be called if the regex is matched. 22 * @param int $priority Optional. Used to specify the order in which the registered handlers will 23 * be tested. Default 10. 24 */ 25 function wp_embed_register_handler( $id, $regex, $callback, $priority = 10 ) { 26 global $wp_embed; 27 $wp_embed->register_handler( $id, $regex, $callback, $priority ); 28 } 29 30 /** 31 * Unregisters a previously-registered embed handler. 32 * 33 * @since 2.9.0 34 * 35 * @global WP_Embed $wp_embed WordPress Embed object. 36 * 37 * @param string $id The handler ID that should be removed. 38 * @param int $priority Optional. The priority of the handler to be removed. Default 10. 39 */ 40 function wp_embed_unregister_handler( $id, $priority = 10 ) { 41 global $wp_embed; 42 $wp_embed->unregister_handler( $id, $priority ); 43 } 44 45 /** 46 * Creates default array of embed parameters. 47 * 48 * The width defaults to the content width as specified by the theme. If the 49 * theme does not specify a content width, then 500px is used. 50 * 51 * The default height is 1.5 times the width, or 1000px, whichever is smaller. 52 * 53 * The {@see 'embed_defaults'} filter can be used to adjust either of these values. 54 * 55 * @since 2.9.0 56 * 57 * @global int $content_width 58 * 59 * @param string $url Optional. The URL that should be embedded. Default empty. 60 * @return int[] { 61 * Indexed array of the embed width and height in pixels. 62 * 63 * @type int $0 The embed width. 64 * @type int $1 The embed height. 65 * } 66 */ 67 function wp_embed_defaults( $url = '' ) { 68 if ( ! empty( $GLOBALS['content_width'] ) ) { 69 $width = (int) $GLOBALS['content_width']; 70 } 71 72 if ( empty( $width ) ) { 73 $width = 500; 74 } 75 76 $height = min( (int) ceil( $width * 1.5 ), 1000 ); 77 78 /** 79 * Filters the default array of embed dimensions. 80 * 81 * @since 2.9.0 82 * 83 * @param int[] $size { 84 * Indexed array of the embed width and height in pixels. 85 * 86 * @type int $0 The embed width. 87 * @type int $1 The embed height. 88 * } 89 * @param string $url The URL that should be embedded. 90 */ 91 return apply_filters( 'embed_defaults', compact( 'width', 'height' ), $url ); 92 } 93 94 /** 95 * Attempts to fetch the embed HTML for a provided URL using oEmbed. 96 * 97 * @since 2.9.0 98 * 99 * @see WP_oEmbed 100 * 101 * @param string $url The URL that should be embedded. 102 * @param array|string $args { 103 * Optional. Additional arguments for retrieving embed HTML. Default empty. 104 * 105 * @type int|string $width Optional. The `maxwidth` value passed to the provider URL. 106 * @type int|string $height Optional. The `maxheight` value passed to the provider URL. 107 * @type bool $discover Optional. Determines whether to attempt to discover link tags 108 * at the given URL for an oEmbed provider when the provider URL 109 * is not found in the built-in providers list. Default true. 110 * } 111 * @return string|false The embed HTML on success, false on failure. 112 */ 113 function wp_oembed_get( $url, $args = '' ) { 114 $oembed = _wp_oembed_get_object(); 115 return $oembed->get_html( $url, $args ); 116 } 117 118 /** 119 * Returns the initialized WP_oEmbed object. 120 * 121 * @since 2.9.0 122 * @access private 123 * 124 * @return WP_oEmbed object. 125 */ 126 function _wp_oembed_get_object() { 127 static $wp_oembed = null; 128 129 if ( is_null( $wp_oembed ) ) { 130 $wp_oembed = new WP_oEmbed(); 131 } 132 return $wp_oembed; 133 } 134 135 /** 136 * Adds a URL format and oEmbed provider URL pair. 137 * 138 * @since 2.9.0 139 * 140 * @see WP_oEmbed 141 * 142 * @param string $format The format of URL that this provider can handle. You can use asterisks 143 * as wildcards. 144 * @param string $provider The URL to the oEmbed provider. 145 * @param bool $regex Optional. Whether the `$format` parameter is in a RegEx format. Default false. 146 */ 147 function wp_oembed_add_provider( $format, $provider, $regex = false ) { 148 if ( did_action( 'plugins_loaded' ) ) { 149 $oembed = _wp_oembed_get_object(); 150 $oembed->providers[ $format ] = array( $provider, $regex ); 151 } else { 152 WP_oEmbed::_add_provider_early( $format, $provider, $regex ); 153 } 154 } 155 156 /** 157 * Removes an oEmbed provider. 158 * 159 * @since 3.5.0 160 * 161 * @see WP_oEmbed 162 * 163 * @param string $format The URL format for the oEmbed provider to remove. 164 * @return bool Was the provider removed successfully? 165 */ 166 function wp_oembed_remove_provider( $format ) { 167 if ( did_action( 'plugins_loaded' ) ) { 168 $oembed = _wp_oembed_get_object(); 169 170 if ( isset( $oembed->providers[ $format ] ) ) { 171 unset( $oembed->providers[ $format ] ); 172 return true; 173 } 174 } else { 175 WP_oEmbed::_remove_provider_early( $format ); 176 } 177 178 return false; 179 } 180 181 /** 182 * Determines if default embed handlers should be loaded. 183 * 184 * Checks to make sure that the embeds library hasn't already been loaded. If 185 * it hasn't, then it will load the embeds library. 186 * 187 * @since 2.9.0 188 * 189 * @see wp_embed_register_handler() 190 */ 191 function wp_maybe_load_embeds() { 192 /** 193 * Filters whether to load the default embed handlers. 194 * 195 * Returning a falsey value will prevent loading the default embed handlers. 196 * 197 * @since 2.9.0 198 * 199 * @param bool $maybe_load_embeds Whether to load the embeds library. Default true. 200 */ 201 if ( ! apply_filters( 'load_default_embeds', true ) ) { 202 return; 203 } 204 205 wp_embed_register_handler( 'youtube_embed_url', '#https?://(www.)?youtube\.com/(?:v|embed)/([^/]+)#i', 'wp_embed_handler_youtube' ); 206 207 /** 208 * Filters the audio embed handler callback. 209 * 210 * @since 3.6.0 211 * 212 * @param callable $handler Audio embed handler callback function. 213 */ 214 wp_embed_register_handler( 'audio', '#^https?://.+?\.(' . implode( '|', wp_get_audio_extensions() ) . ')$#i', apply_filters( 'wp_audio_embed_handler', 'wp_embed_handler_audio' ), 9999 ); 215 216 /** 217 * Filters the video embed handler callback. 218 * 219 * @since 3.6.0 220 * 221 * @param callable $handler Video embed handler callback function. 222 */ 223 wp_embed_register_handler( 'video', '#^https?://.+?\.(' . implode( '|', wp_get_video_extensions() ) . ')$#i', apply_filters( 'wp_video_embed_handler', 'wp_embed_handler_video' ), 9999 ); 224 } 225 226 /** 227 * YouTube iframe embed handler callback. 228 * 229 * Catches YouTube iframe embed URLs that are not parsable by oEmbed but can be translated into a URL that is. 230 * 231 * @since 4.0.0 232 * 233 * @global WP_Embed $wp_embed WordPress Embed object. 234 * 235 * @param array $matches The RegEx matches from the provided regex when calling 236 * wp_embed_register_handler(). 237 * @param array $attr Embed attributes. 238 * @param string $url The original URL that was matched by the regex. 239 * @param array $rawattr The original unmodified attributes. 240 * @return string The embed HTML. 241 */ 242 function wp_embed_handler_youtube( $matches, $attr, $url, $rawattr ) { 243 global $wp_embed; 244 $embed = $wp_embed->autoembed( sprintf( 'https://youtube.com/watch?v=%s', urlencode( $matches[2] ) ) ); 245 246 /** 247 * Filters the YouTube embed output. 248 * 249 * @since 4.0.0 250 * 251 * @see wp_embed_handler_youtube() 252 * 253 * @param string $embed YouTube embed output. 254 * @param array $attr An array of embed attributes. 255 * @param string $url The original URL that was matched by the regex. 256 * @param array $rawattr The original unmodified attributes. 257 */ 258 return apply_filters( 'wp_embed_handler_youtube', $embed, $attr, $url, $rawattr ); 259 } 260 261 /** 262 * Audio embed handler callback. 263 * 264 * @since 3.6.0 265 * 266 * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler(). 267 * @param array $attr Embed attributes. 268 * @param string $url The original URL that was matched by the regex. 269 * @param array $rawattr The original unmodified attributes. 270 * @return string The embed HTML. 271 */ 272 function wp_embed_handler_audio( $matches, $attr, $url, $rawattr ) { 273 $audio = sprintf( '[audio src="%s" /]', esc_url( $url ) ); 274 275 /** 276 * Filters the audio embed output. 277 * 278 * @since 3.6.0 279 * 280 * @param string $audio Audio embed output. 281 * @param array $attr An array of embed attributes. 282 * @param string $url The original URL that was matched by the regex. 283 * @param array $rawattr The original unmodified attributes. 284 */ 285 return apply_filters( 'wp_embed_handler_audio', $audio, $attr, $url, $rawattr ); 286 } 287 288 /** 289 * Video embed handler callback. 290 * 291 * @since 3.6.0 292 * 293 * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler(). 294 * @param array $attr Embed attributes. 295 * @param string $url The original URL that was matched by the regex. 296 * @param array $rawattr The original unmodified attributes. 297 * @return string The embed HTML. 298 */ 299 function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) { 300 $dimensions = ''; 301 if ( ! empty( $rawattr['width'] ) && ! empty( $rawattr['height'] ) ) { 302 $dimensions .= sprintf( 'width="%d" ', (int) $rawattr['width'] ); 303 $dimensions .= sprintf( 'height="%d" ', (int) $rawattr['height'] ); 304 } 305 $video = sprintf( '[video %s src="%s" /]', $dimensions, esc_url( $url ) ); 306 307 /** 308 * Filters the video embed output. 309 * 310 * @since 3.6.0 311 * 312 * @param string $video Video embed output. 313 * @param array $attr An array of embed attributes. 314 * @param string $url The original URL that was matched by the regex. 315 * @param array $rawattr The original unmodified attributes. 316 */ 317 return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr ); 318 } 319 320 /** 321 * Registers the oEmbed REST API route. 322 * 323 * @since 4.4.0 324 */ 325 function wp_oembed_register_route() { 326 $controller = new WP_oEmbed_Controller(); 327 $controller->register_routes(); 328 } 329 330 /** 331 * Adds oEmbed discovery links in the head element of the website. 332 * 333 * @since 4.4.0 334 */ 335 function wp_oembed_add_discovery_links() { 336 $output = ''; 337 338 if ( is_singular() ) { 339 $output .= '<link rel="alternate" title="' . _x( 'oEmbed (JSON)', 'oEmbed resource link name' ) . '" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink() ) ) . '" />' . "\n"; 340 341 if ( class_exists( 'SimpleXMLElement' ) ) { 342 $output .= '<link rel="alternate" title="' . _x( 'oEmbed (XML)', 'oEmbed resource link name' ) . '" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink(), 'xml' ) ) . '" />' . "\n"; 343 } 344 } 345 346 /** 347 * Filters the oEmbed discovery links HTML. 348 * 349 * @since 4.4.0 350 * 351 * @param string $output HTML of the discovery links. 352 */ 353 echo apply_filters( 'oembed_discovery_links', $output ); 354 } 355 356 /** 357 * Adds the necessary JavaScript to communicate with the embedded iframes. 358 * 359 * This function is no longer used directly. For back-compat it exists exclusively as a way to indicate that the oEmbed 360 * host JS _should_ be added. In `default-filters.php` there remains this code: 361 * 362 * add_action( 'wp_head', 'wp_oembed_add_host_js' ) 363 * 364 * Historically a site has been able to disable adding the oEmbed host script by doing: 365 * 366 * remove_action( 'wp_head', 'wp_oembed_add_host_js' ) 367 * 368 * In order to ensure that such code still works as expected, this function remains. There is now a `has_action()` check 369 * in `wp_maybe_enqueue_oembed_host_js()` to see if `wp_oembed_add_host_js()` has not been unhooked from running at the 370 * `wp_head` action. 371 * 372 * @since 4.4.0 373 * @deprecated 5.9.0 Use {@see wp_maybe_enqueue_oembed_host_js()} instead. 374 */ 375 function wp_oembed_add_host_js() {} 376 377 /** 378 * Enqueue the wp-embed script if the provided oEmbed HTML contains a post embed. 379 * 380 * In order to only enqueue the wp-embed script on pages that actually contain post embeds, this function checks if the 381 * provided HTML contains post embed markup and if so enqueues the script so that it will get printed in the footer. 382 * 383 * @since 5.9.0 384 * 385 * @param string $html Embed markup. 386 * @return string Embed markup (without modifications). 387 */ 388 function wp_maybe_enqueue_oembed_host_js( $html ) { 389 if ( 390 has_action( 'wp_head', 'wp_oembed_add_host_js' ) 391 && 392 preg_match( '/<blockquote\s[^>]*?wp-embedded-content/', $html ) 393 ) { 394 wp_enqueue_script( 'wp-embed' ); 395 } 396 return $html; 397 } 398 399 /** 400 * Retrieves the URL to embed a specific post in an iframe. 401 * 402 * @since 4.4.0 403 * 404 * @param int|WP_Post $post Optional. Post ID or object. Defaults to the current post. 405 * @return string|false The post embed URL on success, false if the post doesn't exist. 406 */ 407 function get_post_embed_url( $post = null ) { 408 $post = get_post( $post ); 409 410 if ( ! $post ) { 411 return false; 412 } 413 414 $embed_url = trailingslashit( get_permalink( $post ) ) . user_trailingslashit( 'embed' ); 415 $path_conflict = get_page_by_path( str_replace( home_url(), '', $embed_url ), OBJECT, get_post_types( array( 'public' => true ) ) ); 416 417 if ( ! get_option( 'permalink_structure' ) || $path_conflict ) { 418 $embed_url = add_query_arg( array( 'embed' => 'true' ), get_permalink( $post ) ); 419 } 420 421 /** 422 * Filters the URL to embed a specific post. 423 * 424 * @since 4.4.0 425 * 426 * @param string $embed_url The post embed URL. 427 * @param WP_Post $post The corresponding post object. 428 */ 429 return sanitize_url( apply_filters( 'post_embed_url', $embed_url, $post ) ); 430 } 431 432 /** 433 * Retrieves the oEmbed endpoint URL for a given permalink. 434 * 435 * Pass an empty string as the first argument to get the endpoint base URL. 436 * 437 * @since 4.4.0 438 * 439 * @param string $permalink Optional. The permalink used for the `url` query arg. Default empty. 440 * @param string $format Optional. The requested response format. Default 'json'. 441 * @return string The oEmbed endpoint URL. 442 */ 443 function get_oembed_endpoint_url( $permalink = '', $format = 'json' ) { 444 $url = rest_url( 'oembed/1.0/embed' ); 445 446 if ( '' !== $permalink ) { 447 $url = add_query_arg( 448 array( 449 'url' => urlencode( $permalink ), 450 'format' => ( 'json' !== $format ) ? $format : false, 451 ), 452 $url 453 ); 454 } 455 456 /** 457 * Filters the oEmbed endpoint URL. 458 * 459 * @since 4.4.0 460 * 461 * @param string $url The URL to the oEmbed endpoint. 462 * @param string $permalink The permalink used for the `url` query arg. 463 * @param string $format The requested response format. 464 */ 465 return apply_filters( 'oembed_endpoint_url', $url, $permalink, $format ); 466 } 467 468 /** 469 * Retrieves the embed code for a specific post. 470 * 471 * @since 4.4.0 472 * 473 * @param int $width The width for the response. 474 * @param int $height The height for the response. 475 * @param int|WP_Post $post Optional. Post ID or object. Default is global `$post`. 476 * @return string|false Embed code on success, false if post doesn't exist. 477 */ 478 function get_post_embed_html( $width, $height, $post = null ) { 479 $post = get_post( $post ); 480 481 if ( ! $post ) { 482 return false; 483 } 484 485 $embed_url = get_post_embed_url( $post ); 486 487 $secret = wp_generate_password( 10, false ); 488 $embed_url .= "#?secret={$secret}"; 489 490 $output = sprintf( 491 '<blockquote class="wp-embedded-content" data-secret="%1$s"><a href="%2$s">%3$s</a></blockquote>', 492 esc_attr( $secret ), 493 esc_url( get_permalink( $post ) ), 494 get_the_title( $post ) 495 ); 496 497 $output .= sprintf( 498 '<iframe sandbox="allow-scripts" security="restricted" src="%1$s" width="%2$d" height="%3$d" title="%4$s" data-secret="%5$s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" class="wp-embedded-content"></iframe>', 499 esc_url( $embed_url ), 500 absint( $width ), 501 absint( $height ), 502 esc_attr( 503 sprintf( 504 /* translators: 1: Post title, 2: Site title. */ 505 __( '“%1$s” — %2$s' ), 506 get_the_title( $post ), 507 get_bloginfo( 'name' ) 508 ) 509 ), 510 esc_attr( $secret ) 511 ); 512 513 /* 514 * Note that the script must be placed after the <blockquote> and <iframe> due to a regexp parsing issue in 515 * `wp_filter_oembed_result()`. Because of the regex pattern starts with `|(<blockquote>.*?</blockquote>)?.*|` 516 * wherein the <blockquote> is marked as being optional, if it is not at the beginning of the string then the group 517 * will fail to match and everything will be matched by `.*` and not included in the group. This regex issue goes 518 * back to WordPress 4.4, so in order to not break older installs this script must come at the end. 519 */ 520 $output .= wp_get_inline_script_tag( 521 file_get_contents( ABSPATH . WPINC . '/js/wp-embed' . wp_scripts_get_suffix() . '.js' ) 522 ); 523 524 /** 525 * Filters the embed HTML output for a given post. 526 * 527 * @since 4.4.0 528 * 529 * @param string $output The default iframe tag to display embedded content. 530 * @param WP_Post $post Current post object. 531 * @param int $width Width of the response. 532 * @param int $height Height of the response. 533 */ 534 return apply_filters( 'embed_html', $output, $post, $width, $height ); 535 } 536 537 /** 538 * Retrieves the oEmbed response data for a given post. 539 * 540 * @since 4.4.0 541 * 542 * @param WP_Post|int $post Post ID or post object. 543 * @param int $width The requested width. 544 * @return array|false Response data on success, false if post doesn't exist 545 * or is not publicly viewable. 546 */ 547 function get_oembed_response_data( $post, $width ) { 548 $post = get_post( $post ); 549 $width = absint( $width ); 550 551 if ( ! $post ) { 552 return false; 553 } 554 555 if ( ! is_post_publicly_viewable( $post ) ) { 556 return false; 557 } 558 559 /** 560 * Filters the allowed minimum and maximum widths for the oEmbed response. 561 * 562 * @since 4.4.0 563 * 564 * @param array $min_max_width { 565 * Minimum and maximum widths for the oEmbed response. 566 * 567 * @type int $min Minimum width. Default 200. 568 * @type int $max Maximum width. Default 600. 569 * } 570 */ 571 $min_max_width = apply_filters( 572 'oembed_min_max_width', 573 array( 574 'min' => 200, 575 'max' => 600, 576 ) 577 ); 578 579 $width = min( max( $min_max_width['min'], $width ), $min_max_width['max'] ); 580 $height = max( (int) ceil( $width / 16 * 9 ), 200 ); 581 582 $data = array( 583 'version' => '1.0', 584 'provider_name' => get_bloginfo( 'name' ), 585 'provider_url' => get_home_url(), 586 'author_name' => get_bloginfo( 'name' ), 587 'author_url' => get_home_url(), 588 'title' => get_the_title( $post ), 589 'type' => 'link', 590 ); 591 592 $author = get_userdata( $post->post_author ); 593 594 if ( $author ) { 595 $data['author_name'] = $author->display_name; 596 $data['author_url'] = get_author_posts_url( $author->ID ); 597 } 598 599 /** 600 * Filters the oEmbed response data. 601 * 602 * @since 4.4.0 603 * 604 * @param array $data The response data. 605 * @param WP_Post $post The post object. 606 * @param int $width The requested width. 607 * @param int $height The calculated height. 608 */ 609 return apply_filters( 'oembed_response_data', $data, $post, $width, $height ); 610 } 611 612 613 /** 614 * Retrieves the oEmbed response data for a given URL. 615 * 616 * @since 5.0.0 617 * 618 * @param string $url The URL that should be inspected for discovery `<link>` tags. 619 * @param array $args oEmbed remote get arguments. 620 * @return object|false oEmbed response data if the URL does belong to the current site. False otherwise. 621 */ 622 function get_oembed_response_data_for_url( $url, $args ) { 623 $switched_blog = false; 624 625 if ( is_multisite() ) { 626 $url_parts = wp_parse_args( 627 wp_parse_url( $url ), 628 array( 629 'host' => '', 630 'port' => null, 631 'path' => '/', 632 ) 633 ); 634 635 $qv = array( 636 'domain' => $url_parts['host'] . ( $url_parts['port'] ? ':' . $url_parts['port'] : '' ), 637 'path' => '/', 638 'update_site_meta_cache' => false, 639 ); 640 641 // In case of subdirectory configs, set the path. 642 if ( ! is_subdomain_install() ) { 643 $path = explode( '/', ltrim( $url_parts['path'], '/' ) ); 644 $path = reset( $path ); 645 646 if ( $path ) { 647 $qv['path'] = get_network()->path . $path . '/'; 648 } 649 } 650 651 $sites = get_sites( $qv ); 652 $site = reset( $sites ); 653 654 // Do not allow embeds for deleted/archived/spam sites. 655 if ( ! empty( $site->deleted ) || ! empty( $site->spam ) || ! empty( $site->archived ) ) { 656 return false; 657 } 658 659 if ( $site && get_current_blog_id() !== (int) $site->blog_id ) { 660 switch_to_blog( $site->blog_id ); 661 $switched_blog = true; 662 } 663 } 664 665 $post_id = url_to_postid( $url ); 666 667 /** This filter is documented in wp-includes/class-wp-oembed-controller.php */ 668 $post_id = apply_filters( 'oembed_request_post_id', $post_id, $url ); 669 670 if ( ! $post_id ) { 671 if ( $switched_blog ) { 672 restore_current_blog(); 673 } 674 675 return false; 676 } 677 678 $width = isset( $args['width'] ) ? $args['width'] : 0; 679 680 $data = get_oembed_response_data( $post_id, $width ); 681 682 if ( $switched_blog ) { 683 restore_current_blog(); 684 } 685 686 return $data ? (object) $data : false; 687 } 688 689 690 /** 691 * Filters the oEmbed response data to return an iframe embed code. 692 * 693 * @since 4.4.0 694 * 695 * @param array $data The response data. 696 * @param WP_Post $post The post object. 697 * @param int $width The requested width. 698 * @param int $height The calculated height. 699 * @return array The modified response data. 700 */ 701 function get_oembed_response_data_rich( $data, $post, $width, $height ) { 702 $data['width'] = absint( $width ); 703 $data['height'] = absint( $height ); 704 $data['type'] = 'rich'; 705 $data['html'] = get_post_embed_html( $width, $height, $post ); 706 707 // Add post thumbnail to response if available. 708 $thumbnail_id = false; 709 710 if ( has_post_thumbnail( $post->ID ) ) { 711 $thumbnail_id = get_post_thumbnail_id( $post->ID ); 712 } 713 714 if ( 'attachment' === get_post_type( $post ) ) { 715 if ( wp_attachment_is_image( $post ) ) { 716 $thumbnail_id = $post->ID; 717 } elseif ( wp_attachment_is( 'video', $post ) ) { 718 $thumbnail_id = get_post_thumbnail_id( $post ); 719 $data['type'] = 'video'; 720 } 721 } 722 723 if ( $thumbnail_id ) { 724 list( $thumbnail_url, $thumbnail_width, $thumbnail_height ) = wp_get_attachment_image_src( $thumbnail_id, array( $width, 99999 ) ); 725 $data['thumbnail_url'] = $thumbnail_url; 726 $data['thumbnail_width'] = $thumbnail_width; 727 $data['thumbnail_height'] = $thumbnail_height; 728 } 729 730 return $data; 731 } 732 733 /** 734 * Ensures that the specified format is either 'json' or 'xml'. 735 * 736 * @since 4.4.0 737 * 738 * @param string $format The oEmbed response format. Accepts 'json' or 'xml'. 739 * @return string The format, either 'xml' or 'json'. Default 'json'. 740 */ 741 function wp_oembed_ensure_format( $format ) { 742 if ( ! in_array( $format, array( 'json', 'xml' ), true ) ) { 743 return 'json'; 744 } 745 746 return $format; 747 } 748 749 /** 750 * Hooks into the REST API output to print XML instead of JSON. 751 * 752 * This is only done for the oEmbed API endpoint, 753 * which supports both formats. 754 * 755 * @access private 756 * @since 4.4.0 757 * 758 * @param bool $served Whether the request has already been served. 759 * @param WP_HTTP_Response $result Result to send to the client. Usually a `WP_REST_Response`. 760 * @param WP_REST_Request $request Request used to generate the response. 761 * @param WP_REST_Server $server Server instance. 762 * @return true 763 */ 764 function _oembed_rest_pre_serve_request( $served, $result, $request, $server ) { 765 $params = $request->get_params(); 766 767 if ( '/oembed/1.0/embed' !== $request->get_route() || 'GET' !== $request->get_method() ) { 768 return $served; 769 } 770 771 if ( ! isset( $params['format'] ) || 'xml' !== $params['format'] ) { 772 return $served; 773 } 774 775 // Embed links inside the request. 776 $data = $server->response_to_data( $result, false ); 777 778 if ( ! class_exists( 'SimpleXMLElement' ) ) { 779 status_header( 501 ); 780 die( get_status_header_desc( 501 ) ); 781 } 782 783 $result = _oembed_create_xml( $data ); 784 785 // Bail if there's no XML. 786 if ( ! $result ) { 787 status_header( 501 ); 788 return get_status_header_desc( 501 ); 789 } 790 791 if ( ! headers_sent() ) { 792 $server->send_header( 'Content-Type', 'text/xml; charset=' . get_option( 'blog_charset' ) ); 793 } 794 795 echo $result; 796 797 return true; 798 } 799 800 /** 801 * Creates an XML string from a given array. 802 * 803 * @since 4.4.0 804 * @access private 805 * 806 * @param array $data The original oEmbed response data. 807 * @param SimpleXMLElement $node Optional. XML node to append the result to recursively. 808 * @return string|false XML string on success, false on error. 809 */ 810 function _oembed_create_xml( $data, $node = null ) { 811 if ( ! is_array( $data ) || empty( $data ) ) { 812 return false; 813 } 814 815 if ( null === $node ) { 816 $node = new SimpleXMLElement( '<oembed></oembed>' ); 817 } 818 819 foreach ( $data as $key => $value ) { 820 if ( is_numeric( $key ) ) { 821 $key = 'oembed'; 822 } 823 824 if ( is_array( $value ) ) { 825 $item = $node->addChild( $key ); 826 _oembed_create_xml( $value, $item ); 827 } else { 828 $node->addChild( $key, esc_html( $value ) ); 829 } 830 } 831 832 return $node->asXML(); 833 } 834 835 /** 836 * Filters the given oEmbed HTML to make sure iframes have a title attribute. 837 * 838 * @since 5.2.0 839 * 840 * @param string $result The oEmbed HTML result. 841 * @param object $data A data object result from an oEmbed provider. 842 * @param string $url The URL of the content to be embedded. 843 * @return string The filtered oEmbed result. 844 */ 845 function wp_filter_oembed_iframe_title_attribute( $result, $data, $url ) { 846 if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) { 847 return $result; 848 } 849 850 $title = ! empty( $data->title ) ? $data->title : ''; 851 852 $pattern = '`<iframe([^>]*)>`i'; 853 if ( preg_match( $pattern, $result, $matches ) ) { 854 $attrs = wp_kses_hair( $matches[1], wp_allowed_protocols() ); 855 856 foreach ( $attrs as $attr => $item ) { 857 $lower_attr = strtolower( $attr ); 858 if ( $lower_attr === $attr ) { 859 continue; 860 } 861 if ( ! isset( $attrs[ $lower_attr ] ) ) { 862 $attrs[ $lower_attr ] = $item; 863 unset( $attrs[ $attr ] ); 864 } 865 } 866 } 867 868 if ( ! empty( $attrs['title']['value'] ) ) { 869 $title = $attrs['title']['value']; 870 } 871 872 /** 873 * Filters the title attribute of the given oEmbed HTML iframe. 874 * 875 * @since 5.2.0 876 * 877 * @param string $title The title attribute. 878 * @param string $result The oEmbed HTML result. 879 * @param object $data A data object result from an oEmbed provider. 880 * @param string $url The URL of the content to be embedded. 881 */ 882 $title = apply_filters( 'oembed_iframe_title_attribute', $title, $result, $data, $url ); 883 884 if ( '' === $title ) { 885 return $result; 886 } 887 888 if ( isset( $attrs['title'] ) ) { 889 unset( $attrs['title'] ); 890 $attr_string = implode( ' ', wp_list_pluck( $attrs, 'whole' ) ); 891 $result = str_replace( $matches[0], '<iframe ' . trim( $attr_string ) . '>', $result ); 892 } 893 return str_ireplace( '<iframe ', sprintf( '<iframe title="%s" ', esc_attr( $title ) ), $result ); 894 } 895 896 897 /** 898 * Filters the given oEmbed HTML. 899 * 900 * If the `$url` isn't on the trusted providers list, 901 * we need to filter the HTML heavily for security. 902 * 903 * Only filters 'rich' and 'video' response types. 904 * 905 * @since 4.4.0 906 * 907 * @param string $result The oEmbed HTML result. 908 * @param object $data A data object result from an oEmbed provider. 909 * @param string $url The URL of the content to be embedded. 910 * @return string The filtered and sanitized oEmbed result. 911 */ 912 function wp_filter_oembed_result( $result, $data, $url ) { 913 if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) { 914 return $result; 915 } 916 917 $wp_oembed = _wp_oembed_get_object(); 918 919 // Don't modify the HTML for trusted providers. 920 if ( false !== $wp_oembed->get_provider( $url, array( 'discover' => false ) ) ) { 921 return $result; 922 } 923 924 $allowed_html = array( 925 'a' => array( 926 'href' => true, 927 ), 928 'blockquote' => array(), 929 'iframe' => array( 930 'src' => true, 931 'width' => true, 932 'height' => true, 933 'frameborder' => true, 934 'marginwidth' => true, 935 'marginheight' => true, 936 'scrolling' => true, 937 'title' => true, 938 ), 939 ); 940 941 $html = wp_kses( $result, $allowed_html ); 942 943 preg_match( '|(<blockquote>.*?</blockquote>)?.*(<iframe.*?></iframe>)|ms', $html, $content ); 944 // We require at least the iframe to exist. 945 if ( empty( $content[2] ) ) { 946 return false; 947 } 948 $html = $content[1] . $content[2]; 949 950 preg_match( '/ src=([\'"])(.*?)\1/', $html, $results ); 951 952 if ( ! empty( $results ) ) { 953 $secret = wp_generate_password( 10, false ); 954 955 $url = esc_url( "{$results[2]}#?secret=$secret" ); 956 $q = $results[1]; 957 958 $html = str_replace( $results[0], ' src=' . $q . $url . $q . ' data-secret=' . $q . $secret . $q, $html ); 959 $html = str_replace( '<blockquote', "<blockquote data-secret=\"$secret\"", $html ); 960 } 961 962 $allowed_html['blockquote']['data-secret'] = true; 963 $allowed_html['iframe']['data-secret'] = true; 964 965 $html = wp_kses( $html, $allowed_html ); 966 967 if ( ! empty( $content[1] ) ) { 968 // We have a blockquote to fall back on. Hide the iframe by default. 969 $html = str_replace( '<iframe', '<iframe style="position: absolute; visibility: hidden;"', $html ); 970 $html = str_replace( '<blockquote', '<blockquote class="wp-embedded-content"', $html ); 971 } 972 973 $html = str_ireplace( '<iframe', '<iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"', $html ); 974 975 return $html; 976 } 977 978 /** 979 * Filters the string in the 'more' link displayed after a trimmed excerpt. 980 * 981 * Replaces '[...]' (appended to automatically generated excerpts) with an 982 * ellipsis and a "Continue reading" link in the embed template. 983 * 984 * @since 4.4.0 985 * 986 * @param string $more_string Default 'more' string. 987 * @return string 'Continue reading' link prepended with an ellipsis. 988 */ 989 function wp_embed_excerpt_more( $more_string ) { 990 if ( ! is_embed() ) { 991 return $more_string; 992 } 993 994 $link = sprintf( 995 '<a href="%1$s" class="wp-embed-more" target="_top">%2$s</a>', 996 esc_url( get_permalink() ), 997 /* translators: %s: Post title. */ 998 sprintf( __( 'Continue reading %s' ), '<span class="screen-reader-text">' . get_the_title() . '</span>' ) 999 ); 1000 return ' … ' . $link; 1001 } 1002 1003 /** 1004 * Displays the post excerpt for the embed template. 1005 * 1006 * Intended to be used in 'The Loop'. 1007 * 1008 * @since 4.4.0 1009 */ 1010 function the_excerpt_embed() { 1011 $output = get_the_excerpt(); 1012 1013 /** 1014 * Filters the post excerpt for the embed template. 1015 * 1016 * @since 4.4.0 1017 * 1018 * @param string $output The current post excerpt. 1019 */ 1020 echo apply_filters( 'the_excerpt_embed', $output ); 1021 } 1022 1023 /** 1024 * Filters the post excerpt for the embed template. 1025 * 1026 * Shows players for video and audio attachments. 1027 * 1028 * @since 4.4.0 1029 * 1030 * @param string $content The current post excerpt. 1031 * @return string The modified post excerpt. 1032 */ 1033 function wp_embed_excerpt_attachment( $content ) { 1034 if ( is_attachment() ) { 1035 return prepend_attachment( '' ); 1036 } 1037 1038 return $content; 1039 } 1040 1041 /** 1042 * Enqueues embed iframe default CSS and JS. 1043 * 1044 * Enqueue PNG fallback CSS for embed iframe for legacy versions of IE. 1045 * 1046 * Allows plugins to queue scripts for the embed iframe end using wp_enqueue_script(). 1047 * Runs first in oembed_head(). 1048 * 1049 * @since 4.4.0 1050 */ 1051 function enqueue_embed_scripts() { 1052 wp_enqueue_style( 'wp-embed-template-ie' ); 1053 1054 /** 1055 * Fires when scripts and styles are enqueued for the embed iframe. 1056 * 1057 * @since 4.4.0 1058 */ 1059 do_action( 'enqueue_embed_scripts' ); 1060 } 1061 1062 /** 1063 * Enqueues the CSS in the embed iframe header. 1064 * 1065 * @since 6.4.0 1066 */ 1067 function wp_enqueue_embed_styles() { 1068 // Back-compat for plugins that disable functionality by unhooking this action. 1069 if ( ! has_action( 'embed_head', 'print_embed_styles' ) ) { 1070 return; 1071 } 1072 remove_action( 'embed_head', 'print_embed_styles' ); 1073 1074 $suffix = wp_scripts_get_suffix(); 1075 $handle = 'wp-embed-template'; 1076 wp_register_style( $handle, false ); 1077 wp_add_inline_style( $handle, file_get_contents( ABSPATH . WPINC . "/css/wp-embed-template$suffix.css" ) ); 1078 wp_enqueue_style( $handle ); 1079 } 1080 1081 /** 1082 * Prints the JavaScript in the embed iframe header. 1083 * 1084 * @since 4.4.0 1085 */ 1086 function print_embed_scripts() { 1087 wp_print_inline_script_tag( 1088 file_get_contents( ABSPATH . WPINC . '/js/wp-embed-template' . wp_scripts_get_suffix() . '.js' ) 1089 ); 1090 } 1091 1092 /** 1093 * Prepare the oembed HTML to be displayed in an RSS feed. 1094 * 1095 * @since 4.4.0 1096 * @access private 1097 * 1098 * @param string $content The content to filter. 1099 * @return string The filtered content. 1100 */ 1101 function _oembed_filter_feed_content( $content ) { 1102 $p = new WP_HTML_Tag_Processor( $content ); 1103 while ( $p->next_tag( array( 'tag_name' => 'iframe' ) ) ) { 1104 if ( $p->has_class( 'wp-embedded-content' ) ) { 1105 $p->remove_attribute( 'style' ); 1106 } 1107 } 1108 return $p->get_updated_html(); 1109 } 1110 1111 /** 1112 * Prints the necessary markup for the embed comments button. 1113 * 1114 * @since 4.4.0 1115 */ 1116 function print_embed_comments_button() { 1117 if ( is_404() || ! ( get_comments_number() || comments_open() ) ) { 1118 return; 1119 } 1120 ?> 1121 <div class="wp-embed-comments"> 1122 <a href="<?php comments_link(); ?>" target="_top"> 1123 <span class="dashicons dashicons-admin-comments"></span> 1124 <?php 1125 printf( 1126 /* translators: %s: Number of comments. */ 1127 _n( 1128 '%s <span class="screen-reader-text">Comment</span>', 1129 '%s <span class="screen-reader-text">Comments</span>', 1130 get_comments_number() 1131 ), 1132 number_format_i18n( get_comments_number() ) 1133 ); 1134 ?> 1135 </a> 1136 </div> 1137 <?php 1138 } 1139 1140 /** 1141 * Prints the necessary markup for the embed sharing button. 1142 * 1143 * @since 4.4.0 1144 */ 1145 function print_embed_sharing_button() { 1146 if ( is_404() ) { 1147 return; 1148 } 1149 ?> 1150 <div class="wp-embed-share"> 1151 <button type="button" class="wp-embed-share-dialog-open" aria-label="<?php esc_attr_e( 'Open sharing dialog' ); ?>"> 1152 <span class="dashicons dashicons-share"></span> 1153 </button> 1154 </div> 1155 <?php 1156 } 1157 1158 /** 1159 * Prints the necessary markup for the embed sharing dialog. 1160 * 1161 * @since 4.4.0 1162 */ 1163 function print_embed_sharing_dialog() { 1164 if ( is_404() ) { 1165 return; 1166 } 1167 1168 $unique_suffix = get_the_ID() . '-' . wp_rand(); 1169 $share_tab_wordpress_id = 'wp-embed-share-tab-wordpress-' . $unique_suffix; 1170 $share_tab_html_id = 'wp-embed-share-tab-html-' . $unique_suffix; 1171 $description_wordpress_id = 'wp-embed-share-description-wordpress-' . $unique_suffix; 1172 $description_html_id = 'wp-embed-share-description-html-' . $unique_suffix; 1173 ?> 1174 <div class="wp-embed-share-dialog hidden" role="dialog" aria-label="<?php esc_attr_e( 'Sharing options' ); ?>"> 1175 <div class="wp-embed-share-dialog-content"> 1176 <div class="wp-embed-share-dialog-text"> 1177 <ul class="wp-embed-share-tabs" role="tablist"> 1178 <li class="wp-embed-share-tab-button wp-embed-share-tab-button-wordpress" role="presentation"> 1179 <button type="button" role="tab" aria-controls="<?php echo $share_tab_wordpress_id; ?>" aria-selected="true" tabindex="0"><?php esc_html_e( 'WordPress Embed' ); ?></button> 1180 </li> 1181 <li class="wp-embed-share-tab-button wp-embed-share-tab-button-html" role="presentation"> 1182 <button type="button" role="tab" aria-controls="<?php echo $share_tab_html_id; ?>" aria-selected="false" tabindex="-1"><?php esc_html_e( 'HTML Embed' ); ?></button> 1183 </li> 1184 </ul> 1185 <div id="<?php echo $share_tab_wordpress_id; ?>" class="wp-embed-share-tab" role="tabpanel" aria-hidden="false"> 1186 <input type="text" value="<?php the_permalink(); ?>" class="wp-embed-share-input" aria-label="<?php esc_attr_e( 'URL' ); ?>" aria-describedby="<?php echo $description_wordpress_id; ?>" tabindex="0" readonly/> 1187 1188 <p class="wp-embed-share-description" id="<?php echo $description_wordpress_id; ?>"> 1189 <?php _e( 'Copy and paste this URL into your WordPress site to embed' ); ?> 1190 </p> 1191 </div> 1192 <div id="<?php echo $share_tab_html_id; ?>" class="wp-embed-share-tab" role="tabpanel" aria-hidden="true"> 1193 <textarea class="wp-embed-share-input" aria-label="<?php esc_attr_e( 'HTML' ); ?>" aria-describedby="<?php echo $description_html_id; ?>" tabindex="0" readonly><?php echo esc_textarea( get_post_embed_html( 600, 400 ) ); ?></textarea> 1194 1195 <p class="wp-embed-share-description" id="<?php echo $description_html_id; ?>"> 1196 <?php _e( 'Copy and paste this code into your site to embed' ); ?> 1197 </p> 1198 </div> 1199 </div> 1200 1201 <button type="button" class="wp-embed-share-dialog-close" aria-label="<?php esc_attr_e( 'Close sharing dialog' ); ?>"> 1202 <span class="dashicons dashicons-no"></span> 1203 </button> 1204 </div> 1205 </div> 1206 <?php 1207 } 1208 1209 /** 1210 * Prints the necessary markup for the site title in an embed template. 1211 * 1212 * @since 4.5.0 1213 */ 1214 function the_embed_site_title() { 1215 $site_title = sprintf( 1216 '<a href="%s" target="_top"><img src="%s" srcset="%s 2x" width="32" height="32" alt="" class="wp-embed-site-icon" /><span>%s</span></a>', 1217 esc_url( home_url() ), 1218 esc_url( get_site_icon_url( 32, includes_url( 'images/w-logo-blue.png' ) ) ), 1219 esc_url( get_site_icon_url( 64, includes_url( 'images/w-logo-blue.png' ) ) ), 1220 esc_html( get_bloginfo( 'name' ) ) 1221 ); 1222 1223 $site_title = '<div class="wp-embed-site-title">' . $site_title . '</div>'; 1224 1225 /** 1226 * Filters the site title HTML in the embed footer. 1227 * 1228 * @since 4.4.0 1229 * 1230 * @param string $site_title The site title HTML. 1231 */ 1232 echo apply_filters( 'embed_site_title_html', $site_title ); 1233 } 1234 1235 /** 1236 * Filters the oEmbed result before any HTTP requests are made. 1237 * 1238 * If the URL belongs to the current site, the result is fetched directly instead of 1239 * going through the oEmbed discovery process. 1240 * 1241 * @since 4.5.3 1242 * 1243 * @param null|string $result The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. Default null. 1244 * @param string $url The URL that should be inspected for discovery `<link>` tags. 1245 * @param array $args oEmbed remote get arguments. 1246 * @return null|string The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. 1247 * Null if the URL does not belong to the current site. 1248 */ 1249 function wp_filter_pre_oembed_result( $result, $url, $args ) { 1250 $data = get_oembed_response_data_for_url( $url, $args ); 1251 1252 if ( $data ) { 1253 return _wp_oembed_get_object()->data2html( $data, $url ); 1254 } 1255 1256 return $result; 1257 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu Nov 21 08:20:01 2024 | Cross-referenced by PHPXref |