[ 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 array { 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 website <head>. 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 * @since 4.4.0 360 */ 361 function wp_oembed_add_host_js() { 362 wp_enqueue_script( 'wp-embed' ); 363 } 364 365 /** 366 * Retrieves the URL to embed a specific post in an iframe. 367 * 368 * @since 4.4.0 369 * 370 * @param int|WP_Post $post Optional. Post ID or object. Defaults to the current post. 371 * @return string|false The post embed URL on success, false if the post doesn't exist. 372 */ 373 function get_post_embed_url( $post = null ) { 374 $post = get_post( $post ); 375 376 if ( ! $post ) { 377 return false; 378 } 379 380 $embed_url = trailingslashit( get_permalink( $post ) ) . user_trailingslashit( 'embed' ); 381 $path_conflict = get_page_by_path( str_replace( home_url(), '', $embed_url ), OBJECT, get_post_types( array( 'public' => true ) ) ); 382 383 if ( ! get_option( 'permalink_structure' ) || $path_conflict ) { 384 $embed_url = add_query_arg( array( 'embed' => 'true' ), get_permalink( $post ) ); 385 } 386 387 /** 388 * Filters the URL to embed a specific post. 389 * 390 * @since 4.4.0 391 * 392 * @param string $embed_url The post embed URL. 393 * @param WP_Post $post The corresponding post object. 394 */ 395 return esc_url_raw( apply_filters( 'post_embed_url', $embed_url, $post ) ); 396 } 397 398 /** 399 * Retrieves the oEmbed endpoint URL for a given permalink. 400 * 401 * Pass an empty string as the first argument to get the endpoint base URL. 402 * 403 * @since 4.4.0 404 * 405 * @param string $permalink Optional. The permalink used for the `url` query arg. Default empty. 406 * @param string $format Optional. The requested response format. Default 'json'. 407 * @return string The oEmbed endpoint URL. 408 */ 409 function get_oembed_endpoint_url( $permalink = '', $format = 'json' ) { 410 $url = rest_url( 'oembed/1.0/embed' ); 411 412 if ( '' !== $permalink ) { 413 $url = add_query_arg( 414 array( 415 'url' => urlencode( $permalink ), 416 'format' => ( 'json' !== $format ) ? $format : false, 417 ), 418 $url 419 ); 420 } 421 422 /** 423 * Filters the oEmbed endpoint URL. 424 * 425 * @since 4.4.0 426 * 427 * @param string $url The URL to the oEmbed endpoint. 428 * @param string $permalink The permalink used for the `url` query arg. 429 * @param string $format The requested response format. 430 */ 431 return apply_filters( 'oembed_endpoint_url', $url, $permalink, $format ); 432 } 433 434 /** 435 * Retrieves the embed code for a specific post. 436 * 437 * @since 4.4.0 438 * 439 * @param int $width The width for the response. 440 * @param int $height The height for the response. 441 * @param int|WP_Post $post Optional. Post ID or object. Default is global `$post`. 442 * @return string|false Embed code on success, false if post doesn't exist. 443 */ 444 function get_post_embed_html( $width, $height, $post = null ) { 445 $post = get_post( $post ); 446 447 if ( ! $post ) { 448 return false; 449 } 450 451 $embed_url = get_post_embed_url( $post ); 452 453 $output = '<blockquote class="wp-embedded-content"><a href="' . esc_url( get_permalink( $post ) ) . '">' . get_the_title( $post ) . "</a></blockquote>\n"; 454 455 $output .= "<script type='text/javascript'>\n"; 456 $output .= "<!--//--><![CDATA[//><!--\n"; 457 if ( SCRIPT_DEBUG ) { 458 $output .= file_get_contents( ABSPATH . WPINC . '/js/wp-embed.js' ); 459 } else { 460 /* 461 * If you're looking at a src version of this file, you'll see an "include" 462 * statement below. This is used by the `npm run build` process to directly 463 * include a minified version of wp-embed.js, instead of using the 464 * file_get_contents() method from above. 465 * 466 * If you're looking at a build version of this file, you'll see a string of 467 * minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG 468 * and edit wp-embed.js directly. 469 */ 470 $output .= <<<JS 471 /*! This file is auto-generated */ 472 !function(c,d){"use strict";var e=!1,n=!1;if(d.querySelector)if(c.addEventListener)e=!0;if(c.wp=c.wp||{},!c.wp.receiveEmbedMessage)if(c.wp.receiveEmbedMessage=function(e){var t=e.data;if(t)if(t.secret||t.message||t.value)if(!/[^a-zA-Z0-9]/.test(t.secret)){for(var r,a,i,s=d.querySelectorAll('iframe[data-secret="'+t.secret+'"]'),n=d.querySelectorAll('blockquote[data-secret="'+t.secret+'"]'),o=0;o<n.length;o++)n[o].style.display="none";for(o=0;o<s.length;o++)if(r=s[o],e.source===r.contentWindow){if(r.removeAttribute("style"),"height"===t.message){if(1e3<(i=parseInt(t.value,10)))i=1e3;else if(~~i<200)i=200;r.height=i}if("link"===t.message)if(a=d.createElement("a"),i=d.createElement("a"),a.href=r.getAttribute("src"),i.href=t.value,i.host===a.host)if(d.activeElement===r)c.top.location.href=t.value}}},e)c.addEventListener("message",c.wp.receiveEmbedMessage,!1),d.addEventListener("DOMContentLoaded",t,!1),c.addEventListener("load",t,!1);function t(){if(!n){n=!0;for(var e,t,r=-1!==navigator.appVersion.indexOf("MSIE 10"),a=!!navigator.userAgent.match(/Trident.*rv:11\./),i=d.querySelectorAll("iframe.wp-embedded-content"),s=0;s<i.length;s++){if(!(e=i[s]).getAttribute("data-secret"))t=Math.random().toString(36).substr(2,10),e.src+="#?secret="+t,e.setAttribute("data-secret",t);if(r||a)(t=e.cloneNode(!0)).removeAttribute("security"),e.parentNode.replaceChild(t,e)}}}}(window,document); 473 JS; 474 } 475 $output .= "\n//--><!]]>"; 476 $output .= "\n</script>"; 477 478 $output .= sprintf( 479 '<iframe sandbox="allow-scripts" security="restricted" src="%1$s" width="%2$d" height="%3$d" title="%4$s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" class="wp-embedded-content"></iframe>', 480 esc_url( $embed_url ), 481 absint( $width ), 482 absint( $height ), 483 esc_attr( 484 sprintf( 485 /* translators: 1: Post title, 2: Site title. */ 486 __( '“%1$s” — %2$s' ), 487 get_the_title( $post ), 488 get_bloginfo( 'name' ) 489 ) 490 ) 491 ); 492 493 /** 494 * Filters the embed HTML output for a given post. 495 * 496 * @since 4.4.0 497 * 498 * @param string $output The default iframe tag to display embedded content. 499 * @param WP_Post $post Current post object. 500 * @param int $width Width of the response. 501 * @param int $height Height of the response. 502 */ 503 return apply_filters( 'embed_html', $output, $post, $width, $height ); 504 } 505 506 /** 507 * Retrieves the oEmbed response data for a given post. 508 * 509 * @since 4.4.0 510 * 511 * @param WP_Post|int $post Post object or ID. 512 * @param int $width The requested width. 513 * @return array|false Response data on success, false if post doesn't exist 514 * or is not publicly viewable. 515 */ 516 function get_oembed_response_data( $post, $width ) { 517 $post = get_post( $post ); 518 $width = absint( $width ); 519 520 if ( ! $post ) { 521 return false; 522 } 523 524 if ( ! is_post_publicly_viewable( $post ) ) { 525 return false; 526 } 527 528 /** 529 * Filters the allowed minimum and maximum widths for the oEmbed response. 530 * 531 * @since 4.4.0 532 * 533 * @param array $min_max_width { 534 * Minimum and maximum widths for the oEmbed response. 535 * 536 * @type int $min Minimum width. Default 200. 537 * @type int $max Maximum width. Default 600. 538 * } 539 */ 540 $min_max_width = apply_filters( 541 'oembed_min_max_width', 542 array( 543 'min' => 200, 544 'max' => 600, 545 ) 546 ); 547 548 $width = min( max( $min_max_width['min'], $width ), $min_max_width['max'] ); 549 $height = max( ceil( $width / 16 * 9 ), 200 ); 550 551 $data = array( 552 'version' => '1.0', 553 'provider_name' => get_bloginfo( 'name' ), 554 'provider_url' => get_home_url(), 555 'author_name' => get_bloginfo( 'name' ), 556 'author_url' => get_home_url(), 557 'title' => get_the_title( $post ), 558 'type' => 'link', 559 ); 560 561 $author = get_userdata( $post->post_author ); 562 563 if ( $author ) { 564 $data['author_name'] = $author->display_name; 565 $data['author_url'] = get_author_posts_url( $author->ID ); 566 } 567 568 /** 569 * Filters the oEmbed response data. 570 * 571 * @since 4.4.0 572 * 573 * @param array $data The response data. 574 * @param WP_Post $post The post object. 575 * @param int $width The requested width. 576 * @param int $height The calculated height. 577 */ 578 return apply_filters( 'oembed_response_data', $data, $post, $width, $height ); 579 } 580 581 582 /** 583 * Retrieves the oEmbed response data for a given URL. 584 * 585 * @since 5.0.0 586 * 587 * @param string $url The URL that should be inspected for discovery `<link>` tags. 588 * @param array $args oEmbed remote get arguments. 589 * @return object|false oEmbed response data if the URL does belong to the current site. False otherwise. 590 */ 591 function get_oembed_response_data_for_url( $url, $args ) { 592 $switched_blog = false; 593 594 if ( is_multisite() ) { 595 $url_parts = wp_parse_args( 596 wp_parse_url( $url ), 597 array( 598 'host' => '', 599 'path' => '/', 600 ) 601 ); 602 603 $qv = array( 604 'domain' => $url_parts['host'], 605 'path' => '/', 606 'update_site_meta_cache' => false, 607 ); 608 609 // In case of subdirectory configs, set the path. 610 if ( ! is_subdomain_install() ) { 611 $path = explode( '/', ltrim( $url_parts['path'], '/' ) ); 612 $path = reset( $path ); 613 614 if ( $path ) { 615 $qv['path'] = get_network()->path . $path . '/'; 616 } 617 } 618 619 $sites = get_sites( $qv ); 620 $site = reset( $sites ); 621 622 // Do not allow embeds for deleted/archived/spam sites. 623 if ( ! empty( $site->deleted ) || ! empty( $site->spam ) || ! empty( $site->archived ) ) { 624 return false; 625 } 626 627 if ( $site && get_current_blog_id() !== (int) $site->blog_id ) { 628 switch_to_blog( $site->blog_id ); 629 $switched_blog = true; 630 } 631 } 632 633 $post_id = url_to_postid( $url ); 634 635 /** This filter is documented in wp-includes/class-wp-oembed-controller.php */ 636 $post_id = apply_filters( 'oembed_request_post_id', $post_id, $url ); 637 638 if ( ! $post_id ) { 639 if ( $switched_blog ) { 640 restore_current_blog(); 641 } 642 643 return false; 644 } 645 646 $width = isset( $args['width'] ) ? $args['width'] : 0; 647 648 $data = get_oembed_response_data( $post_id, $width ); 649 650 if ( $switched_blog ) { 651 restore_current_blog(); 652 } 653 654 return $data ? (object) $data : false; 655 } 656 657 658 /** 659 * Filters the oEmbed response data to return an iframe embed code. 660 * 661 * @since 4.4.0 662 * 663 * @param array $data The response data. 664 * @param WP_Post $post The post object. 665 * @param int $width The requested width. 666 * @param int $height The calculated height. 667 * @return array The modified response data. 668 */ 669 function get_oembed_response_data_rich( $data, $post, $width, $height ) { 670 $data['width'] = absint( $width ); 671 $data['height'] = absint( $height ); 672 $data['type'] = 'rich'; 673 $data['html'] = get_post_embed_html( $width, $height, $post ); 674 675 // Add post thumbnail to response if available. 676 $thumbnail_id = false; 677 678 if ( has_post_thumbnail( $post->ID ) ) { 679 $thumbnail_id = get_post_thumbnail_id( $post->ID ); 680 } 681 682 if ( 'attachment' === get_post_type( $post ) ) { 683 if ( wp_attachment_is_image( $post ) ) { 684 $thumbnail_id = $post->ID; 685 } elseif ( wp_attachment_is( 'video', $post ) ) { 686 $thumbnail_id = get_post_thumbnail_id( $post ); 687 $data['type'] = 'video'; 688 } 689 } 690 691 if ( $thumbnail_id ) { 692 list( $thumbnail_url, $thumbnail_width, $thumbnail_height ) = wp_get_attachment_image_src( $thumbnail_id, array( $width, 99999 ) ); 693 $data['thumbnail_url'] = $thumbnail_url; 694 $data['thumbnail_width'] = $thumbnail_width; 695 $data['thumbnail_height'] = $thumbnail_height; 696 } 697 698 return $data; 699 } 700 701 /** 702 * Ensures that the specified format is either 'json' or 'xml'. 703 * 704 * @since 4.4.0 705 * 706 * @param string $format The oEmbed response format. Accepts 'json' or 'xml'. 707 * @return string The format, either 'xml' or 'json'. Default 'json'. 708 */ 709 function wp_oembed_ensure_format( $format ) { 710 if ( ! in_array( $format, array( 'json', 'xml' ), true ) ) { 711 return 'json'; 712 } 713 714 return $format; 715 } 716 717 /** 718 * Hooks into the REST API output to print XML instead of JSON. 719 * 720 * This is only done for the oEmbed API endpoint, 721 * which supports both formats. 722 * 723 * @access private 724 * @since 4.4.0 725 * 726 * @param bool $served Whether the request has already been served. 727 * @param WP_HTTP_ResponseInterface $result Result to send to the client. Usually a WP_REST_Response. 728 * @param WP_REST_Request $request Request used to generate the response. 729 * @param WP_REST_Server $server Server instance. 730 * @return true 731 */ 732 function _oembed_rest_pre_serve_request( $served, $result, $request, $server ) { 733 $params = $request->get_params(); 734 735 if ( '/oembed/1.0/embed' !== $request->get_route() || 'GET' !== $request->get_method() ) { 736 return $served; 737 } 738 739 if ( ! isset( $params['format'] ) || 'xml' !== $params['format'] ) { 740 return $served; 741 } 742 743 // Embed links inside the request. 744 $data = $server->response_to_data( $result, false ); 745 746 if ( ! class_exists( 'SimpleXMLElement' ) ) { 747 status_header( 501 ); 748 die( get_status_header_desc( 501 ) ); 749 } 750 751 $result = _oembed_create_xml( $data ); 752 753 // Bail if there's no XML. 754 if ( ! $result ) { 755 status_header( 501 ); 756 return get_status_header_desc( 501 ); 757 } 758 759 if ( ! headers_sent() ) { 760 $server->send_header( 'Content-Type', 'text/xml; charset=' . get_option( 'blog_charset' ) ); 761 } 762 763 echo $result; 764 765 return true; 766 } 767 768 /** 769 * Creates an XML string from a given array. 770 * 771 * @since 4.4.0 772 * @access private 773 * 774 * @param array $data The original oEmbed response data. 775 * @param SimpleXMLElement $node Optional. XML node to append the result to recursively. 776 * @return string|false XML string on success, false on error. 777 */ 778 function _oembed_create_xml( $data, $node = null ) { 779 if ( ! is_array( $data ) || empty( $data ) ) { 780 return false; 781 } 782 783 if ( null === $node ) { 784 $node = new SimpleXMLElement( '<oembed></oembed>' ); 785 } 786 787 foreach ( $data as $key => $value ) { 788 if ( is_numeric( $key ) ) { 789 $key = 'oembed'; 790 } 791 792 if ( is_array( $value ) ) { 793 $item = $node->addChild( $key ); 794 _oembed_create_xml( $value, $item ); 795 } else { 796 $node->addChild( $key, esc_html( $value ) ); 797 } 798 } 799 800 return $node->asXML(); 801 } 802 803 /** 804 * Filters the given oEmbed HTML to make sure iframes have a title attribute. 805 * 806 * @since 5.2.0 807 * 808 * @param string $result The oEmbed HTML result. 809 * @param object $data A data object result from an oEmbed provider. 810 * @param string $url The URL of the content to be embedded. 811 * @return string The filtered oEmbed result. 812 */ 813 function wp_filter_oembed_iframe_title_attribute( $result, $data, $url ) { 814 if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) { 815 return $result; 816 } 817 818 $title = ! empty( $data->title ) ? $data->title : ''; 819 820 $pattern = '`<iframe([^>]*)>`i'; 821 if ( preg_match( $pattern, $result, $matches ) ) { 822 $attrs = wp_kses_hair( $matches[1], wp_allowed_protocols() ); 823 824 foreach ( $attrs as $attr => $item ) { 825 $lower_attr = strtolower( $attr ); 826 if ( $lower_attr === $attr ) { 827 continue; 828 } 829 if ( ! isset( $attrs[ $lower_attr ] ) ) { 830 $attrs[ $lower_attr ] = $item; 831 unset( $attrs[ $attr ] ); 832 } 833 } 834 } 835 836 if ( ! empty( $attrs['title']['value'] ) ) { 837 $title = $attrs['title']['value']; 838 } 839 840 /** 841 * Filters the title attribute of the given oEmbed HTML iframe. 842 * 843 * @since 5.2.0 844 * 845 * @param string $title The title attribute. 846 * @param string $result The oEmbed HTML result. 847 * @param object $data A data object result from an oEmbed provider. 848 * @param string $url The URL of the content to be embedded. 849 */ 850 $title = apply_filters( 'oembed_iframe_title_attribute', $title, $result, $data, $url ); 851 852 if ( '' === $title ) { 853 return $result; 854 } 855 856 if ( isset( $attrs['title'] ) ) { 857 unset( $attrs['title'] ); 858 $attr_string = implode( ' ', wp_list_pluck( $attrs, 'whole' ) ); 859 $result = str_replace( $matches[0], '<iframe ' . trim( $attr_string ) . '>', $result ); 860 } 861 return str_ireplace( '<iframe ', sprintf( '<iframe title="%s" ', esc_attr( $title ) ), $result ); 862 } 863 864 865 /** 866 * Filters the given oEmbed HTML. 867 * 868 * If the `$url` isn't on the trusted providers list, 869 * we need to filter the HTML heavily for security. 870 * 871 * Only filters 'rich' and 'video' response types. 872 * 873 * @since 4.4.0 874 * 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 * @return string The filtered and sanitized oEmbed result. 879 */ 880 function wp_filter_oembed_result( $result, $data, $url ) { 881 if ( false === $result || ! in_array( $data->type, array( 'rich', 'video' ), true ) ) { 882 return $result; 883 } 884 885 $wp_oembed = _wp_oembed_get_object(); 886 887 // Don't modify the HTML for trusted providers. 888 if ( false !== $wp_oembed->get_provider( $url, array( 'discover' => false ) ) ) { 889 return $result; 890 } 891 892 $allowed_html = array( 893 'a' => array( 894 'href' => true, 895 ), 896 'blockquote' => array(), 897 'iframe' => array( 898 'src' => true, 899 'width' => true, 900 'height' => true, 901 'frameborder' => true, 902 'marginwidth' => true, 903 'marginheight' => true, 904 'scrolling' => true, 905 'title' => true, 906 ), 907 ); 908 909 $html = wp_kses( $result, $allowed_html ); 910 911 preg_match( '|(<blockquote>.*?</blockquote>)?.*(<iframe.*?></iframe>)|ms', $html, $content ); 912 // We require at least the iframe to exist. 913 if ( empty( $content[2] ) ) { 914 return false; 915 } 916 $html = $content[1] . $content[2]; 917 918 preg_match( '/ src=([\'"])(.*?)\1/', $html, $results ); 919 920 if ( ! empty( $results ) ) { 921 $secret = wp_generate_password( 10, false ); 922 923 $url = esc_url( "{$results[2]}#?secret=$secret" ); 924 $q = $results[1]; 925 926 $html = str_replace( $results[0], ' src=' . $q . $url . $q . ' data-secret=' . $q . $secret . $q, $html ); 927 $html = str_replace( '<blockquote', "<blockquote data-secret=\"$secret\"", $html ); 928 } 929 930 $allowed_html['blockquote']['data-secret'] = true; 931 $allowed_html['iframe']['data-secret'] = true; 932 933 $html = wp_kses( $html, $allowed_html ); 934 935 if ( ! empty( $content[1] ) ) { 936 // We have a blockquote to fall back on. Hide the iframe by default. 937 $html = str_replace( '<iframe', '<iframe style="position: absolute; clip: rect(1px, 1px, 1px, 1px);"', $html ); 938 $html = str_replace( '<blockquote', '<blockquote class="wp-embedded-content"', $html ); 939 } 940 941 $html = str_ireplace( '<iframe', '<iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"', $html ); 942 943 return $html; 944 } 945 946 /** 947 * Filters the string in the 'more' link displayed after a trimmed excerpt. 948 * 949 * Replaces '[...]' (appended to automatically generated excerpts) with an 950 * ellipsis and a "Continue reading" link in the embed template. 951 * 952 * @since 4.4.0 953 * 954 * @param string $more_string Default 'more' string. 955 * @return string 'Continue reading' link prepended with an ellipsis. 956 */ 957 function wp_embed_excerpt_more( $more_string ) { 958 if ( ! is_embed() ) { 959 return $more_string; 960 } 961 962 $link = sprintf( 963 '<a href="%1$s" class="wp-embed-more" target="_top">%2$s</a>', 964 esc_url( get_permalink() ), 965 /* translators: %s: Post title. */ 966 sprintf( __( 'Continue reading %s' ), '<span class="screen-reader-text">' . get_the_title() . '</span>' ) 967 ); 968 return ' … ' . $link; 969 } 970 971 /** 972 * Displays the post excerpt for the embed template. 973 * 974 * Intended to be used in 'The Loop'. 975 * 976 * @since 4.4.0 977 */ 978 function the_excerpt_embed() { 979 $output = get_the_excerpt(); 980 981 /** 982 * Filters the post excerpt for the embed template. 983 * 984 * @since 4.4.0 985 * 986 * @param string $output The current post excerpt. 987 */ 988 echo apply_filters( 'the_excerpt_embed', $output ); 989 } 990 991 /** 992 * Filters the post excerpt for the embed template. 993 * 994 * Shows players for video and audio attachments. 995 * 996 * @since 4.4.0 997 * 998 * @param string $content The current post excerpt. 999 * @return string The modified post excerpt. 1000 */ 1001 function wp_embed_excerpt_attachment( $content ) { 1002 if ( is_attachment() ) { 1003 return prepend_attachment( '' ); 1004 } 1005 1006 return $content; 1007 } 1008 1009 /** 1010 * Enqueues embed iframe default CSS and JS. 1011 * 1012 * Enqueue PNG fallback CSS for embed iframe for legacy versions of IE. 1013 * 1014 * Allows plugins to queue scripts for the embed iframe end using wp_enqueue_script(). 1015 * Runs first in oembed_head(). 1016 * 1017 * @since 4.4.0 1018 */ 1019 function enqueue_embed_scripts() { 1020 wp_enqueue_style( 'wp-embed-template-ie' ); 1021 1022 /** 1023 * Fires when scripts and styles are enqueued for the embed iframe. 1024 * 1025 * @since 4.4.0 1026 */ 1027 do_action( 'enqueue_embed_scripts' ); 1028 } 1029 1030 /** 1031 * Prints the CSS in the embed iframe header. 1032 * 1033 * @since 4.4.0 1034 */ 1035 function print_embed_styles() { 1036 $type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/css"'; 1037 ?> 1038 <style<?php echo $type_attr; ?>> 1039 <?php 1040 if ( SCRIPT_DEBUG ) { 1041 readfile( ABSPATH . WPINC . '/css/wp-embed-template.css' ); 1042 } else { 1043 /* 1044 * If you're looking at a src version of this file, you'll see an "include" 1045 * statement below. This is used by the `npm run build` process to directly 1046 * include a minified version of wp-oembed-embed.css, instead of using the 1047 * readfile() method from above. 1048 * 1049 * If you're looking at a build version of this file, you'll see a string of 1050 * minified CSS. If you need to debug it, please turn on SCRIPT_DEBUG 1051 * and edit wp-embed-template.css directly. 1052 */ 1053 ?> 1054 /*! This file is auto-generated */ 1055 body,html{padding:0;margin:0}body{font-family:sans-serif}.screen-reader-text{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.dashicons{display:inline-block;width:20px;height:20px;background-color:transparent;background-repeat:no-repeat;background-size:20px;background-position:center;transition:background .1s ease-in;position:relative;top:5px}.dashicons-no{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M15.55%2013.7l-2.19%202.06-3.42-3.65-3.64%203.43-2.06-2.18%203.64-3.43-3.42-3.64%202.18-2.06%203.43%203.64%203.64-3.42%202.05%202.18-3.64%203.43z%27%20fill%3D%27%23fff%27%2F%3E%3C%2Fsvg%3E")}.dashicons-admin-comments{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E")}.wp-embed-comments a:hover .dashicons-admin-comments{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E")}.dashicons-share{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E");display:none}.js .dashicons-share{display:inline-block}.wp-embed-share-dialog-open:hover .dashicons-share{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E")}.wp-embed{padding:25px;font-size:14px;font-weight:400;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;line-height:1.5;color:#8c8f94;background:#fff;border:1px solid #dcdcde;box-shadow:0 1px 1px rgba(0,0,0,.05);overflow:auto;zoom:1}.wp-embed a{color:#8c8f94;text-decoration:none}.wp-embed a:hover{text-decoration:underline}.wp-embed-featured-image{margin-bottom:20px}.wp-embed-featured-image img{width:100%;height:auto;border:none}.wp-embed-featured-image.square{float:left;max-width:160px;margin-right:20px}.wp-embed p{margin:0}p.wp-embed-heading{margin:0 0 15px;font-weight:600;font-size:22px;line-height:1.3}.wp-embed-heading a{color:#2c3338}.wp-embed .wp-embed-more{color:#c3c4c7}.wp-embed-footer{display:table;width:100%;margin-top:30px}.wp-embed-site-icon{position:absolute;top:50%;left:0;transform:translateY(-50%);height:25px;width:25px;border:0}.wp-embed-site-title{font-weight:600;line-height:1.78571428}.wp-embed-site-title a{position:relative;display:inline-block;padding-left:35px}.wp-embed-meta,.wp-embed-site-title{display:table-cell}.wp-embed-meta{text-align:right;white-space:nowrap;vertical-align:middle}.wp-embed-comments,.wp-embed-share{display:inline}.wp-embed-meta a:hover{text-decoration:none;color:#2271b1}.wp-embed-comments a{line-height:1.78571428;display:inline-block}.wp-embed-comments+.wp-embed-share{margin-left:10px}.wp-embed-share-dialog{position:absolute;top:0;left:0;right:0;bottom:0;background-color:#1d2327;background-color:rgba(0,0,0,.9);color:#fff;opacity:1;transition:opacity .25s ease-in-out}.wp-embed-share-dialog.hidden{opacity:0;visibility:hidden}.wp-embed-share-dialog-close,.wp-embed-share-dialog-open{margin:-8px 0 0;padding:0;background:0 0;border:none;cursor:pointer;outline:0}.wp-embed-share-dialog-close .dashicons,.wp-embed-share-dialog-open .dashicons{padding:4px}.wp-embed-share-dialog-open .dashicons{top:8px}.wp-embed-share-dialog-close:focus .dashicons,.wp-embed-share-dialog-open:focus .dashicons{box-shadow:0 0 0 1px #4f94d4,0 0 2px 1px rgba(79,148,212,.8);border-radius:100%}.wp-embed-share-dialog-close{position:absolute;top:20px;right:20px;font-size:22px}.wp-embed-share-dialog-close:hover{text-decoration:none}.wp-embed-share-dialog-close .dashicons{height:24px;width:24px;background-size:24px}.wp-embed-share-dialog-content{height:100%;transform-style:preserve-3d;overflow:hidden}.wp-embed-share-dialog-text{margin-top:25px;padding:20px}.wp-embed-share-tabs{margin:0 0 20px;padding:0;list-style:none}.wp-embed-share-tab-button{display:inline-block}.wp-embed-share-tab-button button{margin:0;padding:0;border:none;background:0 0;font-size:16px;line-height:1.3;color:#a7aaad;cursor:pointer;transition:color .1s ease-in}.wp-embed-share-tab-button [aria-selected=true]{color:#fff}.wp-embed-share-tab-button button:hover{color:#fff}.wp-embed-share-tab-button+.wp-embed-share-tab-button{margin:0 0 0 10px;padding:0 0 0 11px;border-left:1px solid #a7aaad}.wp-embed-share-tab[aria-hidden=true]{display:none}p.wp-embed-share-description{margin:0;font-size:14px;line-height:1;font-style:italic;color:#a7aaad}.wp-embed-share-input{box-sizing:border-box;width:100%;border:none;height:28px;margin:0 0 10px 0;padding:0 5px;font-size:14px;font-weight:400;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;line-height:1.5;resize:none;cursor:text}textarea.wp-embed-share-input{height:72px}html[dir=rtl] .wp-embed-featured-image.square{float:right;margin-right:0;margin-left:20px}html[dir=rtl] .wp-embed-site-title a{padding-left:0;padding-right:35px}html[dir=rtl] .wp-embed-site-icon{margin-right:0;margin-left:10px;left:auto;right:0}html[dir=rtl] .wp-embed-meta{text-align:left}html[dir=rtl] .wp-embed-share{margin-left:0;margin-right:10px}html[dir=rtl] .wp-embed-share-dialog-close{right:auto;left:20px}html[dir=rtl] .wp-embed-share-tab-button+.wp-embed-share-tab-button{margin:0 10px 0 0;padding:0 11px 0 0;border-left:none;border-right:1px solid #a7aaad} 1056 <?php 1057 } 1058 ?> 1059 </style> 1060 <?php 1061 } 1062 1063 /** 1064 * Prints the JavaScript in the embed iframe header. 1065 * 1066 * @since 4.4.0 1067 */ 1068 function print_embed_scripts() { 1069 $type_attr = current_theme_supports( 'html5', 'script' ) ? '' : ' type="text/javascript"'; 1070 ?> 1071 <script<?php echo $type_attr; ?>> 1072 <?php 1073 if ( SCRIPT_DEBUG ) { 1074 readfile( ABSPATH . WPINC . '/js/wp-embed-template.js' ); 1075 } else { 1076 /* 1077 * If you're looking at a src version of this file, you'll see an "include" 1078 * statement below. This is used by the `npm run build` process to directly 1079 * include a minified version of wp-embed-template.js, instead of using the 1080 * readfile() method from above. 1081 * 1082 * If you're looking at a build version of this file, you'll see a string of 1083 * minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG 1084 * and edit wp-embed-template.js directly. 1085 */ 1086 ?> 1087 /*! This file is auto-generated */ 1088 !function(c,u){"use strict";var r,t,e,n=u.querySelector&&c.addEventListener,b=!1;function f(e,t){c.parent.postMessage({message:e,value:t,secret:r},"*")}function i(){if(!b){b=!0;var e,r=u.querySelector(".wp-embed-share-dialog"),t=u.querySelector(".wp-embed-share-dialog-open"),n=u.querySelector(".wp-embed-share-dialog-close"),i=u.querySelectorAll(".wp-embed-share-input"),a=u.querySelectorAll(".wp-embed-share-tab-button button"),o=u.querySelector(".wp-embed-featured-image img");if(i)for(e=0;e<i.length;e++)i[e].addEventListener("click",function(e){e.target.select()});if(t&&t.addEventListener("click",function(){r.className=r.className.replace("hidden",""),u.querySelector('.wp-embed-share-tab-button [aria-selected="true"]').focus()}),n&&n.addEventListener("click",function(){l()}),a)for(e=0;e<a.length;e++)a[e].addEventListener("click",s),a[e].addEventListener("keydown",d);u.addEventListener("keydown",function(e){var t;27===e.keyCode&&-1===r.className.indexOf("hidden")?l():9===e.keyCode&&(t=e,e=u.querySelector('.wp-embed-share-tab-button [aria-selected="true"]'),n!==t.target||t.shiftKey?e===t.target&&t.shiftKey&&(n.focus(),t.preventDefault()):(e.focus(),t.preventDefault()))},!1),c.self!==c.top&&(f("height",Math.ceil(u.body.getBoundingClientRect().height)),o&&o.addEventListener("load",function(){f("height",Math.ceil(u.body.getBoundingClientRect().height))}),u.addEventListener("click",function(e){var t=((t=e.target).hasAttribute("href")?t:t.parentElement).getAttribute("href");event.altKey||event.ctrlKey||event.metaKey||event.shiftKey||t&&(f("link",t),e.preventDefault())}))}function l(){r.className+=" hidden",u.querySelector(".wp-embed-share-dialog-open").focus()}function s(e){var t=u.querySelector('.wp-embed-share-tab-button [aria-selected="true"]');t.setAttribute("aria-selected","false"),u.querySelector("#"+t.getAttribute("aria-controls")).setAttribute("aria-hidden","true"),e.target.setAttribute("aria-selected","true"),u.querySelector("#"+e.target.getAttribute("aria-controls")).setAttribute("aria-hidden","false")}function d(e){var t,r=e.target,n=r.parentElement.previousElementSibling,i=r.parentElement.nextElementSibling;if(37===e.keyCode)t=n;else{if(39!==e.keyCode)return!1;t=i}(t="rtl"===u.documentElement.getAttribute("dir")?t===n?i:n:t)&&(t=t.firstElementChild,r.setAttribute("tabindex","-1"),r.setAttribute("aria-selected",!1),u.querySelector("#"+r.getAttribute("aria-controls")).setAttribute("aria-hidden","true"),t.setAttribute("tabindex","0"),t.setAttribute("aria-selected","true"),t.focus(),u.querySelector("#"+t.getAttribute("aria-controls")).setAttribute("aria-hidden","false"))}}n&&(!function e(){c.self===c.top||r||(r=c.location.hash.replace(/.*secret=([\d\w]{10}).*/,"$1"),clearTimeout(t),t=setTimeout(function(){e()},100))}(),u.documentElement.className=u.documentElement.className.replace(/\bno-js\b/,"")+" js",u.addEventListener("DOMContentLoaded",i,!1),c.addEventListener("load",i,!1),c.addEventListener("resize",function(){c.self!==c.top&&(clearTimeout(e),e=setTimeout(function(){f("height",Math.ceil(u.body.getBoundingClientRect().height))},100))},!1))}(window,document); 1089 <?php 1090 } 1091 ?> 1092 </script> 1093 <?php 1094 } 1095 1096 /** 1097 * Prepare the oembed HTML to be displayed in an RSS feed. 1098 * 1099 * @since 4.4.0 1100 * @access private 1101 * 1102 * @param string $content The content to filter. 1103 * @return string The filtered content. 1104 */ 1105 function _oembed_filter_feed_content( $content ) { 1106 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 ); 1107 } 1108 1109 /** 1110 * Prints the necessary markup for the embed comments button. 1111 * 1112 * @since 4.4.0 1113 */ 1114 function print_embed_comments_button() { 1115 if ( is_404() || ! ( get_comments_number() || comments_open() ) ) { 1116 return; 1117 } 1118 ?> 1119 <div class="wp-embed-comments"> 1120 <a href="<?php comments_link(); ?>" target="_top"> 1121 <span class="dashicons dashicons-admin-comments"></span> 1122 <?php 1123 printf( 1124 /* translators: %s: Number of comments. */ 1125 _n( 1126 '%s <span class="screen-reader-text">Comment</span>', 1127 '%s <span class="screen-reader-text">Comments</span>', 1128 get_comments_number() 1129 ), 1130 number_format_i18n( get_comments_number() ) 1131 ); 1132 ?> 1133 </a> 1134 </div> 1135 <?php 1136 } 1137 1138 /** 1139 * Prints the necessary markup for the embed sharing button. 1140 * 1141 * @since 4.4.0 1142 */ 1143 function print_embed_sharing_button() { 1144 if ( is_404() ) { 1145 return; 1146 } 1147 ?> 1148 <div class="wp-embed-share"> 1149 <button type="button" class="wp-embed-share-dialog-open" aria-label="<?php esc_attr_e( 'Open sharing dialog' ); ?>"> 1150 <span class="dashicons dashicons-share"></span> 1151 </button> 1152 </div> 1153 <?php 1154 } 1155 1156 /** 1157 * Prints the necessary markup for the embed sharing dialog. 1158 * 1159 * @since 4.4.0 1160 */ 1161 function print_embed_sharing_dialog() { 1162 if ( is_404() ) { 1163 return; 1164 } 1165 ?> 1166 <div class="wp-embed-share-dialog hidden" role="dialog" aria-label="<?php esc_attr_e( 'Sharing options' ); ?>"> 1167 <div class="wp-embed-share-dialog-content"> 1168 <div class="wp-embed-share-dialog-text"> 1169 <ul class="wp-embed-share-tabs" role="tablist"> 1170 <li class="wp-embed-share-tab-button wp-embed-share-tab-button-wordpress" role="presentation"> 1171 <button type="button" role="tab" aria-controls="wp-embed-share-tab-wordpress" aria-selected="true" tabindex="0"><?php esc_html_e( 'WordPress Embed' ); ?></button> 1172 </li> 1173 <li class="wp-embed-share-tab-button wp-embed-share-tab-button-html" role="presentation"> 1174 <button type="button" role="tab" aria-controls="wp-embed-share-tab-html" aria-selected="false" tabindex="-1"><?php esc_html_e( 'HTML Embed' ); ?></button> 1175 </li> 1176 </ul> 1177 <div id="wp-embed-share-tab-wordpress" class="wp-embed-share-tab" role="tabpanel" aria-hidden="false"> 1178 <input type="text" value="<?php the_permalink(); ?>" class="wp-embed-share-input" aria-describedby="wp-embed-share-description-wordpress" tabindex="0" readonly/> 1179 1180 <p class="wp-embed-share-description" id="wp-embed-share-description-wordpress"> 1181 <?php _e( 'Copy and paste this URL into your WordPress site to embed' ); ?> 1182 </p> 1183 </div> 1184 <div id="wp-embed-share-tab-html" class="wp-embed-share-tab" role="tabpanel" aria-hidden="true"> 1185 <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> 1186 1187 <p class="wp-embed-share-description" id="wp-embed-share-description-html"> 1188 <?php _e( 'Copy and paste this code into your site to embed' ); ?> 1189 </p> 1190 </div> 1191 </div> 1192 1193 <button type="button" class="wp-embed-share-dialog-close" aria-label="<?php esc_attr_e( 'Close sharing dialog' ); ?>"> 1194 <span class="dashicons dashicons-no"></span> 1195 </button> 1196 </div> 1197 </div> 1198 <?php 1199 } 1200 1201 /** 1202 * Prints the necessary markup for the site title in an embed template. 1203 * 1204 * @since 4.5.0 1205 */ 1206 function the_embed_site_title() { 1207 $site_title = sprintf( 1208 '<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>', 1209 esc_url( home_url() ), 1210 esc_url( get_site_icon_url( 32, includes_url( 'images/w-logo-blue.png' ) ) ), 1211 esc_url( get_site_icon_url( 64, includes_url( 'images/w-logo-blue.png' ) ) ), 1212 esc_html( get_bloginfo( 'name' ) ) 1213 ); 1214 1215 $site_title = '<div class="wp-embed-site-title">' . $site_title . '</div>'; 1216 1217 /** 1218 * Filters the site title HTML in the embed footer. 1219 * 1220 * @since 4.4.0 1221 * 1222 * @param string $site_title The site title HTML. 1223 */ 1224 echo apply_filters( 'embed_site_title_html', $site_title ); 1225 } 1226 1227 /** 1228 * Filters the oEmbed result before any HTTP requests are made. 1229 * 1230 * If the URL belongs to the current site, the result is fetched directly instead of 1231 * going through the oEmbed discovery process. 1232 * 1233 * @since 4.5.3 1234 * 1235 * @param null|string $result The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. Default null. 1236 * @param string $url The URL that should be inspected for discovery `<link>` tags. 1237 * @param array $args oEmbed remote get arguments. 1238 * @return null|string The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. 1239 * Null if the URL does not belong to the current site. 1240 */ 1241 function wp_filter_pre_oembed_result( $result, $url, $args ) { 1242 $data = get_oembed_response_data_for_url( $url, $args ); 1243 1244 if ( $data ) { 1245 return _wp_oembed_get_object()->data2html( $data, $url ); 1246 } 1247 1248 return $result; 1249 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Mar 7 01:00:03 2021 | Cross-referenced by PHPXref 0.7.1 |