[ Index ] |
PHP Cross Reference of WordPress |
[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 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 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( 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 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 YoutTube 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" 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" 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 esc_url_raw( 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 // Note that the script must be placed after the <blockquote> and <iframe> due to a regexp parsing issue in 514 // `wp_filter_oembed_result()`. Because of the regex pattern starts with `|(<blockquote>.*?</blockquote>)?.*|` 515 // wherein the <blockquote> is marked as being optional, if it is not at the beginning of the string then the group 516 // will fail to match and everything will be matched by `.*` and not included in the group. This regex issue goes 517 // back to WordPress 4.4, so in order to not break older installs this script must come at the end. 518 $output .= wp_get_inline_script_tag( 519 file_get_contents( ABSPATH . WPINC . '/js/wp-embed' . wp_scripts_get_suffix() . '.js' ) 520 ); 521 522 /** 523 * Filters the embed HTML output for a given post. 524 * 525 * @since 4.4.0 526 * 527 * @param string $output The default iframe tag to display embedded content. 528 * @param WP_Post $post Current post object. 529 * @param int $width Width of the response. 530 * @param int $height Height of the response. 531 */ 532 return apply_filters( 'embed_html', $output, $post, $width, $height ); 533 } 534 535 /** 536 * Retrieves the oEmbed response data for a given post. 537 * 538 * @since 4.4.0 539 * 540 * @param WP_Post|int $post Post object or ID. 541 * @param int $width The requested width. 542 * @return array|false Response data on success, false if post doesn't exist 543 * or is not publicly viewable. 544 */ 545 function get_oembed_response_data( $post, $width ) { 546 $post = get_post( $post ); 547 $width = absint( $width ); 548 549 if ( ! $post ) { 550 return false; 551 } 552 553 if ( ! is_post_publicly_viewable( $post ) ) { 554 return false; 555 } 556 557 /** 558 * Filters the allowed minimum and maximum widths for the oEmbed response. 559 * 560 * @since 4.4.0 561 * 562 * @param array $min_max_width { 563 * Minimum and maximum widths for the oEmbed response. 564 * 565 * @type int $min Minimum width. Default 200. 566 * @type int $max Maximum width. Default 600. 567 * } 568 */ 569 $min_max_width = apply_filters( 570 'oembed_min_max_width', 571 array( 572 'min' => 200, 573 'max' => 600, 574 ) 575 ); 576 577 $width = min( max( $min_max_width['min'], $width ), $min_max_width['max'] ); 578 $height = max( ceil( $width / 16 * 9 ), 200 ); 579 580 $data = array( 581 'version' => '1.0', 582 'provider_name' => get_bloginfo( 'name' ), 583 'provider_url' => get_home_url(), 584 'author_name' => get_bloginfo( 'name' ), 585 'author_url' => get_home_url(), 586 'title' => get_the_title( $post ), 587 'type' => 'link', 588 ); 589 590 $author = get_userdata( $post->post_author ); 591 592 if ( $author ) { 593 $data['author_name'] = $author->display_name; 594 $data['author_url'] = get_author_posts_url( $author->ID ); 595 } 596 597 /** 598 * Filters the oEmbed response data. 599 * 600 * @since 4.4.0 601 * 602 * @param array $data The response data. 603 * @param WP_Post $post The post object. 604 * @param int $width The requested width. 605 * @param int $height The calculated height. 606 */ 607 return apply_filters( 'oembed_response_data', $data, $post, $width, $height ); 608 } 609 610 611 /** 612 * Retrieves the oEmbed response data for a given URL. 613 * 614 * @since 5.0.0 615 * 616 * @param string $url The URL that should be inspected for discovery `<link>` tags. 617 * @param array $args oEmbed remote get arguments. 618 * @return object|false oEmbed response data if the URL does belong to the current site. False otherwise. 619 */ 620 function get_oembed_response_data_for_url( $url, $args ) { 621 $switched_blog = false; 622 623 if ( is_multisite() ) { 624 $url_parts = wp_parse_args( 625 wp_parse_url( $url ), 626 array( 627 'host' => '', 628 'path' => '/', 629 ) 630 ); 631 632 $qv = array( 633 'domain' => $url_parts['host'], 634 'path' => '/', 635 'update_site_meta_cache' => false, 636 ); 637 638 // In case of subdirectory configs, set the path. 639 if ( ! is_subdomain_install() ) { 640 $path = explode( '/', ltrim( $url_parts['path'], '/' ) ); 641 $path = reset( $path ); 642 643 if ( $path ) { 644 $qv['path'] = get_network()->path . $path . '/'; 645 } 646 } 647 648 $sites = get_sites( $qv ); 649 $site = reset( $sites ); 650 651 // Do not allow embeds for deleted/archived/spam sites. 652 if ( ! empty( $site->deleted ) || ! empty( $site->spam ) || ! empty( $site->archived ) ) { 653 return false; 654 } 655 656 if ( $site && get_current_blog_id() !== (int) $site->blog_id ) { 657 switch_to_blog( $site->blog_id ); 658 $switched_blog = true; 659 } 660 } 661 662 $post_id = url_to_postid( $url ); 663 664 /** This filter is documented in wp-includes/class-wp-oembed-controller.php */ 665 $post_id = apply_filters( 'oembed_request_post_id', $post_id, $url ); 666 667 if ( ! $post_id ) { 668 if ( $switched_blog ) { 669 restore_current_blog(); 670 } 671 672 return false; 673 } 674 675 $width = isset( $args['width'] ) ? $args['width'] : 0; 676 677 $data = get_oembed_response_data( $post_id, $width ); 678 679 if ( $switched_blog ) { 680 restore_current_blog(); 681 } 682 683 return $data ? (object) $data : false; 684 } 685 686 687 /** 688 * Filters the oEmbed response data to return an iframe embed code. 689 * 690 * @since 4.4.0 691 * 692 * @param array $data The response data. 693 * @param WP_Post $post The post object. 694 * @param int $width The requested width. 695 * @param int $height The calculated height. 696 * @return array The modified response data. 697 */ 698 function get_oembed_response_data_rich( $data, $post, $width, $height ) { 699 $data['width'] = absint( $width ); 700 $data['height'] = absint( $height ); 701 $data['type'] = 'rich'; 702 $data['html'] = get_post_embed_html( $width, $height, $post ); 703 704 // Add post thumbnail to response if available. 705 $thumbnail_id = false; 706 707 if ( has_post_thumbnail( $post->ID ) ) { 708 $thumbnail_id = get_post_thumbnail_id( $post->ID ); 709 } 710 711 if ( 'attachment' === get_post_type( $post ) ) { 712 if ( wp_attachment_is_image( $post ) ) { 713 $thumbnail_id = $post->ID; 714 } elseif ( wp_attachment_is( 'video', $post ) ) { 715 $thumbnail_id = get_post_thumbnail_id( $post ); 716 $data['type'] = 'video'; 717 } 718 } 719 720 if ( $thumbnail_id ) { 721 list( $thumbnail_url, $thumbnail_width, $thumbnail_height ) = wp_get_attachment_image_src( $thumbnail_id, array( $width, 99999 ) ); 722 $data['thumbnail_url'] = $thumbnail_url; 723 $data['thumbnail_width'] = $thumbnail_width; 724 $data['thumbnail_height'] = $thumbnail_height; 725 } 726 727 return $data; 728 } 729 730 /** 731 * Ensures that the specified format is either 'json' or 'xml'. 732 * 733 * @since 4.4.0 734 * 735 * @param string $format The oEmbed response format. Accepts 'json' or 'xml'. 736 * @return string The format, either 'xml' or 'json'. Default 'json'. 737 */ 738 function wp_oembed_ensure_format( $format ) { 739 if ( ! in_array( $format, array( 'json', 'xml' ), true ) ) { 740 return 'json'; 741 } 742 743 return $format; 744 } 745 746 /** 747 * Hooks into the REST API output to print XML instead of JSON. 748 * 749 * This is only done for the oEmbed API endpoint, 750 * which supports both formats. 751 * 752 * @access private 753 * @since 4.4.0 754 * 755 * @param bool $served Whether the request has already been served. 756 * @param WP_HTTP_Response $result Result to send to the client. Usually a `WP_REST_Response`. 757 * @param WP_REST_Request $request Request used to generate the response. 758 * @param WP_REST_Server $server Server instance. 759 * @return true 760 */ 761 function _oembed_rest_pre_serve_request( $served, $result, $request, $server ) { 762 $params = $request->get_params(); 763 764 if ( '/oembed/1.0/embed' !== $request->get_route() || 'GET' !== $request->get_method() ) { 765 return $served; 766 } 767 768 if ( ! isset( $params['format'] ) || 'xml' !== $params['format'] ) { 769 return $served; 770 } 771 772 // Embed links inside the request. 773 $data = $server->response_to_data( $result, false ); 774 775 if ( ! class_exists( 'SimpleXMLElement' ) ) { 776 status_header( 501 ); 777 die( get_status_header_desc( 501 ) ); 778 } 779 780 $result = _oembed_create_xml( $data ); 781 782 // Bail if there's no XML. 783 if ( ! $result ) { 784 status_header( 501 ); 785 return get_status_header_desc( 501 ); 786 } 787 788 if ( ! headers_sent() ) { 789 $server->send_header( 'Content-Type', 'text/xml; charset=' . get_option( 'blog_charset' ) ); 790 } 791 792 echo $result; 793 794 return true; 795 } 796 797 /** 798 * Creates an XML string from a given array. 799 * 800 * @since 4.4.0 801 * @access private 802 * 803 * @param array $data The original oEmbed response data. 804 * @param SimpleXMLElement $node Optional. XML node to append the result to recursively. 805 * @return string|false XML string on success, false on error. 806 */ 807 function _oembed_create_xml( $data, $node = null ) { 808 if ( ! is_array( $data ) || empty( $data ) ) { 809 return false; 810 } 811 812 if ( null === $node ) { 813 $node = new SimpleXMLElement( '<oembed></oembed>' ); 814 } 815 816 foreach ( $data as $key => $value ) { 817 if ( is_numeric( $key ) ) { 818 $key = 'oembed'; 819 } 820 821 if ( is_array( $value ) ) { 822 $item = $node->addChild( $key ); 823 _oembed_create_xml( $value, $item ); 824 } else { 825 $node->addChild( $key, esc_html( $value ) ); 826 } 827 } 828 829 return $node->asXML(); 830 } 831 832 /** 833 * Filters the given oEmbed HTML to make sure iframes have a title attribute. 834 * 835 * @since 5.2.0 836 * 837 * @param string $result The oEmbed HTML result. 838 * @param object $data A data object result from an oEmbed provider. 839 * @param string $url The URL of the content to be embedded. 840 * @return string The filtered oEmbed result. 841 */ 842 function wp_filter_oembed_iframe_title_attribute( $result, $data, $url ) { 843 if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) { 844 return $result; 845 } 846 847 $title = ! empty( $data->title ) ? $data->title : ''; 848 849 $pattern = '`<iframe([^>]*)>`i'; 850 if ( preg_match( $pattern, $result, $matches ) ) { 851 $attrs = wp_kses_hair( $matches[1], wp_allowed_protocols() ); 852 853 foreach ( $attrs as $attr => $item ) { 854 $lower_attr = strtolower( $attr ); 855 if ( $lower_attr === $attr ) { 856 continue; 857 } 858 if ( ! isset( $attrs[ $lower_attr ] ) ) { 859 $attrs[ $lower_attr ] = $item; 860 unset( $attrs[ $attr ] ); 861 } 862 } 863 } 864 865 if ( ! empty( $attrs['title']['value'] ) ) { 866 $title = $attrs['title']['value']; 867 } 868 869 /** 870 * Filters the title attribute of the given oEmbed HTML iframe. 871 * 872 * @since 5.2.0 873 * 874 * @param string $title The title attribute. 875 * @param string $result The oEmbed HTML result. 876 * @param object $data A data object result from an oEmbed provider. 877 * @param string $url The URL of the content to be embedded. 878 */ 879 $title = apply_filters( 'oembed_iframe_title_attribute', $title, $result, $data, $url ); 880 881 if ( '' === $title ) { 882 return $result; 883 } 884 885 if ( isset( $attrs['title'] ) ) { 886 unset( $attrs['title'] ); 887 $attr_string = implode( ' ', wp_list_pluck( $attrs, 'whole' ) ); 888 $result = str_replace( $matches[0], '<iframe ' . trim( $attr_string ) . '>', $result ); 889 } 890 return str_ireplace( '<iframe ', sprintf( '<iframe title="%s" ', esc_attr( $title ) ), $result ); 891 } 892 893 894 /** 895 * Filters the given oEmbed HTML. 896 * 897 * If the `$url` isn't on the trusted providers list, 898 * we need to filter the HTML heavily for security. 899 * 900 * Only filters 'rich' and 'video' response types. 901 * 902 * @since 4.4.0 903 * 904 * @param string $result The oEmbed HTML result. 905 * @param object $data A data object result from an oEmbed provider. 906 * @param string $url The URL of the content to be embedded. 907 * @return string The filtered and sanitized oEmbed result. 908 */ 909 function wp_filter_oembed_result( $result, $data, $url ) { 910 if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) { 911 return $result; 912 } 913 914 $wp_oembed = _wp_oembed_get_object(); 915 916 // Don't modify the HTML for trusted providers. 917 if ( false !== $wp_oembed->get_provider( $url, array( 'discover' => false ) ) ) { 918 return $result; 919 } 920 921 $allowed_html = array( 922 'a' => array( 923 'href' => true, 924 ), 925 'blockquote' => array(), 926 'iframe' => array( 927 'src' => true, 928 'width' => true, 929 'height' => true, 930 'frameborder' => true, 931 'marginwidth' => true, 932 'marginheight' => true, 933 'scrolling' => true, 934 'title' => true, 935 ), 936 ); 937 938 $html = wp_kses( $result, $allowed_html ); 939 940 preg_match( '|(<blockquote>.*?</blockquote>)?.*(<iframe.*?></iframe>)|ms', $html, $content ); 941 // We require at least the iframe to exist. 942 if ( empty( $content[2] ) ) { 943 return false; 944 } 945 $html = $content[1] . $content[2]; 946 947 preg_match( '/ src=([\'"])(.*?)\1/', $html, $results ); 948 949 if ( ! empty( $results ) ) { 950 $secret = wp_generate_password( 10, false ); 951 952 $url = esc_url( "{$results[2]}#?secret=$secret" ); 953 $q = $results[1]; 954 955 $html = str_replace( $results[0], ' src=' . $q . $url . $q . ' data-secret=' . $q . $secret . $q, $html ); 956 $html = str_replace( '<blockquote', "<blockquote data-secret=\"$secret\"", $html ); 957 } 958 959 $allowed_html['blockquote']['data-secret'] = true; 960 $allowed_html['iframe']['data-secret'] = true; 961 962 $html = wp_kses( $html, $allowed_html ); 963 964 if ( ! empty( $content[1] ) ) { 965 // We have a blockquote to fall back on. Hide the iframe by default. 966 $html = str_replace( '<iframe', '<iframe style="position: absolute; clip: rect(1px, 1px, 1px, 1px);"', $html ); 967 $html = str_replace( '<blockquote', '<blockquote class="wp-embedded-content"', $html ); 968 } 969 970 $html = str_ireplace( '<iframe', '<iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"', $html ); 971 972 return $html; 973 } 974 975 /** 976 * Filters the string in the 'more' link displayed after a trimmed excerpt. 977 * 978 * Replaces '[...]' (appended to automatically generated excerpts) with an 979 * ellipsis and a "Continue reading" link in the embed template. 980 * 981 * @since 4.4.0 982 * 983 * @param string $more_string Default 'more' string. 984 * @return string 'Continue reading' link prepended with an ellipsis. 985 */ 986 function wp_embed_excerpt_more( $more_string ) { 987 if ( ! is_embed() ) { 988 return $more_string; 989 } 990 991 $link = sprintf( 992 '<a href="%1$s" class="wp-embed-more" target="_top">%2$s</a>', 993 esc_url( get_permalink() ), 994 /* translators: %s: Post title. */ 995 sprintf( __( 'Continue reading %s' ), '<span class="screen-reader-text">' . get_the_title() . '</span>' ) 996 ); 997 return ' … ' . $link; 998 } 999 1000 /** 1001 * Displays the post excerpt for the embed template. 1002 * 1003 * Intended to be used in 'The Loop'. 1004 * 1005 * @since 4.4.0 1006 */ 1007 function the_excerpt_embed() { 1008 $output = get_the_excerpt(); 1009 1010 /** 1011 * Filters the post excerpt for the embed template. 1012 * 1013 * @since 4.4.0 1014 * 1015 * @param string $output The current post excerpt. 1016 */ 1017 echo apply_filters( 'the_excerpt_embed', $output ); 1018 } 1019 1020 /** 1021 * Filters the post excerpt for the embed template. 1022 * 1023 * Shows players for video and audio attachments. 1024 * 1025 * @since 4.4.0 1026 * 1027 * @param string $content The current post excerpt. 1028 * @return string The modified post excerpt. 1029 */ 1030 function wp_embed_excerpt_attachment( $content ) { 1031 if ( is_attachment() ) { 1032 return prepend_attachment( '' ); 1033 } 1034 1035 return $content; 1036 } 1037 1038 /** 1039 * Enqueues embed iframe default CSS and JS. 1040 * 1041 * Enqueue PNG fallback CSS for embed iframe for legacy versions of IE. 1042 * 1043 * Allows plugins to queue scripts for the embed iframe end using wp_enqueue_script(). 1044 * Runs first in oembed_head(). 1045 * 1046 * @since 4.4.0 1047 */ 1048 function enqueue_embed_scripts() { 1049 wp_enqueue_style( 'wp-embed-template-ie' ); 1050 1051 /** 1052 * Fires when scripts and styles are enqueued for the embed iframe. 1053 * 1054 * @since 4.4.0 1055 */ 1056 do_action( 'enqueue_embed_scripts' ); 1057 } 1058 1059 /** 1060 * Prints the CSS in the embed iframe header. 1061 * 1062 * @since 4.4.0 1063 */ 1064 function print_embed_styles() { 1065 $type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/css"'; 1066 $suffix = SCRIPT_DEBUG ? '' : '.min'; 1067 ?> 1068 <style<?php echo $type_attr; ?>> 1069 <?php echo file_get_contents( ABSPATH . WPINC . "/css/wp-embed-template$suffix.css" ); ?> 1070 </style> 1071 <?php 1072 } 1073 1074 /** 1075 * Prints the JavaScript in the embed iframe header. 1076 * 1077 * @since 4.4.0 1078 */ 1079 function print_embed_scripts() { 1080 wp_print_inline_script_tag( 1081 file_get_contents( ABSPATH . WPINC . '/js/wp-embed-template' . wp_scripts_get_suffix() . '.js' ) 1082 ); 1083 } 1084 1085 /** 1086 * Prepare the oembed HTML to be displayed in an RSS feed. 1087 * 1088 * @since 4.4.0 1089 * @access private 1090 * 1091 * @param string $content The content to filter. 1092 * @return string The filtered content. 1093 */ 1094 function _oembed_filter_feed_content( $content ) { 1095 return str_replace( '<iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; clip: rect(1px, 1px, 1px, 1px);"', '<iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"', $content ); 1096 } 1097 1098 /** 1099 * Prints the necessary markup for the embed comments button. 1100 * 1101 * @since 4.4.0 1102 */ 1103 function print_embed_comments_button() { 1104 if ( is_404() || ! ( get_comments_number() || comments_open() ) ) { 1105 return; 1106 } 1107 ?> 1108 <div class="wp-embed-comments"> 1109 <a href="<?php comments_link(); ?>" target="_top"> 1110 <span class="dashicons dashicons-admin-comments"></span> 1111 <?php 1112 printf( 1113 /* translators: %s: Number of comments. */ 1114 _n( 1115 '%s <span class="screen-reader-text">Comment</span>', 1116 '%s <span class="screen-reader-text">Comments</span>', 1117 get_comments_number() 1118 ), 1119 number_format_i18n( get_comments_number() ) 1120 ); 1121 ?> 1122 </a> 1123 </div> 1124 <?php 1125 } 1126 1127 /** 1128 * Prints the necessary markup for the embed sharing button. 1129 * 1130 * @since 4.4.0 1131 */ 1132 function print_embed_sharing_button() { 1133 if ( is_404() ) { 1134 return; 1135 } 1136 ?> 1137 <div class="wp-embed-share"> 1138 <button type="button" class="wp-embed-share-dialog-open" aria-label="<?php esc_attr_e( 'Open sharing dialog' ); ?>"> 1139 <span class="dashicons dashicons-share"></span> 1140 </button> 1141 </div> 1142 <?php 1143 } 1144 1145 /** 1146 * Prints the necessary markup for the embed sharing dialog. 1147 * 1148 * @since 4.4.0 1149 */ 1150 function print_embed_sharing_dialog() { 1151 if ( is_404() ) { 1152 return; 1153 } 1154 ?> 1155 <div class="wp-embed-share-dialog hidden" role="dialog" aria-label="<?php esc_attr_e( 'Sharing options' ); ?>"> 1156 <div class="wp-embed-share-dialog-content"> 1157 <div class="wp-embed-share-dialog-text"> 1158 <ul class="wp-embed-share-tabs" role="tablist"> 1159 <li class="wp-embed-share-tab-button wp-embed-share-tab-button-wordpress" role="presentation"> 1160 <button type="button" role="tab" aria-controls="wp-embed-share-tab-wordpress" aria-selected="true" tabindex="0"><?php esc_html_e( 'WordPress Embed' ); ?></button> 1161 </li> 1162 <li class="wp-embed-share-tab-button wp-embed-share-tab-button-html" role="presentation"> 1163 <button type="button" role="tab" aria-controls="wp-embed-share-tab-html" aria-selected="false" tabindex="-1"><?php esc_html_e( 'HTML Embed' ); ?></button> 1164 </li> 1165 </ul> 1166 <div id="wp-embed-share-tab-wordpress" class="wp-embed-share-tab" role="tabpanel" aria-hidden="false"> 1167 <input type="text" value="<?php the_permalink(); ?>" class="wp-embed-share-input" aria-describedby="wp-embed-share-description-wordpress" tabindex="0" readonly/> 1168 1169 <p class="wp-embed-share-description" id="wp-embed-share-description-wordpress"> 1170 <?php _e( 'Copy and paste this URL into your WordPress site to embed' ); ?> 1171 </p> 1172 </div> 1173 <div id="wp-embed-share-tab-html" class="wp-embed-share-tab" role="tabpanel" aria-hidden="true"> 1174 <textarea class="wp-embed-share-input" aria-describedby="wp-embed-share-description-html" tabindex="0" readonly><?php echo esc_textarea( get_post_embed_html( 600, 400 ) ); ?></textarea> 1175 1176 <p class="wp-embed-share-description" id="wp-embed-share-description-html"> 1177 <?php _e( 'Copy and paste this code into your site to embed' ); ?> 1178 </p> 1179 </div> 1180 </div> 1181 1182 <button type="button" class="wp-embed-share-dialog-close" aria-label="<?php esc_attr_e( 'Close sharing dialog' ); ?>"> 1183 <span class="dashicons dashicons-no"></span> 1184 </button> 1185 </div> 1186 </div> 1187 <?php 1188 } 1189 1190 /** 1191 * Prints the necessary markup for the site title in an embed template. 1192 * 1193 * @since 4.5.0 1194 */ 1195 function the_embed_site_title() { 1196 $site_title = sprintf( 1197 '<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>', 1198 esc_url( home_url() ), 1199 esc_url( get_site_icon_url( 32, includes_url( 'images/w-logo-blue.png' ) ) ), 1200 esc_url( get_site_icon_url( 64, includes_url( 'images/w-logo-blue.png' ) ) ), 1201 esc_html( get_bloginfo( 'name' ) ) 1202 ); 1203 1204 $site_title = '<div class="wp-embed-site-title">' . $site_title . '</div>'; 1205 1206 /** 1207 * Filters the site title HTML in the embed footer. 1208 * 1209 * @since 4.4.0 1210 * 1211 * @param string $site_title The site title HTML. 1212 */ 1213 echo apply_filters( 'embed_site_title_html', $site_title ); 1214 } 1215 1216 /** 1217 * Filters the oEmbed result before any HTTP requests are made. 1218 * 1219 * If the URL belongs to the current site, the result is fetched directly instead of 1220 * going through the oEmbed discovery process. 1221 * 1222 * @since 4.5.3 1223 * 1224 * @param null|string $result The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. Default null. 1225 * @param string $url The URL that should be inspected for discovery `<link>` tags. 1226 * @param array $args oEmbed remote get arguments. 1227 * @return null|string The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. 1228 * Null if the URL does not belong to the current site. 1229 */ 1230 function wp_filter_pre_oembed_result( $result, $url, $args ) { 1231 $data = get_oembed_response_data_for_url( $url, $args ); 1232 1233 if ( $data ) { 1234 return _wp_oembed_get_object()->data2html( $data, $url ); 1235 } 1236 1237 return $result; 1238 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Dec 22 01:00:02 2024 | Cross-referenced by PHPXref 0.7.1 |